[swift-evolution] Proposal: 'T(literal)' should construct T using the appropriate literal protocol if possible
John McCall
rjmccall at apple.com
Tue Jun 7 15:53:40 CDT 2016
> On Jun 5, 2016, at 5:18 PM, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
> on Thu Jun 02 2016, John McCall <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> 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. However, even if you disagree, it's
>> clear that programmers are going to continue to independently try to
>> use it, so it's really unfortunate for it to be subtly wrong.
>>
>> Therefore, I propose that we adopt the following typing rule:
>>
>> Given a function call expression of the form A(B) (that is, an
>> expr-call with a single, unlabelled argument) where B is an
>> expr-literal or expr-collection, if A has type T.Type for some type T
>> and there is a declared conformance of T to an appropriate literal
>> protocol for B, then the expression is always resolves as a literal
>> construction of type T (as if the expression were written "B as A")
>> rather than as a general initializer call.
>>
>> Formally, this would be a special form of the argument conversion
>> constraint, since the type of the expression A may not be immediately
>> known.
>
> I realize this is somewhat tangential, but... IMO this may not be entirely
> about literals.
>
> We have a standard that full-width type conversions are written as a
> label-free initializer
> <https://swift.org/documentation/api-design-guidelines/#type-conversion <https://swift.org/documentation/api-design-guidelines/#type-conversion>>.
> I believe that is partly responsible for setting up the expectation that
> Int(42) works as one would expect. It gets ultra-weird when you can
> convert from type A to type B using B(someA) but you can't write
> B(someB). We should automatically generate a label-free “copy
> initializer” for value types, to complete implementation of the expected
> mental model.
That may also be a good idea, but it won't magically be preferred for literal
construction if the type has any other constructors of literal-convertible type.
John.
>
>> Note that, as specified, it is possible to suppress this typing rule
>> by wrapping the literal in parentheses. This might seem distasteful;
>> it would be easy enough to allow the form of B to include extra
>> parentheses. It's potentially useful to have a way to suppress this
>> rule and get a normal construction, but there are several other ways
>> of getting that effect, such as explicitly typing the literal argument
>> (e.g. writing "A(Int(B))").
>>
>> A conditional conformance counts as a declared conformance even if the
>> generic arguments are known to not satisfy the conditional
>> conformance. This permits the applicability of the rule to be decided
>> without having to first decide the type arguments, which greatly
>> simplifies the type-checking problem (and may be necessary for
>> soundness; I didn't explore this in depth, but it certainly feels like
>> a very nasty sort of dependence). We could potentially weaken this
>> for cases where A is a direct type reference with bound parameters,
>> e.g. Foo<Int>([]) or the same with a typealias, but I think there's
>> some benefit from having a simpler specification, both for the
>> implementation and for the explicability of the model.
>>
>> John.
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>
> --
> -Dave
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160607/a4693cbd/attachment.html>
More information about the swift-evolution
mailing list