Skip to content

Commit c31a590

Browse files
authored
Merge pull request swiftlang#39988 from hborla/result-builder-attr-substitution
[Result Builders] Correct type witness substitution when computing inferred result builder attributes from protocol requirements.
2 parents 3ea9e9e + 17def18 commit c31a590

File tree

2 files changed

+68
-4
lines changed

2 files changed

+68
-4
lines changed

lib/Sema/TypeCheckRequestFunctions.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -297,10 +297,17 @@ static Type inferResultBuilderType(ValueDecl *decl) {
297297
if (witness != lookupDecl)
298298
continue;
299299

300-
// Substitute into the result builder type.
301-
auto subs =
302-
conformance->getSubstitutions(lookupDecl->getModuleContext());
303-
Type subResultBuilderType = resultBuilderType.subst(subs);
300+
// Substitute Self and associated type witnesses into the
301+
// result builder type. Then, map all type parameters from
302+
// the conforming type into context. We don't want type
303+
// parameters to appear in the result builder type, because
304+
// the result builder type will only be used inside the body
305+
// of this decl; it's not part of the interface type.
306+
auto subs = SubstitutionMap::getProtocolSubstitutions(
307+
protocol, dc->getSelfInterfaceType(),
308+
ProtocolConformanceRef(conformance));
309+
Type subResultBuilderType = dc->mapTypeIntoContext(
310+
resultBuilderType.subst(subs));
304311

305312
matches.push_back(
306313
Match::forConformance(
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// RUN: %target-swift-frontend -dump-ast %s | %FileCheck %s
2+
3+
protocol P {
4+
associatedtype A
5+
6+
@Builder<A>
7+
var x1: [S] { get }
8+
9+
@Builder<Self>
10+
var x2: [S] { get }
11+
}
12+
13+
@resultBuilder
14+
enum Builder<T> {
15+
static func buildBlock(_ args: S...) -> [S] { args }
16+
}
17+
18+
struct S {}
19+
20+
// CHECK: struct_decl{{.*}}ProtocolSubstitution
21+
struct ProtocolSubstitution: P {
22+
typealias A = Int
23+
24+
// CHECK: var_decl{{.*}}x1
25+
// CHECK: Builder.buildBlock{{.*}}(substitution_map generic_signature=<T> (substitution T -> Int))
26+
var x1: [S] { S() }
27+
28+
// CHECK: var_decl{{.*}}x2
29+
// CHECK: Builder.buildBlock{{.*}}(substitution_map generic_signature=<T> (substitution T -> ProtocolSubstitution))
30+
var x2: [S] { S() }
31+
}
32+
33+
// CHECK: struct_decl{{.*}}ArchetypeSubstitution
34+
struct ArchetypeSubstitution<A>: P {
35+
// CHECK: var_decl{{.*}}x1
36+
// CHECK: Builder.buildBlock{{.*}}(substitution_map generic_signature=<T> (substitution T -> A))
37+
var x1: [S] { S() }
38+
39+
// CHECK: var_decl{{.*}}x2
40+
// CHECK: Builder.buildBlock{{.*}}(substitution_map generic_signature=<T> (substitution T -> ArchetypeSubstitution<A>))
41+
var x2: [S] { S() }
42+
}
43+
44+
// CHECK: struct_decl{{.*}}ConcreteTypeSubstitution
45+
struct ConcreteTypeSubstitution<Value> {}
46+
47+
extension ConcreteTypeSubstitution: P where Value == Int {
48+
typealias A = Value
49+
50+
// CHECK: var_decl{{.*}}x1
51+
// CHECK: Builder.buildBlock{{.*}}(substitution_map generic_signature=<T> (substitution T -> Int))
52+
var x1: [S] { S() }
53+
54+
// CHECK: var_decl{{.*}}x2
55+
// CHECK: Builder.buildBlock{{.*}}(substitution_map generic_signature=<T> (substitution T -> ConcreteTypeSubstitution<Int>))
56+
var x2: [S] { S() }
57+
}

0 commit comments

Comments
 (0)