[Second review] SE-0390: Noncopyable structs and enums

Agreed that the searchability would still be poor in either approach, but a keyword would be better than a symbol - not that we should base all our decisions on the whims of search-engine algorithms, but it’s far easier to require a specific word in search results than it is a specific symbol, especially if that symbol isn’t separated from other words by whitespace.

7 Likes

If anything, this is the argument against ~, in favour of another symbol like ! or -.
We don't want it to be perceived like a destructor.

2 Likes

Well, I actually don't know about how English people feel about keywords' searchablity because I use google in Japanese. But you can search "swift ~ operator" on google (that's how typical Japanese search about bitwise not operator), and find literally nothing appears. Perhaps the same happens for ~Copyable notation.
If it's a keyword, you can get some results, even if they are common words like any, some or for.

4 Likes

I’m curious about what you mean by “virality of move”. Do you mean the ubiquitous usage of these features across programming domains, despite the core team’s stated assumption that noncopyable types are a niche feature intended for only a couple key use cases?

This concept is the reason I’ve been using up space on this thread to voice my opinions despite not being someone who plans to use noncopyable types in the niche way anytime soon. I’m intrigued by the possibility of more common use cases for noncopyable types (for example, I posted this recently), and I’m worried that the syntax/feature design might be being overly influenced by the assumption that very few people will find it useful.

This idea interests me a lot. Does this mean that it can make sense to use consume on a copyable type? Because it seems possible to me that this would be the actual way to use these new features in order to replace some classes, without actually needing to use types that are themselves noncopyable.

Not only that, but single-character prefix operators are inherently hard to notice while scanning code. It's really easy to miss the difference between condition and !condition while reading through a file. I worry that ~Copyable will suffer from the same issue.

I find ~Copyable to be extremely un-readable, and code is meant to be read.

15 Likes

Another option for a word prefix version: sans Copyable


We rarely do a vote on this forum, maybe we can do it in this case?
The most fair vote system is a bit complicated (where you have N - 1 rounds for N choices) but perhaps we could use the built-in discourse voting plaque as a mean to get to a lower N. For starters it could be word vs special symbol. The final vote result would not automatically mean a winner, but there could be a strong support for one of the options in which case it would be a good indicator of what we want.

3 Likes

That is true, but at the same time, I think we also want libraries to include comprehensive support for non-copyable types. Otherwise having non-copyable data would be extremely inconvenient, as you wouldn't be able pass it to any generic algorithms.

So I think we should also expect that "copyability is optional" is a constraint that will appear rather often in interfaces that are exposed to Swift developers of all levels.

5 Likes

We've said this before, but swift-evolution is not a democracy. The language workgroup is mostly not interested in how many people like each option--we're interested in the reasons that people use to argue for them. A single person who clearly states a compelling argument will lead us to reject a popular suggestion. We are the court, you are the lawyers arguing your cases. The lawyers don't get to vote.

18 Likes

"compelling argument" is highly subjective thing, e.g. the readability of ~ was brought above which some would consider compelling and others won't. If not for us mortals there must be some voting mechanism for the jury / court members themselves as there could easily be a split of opinions there.

Which is? We don't know what it is... or do we? ~ is brought up frequently but there's a bias towards it because it is the symbol that's used in the proposal. So what is the "vox populi"?

I didn't mean to imply that there's a "popular suggestion" in this case. I mean that, in multiple proposals in the past, many of people have said "I like X" but we ultimately rejected X because one person clearly laid out "Y would be better than X because ..." or "we shouldn't do X because it makes the following ambiguous..."

There's an element of subjectivity in the choice of spelling here, but there might also be real tradeoffs. "I don't like ~" doesn't give us much useful information. "I prefer ? because it implies ..." is better. "We should reserve ~ for this other purpose" or "We shouldn't use ~ because it creates a parsing ambiguity with this feature we might want in the future" are much better still.

I do not expect that we will be able to make a final decision solely on the basis of such non-subjective considerations. But "evolution focused their attention on this issue, and ultimately there was no objective argument for any one option" is also useful. It tells the workgroup that we can pick the one that we can make a choice based on our taste and that's OK, to the best of our information. If evolution manages to rule out one or two options, that's even better.

Yes, ultimately the workgroup will vote an pick an option (though we try pretty hard to reach consensus before we resort to voting). What I am saying is that our votes are influenced much more strongly by your reasons than they are by your preferences, so if you do have strong preferences, your effort is best spent on clarifying why.

6 Likes

Absolutely. I personally predict I will use move-only types most frequently as a wrapper for copyable types, as part of guaranteeing an implementation of a data structure avoids copies. Wrapping will involve consuming the copyable value.

2 Likes

if we care about searchability, we should absolutely avoid - as a sigil, since that excludes any results that include "Copyable".

5 Likes

You should never need to do this, except maybe in the extreme short term, since we plan to make it so that borrow bindings are not implicitly copyable even when bound to values of copyable type.

4 Likes

I’m talking about something like this:

struct Cell<Wrapped: ~Copyable> : ~Copyable {
  var value: Wrapped
  init(wrapping value: consuming Wrapped) {
    self.value = move value
  }
  consuming func unwrap() -> Wrapped { value }
}

IIUC, init must consume value rather than borrow it because the lifetime of the Cell is unbounded.

Also I’d like to point out how confusing it is that ~Copyable means two different things on the same line. I think I it’s important that the generic constraint and the type declaration modifier have different spellings, and my brain really wants to see the modifier spelled moveonly struct.

2 Likes

I had similar thinking on generics ca. 2015. Now I start teaching generics the first day of class. Given that Rust seems to have embraced non-copyable types as one of the first things you are taught as part of it being a "safe" language, I sort of suspect that in a couple of years I'll be deferring the teaching of ARC to very late in the course as a sort of a "you-only-need-to-know-this-if-you-end-up-in-a-place-with-an-old-codebase" option. I'm leaning strongly that way at the moment.

I'm curious as to what you feel makes them something to be avoided by most programmer's @John_McCall? Sure there will be a learning curve but they certainly don't seem worse than Concurrency and we're making everyone face that feature now.

4 Likes

Right. What I was saying was, if your only reason to define this type is to prevent a normally copyable value from being implicitly copyable, there will be better ways to do that soon.

They don't really mean different things, though. In both cases ~Copyable means "not assumed to be copyable here (but may be copyable somewhere else)". Whether or not there is a "somewhere else" that makes the thing strictly non-copyable is not really important enough in the abstract to need a separate syntax for any reason other than natural language clarity, which is a reasonable consideration, but introducing artificial syntactic distinctions has its own tradeoffs.

4 Likes

There is approximately a 0% chance that any introductory article on Copyable would not also discuss ~Copyable/-Copyable, however it is spelt.

5 Likes

If we’re thinking ahead to how this syntax might be extended to other protocols/layout constraints down the road, then I certainly believe it’s worth considering how searchable the more general form will be, absent any specific ties to Copyable.

3 Likes

May I suggest the non- prefix, instead of a single character? For example:

struct FileDescriptor: non-Copyable {
  private var fd: Int32
}
2 Likes

I’m not sure the alternative techniques will be applicable in all situations. If you need to sequester a value for an indeterminate period of time—for example, if you’re implementing Pin or a custom allocator (my expected case)—then I don’t see how borrows help, as they are intrinsically scoped.