SE-0390: @noncopyable structs and enums

This doesn't prevent the proposal from being evaluated in isolation - as all proposals.

I'm failing to see where the confusion would lie. Even copy-on-write—a term which is not surfaced anywhere in the language itself, incidentally, and which describes implementation and not language semantics—implies copy-on-something-other-than-write. A value of @noncopyable type cannot be copied in any manner you describe above.

If the issue is that this proposal brings the concept of copying semantics front-and-center where previously it wasn't, then indeed that is the point: previously everything had copying semantics, and now we are introducing the concept that some things won't.


Incidentally, a fair number of beginners do think of semantic copies—as evidenced by the fairly frequent posts from learners in the user forums with concerns about memory or performance inefficiencies of using value types, which is actually what leads them to be introduced to the concept of copy-on-write as an implementation detail in the first place. Indeed, I would venture that for most people who learn Swift, their first introduction to "copy-on-write" takes the form of distinguishing notional (i.e., semantic) copies from actual copying of memory.

8 Likes

a little off topic now, but this policy is how we ended up with the SE-0346 nightmare. in the end i've seen people hiking toolchain requirements to 5.7 across the board to workaround the issue which was exactly the worst case scenario some of us warned about after it was accepted.

i think we would all be a lot better off if swift evolution started taking the package ecosystem's existence into account, the compiler does not exist in a vacuum.

2 Likes

Still that "copy" you feel comfortable with is unsettling for some people. Some people here have expressed their confusion.

Maybe we can try a little empathy and try to address their concerns? There's no obligation do to so, of course. With enough pedagogy and shoe-horning, this thread will have everybody converge on the "correct" interpretation of "copy" (level of the Language Lawyer)

Still, a review is the perfect place to spend time addressing people's concerns. We are lucky that people express concerns.

I personally am quite fine with @noncopyable, I get the concept(s), I'm a frequent reader of the forums, and I'm interested in the quest for efficient memory-safety.

2 Likes

my hunch is a lot these people are not actually crazy, what is happening is they work in organizations that are infected with the giant structs pattern, and they also use SPM, which always builds modules with resilience on. i think this is mostly unrelated to copy semantics, it has more to do with inlining and poor code architecture.

2 Likes

Well, consume's not the only thing you can do with them (or move, for that matter)—you can also still borrow or mutate the single value. The distinguishing characteristic for these types is that their values are independently unique, and your code always works directly with that unique value (rather than with a copyable reference to the unique instance). I would hesitate to suggest a name like "unique" or something specific to these types, though, because in the context of the broader generics system, it really is the lack of a Copyable capability (or whatever you want to call the implicit make-identical-copies operation) that's most important, and that's why I wanted to emphasize that lack, either with a bespoke name following the @non convention we've used elsewhere, or with a more general notation for suppressing implicit generic requirements.

i know this wasn't your argument but i actually really like the term "unique" i think it captures well the behavior of this new phylum of type, and it avoid trying to express a negation like "noncopyable" or "move-only".

2 Likes

Is it, though? I think most people think of a variable binding's "value" as being the data accessible through it, which the reference itself is not. Also, it doesn't help solve the issue that this code cannot be reasoned about locally:

let x = MyThing(property: true)
var y = copy x
y.property = !y.property
assert(x.property != y.property) // Impossible to say.

So yeah, I'm not entirely happy with how overloaded the word "copy" is, and how we're going to be exposing it in the language. It's also used in Apple frameworks to mean a subtly different concept (a "deep copy" which does define the result of the above code).

I wish we could find a different word, or more precisely define value/reference semantics (including structs/enums with reference semantics, classes with value semantics) and introduce explicit operations for value/reference copying which are limited to types with the respective semantics.

1 Like

@unique definitely looks and sounds like it could be mean "make this a singleton". You would need the whole phrase that was used, @instanceunique for it to be more clear, but I don't think most people would understand what it means at a glance.

I really don't think there's a name we can choose that will have an obvious meaning to less experienced users. If they aren't already familiar with Swift's copy semantics, no name will bridge that gap. Once they are familiar, noncopyable should make sense, if only because it'll be one of the things they learn about.

5 Likes

Indeed the first sentence of the proposal itself merges the two concepts: non-copyable and unique ownership:

