Skip to content

Object lifetime defaults of GATs are not respected #115379

@fmease

Description

@fmease
Member

To infer the default trait object lifetime of a trait object type, we first look at the bounds on the relevant type parameter of the containing generic type. According to my interpretation of the Reference, RFC 599 and RFC 1156, any kind of generic type can be an elegible container type, not just ADTs. However, if the containing generic type is a GAT, the compiler doesn't properly take into consideration the bounds on its type parameters. The RFCs obviously predate GATs.

For example, I expected the following code to compile since dyn Inner in g's signature should be equivalent to dyn Inner + 'r given that 'r is the object lifetime default due to the bound T: 'a at least according to my reading of the Reference and according to #[rustc_object_lifetime_default] but it fails because the default is actually inferred to be 'static leading me to assume that rustc completely ignores the GAT param bounds.

trait Outer {
    type Ty<'a, T: ?Sized + 'a>;
}
impl Outer for () {
    type Ty<'a, T: ?Sized + 'a> = &'a T;
}
trait Inner {}

fn f<'r>(x: <() as Outer>::Ty<'r, dyn Inner + 'r>) { g(x) } //~ ERROR lifetime may not live long enough
fn g<'r>(_: <() as Outer>::Ty<'r, dyn Inner>) {}
error: lifetime may not live long enough
  --> src/lib.rs:10:56
   |
10 | fn f<'r>(x: <() as Outer>::Ty<'r, dyn Inner + 'r>) { g(x) }
   |      -- lifetime `'r` defined here                     ^ cast requires that `'r` must outlive `'static`

As attested by #[rustc_object_lifetime_default], we seem to (be able to) compute the object lifetime defaults for GATs (but we don't use them during resolution):

error: 'a
 --> src/lib.rs:5:17
  |
5 |     type Ty<'a, T: ?Sized + 'a>;
  |                 ^

Is this an oversight in the current implementation or does this work as intended?
Note that it would be a breaking change to fix this, I'm almost certain.

@rustbot label C-bug T-compiler A-lifetimes A-trait-objects A-associated-items F-generic_associated_types

Activity

added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
A-associated-itemsArea: Associated items (types, constants & functions)
A-lifetimesArea: Lifetimes / regions
A-dyn-traitArea: trait objects, vtable layout
C-bugCategory: This is a bug.
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Aug 30, 2023
changed the title [-]Object lifetime defaults of GAT parameters are not respected[/-] [+]Object lifetime defaults of GATs are not respected[/+] on Aug 31, 2023
removed
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Sep 4, 2023
added
T-langRelevant to the language team
I-lang-nominatedNominated for discussion during a lang team meeting.
on Sep 11, 2023
fmease

fmease commented on Sep 11, 2023

@fmease
MemberAuthor

Nominating this for lang team discussion since I really don't know if this works as intended or not.

Feel free to remove the nomination if you don't think it's important enough for a team discussion.
I can nominate it for a types team discussion instead if you think that's more appropriate :)

fmease

fmease commented on Sep 11, 2023

@fmease
MemberAuthor

Possibly relevant: #91302

nikomatsakis

nikomatsakis commented on Sep 19, 2023

@nikomatsakis
Contributor

Hi @fmease !

We discussed this in our @rust-lang/lang triage meeting today. We felt the behavior is a bug and inconsistent. I'm nominating this issue for @rust-lang/types to discuss further and possibly fix.

@rustbot labels +I-types-nominated -I-lang-nominated

In particular, we felt that this example should behave the same as your motivating example:

trait Ref<'a, T: 'a + ?Sized> {
    type Ty;
}
trait Inner {}

fn f<'r, T>(x: <T as Ref<'r, dyn Inner + 'r>>::Ty) { g(x) }
fn g<'r, T>(x: <T as Ref<'r, dyn Inner>>::Ty) { g(x) } 

However, the above example gives an error, as does dyn Trait, but the GAT case seems to infer a bound of 'static. This seems like a bug. If any bound is inferred, in my opinion, it ought to be 'r.

We felt that it was ok to give a hard error since that is forwards compatible and consistent with how we currently behave for other parameters appearing in associated type references, but of course that is technically a breaking change, although the impact seems likely to be small.

@rust-lang/types, this kind of detail also feels like it's in your purview, how do you think we ought to proceed?

16 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-GATsArea: Generic associated types (GATs)A-associated-itemsArea: Associated items (types, constants & functions)A-dyn-traitArea: trait objects, vtable layoutA-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Participants

    @nikomatsakis@fmease@lcnr@rustbot@Noratrieb

    Issue actions

      Object lifetime defaults of GATs are not respected · Issue #115379 · rust-lang/rust