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

higher ranked lifetimes not recognized by type alias impl trait #96146

Open
oli-obk opened this issue Apr 17, 2022 · 5 comments
Open

higher ranked lifetimes not recognized by type alias impl trait #96146

oli-obk opened this issue Apr 17, 2022 · 5 comments
Assignees
Labels
C-bug Category: This is a bug. F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]`

Comments

@oli-obk
Copy link
Contributor

oli-obk commented Apr 17, 2022

The following snippet fails

#![feature(type_alias_impl_trait)]
trait Trait<'a> { type Out: 'a;}
impl<'a> Trait<'a> for i32 { type Out = String;}
type A = impl for<'a> Trait<'a, Out = impl Sized + 'a>;
fn foo() -> A {
    0_i32
}

The error is

error: non-defining opaque type use in defining scope
 --> src/lib.rs:6:5
  |
6 |     0_i32
  |     ^^^^^
  |
note: used non-generic lifetime `'a` for generic parameter
 --> src/lib.rs:4:52
  |
4 | type A = impl for<'a> Trait<'a, Out = impl Sized + 'a>;
  |                                                    ^^

Originally posted by @oli-obk in #96094 (comment)

@oli-obk oli-obk added C-bug Category: This is a bug. F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]` labels Apr 17, 2022
@oli-obk
Copy link
Contributor Author

oli-obk commented Apr 17, 2022

Amusingly you get a different error if the associated type actually uses the lifetime:

#![feature(type_alias_impl_trait)]
trait Trait<'a> { type Out: 'a;}
impl<'a> Trait<'a> for i32 { type Out = &'a String;}
type A = impl for<'a> Trait<'a, Out = impl Sized + 'a>;
fn foo() -> A {
    0_i32
}

Fails with

error: implementation of `Trait` is not general enough
 --> src/lib.rs:6:5
  |
6 |     0_i32
  |     ^^^^^ implementation of `Trait` is not general enough
  |
  = note: `i32` must implement `Trait<'0>`, for any lifetime `'0`...
  = note: ...but it actually implements `Trait<'1>`, for some specific lifetime `'1`

@aliemjay
Copy link
Member

Amusingly you get a different error if the associated type actually uses the lifetime:

I think this the right behavior. I started a thread on internals forum to discuss this.

@jyn514
Copy link
Member

jyn514 commented Apr 19, 2022

cc #96194

@aliemjay
Copy link
Member

aliemjay commented Apr 20, 2022

To rule out the ambiguity of nested impls as shown in #96194, I tried splitting the opaque type into two, inner and outer, and that showed an interesting pattern.


If the inner type has a lifetime paramter <'a>, but it's not used by the associated type:

#![feature(type_alias_impl_trait)]
trait Trait<'a> { type Out; }
impl<'a> Trait<'a> for () { type Out = (); }

type Inner<'a> = impl Sized;
fn outer_impl() -> impl for<'a> Trait<'a, Out = Inner<'a>> {}

This yields the same error of this issue: error: non-defining opaque type use in defining scope

And when the lifetime is used by the associated type:

impl<'a> Trait<'a> for () { type Out = &'a (); }

the compiler produces the same ICE in #95647 .

This behavior is consistent regardless of of whether the inner impl have a lifetime bound impl Sized + 'a or whether the outer impl appears in type alias or in return position.


Surprisingly, if Fn traits are used for the outer impl, both cases work fine:

#![feature(type_alias_impl_trait)]
type Inner<'a> = impl Sized;
fn outer_impl() -> impl for<'a> Fn(&'a ()) -> Inner<'a> { |x| x }

If the Inner type has NO lifetime paramter <'a>, but the associated type actually captures one:

#![feature(type_alias_impl_trait)]
trait Trait<'a> { type Out; }
impl<'a> Trait<'a> for () { type Out = &'a (); }

type Inner = impl Sized;
fn outer_impl() -> impl for<'a> Trait<'a, Out = Inner> {}

This is rejected, but but behavior depends on the outer impl:

  • if outer impl is in return position: implementation not general enough error.
  • if outer impl is in type alias: same ICE as yet another ICE with HRTB and RPIT #95647 .
  • if outer impl is an Fn trait: a nice error 'impl Trait' captures lifetime that does not appear in bounds

@rustbot claim

@lcnr
Copy link
Contributor

lcnr commented Feb 15, 2024

this has been changed to explicitly forbid nested opaques from referencing higher ranked lifetimes:

#![feature(type_alias_impl_trait)]
trait Trait<'a> { type Out: 'a;}
impl<'a> Trait<'a> for i32 { type Out = String;}
type A = impl for<'a> Trait<'a, Out = impl Sized + 'a>;
fn foo() -> A {
    0_i32
}

results in

error: cannot capture late-bound lifetime in type alias impl trait
 --> src/lib.rs:4:52
  |
4 | type A = impl for<'a> Trait<'a, Out = impl Sized + 'a>;
  |                   -- lifetime defined here         ^^

we get a different error when using the Fn-trait sugar

#![feature(type_alias_impl_trait)]
type Inner<'a> = impl Sized;
fn outer_impl() -> impl for<'a> Fn(&'a ()) -> Inner<'a> { |x| x }
error[E0792]: expected generic lifetime parameter, found `'a`
 --> src/lib.rs:3:59
  |
2 | type Inner<'a> = impl Sized;
  |            -- this generic parameter must be used with a generic lifetime parameter
3 | fn outer_impl() -> impl for<'a> Fn(&'a ()) -> Inner<'a> { |x| x }
  |                                                           ^^^^^

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Feb 22, 2024
…r=lcnr

test that we do not support higher-ranked regions in opaque type inference

We already do all the right checks in `check_opaque_type_parameter_valid`, and we have done so since at least 2 years.

I collected the tests from rust-lang#116935 and rust-lang#100503 and added some more

cc rust-lang#96146

r? `@lcnr`
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Feb 22, 2024
…r=lcnr

test that we do not support higher-ranked regions in opaque type inference

We already do all the right checks in `check_opaque_type_parameter_valid`, and we have done so since at least 2 years.

I collected the tests from rust-lang#116935 and rust-lang#100503 and added some more

cc rust-lang#96146

r? `@lcnr`
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Feb 22, 2024
Rollup merge of rust-lang#121386 - oli-obk:no_higher_ranked_opaques, r=lcnr

test that we do not support higher-ranked regions in opaque type inference

We already do all the right checks in `check_opaque_type_parameter_valid`, and we have done so since at least 2 years.

I collected the tests from rust-lang#116935 and rust-lang#100503 and added some more

cc rust-lang#96146

r? `@lcnr`
@traviscross traviscross changed the title higher kinded lifetimes not recognized by type alias impl trait higher ranked lifetimes not recognized by type alias impl trait Mar 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]`
Projects
Status: Can do after stabilization
Development

Successfully merging a pull request may close this issue.

4 participants