rvsrvs
(rvsrvs)
1
The following fails to compile:
struct Ref<T>: ~Copyable {
var value: T
init(_ value: T) { self.value = value }
}
func consumingMap<A>(
_ f: @escaping (inout A) -> Void
) -> (consuming Ref<A>) -> Ref<A> {
{ ref in
var newRef = ref
f(&newRef.value)
return newRef
}
}
with the error:
'ref' is borrowed and cannot be consumed.
Shouldn't consuming be inferred here, or am I missing something fundamental? (I feel like I've missed a huge amount of fundamental stuff on move-only types of late).
2 Likes
rvsrvs
(rvsrvs)
2
ok, fooling around with it more, this does compile:
func consumingMap<A>(
_ f: @escaping (inout A) -> Void
) -> (consuming Ref<A>) -> Ref<A> {
{ (ref: consuming Ref<A>) -> Ref<A> in
var newRef = ref
f(&newRef.value)
return newRef
}
}
Seems like I should not have to spell out the full type-annotation here..
1 Like
kavon
(Kavon Farvardin)
3
I think ‘consuming’ ought to be inferred here from the return type (similarly if it were bound to a variable with that explicit type annotation).
I’m not sure if that inference was part of the corresponding SE proposal, but it should be a source-compatible addition if today it’s defaulting to ‘borrowing’, the weakest ownership kind.
rvsrvs
(rvsrvs)
4
that was my thinking too, but this stuff is all so new to me that I'm never sure if I have properly understood the concept. Another quick question, should ref be mutable there? i.e. should I be able to say:
func consumingMap<A>(
_ f: @escaping (inout A) -> Void
) -> (consuming Ref<A>) -> Ref<A> {
{ (ref: consuming Ref<A>) -> Ref<A> in
f(&ref.value)
return ref
}
}
Intuitively I would think I could or at least that it would be desirable. At present trying it that way yields:
error: couldn't IRGen expression. Please enable the expression log by running "log enable lldb expr", then run the failing expression again, and file a bug report with the log output.
I've reported that as a compiler bug, but my I can't tell if (when the compiler gets fixed) that should work or not.
Nobody1707
(Nobody1707)
5
Yes, a function should always be able to mutate its own parameter if that parameter is consuming.
1 Like