Should this program really compile (is the where clause ignored)?

This compiles and runs:

struct S<T> {
    var a : A
}
extension S where T == Never {
    typealias A = Int
}
let v = S<Int>(a: 123)
print(v)

But should it?

(I'd expect it to be invalid since it requires Int == Never.)

1 Like

I think this is the same inference issue I asked here about, I smell that the where clause is completely ignored. :cry:

struct S<T> {
  var a : A
}
extension S where T == Never {
  typealias A = Int
  init() {
    self.a = 42
  }
}
let v = S()
print(v)
1 Like

Ah yes, it probably is.

I started this thread because I bumped into this particular issue just now (again as it turns out, this time with Swift 5 / Xcode 10.2 and it's also in the latest dev snapshot (2019-04-10)).

I remember now that I've encountered it before and that it is related to the thread you mentioned, as well as this thread and SR-5440 (which I filed almost two years ago, but it's barely partly fixed, as the bug report is a bit too unfocused).

I've now filed the particular code example above as a separate simpler bug.

If it's the same issue I discovered in my thread then it requires a formal proposal for a change of behavior.

See my thread and also the bug report comments: [SR-10158] Associated type inference resolution ignores conditionality of extensions · Issue #52560 · apple/swift · GitHub

  • Do you have a concrete example where this issue popped up for you?
  • Was it a harmful issue?
  • Does it prevent you from implementing something?

I'm not sure if it is the same issue, that's why I try to keep it simple:

The tiny code example in the OP (and SR-10466) as well as the following one, clearly demonstrates that the compiler accepts invalid code, something which is harmful enough by itself and shouldn't require any further motivation for fixing.

struct S<T> {
    typealias Hmm = (A, B, C)
}
extension S where T == Int8 { typealias A = T }
extension S where T == Bool { typealias B = T }
extension S where T == UInt { typealias C = T }

print(S<Int>.Hmm.self) // Prints "(Int8, Bool, UInt)"
// which implies T == Int8 && T == Bool && T == UInt
// ie Int == Int8 && Int == Bool && Int == UInt
// ie something which obviously cannot be the case
// unless Swift is meant to be illogical.
1 Like