From b276b65f46465cffe207b4b732e6ab4642d47558 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 14 May 2022 11:25:53 +0200 Subject: [PATCH 1/2] Forbid nested opaque types to reference HRTB from opaque types. --- compiler/rustc_resolve/src/late/lifetimes.rs | 14 +++++ src/test/ui/impl-trait/issues/issue-54895.rs | 3 +- .../ui/impl-trait/issues/issue-54895.stderr | 14 +++++ .../impl-trait/issues/issue-67830.nll.stderr | 20 ------- src/test/ui/impl-trait/issues/issue-67830.rs | 2 +- .../ui/impl-trait/issues/issue-67830.stderr | 13 +++-- .../issues/issue-88236-2.nll.stderr | 55 ------------------- .../ui/impl-trait/issues/issue-88236-2.rs | 9 ++- .../ui/impl-trait/issues/issue-88236-2.stderr | 40 ++++++++++---- src/test/ui/impl-trait/issues/issue-88236.rs | 3 +- .../ui/impl-trait/issues/issue-88236.stderr | 14 +++++ 11 files changed, 89 insertions(+), 98 deletions(-) create mode 100644 src/test/ui/impl-trait/issues/issue-54895.stderr delete mode 100644 src/test/ui/impl-trait/issues/issue-67830.nll.stderr delete mode 100644 src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-88236.stderr diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index ae4455531ab5b..700d7c3bfb6fe 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1025,6 +1025,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, diff --git a/src/test/ui/impl-trait/issues/issue-54895.rs b/src/test/ui/impl-trait/issues/issue-54895.rs index a70166e03a7b1..8d7a1d56f8320 100644 --- a/src/test/ui/impl-trait/issues/issue-54895.rs +++ b/src/test/ui/impl-trait/issues/issue-54895.rs @@ -1,5 +1,3 @@ -// check-pass - trait Trait<'a> { type Out; fn call(&'a self) -> Self::Out; @@ -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(()) } diff --git a/src/test/ui/impl-trait/issues/issue-54895.stderr b/src/test/ui/impl-trait/issues/issue-54895.stderr new file mode 100644 index 0000000000000..7d22f027a6daf --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-54895.stderr @@ -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 + diff --git a/src/test/ui/impl-trait/issues/issue-67830.nll.stderr b/src/test/ui/impl-trait/issues/issue-67830.nll.stderr deleted file mode 100644 index 17fbe046e3ac9..0000000000000 --- a/src/test/ui/impl-trait/issues/issue-67830.nll.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-67830.rs:23:5 - | -LL | Wrap(|a| Some(a).into_iter()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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` - -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-67830.rs:23:5 - | -LL | Wrap(|a| Some(a).into_iter()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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` - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/impl-trait/issues/issue-67830.rs b/src/test/ui/impl-trait/issues/issue-67830.rs index a308d975b4395..92f7e005dbf0c 100644 --- a/src/test/ui/impl-trait/issues/issue-67830.rs +++ b/src/test/ui/impl-trait/issues/issue-67830.rs @@ -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()) } diff --git a/src/test/ui/impl-trait/issues/issue-67830.stderr b/src/test/ui/impl-trait/issues/issue-67830.stderr index 4c0490c721bc4..d3ea8cb0377c7 100644 --- a/src/test/ui/impl-trait/issues/issue-67830.stderr +++ b/src/test/ui/impl-trait/issues/issue-67830.stderr @@ -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 diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr b/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr deleted file mode 100644 index 66cffa9e36c0d..0000000000000 --- a/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr +++ /dev/null @@ -1,55 +0,0 @@ -error: implementation of `Hrtb` is not general enough - --> $DIR/issue-88236-2.rs:17:5 - | -LL | &() - | ^^^ 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` - -error: implementation of `Hrtb` is not general enough - --> $DIR/issue-88236-2.rs:17:5 - | -LL | &() - | ^^^ 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` - -error: lifetime may not live long enough - --> $DIR/issue-88236-2.rs:20:5 - | -LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { - | -- lifetime `'b` defined here -LL | x - | ^ returning this value requires that `'b` must outlive `'static` - | -help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'b` lifetime bound - | -LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> + 'b { - | ++++ -help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'b` lifetime bound - | -LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a + 'b> { - | ++++ - -error: implementation of `Hrtb` is not general enough - --> $DIR/issue-88236-2.rs:20:5 - | -LL | x - | ^ 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` - -error: implementation of `Hrtb` is not general enough - --> $DIR/issue-88236-2.rs:20:5 - | -LL | x - | ^ 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` - -error: aborting due to 5 previous errors - diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.rs b/src/test/ui/impl-trait/issues/issue-88236-2.rs index af26a1f54c46d..fde8a6704cc45 100644 --- a/src/test/ui/impl-trait/issues/issue-88236-2.rs +++ b/src/test/ui/impl-trait/issues/issue-88236-2.rs @@ -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() {} diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.stderr b/src/test/ui/impl-trait/issues/issue-88236-2.stderr index 9574b880f7d11..8605d07abe943 100644 --- a/src/test/ui/impl-trait/issues/issue-88236-2.stderr +++ b/src/test/ui/impl-trait/issues/issue-88236-2.stderr @@ -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 diff --git a/src/test/ui/impl-trait/issues/issue-88236.rs b/src/test/ui/impl-trait/issues/issue-88236.rs index 2ea35270a7e3b..36d12417354a2 100644 --- a/src/test/ui/impl-trait/issues/issue-88236.rs +++ b/src/test/ui/impl-trait/issues/issue-88236.rs @@ -1,5 +1,3 @@ -// check-pass - // this used to cause stack overflows trait Hrtb<'a> { @@ -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() {} diff --git a/src/test/ui/impl-trait/issues/issue-88236.stderr b/src/test/ui/impl-trait/issues/issue-88236.stderr new file mode 100644 index 0000000000000..7a4cc57b0881a --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-88236.stderr @@ -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 + From 872f09c9756aa1be54b027a556a84132e98552a0 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 14 May 2022 14:07:46 +0200 Subject: [PATCH 2/2] Add a test with both passing and erroneous cases. --- src/test/ui/impl-trait/nested-rpit-hrtb.rs | 64 +++++++++++++++ .../ui/impl-trait/nested-rpit-hrtb.stderr | 82 +++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 src/test/ui/impl-trait/nested-rpit-hrtb.rs create mode 100644 src/test/ui/impl-trait/nested-rpit-hrtb.stderr diff --git a/src/test/ui/impl-trait/nested-rpit-hrtb.rs b/src/test/ui/impl-trait/nested-rpit-hrtb.rs new file mode 100644 index 0000000000000..abf6a7e956c69 --- /dev/null +++ b/src/test/ui/impl-trait/nested-rpit-hrtb.rs @@ -0,0 +1,64 @@ +// 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] + +// 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] + +fn main() {} diff --git a/src/test/ui/impl-trait/nested-rpit-hrtb.stderr b/src/test/ui/impl-trait/nested-rpit-hrtb.stderr new file mode 100644 index 0000000000000..3dbe6ebadfbfc --- /dev/null +++ b/src/test/ui/impl-trait/nested-rpit-hrtb.stderr @@ -0,0 +1,82 @@ +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> {} + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'b` lifetime + | +LL | fn two_htrb_outlives() -> impl for<'b, 'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {} + | +++ +help: consider introducing lifetime `'b` here + | +LL | fn two_htrb_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {} + | ++++ + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/nested-rpit-hrtb.rs:61:82 + | +LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {} + | ^^ undeclared lifetime + | +help: consider making the bound lifetime-generic with a new `'b` lifetime + | +LL | fn two_htrb_outlives_uses() -> impl for<'b, 'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {} + | +++ +help: consider introducing lifetime `'b` here + | +LL | fn two_htrb_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {} + | ++++ + +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: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0261`.