Skip to content
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

Forbid lifetime bounds in nested opaque types in binders #96970

Closed

Conversation

oli-obk
Copy link
Contributor

@oli-obk oli-obk commented May 12, 2022

avoids #96194

Not closing the issue until we have this behind a feature gate and with a corresponding tracking issue.

Since this change is supposed to get backported to beta, I don't want to add a gate and more logic in this PR. Instead, it will happen on a follow up PR solely on nightly.

@oli-obk oli-obk added the beta-nominated Nominated for backporting to the compiler in the beta channel. label May 12, 2022
@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label May 12, 2022
@rust-highfive
Copy link
Collaborator

r? @petrochenkov

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 12, 2022
@oli-obk
Copy link
Contributor Author

oli-obk commented May 12, 2022

cc @cjgillot on the HIR lowering changes. I think it's fine to only do this for named lifetimes, as all others are forbidden anyway ('_ and just leaving them out is already triggering other errors).

@oli-obk
Copy link
Contributor Author

oli-obk commented May 12, 2022

@bors try

@bors
Copy link
Contributor

bors commented May 12, 2022

⌛ Trying commit 1b73e54 with merge 3f7b27fe41ccd116a4c0829bd9a14b65bada4578...

@apiraino
Copy link
Contributor

Beta backport accepted as per compiler team on Zulip

(pending a crater run)

@rustbot label +beta-accepted

@rustbot rustbot added the beta-accepted Accepted for backporting to the compiler in the beta channel. label May 12, 2022
@cjgillot cjgillot self-assigned this May 12, 2022
@bors
Copy link
Contributor

bors commented May 12, 2022

☀️ Try build successful - checks-actions
Build commit: 3f7b27fe41ccd116a4c0829bd9a14b65bada4578 (3f7b27fe41ccd116a4c0829bd9a14b65bada4578)

@oli-obk
Copy link
Contributor Author

oli-obk commented May 12, 2022

@craterbot check

@craterbot
Copy link
Collaborator

👌 Experiment pr-96970 created and queued.
🤖 Automatically detected try build 3f7b27fe41ccd116a4c0829bd9a14b65bada4578
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 12, 2022
@craterbot
Copy link
Collaborator

🚧 Experiment pr-96970 is now running

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@cjgillot
Copy link
Contributor

@oli-obk I don't understand your comment about anonymous lifetimes.

I think it's fine to only do this for named lifetimes, as all others are forbidden anyway ('_ and just leaving them out is already triggering other errors).

To be on the safe side, I'd rather have named and anonymous lifetimes treated the same way. The "other errors" are feature gates for impl-trait in fn and impl Fn(), aren't they?

@petrochenkov petrochenkov removed their assignment May 12, 2022
@Mark-Simulacrum Mark-Simulacrum mentioned this pull request May 13, 2022
@compiler-errors
Copy link
Member

r=me if you're still in search for a reviewer, I am satisfied with the most recent changes after the second commit

@oli-obk
Copy link
Contributor Author

oli-obk commented May 13, 2022

@bors r=compiler-errors p=1

@bors
Copy link
Contributor

bors commented May 13, 2022

📌 Commit 193a16b has been approved by compiler-errors

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels May 13, 2022
@jackh726 jackh726 mentioned this pull request May 13, 2022
@Mark-Simulacrum
Copy link
Member

This doesn't cherry pick cleanly onto beta, so I'm holding off on a backport until someone can prepare that -- the diff doesn't look trivial to me, though I haven't looked super closely. If necessary I'll probably devote a few hours on the weekend or Monday to push it through.

@bors
Copy link
Contributor

bors commented May 14, 2022

⌛ Testing commit 193a16b with merge 71e302eebe4f7c63d76f39c5b03453e12b6c3db0...

@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-nopt failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)

---- [ui (nll)] src/test/ui/impl-trait/issues/issue-67830.rs stdout ----
diff of stderr:

+ error: higher kinded lifetime bounds on nested opaque types are not supported yet
+    |
+    |
+ LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
+    |
+    = help: See https://github.com/rust-lang/rust/issues/96194 for further details
+ 
+ 
1 error: implementation of `FnOnce` is not general enough
-   --> $DIR/issue-67830.rs:23:5
3    |
3    |
4 LL |     Wrap(|a| Some(a).into_iter())
5    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough

