Skip to content

Commit b78ed53

Browse files
authored
Merge pull request swiftlang#30800 from CodaFi/erase-install
[Serialization] Lazily Resolve the Eraser Type of @ _typeEraser
2 parents 5eea0ae + bce1dd6 commit b78ed53

17 files changed

+193
-42
lines changed

include/swift/AST/Attr.h

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,16 +1111,58 @@ class DynamicReplacementAttr final
11111111
/// The \c @_typeEraser(TypeEraserType) attribute.
11121112
class TypeEraserAttr final : public DeclAttribute {
11131113
TypeLoc TypeEraserLoc;
1114-
public:
1115-
TypeEraserAttr(SourceLoc atLoc, SourceRange range, TypeLoc typeEraserLoc)
1114+
LazyMemberLoader *Resolver;
1115+
uint64_t ResolverContextData;
1116+
1117+
friend class ResolveTypeEraserTypeRequest;
1118+
1119+
TypeEraserAttr(SourceLoc atLoc, SourceRange range, TypeLoc typeEraserLoc,
1120+
LazyMemberLoader *Resolver, uint64_t Data)
11161121
: DeclAttribute(DAK_TypeEraser, atLoc, range, /*Implicit=*/false),
1117-
TypeEraserLoc(typeEraserLoc) {}
1122+
TypeEraserLoc(typeEraserLoc),
1123+
Resolver(Resolver), ResolverContextData(Data) {}
11181124

1119-
const TypeLoc &getTypeEraserLoc() const { return TypeEraserLoc; }
1120-
TypeLoc &getTypeEraserLoc() { return TypeEraserLoc; }
1125+
public:
1126+
static TypeEraserAttr *create(ASTContext &ctx,
1127+
SourceLoc atLoc, SourceRange range,
1128+
TypeLoc typeEraserLoc);
1129+
1130+
static TypeEraserAttr *create(ASTContext &ctx,
1131+
LazyMemberLoader *Resolver,
1132+
uint64_t Data);
1133+
1134+
/// Retrieve the parsed type repr for this attribute, if it
1135+
/// was parsed. Else returns \c nullptr.
1136+
TypeRepr *getParsedTypeEraserTypeRepr() const {
1137+
return TypeEraserLoc.getTypeRepr();
1138+
}
11211139

1140+
/// Retrieve the parsed location for this attribute, if it was parsed.
1141+
SourceLoc getLoc() const {
1142+
return TypeEraserLoc.getLoc();
1143+
}
1144+
1145+
/// Retrieve the resolved type of this attribute if it has been resolved by a
1146+
/// successful call to \c getResolvedType(). Otherwise,
1147+
/// returns \c Type()
1148+
///
1149+
/// This entrypoint is only suitable for syntactic clients like the
1150+
/// AST printer. Semantic clients should use \c getResolvedType() instead.
1151+
Type getTypeWithoutResolving() const {
1152+
return TypeEraserLoc.getType();
1153+
}
1154+
1155+
/// Returns \c true if the type eraser type has a valid implementation of the
1156+
/// erasing initializer for the given protocol.
11221157
bool hasViableTypeEraserInit(ProtocolDecl *protocol) const;
11231158

1159+
/// Resolves the type of this attribute.
1160+
///
1161+
/// This entrypoint is suitable for semantic clients like the
1162+
/// expression checker. Syntactic clients should use
1163+
/// \c getTypeWithoutResolving() instead.
1164+
Type getResolvedType(const ProtocolDecl *PD) const;
1165+
11241166
static bool classof(const DeclAttribute *DA) {
11251167
return DA->getKind() == DAK_TypeEraser;
11261168
}

include/swift/AST/LazyResolver.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ class alignas(void*) LazyMemberLoader {
105105
virtual ValueDecl *
106106
loadDynamicallyReplacedFunctionDecl(const DynamicReplacementAttr *DRA,
107107
uint64_t contextData) = 0;
108+
109+
/// Returns the type for a given @_typeEraser() attribute.
110+
virtual Type loadTypeEraserType(const TypeEraserAttr *TRA,
111+
uint64_t contextData) = 0;
108112
};
109113

110114
/// A class that can lazily load conformances from a serialized format.

include/swift/AST/TypeCheckRequests.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2260,6 +2260,27 @@ class CheckRedeclarationRequest
22602260
evaluator::SideEffect) const;
22612261
};
22622262

