Sent from my iPad

> On Jun 2, 2016, at 3:41 PM, John McCall <[email protected]> wrote:
> 
>>> On Jun 2, 2016, at 12:10 PM, Matthew Johnson <[email protected]> wrote:
>>> On Jun 2, 2016, at 1:46 PM, Austin Zheng via swift-evolution 
>>> <[email protected]> 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.
>> 
>> Agree.  This change basically means the label isn’t intended to be used by 
>> callers, but is only present to distinguish the initializer used by the 
>> protocol from any other unlabeled initializer accepting the same type.  But 
>> conceptually it is treated as the *most specific* unlabelled initializer 
>> possible, thus winning the overload resolution.
>> 
>> How important is it that we have the ability to distinguish between literals 
>> and non-literals with the same type?  If that isn’t important, maybe the 
>> literal convertible protocols could be reworked such that the label isn’t 
>> necessary.  That would eliminate the special-case elision of the label.
> 
> There is no way to rework the literal protocols so that this behavior just 
> falls out.  It's easy enough to convince yourself of this if you try to work 
> through an actual example.

Ok, I'll trust you on this point.  +1 on the idea as you proposed it.

> 
> John.
> 
>> 
>>> 
>>> 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 
>>>> <[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.  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
>>>> [email protected]
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected]
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to