[swift-evolution] [Planning][Request] "constexpr" for Swift 5
gor.f.gyolchanyan at icloud.com
Mon Jul 31 03:24:20 CDT 2017
> On Jul 31, 2017, at 11:09 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> On Mon, Jul 31, 2017 at 02:51 Gor Gyolchanyan <gor.f.gyolchanyan at icloud.com <mailto:gor.f.gyolchanyan at icloud.com>> wrote:
>> On Jul 31, 2017, at 10:40 AM, Xiaodi Wu <xiaodi.wu at gmail.com <mailto:xiaodi.wu at gmail.com>> wrote:
>> On Mon, Jul 31, 2017 at 02:15 Gor Gyolchanyan via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> > On Jul 31, 2017, at 7:10 AM, John McCall via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> >> On Jul 30, 2017, at 11:43 PM, Daryle Walker <darylew at mac.com <mailto:darylew at mac.com>> wrote:
>> >> The parameters for a fixed-size array type determine the type's size/stride, so how could the bounds not be needed during compile-time? The compiler can't layout objects otherwise.
>> > Swift is not C; it is perfectly capable of laying out objects at run time. It already has to do that for generic types and types with resilient members. That does, of course, have performance consequences, and those performance consequences might be unacceptable to you; but the fact that we can handle it means that we don't ultimately require a semantic concept of a constant expression, except inasmuch as we want to allow users to explicitly request guarantees about static layout.
>> Doesn't this defeat the purpose of generic value parameters? We might as well use a regular parameter if there's no compile-time evaluation involved. In that case, fixed-sized arrays will be useless, because they'll be normal arrays with resizing disabled.
>> OTOH, if the compiler can prove that a local array is never resized, why *shouldn't* it get all the benefits of a fixed-sized array without having to use a special syntax? Put another way, why shouldn't fixed-size be one of those optional attributes for arrays, like ownership will be for variables, that users can opt into for more performance but is otherwise automatically worked out by the compiler?
> Because the compiler shouldn't know what an array is (that is, what a Swift array is, not the C array that LLVM has a primitive type for).
> Wait, why not? It already does, afaict, just as it knows about integers, strings, etc. In fact, as I understand it, one dividing line between the standard library and Foundation is whether or not a type needs compiler knowledge of it.
> And if the compiler doesn't know what an array is and what resizing means, then the array has to define that optimization hint itself, which will either involve new syntax for attaching metadata for declarative special-case solutions. Besides, it won't be getting the full benefits of fixed-sized arrays. The biggest benefit of fixed-size arrays is allocation cost (which is exactly zero for static fixed-sized arrays and a single clock cycle for unescaped local fixed-sized arrays), which is not going to improve if an array is simply forbidden from resizing.
> I'm not speaking about under the hood; I'm speaking about spelling:
> let foo: [Int] = [1, 2, 3] // this clearly needs no resizing
> var bar: [Int] = [1, 2, 3] // not clear if this needs resizing
> var baz: fixed [Int] = [1, 2, 3] // allow the user to tell the compiler
If a simple compiler hint is what you mean, then I'd go for something less array-centric and more along the lines of "arbitrary compiler hint", much like how C preprocessor has pragmas.
I'd go for this syntax instead:
var baz: @hint(fixed) Int = [1, 2, 3]
Which has the added benefit of prepping the general syntax for any other part of the language where the compiler could use a little hand-holding from the human.
I didn't want it to be simply @fixed, because the singular attributes so far follow the pattern of being mandatory, rather than optional hints, so that we don't confuse people by having at attribute that may or may not actually do anything and reserve that to a single very specific attribute.
But this is all outside of the topic.
Within the topic there were two major points made regarding compile-time evaluation:
* It's not warranted to consider this unless actual use cases are brought forth.
* Many of those use cases can be solved at run-time (e.g. generic value parameters).
My counter-point to those are:
* It's always possible to do things at run-time. I think it isn't worth spending time implementing a feature and complicating the language if it won't provide enough performance and convenience gains.
* Many of the features discussed here (including generic value parameters and fixed-size arrays) would be much simpler, more convenient, more performant and more powerful if the underlying deal-breaking lack of compile-time facilities was remedied.
> Under the hood, Swift optimizes as best it can.
> For really fast storage, Clang has __builtin_alloca, which could be wrapped in an __attribute__((__always_inline__)) function and exposed to Swift.
> For semantically non-resizable arrays, we can simply implement a FixedSizeArray with no changes to the language.
> Considering these options, I don't think solving the use case of fixed-size arrays is worth complicating the language.
> This is why I'm pushing for elaborate compile-time execution feature. It won't solve a specific use-case, it will solve a very wide domain of use cases.
>> As far as I know, the pinnacle of uses for fixed-size arrays is having a compile-time pre-allocated space of the necessary size (either literally at compile-time if that's a static variable, or added to the pre-computed offset of the stack pointer in case of a local variable).
>> > Value equality would still affect the type-checker, but I think we could pretty easily just say that all bound expressions are assumed to potentially resolve unequally unless they are literals or references to the same 'let' constant.
>> Shouldn't the type-checker use the Equatable protocol conformance to test for equality? Moreover, as far as I know, Equatable is not recognized by the compiler in any way, so it's just a regular protocol. What would make it special? Some types would implement operator == to compare themselves to other types, that's beyond the scope of Equatable. What about those? And how are custom operator implementations going to serve this purpose at compile-time? Or will it just ignore the semantics of the type and reduce it to a sequence of bits? Or maybe only a few hand-picked types will be supported?
>> The seemingly simple generic value parameter concept gets vastly complicated and/or poorly designed without an elaborate compile-time execution system... Unless I'm missing an obvious way out.
>> > The only hard constraint is that types need to be consistent, but that just means that we need to have a model in which bound expressions are evaluated exactly once at runtime (and of course typically folded at compile time).
>> What exactly would it take to be able to execute select piece of code at compile-time? Taking the AST, converting it to LLVM IR and feeding it to the MCJIT engine seems to be easy enough. But I'm pretty sure it's more tricky than that. Is there a special assumption or two made about the code that prevents this from happening?
>> > John.
>> >> Or do you mean that the bounds are integer literals? (That's what I have in the design document now.)
>> >> Sent from my iPhone
>> >> On Jul 30, 2017, at 8:51 PM, John McCall <rjmccall at apple.com <mailto:rjmccall at apple.com>> wrote:
>> >>>> On Jul 29, 2017, at 7:01 PM, Daryle Walker via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> >>>> The “constexpr” facility from C++ allows users to define constants and functions that are determined and usable at compile-time, for compile-time constructs but still usable at run-time. The facility is a key step for value-based generic parameters (and fixed-size arrays if you don’t want to be stuck with integer literals for bounds). Can figuring out Swift’s story here be part of Swift 5?
>> >>> Note that there's no particular reason that value-based generic parameters, including fixed-size arrays, actually need to be constant expressions in Swift.
>> >>> John.
>> > _______________________________________________
>> > swift-evolution mailing list
>> > swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> > https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the swift-evolution