> On Jul 31, 2017, at 3:15 AM, Gor Gyolchanyan <gor.f.gyolchan...@icloud.com> 
> wrote:
>> On Jul 31, 2017, at 7:10 AM, John McCall via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>> 
>>> On Jul 30, 2017, at 11:43 PM, Daryle Walker <dary...@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.

You're making huge leaps here.  The primary purpose of a fixed-size array 
feature is to allow the array to be allocated "inline" in its context instead 
of "out-of-line" using heap-allocated copy-on-write buffers.  There is no 
reason that that representation would not be supportable just because the 
array's bound is not statically known; the only thing that matters is whether 
the bound is consistent for all instances of the container.

That is, it would not be okay to have a type like:
  struct Widget {
    let length: Int
    var array: [length x Int]
  }
because the value of the bound cannot be computed independently of a specific 
value.

But it is absolutely okay to have a type like:
  struct Widget {
    var array: [(isRunningOnIOS15() ? 20 : 10) x Int]
  }
It just means that the bound would get computed at runtime and, presumably, 
cached.  The fact that this type's size isn't known statically does mean that 
the compiler has to be more pessimistic, but its values would still get 
allocated inline into their containers and even on the stack, using pretty much 
the same techniques as C99 VLAs.

> 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).

The difference between having to use dynamic offsets + alloca() and static 
offsets + a normal stack slot is noticeable but not nearly as extreme as you're 
imagining.  And again, in most common cases we would absolutely be able to fold 
a bound statically and fall into the optimal path you're talking about.  The 
critical guarantee, that the array does not get heap-allocated, is still 
absolutely intact.

>> 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?

The Equatable protocol does guarantee reflexivity.

> Moreover, as far as I know, Equatable is not recognized by the compiler in 
> any way, so it's just a regular protocol.

That's not quite true: we synthesize Equatable instances in several places.

> 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 thing the compiler really *needs* to know is whether two types are 
known to be the same, i.e. whether two values are known to be the same.  An 
elaborate compile-time execution system would not be sufficient here, because 
again, Swift is not C or C++: we need to be able to answer that question even 
in generic code rather than relying on the ability to fold all computations 
statically.  We do not want to add an algebraic solver to the type-checker.  
The obvious alternative is to simply be conservatively correct by treating 
independent complex expressions as always yielding different values.

>> 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?

We already have the ability to fold simple expressions in SIL; we would just 
make sure that could handle anything that we considered really important and 
allow everything else to be handled dynamically.

John.

> 
>> 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 <rjmcc...@apple.com> wrote:
>>> 
>>>>> On Jul 29, 2017, at 7:01 PM, Daryle Walker via swift-evolution 
>>>>> <swift-evolution@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@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to