diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index d383cb9d91dd..358f14221a0d 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -951,6 +951,34 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { ty::Binder::dummy(ty::PredicateKind::DynCompatible(principal)), )); } + + if !t.has_escaping_bound_vars() { + for projection in data.projection_bounds() { + let pred_binder = projection + .with_self_ty(tcx, t) + .map_bound(|p| { + p.term.as_const().map(|ct| { + let assoc_const_ty = tcx + .type_of(p.projection_term.def_id) + .instantiate(tcx, p.projection_term.args); + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType( + ct, + assoc_const_ty, + )) + }) + }) + .transpose(); + if let Some(pred_binder) = pred_binder { + self.out.push(traits::Obligation::with_depth( + tcx, + self.cause(ObligationCauseCode::WellFormed(None)), + self.recursion_depth, + self.param_env, + pred_binder, + )); + } + } + } } // Inference variables are the complicated case, since we don't diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs new file mode 100644 index 000000000000..319e3421a4cd --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs @@ -0,0 +1,12 @@ +//@ known-bug: unknown +//@ check-pass + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +trait Trait { #[type_const] const CT: bool; } + +// FIXME: this should yield a type mismatch (`bool` v `i32`) +fn f(_: impl Trait) {} + +fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs new file mode 100644 index 000000000000..2adaaa3dd050 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs @@ -0,0 +1,12 @@ +//@ known-bug: unknown +//@ check-pass + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +trait Trait { #[type_const] const CT: bool; } + +fn f() { + let _: dyn Trait; // FIXME: this should yield a type mismatch (`bool` v `i32`) +} +fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs new file mode 100644 index 000000000000..29d089bf9d2b --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs @@ -0,0 +1,15 @@ +//@ known-bug: unknown +//@ check-pass + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +trait Trait { #[type_const] const CT: bool; } + +trait Bound { #[type_const] const N: u32; } +impl Bound for () { #[type_const] const N: u32 = 0; } + +fn f() { let _: dyn Trait::N }>; } // FIXME +fn g(_: impl Trait::N }>) {} // FIXME + +fn main() {}