Skip to content

Commit 3437ec9

Browse files
authored
Merge pull request #33005 from hamishknight/connect-four-builder
2 parents 32443e2 + b2813e1 commit 3437ec9

File tree

4 files changed

+108
-33
lines changed

4 files changed

+108
-33
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,6 @@ class BuilderClosureVisitor
208208
DeclContext *dc, Type builderType,
209209
Type bodyResultType)
210210
: cs(cs), dc(dc), ctx(ctx), builderType(builderType) {
211-
assert((cs || !builderType->hasTypeVariable()) &&
212-
"cannot handle builder type with type variables without "
213-
"constraint system");
214211
builder = builderType->getAnyNominal();
215212
applied.builderType = builderType;
216213
applied.bodyResultType = bodyResultType;
@@ -1635,22 +1632,6 @@ ConstraintSystem::matchFunctionBuilder(
16351632
}
16361633
}
16371634

1638-
// If the builder type has a type parameter, substitute in the type
1639-
// variables.
1640-
if (builderType->hasTypeParameter()) {
1641-
// Find the opened type for this callee and substitute in the type
1642-
// parametes.
1643-
for (const auto &opened : OpenedTypes) {
1644-
if (opened.first == calleeLocator) {
1645-
OpenedTypeMap replacements(opened.second.begin(),
1646-
opened.second.end());
1647-
builderType = openType(builderType, replacements);
1648-
break;
1649-
}
1650-
}
1651-
assert(!builderType->hasTypeParameter());
1652-
}
1653-
16541635
BuilderClosureVisitor visitor(getASTContext(), this, dc, builderType,
16551636
bodyResultType);
16561637

lib/Sema/CSSimplify.cpp

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7274,8 +7274,17 @@ ConstraintSystem::simplifyOneWayConstraint(
72747274
secondSimplified, first, ConstraintKind::BindParam, flags, locator);
72757275
}
72767276

