Skip to content

"non-defining opaque type use" with equal bound regions due to closure #112841

New issue

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

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

Already on GitHub? # to your account

Closed
lcnr opened this issue Jun 20, 2023 · 4 comments · Fixed by #116891
Closed

"non-defining opaque type use" with equal bound regions due to closure #112841

lcnr opened this issue Jun 20, 2023 · 4 comments · Fixed by #116891
Labels
C-bug Category: This is a bug. F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]`

Comments

@lcnr
Copy link
Contributor

lcnr commented Jun 20, 2023

#![feature(type_alias_impl_trait)]
trait Trait<'a, 'b> {}
impl Trait<'_, '_> for () {}
type Tait<'a, 'b> = impl Trait<'a, 'b>;
fn fail<'a: 'b, 'b: 'a>() -> Tait<'a, 'b> {
    (|| {})()
}

results in the following but should ideally compile.

error: non-defining opaque type use in defining scope
 --> src/main.rs:6:5
  |
6 |     (|| {})()
  |     ^^^^^^^^^
  |
note: lifetime used multiple times
 --> src/main.rs:4:11
  |
4 | type Tait<'a, 'b> = impl Trait<'a, 'b>;
  |           ^^  ^^
@lcnr lcnr added C-bug Category: This is a bug. F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]` labels Jun 20, 2023
@lcnr lcnr changed the title non-defining opaque type use with equal bound regions non-defining opaque type use with equal bound regions due to closure Jun 20, 2023
@lcnr
Copy link
Contributor Author

lcnr commented Jun 20, 2023

I think the issue is that the closure erases regions in its signature and does not have any user type, so its generic params for the opaque aren't really sensible.

I feel like maybe closures should return their opaque constraints via https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.BorrowCheckResult.html#structfield.closure_requirements instead of dealing with them itself?

@lcnr lcnr moved this to Can do after stabilization in type alias impl trait stabilization Jun 20, 2023
@lcnr lcnr changed the title non-defining opaque type use with equal bound regions due to closure "non-defining opaque type use" with equal bound regions due to closure Jun 20, 2023
@compiler-errors
Copy link
Member

why does this fail even if a closure is just defined in-scope? 🤔

#![feature(type_alias_impl_trait)]

trait Trait<'a, 'b> {}

impl Trait<'_, '_> for () {}

type Tait<'a, 'b> = impl Trait<'a, 'b>;

fn fail<'a: 'b, 'b: 'a>() -> Tait<'a, 'b> {
    let x = || {};

    ()
}

fn main() {}

@compiler-errors
Copy link
Member

compiler-errors commented Jun 21, 2023

idk, maybe pinging @aliemjay who knows more about borrowck + closures 🤣

@aliemjay
Copy link
Member

I disagree that the OP's code should pass. Even more, I think it is a bug that we accept this:

#![feature(type_alias_impl_trait)]
trait Trait<'a, 'b> {}
impl Trait<'_, '_> for () {}
type Tait<'a, 'b> = impl Trait<'a, 'b>;
fn fail<'a: 'b, 'b: 'a>() -> Tait<'a, 'b> {
    ()
}

because it is in no way different than writing fn fail<'a>() -> Tait<'a, 'a> { ... }, which we currently reject and for a good reason.

The reason we accept these illegal defining uses of TAIT is due to a bug in

let to_universal_region = |vid, subst_regions: &mut Vec<_>| {

which evaluates lifetime equality based on the constraint graph alone, ignoring the the environment bounds. This is why this trivial change triggers the error:

fn fail<'a: 'b, 'b: 'a>() -> Tait<'a, 'b> {
+   let _ = None::<&'a &'b &'a ()>; // Now 'a and 'b are equal in the constraint graph
    ()
+   //~^ ERROR non-defining opaque type use in defining scope
}

and this explains why using closures anywhere in the body triggers the error, because it somehow adds the environmet bounds (on early-bound lifetimes exclusively) to the constraint graph.

bors added a commit to rust-lang-ci/rust that referenced this issue Oct 19, 2023
…2, r=<try>

rework opaque type region inference

fixes rust-lang#113971 Pass -> Error

fixes rust-lang#111906 ICE -> Pass
fixes rust-lang#110623 ==
fixes rust-lang#109059 ==

fixes rust-lang#112841 Pass -> Error

fixes rust-lang#110726 ICE->Error

r? `@ghost`
bors added a commit to rust-lang-ci/rust that referenced this issue Oct 21, 2023
…2, r=<try>

rework opaque type region inference

fixes rust-lang#113971 Pass -> Error

fixes rust-lang#111906 ICE -> Pass
fixes rust-lang#110623 ==
fixes rust-lang#109059 ==

fixes rust-lang#112841 Pass -> Error

fixes rust-lang#110726 ICE->Error

r? `@ghost`
bors added a commit to rust-lang-ci/rust that referenced this issue Oct 23, 2023
…2, r=<try>

rework opaque type region inference

fixes rust-lang#113971 Pass -> Error

fixes rust-lang#111906 ICE -> Pass
fixes rust-lang#110623 ==
fixes rust-lang#109059 ==

fixes rust-lang#112841 Pass -> Error

fixes rust-lang#110726 ICE->Error

fixes rust-lang#111935 Pass -> Error
fixes rust-lang#113916 ==

r? `@ghost`
@bors bors closed this as completed in 551abd6 Mar 28, 2024
@github-project-automation github-project-automation bot moved this from Can do after stabilization to Done in type alias impl trait stabilization Mar 28, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
C-bug Category: This is a bug. F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]`
Development

Successfully merging a pull request may close this issue.

3 participants