[swift-evolution] Proposal: 'T(literal)' should construct T using the appropriate literal protocol if possible

Austin Zheng austinzheng at gmail.com
Thu Jun 2 14:14:33 CDT 2016


On Thu, Jun 2, 2016 at 12:11 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:

> +1 to the proposal. I can also see the argument for disallowing multiple
> ways of doing the same thing, though disallowing the use of `as` in this
> way might be introducing another special case.
>
>
The "as", "as?" and "as!" operators in Swift are already surprisingly
overloaded.  Joe Groff's proposal lists 9 (!!!) different things "as?" does
here:
https://github.com/apple/swift-evolution/blob/master/proposals/0083-remove-bridging-from-dynamic-casts.md
.

"as" is also overloaded in this sense. It performs bridging casts (soon to
go away?), upcasts that can never fail (e.g. subclass to superclass), and
defining the concrete type of a literal expression. It wouldn't be a big
loss for "as" to lose the last meaning.



> If the proposal is accepted, I'd also advocate for the suggestion in the
> initial proposal to apply the rule regardless of the number of parentheses,
> so that `A((B))` behaves the same way as `A(B)`.
>

+1. Yes please.


>
> On Thu, Jun 2, 2016 at 1:55 PM, Austin Zheng via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> I think we should actually go further.
>>
>> If this proposal is accepted, disallow "as" as a way of specifying the
>> type to construct from a literal.
>>
>> If this proposal isn't accepted, disallow using literal values as the
>> argument to one-unlabeled-argument constructors.
>>
>> In either case we should disabuse users of the notion that A(literal) is
>> an initializer that behaves exactly the same as other initializers.
>>
>> Austin
>>
>> On Thu, Jun 2, 2016 at 11:46 AM, Austin Zheng <austinzheng at gmail.com>
>> wrote:
>>
>>> +1.
>>>
>>> The primary advantage is that it aligns the language semantics with how
>>> most programmers expect this common C-language-family idiom to behave and
>>> removes a potential source of silently wrong code.
>>>
>>> The primary disadvantage is that it introduces special-case behavior to
>>> certain types of initializers (although, to be fair, this special-case
>>> behavior is easily recognizable: unlabeled one-argument initializer with a
>>> literal as the argument).
>>>
>>> I think the advantage outweighs the disadvantage.
>>>
>>> This problem should be addressed one way or another. I prefer this
>>> solution, but if it is rejected for whatever reason we should at least
>>> explicitly outlaw A(literal) syntax in favor of "literal as A".
>>>
>>> Austin
>>>
>>> On Thu, Jun 2, 2016 at 9:08 AM, John McCall via swift-evolution <
>>> 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.
>>>>
>>>> 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
>>>>
>>>>
>>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160602/80d3bd1a/attachment.html>


More information about the swift-evolution mailing list