Gregory Higley
Gregory Higley

Reputation: 16558

"IR generation failure: program too clever" in Swift

The full error is "IR generation failure: program too clever: variable collides with existing symbol _TWPSaSs12SequenceType".

I am writing a bunch of functions as an exercise in learning Swift, especially Swift generics. My latest function, concatenate, is an attempt to implement Haskell's Data.List.concat. It goes as follows:

protocol Concatenable {
    func +(lhs: Self, rhs: Self) -> Self
    init()
}

extension Array: Concatenable {}

func concatenate<S: SequenceType, C: Concatenable where S.Generator.Element == C>(seq: S) -> C {
    var result = C()
    for elem in seq {
        result = result + elem
    }
    return result
}

This works well. However, as an experiment, I wanted to require that anything Concatenable was also a SequenceType, so I changed the code as follows:

protocol Concatenable: SequenceType {
    // etc.
}

As soon as I did this, I got the error mentioned above. However, if you take this code and paste it into a fresh Swift project, everything works. So it is conflicting with something else in my project. Because of that—and I apologize for the length—I am pasting my whole "function library" here.

func foreach<S: SequenceType, T where T == S.Generator.Element>(seq: S, action: (T -> Void)) {
    for elem in seq {
        action(elem)
    }
}

protocol Concatenable: SequenceType {
    func +(lhs: Self, rhs: Self) -> Self
    init()
}

extension Array: Concatenable {}

func concatenate<S: SequenceType, C: Concatenable where S.Generator.Element == C>(seq: S) -> C {
    var result = C()
    for elem in seq {
        result = result + elem
    }
    return result
}

typealias AutoOptional = @autoclosure () -> Any?

func coalesce<S: SequenceType where S.Generator.Element == AutoOptional>(values: S) -> Any? {
    for value: () -> Any? in values {
        if let found = value() {
            return found
        }
    }
    return nil
}

func coalesce(values: @autoclosure () -> Any?...) -> Any? {
    return coalesce(values)
}

func any(values: [() -> Any?]) -> Any? {
    for value: () -> Any? in values {
        if let found = value() {
            if let truth = found as? Bool {
                if truth {
                    return truth
                }
            } else {
                return found
            }
        }
    }
    return nil
}

func any(values: @autoclosure () -> Any?...) -> Any? {
    return any(values)
}

func any<T>(test: T -> Bool, values: [@autoclosure () -> T]) -> T? {
    for value: () -> T in values {
        let found = value()
        if test(found) {
            return found
        }
    }
    return nil
}

func any<T>(values: [@autoclosure () -> T], test: T -> Bool) -> T? {
    return any(test, values)
}

func any<T>(test: T -> Bool, values: @autoclosure () -> T...) -> T? {
    return any(test, values)
}

func all(values: [@autoclosure () -> Any?]) -> Bool {
    for value: () -> Any? in values {
        if let found = value() {
            if let truth = found as? Bool {
                if !truth {
                    return false
                }
            }
        } else {
            return false
        }
    }
    return true
}

func all(values: @autoclosure () -> Any?...) -> Bool {
    return all(values)
}

func all<T>(test: T -> Bool, values: [@autoclosure () -> T]) -> Bool {
    for value: () -> T in values {
        if !test(value()) {
            return false
        }
    }
    return true
}

func all<T>(values: [@autoclosure () -> T], test: T -> Bool) -> Bool {
    return all(test, values)
}

func all<T>(test: T -> Bool, values: @autoclosure () -> T...) -> Bool {
    return all(test, values)
}

If you paste all of the above into a new project, you will get the compilation error I mentioned. Anyone have a clue what this is?

Upvotes: 2

Views: 579

Answers (2)

the Reverend
the Reverend

Reputation: 12549

In my case, this was happening on the Release Build, switched the Optimization Level from "Fast, Whole Module Optimization" to "Fast" to fix it.

Upvotes: 0

James Snook
James Snook

Reputation: 4093

I had the same problem, where I extended an Array with a protocol that also conformed to CollectionType. I believe that the error occurred because Swift saw that Array was being asked to conform to two protocols with the same name, but wasn't clever enough to work out that they were the same protocol.

I've just downloaded the latest version of Xcode (6.3) with the latest version of Swift (1.2) and the problem appears to be fixed, so may be worth another go at it.

Update

The problem wasn't fixed it just stopped being a compile time error and crashed when running the program instead.

Upvotes: 0

Related Questions