Skip to content

Commit e334e5d

Browse files
committed
AST: Convert ValueDecl::getOpaqueResultTypeDecl() into a request
Instead of depending on a prior call to setOpaqueResultTypeDecl(), we can instead just build the decl if we need one.
1 parent b32e82c commit e334e5d

File tree

11 files changed

+118
-110
lines changed

11 files changed

+118
-110
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ SWIFT_TYPEID_NAMED(InfixOperatorDecl *, InfixOperatorDecl)
3333
SWIFT_TYPEID_NAMED(IterableDeclContext *, IterableDeclContext)
3434
SWIFT_TYPEID_NAMED(ModuleDecl *, ModuleDecl)
3535
SWIFT_TYPEID_NAMED(NominalTypeDecl *, NominalTypeDecl)
36+
SWIFT_TYPEID_NAMED(OpaqueTypeDecl *, OpaqueTypeDecl)
3637
SWIFT_TYPEID_NAMED(OperatorDecl *, OperatorDecl)
3738
SWIFT_TYPEID_NAMED(Optional<PropertyWrapperMutability>,
3839
PropertyWrapperMutability)

include/swift/AST/ASTTypeIDs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class IterableDeclContext;
3434
class ModuleDecl;
3535
class NominalTypeDecl;
3636
class OperatorDecl;
37+
class OpaqueTypeDecl;
3738
class PrecedenceGroupDecl;
3839
struct PropertyWrapperBackingPropertyInfo;
3940
struct PropertyWrapperTypeInfo;

