From ad57295fc9f5b0c747ae4f72d6208ccf03b94b0b Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Sun, 9 Jan 2022 23:53:57 -0500 Subject: [PATCH] Elaborate param_env predicates when checking if type outlives involving projection holds --- .../src/infer/outlives/obligations.rs | 4 ++- compiler/rustc_infer/src/traits/util.rs | 17 +++++++++--- .../src/traits/select/confirmation.rs | 4 ++- .../generic-associated-types/issue-92096.rs | 27 +++++++++++++++++++ .../issue-92096.stderr | 18 +++++++++++++ .../generic-associated-types/issue-92280.rs | 26 ++++++++++++++++++ 6 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/generic-associated-types/issue-92096.rs create mode 100644 src/test/ui/generic-associated-types/issue-92096.stderr create mode 100644 src/test/ui/generic-associated-types/issue-92280.rs 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.rs b/src/test/ui/generic-associated-types/issue-92096.rs new file mode 100644 index 0000000000000..6c81babc0bccb --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-92096.rs @@ -0,0 +1,27 @@ +// edition:2018 +// check-fail +// FIXME(generic_associated_types): this should pass, but we end up +// essentially requiring that `for<'s> C: 's` + +#![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 +//~^ ERROR the parameter +//~| 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-92096.stderr b/src/test/ui/generic-associated-types/issue-92096.stderr new file mode 100644 index 0000000000000..a897ba5b966ec --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-92096.stderr @@ -0,0 +1,18 @@ +error[E0311]: the parameter type `C` may not live long enough + --> $DIR/issue-92096.rs:18: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:18: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-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() {}