> On Nov 10, 2016, at 8:17 PM, Dave Abrahams via swift-evolution > <[email protected]> wrote: > > > on Thu Nov 10 2016, Joe Groff <jgroff-AT-apple.com > <http://jgroff-at-apple.com/>> wrote: > >>> On Nov 10, 2016, at 1:02 PM, Dave Abrahams <[email protected]> wrote: >>> >>> >>> on Thu Nov 10 2016, Stephen Canon <scanon-AT-apple.com> wrote: >>> >> >>>>> On Nov 10, 2016, at 1:30 PM, Dave Abrahams via swift-evolution >>>>> <[email protected]> wrote: >>>>> >>>>> >>>>> on Thu Nov 10 2016, Joe Groff <jgroff-AT-apple.com> wrote: >>>>> >>>> >>>>>>> On Nov 8, 2016, at 9:29 AM, John McCall <[email protected]> wrote: >>>>>>> >>>>>>>> On Nov 8, 2016, at 7:44 AM, Joe Groff via swift-evolution >>>>>>>> <[email protected]> wrote: >>>>>>>>> On Nov 7, 2016, at 3:55 PM, Dave Abrahams via swift-evolution >>>>>>>>> <[email protected]> wrote: >>>>>>>>> >>>>>> >>>>>>>>> >>>>>>>>> on Mon Nov 07 2016, John McCall <[email protected]> wrote: >>>>>>>>> >>>>>>>>>>> On Nov 6, 2016, at 1:20 PM, Dave Abrahams via swift-evolution >>>>>>>>>>> <[email protected]> wrote: >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Given that we're headed for ABI (and thus stdlib API) stability, >>>>>>>>>>> I've >>>>>>>>>>> been giving lots of thought to the bottom layer of our collection >>>>>>>>>> >>>>>>>>>>> abstraction and how it may limit our potential for efficiency. In >>>>>>>>>>> particular, I want to keep the door open for optimizations that >>>>>>>>>>> work on >>>>>>>>>>> contiguous memory regions. Every cache-friendly data structure, >>>>>>>>>>> even if >>>>>>>>>>> it is not an array, contains contiguous memory regions over which >>>>>>>>>>> operations can often be vectorized, that should define boundaries >>>>>>>>>>> for >>>>>>>>>>> parallelism, etc. Throughout Cocoa you can find patterns designed >>>>>>>>>>> to >>>>>>>>>>> exploit this fact when possible (NSFastEnumeration). Posix I/O >>>>>>>>>>> bottoms >>>>>>>>>>> out in readv/writev, and MPI datatypes essentially boil down to >>>>>>>>>>> identifying the contiguous parts of data structures. My point is >>>>>>>>>>> that >>>>>>>>>>> this is an important class of optimization, with numerous real-world >>>>>>>>>>> examples. >>>>>>>>>>> >>>>>>>>>>> If you think about what it means to build APIs for contiguous memory >>>>>>>>>>> into abstractions like Sequence or Collection, at least without >>>>>>>>>>> penalizing the lowest-level code, it means exposing >>>>>>>>>>> UnsafeBufferPointers >>>>>>>>>>> as a first-class part of the protocols, which is really >>>>>>>>>>> unappealing... unless you consider that *borrowed* >>>>>>>>>>> UnsafeBufferPointers >>>>>>>>>>> can be made safe. >>>>>>>>>>> >>>>>>>>>>> [Well, it's slightly more complicated than that because >>>>>>>>>>> UnsafeBufferPointer is designed to bypass bounds checking in release >>>>>>>>>>> builds, and to ensure safety you'd need a BoundsCheckedBuffer—or >>>>>>>>>>> something—that checks bounds unconditionally... but] the point >>>>>>>>>>> remains >>>>>>>>>>> that >>>>>>>>>>> >>>>>>>>>>> A thing that is unsafe when it's arbitrarily copied can become safe >>>>>>>>>>> if >>>>>>>>>>> you ensure that it's only borrowed (in accordance with >>>>>>>>>>> well-understood >>>>>>>>>>> lifetime rules). >>>>>>>>>> >>>>>>>>>> UnsafeBufferPointer today is a copyable type. Having a borrowed >>>>>>>>>> value >>>>>>>>>> doesn't prevent you from making your own copy, which could then >>>>>>>>>> escape >>>>>>>>>> the scope that was guaranteeing safety. >>>>>>>>>> >>>>>>>>>> This is fixable, of course, but it's a more significant change to the >>>>>>>>>> type and how it would be used. >>>>>>>>> >>>>>>>>> It sounds like you're saying that, to get static safety benefits from >>>>>>>>> ownership, we'll need a whole parallel universe of safe move-only >>>>>>>>> types. Seems a cryin' shame. >>>>>>>> >>>>>>>> We've discussed the possibility of types being able to control >>>>>>>> their "borrowed" representation. Even if this isn't something we >>>>>>>> generalize, arrays and contiguous buffers might be important enough >>>>>>>> to the language that your safe BufferPointer could be called >>>>>>>> 'borrowed ArraySlice<T>', with the owner backreference optimized >>>>>>>> out of the borrowed representation. Perhaps Array's own borrowed >>>>>>>> representation would benefit from acting like a slice rather than a >>>>>>>> whole-buffer borrow too. >>>>>>> >>>>>>> The disadvantage of doing this is that it much more heavily >>>>>>> penalizes the case where we actually do a copy from a borrowed >>>>>>> reference — it becomes an actual array copy, not just a reference >>>>>>> bump. >>>>>> >>>>>> Fair point, though the ArraySlice/Array dichotomy strikes me as >>>>>> already kind of encouraging this—you might pass ArraySlices down into >>>>>> your algorithm, but we encourage people to use Array at storage and >>>>>> API boundaries, forcing copies. >>>>>> >>>>>> From a philosophical perspective of making systems Swift feel like >>>>>> "the same language" as Swift today, it feels better to me to try to >>>>>> express this as making our high-level safe abstractions efficient >>>>>> rather than making our low-level unsafe abstractions safe. >>>>> >>>>> +1, or maybe 10 >>>>> >>>>> What worries me is that if systems programmers are trying to get static >>>>> guarantees that there's no ARC traffic, they won't be willing to handle >>>>> a copyable thing that carries ownership. >>>> >>>> FWIW, we (frequently) only need a static guarantee of no ARC traffic >>>> *within a critical section*. If we can guarantee that whatever ARC >>>> operations need to be done happen in a precisely-controlled manner at >>>> a known interface boundary, that’s often good enough. >>> >>> I don't think you can get those guarantees without static protection >>> against escaping borrowed references, though, can you? >> >> You shouldn't be able to do that without copying it, and copying a >> borrow seems like it ought to at least be explicit. > > I don't think that's true for all types (e.g. Int). > > But regardless, we've come full circle, because I'm talking > about needing to do something explicit to copy a a borrowed type when > copying it will be unsafe.
I’m a bit confused by this. Presumably 99.999% of string slices would be an immutable view. Almost no unicode correct code has any business mutating the contents of a fixed-sized string buffer. (data point: the `&mut str` type exists in Rust, but literally every interface I’ve ever seen handles `&str`). If the views are immutable, they’re safe to copy as long as every copy “remembers” that it’s noescape or whatever you want to call it. > > -- > -Dave > _______________________________________________ > swift-evolution mailing list > [email protected] <mailto:[email protected]> > https://lists.swift.org/mailman/listinfo/swift-evolution > <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
