Skip to content

Commit 12cb8be

Browse files
authored
Merge pull request #70283 from DougGregor/typed-try-force-and-opt
2 parents fbf945d + 00d7e41 commit 12cb8be

11 files changed

+124
-25
lines changed

include/swift/AST/ASTScope.h

+26-10
Original file line numberDiff line numberDiff line change
@@ -945,8 +945,6 @@ class CustomAttributeScope final : public ASTScopeImpl {
945945

946946
bool ignoreInDebugInfo() const override { return true; }
947947

948-
DeclAttribute *getDeclAttr() const { return attr; }
949-
950948
private:
951949
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
952950

@@ -1222,10 +1220,6 @@ class SpecializeAttributeScope final : public ASTScopeImpl {
12221220
return specializeAttr;
12231221
}
12241222

1225-
DeclAttribute *getDeclAttr() const {
1226-
return specializeAttr;
1227-
}
1228-
12291223
protected:
12301224
ASTScopeImpl *expandSpecifically(ScopeCreator &) override;
12311225
bool lookupLocalsOrMembers(DeclConsumer) const override;
@@ -1256,10 +1250,6 @@ class DifferentiableAttributeScope final : public ASTScopeImpl {
12561250
return differentiableAttr;
12571251
}
12581252

1259-
DeclAttribute *getDeclAttr() const {
1260-
return differentiableAttr;
1261-
}
1262-
12631253
protected:
12641254
ASTScopeImpl *expandSpecifically(ScopeCreator &) override;
12651255
bool lookupLocalsOrMembers(DeclConsumer) const override;
@@ -1839,6 +1829,32 @@ class BraceStmtScope final : public AbstractStmtScope {
18391829
return scope->getKind() == ScopeKind::BraceStmt;
18401830
}
18411831
};
1832+
1833+
/// Describes a scope introduced by a try/try!/try? expression.
1834+
class TryScope final : public ASTScopeImpl {
1835+
public:
1836+
AnyTryExpr *const expr;
1837+
TryScope(AnyTryExpr *e)
1838+
: ASTScopeImpl(ScopeKind::Try), expr(e) {}
1839+
virtual ~TryScope() {}
1840+
1841+
protected:
1842+
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
1843+
1844+
private:
1845+
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
1846+
1847+
public:
1848+
SourceRange
1849+
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
1850+
1851+
Expr *getExpr() const { return expr; }
1852+
1853+
static bool classof(const ASTScopeImpl *scope) {
1854+
return scope->getKind() == ScopeKind::Try;
1855+
}
1856+
};
1857+
18421858
} // namespace ast_scope
18431859
} // namespace swift
18441860

include/swift/AST/ASTScopeNodes.def

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ STMT_SCOPE_NODE(CaseStmt)
8888
SCOPE_NODE(CaseLabelItem)
8989
SCOPE_NODE(CaseStmtBody)
9090
STMT_SCOPE_NODE(BraceStmt)
91+
EXPR_SCOPE_NODE(Try)
9192

9293
#undef DECL_ATTRIBUTE_SCOPE_NODE
9394
#undef EXPR_SCOPE_NODE

