Skip to content

Add support for enum variants scoped under their type (enum mod) #10090

Closed
@Kimundi

Description

@Kimundi

Current situation

Right now, enum types and their variants are scoped at the same level, which means this:

mod foo {
    enum Speed {
        Fast,
        Slow
    }
}

leads to these paths:

foo::Speed;
foo::Fast;
foo::Slow;

We will likely not change this, because it often makes working with enums easier, and because many languages with similar enum types work that way.

The problem

However, the restriction to a flat hierarchy currently leads to a lot of variants getting their type name embedded in the variant name to avoid collisions and/or ambiguity. For example, a random enum picked out of libsyntax reads like this:

pub enum Sigil {
    BorrowedSigil,
    OwnedSigil,
    ManagedSigil
}

The possible solution

To improve this situation, it would be convenient to have a enum declaration syntax for scoping the variants under their type instead, like this:

mod foo {
    enum mod Speed {
        Fast,
        Slow
    }
}
foo::Speed;
foo::Speed::Fast;
foo::Speed::Slow;

The above example could then get rewritten to

pub enum mod Sigil {
    Borrowed,
    Owned,
    Managed
}

and get used as Sigil::Borrowed, Sigil::Owned etc, or directly imported in the local scope if there is no collision.

Emulating it

You can currently kinda emulate it with

mod foo {
    pub type Speed = self::Speed::Speed;
    pub mod Speed {
        pub enum Speed {
            Fast,
            Slow
        }
    }
}

but this is very verbose, complicated, and creates more definitions and moving parts than necessary.

Working example

This uses the workaround above to show how using such a scoped enum would look like in practice.

#[feature(globs)];

use foo::Speed;

mod foo {
    pub type Speed = self::Speed::Speed;
    pub mod Speed {
        pub enum Speed {
            Fast,
            Slow
        }
    }
}

fn main() {
    let a: Speed = Speed::Fast;
    let b: Speed = Speed::Slow;

    match a {
        Speed::Fast => {}
        Speed::Slow => {}
    }

    {
        use foo::Speed::*;
        match b {
            Fast => {}
            Slow => {}
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions