swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.37k stars 10.34k forks source link

Type inference failure with noncopyable types. #70001

Open rvsrvs opened 10 months ago

rvsrvs commented 10 months ago

Description

The following code fails to compile with the error message: ref is borrowed and cannot be consumed.

struct Ref<T>: ~Copyable {
    var value: T
}

func consumingMap<A>(
    _ f: @escaping (inout A) -> Void
) -> (consuming Ref<A>) -> Ref<A> {
    { ref in
        var newRef = ref
        f(&newRef.value)
        return newRef
    }
}

The following, however, 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
    }
}

Steps to reproduce

Put the above code in a playground. Observe that it does not compile.

Expected behavior

The first code should compile without having to put the explicit type information on the returned closure.

Environment

swift-driver version: 1.87.3 Apple Swift version 5.9.2 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5) Target: arm64-apple-macosx14.0

Xcode 15.1 Build version 15C5059c

macOS 14

rvsrvs commented 10 months ago

When run in a playground, the following, related, code fails to compile as well:

struct Ref<T>: ~Copyable {
    var value: T
}

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
    }
}

with the message: 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.