Skip to content

Patterns sometimes ignores lifetimes. #144312

@theemathas

Description

@theemathas

I tried this code:

#[derive(PartialEq)]
struct Foo<'a>(&'a ());

#[allow(dead_code)]
struct Dummy<'a>(&'a ());
impl<'a> Dummy<'a> {
    const X: Foo<'a> = Foo(&());
}

fn identity<T>(x: T) -> T { x }

pub fn weird<'a>(_: &'a ()) {
    let Dummy::<'static>::X = { Dummy::<'a>::X };
    let Dummy::<'a>::X = { Dummy::<'static>::X };
    let Dummy::<'static>::X = Dummy::<'a>::X;
    let Dummy::<'a>::X = Dummy::<'static>::X;
    let Dummy::<'static>::X = { Foo(&()) as Foo<'a> };
    let Dummy::<'a>::X = { Foo(&()) as Foo<'static> };
    let Dummy::<'static>::X = identity(Foo(&()) as Foo<'a>);
    let Dummy::<'a>::X = identity(Foo(&()) as Foo<'static>);
    let Dummy::<'static>::X = Foo(&()) as Foo<'a>;
    // For some reason, the line below doesn't compile.
    let Dummy::<'a>::X = Foo(&()) as Foo<'static>;
}

I expected all of the let statements to cause compile errors, (or half of them, due to subtyping). Instead, all of the statements compile fine, except for the last one, which produced this compile error:

error: lifetime may not live long enough
  --> src/lib.rs:23:38
   |
12 | pub fn weird<'a>(_: &'a ()) {
   |              -- lifetime `'a` defined here
...
23 |     let Dummy::<'a>::X = Foo(&()) as Foo<'static>;
   |                                      ^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`

I discovered this issue after some experimentation after @purplesyringa sent me this odd comment in the compiler:

// This *could* accept a type that isn't actually `PartialEq`, because region bounds get
// ignored. However that should be pretty much impossible since consts that do not depend on
// generics can only mention the `'static` lifetime, and how would one have a type that's
// `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem
// we'll need to leave some sort of trace of this requirement in the MIR so that borrowck
// can ensure that the type really implements `PartialEq`.

Meta

Reproducible on the playground with version 1.90.0-nightly (2025-07-21 9748d87dc70a9a6725c5)

@rustbot labels +A-patterns +A-borrow-checker +A-lifetimes

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-borrow-checkerArea: The borrow checkerA-lifetimesArea: Lifetimes / regionsA-patternsRelating to patterns and pattern matchingC-bugCategory: This is a bug.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-highHigh priorityT-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

    Development

    No branches or pull requests

    Issue actions