include/swift/AST/Decl.h

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2764,12 +2764,6 @@ class ValueDecl : public Decl {
27642764
/// Get the representative for this value's opaque result type, if it has one.
27652765
OpaqueReturnTypeRepr *getOpaqueResultTypeRepr() const;
27662766

2767-
/// Set the opaque return type decl for this decl.
2768-
///
2769-
/// `this` must be of a decl type that supports opaque return types, and
2770-
/// must not have previously had an opaque result type set.
2771-
void setOpaqueResultTypeDecl(OpaqueTypeDecl *D);
2772-
27732767
/// Retrieve the attribute associating this declaration with a
27742768
/// function builder, if there is one.
27752769
CustomAttr *getAttachedFunctionBuilder() const;
@@ -4530,8 +4524,6 @@ class AbstractStorageDecl : public ValueDecl {
45304524
Bits.AbstractStorageDecl.IsStatic = IsStatic;
45314525
}
45324526

4533-
OpaqueTypeDecl *OpaqueReturn = nullptr;
4534-
45354527
public:
45364528

45374529
/// Should this declaration be treated as if annotated with transparent
@@ -4789,14 +4781,6 @@ class AbstractStorageDecl : public ValueDecl {
47894781

47904782
bool hasAnyDynamicReplacementAccessors() const;
47914783

4792-
OpaqueTypeDecl *getOpaqueResultTypeDecl() const {
4793-
return OpaqueReturn;
4794-
}
4795-
void setOpaqueResultTypeDecl(OpaqueTypeDecl *decl) {
4796-
assert(!OpaqueReturn && "already has opaque type decl");
4797-
OpaqueReturn = decl;
4798-
}
4799-
48004784
// Implement isa/cast/dyncast/etc.
48014785
static bool classof(const Decl *D) {
48024786
return D->getKind() >= DeclKind::First_AbstractStorageDecl &&
@@ -5982,8 +5966,6 @@ class FuncDecl : public AbstractFunctionDecl {
59825966

59835967
TypeLoc FnRetType;
59845968

5985-
OpaqueTypeDecl *OpaqueReturn = nullptr;
5986-
59875969
protected:
59885970
FuncDecl(DeclKind Kind,
59895971
SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
@@ -6129,15 +6111,7 @@ class FuncDecl : public AbstractFunctionDecl {
61296111
}
61306112

61316113
OperatorDecl *getOperatorDecl() const;
6132-
6133-
OpaqueTypeDecl *getOpaqueResultTypeDecl() const {
6134-
return OpaqueReturn;
6135-
}
6136-
void setOpaqueResultTypeDecl(OpaqueTypeDecl *decl) {
6137-
assert(!OpaqueReturn && "already has opaque type decl");
6138-
OpaqueReturn = decl;
6139-
}
6140-
6114+
61416115
/// Returns true if the function is forced to be statically dispatched.
61426116
bool hasForcedStaticDispatch() const {
61436117
return Bits.FuncDecl.ForcedStaticDispatch;

include/swift/AST/TypeCheckRequests.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,7 @@ class GenericSignatureRequest :
11881188
void cacheResult(GenericSignature value) const;
11891189
};
11901190

1191-
/// Compute the interface type of the underlying definition type of a typealias declaration.
1191+
/// Compute the underlying interface type of a typealias.
11921192
class UnderlyingTypeRequest :
11931193
public SimpleRequest<UnderlyingTypeRequest,
11941194
Type(TypeAliasDecl *),
@@ -1211,6 +1211,7 @@ class UnderlyingTypeRequest :
12111211
void diagnoseCycle(DiagnosticEngine &diags) const;
12121212
};
12131213

1214+
/// Looks up the precedence group of an operator declaration.
12141215
class OperatorPrecedenceGroupRequest
12151216
: public SimpleRequest<OperatorPrecedenceGroupRequest,
12161217
PrecedenceGroupDecl *(InfixOperatorDecl *),
@@ -1272,6 +1273,25 @@ class IsABICompatibleOverrideRequest
12721273
bool isCached() const { return true; }
12731274
};
12741275

1276+
/// Builds an opaque result type for a declaration.
1277+
class OpaqueResultTypeRequest
1278+
: public SimpleRequest<OpaqueResultTypeRequest,
1279+
OpaqueTypeDecl *(ValueDecl *),
1280+
CacheKind::Cached> {
1281+
public:
1282+
using SimpleRequest::SimpleRequest;
1283+
1284+
private:
1285+
friend SimpleRequest;
1286+
1287+
llvm::Expected<OpaqueTypeDecl *>
1288+
evaluate(Evaluator &evaluator, ValueDecl *VD) const;
1289+
1290+
public:
1291+
// Caching.
1292+
bool isCached() const { return true; }
1293+
};
1294+
12751295
// Allow AnyValue to compare two Type values, even though Type doesn't
12761296
// support ==.
12771297
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ SWIFT_REQUEST(TypeChecker, MangleLocalTypeDeclRequest,
8888
SWIFT_REQUEST(TypeChecker, OpaqueReadOwnershipRequest,
8989
OpaqueReadOwnership(AbstractStorageDecl *), SeparatelyCached,
9090
NoLocationInfo)
91+
SWIFT_REQUEST(TypeChecker, OpaqueResultTypeRequest,
92+
OpaqueTypeDecl *(ValueDecl *),
93+
Cached, NoLocationInfo)
9194
SWIFT_REQUEST(TypeChecker, OperatorPrecedenceGroupRequest,
9295
PrecedenceGroupDecl *(PrecedenceGroupDecl *),
9396
Cached, NoLocationInfo)

lib/AST/Decl.cpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2580,7 +2580,22 @@ void ValueDecl::setOverriddenDecls(ArrayRef<ValueDecl *> overridden) {
25802580
OpaqueReturnTypeRepr *ValueDecl::getOpaqueResultTypeRepr() const {
25812581
TypeLoc returnLoc;
25822582
if (auto *VD = dyn_cast<VarDecl>(this)) {
2583-
returnLoc = VD->getTypeLoc();
2583+
if (auto *P = VD->getParentPattern()) {
2584+
while (auto *PP = dyn_cast<ParenPattern>(P))
2585+
P = PP->getSubPattern();
2586+
2587+
if (auto *TP = dyn_cast<TypedPattern>(P)) {
2588+
P = P->getSemanticsProvidingPattern();
2589+
if (auto *NP = dyn_cast<NamedPattern>(P)) {
2590+
assert(NP->getDecl() == VD);
2591+
(void) NP;
2592+
2593+
returnLoc = TP->getTypeLoc();
2594+
}
2595+
}
2596+
} else {
2597+
returnLoc = VD->getTypeLoc();
2598+
}
25842599
} else if (auto *FD = dyn_cast<FuncDecl>(this)) {
25852600
returnLoc = FD->getBodyResultTypeLoc();
25862601
} else if (auto *SD = dyn_cast<SubscriptDecl>(this)) {
@@ -2591,23 +2606,12 @@ OpaqueReturnTypeRepr *ValueDecl::getOpaqueResultTypeRepr() const {
25912606
}
25922607

25932608
OpaqueTypeDecl *ValueDecl::getOpaqueResultTypeDecl() const {
2594-
if (auto func = dyn_cast<FuncDecl>(this)) {
2595-
return func->getOpaqueResultTypeDecl();
2596-
} else if (auto storage = dyn_cast<AbstractStorageDecl>(this)) {
2597-
return storage->getOpaqueResultTypeDecl();
2598-
} else {
2609+
if (getOpaqueResultTypeRepr() == nullptr)
25992610
return nullptr;
2600-
}
2601-
}
26022611

2603-
void ValueDecl::setOpaqueResultTypeDecl(OpaqueTypeDecl *D) {
2604-
if (auto func = dyn_cast<FuncDecl>(this)) {
2605-
func->setOpaqueResultTypeDecl(D);
2606-
} else if (auto storage = dyn_cast<AbstractStorageDecl>(this)){
2607-
storage->setOpaqueResultTypeDecl(D);
2608-
} else {
2609-
llvm_unreachable("decl does not support opaque result types");
2610-
}
2612+
return evaluateOrDefault(getASTContext().evaluator,
2613+
OpaqueResultTypeRequest{const_cast<ValueDecl *>(this)},
2614+
nullptr);
26112615
}
26122616

26132617
bool ValueDecl::isObjC() const {

lib/Sema/TypeCheckDecl.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3793,22 +3793,25 @@ static Type buildAddressorResultType(TypeChecker &TC,
37933793
}
37943794

37953795

3796-
static void validateResultType(TypeChecker &TC,
3797-
ValueDecl *decl, ParameterList *params,
3798-
TypeLoc &resultTyLoc,
3799-
TypeResolution resolution) {
3796+
static void validateResultType(ValueDecl *decl,
3797+
TypeLoc &resultTyLoc) {
38003798
// Nothing to do if there's no result type loc to set into.
38013799
if (resultTyLoc.isNull())
38023800
return;
38033801

38043802
// Check the result type. It is allowed to be opaque.
3805-
if (auto opaqueTy =
3806-
dyn_cast_or_null<OpaqueReturnTypeRepr>(resultTyLoc.getTypeRepr())) {
3807-
// Create the decl and type for it.
3803+
if (decl->getOpaqueResultTypeRepr()) {
3804+
auto *opaqueDecl = decl->getOpaqueResultTypeDecl();
38083805
resultTyLoc.setType(
3809-
TC.getOrCreateOpaqueResultType(resolution, decl, opaqueTy));
3806+
opaqueDecl
3807+
? opaqueDecl->getDeclaredInterfaceType()
3808+
: ErrorType::get(decl->getASTContext()));
38103809
} else {
3811-
TypeChecker::validateType(TC.Context, resultTyLoc, resolution,
3810+
auto *dc = decl->getInnermostDeclContext();
3811+
auto resolution = TypeResolution::forInterface(
3812+
dc, dc->getGenericSignatureOfContext());
3813+
TypeChecker::validateType(dc->getASTContext(),
3814+
resultTyLoc, resolution,
38123815
TypeResolverContext::FunctionResult);
38133816
}
38143817
}
@@ -4081,8 +4084,7 @@ void TypeChecker::validateDecl(ValueDecl *D) {
40814084
FD->getGenericSignature());
40824085
typeCheckParameterList(FD->getParameters(), resolution,
40834086
TypeResolverContext::AbstractFunctionDecl);
4084-
validateResultType(*this, FD, FD->getParameters(),
4085-
FD->getBodyResultTypeLoc(), resolution);
4087+
validateResultType(FD, FD->getBodyResultTypeLoc());
40864088
// FIXME: Roll all of this interface type computation into a request.
40874089
FD->computeType();
40884090

@@ -4152,8 +4154,7 @@ void TypeChecker::validateDecl(ValueDecl *D) {
41524154
auto res = TypeResolution::forInterface(SD, SD->getGenericSignature());
41534155
typeCheckParameterList(SD->getIndices(), res,
41544156
TypeResolverContext::SubscriptDecl);
4155-
validateResultType(*this, SD, SD->getIndices(),
4156-
SD->getElementTypeLoc(), res);
4157+
validateResultType(SD, SD->getElementTypeLoc());
41574158
SD->computeType();
41584159

41594160
if (SD->getOpaqueResultTypeDecl()) {

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -83,43 +83,47 @@ TypeChecker::gatherGenericParamBindingsText(
8383

8484
/// Get the opaque type representing the return type of a declaration, or
8585
/// create it if it does not yet exist.
86-
Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution,
87-
ValueDecl *originatingDecl,
88-
OpaqueReturnTypeRepr *repr) {
86+
llvm::Expected<OpaqueTypeDecl *>
87+
OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
88+
ValueDecl *originatingDecl) const {
89+
auto *repr = originatingDecl->getOpaqueResultTypeRepr();
90+
assert(repr && "Declaration does not have an opaque result type");
91+
auto *dc = originatingDecl->getInnermostDeclContext();
92+
auto &ctx = dc->getASTContext();
93+
8994
// Protocol requirements can't have opaque return types.
9095
//
9196
// TODO: Maybe one day we could treat this as sugar for an associated type.
9297
if (isa<ProtocolDecl>(originatingDecl->getDeclContext())
9398
&& originatingDecl->isProtocolRequirement()) {
94-
99+
95100
SourceLoc fixitLoc;
96101
if (auto vd = dyn_cast<VarDecl>(originatingDecl)) {
97102
fixitLoc = vd->getParentPatternBinding()->getStartLoc();
98103
} else {
99104
fixitLoc = originatingDecl->getStartLoc();
100105
}
101-
102-
diagnose(repr->getLoc(), diag::opaque_type_in_protocol_requirement)
106+
107+
ctx.Diags.diagnose(repr->getLoc(),
108+
diag::opaque_type_in_protocol_requirement)
103109
.fixItInsert(fixitLoc, "associatedtype <#AssocType#>\n")
104110
.fixItReplace(repr->getSourceRange(), "<#AssocType#>");
105111

106-
return ErrorType::get(Context);
107-
}
108-
109-
// If the decl already has an opaque type decl for its return type, use it.
110-
if (auto existingDecl = originatingDecl->getOpaqueResultTypeDecl()) {
111-
return existingDecl->getDeclaredInterfaceType();
112+
return nullptr;
112113
}
113114

114115
// Check the availability of the opaque type runtime support.
115-
if (!Context.LangOpts.DisableAvailabilityChecking) {
116-
auto runningOS = overApproximateAvailabilityAtLocation(repr->getLoc(),
117-
originatingDecl->getInnermostDeclContext());
118-
auto availability = Context.getOpaqueTypeAvailability();
116+
if (!ctx.LangOpts.DisableAvailabilityChecking) {
117+
auto runningOS =
118+
TypeChecker::overApproximateAvailabilityAtLocation(
119+
repr->getLoc(),
120+
originatingDecl->getInnermostDeclContext());
121+
auto availability = ctx.getOpaqueTypeAvailability();
119122
if (!runningOS.isContainedIn(availability)) {
120-
diagnosePotentialOpaqueTypeUnavailability(repr->getSourceRange(),
121-
originatingDecl->getInnermostDeclContext(),
122-
UnavailabilityReason::requiresVersionRange(availability.getOSVersion()));
123+
TypeChecker::diagnosePotentialOpaqueTypeUnavailability(
124+
repr->getSourceRange(),
125+
originatingDecl->getInnermostDeclContext(),
126+
UnavailabilityReason::requiresVersionRange(availability.getOSVersion()));
123127
}
124128
}
125129

@@ -128,18 +132,20 @@ Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution,
128132
TypeResolutionOptions options(TypeResolverContext::GenericRequirement);
129133
TypeLoc constraintTypeLoc(repr->getConstraint());
130134
// Pass along the error type if resolving the repr failed.
135+
auto resolution = TypeResolution::forInterface(
136+
dc, dc->getGenericSignatureOfContext());
131137
bool validationError
132-
= validateType(Context, constraintTypeLoc, resolution, options);
138+
= TypeChecker::validateType(ctx, constraintTypeLoc, resolution, options);
133139
auto constraintType = constraintTypeLoc.getType();
134140
if (validationError)
135-
return constraintType;
141+
return nullptr;
136142

137143
// Error out if the constraint type isn't a class or existential type.
138144
if (!constraintType->getClassOrBoundGenericClass()
139145
&& !constraintType->isExistentialType()) {
140-
diagnose(repr->getConstraint()->getLoc(),
141-
diag::opaque_type_invalid_constraint);
142-
return constraintTypeLoc.getType();
146+
ctx.Diags.diagnose(repr->getConstraint()->getLoc(),
147+
diag::opaque_type_invalid_constraint);
148+
return nullptr;
143149
}
144150

145151
if (constraintType->hasArchetype())
@@ -157,8 +163,7 @@ Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution,
157163
outerGenericSignature->getGenericParams().back()->getDepth() + 1;
158164
}
159165

160-
auto returnTypeParam = GenericTypeParamType::get(returnTypeDepth, 0,
161-
Context);
166+
auto returnTypeParam = GenericTypeParamType::get(returnTypeDepth, 0, ctx);
162167

163168
SmallVector<GenericTypeParamType *, 2> genericParamTypes;
164169
genericParamTypes.push_back(returnTypeParam);
@@ -184,7 +189,7 @@ Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution,
184189
}
185190

186191
auto interfaceSignature = evaluateOrDefault(
187-
Context.evaluator,
192+
ctx.evaluator,
188193
AbstractGenericSignatureRequest{
189194
outerGenericSignature.getPointer(),
190195
std::move(genericParamTypes),
@@ -194,24 +199,21 @@ Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution,
194199
// Create the OpaqueTypeDecl for the result type.
195200
// It has the same parent context and generic environment as the originating
196201
// decl.
197-
auto dc = originatingDecl->getDeclContext();
198-
202+
auto parentDC = originatingDecl->getDeclContext();
199203
auto originatingGenericContext = originatingDecl->getAsGenericContext();
200204
GenericParamList *genericParams = originatingGenericContext
201205
? originatingGenericContext->getGenericParams()
202206
: nullptr;
203207

204-
auto opaqueDecl = new (Context) OpaqueTypeDecl(originatingDecl,
205-
genericParams,
206-
dc,
207-
interfaceSignature,
208-
returnTypeParam);
208+
auto opaqueDecl = new (ctx) OpaqueTypeDecl(originatingDecl,
209+
genericParams,
210+
parentDC,
211+
interfaceSignature,
212+
returnTypeParam);
209213
opaqueDecl->copyFormalAccessFrom(originatingDecl);
210214
if (auto originatingSig = originatingDC->getGenericSignatureOfContext()) {
211215
opaqueDecl->setGenericSignature(originatingSig);
212216
}
213-
214-
originatingDecl->setOpaqueResultTypeDecl(opaqueDecl);
215217

216218
// The declared interface type is an opaque ArchetypeType.
217219
SubstitutionMap subs;
@@ -221,7 +223,7 @@ Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution,
221223
auto opaqueTy = OpaqueTypeArchetypeType::get(opaqueDecl, subs);
222224
auto metatype = MetatypeType::get(opaqueTy);
223225
opaqueDecl->setInterfaceType(metatype);
224-
return opaqueTy;
226+
return opaqueDecl;
225227
}
226228

227229
/// Determine whether the given type is \c Self, an associated type of \c Self,

0 commit comments

Comments
 (0)