This proposal introduces the concept of noncopyable types (also known as "move-only" types). An instance of a noncopyable type always has unique ownership, unlike normal Swift types which can be freely copied.

Is this equivalence profound, I mean, do you think it will stand the test of time?

[..] because in the context of the broader generics system, it really is the lack of a Copyable capability [...] that's most important

Do you mean that the copyable capability is important at the compiler implementation level, or that you also expect it to surface userland, with ?Copyable (or a variation)?

I ask those two questions because "unique ownership" is not bloated as "copy" is. We could have, say, @uniquelyOwned, and ?Shared or ?Shareable.

1 Like

It will surface to userland, because while most generic parameters will still implicitly assume a copyability requirement, there will need to be a way to opt out of that, and then be able to express the copyable requirement in contexts where it's been opted out of, such as in conditional conformances like Foo: Fooable where Bar: Copyable. Most users should still be able to work primarily with implicitly-copyable types like they do today, but the concept will have to be exposed in the language at some level.

All right. But couldn't the concept of shareable/shared replace the concept of copyable, with the same meaning? This could help us firmly install those features in the global realm of Swift ownership, with a distinct set of words (shared, consume, borrow, etc).

"Shared" is free, not bloated, and it matches well the concept of unique ownership (it can be used as its exact opposite). Looks like a good replacement for Copyable to me.

We should certainly include those terms (and the others suggested in this thread) to the document as possible terminology for consideration by the Language Work Group when they do their final review.

Shareable/shared sounds nice, but I worry that it will be confusing, since these types can still be "shared" in the sense that they can be passed to a borrow or inout function argument. Such "borrowing" does not create a copy of the object -- it is implemented by the compiler using pass-by-reference -- but it does "share" it in the intuitive sense of that word. (And we are considering other ways in which noncopyable values might be borrowed -- not just by functions but also by other data structures.)

Tim

1 Like

You're right, it sounds odd that borrowing is possible for non-shareable types.

It actually also sounds odd that borrowing is possible for uniquely owned types.

Perhaps this oddity adds less confusion than "copy", though. It's a small oddity, very focused - when copy is everywhere in the everyday life of developers. Maybe it hurts less.

I trust the wisdom of the Language Workgroup and the community in the search for the best vocabulary.

That doesn't sound odd to me: You still own your car, even if I've borrowed it.

Tim

6 Likes

You're right, sorry. The rest of my post is not invalidated: it can be useful to compare the harmless of so many more or less badly-chosen words. I hope "copy" has become a less obvious choice.

It seems like it gives the opposite connotation to me, though, since being Copyable means you don't have to share a value because you can always* make your own independently-owned copy that's just as good as the original. These new types that aren't copyable, on the other hand, force you to share the single instance.

*to the limit of acceptable time/resource usage, of course

It's a matter of point of view. If we start from "uniquely owned" as a firm and non-ambiguous term, then "shared" can be used an opposite, shorter than "non-uniquely-owned" (aka copyable).

Shared is not perfect, all right - copyable is not either. There are other suggestions as well, and the role of the language workgroup is to choose the best or the less evil word.

Thanks for this conversation - I'm not sure I should continue discussing alternatives to "copy" :-)

“Shared” is problematic because of the longstanding notion of “shared state” in computer science, which refers to something totally different.

I’m not opposed to considering alternative names for this, but suffice to say that all the obvious ones have already been discussed to exhaustion in the various pitch threads and by the team proposing the feature. It isn’t likely to be fruitful unless someone has a real flash of insight.

As review manager I really want to avoid spending two weeks discussing the naming without making progress and neglecting the rest of the proposal, which is frankly much more important. If someone thinks they really have a genuinely better name, please share it, but brainstorming lists of synonyms is not itself very useful feedback for the LWG.

“Copy” isn’t perfect, as discussed, but it’s the best option we’ve seen so far. We can live with it. It will be much worse if the proposal contains something that turns out to just not work with other plans for the language or libraries, but we never got that feedback because everyone had tunnel-vision on naming.

21 Likes

One naming-related aspect I think should be fair game is how to specify non-copyability. I'm not really a fan of the @noncopyable attribute myself, so it would be good to hear the community's feedback about alternatives like a generic constraint suppressor like : ?Copyable, and/or implicitly inferring noncopyability when a type contains a noncopyable field or deinit.

5 Likes