swiftlang / swift

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

autoclosures do not provide explicit typed throw information #75674

Open JessyCatterwaul opened 1 month ago

JessyCatterwaul commented 1 month ago

Description

The type information is there. It just needs some help to be brought to the surface.

Reproduction

Given these…

func closure<Error>(
  _: Error.Type = Error.self,
  _: () throws(Error) -> Void
) throws(Error) { }

func autoclosure<Error>(
  _: Error.Type = Error.self,
  value: @autoclosure () throws(Error) -> Void
) throws(Error) { }

…all but the last line compiles.

closure(Never.self) { }
closure { }
autoclosure(Never.self, value: ())
autoclosure(value: ()) // Generic parameter 'Error' could not be inferred

Expected behavior

The types from autoclosures' errors project outwards so they can be used implicitly, as happens with not-auto-closures.

Environment

swift-driver version: 1.112.3 Apple Swift version 6.0 (swiftlang-6.0.0.6.8 clang-1600.0.23.1) Target: arm64-apple-macosx14.0

Additional information

I want this to work!

/// The "**Error-Coalescing Operator**".
/// - Remark: `shift-option-?` *makes the `¿` symbol.*
public func ¿? <Value, Error>(
  _ value0: @autoclosure () throws -> Value,
  _ value1: @autoclosure () throws(Error) -> Value
) throws(Error) -> Value {
  do {
    return try value0()
  } catch {
    return try value1()
  }
}
gregomni commented 1 month ago

This looks like it's possibly a duplicate of #75430

JessyCatterwaul commented 1 month ago

I worked through that one again, and, as I'm about to comment there, you are correct. One of these issues can be closed, but the other one has to have a name with "autoclosure" in it.

BadPirate commented 1 month ago

This seems related, but doesn't require auto-closure.

struct SomeError: Error {}
struct CustomError: Error {}

let typedThrowingClosure: () throws(CustomError) -> Bool = {
    do { throw SomeError() } catch { throw CustomError() }
}

I think throws from inside the catch just get defaulted to "any Error", can't figure out any way to "Hint" the catch throwing type.

image

JessyCatterwaul commented 1 month ago

This seems related, but doesn't require auto-closure.

As I said in a comment in #75430, that is not the same issue, and mention of it should be removed from here and made into another issues if it hasn't been already. (I never logged that bug, but it's been the behavior since day 1 of Xcode 16.)

You just have to explicitly type the error within the closure:

var typedThrowingClosure: () throws(CustomError) -> Bool
typedThrowingClosure = { () throws(CustomError) in
  do { throw SomeError() } catch { throw .init() }
}
typedThrowingClosure = { () throws(_) in
  do { throw SomeError() } catch { throw CustomError() }
}