Overriding default literal types and scoping

Some users are likely to know that Swift allows you to override the default inferred type of literals by declaring specific typealiases in their code:

typealias StringLiteralType = CustomStringType

let a = "hello"

print(type(of: a)) // CustomStringType

However, this overriding is only valid at the top level. Trying to do something like below, where the user wants to scope the inference of the default literal types, isn't supported:

class MyClass {
  // Inside of class I want string literals to be typed as CustomStringType
  private typealias StringLiteralType = CustomStringType
  
  func testing() -> String {
    let t = "hello" // I want a CustomStringType
    
    return String(fromCustom: t) // t was inferred to be `String`, not our custom type
  }
}

I can see some reasons behind only allowing overriding of the inferred literal types at the top level, mostly
around reducing complexity in the type checker. But are there are concrete reasons that this behavior shouldn't be allowed? I'm curious to know if people would be open to expanding this "feature" to allow more fine grain control.

And at a more fundamental level, was this "feature" ever really meant to exist in a user facing way, or was it more of a outcome of how type inference was implemented?

2 Likes

Also as an aside. The typealiases needed for overriding Array and Dictionary literals are IMO pretty poorly named when you look at the ones needed for all the rest:

struct Max4Array<Element> : ExpressibleByArrayLiteral {
  init(arrayLiteral elements: Element...) { assert(elements.count <= 4) }
}

struct Max4Dictionary<Key, Value> : ExpressibleByDictionaryLiteral {
  init(dictionaryLiteral elements: (Key, Value)...) { assert(elements.count <= 4) }
}

typealias Array = Max4Array
typealias Dictionary = Max4Dictionary

let arr = [1]
let dict = [1: 1]

print(type(of: arr)) // Max4Array<Int>
print(type(of: dict)) // Max4Dictionary<Int, Int>