To help keep proposals moving forward, the Swift core team has set aside some 
time specifically for design discussions of upcoming proposals.  Below are some 
rough notes from the yesterday's discussion.

(This week, I want to point out that my notes for PR 219, the first discussion 
topic, are especially rough.)

These are informal comments, intended to guide the proposals in directions that 
draw constructive feedback. You are welcome to ignore the feedback, agree with 
it, or disagree with it.  As always, the formal decision doesn't happen until 
after the review period ends.




Make pointer nullability explicit using Optional 
<file:///Users/alexmartini/DevPubs%20Git%20Repositories/Swift%20Language%20Review/_build/html/LR_MeetingNotes/2016-03-23.html#make-pointer-nullability-explicit-using-optional>
https://github.com/apple/swift-evolution/pull/219 
<https://github.com/apple/swift-evolution/pull/219>
Biggest open issue is what to do with UnsafeBufferPointer which has a base 
address and a count of the number of elements at that address. The most common 
use is to do fast things with an array. The problem is when you have an empty 
array.

We have a statically initialized empty array, so this doesn’t apply to array. 
But slices and Cocoa arrays can do it.

Half of the use cases are subscripting off of the buffer, so they don’t 
actually use the base address. They can’t actually subscript an empty array, 
but it’s not a syntax error — the loop is run zero times, so it doesn’t matter. 
The other half pass the pointers down to a C API that takes an address and 
count.

Someone might expect that the base address doesn’t change when something is 
initialized.

We can’t easily use the zero pointer because SIL already uses it for nil. But 
there are issues with using the same representation as C to avoid bridging 
costs.

We’re mapping two things in C onto one thing in Swift. In C, the buffer pointer 
would be __nullable long * and the length is ulong.

Given everything else in the system, it’s more like pointer. We didn’t call it 
a buffer because that tends to imply ownership.

Sketching out the state space:

Pointer Length  Static type
null    0       UBP?     
valid   >= 0    UBP      
valid   < 0     X        
vull    != 0    ???      
This issue would go away if we got rid of the base address on 
UnsafeBufferPointer, but that would get rid of a number of valid C operations 
like calling memcopy.

It seems like withUnsafeBufferPointer should never produce nil. With that in 
mind, why should UnsafeBufferPointer need to?

We do need a properly-aligned “valid” invalid pointer. LLVM makes assumptions 
about things being aligned.

Dominant feedback on the list has been for people want something that round 
trips cleanly. Making the base address non-optional adds overhead and removes 
the ability to round trip.

It’s unfortunate that we don’t have a way to represent in the type system a 
buffer pointer that isn’t nullable, from within withUnsafeBufferPointer which 
wouldn’t even call its closure if the buffer has a null base address.

Allow Swift types to provide custom Objective-C representations 
<file:///Users/alexmartini/DevPubs%20Git%20Repositories/Swift%20Language%20Review/_build/html/LR_MeetingNotes/2016-03-23.html#allow-swift-types-to-provide-custom-objective-c-representations>
https://github.com/apple/swift-evolution/pull/198 
<https://github.com/apple/swift-evolution/pull/198>
The associated type could be AnyObject rather than NSObject. The use case for a 
non-subclass of NSObject is very narrow, but it’s not a needed restriction.

The unconditionalyBridgeFromObjectiveC function can probably go away. Calling 
initializers from the downcasting infrastructure is horrible. If we need a 
function, they

This doesn’t break the ability of the optimizer to reason about what a dynamic 
cast can do. We require that the bridgeable conformance must be in the same 
module as where the type is defined, and we have a white list of things that 
don’t follow that. Ok... but do we want people to expand casting this way? If 
we say no, we should take it away from array and string and dictionary too.

You shouldn’t need implicit conversions — the use case is very narrow, and we 
would rather have things use explicit conversions. The APIs come in with the 
right type; the implementation of the bridged type has to do conversion, but 
its clients don’t have to see that. From the Swift point of view, there won’t 
be any APIs that take the reference type.

Implicit conversions. In this proposals, you don’t get implicit conversions. 
Have a separate discussion about whether we can get rid of the four types that 
have implicit conversion. We see the existing ones as deeply problematic.

Dynamic casts. For example, AnyObject to a bridged value type. The whole reason 
for the dynamic cast infrastructure is to make the reference types irrelevant. 
Should this be using cast syntax or should we have a different type of 
function? It’s hard to describe what as does. It’s magic because you are 
casting AnyObject to a struct — calling it AnyObject doesn’t make a lot of 
sense.

If we have reference counted existentials, we could merge Any and AnyObject.

Resilience concern: you can not add this protocol after the type has been 
published.

SE-0054: Abolish ImplicitlyUnwrappedOptional type 
<file:///Users/alexmartini/DevPubs%20Git%20Repositories/Swift%20Language%20Review/_build/html/LR_MeetingNotes/2016-03-23.html#se-0054-abolish-implicitlyunwrappedoptional-type>
https://github.com/apple/swift-evolution/blob/master/proposals/0054-abolish-iuo.md
 
<https://github.com/apple/swift-evolution/blob/master/proposals/0054-abolish-iuo.md>
IUO as a type is bad; it should become conceptually a decl attribute instead. 
If we import things that can be nil, their formal type is Optional but we can 
add an attribute that says when you form a rvalue to that thing, you get 
implicit unwrapping. The typechecker inserts a diamond that lets you convert it 
to T? or T. Meaning T! never enters the type system — although it does still 
appear in user-facing decl descriptions.

For example:

let y = P       // y is of type T?
let y: T! = P   // y is of type T!
let x = [P]     // x is of type [T?]
One issue is that we don’t have a good way to mark a function that takes a 
block pointer, when that block has not been audited.

void foo(C *(*fp)(C* x)) {}
func foo (fp: ((C?) -> C?)!) {}
func foo (@IUO fp: (C?) -> C?) {}
That is a regression from our current behavior. It would have to be a type 
attribute because they can chain. This will show up in places where you return 
(and then call) a block.

For example, you can no longer express the type let y: (T?, U!).

We don’t need to have a diamond for currying, only for rvalue access and 
application.

x.foo()         // T!
Type.foo(x)()   // T? return type
A source breaking change here is that if extract something into an intermediate 
variable could change type in a very important way. That’s already somewhat 
true because of overload resolution, but this makes it much more visible.

Does this gloss over the audit problem? We’ve gotten most of the really 
important stuff audited, but there are lots of unaudited things such as most of 
the SDK on Linux. This means we don’t propagate the IUO stuff up, meaning we 
end up with more explicit forces in code when you are using unaudited API.

Deferred initialization is still a good argument for why we need the feature. 
This approach locks down propagation and makes IUO more predictable: if the 
expression can typecheck as optional it will, otherwise it will force.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to