Nonsense compiler diagnostics

Lately I've run into a few cases where the compiler gives a completely nonsense diagnostic for a compile error. I don't remember any of the previous ones, but I just ran into one that's especially strange and I thought someone working on generics or something might find it useful. It may be related to a previous post of mine about another odd diagnostic (although that one was happening for code that should compile perfectly fine as far as I could see).

Here's the diagnostic:

CompressionUtil.swift:45:15: error: type '(SIMD2<Double>) -> Double' cannot conform to 'BinaryInteger'
    if length != decompressedLength {
              ^

The line that that's occurring on is in a function that has nothing to do with protocol conformances or simd types. I do use simd and some generics related to BinaryInteger in other unrelated files but they're compiling perfectly fine.

The actual issue with that line of code is just that there is no such variable called length (I accidentally renamed the wrong thing). Here's the function that this is occurring in:

  static func decompress(_ bytes: [UInt8], decompressedLength: Int) throws -> [UInt8] {
    let compressedData = Data(bytes: bytes, count: bytes.count)

    // Decompression only works if the first two bytes are removed no idea why, it's probably
    // something to do with headers or magic numbers
    var compressedBytes = [UInt8](compressedData[2...])

    var decompressedLength = UInt(decompressedLength)
    let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: decompressedLength)
    let err = zlib.uncompress(
      buffer,
      &decompressedLength,
      &compressedBytes,
      UInt(compressedBytes.count)
    )

    if err != Z_OK {
      throw CompressionError.decompressionFailed(error: Int(err))
    }

    if length != decompressedLength { // This is the line that has the weird diagnostic
      log.warning("actual decompressed length does not match length in packet")
    }

    let data = Data(bytes: buffer, count: length)
    buffer.deallocate()
    return [UInt8](data)
  }

I'm happy to provide more context if it would be useful in resolving whatever is causing this clearly incorrect diagnostic.

Ok nevermind this one seems to be because there's a global function called length in a package that I rely on. But, I'm not importing that library in this file at all. Does that make this a bug about Swift finding the function even though it's not imported at all?

1 Like

Ok here's an actual one I think (hopefully). I've run into this a few times (excuse the non-standard diagnostic formatting, I was running swift build through my custom swift build logs reformatter when this happened):

error: GUIElementMesh.swift:67:14: cannot convert value of type 'GUISpriteDescriptor' to expected argument type 'Vec2f' (aka 'SIMD2<Float>')
  +> for: sprite,

Here's the code surrounding the error:

GUIQuad(
  for: sprite,
  guiTexturePalette: guiTexturePalette,
  guiArrayTexture: guiArrayTexture
)

The actual issue was that in another file (GUIQuad.swift) where the initialiser was defined, the GUISpriteDescriptor type hadn't been imported, and for some reason the compiler seems to think that the argument is a Vec2f. There are two other initialisers on the type (also with 3 arguments each) but neither of them have the first argument labelled for (one does have the first argument of type Vec2f though).

EDIT: The GUISpriteDescriptor type was imported but the type of the second initialiser parameter wasn't (GUITexturePalette). There were two more related diagnostics, both of which had types from another initialiser. It almost seems like the compiler is just being too resilient and producing multiple diagnostics for an error after it has already made one for the root cause.