Doug Richardson
Doug Richardson

Reputation: 10821

Why can't I use 'Type' as the name of an enum embedded in a struct?

The following fails to compile:

struct S1 {
    enum Type {
        case One, Two, Three
    }

    let e1 : Type
    let i : Int
}

func f1(e : S1.Type) {
    S1(e1: e, i: 1)
}

with error:

error: cannot invoke initializer for type 'S1' with an argument list of type '(e1: S1.Type, i: Int)'
    S1(e1: e, i: 1)
    ^
note: expected an argument list of type '(e1: S1.Type, i: Int)'
    S1(e1: e, i: 1)

However, if I replace Type for the name of the enum with something else, say Types, it compiles fine.

Why can't I use Type as the name of an enum embedded in a struct?

Upvotes: 1

Views: 202

Answers (2)

Doug Richardson
Doug Richardson

Reputation: 10821

Steve was right, it's a keyword. Here's the relevant part of the spec:

Keywords reserved in particular contexts: associativity, convenience, dynamic, didSet, final, get, infix, inout, lazy, left, mutating, none, nonmutating, optional, override, postfix, precedence, prefix, Protocol, required, right, set, Type, unowned, weak, and willSet. Outside the context in which they appear in the grammar, they can be used as identifiers.

Apparently, a top level enum Type is fine, but one embedded in a struct is not. The language reference section on Types > Metatype Types explains why:

Metatype Type

A metatype type refers to the type of any type, including class types, structure types, enumeration types, and protocol types.

The metatype of a class, structure, or enumeration type is the name of that type followed by .Type. The metatype of a protocol type—not the concrete type that conforms to the protocol at runtime—is the name of that protocol followed by .Protocol. For example, the metatype of the class type SomeClass is SomeClass.Type and the metatype of the protocol SomeProtocol is SomeProtocol.Protocol.

Upvotes: 1

Frithjof Schaefer
Frithjof Schaefer

Reputation: 1205

You can do it like this (as mentioned before, Type is also used within the core of Swift. That's why the compiler is kind of confused). Type used as a name works if the enum is not nested:

enum Type {
        case One, Two, Three
}

struct S1 {

    let e1 : Type
    let i : Int
}

func f1(e : Type) {
   var x = S1(e1: Type.One, i: 1)
}

f1(Type.One)

if you use another name for the enum, you can still nest it:

 struct S2 {


    enum Kind {
        case One, Two, Three
    }

    let e1 : Kind
    let i : Int
}

func f2(e : S2.Kind) {
   var x = S2(e1: S2.Kind.One, i: 1)
}

f2(S2.Kind.One)

Upvotes: 2

Related Questions