<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div><blockquote type="cite" class=""><div class="">On Jun 4, 2016, at 11:54 AM, Chris Lattner &lt;<a href="mailto:clattner@apple.com" class="">clattner@apple.com</a>&gt; wrote:</div><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">On Jun 2, 2016, at 9:08 AM, John McCall via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><div class=""><blockquote type="cite" class=""><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">The official way to build a literal of a specific type is to write the literal in an explicitly-typed context, like so:<div class=""><font face="Andale Mono" class="">&nbsp; &nbsp; let x: UInt16 = 7</font></div><div class="">or</div><div class=""><font face="Andale Mono" class="">&nbsp; &nbsp; let x = 7 as UInt16</font></div><div class=""><br class=""></div><div class="">Nonetheless, programmers often try the following:</div><div class=""><font face="Andale Mono" class="">&nbsp; &nbsp; UInt16(7)</font></div><div class=""><br class=""></div><div class="">Unfortunately, this does <i class="">not</i> 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. &nbsp;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.</div><div class=""><br class=""></div><div class="">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.</div></div></div></blockquote><div class=""><br class=""></div><div class="">I completely agree that this is a problem that we need to solve. &nbsp;In addition to the trap of using [U]Int64 values on 32-bit targets, it is embarrassing that we reject (on all targets):</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let x =&nbsp;UInt64(0x8000_0000_0000_0000)</div><div class=""><br class=""></div><div class="">and require people to use the less obvious syntax:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let x =&nbsp;0x1000_0000_0000_0000 as UInt64</div><div class=""><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Therefore, I propose that we adopt the following typing rule:</div></div></blockquote><div class=""><br class=""></div><div class="">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.</div></div></div></div></blockquote><div><br class=""></div>It was somewhat covered elsewhere in the thread, but this particular idea is new, I think.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">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? &nbsp;This would eliminate the need for magic like this in the type checker. &nbsp;Right now, we have this:</div><div class=""><br class=""></div><div class="">public protocol IntegerLiteralConvertible {<br class="">&nbsp;&nbsp;associatedtype IntegerLiteralType : _BuiltinIntegerLiteralConvertible<br class="">&nbsp;&nbsp;init(integerLiteral value: IntegerLiteralType)<br class="">}<br class=""><br class=""></div><div class="">Change it to be an unlabeled requirement like this probably isn’t enough to make it privileged in the case of ambiguity:</div></div></div></div></blockquote><div><br class=""></div>Right.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">public protocol IntegerLiteralConvertible {<br class="">&nbsp;&nbsp;associatedtype IntegerLiteralType : _BuiltinIntegerLiteralConvertible<br class="">&nbsp;&nbsp;init(_ value: IntegerLiteralType)<br class="">}<br class=""><br class=""></div><div class="">but perhaps we could have:</div><div class=""><br class=""></div><div class="">public protocol IntegerLiteralConvertible {<br class="">&nbsp;&nbsp;associatedtype IntegerLiteralType : _BuiltinIntegerLiteralConvertible<br class="">&nbsp;&nbsp;init(integerLiteral&nbsp;value: IntegerLiteralType)<br class="">&nbsp;&nbsp;init&lt;T : IntegerLiteralConvertible&gt;(_ value: T)<br class="">}<br class=""></div><div class=""><br class=""></div><div class="">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?</div></div></div></div></blockquote><div><br class=""></div>Er. &nbsp;We definitely don't want to say that every integer-literal-convertible type has to be initializable from an arbitrary value of an arbitrary other integer-literal-convertible type. &nbsp;That's not an implementable requirement, nor should it be.</div><div><br class=""></div><div>The idea of making a special unlabelled initializer that's preferred by the type-checker came up earlier in the thread; the more workable proposals included declaring it with @literal or changing the type to some magic Literal&lt;T&gt; type. &nbsp;I just don't think it's a good idea because it's still basically the same type-checker magic on the expression side to recognize that we should favor the case, and then it adds extra complexity on the declaration side; plus the different literal protocols start to interfere with each other if one type implements more than one of them.</div><div><br class=""></div><div>If you're worried about the complexity of adding new constraints, we could start with a more modest rule that only applies the special case when the callee is syntactically a type reference rather than e.g. an arbitrary expression of metatype value. &nbsp;But changing the ambiguity-resolution rules is actually a lot more complex than just adding a new constraint.</div><div><br class=""></div><div>John.</div></body></html>