Skip to content

Commit 38bde33

Browse files
authored
Merge pull request #27172 from CodaFi/aliasing-artifacts-and-noise-reduction-techniques
Kill validateDeclForNameLookup Harder
2 parents 4fcef2b + 4f6951c commit 38bde33

36 files changed

+364
-288
lines changed

include/swift/AST/Decl.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2947,6 +2947,8 @@ class OpaqueTypeDecl : public GenericTypeDecl {
29472947
/// TypeAliasDecl's always have 'MetatypeType' type.
29482948
///
29492949
class TypeAliasDecl : public GenericTypeDecl {
2950+
friend class UnderlyingTypeRequest;
2951+
29502952
/// The location of the 'typealias' keyword
29512953
SourceLoc TypeAliasLoc;
29522954

@@ -2974,20 +2976,28 @@ class TypeAliasDecl : public GenericTypeDecl {
29742976

29752977
void setTypeEndLoc(SourceLoc e) { TypeEndLoc = e; }
29762978

2977-
TypeLoc &getUnderlyingTypeLoc() {
2978-
return UnderlyingTy;
2979+
/// Retrieve the TypeRepr corresponding to the parsed underlying type.
2980+
TypeRepr *getUnderlyingTypeRepr() const {
2981+
return UnderlyingTy.getTypeRepr();
29792982
}
2980-
const TypeLoc &getUnderlyingTypeLoc() const {
2981-
return UnderlyingTy;
2983+
void setUnderlyingTypeRepr(TypeRepr *repr) {
2984+
UnderlyingTy = repr;
29822985
}
2983-
2986+
2987+
/// Retrieve the interface type of the underlying type.
2988+
Type getUnderlyingType() const;
29842989
void setUnderlyingType(Type type);
29852990

29862991
/// For generic typealiases, return the unbound generic type.
29872992
UnboundGenericType *getUnboundGenericType() const;
29882993

2994+
/// Retrieve a sugared interface type containing the structure of the interface
2995+
/// type before any semantic validation has occured.
29892996
Type getStructuralType() const;
29902997

2998+
/// Set the interface type of this typealias declaration from the underlying type.
2999+
void computeType();
3000+
29913001
bool isCompatibilityAlias() const {
29923002
return Bits.TypeAliasDecl.IsCompatibilityAlias;
29933003
}

include/swift/AST/TypeCheckRequests.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,9 @@ class RequirementRequest :
434434
// Source location
435435
SourceLoc getNearestLoc() const;
436436

437+
// Cycle handling.
438+
void noteCycleStep(DiagnosticEngine &diags) const;
439+
437440
// Separate caching.
438441
bool isCached() const;
439442
Optional<Requirement> getCachedResult() const;
@@ -1120,6 +1123,9 @@ class InferredGenericSignatureRequest :
11201123
SourceLoc getNearestLoc() const {
11211124
return SourceLoc();
11221125
}
1126+
1127+
// Cycle handling.
1128+
void noteCycleStep(DiagnosticEngine &diags) const;
11231129
};
11241130

11251131
void simple_display(llvm::raw_ostream &out, const TypeLoc source);
@@ -1174,13 +1180,35 @@ class GenericSignatureRequest :
11741180
llvm::Expected<GenericSignature *>
11751181
evaluate(Evaluator &evaluator, GenericContext *value) const;
11761182

1177-
public:
1183+
public:
11781184
// Separate caching.
11791185
bool isCached() const { return true; }
11801186
Optional<GenericSignature *> getCachedResult() const;
11811187
void cacheResult(GenericSignature *value) const;
11821188
};
11831189

1190+
/// Compute the interface type of the underlying definition type of a typealias declaration.
1191+
class UnderlyingTypeRequest :
1192+
public SimpleRequest<UnderlyingTypeRequest,
1193+
Type(TypeAliasDecl *),
1194+
CacheKind::SeparatelyCached> {
1195+
public:
1196+
using SimpleRequest::SimpleRequest;
1197+
1198+
private:
1199+
friend SimpleRequest;
1200+
1201+
// Evaluation.
1202+
llvm::Expected<Type> evaluate(Evaluator &evaluator,
1203+
TypeAliasDecl *decl) const;
1204+
1205+
public:
1206+
// Caching.
1207+
bool isCached() const { return true; }
1208+
Optional<Type> getCachedResult() const;
1209+
void cacheResult(Type value) const;
1210+
};
1211+
11841212
// Allow AnyValue to compare two Type values, even though Type doesn't
11851213
// support ==.
11861214
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,7 @@ SWIFT_REQUEST(TypeChecker, SynthesizeAccessorRequest,
132132
SeparatelyCached, NoLocationInfo)
133133
SWIFT_REQUEST(TypeChecker, TypeCheckFunctionBodyUntilRequest,
134134
bool(AbstractFunctionDecl *, SourceLoc), Cached, NoLocationInfo)
135+
SWIFT_REQUEST(TypeChecker, UnderlyingTypeRequest, Type(TypeAliasDecl *),
136+
SeparatelyCached, NoLocationInfo)
135137
SWIFT_REQUEST(TypeChecker, USRGenerationRequest, std::string(const ValueDecl *),
136138
Cached, NoLocationInfo)

lib/AST/ASTDumper.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -617,9 +617,9 @@ namespace {
617617
void visitTypeAliasDecl(TypeAliasDecl *TAD) {
618618
printCommon(TAD, "typealias");
619619
PrintWithColorRAII(OS, TypeColor) << " type='";
620-
if (TAD->getUnderlyingTypeLoc().getType()) {
620+
if (auto underlying = TAD->getUnderlyingType()) {
621621
PrintWithColorRAII(OS, TypeColor)
622-
<< TAD->getUnderlyingTypeLoc().getType().getString();
622+
<< underlying.getString();
623623
} else {
624624
PrintWithColorRAII(OS, TypeColor) << "<<<unresolved>>>";
625625
}
@@ -3387,6 +3387,12 @@ namespace {
33873387
void visitTypeAliasType(TypeAliasType *T, StringRef label) {
33883388
printCommon(label, "type_alias_type");
33893389
printField("decl", T->getDecl()->printRef());
3390+
PrintWithColorRAII(OS, TypeColor) << " underlying='";
3391+
if (auto underlying = T->getSinglyDesugaredType()) {
3392+
PrintWithColorRAII(OS, TypeColor) << underlying->getString();
3393+
} else {
3394+
PrintWithColorRAII(OS, TypeColor) << "<<<unresolved>>>";
3395+
}
33903396
if (T->getParent())
33913397
printRec("parent", T->getParent());
33923398

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2277,7 +2277,7 @@ void PrintAST::visitTypeAliasDecl(TypeAliasDecl *decl) {
22772277
printGenericDeclGenericParams(decl);
22782278
});
22792279
bool ShouldPrint = true;
2280-
Type Ty = decl->getUnderlyingTypeLoc().getType();
2280+
Type Ty = decl->getUnderlyingType();
22812281

22822282
// If the underlying type is private, don't print it.
22832283
if (Options.SkipPrivateStdlibDecls && Ty && Ty.isPrivateStdlibType())
@@ -2295,7 +2295,7 @@ void PrintAST::visitTypeAliasDecl(TypeAliasDecl *decl) {
22952295
// preserving sugar.
22962296
llvm::SaveAndRestore<GenericEnvironment*> setGenericEnv(Options.GenericEnv,
22972297
decl->getGenericEnvironment());
2298-
printTypeLoc(decl->getUnderlyingTypeLoc());
2298+
printTypeLoc(TypeLoc(decl->getUnderlyingTypeRepr(), Ty));
22992299
printGenericDeclGenericRequirements(decl);
23002300
}
23012301
}

lib/AST/ASTWalker.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,10 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
232232
return true;
233233
}
234234

235-
return doIt(TAD->getUnderlyingTypeLoc());
235+
if (auto typerepr = TAD->getUnderlyingTypeRepr())
236+
if (doIt(typerepr))
237+
return true;
238+
return false;
236239
}
237240

238241
bool visitOpaqueTypeDecl(OpaqueTypeDecl *OTD) {

lib/AST/Decl.cpp

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3528,34 +3528,42 @@ SourceRange TypeAliasDecl::getSourceRange() const {
35283528
return { TypeAliasLoc, getNameLoc() };
35293529
}
35303530

3531-
void TypeAliasDecl::setUnderlyingType(Type underlying) {
3532-
setValidationToChecked();
3531+
void TypeAliasDecl::computeType() {
3532+
assert(!hasInterfaceType());
3533+
3534+
// Set the interface type of this declaration.
3535+
ASTContext &ctx = getASTContext();
3536+
3537+
auto *genericSig = getGenericSignature();
3538+
SubstitutionMap subs;
3539+
if (genericSig)
3540+
subs = genericSig->getIdentitySubstitutionMap();
35333541

3542+
Type parent;
3543+
auto parentDC = getDeclContext();
3544+
if (parentDC->isTypeContext())
3545+
parent = parentDC->getDeclaredInterfaceType();
3546+
auto sugaredType = TypeAliasType::get(this, parent, subs, getUnderlyingType());
3547+
setInterfaceType(MetatypeType::get(sugaredType, ctx));
3548+
}
3549+
3550+
Type TypeAliasDecl::getUnderlyingType() const {
3551+
return evaluateOrDefault(getASTContext().evaluator,
3552+
UnderlyingTypeRequest{const_cast<TypeAliasDecl *>(this)},
3553+
Type());
3554+
}
3555+
3556+
void TypeAliasDecl::setUnderlyingType(Type underlying) {
35343557
// lldb creates global typealiases containing archetypes
35353558
// sometimes...
35363559
if (underlying->hasArchetype() && isGenericContext())
35373560
underlying = underlying->mapTypeOutOfContext();
3538-
UnderlyingTy.setType(underlying);
3539-
3540-
// FIXME -- if we already have an interface type, we're changing the
3541-
// underlying type. See the comment in the ProtocolDecl case of
3542-
// validateDecl().
3543-
if (!hasInterfaceType()) {
3544-
// Set the interface type of this declaration.
3545-
ASTContext &ctx = getASTContext();
3546-
3547-
auto *genericSig = getGenericSignature();
3548-
SubstitutionMap subs;
3549-
if (genericSig)
3550-
subs = genericSig->getIdentitySubstitutionMap();
3551-
3552-
Type parent;
3553-
auto parentDC = getDeclContext();
3554-
if (parentDC->isTypeContext())
3555-
parent = parentDC->getDeclaredInterfaceType();
3556-
auto sugaredType = TypeAliasType::get(this, parent, subs, underlying);
3557-
setInterfaceType(MetatypeType::get(sugaredType, ctx));
3558-
}
3561+
getASTContext().evaluator.cacheOutput(
3562+
StructuralTypeRequest{const_cast<TypeAliasDecl *>(this)},
3563+
std::move(underlying));
3564+
getASTContext().evaluator.cacheOutput(
3565+
UnderlyingTypeRequest{const_cast<TypeAliasDecl *>(this)},
3566+
std::move(underlying));
35593567
}
35603568

35613569
UnboundGenericType *TypeAliasDecl::getUnboundGenericType() const {
@@ -3572,12 +3580,10 @@ UnboundGenericType *TypeAliasDecl::getUnboundGenericType() const {
35723580
}
35733581

35743582
Type TypeAliasDecl::getStructuralType() const {
3575-
assert(!getGenericParams());
3576-
35773583
auto &context = getASTContext();
3578-
return evaluateOrDefault(context.evaluator,
3579-
StructuralTypeRequest { const_cast<TypeAliasDecl *>(this) },
3580-
Type());
3584+
return evaluateOrDefault(
3585+
context.evaluator,
3586+
StructuralTypeRequest{const_cast<TypeAliasDecl *>(this)}, Type());
35813587
}
35823588

35833589
Type AbstractTypeParamDecl::getSuperclass() const {

lib/AST/DiagnosticEngine.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ static bool isInterestingTypealias(Type type) {
380380
// Compatibility aliases are only interesting insofar as their underlying
381381
// types are interesting.
382382
if (aliasDecl->isCompatibilityAlias()) {
383-
auto underlyingTy = aliasDecl->getUnderlyingTypeLoc().getType();
383+
auto underlyingTy = aliasDecl->getUnderlyingType();
384384
return isInterestingTypealias(underlyingTy);
385385
}
386386

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3786,10 +3786,13 @@ PotentialArchetype *GenericSignatureBuilder::realizePotentialArchetype(
37863786

37873787
static Type getStructuralType(TypeDecl *typeDecl) {
37883788
if (auto typealias = dyn_cast<TypeAliasDecl>(typeDecl)) {
3789-
if (auto resolved = typealias->getUnderlyingTypeLoc().getType())
3790-
return resolved;
3791-
3792-
return typealias->getStructuralType();
3789+
// When we're computing requirement signatures, the structural type
3790+
// suffices. Otherwise we'll potentially try to validate incomplete
3791+
// requirements.
3792+
auto *proto = dyn_cast_or_null<ProtocolDecl>(typealias->getDeclContext()->getAsDecl());
3793+
if (proto && proto->isComputingRequirementSignature())
3794+
return typealias->getStructuralType();
3795+
return typealias->getUnderlyingType();
37933796
}
37943797

37953798
return typeDecl->getDeclaredInterfaceType();
@@ -4197,11 +4200,10 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
41974200
out << start;
41984201
out << type->getFullName() << " == ";
41994202
if (auto typealias = dyn_cast<TypeAliasDecl>(type)) {
4200-
if (auto underlyingTypeRepr =
4201-
typealias->getUnderlyingTypeLoc().getTypeRepr())
4203+
if (auto underlyingTypeRepr = typealias->getUnderlyingTypeRepr())
42024204
underlyingTypeRepr->print(out);
42034205
else
4204-
typealias->getUnderlyingTypeLoc().getType().print(out);
4206+
typealias->getUnderlyingType().print(out);
42054207
} else {
42064208
type->print(out);
42074209
}

lib/AST/Module.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ void BuiltinUnit::LookupCache::lookupValue(
103103
const_cast<BuiltinUnit*>(&M));
104104
TAD->setUnderlyingType(Ty);
105105
TAD->setAccess(AccessLevel::Public);
106+
TAD->setValidationToChecked();
107+
TAD->computeType();
106108
Entry = TAD;
107109
}
108110
}

lib/AST/NameLookup.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,7 +1814,7 @@ resolveTypeDeclsToNominal(Evaluator &evaluator,
18141814
// Recognize Swift.AnyObject directly.
18151815
if (typealias->getName().is("AnyObject")) {
18161816
// TypeRepr version: Builtin.AnyObject
1817-
if (auto typeRepr = typealias->getUnderlyingTypeLoc().getTypeRepr()) {
1817+
if (auto typeRepr = typealias->getUnderlyingTypeRepr()) {
18181818
if (auto compound = dyn_cast<CompoundIdentTypeRepr>(typeRepr)) {
18191819
auto components = compound->getComponents();
18201820
if (components.size() == 2 &&
@@ -1826,9 +1826,10 @@ resolveTypeDeclsToNominal(Evaluator &evaluator,
18261826
}
18271827

18281828
// Type version: an empty class-bound existential.
1829-
if (auto type = typealias->getUnderlyingTypeLoc().getType()) {
1830-
if (type->isAnyObject())
1831-
anyObject = true;
1829+
if (typealias->hasInterfaceType()) {
1830+
if (auto type = typealias->getUnderlyingType())
1831+
if (type->isAnyObject())
1832+
anyObject = true;
18321833
}
18331834
}
18341835

@@ -2092,15 +2093,15 @@ DirectlyReferencedTypeDecls UnderlyingTypeDeclsReferencedRequest::evaluate(
20922093
Evaluator &evaluator,
20932094
TypeAliasDecl *typealias) const {
20942095
// Prefer syntactic information when we have it.
2095-
if (auto typeRepr = typealias->getUnderlyingTypeLoc().getTypeRepr()) {
2096+
if (auto typeRepr = typealias->getUnderlyingTypeRepr()) {
20962097
return directReferencesForTypeRepr(evaluator, typealias->getASTContext(),
20972098
typeRepr, typealias);
20982099
}
20992100

21002101
// Fall back to semantic types.
21012102
// FIXME: In the long run, we shouldn't need this. Non-syntactic results
21022103
// should be cached.
2103-
if (auto type = typealias->getUnderlyingTypeLoc().getType()) {
2104+
if (auto type = typealias->getUnderlyingType()) {
21042105
return directReferencesForType(type);
21052106
}
21062107

lib/AST/TypeCheckRequests.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,14 @@ SourceLoc RequirementRequest::getNearestLoc() const {
364364
return owner.getLoc();
365365
}
366366

367+
void RequirementRequest::noteCycleStep(DiagnosticEngine &diags) const {
368+
// For now, the GSB does a better job of describing the exact structure of
369+
// the cycle.
370+
//
371+
// FIXME: We should consider merging the circularity handling the GSB does
372+
// into this request. See rdar://55263708
373+
}
374+
367375
MutableArrayRef<RequirementRepr> WhereClauseOwner::getRequirements() const {
368376
if (auto genericParams = source.dyn_cast<GenericParamList *>()) {
369377
return genericParams->getRequirements();
@@ -822,3 +830,32 @@ void GenericSignatureRequest::cacheResult(GenericSignature *value) const {
822830
auto *GC = std::get<0>(getStorage());
823831
GC->GenericSigAndBit.setPointerAndInt(value, true);
824832
}
833+
834+
//----------------------------------------------------------------------------//
835+
// GenericSignatureRequest computation.
836+
//----------------------------------------------------------------------------//
837+
838+
void InferredGenericSignatureRequest::noteCycleStep(DiagnosticEngine &d) const {
839+
// For now, the GSB does a better job of describing the exact structure of
840+
// the cycle.
841+
//
842+
// FIXME: We should consider merging the circularity handling the GSB does
843+
// into this request. See rdar://55263708
844+
}
845+
846+
//----------------------------------------------------------------------------//
847+
// IsImplicitlyUnwrappedOptionalRequest computation.
848+
//----------------------------------------------------------------------------//
849+
850+
Optional<Type>
851+
UnderlyingTypeRequest::getCachedResult() const {
852+
auto *typeAlias = std::get<0>(getStorage());
853+
if (auto type = typeAlias->UnderlyingTy.getType())
854+
return type;
855+
return None;
856+
}
857+
858+
void UnderlyingTypeRequest::cacheResult(Type value) const {
859+
auto *typeAlias = std::get<0>(getStorage());
860+
typeAlias->UnderlyingTy.setType(value);
861+
}

lib/ClangImporter/ClangImporter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2659,7 +2659,7 @@ void ClangModuleUnit::getTopLevelDecls(SmallVectorImpl<Decl*> &results) const {
26592659
auto alias = dyn_cast<TypeAliasDecl>(importedDecl);
26602660
if (!alias || !alias->isCompatibilityAlias()) continue;
26612661

2662-
auto aliasedTy = alias->getUnderlyingTypeLoc().getType();
2662+
auto aliasedTy = alias->getUnderlyingType();
26632663
ext = nullptr;
26642664
importedDecl = nullptr;
26652665

0 commit comments

Comments
 (0)