Merge pull request #85681 from allevato/more-json-ast-fixes

[ASTDumper] Fix some more JSON AST dump crashes.
This commit is contained in:
Tony Allevato
2025-12-02 15:59:21 -05:00
committed by GitHub
2 changed files with 37 additions and 1 deletions

View File

@@ -260,6 +260,12 @@ std::string typeUSR(Type type) {
if (!type)
return "";
if (type->is<ModuleType>()) {
// ASTMangler does not support "module types". This can appear, for
// example, on the left-hand side of a `DotSyntaxBaseIgnoredExpr` for a
// module-qualified free function call: `Swift.print()`.
return "";
}
if (type->hasArchetype()) {
type = type->mapTypeOutOfEnvironment();
}
@@ -280,6 +286,13 @@ std::string declTypeUSR(const ValueDecl *D) {
if (!D)
return "";
if (isa<ModuleDecl>(D)) {
// ASTMangler does not support "module types". This can appear, for
// example, on the left-hand side of a `DotSyntaxBaseIgnoredExpr` for a
// module-qualified free function call: `Swift.print()`.
return "";
}
std::string usr;
llvm::raw_string_ostream os(usr);
if (swift::ide::printDeclTypeUSR(D, os))
@@ -1471,7 +1484,11 @@ namespace {
printFlag(value.isLocalCapture(), "is_local_capture");
printFlag(value.isDynamicSelfMetadata(), "is_dynamic_self_metadata");
if (auto *D = value.getDecl()) {
printRec(D, Label::always("decl"));
// We print the decl ref, not the full decl, to avoid infinite
// recursion when a function captures itself (and also because
// those decls are already printed elsewhere, so we don't need to
// print what could be a very large amount of information twice).
printDeclRefField(D, Label::always("decl"));
}
if (auto *E = value.getExpr()) {
printRec(E, Label::always("expr"));

View File

@@ -484,3 +484,22 @@ dynamic func toBeReplaced(arg: Int) {}
@_dynamicReplacement(for: toBeReplaced(arg:))
func toReplaceWith(arg: Int) {}
// Regression test: Swift 6.2 and earlier crashed trying to form the type USR
// of the "module type" of a `DotSyntaxBaseIgnoredExpr` when calling a
// module-qualified free function.
func moduleTypeUSRRegressionTest() {
Swift.print("")
}
// Regression test: When a function captures another function, don't print the
// entire captured decl. This causes infinite recursion in the dumper when a
// local (nested) function captures itself.
func outerFn() {
func innerFun(shouldRecurse: Bool) {
if shouldRecurse {
innerFun(shouldRecurse: false)
}
}
innerFun(shouldRecurse: true)
}