instantiate predicate binder without recanonicalizing goal in new solver

This commit is contained in:
Michael Goulet 2025-02-14 00:26:30 +00:00 committed by lcnr
parent c0c37cafdc
commit 5508b471bd
23 changed files with 114 additions and 213 deletions

View file

@ -1,7 +1,6 @@
//! A utility module to inspect currently ambiguous obligations in the current context.
use rustc_infer::traits::{self, ObligationCause, PredicateObligations};
use rustc_middle::traits::solve::GoalSource;
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_span::Span;
use rustc_trait_selection::solve::Certainty;
@ -127,21 +126,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'a, 'tcx> {
let tcx = self.fcx.tcx;
let goal = inspect_goal.goal();
if self.fcx.predicate_has_self_ty(goal.predicate, self.self_ty)
// We do not push the instantiated forms of goals as it would cause any
// aliases referencing bound vars to go from having escaping bound vars to
// being able to be normalized to an inference variable.
//
// This is mostly just a hack as arbitrary nested goals could still contain
// such aliases while having a different `GoalSource`. Closure signature inference
// however can't really handle *every* higher ranked `Fn` goal also being present
// in the form of `?c: Fn<(<?x as Trait<'!a>>::Assoc)`.
//
// This also just better matches the behaviour of the old solver where we do not
// encounter instantiated forms of goals, only nested goals that referred to bound
// vars from instantiated goals.
&& !matches!(inspect_goal.source(), GoalSource::InstantiateHigherRanked)
{
if self.fcx.predicate_has_self_ty(goal.predicate, self.self_ty) {
self.obligations_for_self_ty.push(traits::Obligation::new(
tcx,
self.root_cause.clone(),

View file

@ -297,9 +297,6 @@ where
// corecursive functions as explained in #136824, relating types never
// introduces a constructor which could cause the recursion to be guarded.
GoalSource::TypeRelating => PathKind::Inductive,
// Instantiating a higher ranked goal can never cause the recursion to be
// guarded and is therefore unproductive.
GoalSource::InstantiateHigherRanked => PathKind::Inductive,
// These goal sources are likely unproductive and can be changed to
// `PathKind::Inductive`. Keeping them as unknown until we're confident
// about this and have an example where it is necessary.
@ -567,66 +564,56 @@ where
pub(super) fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
let Goal { param_env, predicate } = goal;
let kind = predicate.kind();
if let Some(kind) = kind.no_bound_vars() {
match kind {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
self.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r)
}
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
self.compute_host_effect_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => {
self.compute_projection_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(predicate)) => {
self.compute_type_outlives_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(predicate)) => {
self.compute_region_outlives_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
self.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) })
}
ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => {
self.compute_unstable_feature_goal(param_env, symbol)
}
ty::PredicateKind::Subtype(predicate) => {
self.compute_subtype_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Coerce(predicate) => {
self.compute_coerce_goal(Goal { param_env, predicate })
}
ty::PredicateKind::DynCompatible(trait_def_id) => {
self.compute_dyn_compatible_goal(trait_def_id)
}
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
self.compute_well_formed_goal(Goal { param_env, predicate: term })
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
self.compute_const_evaluatable_goal(Goal { param_env, predicate: ct })
}
ty::PredicateKind::ConstEquate(_, _) => {
panic!("ConstEquate should not be emitted when `-Znext-solver` is active")
}
ty::PredicateKind::NormalizesTo(predicate) => {
self.compute_normalizes_to_goal(Goal { param_env, predicate })
}
ty::PredicateKind::AliasRelate(lhs, rhs, direction) => self
.compute_alias_relate_goal(Goal {
param_env,
predicate: (lhs, rhs, direction),
}),
ty::PredicateKind::Ambiguous => {
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
self.enter_forall(kind, |ecx, kind| match kind {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
ecx.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r)
}
} else {
self.enter_forall(kind, |ecx, kind| {
let goal = goal.with(ecx.cx(), ty::Binder::dummy(kind));
ecx.add_goal(GoalSource::InstantiateHigherRanked, goal);
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
ecx.compute_host_effect_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => {
ecx.compute_projection_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(predicate)) => {
ecx.compute_type_outlives_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(predicate)) => {
ecx.compute_region_outlives_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
ecx.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) })
}
ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => {
ecx.compute_unstable_feature_goal(param_env, symbol)
}
ty::PredicateKind::Subtype(predicate) => {
ecx.compute_subtype_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Coerce(predicate) => {
ecx.compute_coerce_goal(Goal { param_env, predicate })
}
ty::PredicateKind::DynCompatible(trait_def_id) => {
ecx.compute_dyn_compatible_goal(trait_def_id)
}
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
ecx.compute_well_formed_goal(Goal { param_env, predicate: term })
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
ecx.compute_const_evaluatable_goal(Goal { param_env, predicate: ct })
}
ty::PredicateKind::ConstEquate(_, _) => {
panic!("ConstEquate should not be emitted when `-Znext-solver` is active")
}
ty::PredicateKind::NormalizesTo(predicate) => {
ecx.compute_normalizes_to_goal(Goal { param_env, predicate })
}
ty::PredicateKind::AliasRelate(lhs, rhs, direction) => {
ecx.compute_alias_relate_goal(Goal { param_env, predicate: (lhs, rhs, direction) })
}
ty::PredicateKind::Ambiguous => {
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
})
}
// Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning

