Skip to content

Outlives-bounds in type aliases may affect object lifetime defaults which lint type_alias_bounds fails to acknowledge #100270

Closed as not planned

Description

@conradludgate

I tried this code:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c358b7f20cd1b96bf3919a4339288971

#![allow(dead_code)]

pub type Borrow<'a, T: 'a> = &'a T;

pub trait Foo {
    fn foo(&self);
}

impl<T: AsRef<str> + ?Sized> Foo for T {
    fn foo(&self) {}
}

pub struct Bar<'a> {
    foo: Borrow<'a, dyn Foo>,
}

fn bar(name: &str) {
    let _ = Bar { foo: &name };
}

I expected to see this happen:

error[E0759]: `name` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
  --> src/lib.rs:18:24
   |
17 | fn bar(name: &str) {
   |              ---- this data with an anonymous lifetime `'_`...
18 |     let _ = Bar { foo: &name };
   |                        ^^^^^ ...is used and required to live as long as `'static` here

For more information about this error, try `rustc --explain E0759`.

Borrow<'a, dyn Foo> should default to dyn Foo + 'static and the T: 'a should be ignored.

Instead, this happened:

warning: bounds on generic parameters are not enforced in type aliases
 --> src/lib.rs:3:24
  |
3 | pub type Borrow<'a, T: 'a> = &'a T;
  |                        ^^
  |
  = note: `#[warn(type_alias_bounds)]` on by default
help: the bound will not be checked when the type alias is used, and should be removed
  |
3 - pub type Borrow<'a, T: 'a> = &'a T;
3 + pub type Borrow<'a, T> = &'a T;
  | 

If you follow the guidance from the warning, it no longer compiles due to dyn Foo being static-ish, as mentioned

Activity

  1. danielhenrymantilla commented on Aug 8, 2022

    @danielhenrymantilla
    Contributor

    Reduced:

      pub fn check<'a>(r: &'a &'a ()) {
    -     pub type Borrow<'a, T : 'a> = &'a T;
    +     pub type Borrow<'a, T> = &'a T;
          type DynSend<'a> = Borrow<'a, dyn Send>;
          let _: DynSend<'a> = r;
      }

    removes the lint but leads to a compile failure.

  2. QuineDot commented on Oct 27, 2022

    @QuineDot

    I did some more exploration here (and playground). More generally, using an alias will apply the dyn lifetime defaults (RFC 0599, RFC 1156) based on the alias bounds (or lack of bounds), be they stronger or looser than the aliased type.

    So they definitely have semantic impact. I don't think they're checked (enforced) per se, though.

    pub type Lt<'a, 'b: 'a> = (&'a (), &'b ());
    
    // Compiles
    fn check<'a, 'b>(r: &'a &'b ()) {
        let _: Lt<'a, 'b> = (*r, *r);
        let _: Lt<'b, 'a> = (*r, *r);
    }
  3. fmease commented on Jan 25, 2024

    @fmease
    Member

    @QuineDot is correct, the outlives-bounds T: 'a on the (eager) type alias Borrow influences the default object lifetime of dyn Foo.

    I don't think they're checked (enforced) per se, though.

    Bounds on lazy type aliases (feature lazy_type_alias) on the other hand are enforced and they are checked for well-formedness. Lazy type aliases will become the default in Rust 202X (the plan is Rust 2024 but the implementation stills needs to be completed by me). CC #112792. I don't know how to proceed with this issue? Should I close it or keep it open?

  4. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    A-dyn-traitArea: trait objects, vtable layout
    and removed on Jan 25, 2024
  5. QuineDot commented on May 19, 2024

    @QuineDot

    If nothing else this should be documented somewhere. Based on some light testing, it seems lazy_type_alias preserves this behavior, correct? That also seems reasonable to me.

  6. self-assigned this
    on Jun 5, 2024
  7. fmease commented on Jun 5, 2024

    @fmease
    Member

    If nothing else this should be documented somewhere. Based on some light testing, it seems lazy_type_alias preserves this behavior, correct? That also seems reasonable to me.

    Yes, lazy_type_alias does preserve it (because it's consistent).


    Regarding eager type aliases & L-type_alias_bounds Lint: type_alias_bounds , while I could just suppress this lint for any kind of type-outlives-bounds (T: 'a), I don't think that would be a good idea because this concerns an edge case and apart from object lifetime defaults, type-outlives-bounds are not enforced. I've assigned myself to this issue as well all(?) the other L-type_alias_bounds Lint: type_alias_bounds issues as part of my work on lazy_type_alias.

    I think the best way forward is to adjust the description and wordings of this lint. Point out limitations and specify exactly what we mean by "enforced".

  8. changed the title [-]Lifetime bound in type alias is checked[/-] [+]Outlives-bounds in type aliases may affect object lifetime defaults which lint `type_alias_bounds` fails to acknowledge[/+] on Jun 10, 2024
  9. added a commit that references this issue on Jul 26, 2024
    ceae371
  10. added a commit that references this issue on Jul 26, 2024
    eac4883
  11. fmease commented on Jul 27, 2024

    @fmease
    Member

    WONTFIX as per #126575. I've lowered the applicability of the suggestion diagnostic from machine-applicable to maybe-incorrect in cases where any of the bounds affect the object lifetime default.

  12. fmease commented on Jul 27, 2024

    @fmease
    Member

    Note that this issue will be fixed properly once lazy_type_alias becomes the default in a future edition. CC #112792. Since the description of the lint now acknowledges limitations like this one, I don't see any reason to keep this issue open.

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

Metadata

Metadata

Assignees

Labels

A-dyn-traitArea: trait objects, vtable layoutC-bugCategory: This is a bug.L-type_alias_boundsLint: type_alias_boundsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions