Skip to content

Commit e95f5a1

Browse files
authored
Merge pull request #85813 from allevato/json-ast-fixes-6.3
[6.3 🍒] [ASTDumper] Fix some crashers and malformed AST dumps
2 parents 6267454 + 674b51e commit e95f5a1

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed

lib/AST/ASTDumper.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,12 @@ std::string typeUSR(Type type) {
260260
if (!type)
261261
return "";
262262

263+
if (type->is<ModuleType>()) {
264+
// ASTMangler does not support "module types". This can appear, for
265+
// example, on the left-hand side of a `DotSyntaxBaseIgnoredExpr` for a
266+
// module-qualified free function call: `Swift.print()`.
267+
return "";
268+
}
263269
if (type->hasArchetype()) {
264270
type = type->mapTypeOutOfEnvironment();
265271
}
@@ -280,6 +286,13 @@ std::string declTypeUSR(const ValueDecl *D) {
280286
if (!D)
281287
return "";
282288

289+
if (isa<ModuleDecl>(D)) {
290+
// ASTMangler does not support "module types". This can appear, for
291+
// example, on the left-hand side of a `DotSyntaxBaseIgnoredExpr` for a
292+
// module-qualified free function call: `Swift.print()`.
293+
return "";
294+
}
295+
283296
std::string usr;
284297
llvm::raw_string_ostream os(usr);
285298
if (swift::ide::printDeclTypeUSR(D, os))
@@ -1471,7 +1484,11 @@ namespace {
14711484
printFlag(value.isLocalCapture(), "is_local_capture");
14721485
printFlag(value.isDynamicSelfMetadata(), "is_dynamic_self_metadata");
14731486
if (auto *D = value.getDecl()) {
1474-
printRec(D, Label::always("decl"));
1487+
// We print the decl ref, not the full decl, to avoid infinite
1488+
// recursion when a function captures itself (and also because
1489+
// those decls are already printed elsewhere, so we don't need to
1490+
// print what could be a very large amount of information twice).
1491+
printDeclRefField(D, Label::always("decl"));
14751492
}
14761493
if (auto *E = value.getExpr()) {
14771494
printRec(E, Label::always("expr"));
@@ -1896,10 +1913,8 @@ namespace {
18961913
printFoot();
18971914
}
18981915
void visitAnyPattern(AnyPattern *P, Label label) {
1899-
if (P->isAsyncLet()) {
1900-
printCommon(P, "async_let ", label);
1901-
}
19021916
printCommon(P, "pattern_any", label);
1917+
printFlag(P->isAsyncLet(), "async_let", DeclModifierColor);
19031918
printFoot();
19041919
}
19051920
void visitTypedPattern(TypedPattern *P, Label label) {

test/Frontend/ast-dump-json-no-crash.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,3 +484,30 @@ dynamic func toBeReplaced(arg: Int) {}
484484

485485
@_dynamicReplacement(for: toBeReplaced(arg:))
486486
func toReplaceWith(arg: Int) {}
487+
488+
// Regression test: Swift 6.2 and earlier crashed trying to form the type USR
489+
// of the "module type" of a `DotSyntaxBaseIgnoredExpr` when calling a
490+
// module-qualified free function.
491+
func moduleTypeUSRRegressionTest() {
492+
Swift.print("")
493+
}
494+
495+
// Regression test: When a function captures another function, don't print the
496+
// entire captured decl. This causes infinite recursion in the dumper when a
497+
// local (nested) function captures itself.
498+
func outerFn() {
499+
func innerFun(shouldRecurse: Bool) {
500+
if shouldRecurse {
501+
innerFun(shouldRecurse: false)
502+
}
503+
}
504+
innerFun(shouldRecurse: true)
505+
}
506+
507+
// Regression test: Discarded async lets were calling `printCommon` twice,
508+
// which resulted in invalid JSON (and not-so-great S-expression output)
509+
// either.
510+
func discardedAsyncLet() async {
511+
func someTask() async {}
512+
async let _ = someTask()
513+
}

0 commit comments

Comments
 (0)