Skip to content

Braced variant ctor gets rejected if enum has lifetime params & you pass gen args to enum explicitly #108224

@ijackson

Description

@ijackson

I tried this code:

#![allow(dead_code)]
#![allow(unused_variables)]
enum Enum<'l, F> {
    Tuple(&'l F),
    Struct { f: &'l F },
}
fn main(){
    let v = 42u32;
    let t = Enum::<u32>::Struct { f: &v };
}

I expected to see this happen: it compiles.

Instead, this happened (on the playground, with stable and with nightly):

error[E0109]: lifetime arguments are not allowed on variant `Struct`
 --> src/main.rs:9:26
  |
9 |     let t = Enum::<u32>::Struct { f: &v };
  |                          ^^^^^^
  |                          |
  |                          lifetime argument not allowed
  |                          not allowed on variant `Struct`
  |
  = note: enum variants can't have type parameters

error[E0107]: this enum takes 1 lifetime argument but 0 lifetime arguments were supplied
 --> src/main.rs:9:13
  |
9 |     let t = Enum::<u32>::Struct { f: &v };
  |             ^^^^ expected 1 lifetime argument
  |
note: enum defined here, with 1 lifetime parameter: `'l`
 --> src/main.rs:3:6
  |
3 | enum Enum<'l, F> {
  |      ^^^^ --
help: add missing lifetime argument
  |
9 |     let t = Enum::<'l, u32>::Struct { f: &v };
  |                    +++

It's not 100% clear to me that this syntax, with the generics applied to the enum type rather than the variant, is intended to be accepted. I think it probably ought to be, though. On this point I found #69363/#69356. The Reference doesn't seem to discuss it.

Also, the error messages are nonsensical, and the suggestion doesn't compile.

Variations:

    let t = Enum::<'l, u32>::Tuple { 0: &v }; // use of undeclared lifetime name `'l`  [obviously]
    let t = Enum::<u32>::Tuple { 0: &v }; //  lifetime arguments are not allowed on variant `Tuple`
    let t = Enum::<'_, u32>::Tuple { 0: &v }; // //  lifetime arguments are not allowed on variant `Tuple`
    let t = Enum::<u32>::Tuple(&v);; // compiles, but of course you can't use this for a named-fields variant
    let t = Enum::Struct::<u32> { f: &v }; // compiles
    let t = Enum::Tuple::<u32> { 0: &v }; // compiles

Metadata

Metadata

Assignees

Labels

A-enumArea: Enums (discriminated unions, or more generally ADTs (algebraic data types))A-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.S-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueT-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
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions