From 62f0926d2503cbb1602f688ec940912b7d3f84dd Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Sun, 26 Oct 2025 12:33:29 +0000 Subject: [PATCH] [CS] Invalidate nested unresolved VarDecls when ignoring completion argument Make sure we set types for any nested VarDecls in UnresolvedPatternExprs to ensure we don't crash when attempting to solve the body. --- include/swift/AST/Expr.h | 4 ++++ include/swift/AST/Pattern.h | 2 +- lib/AST/Pattern.cpp | 6 ++++-- lib/Sema/CSGen.cpp | 5 +++++ .../ConstraintSystem-getType-64cbd4.swift | 2 +- 5 files changed, 15 insertions(+), 4 deletions(-) rename validation-test/IDE/{crashers => crashers_fixed}/ConstraintSystem-getType-64cbd4.swift (64%) diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index 5ef39c4d6a44b..d5472701e8b96 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -506,6 +506,10 @@ class alignas(8) Expr : public ASTAllocated { /// walk into the body of it (unless it is single-expression). void forEachChildExpr(llvm::function_ref callback); + /// Apply the specified function to all variables referenced in any + /// child UnresolvedPatternExprs. + void forEachUnresolvedVariable(llvm::function_ref f) const; + /// Determine whether this expression refers to a type by name. /// /// This distinguishes static references to types, like Int, from metatype diff --git a/include/swift/AST/Pattern.h b/include/swift/AST/Pattern.h index dc2a836ed0bc5..ab6e94ff01b20 100644 --- a/include/swift/AST/Pattern.h +++ b/include/swift/AST/Pattern.h @@ -192,7 +192,7 @@ class alignas(8) Pattern : public ASTAllocated { /// Collect the set of variables referenced in the given pattern. void collectVariables(SmallVectorImpl &variables) const; - /// apply the specified function to all variables referenced in this + /// Apply the specified function to all variables referenced in this /// pattern. void forEachVariable(llvm::function_ref f) const; diff --git a/lib/AST/Pattern.cpp b/lib/AST/Pattern.cpp index 94a2fc40be5c3..790ac003f0bed 100644 --- a/lib/AST/Pattern.cpp +++ b/lib/AST/Pattern.cpp @@ -192,8 +192,7 @@ namespace { const std::function &fn; public: - WalkToVarDecls(const std::function &fn) - : fn(fn) {} + WalkToVarDecls(const std::function &fn) : fn(fn) {} /// Walk everything that's available; there shouldn't be macro expansions /// that matter anyway. @@ -239,6 +238,9 @@ namespace { }; } // end anonymous namespace +void Expr::forEachUnresolvedVariable(llvm::function_ref f) const { + const_cast(this)->walk(WalkToVarDecls(f)); +} /// apply the specified function to all variables referenced in this /// pattern. diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index b32146a7dd4ea..20ecbaa9567a2 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -4354,6 +4354,11 @@ namespace { auto &CS = CG.getConstraintSystem(); if (CS.isArgumentIgnoredForCodeCompletion(expr)) { + // Make sure we invalidate any nested VarDecls to ensure the body + // VarDecl for a case statement still gets a type assigned. + expr->forEachUnresolvedVariable([&](VarDecl *VD) { + CS.setType(VD, ErrorType::get(CS.getASTContext())); + }); CG.setTypeForArgumentIgnoredForCompletion(expr); return Action::SkipNode(expr); } diff --git a/validation-test/IDE/crashers/ConstraintSystem-getType-64cbd4.swift b/validation-test/IDE/crashers_fixed/ConstraintSystem-getType-64cbd4.swift similarity index 64% rename from validation-test/IDE/crashers/ConstraintSystem-getType-64cbd4.swift rename to validation-test/IDE/crashers_fixed/ConstraintSystem-getType-64cbd4.swift index 399e75733673b..03e85e0613784 100644 --- a/validation-test/IDE/crashers/ConstraintSystem-getType-64cbd4.swift +++ b/validation-test/IDE/crashers_fixed/ConstraintSystem-getType-64cbd4.swift @@ -1,3 +1,3 @@ // {"kind":"complete","signature":"swift::constraints::ConstraintSystem::getType(swift::ASTNode) const","signatureAssert":"Assertion failed: (found != NodeTypes.end() && \"Expected type to have been set!\"), function getType"} -// RUN: not --crash %target-swift-ide-test -code-completion -batch-code-completion -skip-filecheck -code-completion-diagnostics -source-filename %s +// RUN: %target-swift-ide-test -code-completion -batch-code-completion -skip-filecheck -code-completion-diagnostics -source-filename %s { switch { case let c(#^COMPLETE^# b) a