on Wed Jun 08 2016, John McCall <rjmccall-AT-apple.com> wrote: >> On Jun 7, 2016, at 4:25 PM, Dave Abrahams <[email protected]> wrote: >> on Tue Jun 07 2016, John McCall <rjmccall-AT-apple.com> wrote: >> >>>> On Jun 5, 2016, at 5:18 PM, Dave Abrahams via swift-evolution >>>> <[email protected]> wrote: >>>> on Thu Jun 02 2016, John McCall <[email protected] >>>> <mailto:[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. >>>> >>>> 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. >> >> I know. I'm saying, fixing this for literals without giving value types >> copy initializers leaves us with only a partial realization of a larger >> mental model to which I believe people are programming. > > That's fair. Would you like me to incorporate that into my proposal, > then? I see the relation, but it's a pretty significant jump in > scope.
I'm not sure it should be in the same proposal; I just want it to be a part of the discussion. We should be able to make incremental progress, but let's make sure we understand how our changes fit into the big picture. -- Dave _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
