Skip to content

Commit 497d42d

Browse files
committed
[ConstraintSystem] Add a new constraint which connects base with result of the member chain
The first type represents a result of an unresolved member chain, and the second type is its base type. This constraint acts almost like `Equal` but also enforces following semantics: - It's possible to infer a base from a result type by looking through this constraint, but it's only solved when both types are bound. - If base is a protocol metatype, this constraint becomes a conformance check instead of an equality.
1 parent 9231acf commit 497d42d

File tree

5 files changed

+60
-1
lines changed

5 files changed

+60
-1
lines changed

include/swift/Sema/Constraint.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,16 @@ enum class ConstraintKind : char {
177177
/// - Handled specially by binding inference, specifically contributes
178178
/// to the bindings only if there are no contextual types available.
179179
DefaultClosureType,
180+
/// The first type represents a result of an unresolved member chain,
181+
/// and the second type is its base type. This constraint acts almost
182+
/// like `Equal` but also enforces following semantics:
183+
///
184+
/// - It's possible to infer a base from a result type by looking through
185+
/// this constraint, but it's only solved when both types are bound.
186+
///
187+
/// - If base is a protocol metatype, this constraint becomes a conformance
188+
/// check instead of an equality.
189+
UnresolvedMemberChainBase,
180190
};
181191

182192
/// Classification of the different kinds of constraints.
@@ -570,6 +580,7 @@ class Constraint final : public llvm::ilist_node<Constraint>,
570580
case ConstraintKind::OneWayEqual:
571581
case ConstraintKind::OneWayBindParam:
572582
case ConstraintKind::DefaultClosureType:
583+
case ConstraintKind::UnresolvedMemberChainBase:
573584
return ConstraintClassification::Relational;
574585

575586
case ConstraintKind::ValueMember:

include/swift/Sema/ConstraintSystem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4568,6 +4568,12 @@ class ConstraintSystem {
45684568
TypeMatchOptions flags,
45694569
ConstraintLocatorBuilder locator);
45704570

4571+
/// Simplify an equality constraint between result and base types of
4572+
/// a unresolved member chain.
4573+
SolutionKind simplifyUnresolvedMemberChainBaseConstraint(
4574+
Type first, Type second, TypeMatchOptions flags,
4575+
ConstraintLocatorBuilder locator);
4576+
45714577
/// Simplify a conversion constraint by applying the given
45724578
/// reduction rule, which is known to apply at the outermost level.
45734579
SolutionKind simplifyRestrictedConstraintImpl(

lib/Sema/CSBindings.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1158,7 +1158,8 @@ void PotentialBindings::infer(Constraint *constraint) {
11581158
case ConstraintKind::Conversion:
11591159
case ConstraintKind::ArgumentConversion:
11601160
case ConstraintKind::OperatorArgumentConversion:
1161-
case ConstraintKind::OptionalObject: {
1161+
case ConstraintKind::OptionalObject:
1162+
case ConstraintKind::UnresolvedMemberChainBase: {
11621163
auto binding = inferFromRelational(constraint);
11631164
if (!binding)
11641165
break;

lib/Sema/CSSimplify.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,6 +1541,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
15411541
case ConstraintKind::OneWayEqual:
15421542
case ConstraintKind::OneWayBindParam:
15431543
case ConstraintKind::DefaultClosureType:
1544+
case ConstraintKind::UnresolvedMemberChainBase:
15441545
llvm_unreachable("Not a conversion");
15451546
}
15461547

@@ -1678,6 +1679,7 @@ static bool matchFunctionRepresentations(FunctionType::ExtInfo einfo1,
16781679
case ConstraintKind::OneWayEqual:
16791680
case ConstraintKind::OneWayBindParam:
16801681
case ConstraintKind::DefaultClosureType:
1682+
case ConstraintKind::UnresolvedMemberChainBase:
16811683
return true;
16821684
}
16831685

@@ -2032,6 +2034,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
20322034
case ConstraintKind::OneWayEqual:
20332035
case ConstraintKind::OneWayBindParam:
20342036
case ConstraintKind::DefaultClosureType:
2037+
case ConstraintKind::UnresolvedMemberChainBase:
20352038
llvm_unreachable("Not a relational constraint");
20362039
}
20372040

@@ -4896,6 +4899,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
48964899
case ConstraintKind::OneWayEqual:
48974900
case ConstraintKind::OneWayBindParam:
48984901
case ConstraintKind::DefaultClosureType:
4902+
case ConstraintKind::UnresolvedMemberChainBase:
48994903
llvm_unreachable("Not a relational constraint");
49004904
}
49014905
}
@@ -7955,6 +7959,27 @@ ConstraintSystem::simplifyOneWayConstraint(
79557959
secondSimplified, first, ConstraintKind::BindParam, flags, locator);
79567960
}
79577961