View file

@ -231,7 +231,6 @@ impl<'tcx> BestObligation<'tcx> {
nested_goal.source(),
GoalSource::ImplWhereBound
| GoalSource::AliasBoundConstCondition
| GoalSource::InstantiateHigherRanked
| GoalSource::AliasWellFormed
) && nested_goal.result().is_err()
},
@ -523,10 +522,6 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
));
impl_where_bound_count += 1;
}
// Skip over a higher-ranked predicate.
(_, GoalSource::InstantiateHigherRanked) => {
obligation = self.obligation.clone();
}
(ChildMode::PassThrough, _)
| (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => {
obligation = make_obligation(self.obligation.cause.clone());

View file

@ -735,9 +735,10 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
// For bound predicates we simply call `infcx.enter_forall`
// and then prove the resulting predicate as a nested goal.
let Goal { param_env, predicate } = goal.goal();
let trait_ref = match predicate.kind().no_bound_vars() {
Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref,
Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)))
let predicate_kind = goal.infcx().enter_forall_and_leak_universe(predicate.kind());
let trait_ref = match predicate_kind {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.trait_ref,
ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj))
if matches!(
infcx.tcx.def_kind(proj.projection_term.def_id),
DefKind::AssocTy | DefKind::AssocConst

View file

@ -78,8 +78,6 @@ pub enum GoalSource {
ImplWhereBound,
/// Const conditions that need to hold for `[const]` alias bounds to hold.
AliasBoundConstCondition,
/// Instantiating a higher-ranked goal and re-proving it.
InstantiateHigherRanked,
/// Predicate required for an alias projection to be well-formed.
/// This is used in three places:
/// 1. projecting to an opaque whose hidden type is already registered in

View file

@ -12,7 +12,7 @@ LL | impl<T> Trait for Box<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
|
= note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>`
= note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<_>`
= note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<<std::boxed::Box<_> as WithAssoc<'a>>::Assoc>`
error: aborting due to 1 previous error

View file

@ -1,6 +1,7 @@
//@ known-bug: #140609
//@ check-pass
#![feature(with_negative_coherence)]
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
#![crate_type = "lib"]
trait Trait {}
struct A<const B: bool>;

View file

@ -1,23 +0,0 @@
error[E0277]: the trait bound `for<'a> &'a &T: Trait` is not satisfied
--> $DIR/candidate-from-env-universe-err-1.rs:27:16
|
LL | hr_bound::<&T>();
| ^^ the trait `for<'a> Trait` is not implemented for `&'a &T`
|
note: required by a bound in `hr_bound`
--> $DIR/candidate-from-env-universe-err-1.rs:14:20
|
LL | fn hr_bound<T>()
| -------- required by a bound in this function
LL | where
LL | for<'a> &'a T: Trait,
| ^^^^^ required by this bound in `hr_bound`
help: consider removing the leading `&`-reference
|
LL - hr_bound::<&T>();
LL + hr_bound::<T>();
|
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,6 +1,7 @@
//@ revisions: old next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@[old] check-pass
//@ check-pass
// cc #119820
@ -24,8 +25,11 @@ where
// but are able to successfully use the impl candidate. Without
// the leak check both candidates may apply and we prefer the
// `param_env` candidate in winnowing.
//
// By doing the leak check for each candidate, we discard the `param_env`
// candidate and use the impl candidate instead, allowing this to
// compile.
hr_bound::<&T>();
//[next]~^ ERROR the trait bound `for<'a> &'a &T: Trait` is not satisfied
}
fn main() {}

View file

@ -1,15 +0,0 @@
error[E0277]: the trait bound `for<'a> T: Trait<'a, '_>` is not satisfied
--> $DIR/candidate-from-env-universe-err-2.rs:15:15
|
LL | impl_hr::<T>();
| ^ the trait `for<'a> Trait<'a, '_>` is not implemented for `T`
|
note: required by a bound in `impl_hr`
--> $DIR/candidate-from-env-universe-err-2.rs:12:19
|
LL | fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {}
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impl_hr`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,6 +1,7 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@[current] check-pass
//@ check-pass
// cc #119820
@ -13,7 +14,6 @@ fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {}
fn not_hr<'a, T: for<'b> Trait<'a, 'b> + OtherTrait<'static>>() {
impl_hr::<T>();
//[next]~^ ERROR the trait bound `for<'a> T: Trait<'a, '_>` is not satisfied
}
fn main() {}

