"Typealias overriding associated type" fixit breaks code

Here is my original typealias in IntentAction variant that works fine, compiles fine, but we get this warning (the cause of this whole thread) which erroneously tells me to use an associated type.

Either I'm doing something Swift is not meant to support or this warning is wrong for this use case. This is the truth I am after as I'm trying to ship a 1.0 of my open source library that wants to supply this default typealias so consumers of the API don't have to.

FYI @Slava_Pestov @Nevin @anthonylatsis I got to the bottom of this. The key was using associatedtype, and constraining the extension to the exact type (==) specified in the associatedtype assignment, and using the exact types in the extension functions:

public protocol DismissingUIAction: UIAction {
    associatedtype InputType = DismissUIInput
    associatedtype PresenterType = UIViewController
}

public extension DismissingUIAction where InputType == DismissUIInput, PresenterType == UIViewController {
    static func perform(context: ActionContext<DismissUIInput>, presenter: UIViewController, completion: Completion) -> Completion.Status {
        presenter.dismiss(animated: context.input.animated)
        return completion.completedSync(.successWithFeatureTermination)
    }
}

Thanks for your support and patience.

I still have the feeling there are a couple of misunderstandings going on, but am glad the question is resolved. By the way, the last simplified example you provided compiles fine with the Swift 5 compiler. Here's a shorter version:

struct Generic<T: CustomStringConvertible> {}

protocol P {
    associatedtype Assoc1 = Void
}

protocol RefinedP: P {
    associatedtype Assoc1 = Generic<Assoc2>
    associatedtype Assoc2: CustomStringConvertible
}

extension RefinedP where Assoc1 == Generic<Assoc2> {
    static func foo(arg: Assoc1) {}
}

final class Foo: RefinedP {
    typealias Assoc2 = String
}

// Test
Foo.foo(arg: Generic<String>())

OK I showed the code and the issue to @Slava_Pestov at WWDC Swift labs and we established that this is a Swift type inference bug.

We created the relevant JIRA for improving the type inference so that protocols with where constraints that completely specify the associated types as Slava confirmed that subtypes and extensions should not have to also specify these constraints when the sub-protocol has refined them in the where clause.

He also gave me a workaround for now of specifying them as associated types as well as constraints for now, which suppresses the warning, and means that extensions and subtypes don't have to also specify them.

I'm afraid I still fail to understand the exact problem.. At least the latest examples compile fine with Swift 5. Could you share a link to the SR? I suspect a terminological confusion between us; hopefully the bug description can clarify the issue for me. Thanks.

https://bugs.swift.org/browse/SR-10831

Marc, the snippet you attached compiles in Swift 5. Are you using an older language version
(< Xcode10)?

I've updated the issue with more context. It was created with Slava sitting next to me, and the sample was suggested by him!

I see, apologies.

@Slava_Pestov Slava, can you please double-check whether this SR actually describes a relevant bug?

You're right, the example does indeed compile with the Swift 5 compiler. Marc's code however did not, and it was a very similar setup. Here is another case that does not work:

struct G<T> {}
  
protocol P {
  associatedtype T
  associatedtype U
}

protocol Q: P where T == G<U> {}

protocol R: Q where U == Int {}

struct X: R {}

Marc, if I recall the project was open source. Can you share a link to the code?

Thanks, that clarifies a lot. It seems to me the core of the issue is the protocol hierarchy itself, because it works if you swap those constraints. I've managed to boil down one of Marc's examples to what probably is the very similar setup we are after:

struct G<T> {}

protocol P {
    associatedtype U
}

protocol Q: P where U == G<T> {
    associatedtype T
}

struct Foo: Q { // Type 'Foo' does not conform to protocol 'P'
    typealias T = Int
}