Has type checking operators on generic types always been this slow?

The following is too complex for Xcode 10.2.1:

let u = SIMD2<Float>(0, 1)
let v = SIMD2<Float>(1, 2)
let r = [ // ERROR: The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
    2*u + 3*v,
    4*u + 5*v
]

I've described the same problem in another thread and reported it as SR-10461, but this thread is an attempt to present it more clearly to try and gain some attention and priority.

Our projects use a lot of SIMD vectors and because of this regression (first in Xcode 10.2) they've become a pain to work on.


And just to be clear: This issue is not particular to the new SIMD API.

As demonstrated here.
struct Point2D<Scalar: BinaryFloatingPoint> {
    var x, y : Scalar
    init(_ x: Scalar, _ y: Scalar) { (self.x, self.y) = (x, y) }
    
    static func +(lhs: Point2D, rhs: Point2D) -> Point2D {
        return Point2D(lhs.x + rhs.x, lhs.y + rhs.y)
    }
    static func *(lhs: Scalar, rhs: Point2D) -> Point2D {
        return Point2D(lhs * rhs.x, lhs * rhs.y)
    }
}

let u = Point2D(0, 1)
let v = Point2D(1, 2)
let r = [ // ERROR: The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
    2*u + 3*v,
    4*u + 5*v
]

(Note that if Point2D is rewritten to not be generic, it will type check quickly.)


Is this a prioritized issue? If not, doesn't the new SIMD API make it so?

2 Likes

Hmm, I just noticed this:

import AppKit

let u = CGPoint(x: 0, y: 1)
let v = CGPoint(x: 1, y: 2)
let r = [ // ERROR: The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
    2*u + 3*v,
    4*u + 5*v
]

Which I find a bit strange, since CGPoint isn't generic ...

Hi Jens,

I tried recreating your example with CGPoint and I think the issue is it doesn't declare operators for addition and multiplication with a CGFloat.

When the second element in the array is removed I'm seeing the ambiguous error message.

let u = CGPoint(x: 0, y: 1)
let v = CGPoint(x: 1, y: 2)

let r = [ // type of expression is ambiguous without more context
    2 * u + 3 * v,
    //4 * u + 5 * v
]

This compiles without error, but I understand it doesn't answer your original question.

import Cocoa

extension CGPoint {
    
    static func + (lhs: CGPoint, rhs: CGPoint) -> CGPoint {
        return CGPoint(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
    }

    static func * (lhs: CGFloat, rhs: CGPoint) -> CGPoint {
        return CGPoint(x: lhs * rhs.x, y: lhs * rhs.y)
    }
}

let u = CGPoint(x: 0, y: 1)
let v = CGPoint(x: 1, y: 2)

let r = [
    2 * u + 3 * v,
    4 * u + 5 * v
]

Ah! This means that the CGPoint example wasn’t related to the original question then, thanks!

Does annotating the type of r fix it? I suspect the compiler is trying a whole bunch of combinations, to make sure all elements have compatible types, which is wasting a lot of time.

Writing out the type of r helps the type checker enough to make it compile in "reasonable" time, but that is 10 seconds (!) on my machine:

let u = SIMD2<Float>(0, 1)
let v = SIMD2<Float>(1, 2)
let r: [SIMD2<Float>] = [
    2*u + 3*v,
    4*u + 5*v
]

$ time swiftc test.swift 

real	0m10.163s
user	0m9.804s
sys	0m0.344s