From 97f7efd25724e1f927eb807157bce1abf9a750da Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 28 Oct 2025 19:20:36 -0400 Subject: [PATCH 1/4] Sema: rdar://r78102266 was a SILGen crash so fix the test to pass -emit-silgen --- .../Sema/type_checker_crashers_fixed/rdar78102266.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validation-test/Sema/type_checker_crashers_fixed/rdar78102266.swift b/validation-test/Sema/type_checker_crashers_fixed/rdar78102266.swift index 704728f2f1653..e705239b2d9d9 100644 --- a/validation-test/Sema/type_checker_crashers_fixed/rdar78102266.swift +++ b/validation-test/Sema/type_checker_crashers_fixed/rdar78102266.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend %s -typecheck +// RUN: %target-swift-emit-silgen %s struct Info { } From f014a9aeec63bb9e2217e7a1019ae071586bfa36 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 28 Oct 2025 17:48:55 -0400 Subject: [PATCH 2/4] Sema: Don't coerce subexpression of 'try' to rvalue The change in 8ab8b2e3e9107f32ea13efd38e270ff3b45d324a, was too broad. We want to coerce the subexpression of `try!` to an rvalue, but not the subexpression of a `try`. If the subexpression of a `try` becomes an rvalue even though the type of the parent expression is an lvalue, we can end up with infinite recursion in coerceToType(), as demonstrated by the test case. Fixes https://github.com/swiftlang/swift/issues/85034. --- lib/Sema/CSApply.cpp | 6 +++++- .../compiler_crashers_fixed/issue-85034.swift | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 validation-test/compiler_crashers_fixed/issue-85034.swift diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 900375b327fd6..96dbd06c25e82 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -3752,7 +3752,11 @@ namespace { return expr; } - Expr *visitAnyTryExpr(AnyTryExpr *expr) { + Expr *visitTryExpr(TryExpr *expr) { + return simplifyExprType(expr); + } + + Expr *visitForceTryExpr(ForceTryExpr *expr) { auto *subExpr = expr->getSubExpr(); auto type = simplifyType(cs.getType(subExpr)); diff --git a/validation-test/compiler_crashers_fixed/issue-85034.swift b/validation-test/compiler_crashers_fixed/issue-85034.swift new file mode 100644 index 0000000000000..5ff6b813ad8a7 --- /dev/null +++ b/validation-test/compiler_crashers_fixed/issue-85034.swift @@ -0,0 +1,10 @@ +// RUN: %target-typecheck-verify-swift + +class C { + var x = 0 +} + +do { + let x = C() + let _ = (0, try x.x) // expected-warning {{no calls to throwing functions occur within 'try' expression}} +} From 5c6a5265fe4431ef1adda4bdd6ff149f4f5b2b9d Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 28 Oct 2025 17:51:46 -0400 Subject: [PATCH 3/4] Sema: Replace early return with ASSERT It seems that we end up with a null Type in one place in StmtChecker::visitSwitchStmt(), so add a null check there, and a FIXME to investigate further. --- lib/Sema/TypeCheckConstraints.cpp | 5 +---- lib/Sema/TypeCheckStmt.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 9d3c4fe2310e2..b3c00f731bbc8 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -1192,10 +1192,7 @@ TypeChecker::coerceToRValue(ASTContext &Context, Expr *expr, llvm::function_ref getType, llvm::function_ref setType) { Type exprTy = getType(expr); - - // If expr has no type, just assume it's the right expr. - if (!exprTy) - return expr; + ASSERT(exprTy); // If the type is already materializable, then we're already done. if (!exprTy->hasLValueType()) diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 0bad17c728222..1a8b3939138ca 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -1702,10 +1702,11 @@ class StmtChecker : public StmtVisitor { // Type-check the subject expression. Expr *subjectExpr = switchStmt->getSubjectExpr(); auto resultTy = TypeChecker::typeCheckExpression(subjectExpr, DC); + auto limitExhaustivityChecks = !resultTy; - if (Expr *newSubjectExpr = - TypeChecker::coerceToRValue(getASTContext(), subjectExpr)) - subjectExpr = newSubjectExpr; + if (resultTy) + subjectExpr = TypeChecker::coerceToRValue(getASTContext(), subjectExpr); + switchStmt->setSubjectExpr(subjectExpr); Type subjectType = switchStmt->getSubjectExpr()->getType(); From 8fd7a1db867027e51eaff8a130e9b80d7c906342 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 28 Oct 2025 19:55:51 -0400 Subject: [PATCH 4/4] Sema: Fix CSGen for ForceTryExpr --- lib/Sema/CSGen.cpp | 12 +++++++++++- .../compiler_crashers_fixed/issue-85034.swift | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 20ecbaa9567a2..850d858fbbbc5 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -2060,10 +2060,20 @@ namespace { return valueTy; } - Type visitAnyTryExpr(AnyTryExpr *expr) { + Type visitTryExpr(AnyTryExpr *expr) { return CS.getType(expr->getSubExpr()); } + Type visitForceTryExpr(AnyTryExpr *expr) { + auto valueTy = CS.createTypeVariable(CS.getConstraintLocator(expr), + TVO_PrefersSubtypeBinding | + TVO_CanBindToNoEscape); + CS.addConstraint(ConstraintKind::Equal, valueTy, + CS.getType(expr->getSubExpr()), + CS.getConstraintLocator(expr)); + return valueTy; + } + Type visitOptionalTryExpr(OptionalTryExpr *expr) { auto valueTy = CS.createTypeVariable(CS.getConstraintLocator(expr), TVO_PrefersSubtypeBinding | diff --git a/validation-test/compiler_crashers_fixed/issue-85034.swift b/validation-test/compiler_crashers_fixed/issue-85034.swift index 5ff6b813ad8a7..3d1dc75c4497b 100644 --- a/validation-test/compiler_crashers_fixed/issue-85034.swift +++ b/validation-test/compiler_crashers_fixed/issue-85034.swift @@ -1,4 +1,5 @@ // RUN: %target-typecheck-verify-swift +// RUN: %target-swift-emit-silgen %s class C { var x = 0 @@ -7,4 +8,5 @@ class C { do { let x = C() let _ = (0, try x.x) // expected-warning {{no calls to throwing functions occur within 'try' expression}} + let _ = (0, try! x.x) // expected-warning {{no calls to throwing functions occur within 'try' expression}} }