View file

@ -7,7 +7,7 @@ LL | projection_bound::<T>();
= note: expected associated type `<T as Trait<'static>>::Assoc`
found associated type `<T as Trait<'a>>::Assoc`
note: the lifetime requirement is introduced here
--> $DIR/candidate-from-env-universe-err-project.rs:18:42
--> $DIR/candidate-from-env-universe-err-project.rs:19:42
|
LL | fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
| ^^^^^^^^^^^^^

View file

@ -1,26 +1,14 @@
error[E0277]: the trait bound `for<'a> T: Trait<'a>` is not satisfied
--> $DIR/candidate-from-env-universe-err-project.rs:28:19
|
LL | trait_bound::<T>();
| ^ the trait `for<'a> Trait<'a>` is not implemented for `T`
|
note: required by a bound in `trait_bound`
--> $DIR/candidate-from-env-universe-err-project.rs:17:19
|
LL | fn trait_bound<T: for<'a> Trait<'a>>() {}
| ^^^^^^^^^^^^^^^^^ required by this bound in `trait_bound`
error[E0277]: the trait bound `for<'a> T: Trait<'a>` is not satisfied
error[E0271]: type mismatch resolving `<T as Trait<'a>>::Assoc == usize`
--> $DIR/candidate-from-env-universe-err-project.rs:38:24
|
LL | projection_bound::<T>();
| ^ the trait `for<'a> Trait<'a>` is not implemented for `T`
| ^ types differ
|
note: required by a bound in `projection_bound`
--> $DIR/candidate-from-env-universe-err-project.rs:18:24
--> $DIR/candidate-from-env-universe-err-project.rs:19:42
|
LL | fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `projection_bound`
| ^^^^^^^^^^^^^ required by this bound in `projection_bound`
error: higher-ranked subtype error
--> $DIR/candidate-from-env-universe-err-project.rs:52:30
@ -36,6 +24,6 @@ LL | let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 4 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0271`.

View file

@ -1,4 +1,5 @@
//@ revisions: next current
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
// cc #119820 the behavior is inconsistent as we discard the where-bound
@ -20,13 +21,12 @@ fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
// We use a function with a trivial where-bound which is more
// restrictive than the impl.
fn function1<T: Trait<'static>>() {
// err
// ok
//
// Proving `for<'a> T: Trait<'a>` using the where-bound does not
// result in a leak check failure even though it does not apply.
// We prefer env candidates over impl candidatescausing this to succeed.
trait_bound::<T>();
//[next]~^ ERROR the trait bound `for<'a> T: Trait<'a>` is not satisfied
}
fn function2<T: Trait<'static, Assoc = usize>>() {
@ -36,7 +36,7 @@ fn function2<T: Trait<'static, Assoc = usize>>() {
// does not use the leak check when trying the where-bound, causing us
// to prefer it over the impl, resulting in a placeholder error.
projection_bound::<T>();
//[next]~^ ERROR the trait bound `for<'a> T: Trait<'a>` is not satisfied
//[next]~^ ERROR type mismatch resolving `<T as Trait<'a>>::Assoc == usize`
//[current]~^^ ERROR mismatched types
}

