Skip to content

Commit b2813e1

Browse files
committed
[CS] Connect arg-to-param constraint to function builder
Previously we could inadvertently split the constraint system without realizing that a function builder with a generic argument may allow the closure body to reference a type variable that connects it to the enclosing expression. Fix this issue by checking for an unresolved closure argument and forming an unresolved argument conversion constraint that includes any type variables from the function builder type. Resolves SR-13183 Resolves rdar://problem/65695054
1 parent a2f9a69 commit b2813e1

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9905,9 +9905,11 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first,
99059905
case ConstraintKind::BindToPointerType:
99069906
case ConstraintKind::Subtype:
99079907
case ConstraintKind::Conversion:
9908+
return matchTypes(first, second, kind, subflags, locator);
9909+
99089910
case ConstraintKind::ArgumentConversion:
99099911
case ConstraintKind::OperatorArgumentConversion:
9910-
return matchTypes(first, second, kind, subflags, locator);
9912+
return addArgumentConversionConstraintImpl(kind, first, second, locator);
99119913

99129914
case ConstraintKind::OpaqueUnderlyingType:
99139915
return simplifyOpaqueUnderlyingTypeConstraint(first, second,
@@ -9977,6 +9979,36 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first,
99779979
llvm_unreachable("Unhandled ConstraintKind in switch.");
99789980
}
99799981

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+
998010012
void
998110013
ConstraintSystem::addKeyPathApplicationRootConstraint(Type root, ConstraintLocatorBuilder locator) {
998210014
// 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
@@ -4686,6 +4686,13 @@ class ConstraintSystem {
46864686
ConstraintLocatorBuilder locator,
46874687
bool isFavored);
46884688

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

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)