diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 110cc30e740bb..8da4289bf185e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -235,8 +235,9 @@ where // See . ecx.try_evaluate_added_goals()?; - // Add GAT where clauses from the trait's definition. - // FIXME: We don't need these, since these are the type's own WF obligations. + // Add GAT where clauses from the trait's definition. This is necessary + // for soundness until we properly handle implied bounds on binders, + // see tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.rs. ecx.add_goals( GoalSource::AliasWellFormed, cx.own_predicates_of(goal.predicate.def_id()) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 0906284e70196..e5c2adaa261d3 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2055,6 +2055,9 @@ fn confirm_impl_candidate<'cx, 'tcx>( // Get obligations corresponding to the predicates from the where-clause of the // associated type itself. +// +// This is necessary for soundness until we properly handle implied bounds on binders. +// see tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.rs. // FIXME(mgca): While this supports constants, it is only used for types by default right now fn assoc_term_own_obligations<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, diff --git a/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.current.stderr b/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.current.stderr new file mode 100644 index 0000000000000..2e7e8c12e671e --- /dev/null +++ b/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.current.stderr @@ -0,0 +1,10 @@ +error: higher-ranked lifetime error + --> $DIR/must-prove-where-clauses-on-norm.rs:23:61 + | +LL | let func: for<'a, 'b> fn((), &'b str) -> &'static str = foo::<()>; + | ^^^^^^^^^ + | + = note: could not normalize `for<'b> fn(<() as Trait>::Assoc<'_, 'b>, &'b str) -> &str` + +error: aborting due to 1 previous error + diff --git a/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.next.stderr b/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.next.stderr new file mode 100644 index 0000000000000..ab51e2bdae77f --- /dev/null +++ b/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.next.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/must-prove-where-clauses-on-norm.rs:23:61 + | +LL | let func: for<'a, 'b> fn((), &'b str) -> &'static str = foo::<()>; + | ------------------------------------------- ^^^^^^^^^ one type is more general than the other + | | + | expected due to this + | + = note: expected fn pointer `for<'b> fn((), &'b _) -> &'static _` + found fn item `for<'b> fn(<() as Trait>::Assoc<'_, 'b>, &'b _) -> &_ {foo::<'_, ()>}` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.rs b/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.rs new file mode 100644 index 0000000000000..064ed18248206 --- /dev/null +++ b/tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.rs @@ -0,0 +1,28 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// We have to prove implied bounds of higher-ranked types at some point. +// Normalizing associated types can drop requirements. This means we need +// to prove well-formedness when normalizing them, at least as long as +// implied bounds are implicit. + +trait Trait { + type Assoc<'a, 'b: 'a>; +} + +impl Trait for () { + type Assoc<'a, 'b: 'a> = (); +} + +fn foo<'a, 'b, T: Trait>(_: ::Assoc<'a, 'b>, x: &'b str) -> &'a str { + x +} + +fn main() { + let func: for<'a, 'b> fn((), &'b str) -> &'static str = foo::<()>; + //[current]~^ ERROR higher-ranked lifetime error + //[next]~^^ ERROR mismatched types + let x: &'static str = func((), &String::from("temporary")); + println!("{x}"); +}