7962+
ConstraintSystem::SolutionKind
7963+
ConstraintSystem::simplifyUnresolvedMemberChainBaseConstraint(
7964+
Type first, Type second, TypeMatchOptions flags,
7965+
ConstraintLocatorBuilder locator) {
7966+
auto resultTy = getFixedTypeRecursive(first, flags, /*wantRValue=*/true);
7967+
auto baseTy = getFixedTypeRecursive(second, flags, /*wantRValue=*/true);
7968+
7969+
if (baseTy->isTypeVariableOrMember() || resultTy->isTypeVariableOrMember()) {
7970+
if (flags.contains(TMF_GenerateConstraints)) {
7971+
addUnsolvedConstraint(
7972+
Constraint::create(*this, ConstraintKind::UnresolvedMemberChainBase,
7973+
first, second, getConstraintLocator(locator)));
7974+
return SolutionKind::Solved;
7975+
}
7976+
7977+
return SolutionKind::Unsolved;
7978+
}
7979+
7980+
return matchTypes(baseTy, resultTy, ConstraintKind::Equal, flags, locator);
7981+
}
7982+
79587983
static Type getOpenedResultBuilderTypeFor(ConstraintSystem &cs,
79597984
ConstraintLocatorBuilder locator) {
79607985
auto lastElt = locator.last();
@@ -10761,6 +10786,10 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first,
1076110786
case ConstraintKind::OneWayBindParam:
1076210787
return simplifyOneWayConstraint(kind, first, second, subflags, locator);
1076310788

10789+
case ConstraintKind::UnresolvedMemberChainBase:
10790+
return simplifyUnresolvedMemberChainBaseConstraint(first, second, subflags,
10791+
locator);
10792+
1076410793
case ConstraintKind::ValueMember:
1076510794
case ConstraintKind::UnresolvedValueMember:
1076610795
case ConstraintKind::ValueWitness:
@@ -11280,6 +11309,11 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
1128011309
constraint.getFirstType(),
1128111310
constraint.getSecondType(),
1128211311
/*flags*/ None, constraint.getLocator());
11312+
11313+
case ConstraintKind::UnresolvedMemberChainBase:
11314+
return simplifyUnresolvedMemberChainBaseConstraint(
11315+
constraint.getFirstType(), constraint.getSecondType(),
11316+
/*flags=*/None, constraint.getLocator());
1128311317
}
1128411318

1128511319
llvm_unreachable("Unhandled ConstraintKind in switch.");

lib/Sema/Constraint.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second,
6767
case ConstraintKind::OpaqueUnderlyingType:
6868
case ConstraintKind::OneWayEqual:
6969
case ConstraintKind::OneWayBindParam:
70+
case ConstraintKind::UnresolvedMemberChainBase:
7071
assert(!First.isNull());
7172
assert(!Second.isNull());
7273
break;
@@ -142,6 +143,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second, Type Third,
142143
case ConstraintKind::OneWayEqual:
143144
case ConstraintKind::OneWayBindParam:
144145
case ConstraintKind::DefaultClosureType:
146+
case ConstraintKind::UnresolvedMemberChainBase:
145147
llvm_unreachable("Wrong constructor");
146148

147149
case ConstraintKind::KeyPath:
@@ -269,6 +271,7 @@ Constraint *Constraint::clone(ConstraintSystem &cs) const {
269271
case ConstraintKind::OneWayEqual:
270272
case ConstraintKind::OneWayBindParam:
271273
case ConstraintKind::DefaultClosureType:
274+
case ConstraintKind::UnresolvedMemberChainBase:
272275
return create(cs, getKind(), getFirstType(), getSecondType(), getLocator());
273276

274277
case ConstraintKind::ApplicableFunction:
@@ -364,6 +367,9 @@ void Constraint::print(llvm::raw_ostream &Out, SourceManager *sm) const {
364367
case ConstraintKind::DefaultClosureType:
365368
Out << " closure can default to ";
366369
break;
370+
case ConstraintKind::UnresolvedMemberChainBase:
371+
Out << " unresolved member chain base ";
372+
break;
367373
case ConstraintKind::KeyPath:
368374
Out << " key path from ";
369375
Out << getSecondType()->getString(PO);
@@ -590,6 +596,7 @@ gatherReferencedTypeVars(Constraint *constraint,
590596
case ConstraintKind::OneWayEqual:
591597
case ConstraintKind::OneWayBindParam:
592598
case ConstraintKind::DefaultClosureType:
599+
case ConstraintKind::UnresolvedMemberChainBase:
593600
constraint->getFirstType()->getTypeVariables(typeVars);
594601
constraint->getSecondType()->getTypeVariables(typeVars);
595602
break;

0 commit comments

Comments
 (0)