diff --git a/lib/AST/RequirementMachine/ApplyInverses.cpp b/lib/AST/RequirementMachine/ApplyInverses.cpp index 7467c86e66c46..e86524018de5e 100644 --- a/lib/AST/RequirementMachine/ApplyInverses.cpp +++ b/lib/AST/RequirementMachine/ApplyInverses.cpp @@ -204,7 +204,8 @@ void swift::rewriting::applyInverses( // func f() where Self: ~Copyable // } // - if (representativeGPs.find(canSubject) == representativeGPs.end()) { + auto subjectRoot = canSubject->getDependentMemberRoot()->getCanonicalType(); + if (representativeGPs.find(subjectRoot) == representativeGPs.end()) { errors.push_back( RequirementError::forInvalidInverseOuterSubject(inverse)); continue; diff --git a/test/Generics/inverse_assoc_types.swift b/test/Generics/inverse_assoc_types.swift index 8ed117b33ba75..35ead9097ad8b 100644 --- a/test/Generics/inverse_assoc_types.swift +++ b/test/Generics/inverse_assoc_types.swift @@ -53,7 +53,7 @@ protocol Iterable: ~Copyable { struct ReqC {} -func reqC(_ t: T) {} // expected-note 8{{'where T: Copyable' is implicit here}} +func reqC(_ t: T) {} // expected-note 14{{'where T: Copyable' is implicit here}} protocol ProvideA: ~Copyable { @@ -130,25 +130,45 @@ func checkExistential(_ s: any Gen) { reqC(s.i().e().i().e()) } +func checkExistential2(_ s: any Gen) { + reqC(s.e()) // expected-error {{global function 'reqC' requires that 'R' conform to 'Copyable'}} + reqC(s.e().e()) // expected-error {{value of type 'R' has no member 'e'}} + + reqC(s.i()) // expected-error {{requires that 'T' conform to 'Copyable'}} + reqC(s.i().e()) + reqC(s.i().e().i()) // expected-error {{requires that 'T' conform to 'Copyable'}} + reqC(s.i().e().i().e()) +} + +// Suppression on the constrained existential only goes far down +// as possible to suppress on the generic type parameter itself. +func checkExistential3(_ s: any Gen) where R: Gen, R: ~Copyable, R.E: ~Copyable { + reqC(s.e()) // expected-error {{global function 'reqC' requires that 'R' conform to 'Copyable'}} + reqC(s.e().e()) // expected-error {{global function 'reqC' requires that 'R.E' conform to 'Copyable'}} + reqC(s.e().e().e()) +} + protocol Veggie { associatedtype A: ~Copyable associatedtype NeedsCopyable + + func a() -> A } protocol Carrot: Veggie where Self.NeedsCopyable: ~Copyable {} // expected-error {{'Self.NeedsCopyable' required to be 'Copyable' but is marked with '~Copyable'}} - // expected-error @-1{{cannot suppress '~Copyable' on generic parameter 'Self.NeedsCopyable' defined in outer scope}} protocol CarrotCake: Carrot where Self.A: ~Copyable {} // expected-error {{'Self.A' required to be 'Copyable' but is marked with '~Copyable'}} -// expected-error @-1{{cannot suppress '~Copyable' on generic parameter 'Self.A' defined in outer scope}} +func ex1(_ nc: any Veggie, c: any Veggie) { + reqC(nc.a()) // expected-error {{global function 'reqC' requires that 'Cucumber' conform to 'Copyable'}} + reqC(c.a()) +} protocol Bird { associatedtype Song } protocol Eagle: Bird where Self.Song: ~Copyable {}// expected-error {{'Self.Song' required to be 'Copyable' but is marked with '~Copyable'}} -// expected-error @-1{{cannot suppress '~Copyable' on generic parameter 'Self.Song' defined in outer scope}} - protocol Pushable { associatedtype Element: ~Copyable diff --git a/test/Generics/inverse_extensions.swift b/test/Generics/inverse_extensions.swift index 9e0514b65f248..686ed2ca05a18 100644 --- a/test/Generics/inverse_extensions.swift +++ b/test/Generics/inverse_extensions.swift @@ -16,8 +16,7 @@ protocol HasAssoc { associatedtype A } extension HasAssoc where Self.A: ~Copyable {} -// expected-error@-1 {{cannot suppress '~Copyable' on generic parameter 'Self.A' defined in outer scope}} -// expected-error@-2 {{'Self.A' required to be 'Copyable' but is marked with '~Copyable'}} +// expected-error@-1 {{'Self.A' required to be 'Copyable' but is marked with '~Copyable'}} class Box {} extension Box where T: ~Copyable {}