Skip to content

[SR-12033] Error or inconsistency in capturing variable by @autoclosure closure #54470

Closed
@ktoso

Description

@ktoso
Previous ID SR-12033
Radar rdar://problem/72801670
Original Reporter @ktoso
Type Bug
Status Resolved
Resolution Duplicate
Environment

Swift: 5.2-DEVELOPMENT-SNAPSHOT-2020-01-13-a

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee @LucianoPAlmeida
Priority Medium

md5: 400b29754adbf7f534b6f2d46fb3b6f2

duplicates:

  • SR-8625 Swift should warn if a closures is passed to an argument that is an autoclosure

Issue Description:

I bumped into a somewhat confusing compile error recently.
Reproducer below.

The general issue seems to come up when using a closure which is an @autoclosure parameter defined within a generic type.

Most notably it's a bit surprising that t5 works fine, so when the function itself has the generic, but the e examples all fail to compile, though they seem equivalent on what they're achieving.

struct Thing<T> {

    public static func capture(_ thunk: () -> T) -> Thing<T> {
        .init() // does not matter how implemented
    }
    public static func captureA(_ thunk: @autoclosure () -> T) -> Thing<T> {
        .init() // does not matter how implemented
    }
    public static func captureE(_ thunk: @escaping () -> T) -> Thing<T> {
        .init() // does not matter how implemented
    }
    public static func captureAE(_ thunk: @autoclosure @escaping () -> T) -> Thing<T> {
        .init() // does not matter how implemented
    }
}
struct Ok {

    public static func captureGenericFuncA<T>(_ thunk: @autoclosure () -> T) -> Thing<T> {
        .init()
    }

    func compiles() {
        var number = 1

        let t = Thing<Int>.capture {
            number
        } // ok, just a sanity check
        let t2 = Thing<Int>.captureE {
            number
        } // ok, just a sanity check

        let t3 = Thing<Int>.captureA(number) // ok

        let t4 = Self.captureGenericFuncA(number) // ok
        let t5 = Self.captureGenericFuncA { number } // ok, works fine, so why not the `e` ones below:
    }
}
struct Bad { 
    func doesNotCompile() {
        var number = 1

        let e = Thing<Int>.captureA { // equivalent to `t5` above
            number
        }
        // cannot convert value of type '@lvalue Int' to closure result type 'Int'
        //        }
        //        ^

        let e2 = Thing<Int>.captureAE {
            number
        }
        // cannot convert value of type '@lvalue Int' to closure result type 'Int'
        //        }
        //        ^
    }
}

Or is there something I'm missing here?

Metadata

Metadata

Labels

bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.compilerThe Swift compiler itself

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions