Skip to content

Commit 91df336

Browse files
committed
[Typed throws] Unify ThrownTypeRequest and DoCatchExplicitThrownTypeRequest
These two requests are effectively doing the same thing to two different cases within CatchNode. Unify the requests into a single request, ExplicitCaughtTypeRequest, which operates on a CatchNode. This also moves the logic for closures with explicitly-specified throws clauses into the same request, taking it out of the constraint system.
1 parent b080b5f commit 91df336

16 files changed

+250
-162
lines changed

include/swift/AST/CatchNode.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef SWIFT_AST_CATCHNODE_H
1414
#define SWIFT_AST_CATCHNODE_H
1515

16+
#include "llvm/ADT/Hashing.h"
1617
#include "llvm/ADT/Optional.h"
1718
#include "llvm/ADT/PointerUnion.h"
1819
#include "swift/AST/Decl.h"
@@ -36,8 +37,15 @@ class CatchNode: public llvm::PointerUnion<
3637
/// Returns the thrown error type for a throwing context, or \c llvm::None
3738
/// if this is a non-throwing context.
3839
llvm::Optional<Type> getThrownErrorTypeInContext(DeclContext *dc) const;
40+
41+
friend llvm::hash_code hash_value(CatchNode catchNode) {
42+
using llvm::hash_value;
43+
return hash_value(catchNode.getOpaqueValue());
44+
}
3945
};
4046

47+
void simple_display(llvm::raw_ostream &out, CatchNode catchNode);
48+
4149
} // end namespace swift
4250

4351
#endif // SWIFT_AST_CATCHNODE_H

