Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does "__consuming" do in Swift?

Tags:

swift

There are functions prepended with __consuming in Sequence.swift (most likely other places too, but I haven't really looked around). I know it's some type of declaration modifier but I'm not sure what it does.

like image 308
Dalton Sweeney Avatar asked Jul 11 '18 19:07

Dalton Sweeney


2 Answers

As I understand it, __consuming doesn't actually do anything yet. It has been added in anticipation of the implementation of move-only types, at which point it will be used to in order to denote a method that consumes the value it is called upon (i.e the value will be moved from the caller to the callee).

To illustrate, consider this pseudocode:

// Foo is a move-only type, it cannot be copied.
moveonly struct Foo {
  consuming func bar() { // Method is marked consuming, therefore `self` is moved into it.
    print(self) // We now 'own' `self`, and it will be deinitialised at the end of the call.
  }
}

let f = Foo()
f.bar() // `bar` is a `consuming` method, so `f` is moved from the caller to the callee.
print(f) // Invalid, because we no longer own `f`.

The attribute is currently prefixed by two underscores in order to indicate that it shouldn't be used by users until move-only types are actually implemented, at which point it will likely be renamed to consuming.

As you've found out, some standard library protocol requirements have been marked __consuming in order to indicate that they can be satisfied by a consuming method of a move-only type, as well as a non-consuming method. This is in much the same way that a mutating protocol requirement indicates that it can be satisfied by a mutating method on a value-type, or an otherwise non-mutating method (but as far as I'm aware, no actual compiler logic backs the checking of __consuming yet).

For example, the filter(_:) requirement on Sequence has been marked consuming, as an adopting sequence of move-only elements would need to be able to move the applicable elements into the resulting array, thereby invalidating the sequence.

The reason why the attribute has been added well before the implementation of move-only types is in preparation for the Swift 5 ABI stability freeze. As Martin says, this is discussed in more detail on the forums:

  • Preparing the iteration ABI for move-only types
like image 51
Hamish Avatar answered Nov 10 '22 07:11

Hamish


It's an attribute defined by a macro in Attr.def:

CONTEXTUAL_SIMPLE_DECL_ATTR(__consuming, Consuming,
  OnFunc | OnAccessor |
  DeclModifier |
  UserInaccessible |
NotSerialized, 40)
like image 39
Ortomala Lokni Avatar answered Nov 10 '22 06:11

Ortomala Lokni