diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 74eb263a63390..a5276afc5bfa7 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -164,7 +164,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { "cannot process registered region obligations in a snapshot" ); - debug!("process_registered_region_obligations()"); + debug!(?param_env, "process_registered_region_obligations()"); let my_region_obligations = self.take_registered_region_obligations(); @@ -356,6 +356,8 @@ where let trait_bounds: Vec<_> = self.verify_bound.projection_declared_bounds_from_trait(projection_ty).collect(); + debug!(?trait_bounds); + // Compute the bounds we can derive from the environment. This // is an "approximate" match -- in some cases, these bounds // may not apply. diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 8f5d6c85097cb..0833ebfd5f333 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -241,10 +241,19 @@ impl<'tcx> Elaborator<'tcx> { Component::UnresolvedInferenceVariable(_) => None, - Component::Projection(_) | Component::EscapingProjection(_) => { - // We can probably do more here. This - // corresponds to a case like `>::U: 'b`. + Component::Projection(projection) => { + // We might end up here if we have `Foo<::Assoc>: 'a`. + // With this, we can deduce that `::Assoc: 'a`. + let ty = + tcx.mk_projection(projection.item_def_id, projection.substs); + Some(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( + ty, r_min, + ))) + } + + Component::EscapingProjection(_) => { + // We might be able to do more here, but we don't + // want to deal with escaping vars right now. None } }) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index b7fc578ea3bd3..d7b92c64fd7a1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -206,7 +206,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { })?); if let ty::Projection(..) = placeholder_self_ty.kind() { - for predicate in tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates { + let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates; + debug!(?predicates, "projection predicates"); + for predicate in predicates { let normalized = normalize_with_depth_to( self, obligation.param_env, diff --git a/src/test/ui/generic-associated-types/issue-92096.migrate.stderr b/src/test/ui/generic-associated-types/issue-92096.migrate.stderr new file mode 100644 index 0000000000000..72ade5774d749 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-92096.migrate.stderr @@ -0,0 +1,18 @@ +error[E0311]: the parameter type `C` may not live long enough + --> $DIR/issue-92096.rs:20:33 + | +LL | fn call_connect(c: &'_ C) -> impl '_ + Future + Send + | - ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | | + | help: consider adding an explicit lifetime bound...: `C: 'a` + +error[E0311]: the parameter type `C` may not live long enough + --> $DIR/issue-92096.rs:20:33 + | +LL | fn call_connect(c: &'_ C) -> impl '_ + Future + Send + | - ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | | + | help: consider adding an explicit lifetime bound...: `C: 'a` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/generic-associated-types/issue-92096.rs b/src/test/ui/generic-associated-types/issue-92096.rs new file mode 100644 index 0000000000000..066132a5d98bb --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-92096.rs @@ -0,0 +1,29 @@ +// edition:2018 +// [nll] check-pass +// revisions: migrate nll +// Explicitly testing nll with revision, so ignore compare-mode=nll +// ignore-compare-mode-nll + +#![cfg_attr(nll, feature(nll))] +#![feature(generic_associated_types)] + +use std::future::Future; + +trait Client { + type Connecting<'a>: Future + Send + where + Self: 'a; + + fn connect(&'_ self) -> Self::Connecting<'_>; +} + +fn call_connect(c: &'_ C) -> impl '_ + Future + Send +//[migrate]~^ ERROR the parameter +//[migrate]~| ERROR the parameter +where + C: Client + Send + Sync, +{ + async move { c.connect().await } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-92280.rs b/src/test/ui/generic-associated-types/issue-92280.rs new file mode 100644 index 0000000000000..db26493ecadfa --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-92280.rs @@ -0,0 +1,26 @@ +// check-pass + +#![feature(generic_associated_types)] +#![allow(non_camel_case_types)] + +trait HasAssoc { + type Assoc; +} + +trait Iterate { + type Iter<'a> + where + Self: 'a; +} + +struct KeySegment_Broken { + key: T, +} +impl Iterate for KeySegment_Broken { + type Iter<'a> + where + Self: 'a, + = (); +} + +fn main() {}