Skip to content

Commit b7a4822

Browse files
authored
Merge pull request #38648 from ahoppen/pr/apply-key-path-results-when-merging-solutions
[Sema] Copy key path component types when merging solutions
2 parents 9397ee5 + f42f961 commit b7a4822

File tree

3 files changed

+74
-8
lines changed

3 files changed

+74
-8
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,7 +1186,7 @@ class Solution {
11861186
llvm::DenseMap<ASTNode, Type> nodeTypes;
11871187

11881188
/// The key path component types introduced by this solution.
1189-
llvm::DenseMap<std::pair<const KeyPathExpr *, unsigned>, TypeBase *>
1189+
llvm::DenseMap<std::pair<const KeyPathExpr *, unsigned>, Type>
11901190
keyPathComponentTypes;
11911191

11921192
/// Contextual types introduced by this solution.
@@ -2183,9 +2183,23 @@ class ConstraintSystem {
21832183
/// run through various diagnostics passes without actually mutating
21842184
/// the types on the nodes.
21852185
llvm::MapVector<ASTNode, Type> NodeTypes;
2186-
llvm::DenseMap<std::pair<const KeyPathExpr *, unsigned>, TypeBase *>
2186+
2187+
/// The nodes for which we have produced types, along with the prior type
2188+
/// each node had before introducing this type.
2189+
llvm::SmallVector<std::pair<ASTNode, Type>, 8> addedNodeTypes;
2190+
2191+
/// Maps components in a key path expression to their type. Needed because
2192+
/// KeyPathExpr + Index isn't an \c ASTNode and thus can't be stored in \c
2193+
/// NodeTypes.
2194+
llvm::DenseMap<std::pair<const KeyPathExpr *, /*component index=*/unsigned>,
2195+
Type>
21872196
KeyPathComponentTypes;
21882197

2198+
/// Same as \c addedNodeTypes for \c KeyPathComponentTypes.
2199+
llvm::SmallVector<
2200+
std::tuple<const KeyPathExpr *, /*component index=*/unsigned, Type>>
2201+
addedKeyPathComponentTypes;
2202+
21892203
/// Maps AST entries to their solution application targets.
21902204
llvm::MapVector<SolutionApplicationTargetsKey, SolutionApplicationTarget>
21912205
solutionApplicationTargets;
@@ -2266,10 +2280,6 @@ class ConstraintSystem {
22662280
SmallVector<std::pair<ConstraintLocator *, OpenedArchetypeType *>, 4>
22672281
OpenedExistentialTypes;
22682282

2269-
/// The nodes for which we have produced types, along with the prior type
2270-
/// each node had before introducing this type.
2271-
llvm::SmallVector<std::pair<ASTNode, Type>, 8> addedNodeTypes;
2272-
22732283
/// The set of functions that have been transformed by a result builder.
22742284
std::vector<std::pair<AnyFunctionRef, AppliedBuilderTransform>>
22752285
resultBuilderTransformed;
@@ -2739,6 +2749,8 @@ class ConstraintSystem {
27392749

27402750
unsigned numAddedNodeTypes;
27412751

2752+
unsigned numAddedKeyPathComponentTypes;
2753+
27422754
unsigned numDisabledConstraints;
27432755

27442756
unsigned numFavoredConstraints;
@@ -2954,10 +2966,15 @@ class ConstraintSystem {
29542966
/// map is used throughout the expression type checker in order to
29552967
/// avoid mutating expressions until we know we have successfully
29562968
/// type-checked them.
2957-
void setType(KeyPathExpr *KP, unsigned I, Type T) {
2969+
void setType(const KeyPathExpr *KP, unsigned I, Type T) {
29582970
assert(KP && "Expected non-null key path parameter!");
29592971
assert(T && "Expected non-null type!");
2960-
KeyPathComponentTypes[std::make_pair(KP, I)] = T.getPointer();
2972+
2973+
Type &entry = KeyPathComponentTypes[{KP, I}];
2974+
Type oldType = entry;
2975+
entry = T;
2976+
2977+
addedKeyPathComponentTypes.push_back(std::make_tuple(KP, I, oldType));
29612978
}
29622979

29632980
/// Check to see if we have a type for a node.

lib/Sema/CSSolver.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,11 @@ void ConstraintSystem::applySolution(const Solution &solution) {
260260
setType(nodeType.first, nodeType.second);
261261
}
262262

263+
for (auto &nodeType : solution.keyPathComponentTypes) {
264+
setType(nodeType.getFirst().first, nodeType.getFirst().second,
265+
nodeType.getSecond());
266+
}
267+
263268
// Add the contextual types.
264269
for (const auto &contextualType : solution.contextualTypes) {
265270
if (!getContextualTypeInfo(contextualType.first)) {
@@ -489,6 +494,7 @@ ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs)
489494
numOpenedExistentialTypes = cs.OpenedExistentialTypes.size();
490495
numDefaultedConstraints = cs.DefaultedConstraints.size();
491496
numAddedNodeTypes = cs.addedNodeTypes.size();
497+
numAddedKeyPathComponentTypes = cs.addedKeyPathComponentTypes.size();
492498
numDisabledConstraints = cs.solverState->getNumDisabledConstraints();
493499
numFavoredConstraints = cs.solverState->getNumFavoredConstraints();
494500
numResultBuilderTransformed = cs.resultBuilderTransformed.size();
@@ -570,6 +576,19 @@ ConstraintSystem::SolverScope::~SolverScope() {
570576
}
571577
truncate(cs.addedNodeTypes, numAddedNodeTypes);
572578

579+
// Remove any node types we registered.
580+
for (unsigned i : reverse(range(numAddedKeyPathComponentTypes,
581+
cs.addedKeyPathComponentTypes.size()))) {
582+
auto KeyPath = std::get<0>(cs.addedKeyPathComponentTypes[i]);
583+
auto KeyPathIndex = std::get<1>(cs.addedKeyPathComponentTypes[i]);
584+
if (Type oldType = std::get<2>(cs.addedKeyPathComponentTypes[i])) {
585+
cs.KeyPathComponentTypes[{KeyPath, KeyPathIndex}] = oldType;
586+
} else {
587+
cs.KeyPathComponentTypes.erase({KeyPath, KeyPathIndex});
588+
}
589+
}
590+
truncate(cs.addedKeyPathComponentTypes, numAddedKeyPathComponentTypes);
591+
573592
/// Remove any builder transformed closures.
574593
truncate(cs.resultBuilderTransformed, numResultBuilderTransformed);
575594

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %swift-ide-test --code-completion --source-filename %s -code-completion-token CC
2+
3+
func foo() {
4+
let months: [[String]] = []
5+
let abcd: Int
6+
let x = ForEach2(months) { group in
7+
HStack2(spacing: 3) {
8+
useKeyPath(id: \.abcd#^CC^#)
9+
}
10+
}
11+
}
12+
13+
14+
struct ForEach2<Data> where Data : RandomAccessCollection {
15+
init(_ data: Data, content: @escaping (Data.Element) -> Void) {}
16+
}
17+
18+
struct Bar {
19+
let abcd: Int
20+
}
21+
22+
func useKeyPath(id: KeyPath<Bar, String>) {}
23+
24+
struct HStack2<Content> {
25+
init(spacing: Double, @ViewBuilder2 content: () -> Content)
26+
}
27+
28+
@resultBuilder struct ViewBuilder2 {
29+
static func buildBlock<Content>(_ content: Content) -> Content { fatalError() }
30+
}

0 commit comments

Comments
 (0)