diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 964f801e53819..1898c43c6d0ac 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -239,26 +239,21 @@ fn compare_method_predicate_entailment<'tcx>( let hybrid_preds = hybrid_preds.into_iter().map(Unnormalized::skip_norm_wip); let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id); let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds)); - // FIXME(-Zhigher-ranked-assumptions): The `hybrid_preds` + // NOTE(-Zhigher-ranked-assumptions): The `hybrid_preds` // should be well-formed. However, using them may result in // region errors as we currently don't track placeholder // assumptions. // - // To avoid being backwards incompatible with the old solver, - // we also eagerly normalize the where-bounds in the new solver - // here while ignoring region constraints. This means we can then - // use where-bounds whose normalization results in placeholder - // errors further down without getting any errors. + // We eagerly normalize the where-clauses here while ignoring + // region constraints This means we can then use where-bounds + // whose normalization results in placeholder errors further + // down without getting any errors. // - // It should be sound to do so as the only region errors here + // This should be sound to do so as the only region errors here // should be due to missing implied bounds. // // cc trait-system-refactor-initiative/issues/166. - let param_env = if tcx.next_trait_solver_globally() { - traits::deeply_normalize_param_env_ignoring_regions(tcx, param_env, normalize_cause) - } else { - traits::normalize_param_env_or_error(tcx, param_env, normalize_cause) - }; + let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); debug!(caller_bounds=?param_env.caller_bounds()); let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis()); diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 678f1ee96abbb..fc9ac0e4f8923 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -30,7 +30,6 @@ use rustc_errors::ErrorGuaranteed; pub use rustc_infer::traits::*; use rustc_macros::TypeVisitable; use rustc_middle::query::Providers; -use rustc_middle::span_bug; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ self, Clause, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder, @@ -257,12 +256,6 @@ fn do_normalize_predicates<'tcx>( elaborated_env: ty::ParamEnv<'tcx>, predicates: Vec>, ) -> Result>, ErrorGuaranteed> { - // Even if we move back to eager normalization elsewhere, - // param env normalization remains lazy in the next solver. - if tcx.next_trait_solver_globally() { - return Ok(predicates); - } - // FIXME. We should really... do something with these region // obligations. But this call just continues the older // behavior (i.e., doesn't cause any new bugs), and it would @@ -291,17 +284,20 @@ fn do_normalize_predicates<'tcx>( // We can use the `elaborated_env` here; the region code only // cares about declarations like `'a: 'b`. + // // FIXME: It's very weird that we ignore region obligations but apparently // still need to use `resolve_regions` as we need the resolved regions in // the normalized predicates. - let errors = infcx.resolve_regions(cause.body_id, elaborated_env, []); - if !errors.is_empty() { - tcx.dcx().span_delayed_bug( - span, - format!("failed region resolution while normalizing {elaborated_env:?}: {errors:?}"), - ); - } - + // + // FIXME(-Zhigher-ranked-assumptions): We're ignoring region errors for now. + // There're placeholder constraints `leaking` out. This is a hack to work around + // the fact that we don't support placeholder assumptions right now and is necessary + // for `compare_method_predicate_entailment`. We should remove this once we + // have proper support for implied bounds on binders. + // + // This is required by trait-system-refactor-initiative#166. The new solver encounters + // this more frequently as we entirely ignore outlives predicates with the old solver. + let _errors = infcx.resolve_regions(cause.body_id, elaborated_env, []); match infcx.fully_resolve(predicates) { Ok(predicates) => Ok(predicates), Err(fixup_err) => { @@ -478,69 +474,6 @@ pub fn normalize_param_env_or_error<'tcx>( ty::ParamEnv::new(tcx.mk_clauses(&predicates)) } -/// Deeply normalize the param env using the next solver ignoring -/// region errors. -/// -/// FIXME(-Zhigher-ranked-assumptions): this is a hack to work around -/// the fact that we don't support placeholder assumptions right now -/// and is necessary for `compare_method_predicate_entailment`, see the -/// use of this function for more info. We should remove this once we -/// have proper support for implied bounds on binders. -#[instrument(level = "debug", skip(tcx))] -pub fn deeply_normalize_param_env_ignoring_regions<'tcx>( - tcx: TyCtxt<'tcx>, - unnormalized_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, -) -> ty::ParamEnv<'tcx> { - let predicates: Vec<_> = - util::elaborate(tcx, unnormalized_env.caller_bounds().into_iter()).collect(); - - debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates); - - let elaborated_env = ty::ParamEnv::new(tcx.mk_clauses(&predicates)); - if !elaborated_env.has_aliases() { - return elaborated_env; - } - - let span = cause.span; - let infcx = tcx - .infer_ctxt() - .with_next_trait_solver(true) - .ignoring_regions() - .build(TypingMode::non_body_analysis()); - let predicates = match crate::solve::deeply_normalize::<_, FulfillmentError<'tcx>>( - infcx.at(&cause, elaborated_env), - Unnormalized::new_wip(predicates), - ) { - Ok(predicates) => predicates, - Err(errors) => { - infcx.err_ctxt().report_fulfillment_errors(errors); - // An unnormalized env is better than nothing. - debug!("normalize_param_env_or_error: errored resolving predicates"); - return elaborated_env; - } - }; - - debug!("do_normalize_predicates: normalized predicates = {:?}", predicates); - // FIXME(-Zhigher-ranked-assumptions): We're ignoring region errors for now. - // There're placeholder constraints `leaking` out. - // See the fixme in the enclosing function's docs for more. - let _errors = infcx.resolve_regions(cause.body_id, elaborated_env, []); - - let predicates = match infcx.fully_resolve(predicates) { - Ok(predicates) => predicates, - Err(fixup_err) => { - span_bug!( - span, - "inference variables in normalized parameter environment: {}", - fixup_err - ) - } - }; - debug!("normalize_param_env_or_error: final predicates={:?}", predicates); - ty::ParamEnv::new(tcx.mk_clauses(&predicates)) -} - #[derive(Debug)] pub enum EvaluateConstErr { /// The constant being evaluated was either a generic parameter or inference variable, *or*, diff --git a/tests/crashes/136661.rs b/tests/crashes/136661.rs deleted file mode 100644 index 76161a566f4c7..0000000000000 --- a/tests/crashes/136661.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ known-bug: #136661 - -#![allow(unused)] - -trait Supertrait {} - -trait Other { - fn method(&self) {} -} - -impl WithAssoc for &'static () { - type As = (); -} - -trait WithAssoc { - type As; -} - -trait Trait: Supertrait { - fn method(&self) {} -} - -fn hrtb Trait<&'a ()>>() {} - -pub fn main() {} diff --git a/tests/ui/specialization/min_specialization/next-solver-region-resolution.rs b/tests/ui/specialization/min_specialization/next-solver-region-resolution.rs index 2bd8529df3991..16c0f80b1c8dd 100644 --- a/tests/ui/specialization/min_specialization/next-solver-region-resolution.rs +++ b/tests/ui/specialization/min_specialization/next-solver-region-resolution.rs @@ -16,7 +16,7 @@ where } impl<'a, T> Foo for &T -//~^ ERROR: conflicting implementations of trait `Foo` for type `&_` +//~^ ERROR: cycle detected when computing normalized predicates of `` where Self::Item: Baz, { diff --git a/tests/ui/specialization/min_specialization/next-solver-region-resolution.stderr b/tests/ui/specialization/min_specialization/next-solver-region-resolution.stderr index cae27b4b31097..4c2dc5e8e71fa 100644 --- a/tests/ui/specialization/min_specialization/next-solver-region-resolution.stderr +++ b/tests/ui/specialization/min_specialization/next-solver-region-resolution.stderr @@ -1,17 +1,22 @@ -error[E0119]: conflicting implementations of trait `Foo` for type `&_` +error[E0391]: cycle detected when computing normalized predicates of `` --> $DIR/next-solver-region-resolution.rs:18:1 | -LL | / impl<'a, T> Foo for &'a T -LL | | where -LL | | Self::Item: 'a, - | |___________________- first implementation here -... LL | / impl<'a, T> Foo for &T LL | | LL | | where LL | | Self::Item: Baz, - | |____________________^ conflicting implementation for `&_` + | |____________________^ + | + = note: ...which immediately requires computing normalized predicates of `` again +note: cycle used when computing whether impls specialize one another + --> $DIR/next-solver-region-resolution.rs:12:1 + | +LL | / impl<'a, T> Foo for &'a T +LL | | where +LL | | Self::Item: 'a, + | |___________________^ + = note: for more information, see and error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr index 1e450571ed9da..147b248c33da8 100644 --- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr @@ -18,8 +18,9 @@ LL | fn accept0(_: Container<{ T::make() }>) {} = note: ...which requires building an abstract representation for `accept0::{constant#0}`... = note: ...which requires building THIR for `accept0::{constant#0}`... = note: ...which requires type-checking `accept0::{constant#0}`... + = note: ...which requires computing normalized predicates of `accept0::{constant#0}`... = note: ...which again requires evaluating type-level constant, completing the cycle - = note: cycle used when checking that `accept0` is well-formed + = note: cycle used when computing normalized predicates of `accept0` = note: for more information, see and error[E0391]: cycle detected when checking if `accept1::{constant#0}` is a trivial const @@ -32,6 +33,7 @@ LL | const fn accept1(_: Container<{ T::make() }>) {} = note: ...which requires building an abstract representation for `accept1::{constant#0}`... = note: ...which requires building THIR for `accept1::{constant#0}`... = note: ...which requires type-checking `accept1::{constant#0}`... + = note: ...which requires computing normalized predicates of `accept1::{constant#0}`... = note: ...which requires evaluating type-level constant... = note: ...which requires const-evaluating + checking `accept1::{constant#0}`... = note: ...which again requires checking if `accept1::{constant#0}` is a trivial const, completing the cycle diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs index 6cd0b0b1aaa30..d3603accf2292 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs @@ -21,6 +21,10 @@ trait Foo { impl Foo for () { type Item = String where String: Copy; //~^ ERROR overflow evaluating the requirement `String: Copy` + //~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275] + //~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275] + //~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275] + //~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275] } fn main() { diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.stderr b/tests/ui/traits/next-solver/alias-bound-unsound.stderr index 60e337f98d8a2..2fc6c23726b7a 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr @@ -1,3 +1,33 @@ +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` + --> $DIR/alias-bound-unsound.rs:22:5 + | +LL | type Item = String where String: Copy; + | ^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` + --> $DIR/alias-bound-unsound.rs:22:5 + | +LL | type Item = String where String: Copy; + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` + --> $DIR/alias-bound-unsound.rs:22:5 + | +LL | type Item = String where String: Copy; + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` + --> $DIR/alias-bound-unsound.rs:22:5 + | +LL | type Item = String where String: Copy; + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0275]: overflow evaluating the requirement `String: Copy` --> $DIR/alias-bound-unsound.rs:22:38 | @@ -13,31 +43,31 @@ LL | type Item: Copy | ^^^^ this trait's associated type doesn't have the requirement `String: Copy` error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == String` - --> $DIR/alias-bound-unsound.rs:28:22 + --> $DIR/alias-bound-unsound.rs:32:22 | LL | let _ = identity(<() as Foo>::copy_me(&x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` - --> $DIR/alias-bound-unsound.rs:28:22 + --> $DIR/alias-bound-unsound.rs:32:22 | LL | let _ = identity(<() as Foo>::copy_me(&x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` - --> $DIR/alias-bound-unsound.rs:28:43 + --> $DIR/alias-bound-unsound.rs:32:43 | LL | let _ = identity(<() as Foo>::copy_me(&x)); | ^^ error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` - --> $DIR/alias-bound-unsound.rs:28:22 + --> $DIR/alias-bound-unsound.rs:32:22 | LL | let _ = identity(<() as Foo>::copy_me(&x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 5 previous errors +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs index ffbbecaf89570..83e300b077428 100644 --- a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs +++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs @@ -38,6 +38,7 @@ fn impls_bound() { // - normalize `>::Assoc` // - via blanket impl, requires where-clause `Foo: Bound` -> cycle fn generic() +//~^ ERROR the trait bound `Foo: Bound` is not satisfied where >::Assoc: Bound, //~^ ERROR the trait bound `Foo: Bound` is not satisfied diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr index f679b94a92377..e18265190278a 100644 --- a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr +++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr @@ -1,5 +1,32 @@ error[E0277]: the trait bound `Foo: Bound` is not satisfied - --> $DIR/normalizes-to-is-not-productive.rs:42:31 + --> $DIR/normalizes-to-is-not-productive.rs:40:1 + | +LL | / fn generic() +LL | | +LL | | where +LL | | >::Assoc: Bound, + | |____________________________________^ unsatisfied trait bound + | +help: the trait `Bound` is not implemented for `Foo` + --> $DIR/normalizes-to-is-not-productive.rs:18:1 + | +LL | struct Foo; + | ^^^^^^^^^^ +help: the trait `Bound` is implemented for `u32` + --> $DIR/normalizes-to-is-not-productive.rs:11:1 + | +LL | impl Bound for u32 { + | ^^^^^^^^^^^^^^^^^^ +note: required for `Foo` to implement `Trait` + --> $DIR/normalizes-to-is-not-productive.rs:23:19 + | +LL | impl Trait for T { + | ----- ^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error[E0277]: the trait bound `Foo: Bound` is not satisfied + --> $DIR/normalizes-to-is-not-productive.rs:43:31 | LL | >::Assoc: Bound, | ^^^^^ unsatisfied trait bound @@ -30,7 +57,7 @@ LL | | } | |_^ required by this bound in `Bound` error[E0277]: the trait bound `Foo: Bound` is not satisfied - --> $DIR/normalizes-to-is-not-productive.rs:47:19 + --> $DIR/normalizes-to-is-not-productive.rs:48:19 | LL | impls_bound::(); | ^^^ unsatisfied trait bound @@ -51,6 +78,6 @@ note: required by a bound in `impls_bound` LL | fn impls_bound() { | ^^^^^ required by this bound in `impls_bound` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs index 914773c82196a..4d088073c3ba6 100644 --- a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs +++ b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs @@ -14,7 +14,7 @@ fn foo() where T: for<'a> Proj<'a, Assoc = for<'b> fn(>::Assoc)>, (): Trait<>::Assoc> - //~^ ERROR: overflow evaluating the requirement `(): Trait<>::Assoc>` + //~^ ERROR: the trait bound `(): Trait fn(>::Assoc))>` is not satisfied { } diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr index e2ee83cfadbef..1408890184a90 100644 --- a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr +++ b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr @@ -1,11 +1,14 @@ -error[E0275]: overflow evaluating the requirement `(): Trait<>::Assoc>` +error[E0277]: the trait bound `(): Trait fn(>::Assoc))>` is not satisfied --> $DIR/find-param-recursion-issue-152716.rs:16:9 | LL | (): Trait<>::Assoc> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait fn(>::Assoc))>` is not implemented for `()` | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`find_param_recursion_issue_152716`) +help: consider extending the `where` clause, but there might be an alternative better way to express this requirement + | +LL | (): Trait<>::Assoc>, (): Trait fn(>::Assoc))> + | +++++++++++++++++++++++++++++++++++++++++++++++++++ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr index ecd86dba97994..61eb660042d46 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr @@ -45,6 +45,26 @@ LL | trait A { LL | fn f() | ^ this trait's associated function doesn't have the requirement `_: A` +error[E0275]: overflow evaluating the requirement `<() as A>::Assoc == _` + --> $DIR/normalize-param-env-2.rs:22:5 + | +LL | / fn f() +LL | | where +LL | | Self::Assoc: A, + | |__________________________^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0275]: overflow evaluating the requirement `<() as A>::Assoc == _` + --> $DIR/normalize-param-env-2.rs:22:5 + | +LL | / fn f() +LL | | where +LL | | Self::Assoc: A, + | |__________________________^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: A` --> $DIR/normalize-param-env-2.rs:24:22 | @@ -92,7 +112,7 @@ LL | where LL | Self::Assoc: A, | ^^^^ required by this bound in `A::f` -error: aborting due to 9 previous errors +error: aborting due to 11 previous errors Some errors have detailed explanations: E0275, E0283. For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr index 47d38365e970e..01c82c49975d4 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr @@ -1,3 +1,21 @@ +error[E0275]: overflow evaluating the requirement `::Assoc == _` + --> $DIR/normalize-param-env-4.rs:17:1 + | +LL | / fn foo() +LL | | where +LL | | ::Assoc: Trait, + | |_______________________________^ + +error[E0275]: overflow evaluating the requirement `::Assoc == _` + --> $DIR/normalize-param-env-4.rs:17:1 + | +LL | / fn foo() +LL | | where +LL | | ::Assoc: Trait, + | |_______________________________^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0275]: overflow evaluating the requirement `::Assoc: Trait` --> $DIR/normalize-param-env-4.rs:19:26 | @@ -22,6 +40,6 @@ note: required by a bound in `impls_trait` LL | fn impls_trait() {} | ^^^^^ required by this bound in `impls_trait` -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/normalize/param_env-region-constraints-ambiguity.rs b/tests/ui/traits/next-solver/normalize/param_env-region-constraints-ambiguity.rs new file mode 100644 index 0000000000000..08a7148ca5e88 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/param_env-region-constraints-ambiguity.rs @@ -0,0 +1,101 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// Regression test for trait-system-refactor-initiative#265. Different where-clauses +// normalizing to the same bound caused ambiguity errors if we lazily normalized +// where-clauses when using them to prove a goal. +// +// We avoid these errors by eagerly normalizing the `param_env`. + +mod one { + trait Trait { + type Assoc<'a> + where + Self: 'a; + } + + trait Bound<'a> {} + fn impls_bound<'a, T: Bound<'a>>() {} + fn foo<'a, T: 'a>() + where + T: Trait = T> + Bound<'a>, + T::Assoc<'a>: Bound<'a>, + { + impls_bound::<'_, T>(); + } +} + +mod two { + trait Trait { + type Assoc<'a> + where + Self: 'a; + } + + trait Bound {} + fn impls_bound() {} + fn foo<'a, T: 'a>() + where + T: Trait = T> + Bound, + T::Assoc<'a>: Bound, + { + impls_bound::(); + } +} + +// Minimization of tokio-par-util. +mod three { + trait Trait1 { + type Assoc1; + } + + trait Trait2 { + type Assoc2; + } + + struct Indir(T); + impl Trait2 for Indir + where + T: Trait1, + T::Assoc1: Trait2 + 'static, + { + type Assoc2 = ::Assoc2; + } + + struct WrapperTwo(T, U); + + impl Trait1 for WrapperTwo + where + T: Trait1, + T::Assoc1: Trait2 + 'static, + // additional region constraint in this candidate so they + // can't be merged. + U: Trait1 as Trait2>::Assoc2>, + U: Trait1::Assoc2>, + { + type Assoc1 = i32; + } +} + +// Minimization of `qazer` +mod four { + trait Value { + type SelfType<'a> + where + Self: 'a; + } + + trait Repository {} + struct RedbRepo(From, Into); + + impl Repository for RedbRepo + where + for<'a> From: Value = From> + Clone + 'static, + for<'a> ::SelfType<'a>: Clone, + { + } +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs index c61fbef05b224..8dc27c0da605a 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs @@ -13,7 +13,7 @@ fn needs_bar() {} fn test::Assoc2> + Foo2::Assoc1>>() { needs_bar::(); - //~^ ERROR: the trait bound `::Assoc2: Bar` is not satisfied + //~^ ERROR: the trait bound `::Assoc1: Bar` is not satisfied } fn main() {} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr index c4be47e3520da..6f5111a6193ca 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `::Assoc2: Bar` is not satisfied +error[E0277]: the trait bound `::Assoc1: Bar` is not satisfied --> $DIR/recursive-self-normalization-2.rs:15:17 | LL | needs_bar::(); - | ^^^^^^^^^ the trait `Bar` is not implemented for `::Assoc2` + | ^^^^^^^^^ the trait `Bar` is not implemented for `::Assoc1` | note: required by a bound in `needs_bar` --> $DIR/recursive-self-normalization-2.rs:12:17 @@ -11,7 +11,7 @@ LL | fn needs_bar() {} | ^^^ required by this bound in `needs_bar` help: consider further restricting the associated type | -LL | fn test::Assoc2> + Foo2::Assoc1>>() where ::Assoc2: Bar { +LL | fn test::Assoc2> + Foo2::Assoc1>>() where ::Assoc1: Bar { | ++++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-1.rs b/tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-1.rs new file mode 100644 index 0000000000000..7fcb164d3a95d --- /dev/null +++ b/tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-1.rs @@ -0,0 +1,41 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// In `fn hrtb` normalizing the elaborated where-clause +// `T: for<'a> Supertrait<<&'a () as WithAssoc>::As>` results in +// a region error as `&'a ()` is not equal to `&'static ()`. +// +// This happens even though the where-clauses themselves are well-formed +// as we never have to prove `&'a (): WithAssoc` as `'a` is a bound variable. +// +// I don't think this can cause unsoundness and has already been accepted in the +// old solver as we didn't register TypeOutlives constraints if `ignoring_regions` +// is set. The new solver always registers outlives constraints, so this then +// caused an error there. We need to ignore these region errors with the new solver +// due to trait-system-refactor-initiative#166. + +#![allow(unused)] + +trait Supertrait {} + +trait Other { + fn method(&self) {} +} + +impl WithAssoc for T { + type As = T; +} + +trait WithAssoc { + type As; +} + +trait Trait: Supertrait { + fn method(&self) {} +} + +fn hrtb Trait<&'a ()>>() {} + +pub fn main() {} diff --git a/tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-2.rs b/tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-2.rs new file mode 100644 index 0000000000000..9339518aae1a0 --- /dev/null +++ b/tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-2.rs @@ -0,0 +1,39 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// In `fn hrtb` normalizing the elaborated where-clause +// `T: for<'a> Supertrait<<&'a () as WithAssoc>::As>` results in +// a region error as `&'a ()` is not `'static`. +// +// This happens even though the where-clauses themselves are well-formed +// as we never have to prove `&'a (): WithAssoc` as `'a` is a bound variable. +// +// Unlike `normalize-param-env-missing-implied-bound-1.rs` this snippet caused +// an ICE with the old trait solver, as we did register region constraints from +// relating types. This ICE was tracked in #136661. + +#![allow(unused)] + +trait Supertrait {} + +trait Other { + fn method(&self) {} +} + +impl WithAssoc for &'static () { + type As = (); +} + +trait WithAssoc { + type As; +} + +trait Trait: Supertrait { + fn method(&self) {} +} + +fn hrtb Trait<&'a ()>>() {} + +pub fn main() {}