my perception of the proposed @noncopyable goes through cycles of hype and despair.
@_moveOnly
enum Enum
{
case a(Int)
case b(Int)
case c(Int)
}
extension Enum
{
var name:Character
{
switch self
{
case .a: return "a"
case .b: return "b"
case .c: return "c"
}
}
}
error: 'self' has guaranteed ownership but was consumed
{
^
note: consuming use
switch self
^
okay. i get that switch makes a new binding, which probably we care about if the associated values are themselves noncopyable. so maybe… this?
extension Enum
{
var name:Character
{
switch self
{
case .a(let value): self = .a(value) ; return "a"
case .b(let value): self = .b(value) ; return "b"
case .c(let value): self = .c(value) ; return "c"
}
}
}
nope, the compiler doesn’t like that either:
error: cannot assign to value: 'self' is immutable
case .a(let value): self = .a(value) ; return "a"
^~~~
error: cannot assign to value: 'self' is immutable
case .b(let value): self = .b(value) ; return "b"
^~~~
error: cannot assign to value: 'self' is immutable
case .c(let value): self = .c(value) ; return "c"
^~~~
it must become:
extension Enum
{
var name:Character
{
mutating get
{
switch self
{
case .a(let value): self = .a(value) ; return "a"
case .b(let value): self = .b(value) ; return "b"
case .c(let value): self = .c(value) ; return "c"
}
}
}
}
surely there there must be an easier way?
1 Like
xwu
(Xiaodi Wu)
2
Currently, switch is always consuming; for clarity, and because this state of affairs is certainly not the desired default for switching over a noncopyable value, the language steering group has decided that switch consume foo will be the required spelling for a consuming switch over a noncopyable foo.
There are open design questions about if and how a non-consuming switch can be made the default in the language. It has not escaped our attention, though, that this is a missing feature.
6 Likes