diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index dbb6c54fcd93b..07720ba71ca95 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -175,9 +175,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let needs_infer = stack.obligation.predicate.has_infer_types_or_consts(); - let sized_predicate = self.tcx().lang_items().sized_trait() - == Some(stack.obligation.predicate.skip_binder().def_id()); - // If there are STILL multiple candidates, we can further // reduce the list by dropping duplicates -- including // resolving specializations. @@ -186,7 +183,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { while i < candidates.len() { let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| { self.candidate_should_be_dropped_in_favor_of( - sized_predicate, &candidates[i], &candidates[j], needs_infer, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e69bf6eca90ef..9e2d0657029fd 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1553,7 +1553,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// See the comment for "SelectionCandidate" for more details. fn candidate_should_be_dropped_in_favor_of( &mut self, - sized_predicate: bool, victim: &EvaluatedCandidate<'tcx>, other: &EvaluatedCandidate<'tcx>, needs_infer: bool, @@ -1625,16 +1624,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Drop otherwise equivalent non-const fn pointer candidates (FnPointerCandidate { .. }, FnPointerCandidate { is_const: false }) => true, - // If obligation is a sized predicate or the where-clause bound is - // global, prefer the projection or object candidate. See issue - // #50825 and #89352. - (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => { - sized_predicate || is_global(cand) - } - (ParamCandidate(ref cand), ObjectCandidate(_) | ProjectionCandidate(_)) => { - !(sized_predicate || is_global(cand)) - } - // Global bounds from the where clause should be ignored // here (see issue #50825). Otherwise, we have a where // clause so don't go around looking for impls. @@ -1650,8 +1639,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | BuiltinUnsizeCandidate | TraitUpcastingUnsizeCandidate(_) | BuiltinCandidate { .. } - | TraitAliasCandidate(..), + | TraitAliasCandidate(..) + | ObjectCandidate(_) + | ProjectionCandidate(_), ) => !is_global(cand), + (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => { + // Prefer these to a global where-clause bound + // (see issue #50825). + is_global(cand) + } ( ImplCandidate(_) | ClosureCandidate diff --git a/src/test/ui/generic-associated-types/bugs/issue-89352.base.stderr b/src/test/ui/generic-associated-types/bugs/issue-89352.base.stderr new file mode 100644 index 0000000000000..81125a7d6f320 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-89352.base.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/issue-89352.rs:36:13 + | +LL | let a = A::reborrow::<'ai, 's>(self.a.clone()); + | ^ lifetime mismatch + | + = note: expected type `<>::Iter<'s> as Sized>` + found type `<>::Iter<'ai> as Sized>` +note: the lifetime `'s` as defined here... + --> $DIR/issue-89352.rs:35:13 + | +LL | fn iter<'s>(&'s self) -> Self::Iter<'s> { + | ^^ +note: ...does not necessarily outlive the lifetime `'ai` as defined here + --> $DIR/issue-89352.rs:30:6 + | +LL | impl<'ai, T: 'ai, A: GenAssoc> GenAssoc for Wrapper<'ai, T, A> + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generic-associated-types/issue-89352.rs b/src/test/ui/generic-associated-types/bugs/issue-89352.rs similarity index 58% rename from src/test/ui/generic-associated-types/issue-89352.rs rename to src/test/ui/generic-associated-types/bugs/issue-89352.rs index d9c656d5f58a9..a9f0dd0a0b4ad 100644 --- a/src/test/ui/generic-associated-types/issue-89352.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-89352.rs @@ -1,4 +1,16 @@ -// check-pass +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + +//[base] check-fail +//[nll] check-pass +// known-bug + +// This should pass, but we end up with `A::Iter<'ai>: Sized` for some specific +// `'ai`. We also know that `for<'at> A::Iter<'at>: Sized` from the definition, +// but we prefer param env candidates. We changed this to preference in #92191, +// but this led to unintended consequences (#93262). Suprisingly, this passes +// under NLL. So only a bug in migrate mode. #![feature(generic_associated_types)] diff --git a/src/test/ui/generic-associated-types/issue-93262.rs b/src/test/ui/generic-associated-types/issue-93262.rs new file mode 100644 index 0000000000000..adc6aa8fa1afa --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-93262.rs @@ -0,0 +1,21 @@ +// check-pass + +#![feature(generic_associated_types)] + +pub trait Trait { + type Assoc<'a> where Self: 'a; +} + +pub trait Foo +where + for<'a> T::Assoc<'a>: Clone +{} + +pub struct Type; + +impl Foo for Type +where + for<'a> T::Assoc<'a>: Clone +{} + +fn main() {}