Skip to content

Commit c90c055

Browse files
committed
Record the thrown error type for try? and try! in the AST
SILGen wants this so it knows what kind of error its going to end up with.
1 parent d3ede19 commit c90c055

File tree

6 files changed

+53
-6
lines changed

6 files changed

+53
-6
lines changed

include/swift/AST/Expr.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,6 +1918,7 @@ class TryExpr : public AnyTryExpr {
19181918
/// should dynamically assert if it does.
19191919
class ForceTryExpr final : public AnyTryExpr {
19201920
SourceLoc ExclaimLoc;
1921+
Type thrownError;
19211922

19221923
public:
19231924
ForceTryExpr(SourceLoc tryLoc, Expr *sub, SourceLoc exclaimLoc,
@@ -1927,6 +1928,15 @@ class ForceTryExpr final : public AnyTryExpr {
19271928

19281929
SourceLoc getExclaimLoc() const { return ExclaimLoc; }
19291930

1931+
/// Retrieve the type of the error thrown from the subexpression.
1932+
Type getThrownError() const { return thrownError; }
1933+
1934+
/// Set the type of the error thrown from the subexpression.
1935+
void setThrownError(Type type) {
1936+
assert(!thrownError || thrownError->isEqual(type));
1937+
thrownError = type;
1938+
}
1939+
19301940
static bool classof(const Expr *e) {
19311941
return e->getKind() == ExprKind::ForceTry;
19321942
}
@@ -1937,6 +1947,7 @@ class ForceTryExpr final : public AnyTryExpr {
19371947
/// Optional. If the code does throw, \c nil is produced.
19381948
class OptionalTryExpr final : public AnyTryExpr {
19391949
SourceLoc QuestionLoc;
1950+
Type thrownError;
19401951

19411952
public:
19421953
OptionalTryExpr(SourceLoc tryLoc, Expr *sub, SourceLoc questionLoc,
@@ -1946,6 +1957,15 @@ class OptionalTryExpr final : public AnyTryExpr {
19461957

19471958
SourceLoc getQuestionLoc() const { return QuestionLoc; }
19481959

1960+
/// Retrieve the type of the error thrown from the subexpression.
1961+
Type getThrownError() const { return thrownError; }
1962+
1963+
/// Set the type of the error thrown from the subexpression.
1964+
void setThrownError(Type type) {
1965+
assert(!thrownError || thrownError->isEqual(type));
1966+
thrownError = type;
1967+
}
1968+
19491969
static bool classof(const Expr *e) {
19501970
return e->getKind() == ExprKind::OptionalTry;
19511971
}

lib/AST/ASTDumper.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2690,12 +2690,22 @@ class PrintExpr : public ExprVisitor<PrintExpr, void, StringRef>,
26902690

26912691
void visitForceTryExpr(ForceTryExpr *E, StringRef label) {
26922692
printCommon(E, "force_try_expr", label);
2693+
2694+
PrintOptions PO;
2695+
PO.PrintTypesForDebugging = true;
2696+
printFieldQuoted(E->getThrownError().getString(PO), "thrown_error", TypeColor);
2697+
26932698
printRec(E->getSubExpr());
26942699
printFoot();
26952700
}
26962701

26972702
void visitOptionalTryExpr(OptionalTryExpr *E, StringRef label) {
26982703
printCommon(E, "optional_try_expr", label);
2704+
2705+
PrintOptions PO;
2706+
PO.PrintTypesForDebugging = true;
2707+
printFieldQuoted(E->getThrownError().getString(PO), "thrown_error", TypeColor);
2708+
26992709
printRec(E->getSubExpr());
27002710
printFoot();
27012711
}

lib/Sema/CSApply.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8892,7 +8892,8 @@ static Expr *wrapAsyncLetInitializer(
88928892
ConstraintSystem &cs, Expr *initializer, DeclContext *dc) {
88938893
// Form the autoclosure type. It is always 'async', and will be 'throws'.
88948894
Type initializerType = initializer->getType();
8895-
bool throws = TypeChecker::canThrow(cs.getASTContext(), initializer);
8895+
bool throws = TypeChecker::canThrow(cs.getASTContext(), initializer)
8896+
.has_value();
88968897
auto extInfo = ASTExtInfoBuilder()
88978898
.withAsync()
88988899
.withConcurrent()

lib/Sema/TypeCheckEffects.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3102,6 +3102,10 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
31023102
if (!Flags.has(ContextFlags::HasTryThrowSite))
31033103
diagnoseRedundantTry(E);
31043104

3105+
if (auto thrownError = TypeChecker::canThrow(Ctx, E->getSubExpr())) {
3106+
E->setThrownError(*thrownError);
3107+
}
3108+
31053109
scope.preserveCoverageFromOptionalOrForcedTryOperand();
31063110
return ShouldNotRecurse;
31073111
}
@@ -3117,6 +3121,10 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
31173121
if (!Flags.has(ContextFlags::HasTryThrowSite))
31183122
diagnoseRedundantTry(E);
31193123

3124+
if (auto thrownError = TypeChecker::canThrow(Ctx, E->getSubExpr())) {
3125+
E->setThrownError(*thrownError);
3126+
}
3127+
31203128
scope.preserveCoverageFromOptionalOrForcedTryOperand();
31213129
return ShouldNotRecurse;
31223130
}
@@ -3351,11 +3359,14 @@ void TypeChecker::checkPropertyWrapperEffects(
33513359
expr->walk(LocalFunctionEffectsChecker());
33523360
}
33533361

3354-
bool TypeChecker::canThrow(ASTContext &ctx, Expr *expr) {
3362+
llvm::Optional<Type> TypeChecker::canThrow(ASTContext &ctx, Expr *expr) {
33553363
ApplyClassifier classifier(ctx);
33563364
auto classification = classifier.classifyExpr(expr, EffectKind::Throws);
3357-
return classification.getConditionalKind(EffectKind::Throws) !=
3358-
ConditionalEffectKind::None;
3365+
if (classification.getConditionalKind(EffectKind::Throws) ==
3366+
ConditionalEffectKind::None)
3367+
return llvm::None;
3368+
3369+
return classification.getThrownError();
33593370
}
33603371

33613372
Type TypeChecker::catchErrorType(ASTContext &ctx, DoCatchStmt *stmt) {

lib/Sema/TypeChecker.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,8 +1175,8 @@ void checkInitializerEffects(Initializer *I, Expr *E);
11751175
void checkEnumElementEffects(EnumElementDecl *D, Expr *expr);
11761176
void checkPropertyWrapperEffects(PatternBindingDecl *binding, Expr *expr);
11771177

1178-
/// Whether the given expression can throw.
1179-
bool canThrow(ASTContext &ctx, Expr *expr);
1178+
/// Whether the given expression can throw, and if so, the thrown type.
1179+
llvm::Optional<Type> canThrow(ASTContext &ctx, Expr *expr);
11801180

11811181
/// Determine the error type that is thrown out of the body of the given
11821182
/// do-catch statement.

test/stmt/typed_throws_ast.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,9 @@ func throwsAnything() throws {
3131
// swallow this error
3232
_ = e
3333
} // implicit rethrow
34+
35+
// CHECK: force_try_expr{{.*}}thrown_error="MyError"
36+
try! printOrFail("boom")
37+
// CHECK: optional_try_expr{{.*}}thrown_error="MyError"
38+
try? printOrFail("ssshhhhh")
3439
}

0 commit comments

Comments
 (0)