Skip to content

Commit 3e090b4

Browse files
authored
Merge pull request #32893 from CodaFi/build-a-bear
Fix a Source Break With Function Builders
2 parents 864c126 + 53505c7 commit 3e090b4

File tree

3 files changed

+36
-2
lines changed

3 files changed

+36
-2
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,21 @@ class BuilderClosureVisitor
8080
auto simplifiedTy = cs->simplifyType(builderType);
8181
if (!simplifiedTy->hasTypeVariable()) {
8282
typeExpr = TypeExpr::createImplicitHack(loc, simplifiedTy, ctx);
83+
} else if (auto *decl = simplifiedTy->getAnyGeneric()) {
84+
// HACK: If there's not enough information to completely resolve the
85+
// builder type, but we have the base available to us, form an *explicit*
86+
// TypeExpr pointing at it. We cannot form an implicit base without
87+
// a fully-resolved concrete type. Really, whatever we put here has no
88+
// bearing on the generated solution because we're going to use this node
89+
// to stash the builder type and hand it back to the ambient
90+
// constraint system.
91+
typeExpr = TypeExpr::createForDecl(DeclNameLoc(loc), decl, dc);
8392
} else {
8493
// HACK: If there's not enough information in the constraint system,
8594
// create a garbage base type to force it to diagnose
8695
// this as an ambiguous expression.
96+
// FIXME: We can also construct an UnresolvedMemberExpr here instead of
97+
// an UnresolvedDotExpr and get a slightly better diagnostic.
8798
typeExpr = TypeExpr::createImplicitHack(loc, ErrorType::get(ctx), ctx);
8899
}
89100
cs->setType(typeExpr, MetatypeType::get(builderType));

lib/Sema/CSGen.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,13 @@ namespace {
14721472
type = CS.getInstanceType(CS.cacheType(E));
14731473
assert(type && "Implicit type expr must have type set!");
14741474
type = CS.openUnboundGenericTypes(type, locator);
1475+
} else if (CS.hasType(E)) {
1476+
// If there's a type already set into the constraint system, honor it.
1477+
// FIXME: This supports the function builder transform, which sneakily
1478+
// stashes a type in the constraint system through a TypeExpr in order
1479+
// to pass it down to the rest of CSGen. This is a terribly
1480+
// unprincipled thing to do.
1481+
return CS.getType(E);
14751482
} else {
14761483
auto *repr = E->getTypeRepr();
14771484
assert(repr && "Explicit node has no type repr!");

test/Constraints/rdar64890308.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ class ArrayBuilder<Element> {
1313

1414
func foo<T>(@ArrayBuilder<T> fn: () -> [T]) {}
1515

16-
// FIXME(SR-13132): This should compile.
17-
foo { // expected-error {{type of expression is ambiguous without more context}}
16+
foo {
1817
""
1918
}
2019

@@ -29,3 +28,20 @@ func bar<T>(_ x: T, _ fn: (T, T.Type) -> [T]) {}
2928
bar("") { x, ty in
3029
(Builtin.one_way(S(ty).overloaded(x)))
3130
}
31+
32+
protocol P {}
33+
extension String : P {}
34+
35+
@_functionBuilder
36+
struct FooBuilder<T> {}
37+
38+
extension FooBuilder where T : P {
39+
static func buildBlock(_ x: Int, _ y: Int) -> String { "" }
40+
}
41+
42+
func foo<T : P>(@FooBuilder<T> fn: () -> T) {}
43+
44+
foo {
45+
0
46+
0
47+
}

0 commit comments

Comments
 (0)