8    = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
9 
10 error: implementation of `FnOnce` is not general enough
-   --> $DIR/issue-67830.rs:23:5
12    |
12    |
13 LL |     Wrap(|a| Some(a).into_iter())
14    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough

16    = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
17    = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
- error: aborting due to 2 previous errors
+ error: aborting due to 3 previous errors
20 
21 
21 


The actual stderr differed from the expected stderr.
Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/impl-trait/issues/issue-67830.nll/issue-67830.nll.stderr
To only update this specific test, also pass `--test-args impl-trait/issues/issue-67830.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/impl-trait/issues/issue-67830.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/impl-trait/issues/issue-67830.nll" "-Zborrowck=mir" "-A" "unused" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/impl-trait/issues/issue-67830.nll/auxiliary"
stdout: none
--- stderr -------------------------------
error: higher kinded lifetime bounds on nested opaque types are not supported yet
   |
   |
LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
   |
   = help: See https://github.com/rust-lang/rust/issues/96194 for further details


error: implementation of `FnOnce` is not general enough
   |
   |
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
   |
   |
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 3 previous errors
------------------------------------------



---- [ui (nll)] src/test/ui/impl-trait/issues/issue-88236-2.rs stdout ----
diff of stderr:

+ error: higher kinded lifetime bounds on nested opaque types are not supported yet
+    |
+    |
+ LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+    |
+    = help: See https://github.com/rust-lang/rust/issues/96194 for further details
+ 
+ 
+ error: higher kinded lifetime bounds on nested opaque types are not supported yet
+    |
+    |
+ LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+    |
+    = help: See https://github.com/rust-lang/rust/issues/96194 for further details
+ 
+ 
+ error: higher kinded lifetime bounds on nested opaque types are not supported yet
+    |
+    |
+ LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+    |
+    = help: See https://github.com/rust-lang/rust/issues/96194 for further details
+ 
+ 
+ error: higher kinded lifetime bounds on nested opaque types are not supported yet
+    |
+    |
+ LL | fn make_bad_impl_2<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Zend<'a>> {
+    |
+    = help: See https://github.com/rust-lang/rust/issues/96194 for further details
+ 
+ 
1 error: implementation of `Hrtb` is not general enough
-   --> $DIR/issue-88236-2.rs:17:5
3    |
4 LL |     &()
4 LL |     &()
5    |     ^^^ implementation of `Hrtb` is not general enough

8    = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
9 
10 error: implementation of `Hrtb` is not general enough
-   --> $DIR/issue-88236-2.rs:17:5
12    |
13 LL |     &()
13 LL |     &()
14    |     ^^^ implementation of `Hrtb` is not general enough

17    = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
19 error: lifetime may not live long enough
-   --> $DIR/issue-88236-2.rs:20:5
+   --> $DIR/issue-88236-2.rs:22:5
21    |
21    |
22 LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
23    |                  -- lifetime `'b` defined here
34    |                                                                                 ++++
35 
35 
36 error: implementation of `Hrtb` is not general enough
-   --> $DIR/issue-88236-2.rs:20:5
38    |
39 LL |     x
39 LL |     x
40    |     ^ implementation of `Hrtb` is not general enough

43    = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
44 
45 error: implementation of `Hrtb` is not general enough
-   --> $DIR/issue-88236-2.rs:20:5
47    |
48 LL |     x
48 LL |     x
49    |     ^ implementation of `Hrtb` is not general enough

