Skip to content

Forbid nested opaque types to reference HRTB from opaque types. #97040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions compiler/rustc_resolve/src/late/lifetimes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
self.uninsert_lifetime_on_error(lifetime, def.unwrap());
}
if let hir::Node::Item(hir::Item {
kind: hir::ItemKind::OpaqueTy { .. }, ..
}) = self.tcx.hir().get(parent_id)
{
if !self.trait_definition_only {
let mut err = self.tcx.sess.struct_span_err(
lifetime.span,
"higher kinded lifetime bounds on nested opaque types are not supported yet",
);
err.span_note(self.tcx.def_span(def_id), "lifetime declared here");
err.emit();
}
self.uninsert_lifetime_on_error(lifetime, def.unwrap());
}
}

// We want to start our early-bound indices at the end of the parent scope,
Expand Down
3 changes: 1 addition & 2 deletions src/test/ui/impl-trait/issues/issue-54895.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// check-pass

trait Trait<'a> {
type Out;
fn call(&'a self) -> Self::Out;
Expand All @@ -15,6 +13,7 @@ impl<'a> Trait<'a> for X {
}

fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
X(())
}

Expand Down
14 changes: 14 additions & 0 deletions src/test/ui/impl-trait/issues/issue-54895.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/issue-54895.rs:15:53
|
LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
| ^^
|
note: lifetime declared here
--> $DIR/issue-54895.rs:15:20
|
LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
| ^^

error: aborting due to previous error

20 changes: 0 additions & 20 deletions src/test/ui/impl-trait/issues/issue-67830.nll.stderr

This file was deleted.

2 changes: 1 addition & 1 deletion src/test/ui/impl-trait/issues/issue-67830.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ where

struct A;
fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
//~^ ERROR implementation of `FnOnce` is not general enough
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
Wrap(|a| Some(a).into_iter())
}

Expand Down
13 changes: 8 additions & 5 deletions src/test/ui/impl-trait/issues/issue-67830.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
error: implementation of `FnOnce` is not general enough
--> $DIR/issue-67830.rs:21:14
error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/issue-67830.rs:21:62
|
LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
| ^^
|
= note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
note: lifetime declared here
--> $DIR/issue-67830.rs:21:23
|
LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
| ^^

error: aborting due to previous error

51 changes: 0 additions & 51 deletions src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr

This file was deleted.

9 changes: 7 additions & 2 deletions src/test/ui/impl-trait/issues/issue-88236-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@ impl<'a> Hrtb<'a> for &'a () {
}

fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet

fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
&() //~^ ERROR implementation of `Hrtb` is not general enough
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
&()
}

fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
x //~^ ERROR implementation of `Hrtb` is not general enough
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
x
}

fn main() {}
40 changes: 29 additions & 11 deletions src/test/ui/impl-trait/issues/issue-88236-2.stderr
Original file line number Diff line number Diff line change
@@ -1,20 +1,38 @@
error: implementation of `Hrtb` is not general enough
--> $DIR/issue-88236-2.rs:16:38
error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/issue-88236-2.rs:15:61
|
LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
| ^^
|
note: lifetime declared here
--> $DIR/issue-88236-2.rs:15:28
|
LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
| ^^

error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/issue-88236-2.rs:18:80
|
LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Hrtb` is not general enough
| ^^
|
= note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
= note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
note: lifetime declared here
--> $DIR/issue-88236-2.rs:18:47
|
LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
| ^^

error: implementation of `Hrtb` is not general enough
--> $DIR/issue-88236-2.rs:19:36
error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/issue-88236-2.rs:23:78
|
LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Hrtb` is not general enough
| ^^
|
= note: `Hrtb<'1>` would have to be implemented for the type `&()`, for any lifetime `'1`...
= note: ...but `Hrtb<'_>` is actually implemented for the type `&()`
note: lifetime declared here
--> $DIR/issue-88236-2.rs:23:45
|
LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
| ^^

error: aborting due to 2 previous errors
error: aborting due to 3 previous errors

