Swift Compiler crashes when trying to compile the attached sample project when optimization is set to Fastest

Originator:dave
Number:rdar://18510680 Date Originated:01-Oct-2014 00:07 AM
Status:Open Resolved:
Product:Developer Tools Product Version:Xcode 6, up to and including Xcode 6.1.1 GM
Classification:Performance Reproducible:Always
 
Summary:
See the attached sample project.

class SampleClass {

    enum LogLevel: Int, Comparable {
        case Verbose = 0
        case Debug
        case Info
        case Error
    }

    var outputLogLevel: LogLevel = .Verbose

    class func defaultInstance() -> SampleClass {
        struct statics {
            static let instance: SampleClass = SampleClass()
        }
        return statics.instance
    }

    func isEnabledForLogLevel(logLevel: SampleClass.LogLevel) -> Bool {
        return logLevel >= self.outputLogLevel
    }

    func exec(logLevel: LogLevel = .Verbose, closure: () -> () = {}) {
// START CODE BLOCK 1
        if (!isEnabledForLogLevel(logLevel)) { return }
// END CODE BLOCK 1

        closure()
    }

// START CODE BLOCK 2
    class func verboseExec(closure: () -> () = {}) {
        self.defaultInstance().exec(logLevel: SampleClass.LogLevel.Verbose, closure: closure)
    }
// END CODE BLOCK 2
}

func < (lhs:SampleClass.LogLevel, rhs:SampleClass.LogLevel) -> Bool {
    return lhs.rawValue < rhs.rawValue
}

The SampleClass exhibits some very strange behaviour.
When built with the Swift compiler optimization level set to None, it builds without errors.
When the optimization level is Fastest (or Fastest, Unchecked), there are build errors:
    Swift Compiler Error
    - Command failed due to signal: Segmentation fault: 11
    Ditto Error
    - Command /usr/bin/ditto failed with exit code 1
    Apple Mach-O Linker Error
    - Linker command failed with exit code 1 (use -v to see invocation)
    Dsymutil Error
    - error: unable to open executable '...'

I've stripped this class down to the bare minimum needed to see the problem.

Built as is, with -O, and with all code below enabled, you'll see the build errors in Xcode 6.1 GM (6A1042b).

Here is were it gets really strange.

Test 1)
    Start with no code commented out.
    Comment out the line: "case Error" from the LogLevel enum, reducing it to 3 options, and the code will build.
    Same effect for Debug or Info. Can't comment out Verbose as it's used elsewhere in the class as the default value.
    How can having 4+ options cause a build failure, while 3 works fine?

Test 2)
    Start with no code commented out.
    Comment out the Code Block 1: "if (!isEnabledForLogLevel(logLevel)) { return }"
    The code builds again.

Test 3)
    Start with no code commented out.
    Comment out the Code Block 2, the entire class func verboseExec()
    The code builds again.

Test 4)
    Start with no code commented out.
    Change the build settings to use Optimization Level None.
    The code builds again.

Something here is really borking the compiler.

Steps to Reproduce:
Build the sample project attached.

Expected Results:
Compile cleanly.

Actual Results:
Does not compile:

    Swift Compiler Error
    - Command failed due to signal: Segmentation fault: 11
    Ditto Error
    - Command /usr/bin/ditto failed with exit code 1
    Apple Mach-O Linker Error
    - Linker command failed with exit code 1 (use -v to see invocation)
    Dsymutil Error
    - error: unable to open executable '...'


Version:
Xcode 6.1 GM (6A1042b) on Mavericks 10.9.5.

Notes:


Configuration:



Note: Sample project file: http://cl.ly/1G0c0F2D2p0Z
If the link breaks, you can add the code above to a blank Swift project and recreate it.

Problem still exists in Xcode 6.1.1 GM

Comments

Found a workaround

Some interesting additions to this bug.

The line "return logLevel >= self.outputLogLevel" in the isEnabledForLogLevel() function seems to be the main cause of the issue. The compiler is crashing somehow because of the >= operation. Changing it to two separate tests > and == prevents the compiler from crashing.

So this line works "return logLevel > self.outputLogLevel || logLevel == self.outputLogLevel"

Alternatively, adding overloading the >= operator also appears to workaround the compiler crash:

func >= (lhs:SampleClass.LogLevel, rhs:SampleClass.LogLevel) -> Bool { return lhs.rawValue > rhs.rawValue || lhs.rawValue == rhs.rawValue }

Problem still exists in Xcode 6.2

Would love to see some traction on this.

By gemmakbarlow at Dec. 1, 2014, 10:14 p.m. (reply...)

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!