Skip to content

Commit d18ecda

Browse files
committed
[GSB] Ensure that we don't build an invalid potential archetype.
Queries against the generic signature might use types that are ill-formed for that generic signature, e.g., because they refer to associated types of unrelated protocols. Detect such conditions to maintain GSB invariants that all potential archetypes in a well-formed generic signature are well-formed. Fixes the crash in SR-6797 / rdar://problem/36673825.
1 parent b1e37b9 commit d18ecda

File tree

4 files changed

+22
-3
lines changed

4 files changed

+22
-3
lines changed

include/swift/AST/GenericSignature.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
147147
/// requirements, first canonicalizing the types.
148148
static CanGenericSignature getCanonical(
149149
ArrayRef<GenericTypeParamType *> params,
150-
ArrayRef<Requirement> requirements);
150+
ArrayRef<Requirement> requirements,
151+
bool skipValidation = false);
151152

152153
/// Retrieve the generic parameters.
153154
ArrayRef<GenericTypeParamType *> getGenericParams() const {

lib/AST/GenericSignature.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ static unsigned getRequirementKindOrder(RequirementKind kind) {
150150

151151
CanGenericSignature GenericSignature::getCanonical(
152152
ArrayRef<GenericTypeParamType *> params,
153-
ArrayRef<Requirement> requirements) {
153+
ArrayRef<Requirement> requirements,
154+
bool skipValidation) {
154155
// Canonicalize the parameters and requirements.
155156
SmallVector<GenericTypeParamType*, 8> canonicalParams;
156157
canonicalParams.reserve(params.size());
@@ -172,10 +173,14 @@ CanGenericSignature GenericSignature::getCanonical(
172173
reqt.getLayoutConstraint()));
173174
}
174175

176+
(void)skipValidation;
175177
auto canSig = get(canonicalParams, canonicalRequirements,
176178
/*isKnownCanonical=*/true);
177179

178180
#ifndef NDEBUG
181+
if (skipValidation)
182+
return CanGenericSignature(canSig);
183+
179184
PrettyStackTraceGenericSignature debugStack("canonicalizing", canSig);
180185

181186
// Check that the signature is canonical.

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3026,6 +3026,12 @@ ResolvedType GenericSignatureBuilder::maybeResolveEquivalenceClass(
30263026
TypeDecl *nestedTypeDecl;
30273027
SmallVector<TypeDecl *, 4> concreteDecls;
30283028
if (auto assocType = depMemTy->getAssocType()) {
3029+
// Check whether this associated type references a protocol to which
3030+
// the base conforms. If not, it's unresolved.
3031+
if (baseEquivClass->conformsTo.find(assocType->getProtocol())
3032+
== baseEquivClass->conformsTo.end())
3033+
return ResolvedType::forUnresolved(baseEquivClass);
3034+
30293035
nestedTypeDecl = assocType;
30303036
} else {
30313037
nestedTypeDecl =

lib/Sema/TypeCheckDecl.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4885,8 +4885,15 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
48854885
llvm::errs() << "Requirement signature: ";
48864886
requirementsSig->print(llvm::errs());
48874887
llvm::errs() << "\n";
4888+
4889+
// Note: One cannot canonicalize a requirement signature, because
4890+
// requirement signatures are necessarily missing requirements.
48884891
llvm::errs() << "Canonical requirement signature: ";
4889-
requirementsSig->getCanonicalSignature()->print(llvm::errs());
4892+
auto canRequirementSig =
4893+
GenericSignature::getCanonical(requirementsSig->getGenericParams(),
4894+
requirementsSig->getRequirements(),
4895+
/*skipValidation=*/true);
4896+
canRequirementSig->print(llvm::errs());
48904897
llvm::errs() << "\n";
48914898
}
48924899
}

0 commit comments

Comments
 (0)