51    = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
52    = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
- error: aborting due to 5 previous errors
+ error: lifetime may not live long enough
+   --> $DIR/issue-88236-2.rs:31:5
+    |
+    |
+ LL | fn make_bad_impl_2<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Zend<'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_2<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Zend<'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_2<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Zend<'a> + 'b> {
+ 
+ 
+ error: implementation of `Hrtb` is not general enough
+    |
+ LL |     x
+ 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
+    |
+ LL |     x
+ 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 12 previous errors
55 
56 



The actual stderr differed from the expected stderr.
Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/impl-trait/issues/issue-88236-2.nll/issue-88236-2.nll.stderr
To only update this specific test, also pass `--test-args impl-trait/issues/issue-88236-2.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/impl-trait/issues/issue-88236-2.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/impl-trait/issues/issue-88236-2.nll" "-Zborrowck=mir" "-A" "unused" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/impl-trait/issues/issue-88236-2.nll/auxiliary"
stdout: none
--- stderr -------------------------------
error: higher kinded lifetime bounds on nested opaque types are not supported yet
   |
   |
LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
   |
   = help: See https://github.com/rust-lang/rust/issues/96194 for further details


error: higher kinded lifetime bounds on nested opaque types are not supported yet
   |
   |
LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
   |
   = help: See https://github.com/rust-lang/rust/issues/96194 for further details


error: higher kinded lifetime bounds on nested opaque types are not supported yet
   |
   |
LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
   |
   = help: See https://github.com/rust-lang/rust/issues/96194 for further details


error: higher kinded lifetime bounds on nested opaque types are not supported yet
   |
   |
LL | fn make_bad_impl_2<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Zend<'a>> {
   |
   = help: See https://github.com/rust-lang/rust/issues/96194 for further details


error: implementation of `Hrtb` is not general enough
   |
   |
LL |     &() //~^ ERROR implementation of `Hrtb` is not general enough
   |     ^^^ 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
   |
   |
LL |     &() //~^ ERROR implementation of `Hrtb` is not general enough
   |     ^^^ 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
  --> /checkout/src/test/ui/impl-trait/issues/issue-88236-2.rs:22:5
   |
   |
LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
   |                  -- lifetime `'b` defined here
LL |     x //~^ ERROR implementation of `Hrtb` is not general enough
   |     ^ 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
   |
   |
LL |     x //~^ ERROR implementation of `Hrtb` is not general enough
   |     ^ 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
   |
   |
LL |     x //~^ ERROR implementation of `Hrtb` is not general enough
   |     ^ 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
  --> /checkout/src/test/ui/impl-trait/issues/issue-88236-2.rs:31:5
   |
   |
LL | fn make_bad_impl_2<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Zend<'a>> {
   |                    -- lifetime `'b` defined here
LL |     x //~^ ERROR implementation of `Hrtb` is not general enough
   |     ^ 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_2<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Zend<'a>> + 'b {
   |                                                                                   ++++
help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'b` lifetime bound
Some tests failed in compiletest suite=ui compare_mode=Nll mode=ui host=x86_64-unknown-linux-gnu target=x86_64-unknown-linux-gnu
   |
LL | fn make_bad_impl_2<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Zend<'a> + 'b> {


error: implementation of `Hrtb` is not general enough
   |
   |
LL |     x //~^ ERROR implementation of `Hrtb` is not general enough
   |     ^ 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
   |
   |
LL |     x //~^ ERROR implementation of `Hrtb` is not general enough
   |     ^ 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 12 previous errors
------------------------------------------


@bors
Copy link
Contributor

bors commented May 14, 2022

💔 Test failed - checks-actions

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 14, 2022
@compiler-errors
Copy link
Member

compiler-errors commented May 14, 2022

NLL tests need to be blessed, but @pnkfelix has pointed out an interesting side effect of this PR, being:

impl for<'a> Foo<'a, Assoc = impl for<'b> Qux<'b>> fails under this PR, which is possibly not correct.

Current nightly accepts the following code, for example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f25115b4ae04c819e56781bf952b766f

@bors r- until that issue is settled

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 14, 2022
bors added a commit to rust-lang-ci/rust that referenced this pull request May 14, 2022
Forbid nested opaque types to reference HRTB from opaque types.

Avoids rust-lang#96194
Alternative to rust-lang#96970

r? `@oli-obk`
@oli-obk oli-obk closed this May 14, 2022
@oli-obk oli-obk deleted the lifetime_bounds_on_nested_rpit branch May 14, 2022 16:25
@oli-obk
Copy link
Contributor Author

oli-obk commented May 14, 2022

Closing as @cjgillot wrote an actual fix instead of overzealous patch that this PR was

@Mark-Simulacrum Mark-Simulacrum removed beta-nominated Nominated for backporting to the compiler in the beta channel. beta-accepted Accepted for backporting to the compiler in the beta channel. labels May 15, 2022
@Mark-Simulacrum
Copy link
Member

De-accepting from beta backport.

bors added a commit to rust-lang-ci/rust that referenced this pull request May 15, 2022
…Simulacrum

Bump to 1.63

r? `@Mark-Simulacrum`

Posting this now, but will only approve later today / early tomorrow to give a little more time for not-yet-approved PRs to land on master (e.g., rust-lang#96970).
@craterbot
Copy link
Collaborator

🎉 Experiment pr-96970 is completed!
📊 9 regressed and 6 fixed (233200 total)
📰 Open the full report.

⚠️ If you notice any spurious failure please add them to the blacklist!
ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.