Skip to content

Commit f4a5f85

Browse files
authored
Merge pull request #42293 from hank121314/main
[Sema] SR-15807: Associated Type Inference fails across module boundaries
2 parents 270d100 + 1e5519c commit f4a5f85

File tree

7 files changed

+108
-2
lines changed

7 files changed

+108
-2
lines changed

include/swift/AST/NameLookup.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,11 @@ SmallVector<InheritedNominalEntry, 4> getDirectlyInheritedNominalTypeDecls(
548548
SelfBounds getSelfBoundsFromWhereClause(
549549
llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> decl);
550550

551+
/// Retrieve the set of nominal type declarations that appear as the
552+
/// constraint type of any "Self" constraints in the generic signature of the
553+
/// given protocol or protocol extension.
554+
SelfBounds getSelfBoundsFromGenericSignature(const ExtensionDecl *extDecl);
555+
551556
/// Retrieve the TypeLoc at the given \c index from among the set of
552557
/// type declarations that are directly "inherited" by the given declaration.
553558
inline const TypeLoc &getInheritedTypeLocAtIndex(

include/swift/AST/NameLookupRequests.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,22 @@ class SelfBoundsFromWhereClauseRequest
270270
llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *>) const;
271271
};
272272

273+
/// Request the nominal types that occur as the right-hand side of "Self: Foo"
274+
/// constraints in the generic signature of a protocol extension.
275+
class SelfBoundsFromGenericSignatureRequest
276+
: public SimpleRequest<SelfBoundsFromGenericSignatureRequest,
277+
SelfBounds(const ExtensionDecl *),
278+
RequestFlags::Uncached> {
279+
public:
280+
using SimpleRequest::SimpleRequest;
281+
282+
private:
283+
friend SimpleRequest;
284+
285+
// Evaluation.
286+
SelfBounds evaluate(Evaluator &evaluator, const ExtensionDecl *extDecl) const;
287+
};
288+
273289
/// Request all type aliases and nominal types that appear in the "where"
274290
/// clause of an extension.
275291
class TypeDeclsFromWhereClauseRequest :

include/swift/AST/NameLookupTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ SWIFT_REQUEST(NameLookup, SelfBoundsFromWhereClauseRequest,
6868
SelfBounds(llvm::PointerUnion<const TypeDecl *,
6969
const ExtensionDecl *>),
7070
Uncached, NoLocationInfo)
71+
SWIFT_REQUEST(NameLookup, SelfBoundsFromGenericSignatureRequest,
72+
SelfBounds(const ExtensionDecl * extDecl),
73+
Uncached, NoLocationInfo)
7174
SWIFT_REQUEST(NameLookup, SuperclassDeclRequest, ClassDecl *(NominalTypeDecl *),
7275
SeparatelyCached, NoLocationInfo)
7376
SWIFT_REQUEST(NameLookup, HasMissingDesignatedInitializersRequest,

lib/AST/NameLookup.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,39 @@ SelfBounds swift::getSelfBoundsFromWhereClause(
980980
SelfBoundsFromWhereClauseRequest{decl}, {});
981981
}
982982

983+
SelfBounds SelfBoundsFromGenericSignatureRequest::evaluate(
984+
Evaluator &evaluator, const ExtensionDecl *extDecl) const {
985+
SelfBounds result;
986+
ASTContext &ctx = extDecl->getASTContext();
987+
auto selfType = extDecl->getSelfInterfaceType();
988+
for (const auto &req : extDecl->getGenericRequirements()) {
989+
auto kind = req.getKind();
990+
if (kind != RequirementKind::Conformance &&
991+
kind != RequirementKind::Superclass)
992+
continue;
993+
// The left-hand side of the type constraint must be 'Self'.
994+
bool isSelfLHS = selfType->isEqual(req.getFirstType());
995+
if (!isSelfLHS)
996+
continue;
997+
998+
auto rhsDecls = directReferencesForType(req.getSecondType());
999+
SmallVector<ModuleDecl *, 2> modulesFound;
1000+
auto rhsNominals = resolveTypeDeclsToNominal(
1001+
evaluator, ctx, rhsDecls, modulesFound, result.anyObject);
1002+
result.decls.insert(result.decls.end(), rhsNominals.begin(),
1003+
rhsNominals.end());
1004+
}
1005+
1006+
return result;
1007+
}
1008+
1009+
SelfBounds
1010+
swift::getSelfBoundsFromGenericSignature(const ExtensionDecl *extDecl) {
1011+
auto &ctx = extDecl->getASTContext();
1012+
return evaluateOrDefault(ctx.evaluator,
1013+
SelfBoundsFromGenericSignatureRequest{extDecl}, {});
1014+
}
1015+
9831016
TinyPtrVector<TypeDecl *>
9841017
TypeDeclsFromWhereClauseRequest::evaluate(Evaluator &evaluator,
9851018
ExtensionDecl *ext) const {

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,16 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
220220
if (!checkConformance(proto))
221221
return false;
222222

223-
// Now check any additional bounds on 'Self' from the where clause.
224-
auto bounds = getSelfBoundsFromWhereClause(extension);
223+
// Source file and module file have different ways to get self bounds.
224+
// Source file extension will have trailing where clause which can avoid
225+
// computing a generic signature. Module file will not have
226+
// trailing where clause, so it will compute generic signature to get
227+
// self bounds which might result in slow performance.
228+
SelfBounds bounds;
229+
if (extension->getParentSourceFile() != nullptr)
230+
bounds = getSelfBoundsFromWhereClause(extension);
231+
else
232+
bounds = getSelfBoundsFromGenericSignature(extension);
225233
for (auto *decl : bounds.decls) {
226234
if (auto *proto = dyn_cast<ProtocolDecl>(decl)) {
227235
if (!checkConformance(proto))
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
public protocol DefaultsBridge {
2+
associatedtype T
3+
}
4+
5+
public struct BridgeStructSerializable<T: Codable>: DefaultsBridge {
6+
}
7+
8+
public struct BridgeStructRawRepresentable<T: RawRepresentable>: DefaultsBridge {
9+
}
10+
11+
public protocol DefaultsSerializable {
12+
associatedtype Bridge: DefaultsBridge
13+
static var _defaults: Bridge { get }
14+
}
15+
16+
public extension DefaultsSerializable where Self: Codable {
17+
static var _defaults: BridgeStructSerializable<Self> { return BridgeStructSerializable() }
18+
}
19+
20+
public extension DefaultsSerializable where Self: RawRepresentable {
21+
static var _defaults: BridgeStructRawRepresentable<Self> { return BridgeStructRawRepresentable() }
22+
}
23+
24+
public struct ModuleAFoo: Codable, DefaultsSerializable {
25+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -o %t/ModuleA.swiftmodule %S/Inputs/where_clause_across_module_boundaries_module.swift
3+
// RUN: %target-typecheck-verify-swift -I %t
4+
5+
// SR-15807:
6+
// Associated Type Inference fails across module boundaries
7+
// Self bounds from where clause cannot be accessed across modules.
8+
// This test is intended to test whether it can use generic signature to get self bounds.
9+
import ModuleA
10+
11+
struct ModuleBFoo: Codable, DefaultsSerializable {
12+
}
13+
14+
enum ModuleBBar: Int, Codable, DefaultsSerializable { // expected-error {{type 'ModuleBBar' does not conform to protocol 'DefaultsSerializable'}}
15+
case foo, bar
16+
}

0 commit comments

Comments
 (0)