Is this a regression or a bug fix in Swift 5 compiler?

This used to compile and work as expected, now the local typealias is not found or ignored.

struct T {
  typealias Test = Int
}

protocol Test {
  typealias Test = T.Test
}

struct S: Test {
  var x: Test = 42 // error: Value of type 'Int' does not conform to specified type 'Test'
}

Next regression:

struct A {
  typealias Value = Int
}

protocol B {
  typealias Value = A.Value
  typealias X = String
}

protocol NestedProtocol {
  typealias _B = B
}

struct Something: NestedProtocol {
  // workaround: `struct InnerTest: B` but why did it break?

  struct InnerTest: _B { // conforms to `B` but all type aliases are lost
    var value: Value = 42 // error: Use of undeclared type 'Value'
    var x: X = "wait what?" // error Use of undeclared type 'X'
  }
}

Next similar issue:

protocol X {}

protocol Y {
  typealias _X = X
  var x: _X { get }
}

struct Struct: Y {
  // error: Value of type 'Struct.__X' does not conform to specified type 'Struct._X' (aka 'X')
  var x: _X = __X()
}

extension Struct {
  struct __X: _X {}
}

Something is broken with type aliases in protocols.

This doesn't compile with 4.2 either. It results in the same (to me expected) error. I don't know if you meant to type var x: T.Text = 42?

This used to compile in my project. Let me grab my other mac where I did not updated to Xcode 10.2 yet.

Inside S Test should be a type alias to T.Test as the local rule always wins.

Why should var x: Test mean that the type of x should be T.Test? It's clearly the protocol Test.

I just tested your example with Swift 4.2 and it produced the same error.

Because S conforms to protocol Test that as a type alias that shadows it. Give me a minute to test. All three examples are basically re-constructed examples from our app where it now errors out but previously did not.

OK

Here's what I did fwiw.
$ swiftc --version
Apple Swift version 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)
Target: x86_64-apple-darwin18.2.0
$ cat > test.swift
struct T {
  typealias Test = Int
}

protocol Test {
  typealias Test = T.Test
}

struct S: Test {
  var x: Test = 42 // error: Value of type 'Int' does not conform to specified type 'Test'
}
$ swiftc test.swift 
test.swift:10:17: error: value of type 'Int' does not conform to specified type 'Test'
  var x: Test = 42 // error: Value of type 'Int' does not conform to specified type 'Test'
                ^~
                   as! Test
$ 

I can verify that your next example does compile with 4.2 though.

Let's change the example a little:

struct T {
  typealias Test = Int
}

protocol Test {
  typealias Test = T.Test
  var test: Test { get }
}

struct S: Test {
  var test: Self.Test = ... 
}

The Swift 4.2.1 compiler suggests Self.Test but since Self is only available in Swift 5 it does not work. But this is indicates that Self.Test should not be different from Test in the body of S. This is failing in playgrounds. I'll check the project again if I reduced the example correctly.

OK, then perhaps this has different behavior with Swift 5:

struct T {
  typealias Test = Int
}
protocol Test {
  typealias Test = T.Test
}
struct S: Test {
  static func foo() { print(Test.self) }
}
S.foo() // Prints Int with Swift 4.2 (haven't tested Swift 5)

Well the first example is part of the second post in this thread, which for some reason loses the type alias. Maybe the first example should not compile, but second and third did work but now fail.

1 Like

It prints Int in Swift 5 as well, but the type alias is lost if you use it one level higher.

I'm at least glad that these were the only errors the compiler emitted in our project. :sweat_smile:

Adding to this thread, here's another regression:

1 Like

Filed the second and third issue from this thread: [SR-10201] Type aliases are lost or invalid/inaccessible from nested protocols · Issue #52601 · apple/swift · GitHub