View file

@ -1,23 +0,0 @@
error[E0283]: type annotations needed
--> $DIR/leak-check-in-selection-2.rs:17:5
|
LL | impls_trait::<(), _>();
| ^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_trait`
|
note: multiple `impl`s satisfying `for<'a> (): Trait<&'a str, _>` found
--> $DIR/leak-check-in-selection-2.rs:10:1
|
LL | impl<'a> Trait<&'a str, &'a str> for () {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | impl<'a> Trait<&'a str, String> for () {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `impls_trait`
--> $DIR/leak-check-in-selection-2.rs:14:19
|
LL | fn impls_trait<T: for<'a> Trait<&'a str, U>, U>() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls_trait`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0283`.

View file

@ -1,6 +1,7 @@
//@ revisions: old next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@[old] check-pass
//@ check-pass
// cc #119820
@ -15,5 +16,4 @@ fn impls_trait<T: for<'a> Trait<&'a str, U>, U>() {}
fn main() {
impls_trait::<(), _>();
//[next]~^ ERROR type annotations needed
}

View file

@ -1,22 +1,3 @@
error[E0283]: type annotations needed
--> $DIR/leak-check-in-selection-3.rs:18:5
|
LL | impls_leak::<Box<_>>();
| ^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_leak`
|
note: multiple `impl`s satisfying `for<'a> Box<_>: Leak<'a>` found
--> $DIR/leak-check-in-selection-3.rs:9:1
|
LL | impl Leak<'_> for Box<u32> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl Leak<'static> for Box<u16> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `impls_leak`
--> $DIR/leak-check-in-selection-3.rs:12:18
|
LL | fn impls_leak<T: for<'a> Leak<'a>>() {}
| ^^^^^^^^^^^^^^^^ required by this bound in `impls_leak`
error[E0283]: type annotations needed
--> $DIR/leak-check-in-selection-3.rs:35:5
|
@ -24,7 +5,7 @@ LL | impls_indirect_leak::<Box<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_indirect_leak`
|
note: multiple `impl`s satisfying `for<'a> Box<_>: Leak<'a>` found
--> $DIR/leak-check-in-selection-3.rs:9:1
--> $DIR/leak-check-in-selection-3.rs:10:1
|
LL | impl Leak<'_> for Box<u32> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -43,6 +24,6 @@ note: required by a bound in `impls_indirect_leak`
LL | fn impls_indirect_leak<T: for<'a> IndirectLeak<'a>>() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls_indirect_leak`
error: aborting due to 2 previous errors
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0283`.

View file

@ -5,7 +5,7 @@ LL | impls_indirect_leak::<Box<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_indirect_leak`
|
note: multiple `impl`s satisfying `Box<_>: Leak<'_>` found
--> $DIR/leak-check-in-selection-3.rs:9:1
--> $DIR/leak-check-in-selection-3.rs:10:1
|
LL | impl Leak<'_> for Box<u32> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,4 +1,5 @@
//@ revisions: old next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
// cc #119820, the behavior here is inconsistent,
@ -16,7 +17,6 @@ fn direct() {
// The `Box<u16>` impls fails the leak check,
// meaning that we apply the `Box<u32>` impl.
impls_leak::<Box<_>>();
//[next]~^ ERROR type annotations needed
}
trait IndirectLeak<'a> {}

