Skip to content

Commit

Permalink
Rollup merge of #92710 - jackh726:issue-92280, r=nikomatsakis
Browse files Browse the repository at this point in the history
Include Projections when elaborating TypeOutlives

Fixes #92280

In `Elaborator`, we elaborate that `Foo<<Bar as Baz>::Assoc>: 'a` -> `<Bar as Baz>::Assoc: 'a`. This is the same rule that would be applied to any other `Param`. If there are escaping vars, we continue to do nothing.

r? `@nikomatsakis`
  • Loading branch information
matthiaskrgr committed Jan 16, 2022
2 parents 039d6dc + ea562ae commit 9835b90
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 6 deletions.
4 changes: 3 additions & 1 deletion compiler/rustc_infer/src/infer/outlives/obligations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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.
Expand Down
17 changes: 13 additions & 4 deletions compiler/rustc_infer/src/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<T as
// Foo<'a>>::U: 'b`.
Component::Projection(projection) => {
// We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
// With this, we can deduce that `<Bar as Baz>::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
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
18 changes: 18 additions & 0 deletions src/test/ui/generic-associated-types/issue-92096.migrate.stderr
Original file line number Diff line number Diff line change
@@ -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: &'_ 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: &'_ 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

29 changes: 29 additions & 0 deletions src/test/ui/generic-associated-types/issue-92096.rs
Original file line number Diff line number Diff line change
@@ -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: &'_ C) -> impl '_ + Future + Send
//[migrate]~^ ERROR the parameter
//[migrate]~| ERROR the parameter
where
C: Client + Send + Sync,
{
async move { c.connect().await }
}

fn main() {}
26 changes: 26 additions & 0 deletions src/test/ui/generic-associated-types/issue-92280.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// check-pass

#![feature(generic_associated_types)]
#![allow(non_camel_case_types)]

trait HasAssoc {
type Assoc;
}

trait Iterate<S: HasAssoc> {
type Iter<'a>
where
Self: 'a;
}

struct KeySegment_Broken<T> {
key: T,
}
impl<S: HasAssoc> Iterate<S> for KeySegment_Broken<S::Assoc> {
type Iter<'a>
where
Self: 'a,
= ();
}

fn main() {}

0 comments on commit 9835b90

Please sign in to comment.