3 changes: 1 addition & 2 deletions src/test/ui/impl-trait/issues/issue-88236.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// check-pass

// this used to cause stack overflows

trait Hrtb<'a> {
Expand All @@ -15,5 +13,6 @@ impl<'a> Hrtb<'a> for &'a () {
}

fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet

fn main() {}
14 changes: 14 additions & 0 deletions src/test/ui/impl-trait/issues/issue-88236.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/issue-88236.rs:15:61
|
LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
| ^^
|
note: lifetime declared here
--> $DIR/issue-88236.rs:15:28
|
LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
| ^^

error: aborting due to previous error

66 changes: 66 additions & 0 deletions src/test/ui/impl-trait/nested-rpit-hrtb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Test the interaction between rested RPIT and HRTB.

trait Foo<'a> {
type Assoc;
}

impl Foo<'_> for () {
type Assoc = ();
}

// Alternative version of `Foo` whose impl uses `'a`.
trait Bar<'a> {
type Assoc;
}

impl<'a> Bar<'a> for () {
type Assoc = &'a ();
}

trait Qux<'a> {}

impl Qux<'_> for () {}

// This is not supported.
fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet

// This is not supported.
fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet

fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet

fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet

// This should pass.
fn one_hrtb_mention_fn_trait_param<'b>() -> impl for<'a> Foo<'a, Assoc = impl Qux<'b>> {}

// This should pass.
fn one_hrtb_mention_fn_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'b> {}

// This should pass.
fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {}

// This should pass.
fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {}

// This should pass.
fn two_htrb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Qux<'b>> {}

// `'b` is not in scope for the outlives bound.
fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
//~^ ERROR use of undeclared lifetime name `'b` [E0261]
//~| ERROR lifetime name `'b` shadows a lifetime name that is already in scope [E0496]

// This should pass.
fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {}

// `'b` is not in scope for the outlives bound.
fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
//~^ ERROR use of undeclared lifetime name `'b` [E0261]
//~| ERROR lifetime name `'b` shadows a lifetime name that is already in scope [E0496]

fn main() {}
80 changes: 80 additions & 0 deletions src/test/ui/impl-trait/nested-rpit-hrtb.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/nested-rpit-hrtb.rs:25:69
|
LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
| ^^
|
note: lifetime declared here
--> $DIR/nested-rpit-hrtb.rs:25:36
|
LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
| ^^

error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/nested-rpit-hrtb.rs:29:68
|
LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
| ^^
|
note: lifetime declared here
--> $DIR/nested-rpit-hrtb.rs:29:39
|
LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
| ^^

error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/nested-rpit-hrtb.rs:32:74
|
LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
| ^^
|
note: lifetime declared here
--> $DIR/nested-rpit-hrtb.rs:32:41
|
LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
| ^^

error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/nested-rpit-hrtb.rs:35:73
|
LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
| ^^
|
note: lifetime declared here
--> $DIR/nested-rpit-hrtb.rs:35:44
|
LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
| ^^

error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/nested-rpit-hrtb.rs:54:77
|
LL | fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
| - help: consider introducing lifetime `'b` here: `<'b>` ^^ undeclared lifetime

error[E0496]: lifetime name `'b` shadows a lifetime name that is already in scope
--> $DIR/nested-rpit-hrtb.rs:54:65
|
LL | fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
| ^^ -- first declared here
| |
| lifetime `'b` already in scope

error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/nested-rpit-hrtb.rs:62:82
|
LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
| - help: consider introducing lifetime `'b` here: `<'b>` ^^ undeclared lifetime

error[E0496]: lifetime name `'b` shadows a lifetime name that is already in scope
--> $DIR/nested-rpit-hrtb.rs:62:70
|
LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
| ^^ -- first declared here
| |
| lifetime `'b` already in scope

error: aborting due to 8 previous errors

Some errors have detailed explanations: E0261, E0496.
For more information about an error, try `rustc --explain E0261`.