Nobody really seems to know what the `consuming` keyword does

among those with excellent pagerank, nobody really seems to know what the consuming keyword does, at least in the position of a function parameter.

(in contrast, consuming in the “__consuming” position seems to be a bit better documented.)

today, i personally did not know why this doesn’t compile:

init(prefix:consuming [String])
{
    if  prefix.isEmpty
    {
        ...
    }
    else
    {
        self.init(components: prefix)
    }
}

unlike __owned, the compiler doesn’t like that prefix was used to check prefix.isEmpty. that is the intended behavior of SE-0377.

the explanation and prescribed pattern is in fact hidden deep inside SE-0377, it is the third example in the fifth code block under the Using parameter bindings with ownership modifiers subsection.

func baz(a: consuming String) {
    // let aa = (a, a) // ERROR: attempt to copy `a`

    let b = a
    let bb = (b, b) // OK, b is implicitly copyable
}

suffice to say, that is probably not the first place you would think to look to answer the question “why doesn’t this compile?”

can’t we make it easier for people to learn how the ownership modifiers work?

9 Likes

This just seems like a bug to me. isEmpty should not be a consuming method on a Collection, even though it is on a Sequence.

EDIT: and the error messages should make it clear that isEmpty is declared to be consuming.

LATER EDIT: as noted below, I got this wrong; should have verified it! Everyone agrees it’s a bug, though.

9 Likes

From what I can see, it looks like isEmpty is a requirement that starts on Collection, and it isn't declared as consuming there. So this is a bug.

9 Likes

The Array.isEmpty.getter ABI is correct. The "bug" is that the consuming and borrowing keywords are not properly enforced.

8 Likes

i’m having a hard time following what is intended behavior and what isn’t. is Array.isEmpty supposed to be consuming or not?

1 Like

No, it isn't.

2 Likes

All of the following property getters are expected to work by borrowing self:

Sequence.underestimatedCount
Collection.isEmpty
Collection.count
Collection.startIndex/endIndex

(If they consumed self, then that would render them useless.)

10 Likes

For anyone following along, here is the pull request that updates "The Swift Programming Language" to discuss 'borrowing' and 'consuming':

3 Likes

And this PR should fix the example from the OP:

6 Likes