Skip to content

discuss casting of parameters with ownership #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: noncopyable-structs-and-enums
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions proposals/NNNN-noncopyable-structs-and-enums.md
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,12 @@ extension FileDescriptor {
}
```

Casts of function types that change the ownership modifier of a noncopyable
parameter are currently invalid. One reason is that it is impossible to cast a
function with a noncopyable `consuming` parameter, into one where that
parameter is `borrowed`. See Future Directions for details.


### Declaring properties of noncopyable type

A class or noncopyable struct may declare stored `let` or `var` properties of
Expand Down Expand Up @@ -1473,3 +1479,38 @@ borrowing or mutating, instead of passing copies of values back and forth.
We can expose the ability for code to implement these coroutines directly,
which is a good optimization for copyable value types, but also allows for
more expressivity with noncopyable properties.

### Casting function types based on ownership modifiers

The current rules for casting functions with a noncopyable parameter is that
the ownership modifier must remain the same.

One reason behind this limitation is a matter of scope. There is a broader need
to support such casts even for copyable types. For example, a function
containing an `inout` parameter cannot currently be cast to or from any other
function type, unless if the parameter remains `inout`. But it should be safe to
allow a cast to change a `borrowing` parameter into one that is `inout`, as it
only adds a capability (mutation) that is not actually used by the underlying
function:

```swift
// This should be possible, but currently is not.
{ (x: borrowing SomeType) in () } as (inout SomeType) -> ()
```

The second reason is that some casts are only valid for copyable types.
In particular, a cast that changes a `consuming` parameter into one that is
`borrowing` is only valid for copyable types, because a copy of the borrowed
value is required to provide a non-borrowed value to the underlying callee.

```swift
// String is copyable, so both are OK and currently permitted.
{ (x: borrowing String) in () } as (consuming String) -> ()
{ (x: consuming String) in () } as (borrowing String) -> ()

// FileDescriptor is noncopyable, so it cannot go from consuming to borrowing:
{ (x: consuming FileDescriptor) in () } as (borrowing String) -> ()

// but the reverse could be permitted in the future:
{ (x: borrowing FileDescriptor) in () } as (consuming String) -> ()
```