Skip to content

Commit 25faa00

Browse files
authored
Merge pull request #70397 from DougGregor/cleanup-caught-error-type
[Typed throws] Cleanups for the caught error type computation
2 parents 55c932c + 010a412 commit 25faa00

18 files changed

+298
-204
lines changed

include/swift/AST/AnyFunctionRef.h

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -124,24 +124,6 @@ class AnyFunctionRef {
124124
return TheFunction.get<AbstractClosureExpr *>()->getType();
125125
}
126126

127-
Type getThrownErrorType() const {
128-
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
129-
if (Type thrownError = AFD->getThrownInterfaceType())
130-
return AFD->mapTypeIntoContext(thrownError);
131-
132-
return Type();
133-
}
134-
135-
Type closureType = TheFunction.get<AbstractClosureExpr *>()->getType();
136-
if (!closureType)
137-
return Type();
138-
139-
if (auto closureFnType = closureType->getAs<AnyFunctionType>())
140-
return closureFnType->getThrownError();
141-
142-
return Type();
143-
}
144-
145127
Type getBodyResultType() const {
146128
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
147129
if (auto *FD = dyn_cast<FuncDecl>(AFD))

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
@@ -6985,7 +6985,7 @@ void simple_display(llvm::raw_ostream &out, BodyAndFingerprint value);
69856985
/// Base class for function-like declarations.
69866986
class AbstractFunctionDecl : public GenericContext, public ValueDecl {
69876987
friend class NeedsNewVTableEntryRequest;
6988-
friend class ThrownTypeRequest;
6988+
friend class ExplicitCaughtTypeRequest;
69896989

69906990
public:
69916991
/// 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"
@@ -2284,31 +2285,16 @@ class ParamSpecifierRequest
22842285
void cacheResult(ParamSpecifier value) const;
22852286
};
22862287

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

23192305
// Evaluation.
2320-
Type evaluate(Evaluator &evaluator, DeclContext *dc, DoCatchStmt *stmt) const;
2306+
Type evaluate(Evaluator &evaluator, DeclContext *dc, CatchNode catchNode) const;
23212307

23222308
public:
23232309
// Separate caching.

include/swift/AST/TypeCheckerTypeIDZone.def

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

lib/AST/Decl.cpp

Lines changed: 110 additions & 5 deletions
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

@@ -11714,11 +11718,19 @@ CatchNode::getThrownErrorTypeInContext(DeclContext *dc) const {
1171411718
return llvm::None;
1171511719
}
1171611720

11717-
if (auto closure = dyn_cast<AbstractClosureExpr *>()) {
11718-
if (closure->getType())
11719-
return closure->getEffectiveThrownType();
11721+
if (auto abstractClosure = dyn_cast<AbstractClosureExpr *>()) {
11722+
if (abstractClosure->getType())
11723+
return abstractClosure->getEffectiveThrownType();
11724+
11725+
if (auto closure = llvm::dyn_cast<ClosureExpr>(abstractClosure)) {
11726+
if (Type thrownType = closure->getExplicitThrownType()) {
11727+
if (thrownType->isNever())
11728+
return llvm::None;
11729+
11730+
return thrownType;
11731+
}
11732+
}
1172011733

11721-
// FIXME: Should we lazily compute this?
1172211734
return llvm::None;
1172311735
}
1172411736

@@ -11753,3 +11765,96 @@ CatchNode::getThrownErrorTypeInContext(DeclContext *dc) const {
1175311765

1175411766
llvm_unreachable("Unhandled catch node kind");
1175511767
}
11768+
11769+
void swift::simple_display(llvm::raw_ostream &out, CatchNode catchNode) {
11770+
out << "catch node";
11771+
}
11772+
11773+
//----------------------------------------------------------------------------//
11774+
// ExplicitCaughtTypeRequest computation.
11775+
//----------------------------------------------------------------------------//
11776+
bool ExplicitCaughtTypeRequest::isCached() const {
11777+
auto catchNode = std::get<1>(getStorage());
11778+
11779+
// try? and try! never need to be cached.
11780+
if (catchNode.is<AnyTryExpr *>())
11781+
return false;
11782+
11783+
// Functions with explicitly-written thrown types need the result cached.
11784+
if (auto func = catchNode.dyn_cast<AbstractFunctionDecl *>()) {
11785+
return func->ThrownType.getTypeRepr() != nullptr;
11786+
}
11787+
11788+
// Closures with explicitly-written thrown types need the result cached.
11789+
if (auto abstractClosure = catchNode.dyn_cast<AbstractClosureExpr *>()) {
11790+
if (auto closure = dyn_cast<ClosureExpr>(abstractClosure)) {
11791+
return closure->ThrownType != nullptr;
11792+
}
11793+
11794+
return false;
11795+
}
11796+
11797+
// Do..catch with explicitly-written thrown types need the result cached.
11798+
if (auto doCatch = catchNode.dyn_cast<DoCatchStmt *>()) {
11799+
return doCatch->getThrowsLoc().isValid();
11800+
}
11801+
11802+
llvm_unreachable("Unhandled catch node");
11803+
}
11804+
11805+
llvm::Optional<Type> ExplicitCaughtTypeRequest::getCachedResult() const {
11806+
// Map a possibly-null Type to llvm::Optional<Type>.
11807+
auto nonnullTypeOrNone = [](Type type) -> llvm::Optional<Type> {
11808+
if (type.isNull())
11809+
return llvm::None;
11810+
11811+
return type;
11812+
};
11813+
11814+
auto catchNode = std::get<1>(getStorage());
11815+
11816+
if (auto func = catchNode.dyn_cast<AbstractFunctionDecl *>()) {
11817+
return nonnullTypeOrNone(func->ThrownType.getType());
11818+
}
11819+
11820+
if (auto abstractClosure = catchNode.dyn_cast<AbstractClosureExpr *>()) {
11821+
auto closure = cast<ClosureExpr>(abstractClosure);
11822+
if (closure->ThrownType) {
11823+
return nonnullTypeOrNone(closure->ThrownType->getInstanceType());
11824+
}
11825+
11826+
return llvm::None;
11827+
}
11828+
11829+
if (auto doCatch = catchNode.dyn_cast<DoCatchStmt *>()) {
11830+
return nonnullTypeOrNone(doCatch->ThrownType.getType());
11831+
}
11832+
11833+
llvm_unreachable("Unhandled catch node");
11834+
}
11835+
11836+
void ExplicitCaughtTypeRequest::cacheResult(Type type) const {
11837+
auto catchNode = std::get<1>(getStorage());
11838+
11839+
if (auto func = catchNode.dyn_cast<AbstractFunctionDecl *>()) {
11840+
func->ThrownType.setType(type);
11841+
return;
11842+
}
11843+
11844+
if (auto abstractClosure = catchNode.dyn_cast<AbstractClosureExpr *>()) {
11845+
auto closure = cast<ClosureExpr>(abstractClosure);
11846+
if (closure->ThrownType)
11847+
closure->ThrownType->setType(MetatypeType::get(type));
11848+
else
11849+
closure->ThrownType =
11850+
TypeExpr::createImplicit(type, type->getASTContext());
11851+
return;
11852+
}
11853+
11854+
if (auto doCatch = catchNode.dyn_cast<DoCatchStmt *>()) {
11855+
doCatch->ThrownType.setType(type);
11856+
return;
11857+
}
11858+
11859+
llvm_unreachable("Unhandled catch node");
11860+
}

lib/AST/Expr.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,8 +1937,10 @@ Type AbstractClosureExpr::getResultType(
19371937
}
19381938

19391939
llvm::Optional<Type> AbstractClosureExpr::getEffectiveThrownType() const {
1940-
return getType()->castTo<AnyFunctionType>()
1941-
->getEffectiveThrownErrorType();
1940+
if (auto fnType = getType()->getAs<AnyFunctionType>())
1941+
return fnType->getEffectiveThrownErrorType();
1942+
1943+
return llvm::None;
19421944
}
19431945

19441946
bool AbstractClosureExpr::isBodyThrowing() const {
@@ -2046,11 +2048,14 @@ bool ClosureExpr::hasEmptyBody() const {
20462048
return getBody()->empty();
20472049
}
20482050

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

20562061
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()

0 commit comments

Comments
 (0)