Skip to content

Commit ab83d90

Browse files
committed
Sema: Fix cycle between closure type computation and EmittedMembersRequest
EmittedMembersRequest needs a stable order for synthesized members to ensure that vtable layout is computed consistently across frontend jobs. This used to use the mangled name as the sort key. However, the mangling includes the type of all outer contexts, and if an outer type is a closure, we would need to compute the type of the closure. Computing the type of a closure might require type checking its body though, which would in turn type check the local class, which would invoke EmittedMembersRequest, introducing a cycle. Instead, let's use the DeclName and string-ified type as the sort key. This is simpler to compute than th mangled name, and breaks the cycle. Fixes <rdar://problem/67842221>.
1 parent 6cad1c2 commit ab83d90

File tree

3 files changed

+26
-11
lines changed

3 files changed

+26
-11
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#include "TypeCheckType.h"
2626
#include "MiscDiagnostics.h"
2727
#include "swift/AST/AccessScope.h"
28-
#include "swift/AST/ASTMangler.h"
2928
#include "swift/AST/ASTPrinter.h"
3029
#include "swift/AST/ASTVisitor.h"
3130
#include "swift/AST/ASTWalker.h"
@@ -2463,21 +2462,16 @@ namespace {
24632462
// Utility class for deterministically ordering vtable entries for
24642463
// synthesized methods.
24652464
struct SortedFuncList {
2466-
using Entry = std::pair<std::string, AbstractFunctionDecl *>;
2465+
using Key = std::tuple<DeclName, std::string>;
2466+
using Entry = std::pair<Key, AbstractFunctionDecl *>;
24672467
SmallVector<Entry, 2> elts;
24682468
bool sorted = false;
24692469

24702470
void add(AbstractFunctionDecl *afd) {
2471-
Mangle::ASTMangler mangler;
2472-
std::string mangledName;
2473-
if (auto *cd = dyn_cast<ConstructorDecl>(afd))
2474-
mangledName = mangler.mangleConstructorEntity(cd, /*allocator=*/false);
2475-
else if (auto *dd = dyn_cast<DestructorDecl>(afd))
2476-
mangledName = mangler.mangleDestructorEntity(dd, /*deallocating=*/false);
2477-
else
2478-
mangledName = mangler.mangleEntity(afd);
2471+
assert(!isa<AccessorDecl>(afd));
24792472

2480-
elts.push_back(std::make_pair(mangledName, afd));
2473+
Key key{afd->getName(), afd->getInterfaceType().getString()};
2474+
elts.emplace_back(key, afd);
24812475
}
24822476

24832477
bool empty() { return elts.empty(); }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
let closureValue = { () -> () in
2+
class DummyClass {}
3+
return ()
4+
}()

test/multifile/rdar67842221.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Test both orderings, and single-file vs WMO
2+
3+
// RUN: %target-swift-frontend -emit-ir -primary-file %s %S/Inputs/rdar67842221-other.swift -module-name main
4+
// RUN: %target-swift-frontend -emit-ir %s -primary-file %S/Inputs/rdar67842221-other.swift -module-name main
5+
6+
// RUN: %target-swift-frontend -emit-ir -primary-file %S/Inputs/rdar67842221-other.swift %s -module-name main
7+
// RUN: %target-swift-frontend -emit-ir %S/Inputs/rdar67842221-other.swift -primary-file %s -module-name main
8+
9+
// RUN: %target-swift-frontend -emit-ir %S/Inputs/rdar67842221-other.swift %s -module-name main
10+
// RUN: %target-swift-frontend -emit-ir %S/Inputs/rdar67842221-other.swift %s -module-name main
11+
12+
// The closure defines a local class; we want to make sure there is no cycle
13+
// between computing the semantic members of the local class (which requires
14+
// sorting) and computing the type of the closure value
15+
public func force() {
16+
_ = closureValue
17+
}

0 commit comments

Comments
 (0)