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 1/2] 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() {} From ea562aeed553eaee9961a2adb259f48ffbe83666 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Sat, 15 Jan 2022 23:17:32 -0500 Subject: [PATCH 2/2] Add nll revision for issue-92096 test that passes --- ...issue-92096.stderr => issue-92096.migrate.stderr} | 4 ++-- src/test/ui/generic-associated-types/issue-92096.rs | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) rename src/test/ui/generic-associated-types/{issue-92096.stderr => issue-92096.migrate.stderr} (92%) diff --git a/src/test/ui/generic-associated-types/issue-92096.stderr b/src/test/ui/generic-associated-types/issue-92096.migrate.stderr similarity index 92% rename from src/test/ui/generic-associated-types/issue-92096.stderr rename to src/test/ui/generic-associated-types/issue-92096.migrate.stderr index a897ba5b966ec..72ade5774d749 100644 --- a/src/test/ui/generic-associated-types/issue-92096.stderr +++ b/src/test/ui/generic-associated-types/issue-92096.migrate.stderr @@ -1,5 +1,5 @@ error[E0311]: the parameter type `C` may not live long enough - --> $DIR/issue-92096.rs:18:33 + --> $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 @@ -7,7 +7,7 @@ LL | fn call_connect(c: &'_ C) -> impl '_ + Future + Send | 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 + --> $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 diff --git a/src/test/ui/generic-associated-types/issue-92096.rs b/src/test/ui/generic-associated-types/issue-92096.rs index 6c81babc0bccb..066132a5d98bb 100644 --- a/src/test/ui/generic-associated-types/issue-92096.rs +++ b/src/test/ui/generic-associated-types/issue-92096.rs @@ -1,8 +1,10 @@ // edition:2018 -// check-fail -// FIXME(generic_associated_types): this should pass, but we end up -// essentially requiring that `for<'s> C: 's` +// [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; @@ -16,8 +18,8 @@ trait Client { } fn call_connect(c: &'_ C) -> impl '_ + Future + Send -//~^ ERROR the parameter -//~| ERROR the parameter +//[migrate]~^ ERROR the parameter +//[migrate]~| ERROR the parameter where C: Client + Send + Sync, {