Open
Description
Previous ID | SR-487 |
Radar | rdar://problem/22394263 |
Original Reporter | russ (JIRA User) |
Type | Bug |
Environment
Apple Swift version 2.1.1 (swiftlang-700.1.101.15 clang-700.1.81)
Apple Swift version 3.0-dev (LLVM dffa09ffd8, Clang 9f0d189820, Swift 1c720b8) (May 9, 2016 snapshot)
Additional Detail from JIRA
Votes | 10 |
Component/s | Compiler |
Labels | Bug |
Assignee | @slavapestov |
Priority | Medium |
md5: 144912dacff217d48a6b1ce1fd642c20
is duplicated by:
- [SR-4500] Wrong compiler error with @autoclosure parameter #47077
- [SR-9731] @autoclosure dealing
throws
declaration wiredly #52165 - [SR-9815] Swift complains about throwing function that isn't one (through @autoclosure) #52233
- [SR-10814] Incorrect compiler error with try + autoclosure inside another closure #53204
- [SR-11214] Swift compiler incorrectly warns or errors when a try is captured by a throwing @autoclosure parameter to a function which does not itself throw. #53613
- [SR-11669] Calling function with throwing autoclosure parameter in another closure. #54078
Issue Description:
Minimal example shown below. In certain situations the compiler is attempting to promote the outer closure to throws
when the try
is automatically promoted to a closure. In other situations it correctly surmises that the auto closure makes any attempt to catch
pointless.
func fancyThings() throws { }
func withTemporaryFile(filename: String = NSUUID().UUIDString, deleteWhenFinished: Bool = true, @noescape f: (NSURL) -> Void) { }
func AssertNoThrowNoAutoclosure<T>(expression: () throws -> T) {
do {
try expression()
} catch {
fatalError("Error was thrown when none were expected: \(error)")
}
}
func AssertNoThrow<T>(@autoclosure expression: () throws -> T) {
do {
try expression()
} catch {
fatalError("Error was thrown when none were expected: \(error)")
}
}
withTemporaryFile { tempFile -> Void in
//: Works fine, param is not autoclosure
AssertNoThrowNoAutoclosure({ try fancyThings() })
/*:
This triggers a compiler error even though autoclosure
promotes the `try` into a closure; the `do` form below
should be equivalent since `AssertNoThrow` is not a
throwing function. Instead it attempts to promote the
`withTemporaryFile` closure to throwing.
**error: invalid conversion from throwing function of type '_ throws -> Void' to non-throwing function type '(NSURL) -> Void'**
*/
AssertNoThrow(try fancyThings())
/*:
Attempting to pass an explicit closure also confuses the compiler
**error: cannot invoke 'AssertNoThrow' with an argument list of type '(() throws -> ())'**
*/
AssertNoThrow({ try fancyThings() })
/*:
An explicit `do` still emits a warning because the compiler
correctly deduces that nothing can throw (the autoclosure
hides the try)
**warning: 'catch' block is unreachable because no errors are thrown in 'do' block**
*/
do {
AssertNoThrow(try fancyThings())
} catch { }
}
Metadata
Metadata
Assignees
Labels
Feature → attributes: the @autoclosure type attributeFeature: Declaration and type attributesA deviation from expected or documented behavior. Also: expected but undesirable behavior.Feature: closuresThe Swift compiler itselfFeature: expressionsFeature → error handling: throws & rethrowsArea → compiler: Semantic analysisFeature: type inferenceBug: Unexpected error