View file

@ -1,18 +1,18 @@
error[E0283]: type annotations needed
--> $DIR/leak-check-in-selection-6-ambig-unify.rs:30:5
--> $DIR/leak-check-in-selection-6-ambig-unify.rs:32:5
|
LL | impls_trait::<(), _, _>()
| ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_trait`
|
note: multiple `impl`s satisfying `(): Trait<_, _>` found
--> $DIR/leak-check-in-selection-6-ambig-unify.rs:26:1
--> $DIR/leak-check-in-selection-6-ambig-unify.rs:28:1
|
LL | impl<V> Trait<u32, V> for () where for<'b> (): LeakCheckFailure<'static, 'b, V> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl<V> Trait<u32, V> for () where for<'b> ((),): LeakCheckFailure<'static, 'b, V> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl<V> Trait<u16, V> for () {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `impls_trait`
--> $DIR/leak-check-in-selection-6-ambig-unify.rs:28:19
--> $DIR/leak-check-in-selection-6-ambig-unify.rs:30:19
|
LL | fn impls_trait<T: Trait<U, V>, U: Id<V>, V>() {}
| ^^^^^^^^^^^ required by this bound in `impls_trait`

View file

@ -1,18 +1,18 @@
error[E0283]: type annotations needed
--> $DIR/leak-check-in-selection-6-ambig-unify.rs:30:5
--> $DIR/leak-check-in-selection-6-ambig-unify.rs:32:5
|
LL | impls_trait::<(), _, _>()
| ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_trait`
|
note: multiple `impl`s satisfying `(): Trait<_, _>` found
--> $DIR/leak-check-in-selection-6-ambig-unify.rs:26:1
--> $DIR/leak-check-in-selection-6-ambig-unify.rs:28:1
|
LL | impl<V> Trait<u32, V> for () where for<'b> (): LeakCheckFailure<'static, 'b, V> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl<V> Trait<u32, V> for () where for<'b> ((),): LeakCheckFailure<'static, 'b, V> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl<V> Trait<u16, V> for () {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `impls_trait`
--> $DIR/leak-check-in-selection-6-ambig-unify.rs:28:19
--> $DIR/leak-check-in-selection-6-ambig-unify.rs:30:19
|
LL | fn impls_trait<T: Trait<U, V>, U: Id<V>, V>() {}
| ^^^^^^^^^^^ required by this bound in `impls_trait`

View file

@ -1,4 +1,5 @@
//@ revisions: old next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
// The new trait solver does not return region constraints if the goal
@ -21,9 +22,10 @@ impl Id<u16> for u16 {}
trait LeakCheckFailure<'a, 'b, V: ?Sized> {}
impl<'a, 'b: 'a, V: ?Sized + Ambig> LeakCheckFailure<'a, 'b, V> for () {}
impl<'a, 'b, V: ?Sized, T: LeakCheckFailure<'a, 'b, V>> LeakCheckFailure<'a, 'b, V> for (T,) {}
trait Trait<U, V> {}
impl<V> Trait<u32, V> for () where for<'b> (): LeakCheckFailure<'static, 'b, V> {}
impl<V> Trait<u32, V> for () where for<'b> ((),): LeakCheckFailure<'static, 'b, V> {}
impl<V> Trait<u16, V> for () {}
fn impls_trait<T: Trait<U, V>, U: Id<V>, V>() {}
fn main() {

View file

@ -0,0 +1,20 @@
//@ check-pass
// cc #119820
struct W<T, U>(T, U);
trait Trait<T> {}
// using this impl results in a higher-ranked region error.
impl<'a> Trait<W<&'a str, &'a str>> for () {}
impl<'a> Trait<W<&'a str, String>> for () {}
trait NotString {}
impl NotString for &str {}
impl NotString for u32 {}
trait Overlap<U> {}
impl<T: for<'a> Trait<W<&'a str, U>>, U> Overlap<U> for T {}
impl<U: NotString> Overlap<U> for () {}
fn main() {}