include/swift/AST/Decl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6989,7 +6989,7 @@ void simple_display(llvm::raw_ostream &out, BodyAndFingerprint value);
69896989
/// Base class for function-like declarations.
69906990
class AbstractFunctionDecl : public GenericContext, public ValueDecl {
69916991
friend class NeedsNewVTableEntryRequest;
6992-
friend class ThrownTypeRequest;
6992+
friend class ExplicitCaughtTypeRequest;
69936993

69946994
public:
69956995
/// records the kind of SILGen-synthesized body this decl represents

include/swift/AST/Expr.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3987,6 +3987,8 @@ class SerializedAbstractClosureExpr : public SerializedLocalDeclContext {
39873987
/// { [weak c] (a : Int) -> Int in a + c!.getFoo() }
39883988
/// \endcode
39893989
class ClosureExpr : public AbstractClosureExpr {
3990+
friend class ExplicitCaughtTypeRequest;
3991+
39903992
public:
39913993
enum class BodyState {
39923994
/// The body was parsed, but not ready for type checking because
@@ -4034,7 +4036,7 @@ class ClosureExpr : public AbstractClosureExpr {
40344036
/// The location of the "in", if present.
40354037
SourceLoc InLoc;
40364038

4037-
/// The explcitly-specified thrown type.
4039+
/// The explicitly-specified thrown type.
40384040
TypeExpr *ThrownType;
40394041

40404042
/// The explicitly-specified result type.
@@ -4149,14 +4151,7 @@ class ClosureExpr : public AbstractClosureExpr {
41494151
}
41504152

41514153
/// Retrieve the explicitly-thrown type.
4152-
Type getExplicitThrownType() const {
4153-
if (ThrownType)
4154-
return ThrownType->getInstanceType();
4155-
4156-
return nullptr;
4157-
}
4158-
4159-
void setExplicitThrownType(Type thrownType);
4154+
Type getExplicitThrownType() const;
41604155

41614156
/// Retrieve the explicitly-thrown type representation.
41624157
TypeRepr *getExplicitThrownTypeRepr() const {

include/swift/AST/Stmt.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,7 +1387,7 @@ class DoCatchStmt final
13871387
: public LabeledStmt,
13881388
private llvm::TrailingObjects<DoCatchStmt, CaseStmt *> {
13891389
friend TrailingObjects;
1390-
friend class DoCatchExplicitThrownTypeRequest;
1390+
friend class ExplicitCaughtTypeRequest;
13911391

13921392
SourceLoc DoLoc;
13931393

@@ -1429,13 +1429,13 @@ class DoCatchStmt final
14291429
SourceLoc getStartLoc() const { return getLabelLocOrKeywordLoc(DoLoc); }
14301430
SourceLoc getEndLoc() const { return getCatches().back()->getEndLoc(); }
14311431

1432-
/// Retrieves the type representation for the thrown type.
1433-
TypeRepr *getThrownTypeRepr() const {
1432+
/// Retrieves the type representation for the caught type.
1433+
TypeRepr *getCaughtTypeRepr() const {
14341434
return ThrownType.getTypeRepr();
14351435
}
14361436

1437-
// Get the explicitly-specified thrown error type.
1438-
Type getExplicitlyThrownType(DeclContext *dc) const;
1437+
// Get the explicitly-specified caught error type.
1438+
Type getExplicitCaughtType(DeclContext *dc) const;
14391439

14401440
Stmt *getBody() const { return Body; }
14411441
void setBody(Stmt *s) { Body = s; }

include/swift/AST/TypeCheckRequests.h

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/AnyFunctionRef.h"
2121
#include "swift/AST/ASTNode.h"
2222
#include "swift/AST/ASTTypeIDs.h"
23+
#include "swift/AST/CatchNode.h"
2324
#include "swift/AST/Effects.h"
2425
#include "swift/AST/GenericParamList.h"
2526
#include "swift/AST/GenericSignature.h"
@@ -2283,31 +2284,16 @@ class ParamSpecifierRequest
22832284
void cacheResult(ParamSpecifier value) const;
22842285
};
22852286

2286-
/// Determines the explicitly-written thrown result type of a function.
2287-
class ThrownTypeRequest
2288-
: public SimpleRequest<ThrownTypeRequest,
2289-
Type(AbstractFunctionDecl *),
2290-
RequestFlags::SeparatelyCached> {
2291-
public:
2292-
using SimpleRequest::SimpleRequest;
2293-
2294-
private:
2295-
friend SimpleRequest;
2296-
2297-
// Evaluation.
2298-
Type evaluate(Evaluator &evaluator, AbstractFunctionDecl *func) const;
2299-
2300-
public:
2301-
// Separate caching.
2302-
bool isCached() const { return true; }
2303-
llvm::Optional<Type> getCachedResult() const;
2304-
void cacheResult(Type value) const;
2305-
};
2306-
2307-
/// Determines the explicitly-written thrown error type in a do..catch block.
2308-
class DoCatchExplicitThrownTypeRequest
2309-
: public SimpleRequest<DoCatchExplicitThrownTypeRequest,
2310-
Type(DeclContext *, DoCatchStmt *),
2287+
/// Determines the explicitly-written caught result type for any catch node,
2288+
/// including functions/closures and do..catch statements.
2289+
///
2290+
/// Returns the caught result type for the catch node, which will be
2291+
/// `Never` if no error can be thrown from within the context (e.g., a
2292+
/// non-throwing function). Returns a NULL type if the caught error type
2293+
/// requires type inference.
2294+
class ExplicitCaughtTypeRequest
2295+
: public SimpleRequest<ExplicitCaughtTypeRequest,
2296+
Type(DeclContext *, CatchNode),
23112297
RequestFlags::SeparatelyCached> {
23122298
public:
23132299
using SimpleRequest::SimpleRequest;
@@ -2316,7 +2302,7 @@ class DoCatchExplicitThrownTypeRequest
23162302
friend SimpleRequest;
23172303

23182304
// Evaluation.
2319-
Type evaluate(Evaluator &evaluator, DeclContext *dc, DoCatchStmt *stmt) const;
2305+
Type evaluate(Evaluator &evaluator, DeclContext *dc, CatchNode catchNode) const;
23202306

23212307
public:
23222308
// Separate caching.

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -358,11 +358,8 @@ SWIFT_REQUEST(TypeChecker, NeedsNewVTableEntryRequest,
358358
bool(AbstractFunctionDecl *), SeparatelyCached, NoLocationInfo)
359359
SWIFT_REQUEST(TypeChecker, ParamSpecifierRequest,
360360
ParamDecl::Specifier(ParamDecl *), SeparatelyCached, NoLocationInfo)
361-
SWIFT_REQUEST(TypeChecker, ThrownTypeRequest,
362-
Type(AbstractFunctionDecl *), SeparatelyCached, NoLocationInfo)
363-
SWIFT_REQUEST(TypeChecker, DoCatchExplicitThrownTypeRequest,
364-
Type(DeclContext *, DoCatchStmt *), SeparatelyCached,
365-
NoLocationInfo)
361+
SWIFT_REQUEST(TypeChecker, ExplicitCaughtTypeRequest,
362+
Type(DeclContext *, CatchNode), SeparatelyCached, NoLocationInfo)
366363
SWIFT_REQUEST(TypeChecker, ResultTypeRequest,
367364
Type(ValueDecl *), SeparatelyCached, NoLocationInfo)
368365
SWIFT_REQUEST(TypeChecker, AreAllStoredPropertiesDefaultInitableRequest,

lib/AST/Decl.cpp

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,9 +979,13 @@ bool Decl::preconcurrency() const {
979979
}
980980

981981
Type AbstractFunctionDecl::getThrownInterfaceType() const {
982+
if (!getThrownTypeRepr())
983+
return ThrownType.getType();
984+
985+
auto mutableThis = const_cast<AbstractFunctionDecl *>(this);
982986
return evaluateOrDefault(
983987
getASTContext().evaluator,
984-
ThrownTypeRequest{const_cast<AbstractFunctionDecl *>(this)},
988+
ExplicitCaughtTypeRequest{mutableThis, mutableThis},
985989
Type());
986990
}
987991

@@ -11737,3 +11741,96 @@ CatchNode::getThrownErrorTypeInContext(DeclContext *dc) const {
1173711741

1173811742
llvm_unreachable("Unhandled catch node kind");
1173911743
}
11744+
11745+
void swift::simple_display(llvm::raw_ostream &out, CatchNode catchNode) {
11746+
out << "catch node";
11747+
}
11748+
11749+
//----------------------------------------------------------------------------//
11750+
// ExplicitCaughtTypeRequest computation.
11751+
//----------------------------------------------------------------------------//
11752+
bool ExplicitCaughtTypeRequest::isCached() const {
11753+
auto catchNode = std::get<1>(getStorage());
11754+
11755+
// try? and try! never need to be cached.
11756+
if (catchNode.is<AnyTryExpr *>())
11757+
return false;
11758+
11759+
// Functions with explicitly-written thrown types need the result cached.
11760+
if (auto func = catchNode.dyn_cast<AbstractFunctionDecl *>()) {
11761+
return func->ThrownType.getTypeRepr() != nullptr;
11762+
}
11763+
11764+
// Closures with explicitly-written thrown types need the result cached.
11765+
if (auto abstractClosure = catchNode.dyn_cast<AbstractClosureExpr *>()) {
11766+
if (auto closure = dyn_cast<ClosureExpr>(abstractClosure)) {
11767+
return closure->ThrownType != nullptr;
11768+
}
11769+
11770+
return false;
11771+
}
11772+
11773+
// Do..catch with explicitly-written thrown types need the result cached.
11774+
if (auto doCatch = catchNode.dyn_cast<DoCatchStmt *>()) {
11775+
return doCatch->getThrowsLoc().isValid();
11776+
}
11777+
11778+
llvm_unreachable("Unhandled catch node");
11779+
}
11780+
11781+
llvm::Optional<Type> ExplicitCaughtTypeRequest::getCachedResult() const {
11782+
// Map a possibly-null Type to llvm::Optional<Type>.
11783+
auto nonnullTypeOrNone = [](Type type) -> llvm::Optional<Type> {
11784+
if (type.isNull())
11785+
return llvm::None;
11786+
11787+
return type;
11788+
};
11789+
11790+
auto catchNode = std::get<1>(getStorage());
11791+
11792+
if (auto func = catchNode.dyn_cast<AbstractFunctionDecl *>()) {
11793+
return nonnullTypeOrNone(func->ThrownType.getType());
11794+
}
11795+
11796+
if (auto abstractClosure = catchNode.dyn_cast<AbstractClosureExpr *>()) {
11797+
auto closure = cast<ClosureExpr>(abstractClosure);
11798+
if (closure->ThrownType) {
11799+
return nonnullTypeOrNone(closure->ThrownType->getInstanceType());
11800+
}
11801+
11802+
return llvm::None;
11803+
}
11804+
11805+
if (auto doCatch = catchNode.dyn_cast<DoCatchStmt *>()) {
11806+
return nonnullTypeOrNone(doCatch->ThrownType.getType());
11807+
}
11808+
11809+
llvm_unreachable("Unhandled catch node");
11810+
}
11811+
11812+
void ExplicitCaughtTypeRequest::cacheResult(Type type) const {
11813+
auto catchNode = std::get<1>(getStorage());
11814+
11815+
if (auto func = catchNode.dyn_cast<AbstractFunctionDecl *>()) {
11816+
func->ThrownType.setType(type);
11817+
return;
11818+
}
11819+
11820+
if (auto abstractClosure = catchNode.dyn_cast<AbstractClosureExpr *>()) {
11821+
auto closure = cast<ClosureExpr>(abstractClosure);
11822+
if (closure->ThrownType)
11823+
closure->ThrownType->setType(MetatypeType::get(type));
11824+
else
11825+
closure->ThrownType =
11826+
TypeExpr::createImplicit(type, type->getASTContext());
11827+
return;
11828+
}
11829+
11830+
if (auto doCatch = catchNode.dyn_cast<DoCatchStmt *>()) {
11831+
doCatch->ThrownType.setType(type);
11832+
return;
11833+
}
11834+
11835+
llvm_unreachable("Unhandled catch node");
11836+
}

lib/AST/Expr.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,11 +2046,14 @@ bool ClosureExpr::hasEmptyBody() const {
20462046
return getBody()->empty();
20472047
}
20482048

2049-
void ClosureExpr::setExplicitThrownType(Type thrownType) {
2050-
assert(thrownType && !thrownType->hasTypeVariable() &&
2051-
!thrownType->hasPlaceholder());
2052-
assert(ThrownType);
2053-
ThrownType->setType(MetatypeType::get(thrownType));
2049+
Type ClosureExpr::getExplicitThrownType() const {
2050+
if (getThrowsLoc().isInvalid())
2051+
return Type();
2052+
2053+
ASTContext &ctx = getASTContext();
2054+
auto mutableThis = const_cast<ClosureExpr *>(this);
2055+
ExplicitCaughtTypeRequest request{mutableThis, mutableThis};
2056+
return evaluateOrDefault(ctx.evaluator, request, Type());
20542057
}
20552058

20562059
void ClosureExpr::setExplicitResultType(Type ty) {

lib/AST/Stmt.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -478,15 +478,15 @@ bool DoCatchStmt::isSyntacticallyExhaustive() const {
478478
return false;
479479
}
480480

481-
Type DoCatchStmt::getExplicitlyThrownType(DeclContext *dc) const {
481+
Type DoCatchStmt::getExplicitCaughtType(DeclContext *dc) const {
482482
ASTContext &ctx = dc->getASTContext();
483-
DoCatchExplicitThrownTypeRequest request{dc, const_cast<DoCatchStmt *>(this)};
483+
ExplicitCaughtTypeRequest request{dc, const_cast<DoCatchStmt *>(this)};
484484
return evaluateOrDefault(ctx.evaluator, request, Type());
485485
}
486486

487487
Type DoCatchStmt::getCaughtErrorType(DeclContext *dc) const {
488488
// Check for an explicitly-specified error type.
489-
if (Type explicitError = getExplicitlyThrownType(dc))
489+
if (Type explicitError = getExplicitCaughtType(dc))
490490
return explicitError;
491491

492492
auto firstPattern = getCatches()

lib/AST/TypeCheckRequests.cpp

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -951,47 +951,6 @@ void ParamSpecifierRequest::cacheResult(ParamSpecifier specifier) const {
951951
decl->setSpecifier(specifier);
952952
}
953953

954-
//----------------------------------------------------------------------------//
955-
// ThrownTypeRequest computation.
956-
//----------------------------------------------------------------------------//
957-
958-
llvm::Optional<Type> ThrownTypeRequest::getCachedResult() const {
959-
auto *const func = std::get<0>(getStorage());
960-
Type thrownType = func->ThrownType.getType();
961-
if (thrownType.isNull())
962-
return llvm::None;
963-
964-
return thrownType;
965-
}
966-
967-
void ThrownTypeRequest::cacheResult(Type type) const {
968-
auto *const func = std::get<0>(getStorage());
969-
func->ThrownType.setType(type);
970-
}
971-
972-
//----------------------------------------------------------------------------//
973-
// DoCatchExplicitThrownTypeRequest computation.
974-
//----------------------------------------------------------------------------//
975-
976-
bool DoCatchExplicitThrownTypeRequest::isCached() const {
977-
auto *const stmt = std::get<1>(getStorage());
978-
return stmt->getThrowsLoc().isValid();
979-
}
980-
981-
llvm::Optional<Type> DoCatchExplicitThrownTypeRequest::getCachedResult() const {
982-
auto *const stmt = std::get<1>(getStorage());
983-
Type thrownType = stmt->ThrownType.getType();
984-
if (thrownType.isNull())
985-
return llvm::None;
986-
987-
return thrownType;
988-
}
989-
990-
void DoCatchExplicitThrownTypeRequest::cacheResult(Type type) const {
991-
auto *const stmt = std::get<1>(getStorage());
992-
stmt->ThrownType.setType(type);
993-
}
994-
995954
//----------------------------------------------------------------------------//
996955
// ResultTypeRequest computation.
997956
//----------------------------------------------------------------------------//

0 commit comments

Comments
 (0)