From fbe9d366c330bc1ce03a6568479ff2cd522539b7 Mon Sep 17 00:00:00 2001 From: YUZHEthefool <2804776511@qq.com> Date: Wed, 26 Aug 2026 03:26:37 +0000 Subject: [PATCH] Check associated const binding types --- compiler/rustc_middle/src/traits/mod.rs | 4 ++ .../traits/fulfillment_errors.rs | 25 ++++++++---- .../src/error_reporting/traits/suggestions.rs | 1 + .../rustc_trait_selection/src/traits/wf.rs | 39 ++++++++++++++++++- .../associated-type-bound-issue-161100.rs | 15 +++++++ .../associated-type-bound-issue-161100.stderr | 9 +++++ ...t-item-associated-equality-issue-161100.rs | 15 +++++++ ...em-associated-equality-issue-161100.stderr | 15 +++++++ .../dyn-associated-const-issue-161100.rs | 12 ++++++ .../dyn-associated-const-issue-161100.stderr | 9 +++++ .../fn-ptr-const-param-issue-161100.rs | 13 +++++++ .../fn-ptr-const-param-issue-161100.stderr | 9 +++++ ...-associated-const-equality-issue-161100.rs | 18 +++++++++ ...ociated-const-equality-issue-161100.stderr | 15 +++++++ .../where-clause-issue-161100.rs | 12 ++++++ .../where-clause-issue-161100.stderr | 9 +++++ 16 files changed, 212 insertions(+), 8 deletions(-) create mode 100644 tests/ui/const-generics/associated-const-bindings/associated-type-bound-issue-161100.rs create mode 100644 tests/ui/const-generics/associated-const-bindings/associated-type-bound-issue-161100.stderr create mode 100644 tests/ui/const-generics/associated-const-bindings/direct-const-item-associated-equality-issue-161100.rs create mode 100644 tests/ui/const-generics/associated-const-bindings/direct-const-item-associated-equality-issue-161100.stderr create mode 100644 tests/ui/const-generics/associated-const-bindings/dyn-associated-const-issue-161100.rs create mode 100644 tests/ui/const-generics/associated-const-bindings/dyn-associated-const-issue-161100.stderr create mode 100644 tests/ui/const-generics/associated-const-bindings/fn-ptr-const-param-issue-161100.rs create mode 100644 tests/ui/const-generics/associated-const-bindings/fn-ptr-const-param-issue-161100.stderr create mode 100644 tests/ui/const-generics/associated-const-bindings/non-const-param-ty-associated-const-equality-issue-161100.rs create mode 100644 tests/ui/const-generics/associated-const-bindings/non-const-param-ty-associated-const-equality-issue-161100.stderr create mode 100644 tests/ui/const-generics/associated-const-bindings/where-clause-issue-161100.rs create mode 100644 tests/ui/const-generics/associated-const-bindings/where-clause-issue-161100.stderr diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 5520b059f5678..5fd61451bce8e 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -415,6 +415,10 @@ pub enum ObligationCauseCode<'tcx> { /// Requirement for a `const N: Ty` to implement `Ty: ConstParamTy` ConstParam(Ty<'tcx>), + /// Requirement for the type of a const item used in the type system to implement + /// `ConstParamTy`. + ConstItemTy(Ty<'tcx>), + /// Obligations emitted during the normalization of a free type alias. TypeAlias(ObligationCauseCodeHandle<'tcx>, Span, DefId), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 4cb5465b5bbee..e6891dfa2866c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -103,10 +103,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .emit_err(); } - // Report a const-param specific error - if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives() - { - return self.report_const_param_not_wf(ty, &obligation).emit_err(); + // Report a `ConstParamTy`-specific error + match *obligation.cause.code().peel_derives() { + ObligationCauseCode::ConstParam(ty) => { + return self + .report_const_param_not_wf( + ty, + self.tcx.ty_span(obligation.cause.body_def_id), + &obligation, + ) + .emit_err(); + } + ObligationCauseCode::ConstItemTy(ty) => { + return self + .report_const_param_not_wf(ty, obligation.cause.span, &obligation) + .emit_err(); + } + _ => {} } let bound_predicate = obligation.predicate.kind(); @@ -1422,11 +1435,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn report_const_param_not_wf( &self, ty: Ty<'tcx>, + span: Span, obligation: &PredicateObligation<'tcx>, ) -> Diag<'a> { - let def_id = obligation.cause.body_def_id; - let span = self.tcx.ty_span(def_id); - let mut file = None; let ty_str = self.tcx.short_string(ty, &mut file); let mut diag = match ty.kind() { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 32237e9f60ca3..bc9349967ed6a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3906,6 +3906,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | ObligationCauseCode::AscribeUserTypeProvePredicate(..) | ObligationCauseCode::AlwaysApplicableImpl | ObligationCauseCode::ConstParam(_) + | ObligationCauseCode::ConstItemTy(_) | ObligationCauseCode::ReferenceOutlivesReferent(..) | ObligationCauseCode::ObjectTypeBound(..) => {} ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, .. } => { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index ba33270c2adba..8068ce00af21b 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -185,6 +185,9 @@ pub fn clause_obligations<'tcx>( wf.add_wf_preds_for_term(ty.into()); } ty::ClauseKind::Projection(t) => { + if matches!(t.projection_term.kind, ty::AliasTermKind::ProjectionConst { .. }) { + wf.require_const_item_ty(t.projection_term.expect_ct()); + } wf.add_wf_preds_for_projection_term(t.projection_term); wf.add_wf_preds_for_term(t.term); } @@ -570,6 +573,32 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } } + fn require_const_item_ty(&mut self, ct: ty::AliasConst<'tcx>) { + let ty = ct.type_of(self.tcx()).skip_norm_wip(); + + if ct.kind.is_direct_const(self.tcx()) { + return; + } + + if self.tcx().features().const_param_ty_unchecked() || ty.has_escaping_bound_vars() { + return; + } + + let cause = self.cause(ObligationCauseCode::ConstItemTy(ty)); + let trait_ref = ty::TraitRef::new( + self.tcx(), + self.tcx().require_lang_item(LangItem::ConstParamTy, cause.span), + [ty], + ); + self.out.push(traits::Obligation::with_depth( + self.tcx(), + cause, + self.recursion_depth, + self.param_env, + ty::Binder::dummy(trait_ref), + )); + } + /// Pushes all the predicates needed to validate that `term` is WF into `out`. #[instrument(level = "debug", skip(self))] fn add_wf_preds_for_term(&mut self, term: Term<'tcx>) { @@ -1026,8 +1055,16 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { if !t.has_escaping_bound_vars() { for projection in data.projection_bounds() { + let projection = projection.with_self_ty(tcx, t); + let projection_pred = projection.skip_binder(); + if matches!( + projection_pred.projection_term.kind, + ty::AliasTermKind::ProjectionConst { .. } + ) { + self.require_const_item_ty(projection_pred.projection_term.expect_ct()); + } + let pred_binder = projection - .with_self_ty(tcx, t) .map_bound(|p| { p.term.as_const().map(|ct| { let assoc_const_ty = tcx diff --git a/tests/ui/const-generics/associated-const-bindings/associated-type-bound-issue-161100.rs b/tests/ui/const-generics/associated-const-bindings/associated-type-bound-issue-161100.rs new file mode 100644 index 0000000000000..4c479619c06d7 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/associated-type-bound-issue-161100.rs @@ -0,0 +1,15 @@ +//@ compile-flags: -Znext-solver=globally + +#![feature(generic_const_args, min_generic_const_args)] +#![allow(incomplete_features)] + +trait Trait { + const F: fn(); +} + +trait Nested { + type Out: Trait; + //~^ ERROR using function pointers as const generic parameters is forbidden +} + +fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/associated-type-bound-issue-161100.stderr b/tests/ui/const-generics/associated-const-bindings/associated-type-bound-issue-161100.stderr new file mode 100644 index 0000000000000..873bcc26d6ea0 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/associated-type-bound-issue-161100.stderr @@ -0,0 +1,9 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/associated-type-bound-issue-161100.rs:11:21 + | +LL | type Out: Trait; + | ^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/associated-const-bindings/direct-const-item-associated-equality-issue-161100.rs b/tests/ui/const-generics/associated-const-bindings/direct-const-item-associated-equality-issue-161100.rs new file mode 100644 index 0000000000000..fad24e1248bb5 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/direct-const-item-associated-equality-issue-161100.rs @@ -0,0 +1,15 @@ +//@ compile-flags: -Znext-solver=globally + +#![feature(generic_const_args, min_generic_const_args)] + +struct S; +const C: S = S; + +trait Trait { + const F: S; +} + +fn take(_: impl Trait) {} +//~^ ERROR `S` must implement `ConstParamTy` + +fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/direct-const-item-associated-equality-issue-161100.stderr b/tests/ui/const-generics/associated-const-bindings/direct-const-item-associated-equality-issue-161100.stderr new file mode 100644 index 0000000000000..c9a4207afea05 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/direct-const-item-associated-equality-issue-161100.stderr @@ -0,0 +1,15 @@ +error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter + --> $DIR/direct-const-item-associated-equality-issue-161100.rs:12:23 + | +LL | fn take(_: impl Trait) {} + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct + | +LL + #[derive(ConstParamTy, PartialEq, Eq)] +LL | struct S; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-associated-const-issue-161100.rs b/tests/ui/const-generics/associated-const-bindings/dyn-associated-const-issue-161100.rs new file mode 100644 index 0000000000000..71a8a40f15cf9 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/dyn-associated-const-issue-161100.rs @@ -0,0 +1,12 @@ +//@ compile-flags: -Znext-solver=globally + +#![feature(generic_const_args, min_generic_const_args)] + +trait Trait { + const F: fn(); +} + +fn take(_: &dyn Trait) {} +//~^ ERROR using function pointers as const generic parameters is forbidden + +fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-associated-const-issue-161100.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-associated-const-issue-161100.stderr new file mode 100644 index 0000000000000..01e043016f96d --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/dyn-associated-const-issue-161100.stderr @@ -0,0 +1,9 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/dyn-associated-const-issue-161100.rs:9:13 + | +LL | fn take(_: &dyn Trait) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/associated-const-bindings/fn-ptr-const-param-issue-161100.rs b/tests/ui/const-generics/associated-const-bindings/fn-ptr-const-param-issue-161100.rs new file mode 100644 index 0000000000000..fabd5683a2904 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/fn-ptr-const-param-issue-161100.rs @@ -0,0 +1,13 @@ +//@ compile-flags: -Znext-solver=globally + +#![feature(generic_const_args)] +#![feature(min_generic_const_args)] + +trait Trait { + const F: fn(); +} + +fn take(_: impl Trait) {} +//~^ ERROR using function pointers as const generic parameters is forbidden + +fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/fn-ptr-const-param-issue-161100.stderr b/tests/ui/const-generics/associated-const-bindings/fn-ptr-const-param-issue-161100.stderr new file mode 100644 index 0000000000000..803dbd7a04b84 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/fn-ptr-const-param-issue-161100.stderr @@ -0,0 +1,9 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/fn-ptr-const-param-issue-161100.rs:10:23 + | +LL | fn take(_: impl Trait) {} + | ^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/associated-const-bindings/non-const-param-ty-associated-const-equality-issue-161100.rs b/tests/ui/const-generics/associated-const-bindings/non-const-param-ty-associated-const-equality-issue-161100.rs new file mode 100644 index 0000000000000..32e7b4fde6b73 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/non-const-param-ty-associated-const-equality-issue-161100.rs @@ -0,0 +1,18 @@ +//@ compile-flags: -Znext-solver=globally + +#![feature(generic_const_args)] +#![feature(min_generic_const_args)] + +enum Foo { + Unit, + Function(fn()), +} + +trait Trait { + const X: Foo; +} + +fn unit(_: impl Trait) {} +//~^ ERROR `Foo` must implement `ConstParamTy` + +fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/non-const-param-ty-associated-const-equality-issue-161100.stderr b/tests/ui/const-generics/associated-const-bindings/non-const-param-ty-associated-const-equality-issue-161100.stderr new file mode 100644 index 0000000000000..62dc2045da0fa --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/non-const-param-ty-associated-const-equality-issue-161100.stderr @@ -0,0 +1,15 @@ +error[E0741]: `Foo` must implement `ConstParamTy` to be used as the type of a const generic parameter + --> $DIR/non-const-param-ty-associated-const-equality-issue-161100.rs:15:23 + | +LL | fn unit(_: impl Trait) {} + | ^^^^^^^^^^^^^^^^^ + | +help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the enum + | +LL + #[derive(ConstParamTy, PartialEq, Eq)] +LL | enum Foo { + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/associated-const-bindings/where-clause-issue-161100.rs b/tests/ui/const-generics/associated-const-bindings/where-clause-issue-161100.rs new file mode 100644 index 0000000000000..16023eb66f209 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/where-clause-issue-161100.rs @@ -0,0 +1,12 @@ +//@ compile-flags: -Znext-solver=globally + +#![feature(generic_const_args, min_generic_const_args)] + +trait Trait { + const F: fn(); +} + +fn take() where T: Trait {} +//~^ ERROR using function pointers as const generic parameters is forbidden + +fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/where-clause-issue-161100.stderr b/tests/ui/const-generics/associated-const-bindings/where-clause-issue-161100.stderr new file mode 100644 index 0000000000000..f5ee2c0bba6b9 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/where-clause-issue-161100.stderr @@ -0,0 +1,9 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/where-clause-issue-161100.rs:9:29 + | +LL | fn take() where T: Trait {} + | ^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0741`.