Skip to content

Commit e635e42

Browse files
committed
Sema: Re-introduce the hack for re-using generic signature of extended protocol
In Swift 5.10 if you wrote `extension Foo {}` for some protocol Foo, the extension would always re-use the generic signature of Foo, which is <Self where Self: Foo>. In Swift 6 this no longer works because Foo might be ~Copyable, in which case `extension Foo {}` adds default requirements, so we changed GenericSignatureRequest to just always build a new signature if we're given an extension. However, to avoid a request cycle with a code example that really should have never worked at all, I'm re-introducing the hack for re-using the signature. Fixes rdar://problem/129540617.
1 parent 5c01ca1 commit e635e42

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,25 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator,
818818

819819
auto *extendedNominal = ext->getExtendedNominal();
820820

821+
// Avoid building a generic signature if we have an unconstrained protocol
822+
// extension of a protocol that does not suppress conformance to ~Copyable
823+
// or ~Escapable. This avoids a request cycle when referencing a protocol
824+
// extension type alias via an unqualified name from a `where` clause on
825+
// the protocol.
826+
if (auto *proto = dyn_cast<ProtocolDecl>(extendedNominal)) {
827+
if (extraReqs.empty() &&
828+
!ext->getTrailingWhereClause()) {
829+
InvertibleProtocolSet protos;
830+
for (auto *inherited : proto->getAllInheritedProtocols()) {
831+
if (auto kind = inherited->getInvertibleProtocolKind())
832+
protos.insert(*kind);
833+
}
834+
835+
if (protos == InvertibleProtocolSet::allKnown())
836+
return extendedNominal->getGenericSignatureOfContext();
837+
}
838+
}
839+
821840
if (isa<BuiltinTupleDecl>(extendedNominal)) {
822841
genericParams = ext->getGenericParams();
823842
} else {

test/Generics/rdar123013710.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ extension Never: Q, P { // expected-note 2{{through reference here}}
1515
public static func f() -> Any? { nil }
1616
}
1717

18-
extension Q { // expected-note {{through reference here}}
19-
public var b: Never { fatalError() } // expected-note 4{{through reference here}}
18+
extension Q {
19+
public var b: Never { fatalError() } // expected-note {{through reference here}}
2020
}
2121

test/NameLookup/protocol_extension_where_clause.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,15 @@ extension P1 where Self: A {
2828
// This is terrible and we should ban it some day
2929
extension P1 where Self: A, B: Hashable {
3030
func h(_: Set<B>) {}
31+
}
32+
33+
// This is also terrible and we should ban it
34+
public protocol P3 {
35+
associatedtype A
36+
}
37+
38+
public protocol P4: P3 where A == B {}
39+
40+
extension P4 {
41+
public typealias B = String
3142
}

0 commit comments

Comments
 (0)