<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 <<a href="mailto:clattner@apple.com" class="">clattner@apple.com</a>> 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 <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> 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=""> let x: UInt16 = 7</font></div><div class="">or</div><div class=""><font face="Andale Mono" class=""> 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=""> 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. 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. 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 = 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 = 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? This would eliminate the need for magic like this in the type checker. Right now, we have this:</div><div class=""><br class=""></div><div class="">public protocol IntegerLiteralConvertible {<br class=""> associatedtype IntegerLiteralType : _BuiltinIntegerLiteralConvertible<br class=""> 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=""> associatedtype IntegerLiteralType : _BuiltinIntegerLiteralConvertible<br class=""> 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=""> associatedtype IntegerLiteralType : _BuiltinIntegerLiteralConvertible<br class=""> init(integerLiteral value: IntegerLiteralType)<br class=""> init<T : IntegerLiteralConvertible>(_ 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. 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. 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<T> type. 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. 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>