Permalink
Fetching contributors…
Cannot retrieve contributors at this time
97 lines (73 sloc) 3.8 KB

Requiring Leading Dot Prefixes for Enum Instance Member Implementations

Introduction

Enumeration cases are essentially static not instance type members. Unlike static members in structures and classes, enumeration cases can be mentioned in initializers and instance methods without referencing a fully qualified type. This makes little sense. In no other case can an instance implementation directly access a static member. This proposal introduces a rule that requires leading dots or fully qualified references (EnumType.caseMember) to provide a more consistent developer experience to clearly disambiguate static cases from instance members.

Discussion took place on the Swift Evolution mailing list in the [Discussion] Enum Leading Dot Prefixes thread. This proposal uses lowerCamelCase enumeration cases in compliance with current API Guideline Working Group guidance.

Review

Motivation

Swift infers the enclosing type for a case on a developer's behalf when the use is unambiguously of a single enumeration type. Inference enables you to craft switch statements like this:

switch Coin() {
case .heads: print("Heads")
case .tails: print("Tails")
}

A leading dot has become a conventional shorthand for "enumeration case" across the language. When used internally in enum implementations, a leading dot is not required, nor is a type name to access the static case member. The following code is legal in Swift.

enum Coin {
    case heads, tails
    func printMe() {
        switch self {
        case heads: print("Heads")  // no leading dot
        case .tails: print("Tails") // leading dot
        }
        
        if self == heads {          // no leading dot
            print("This is a head")
        }
        
        if self == .tails {         // leading dot
            print("This is a tail")
        }
    }

    init() {
        let cointoss = arc4random_uniform(2) == 0
        self = cointoss ? .heads : tails // mix and match leading dots
    }
}

This quirk produces a language inconsistency that can confuse developers and contravenes the guiding Principle of Least Astonishment. We propose to mandate a leading dot. This brings case mentions into lock-step with conventions used to reference them outside of enumeration type implementations.

Detail Design

Under this rule, the compiler will require a leading dot for all case members. The change will not affect other static members, which require fully qualified references from instance methods and infer self from static methods.

enum Coin {
    case heads, tails
    static func doSomething() { print("Something") }
    static func staticFunc() { doSomething() } // does not require leading dot
    static func staticFunc2() { let foo = tails } // does not require leading dot, following static convention
    func instanceFunc() { self.dynamicType.doSomething() } // requires full qualification
    func otherFunc() { if self == .heads ... } // requires leading dot, also initializers

    /// ...
} 

Alternatives Considered

Other than leaving the status quo, the language could force instance members to refer to cases using a fully qualified type, as with other static members.