2263+
class ResolveTypeEraserTypeRequest
2264+
: public SimpleRequest<ResolveTypeEraserTypeRequest,
2265+
Type (ProtocolDecl *, TypeEraserAttr *),
2266+
RequestFlags::SeparatelyCached> {
2267+
public:
2268+
using SimpleRequest::SimpleRequest;
2269+
2270+
private:
2271+
friend SimpleRequest;
2272+
2273+
// Evaluation.
2274+
Type evaluate(Evaluator &evaluator, ProtocolDecl *PD,
2275+
TypeEraserAttr *attr) const;
2276+
2277+
public:
2278+
// Separate caching.
2279+
bool isCached() const { return true; }
2280+
Optional<Type> getCachedResult() const;
2281+
void cacheResult(Type value) const;
2282+
};
2283+
22632284
// Allow AnyValue to compare two Type values, even though Type doesn't
22642285
// support ==.
22652286
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ SWIFT_REQUEST(TypeChecker, PreCheckFunctionBuilderRequest,
213213
SWIFT_REQUEST(TypeChecker, ResolveImplicitMemberRequest,
214214
evaluator::SideEffect(NominalTypeDecl *, ImplicitMemberAction),
215215
Uncached, NoLocationInfo)
216+
SWIFT_REQUEST(TypeChecker, ResolveTypeEraserTypeRequest,
217+
Type(ProtocolDecl *, TypeEraserAttr *),
218+
SeparatelyCached, NoLocationInfo)
216219
SWIFT_REQUEST(TypeChecker, SPIGroupsRequest,
217220
llvm::ArrayRef<Identifier>(Decl *),
218221
Cached, NoLocationInfo)

lib/AST/Attr.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,11 +1006,11 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
10061006
Printer.printAttrName("@_typeEraser");
10071007
Printer << "(";
10081008
Printer.callPrintNamePre(PrintNameContext::Attribute);
1009-
auto typeLoc = cast<TypeEraserAttr>(this)->getTypeEraserLoc();
1010-
if (auto type = typeLoc.getType())
1011-
type->print(Printer, Options);
1009+
auto *attr = cast<TypeEraserAttr>(this);
1010+
if (auto *repr = attr->getParsedTypeEraserTypeRepr())
1011+
repr->print(Printer, Options);
10121012
else
1013-
typeLoc.getTypeRepr()->print(Printer, Options);
1013+
attr->getTypeWithoutResolving()->print(Printer, Options);
10141014
Printer.printNamePost(PrintNameContext::Attribute);
10151015
Printer << ")";
10161016
break;
@@ -1381,6 +1381,19 @@ SourceLoc DynamicReplacementAttr::getRParenLoc() const {
13811381
return getTrailingLocations()[1];
13821382
}
13831383

1384+
TypeEraserAttr *TypeEraserAttr::create(ASTContext &ctx,
1385+
SourceLoc atLoc, SourceRange range,
1386+
TypeLoc typeEraserLoc) {
1387+
return new (ctx) TypeEraserAttr(atLoc, range, typeEraserLoc, nullptr, 0);
1388+
}
1389+
1390+
TypeEraserAttr *TypeEraserAttr::create(ASTContext &ctx,
1391+
LazyMemberLoader *Resolver,
1392+
uint64_t Data) {
1393+
return new (ctx) TypeEraserAttr(SourceLoc(), SourceRange(),
1394+
TypeLoc(), Resolver, Data);
1395+
}
1396+
13841397
bool
13851398
TypeEraserAttr::hasViableTypeEraserInit(ProtocolDecl *protocol) const {
13861399
return evaluateOrDefault(protocol->getASTContext().evaluator,
@@ -1389,6 +1402,15 @@ TypeEraserAttr::hasViableTypeEraserInit(ProtocolDecl *protocol) const {
13891402
false);
13901403
}
13911404

1405+
Type TypeEraserAttr::getResolvedType(const ProtocolDecl *PD) const {
1406+
auto &ctx = PD->getASTContext();
1407+
return evaluateOrDefault(ctx.evaluator,
1408+
ResolveTypeEraserTypeRequest{
1409+
const_cast<ProtocolDecl *>(PD),
1410+
const_cast<TypeEraserAttr *>(this)},
1411+
ErrorType::get(ctx));
1412+
}
1413+
13921414
AvailableAttr *
13931415
AvailableAttr::createPlatformAgnostic(ASTContext &C,
13941416
StringRef Message,

lib/AST/DeclContext.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1080,11 +1080,12 @@ bool DeclContext::isClassConstrainedProtocolExtension() const {
10801080

10811081
SourceLoc swift::extractNearestSourceLoc(const DeclContext *dc) {
10821082
switch (dc->getContextKind()) {
1083+
case DeclContextKind::Module:
1084+
return SourceLoc();
10831085
case DeclContextKind::AbstractFunctionDecl:
10841086
case DeclContextKind::EnumElementDecl:
10851087
case DeclContextKind::ExtensionDecl:
10861088
case DeclContextKind::GenericTypeDecl:
1087-
case DeclContextKind::Module:
10881089
case DeclContextKind::SubscriptDecl:
10891090
case DeclContextKind::TopLevelCodeDecl:
10901091
return extractNearestSourceLoc(dc->getAsDecl());

lib/AST/TypeCheckRequests.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,23 @@ void LookupAllConformancesInContextRequest::writeDependencySink(
13711371
}
13721372
}
13731373

1374+
//----------------------------------------------------------------------------//
1375+
// ResolveTypeEraserTypeRequest computation.
1376+
//----------------------------------------------------------------------------//
1377+
1378+
Optional<Type> ResolveTypeEraserTypeRequest::getCachedResult() const {
1379+
auto ty = std::get<1>(getStorage())->TypeEraserLoc.getType();
1380+
if (ty.isNull()) {
1381+
return None;
1382+
}
1383+
return ty;
1384+
}
1385+
1386+
void ResolveTypeEraserTypeRequest::cacheResult(Type value) const {
1387+
assert(value && "Resolved type erasure type to null type!");
1388+
std::get<1>(getStorage())->TypeEraserLoc.setType(value);
1389+
}
1390+
13741391
//----------------------------------------------------------------------------//
13751392
// TypeCheckSourceFileRequest computation.
13761393
//----------------------------------------------------------------------------//

lib/ClangImporter/ImporterImpl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,6 +1290,11 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
12901290
llvm_unreachable("unimplemented for ClangImporter");
12911291
}
12921292

1293+
Type loadTypeEraserType(const TypeEraserAttr *TRA,
1294+
uint64_t contextData) override {
1295+
llvm_unreachable("unimplemented for ClangImporter");
1296+
}
1297+
12931298
void loadRequirementSignature(const ProtocolDecl *decl, uint64_t contextData,
12941299
SmallVectorImpl<Requirement> &reqs) override {
12951300
llvm_unreachable("unimplemented for ClangImporter");

lib/Parse/ParseDecl.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,8 +2209,7 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
22092209
if (invalid)
22102210
return false;
22112211

2212-
Attributes.add(new (Context)
2213-
TypeEraserAttr(AtLoc, {Loc, RParenLoc}, ErasedType.get()));
2212+
Attributes.add(TypeEraserAttr::create(Context, AtLoc, {Loc, RParenLoc}, ErasedType.get()));
22142213
break;
22152214
}
22162215

lib/Sema/ConstraintSystem.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4103,11 +4103,13 @@ Expr *ConstraintSystem::buildTypeErasedExpr(Expr *expr, DeclContext *dc,
41034103
if (protocols.size() != 1)
41044104
return expr;
41054105

4106-
auto *attr = protocols.front()->getAttrs().getAttribute<TypeEraserAttr>();
4106+
auto *PD = protocols.front();
4107+
auto *attr = PD->getAttrs().getAttribute<TypeEraserAttr>();
41074108
if (!attr)
41084109
return expr;
41094110

4110-
auto typeEraser = attr->getTypeEraserLoc().getType();
4111+
auto typeEraser = attr->getResolvedType(PD);
4112+
assert(typeEraser && "Failed to resolve eraser type!");
41114113
auto &ctx = dc->getASTContext();
41124114
return CallExpr::createImplicit(ctx,
41134115
TypeExpr::createImplicit(typeEraser, ctx),

0 commit comments

Comments
 (0)