include/swift/AST/CatchNode.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace swift {
2424
/// An AST node that represents a point where a thrown error can be caught and
2525
/// or rethrown, which includes functions do...catch statements.
2626
class CatchNode: public llvm::PointerUnion<
27-
AbstractFunctionDecl *, AbstractClosureExpr *, DoCatchStmt *
27+
AbstractFunctionDecl *, AbstractClosureExpr *, DoCatchStmt *, AnyTryExpr *
2828
> {
2929
public:
3030
using PointerUnion::PointerUnion;

lib/AST/ASTScopeCreation.cpp

+15-2
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ class ScopeCreator final : public ASTAllocated<ScopeCreator> {
100100
ASTScopeAssert(expr,
101101
"If looking for closures, must have an expression to search.");
102102

103-
/// AST walker that finds nested scopes in expressions. This handles both
104-
/// closures and if/switch expressions.
103+
/// AST walker that finds nested scopes in expressions. This handles
104+
/// closures, if/switch expressions, and try/try!/try? expressions.
105105
class NestedExprScopeFinder : public ASTWalker {
106106
ScopeCreator &scopeCreator;
107107
ASTScopeImpl *parent;
@@ -130,6 +130,13 @@ class ScopeCreator final : public ASTAllocated<ScopeCreator> {
130130
scopeCreator.addToScopeTree(SVE->getStmt(), parent);
131131
return Action::SkipChildren(E);
132132
}
133+
134+
// If we have a try/try!/try?, we need to add a scope for it
135+
if (auto anyTry = dyn_cast<AnyTryExpr>(E)) {
136+
scopeCreator.constructExpandAndInsert<TryScope>(parent, anyTry);
137+
return Action::SkipChildren(E);
138+
}
139+
133140
return Action::Continue(E);
134141
}
135142
PreWalkResult<Stmt *> walkToStmtPre(Stmt *S) override {
@@ -762,6 +769,7 @@ NO_NEW_INSERTION_POINT(MacroDefinitionScope)
762769
NO_NEW_INSERTION_POINT(MacroExpansionDeclScope)
763770
NO_NEW_INSERTION_POINT(SwitchStmtScope)
764771
NO_NEW_INSERTION_POINT(WhileStmtScope)
772+
NO_NEW_INSERTION_POINT(TryScope)
765773

766774
NO_EXPANSION(GenericParamScope)
767775
NO_EXPANSION(SpecializeAttributeScope)
@@ -1372,6 +1380,11 @@ IterableTypeBodyPortion::insertionPointForDeferredExpansion(
13721380
return s->getParent().get();
13731381
}
13741382

1383+
void TryScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
1384+
ScopeCreator &scopeCreator) {
1385+
scopeCreator.addToScopeTree(expr->getSubExpr(), this);
1386+
}
1387+
13751388
#pragma mark verification
13761389

13771390
void ast_scope::simple_display(llvm::raw_ostream &out,

lib/AST/ASTScopeLookup.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,13 @@ CatchNode ASTScopeImpl::lookupCatchNode(ModuleDecl *module, SourceLoc loc) {
724724
return caught.first;
725725
}
726726

727+
// If this is a try scope for a try! or try?, it catches the error.
728+
if (auto tryScope = dyn_cast<TryScope>(scope)) {
729+
if (isa<ForceTryExpr>(tryScope->expr) ||
730+
isa<OptionalTryExpr>(tryScope->expr))
731+
return tryScope->expr;
732+
}
733+
727734
innerBodyScope = dyn_cast<BraceStmtScope>(scope);
728735
}
729736

lib/AST/ASTScopeSourceRange.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -408,3 +408,8 @@ SourceLoc ast_scope::extractNearestSourceLoc(
408408
const ASTScopeImpl *scope = std::get<0>(scopeAndCreator);
409409
return scope->getSourceRangeOfThisASTNode().Start;
410410
}
411+
412+
SourceRange TryScope::getSourceRangeOfThisASTNode(
413+
const bool omitAssertions) const {
414+
return expr->getSourceRange();
415+
}

lib/AST/Decl.cpp

+27-7
Original file line numberDiff line numberDiff line change
@@ -11701,14 +11701,34 @@ CatchNode::getThrownErrorTypeInContext(DeclContext *dc) const {
1170111701
return llvm::None;
1170211702
}
1170311703

11704-
auto doCatch = get<DoCatchStmt *>();
11705-
if (auto thrownError = doCatch->getCaughtErrorType(dc)) {
11706-
if (thrownError->isNever())
11707-
return llvm::None;
11704+
if (auto doCatch = dyn_cast<DoCatchStmt *>()) {
11705+
if (auto thrownError = doCatch->getCaughtErrorType(dc)) {
11706+
if (thrownError->isNever())
11707+
return llvm::None;
11708+
11709+
return thrownError;
11710+
}
11711+
11712+
// If we haven't computed the error type yet, return 'any Error'.
11713+
return dc->getASTContext().getErrorExistentialType();
11714+
}
11715+
11716+
auto tryExpr = get<AnyTryExpr *>();
11717+
if (auto forceTry = llvm::dyn_cast<ForceTryExpr>(tryExpr)) {
11718+
if (auto thrownError = forceTry->getThrownError())
11719+
return thrownError;
11720+
11721+
// If we haven't computed the error type yet, return 'any Error'.
11722+
return dc->getASTContext().getErrorExistentialType();
11723+
}
11724+
11725+
if (auto optTry = llvm::dyn_cast<OptionalTryExpr>(tryExpr)) {
11726+
if (auto thrownError = optTry->getThrownError())
11727+
return thrownError;
1170811728

11709-
return thrownError;
11729+
// If we haven't computed the error type yet, return 'any Error'.
11730+
return dc->getASTContext().getErrorExistentialType();
1171011731
}
1171111732

11712-
// If we haven't computed the error type yet, do so now.
11713-
return dc->getASTContext().getErrorExistentialType();
11733+
llvm_unreachable("Unhandled catch node kind");
1171411734
}

lib/SILGen/SILGenStmt.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1569,7 +1569,7 @@ void SILGenFunction::emitThrow(SILLocation loc, ManagedValue exnMV,
15691569
// If the thrown error type differs from what the throw destination expects,
15701570
// perform the conversion.
15711571
// FIXME: Can the AST tell us what to do here?
1572-
if (exnType != destErrorType && !shouldDiscard) {
1572+
if (exnType != destErrorType) {
15731573
assert(destErrorType == SILType::getExceptionType(getASTContext()));
15741574

15751575
ProtocolConformanceRef conformances[1] = {

test/NameLookup/scope_map-astscopelookup.swift

+5-4
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func HasLabeledDo() {
209209
// RUN: %FileCheck -check-prefix CHECK-EXPANDED %s < %t.expanded
210210

211211
// CHECK-EXPANDED: ***Complete scope map***
212-
// CHECK-EXPANDED-NEXT: ASTSourceFileScope {{.*}}, [1:1 - 480:1] '{{.*}}scope_map-astscopelookup.swift'
212+
// CHECK-EXPANDED-NEXT: ASTSourceFileScope {{.*}}, [1:1 - 481:1] '{{.*}}scope_map-astscopelookup.swift'
213213
// CHECK-EXPANDED-NEXT: |-NominalTypeDeclScope {{.*}}, [5:1 - 7:1] 'S0'
214214
// CHECK-EXPANDED-NEXT: `-NominalTypeBodyScope {{.*}}, [5:11 - 7:1] 'S0'
215215
// CHECK-EXPANDED-NEXT: `-NominalTypeDeclScope {{.*}}, [6:3 - 6:19] 'InnerC0'
@@ -317,7 +317,8 @@ func HasLabeledDo() {
317317
// CHECK-EXPANDED-NEXT: |-ForEachStmtScope {{.*}}, [80:3 - 82:3]
318318
// CHECK-EXPANDED-NEXT: `-ForEachPatternScope, [80:52 - 82:3]
319319
// CHECK-EXPANDED-NEXT: |-DoCatchStmtScope {{.*}}, [84:3 - 88:3]
320-
// CHECK-EXPANDED-NEXT: |-BraceStmtScope {{.*}}, [84:6 - 86:3]
320+
// CHECK-EXPANDED-NEXT: |-BraceStmtScope {{.*}}, [84:6 - 86:3]
321+
// CHECK-EXPANDED-NEXT: `-TryScope {{.*}}, [85:5 - 85:18]
321322
// CHECK-EXPANDED-NEXT: |-CaseStmtScope {{.*}}, [86:5 - 87:3]
322323
// CHECK-EXPANDED-NEXT: `-CaseLabelItemScope, [86:37 - 86:51]
323324
// CHECK-EXPANDED-NEXT: `-CaseStmtScope {{.*}}, [87:5 - 88:3]
@@ -396,8 +397,8 @@ func HasLabeledDo() {
396397
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [160:12 - 160:22]
397398
// CHECK-EXPANDED-NEXT: `-ClosureParametersScope {{.*}}, [162:10 - 162:19]
398399
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [162:10 - 162:19]
399-
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [165:1 - 480:1]
400-
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [165:1 - 480:1]
400+
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [165:1 - 481:1]
401+
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [165:1 - 481:1]
401402
// CHECK-EXPANDED-NEXT: |-ClosureParametersScope {{.*}}, [165:1 - 165:14]
402403
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [165:1 - 165:14]
403404
// CHECK-EXPANDED-NEXT: |-AbstractFunctionDeclScope {{.*}}, [167:1 - 176:1] 'defaultArguments(i:j:)'

test/SILGen/typed_throws.swift

+30
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,36 @@ func throwsDifferentFromEnclosing() throws(Foo) {
146146
throw Foo()
147147
}
148148

149+
// CHECK-LABEL: sil hidden [ossa] @$s12typed_throws17forceTryDifferentyyAA7MyErrorOYKF
150+
func forceTryDifferent() throws(MyError) {
151+
// CHECK: try_apply{{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
152+
// CHECK: [[NORMAL_BB]]([[RESULT:%.*]] : $()):
153+
// CHECK: return
154+
// CHECK: [[ERROR_BB]]([[ERROR:%.*]] : $MyBigError):
155+
// CHECK-NEXT: unreachable
156+
try! throwsMyBigError()
157+
}
158+
159+
// CHECK-LABEL: sil hidden [ossa] @$s12typed_throws20optionalTryDifferentyyAA7MyErrorOYKF
160+
func optionalTryDifferent() throws(MyError) {
161+
// CHECK: try_apply{{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
162+
// CHECK: [[NORMAL_BB]]([[RESULT:%.*]] : $()):
163+
// CHECK: br
164+
// CHECK: [[ERROR_BB]]([[ERROR:%.*]] : $MyBigError):
165+
// CHECK-NEXT: enum $Optional<()>, #Optional.none!enumelt
166+
try? throwsMyBigError()
167+
}
168+
169+
func throwsMyBigErrorOrReturnsInt() throws(MyBigError) -> Int { 5 }
170+
171+
func mightThrowAny(arg: Int) throws { }
172+
173+
// CHECK-LABEL: sil hidden [ossa] @$s12typed_throws14forceTryErasedyyF : $@convention(thin) () -> () {
174+
func forceTryErased() {
175+
// CHECK: try_apply {{.*}} @error MyBigError
176+
// CHECK: try_apply {{.*}} @error any Error
177+
try! mightThrowAny(arg: throwsMyBigErrorOrReturnsInt())
178+
}
149179

150180
// CHECK-LABEL: sil_vtable MySubclass {
151181
// CHECK-NEXT: #MyClass.init!allocator: <E where E : Error> (MyClass.Type) -> (() throws(E) -> ()) throws(E) -> MyClass : @$s12typed_throws10MySubclassC4bodyACyyxYKXE_txYKcs5ErrorRzlufC [override]

test/stmt/typed_throws.swift

+6
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,9 @@ func testDoCatchExplicitTyped() {
170170
do throws(HomeworkError) { // expected-error{{a 'do' statement with a 'throws' clause must have at least one 'catch'}}
171171
}
172172
}
173+
174+
func tryBangQuestionMismatchingContext() throws(MyError) {
175+
try! doHomework()
176+
try? doHomework()
177+
try doHomework() // expected-error{{thrown expression type 'HomeworkError' cannot be converted to error type 'MyError'}}
178+
}

0 commit comments

Comments
 (0)