On Jun 2, 2016, at 9:08 AM, John McCall via swift-evolution 
<[email protected]> wrote:
> 
> The official way to build a literal of a specific type is to write the 
> literal in an explicitly-typed context, like so:
>     let x: UInt16 = 7
> or
>     let x = 7 as UInt16
> 
> Nonetheless, programmers often try the following:
>     UInt16(7)
> 
> Unfortunately, this does not attempt to construct the value using the 
> appropriate literal protocol; it instead performs overload resolution using 
> the standard rules, i.e. considering only single-argument unlabelled 
> initializers of a type which conforms to IntegerLiteralConvertible.  Often 
> this leads to static ambiguities or, worse, causes the literal to be built 
> using a default type (such as Int); this may have semantically very different 
> results which are only caught at runtime.
> 
> In my opinion, using this initializer-call syntax to build an 
> explicitly-typed literal is an obvious and natural choice with several 
> advantages over the "as" syntax.

I completely agree that this is a problem that we need to solve.  In addition 
to the trap of using [U]Int64 values on 32-bit targets, it is embarrassing that 
we reject (on all targets):

        let x = UInt64(0x8000_0000_0000_0000)

and require people to use the less obvious syntax:

        let x = 0x1000_0000_0000_0000 as UInt64

> Therefore, I propose that we adopt the following typing rule:

I’m sorry of this has already been covered down-thread (just getting caught up 
now, and haven’t read it all), but this seems like a LOT of magic in the type 
checker to solve this problem.

Can’t we just require that literal convertibles implement an initializer that 
the type checker will already consider to be more specific than any of the 
other overloads?  This would eliminate the need for magic like this in the type 
checker.  Right now, we have this:

public protocol IntegerLiteralConvertible {
  associatedtype IntegerLiteralType : _BuiltinIntegerLiteralConvertible
  init(integerLiteral value: IntegerLiteralType)
}

Change it to be an unlabeled requirement like this probably isn’t enough to 
make it privileged in the case of ambiguity:

public protocol IntegerLiteralConvertible {
  associatedtype IntegerLiteralType : _BuiltinIntegerLiteralConvertible
  init(_ value: IntegerLiteralType)
}

but perhaps we could have:

public protocol IntegerLiteralConvertible {
  associatedtype IntegerLiteralType : _BuiltinIntegerLiteralConvertible
  init(integerLiteral value: IntegerLiteralType)
  init<T : IntegerLiteralConvertible>(_ value: T)
}

and get the type checker to consider the later one to be a“more specific” match 
than the other overloads, when confronted with a literal?

-Chris

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to