7277-
static Type getFunctionBuilderTypeFor(ConstraintSystem &cs, unsigned paramIdx,
7278-
ConstraintLocator *calleeLocator) {
7277+
static Type getOpenedFunctionBuilderTypeFor(ConstraintSystem &cs,
7278+
ConstraintLocatorBuilder locator) {
7279+
auto lastElt = locator.last();
7280+
if (!lastElt)
7281+
return Type();
7282+
7283+
auto argToParamElt = lastElt->getAs<LocatorPathElt::ApplyArgToParam>();
7284+
if (!argToParamElt)
7285+
return Type();
7286+
7287+
auto *calleeLocator = cs.getCalleeLocator(cs.getConstraintLocator(locator));
72797288
auto selectedOverload = cs.findSelectedOverloadFor(calleeLocator);
72807289
if (!(selectedOverload &&
72817290
selectedOverload->choice.getKind() == OverloadChoiceKind::Decl))
@@ -7290,8 +7299,27 @@ static Type getFunctionBuilderTypeFor(ConstraintSystem &cs, unsigned paramIdx,
72907299
if (!choice->hasParameterList())
72917300
return Type();
72927301

7293-
auto *PD = getParameterAt(choice, paramIdx);
7294-
return PD->getFunctionBuilderType();
7302+
auto *PD = getParameterAt(choice, argToParamElt->getParamIdx());
7303+
auto builderType = PD->getFunctionBuilderType();
7304+
if (!builderType)
7305+
return Type();
7306+
7307+
// If the builder type has a type parameter, substitute in the type
7308+
// variables.
7309+
if (builderType->hasTypeParameter()) {
7310+
// Find the opened type for this callee and substitute in the type
7311+
// parametes.
7312+
// FIXME: We should consider changing OpenedTypes to a MapVector.
7313+
for (const auto &opened : cs.getOpenedTypes()) {
7314+
if (opened.first == calleeLocator) {
7315+
OpenedTypeMap replacements(opened.second.begin(), opened.second.end());
7316+
builderType = cs.openType(builderType, replacements);
7317+
break;
7318+
}
7319+
}
7320+
assert(!builderType->hasTypeParameter());
7321+
}
7322+
return builderType;
72957323
}
72967324

72977325
bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
@@ -7310,15 +7338,7 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
73107338
auto *inferredClosureType = getClosureType(closure);
73117339

73127340
// Determine whether a function builder will be applied.
7313-
Type functionBuilderType;
7314-
ConstraintLocator *calleeLocator = nullptr;
7315-
if (auto last = locator.last()) {
7316-
if (auto argToParam = last->getAs<LocatorPathElt::ApplyArgToParam>()) {
7317-
calleeLocator = getCalleeLocator(getConstraintLocator(locator));
7318-
functionBuilderType = getFunctionBuilderTypeFor(
7319-
*this, argToParam->getParamIdx(), calleeLocator);
7320-
}
7321-
}
7341+
auto functionBuilderType = getOpenedFunctionBuilderTypeFor(*this, locator);
73227342

73237343
// Determine whether to introduce one-way constraints between the parameter's
73247344
// type as seen in the body of the closure and the external parameter
@@ -7392,6 +7412,7 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
73927412

73937413
// If there is a function builder to apply, do so now.
73947414
if (functionBuilderType) {
7415+
auto *calleeLocator = getCalleeLocator(getConstraintLocator(locator));
73957416
if (auto result = matchFunctionBuilder(
73967417
closure, functionBuilderType, closureType->getResult(),
73977418
ConstraintKind::Conversion, calleeLocator, locator)) {
@@ -9884,9 +9905,11 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first,
98849905
case ConstraintKind::BindToPointerType:
98859906
case ConstraintKind::Subtype:
98869907
case ConstraintKind::Conversion:
9908+
return matchTypes(first, second, kind, subflags, locator);
9909+
98879910
case ConstraintKind::ArgumentConversion:
98889911
case ConstraintKind::OperatorArgumentConversion:
9889-
return matchTypes(first, second, kind, subflags, locator);
9912+
return addArgumentConversionConstraintImpl(kind, first, second, locator);
98909913

98919914
case ConstraintKind::OpaqueUnderlyingType:
98929915
return simplifyOpaqueUnderlyingTypeConstraint(first, second,
@@ -9956,6 +9979,36 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first,
99569979
llvm_unreachable("Unhandled ConstraintKind in switch.");
99579980
}
99589981

9982+
ConstraintSystem::SolutionKind
9983+
ConstraintSystem::addArgumentConversionConstraintImpl(
9984+
ConstraintKind kind, Type first, Type second,
9985+
ConstraintLocatorBuilder locator) {
9986+
assert(kind == ConstraintKind::ArgumentConversion ||
9987+
kind == ConstraintKind::OperatorArgumentConversion);
9988+
9989+
// If we have an unresolved closure argument, form an unsolved argument
9990+
// conversion constraint, making sure to reference the type variables for
9991+
// a function builder if applicable. This ensures we properly connect the
9992+
// closure type variable with any type variables in the function builder, as
9993+
// such type variables will be accessible within the body of the closure when
9994+
// we open it.
9995+
first = getFixedTypeRecursive(first, /*rvalue*/ false);
9996+
if (auto *argTypeVar = first->getAs<TypeVariableType>()) {
9997+
if (argTypeVar->getImpl().isClosureType()) {
9998+
// Extract any type variables present in the parameter's function builder.
9999+
SmallVector<TypeVariableType *, 4> typeVars;
10000+
if (auto builderTy = getOpenedFunctionBuilderTypeFor(*this, locator))
10001+
builderTy->getTypeVariables(typeVars);
10002+
10003+
auto *loc = getConstraintLocator(locator);
10004+
addUnsolvedConstraint(
10005+
Constraint::create(*this, kind, first, second, loc, typeVars));
10006+
return SolutionKind::Solved;
10007+
}
10008+
}
10009+
return matchTypes(first, second, kind, TMF_GenerateConstraints, locator);
10010+
}
10011+
995910012
void
996010013
ConstraintSystem::addKeyPathApplicationRootConstraint(Type root, ConstraintLocatorBuilder locator) {
996110014
// If this is a subscript with a KeyPath expression, add a constraint that

lib/Sema/ConstraintSystem.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4685,6 +4685,13 @@ class ConstraintSystem {
46854685
ConstraintLocatorBuilder locator,
46864686
bool isFavored);
46874687

4688+
/// Adds a constraint for the conversion of an argument to a parameter. Do not
4689+
/// call directly, use \c addConstraint instead.
4690+
SolutionKind
4691+
addArgumentConversionConstraintImpl(ConstraintKind kind, Type first,
4692+
Type second,
4693+
ConstraintLocatorBuilder locator);
4694+
46884695
/// Collect the current inactive disjunction constraints.
46894696
void collectDisjunctions(SmallVectorImpl<Constraint *> &disjunctions);
46904697

test/Constraints/sr13183.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// SR-13183: Make sure we don't incorrectly split the constraint system without
4+
// considering that a function builder type var may connect the inside of a
5+
// closure body with the enclosing expression.
6+
7+
struct New<Value> {
8+
init(value: Value, @ScopeBuilder<Value> scope: () -> Component) { }
9+
}
10+
11+
struct Component {}
12+
13+
struct Map<Value, Transformed> {
14+
let transform: (Value) -> Transformed
15+
}
16+
17+
@_functionBuilder
18+
struct ScopeBuilder<Value> {
19+
static func buildExpression<T>(_ map: Map<Value, T>) -> Component {
20+
Component()
21+
}
22+
23+
static func buildBlock(_ components: Component...) -> Component {
24+
Component()
25+
}
26+
}
27+
28+
let new1 = New(value: 42) {
29+
Map { $0.description }
30+
}
31+
32+
let new2 = New<Int>(value: 42) {
33+
Map { $0.description }
34+
}

0 commit comments

Comments
 (0)