Swift/Xcode 6.1.1: Type inference & @autoclosure gone wrong
| Originator: | weissismail | ||
| Number: | rdar://19510188 | Date Originated: | 2015-01-17 |
| Status: | Duplicate | Resolved: | |
| Product: | Developer Tools | Product Version: | Xcode 6.1.1 |
| Classification: | Reproducible: | always |
Summary:
A specific instance of type inference and @autoclosure that produces a different and wrong output from the same program with a manually added type signature. The effect is as if a function parameter would be a plain normal value and wouldn't be @autoclosure at all.
More specifically: In the Swift program below (also attached as main.swift) the lines marked as [L2] and [L3] should have exactly the same effect as the are the same except that L2 has the additional type annotation "as Result<String>" which should not be needed. As expected, line L2 runs just fine and the constant x gets set to 'let x : Result<String> = Result.Failure(...)'. L3 however does evaluate the expression 'undefined()' which crashes the program. But it should not have evaluated 'undefined()' as it should be wrapped in an @autoclosure and the chain() function does not use the right argument in this case (because the first argument (failure) pattern matches the 'case .Failure(let f)' case in chain() ).
import Foundation
enum Result<T> {
case Success(@autoclosure () -> T);
case Failure(@autoclosure () -> NSError)
}
func undefined<T>(file:StaticString=__FILE__, line:UWord=__LINE__) -> T {
fatalError("undefined", file:file, line:line)
}
func chain<L,R>(l : Result<L>, r : @autoclosure () -> Result<R>) -> Result<R> {
switch(l) {
case .Failure(let f):
return .Failure(f())
case .Success(let _):
return r()
}
}
func testEvaluation() {
let error = NSError(domain: NSPOSIXErrorDomain, code: Int(ENOENT), userInfo: nil)
let failure : Result<String> = .Failure(error)
assert(true || undefined() as Bool) // [L1]: works
let x : Result<String> = chain(failure, undefined() as Result<String>) // [L2]: works
print("x = \(x)\n")
let y : Result<String> = chain(failure, undefined()) // [L3]: CRASHES THE PROGRAM EVALUATING undefined()
print("y = \(y)\n")
}
testEvaluation()
Steps to Reproduce:
1. Download the attached file main.swift
2. Compile and run it with "xcrun -sdk macosx swiftc main.swift && ./main"
Expected Results:
The output should be:
x = (Enum Value)
y = (Enum Value)
Actual Results:
The output is:
x = (Enum Value)
fatal error: undefined: file main.swift, line 27
Illegal instruction: 4
Regression:
n/a
Notes:
- See also my stackoverflow.com question [1].
- dupes rdar://19510182
[1]: http://stackoverflow.com/questions/28004126/swift-autoclosure-evaluation-influenced-by-type-annotations-compiler-bug
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!
dupe of 19821633
Engineering has determined that your bug report is a duplicate of another issue and will be closed.
The open or closed status of the original bug report your issue was duplicated to appears in the yellow "Duplicate of XXXXXXXX" section of the bug reporter user interface. This section appears near the top of the right column's bug detail view just under the bug number, title, state, product and rank.
note just for OpenRadar
I originally misfiled the issue from my work account and asked Apple to close the work one instead of this. They did the opposite :-(
Never mind, that's the open ticket: http://openradar.appspot.com/radar?id=4975887451684864 || rdar://19510182
Apple Developer Relations20-Jan-2015 07:06 AM
Engineering has determined that your bug report is a duplicate of another issue and will be closed.
The open or closed status of the original bug report your issue was duplicated to appears in the yellow "Duplicate of XXXXXXXX" section of the bug reporter user interface. This section appears near the top of the right column's bug detail view just under the bug number, title, state, product and rank.
Johannes Weiß18-Jan-2015 01:26 PM
The type-inference seems to go wrong indeed an that seems to remove @autoclosure.
In L2 (changing 'chain(failure, undefined())' to 'chain(.Success(()), undefined())' the debugger shows
$swift.type.T Builtin.RawPointer TyDDSwift.Result
In L3 however
$swift.type.T Builtin.RawPointer () -> TyDDSwift.Result
so it inferred T as a closure instead of Result...