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.
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,
/// 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,
// 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.
| 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
--- /dev/null
+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 `<<A as GenAssoc<T>>::Iter<'s> as Sized>`
+ found type `<<A as GenAssoc<T>>::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<T>> GenAssoc<T> for Wrapper<'ai, T, A>
+ | ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// 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)]
+
+use std::marker::PhantomData;
+
+pub trait GenAssoc<T> {
+ type Iter<'at>;
+ fn iter(&self) -> Self::Iter<'_>;
+ fn reborrow<'longt: 'shortt, 'shortt>(iter: Self::Iter<'longt>) -> Self::Iter<'shortt>;
+}
+
+pub struct Wrapper<'a, T: 'a, A: GenAssoc<T>> {
+ a: A::Iter<'a>,
+ _p: PhantomData<T>,
+}
+
+impl<'ai, T: 'ai, A: GenAssoc<T>> GenAssoc<T> for Wrapper<'ai, T, A>
+where
+ A::Iter<'ai>: Clone,
+{
+ type Iter<'b> = ();
+ fn iter<'s>(&'s self) -> Self::Iter<'s> {
+ let a = A::reborrow::<'ai, 's>(self.a.clone());
+ }
+
+ fn reborrow<'long: 'short, 'short>(iter: Self::Iter<'long>) -> Self::Iter<'short> {
+ ()
+ }
+}
+
+fn main() {}
+++ /dev/null
-// check-pass
-
-#![feature(generic_associated_types)]
-
-use std::marker::PhantomData;
-
-pub trait GenAssoc<T> {
- type Iter<'at>;
- fn iter(&self) -> Self::Iter<'_>;
- fn reborrow<'longt: 'shortt, 'shortt>(iter: Self::Iter<'longt>) -> Self::Iter<'shortt>;
-}
-
-pub struct Wrapper<'a, T: 'a, A: GenAssoc<T>> {
- a: A::Iter<'a>,
- _p: PhantomData<T>,
-}
-
-impl<'ai, T: 'ai, A: GenAssoc<T>> GenAssoc<T> for Wrapper<'ai, T, A>
-where
- A::Iter<'ai>: Clone,
-{
- type Iter<'b> = ();
- fn iter<'s>(&'s self) -> Self::Iter<'s> {
- let a = A::reborrow::<'ai, 's>(self.a.clone());
- }
-
- fn reborrow<'long: 'short, 'short>(iter: Self::Iter<'long>) -> Self::Iter<'short> {
- ()
- }
-}
-
-fn main() {}
--- /dev/null
+// check-pass
+
+#![feature(generic_associated_types)]
+
+pub trait Trait {
+ type Assoc<'a> where Self: 'a;
+}
+
+pub trait Foo<T: Trait>
+where
+ for<'a> T::Assoc<'a>: Clone
+{}
+
+pub struct Type;
+
+impl<T: Trait> Foo<T> for Type
+where
+ for<'a> T::Assoc<'a>: Clone
+{}
+
+fn main() {}