Skip to content

Commit 985843a

Browse files
committed
[ConstraintSystem] Add a new transitive conformance constraint
Conformance constraints could be transferred through conversions, but that would also require checking implicit conversions such as optional and pointer promotions for conformance is the type itself doesn't conform, for that let's add a special constraint `TransitivelyConformsTo`.
1 parent 4de232e commit 985843a

File tree

6 files changed

+48
-1
lines changed

6 files changed

+48
-1
lines changed

include/swift/Sema/Constraint.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ enum class ConstraintKind : char {
190190
/// The first type is a property wrapper with a wrapped-value type
191191
/// equal to the second type.
192192
PropertyWrapper,
193+
/// The first type (or its optional or pointer version) must conform to a
194+
/// second type (protocol type). This is not a direct requirement but one
195+
/// inferred from a conversion, so the check is more relax comparing to
196+
/// `ConformsTo`.
197+
TransitivelyConformsTo,
193198
};
194199

195200
/// Classification of the different kinds of constraints.
@@ -579,6 +584,7 @@ class Constraint final : public llvm::ilist_node<Constraint>,
579584
case ConstraintKind::OperatorArgumentConversion:
580585
case ConstraintKind::ConformsTo:
581586
case ConstraintKind::LiteralConformsTo:
587+
case ConstraintKind::TransitivelyConformsTo:
582588
case ConstraintKind::CheckedCast:
583589
case ConstraintKind::SelfObjectOfProtocol:
584590
case ConstraintKind::ApplicableFunction:

include/swift/Sema/ConstraintSystem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4513,6 +4513,12 @@ class ConstraintSystem {
45134513
ConstraintLocatorBuilder locator,
45144514
TypeMatchOptions flags);
45154515

4516+
/// Similar to \c simplifyConformsToConstraint but also checks for
4517+
/// optional and pointer derived a given type.
4518+
SolutionKind simplifyTransitivelyConformsTo(Type type, Type protocol,
4519+
ConstraintLocatorBuilder locator,
4520+
TypeMatchOptions flags);
4521+
45164522
/// Attempt to simplify a checked-cast constraint.
45174523
SolutionKind simplifyCheckedCastConstraint(Type fromType, Type toType,
45184524
TypeMatchOptions flags,

lib/Sema/CSBindings.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,12 @@ void PotentialBindings::infer(Constraint *constraint) {
13121312
// Constraints from which we can't do anything.
13131313
break;
13141314

1315+
// For now let's avoid inferring protocol requirements from
1316+
// this constraint, but in the future we could do that to
1317+
// to filter bindings.
1318+
case ConstraintKind::TransitivelyConformsTo:
1319+
break;
1320+
13151321
case ConstraintKind::DynamicTypeOf: {
13161322
// Direct binding of the left-hand side could result
13171323
// in `DynamicTypeOf` failure if right-hand side is

lib/Sema/CSSimplify.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,6 +1542,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
15421542
case ConstraintKind::BindOverload:
15431543
case ConstraintKind::CheckedCast:
15441544
case ConstraintKind::ConformsTo:
1545+
case ConstraintKind::TransitivelyConformsTo:
15451546
case ConstraintKind::Defaultable:
15461547
case ConstraintKind::Disjunction:
15471548
case ConstraintKind::DynamicTypeOf:
@@ -1682,6 +1683,7 @@ static bool matchFunctionRepresentations(FunctionType::ExtInfo einfo1,
16821683
case ConstraintKind::BindOverload:
16831684
case ConstraintKind::CheckedCast:
16841685
case ConstraintKind::ConformsTo:
1686+
case ConstraintKind::TransitivelyConformsTo:
16851687
case ConstraintKind::Defaultable:
16861688
case ConstraintKind::Disjunction:
16871689
case ConstraintKind::DynamicTypeOf:
@@ -2072,6 +2074,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
20722074
case ConstraintKind::BindOverload:
20732075
case ConstraintKind::CheckedCast:
20742076
case ConstraintKind::ConformsTo:
2077+
case ConstraintKind::TransitivelyConformsTo:
20752078
case ConstraintKind::Defaultable:
20762079
case ConstraintKind::Disjunction:
20772080
case ConstraintKind::DynamicTypeOf:
@@ -4983,6 +4986,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
49834986
case ConstraintKind::BridgingConversion:
49844987
case ConstraintKind::CheckedCast:
49854988
case ConstraintKind::ConformsTo:
4989+
case ConstraintKind::TransitivelyConformsTo:
49864990
case ConstraintKind::Defaultable:
49874991
case ConstraintKind::Disjunction:
49884992
case ConstraintKind::DynamicTypeOf:
@@ -6186,6 +6190,12 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
61866190
return SolutionKind::Error;
61876191
}
61886192

6193+
ConstraintSystem::SolutionKind ConstraintSystem::simplifyTransitivelyConformsTo(
6194+
Type type, Type protocolTy, ConstraintLocatorBuilder locator,
6195+
TypeMatchOptions flags) {
6196+
return SolutionKind::Error;
6197+
}
6198+
61896199
/// Determine the kind of checked cast to perform from the given type to
61906200
/// the given type.
61916201
///
@@ -11259,6 +11269,10 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first,
1125911269
return simplifyConformsToConstraint(first, second, kind, locator,
1126011270
subflags);
1126111271

11272+
case ConstraintKind::TransitivelyConformsTo:
11273+
return simplifyTransitivelyConformsTo(first, second, locator,
11274+
subflags);
11275+
1126211276
case ConstraintKind::CheckedCast:
1126311277
return simplifyCheckedCastConstraint(first, second, subflags, locator);
1126411278

@@ -11727,6 +11741,13 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
1172711741
constraint.getLocator(),
1172811742
None);
1172911743

11744+
case ConstraintKind::TransitivelyConformsTo:
11745+
return simplifyTransitivelyConformsTo(
11746+
constraint.getFirstType(),
11747+
constraint.getSecondType(),
11748+
constraint.getLocator(),
11749+
None);
11750+
1173011751
case ConstraintKind::CheckedCast: {
1173111752
auto result = simplifyCheckedCastConstraint(constraint.getFirstType(),
1173211753
constraint.getSecondType(),

lib/Sema/CSSolver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2232,6 +2232,7 @@ void DisjunctionChoice::propagateConversionInfo(ConstraintSystem &cs) const {
22322232
case ConstraintKind::Defaultable:
22332233
case ConstraintKind::ConformsTo:
22342234
case ConstraintKind::LiteralConformsTo:
2235+
case ConstraintKind::TransitivelyConformsTo:
22352236
return false;
22362237

22372238
default:

lib/Sema/Constraint.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second,
5656
case ConstraintKind::OperatorArgumentConversion:
5757
case ConstraintKind::ConformsTo:
5858
case ConstraintKind::LiteralConformsTo:
59+
case ConstraintKind::TransitivelyConformsTo:
5960
case ConstraintKind::CheckedCast:
6061
case ConstraintKind::SelfObjectOfProtocol:
6162
case ConstraintKind::DynamicTypeOf:
@@ -124,6 +125,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second, Type Third,
124125
case ConstraintKind::OperatorArgumentConversion:
125126
case ConstraintKind::ConformsTo:
126127
case ConstraintKind::LiteralConformsTo:
128+
case ConstraintKind::TransitivelyConformsTo:
127129
case ConstraintKind::CheckedCast:
128130
case ConstraintKind::SelfObjectOfProtocol:
129131
case ConstraintKind::DynamicTypeOf:
@@ -241,7 +243,8 @@ Constraint::Constraint(ConstraintKind kind, ConstraintFix *fix, Type first,
241243
ProtocolDecl *Constraint::getProtocol() const {
242244
assert((Kind == ConstraintKind::ConformsTo ||
243245
Kind == ConstraintKind::LiteralConformsTo ||
244-
Kind == ConstraintKind::SelfObjectOfProtocol)
246+
Kind == ConstraintKind::SelfObjectOfProtocol ||
247+
Kind == ConstraintKind::TransitivelyConformsTo)
245248
&& "Not a conformance constraint");
246249
return Types.Second->castTo<ProtocolType>()->getDecl();
247250
}
@@ -259,6 +262,7 @@ Constraint *Constraint::clone(ConstraintSystem &cs) const {
259262
case ConstraintKind::OperatorArgumentConversion:
260263
case ConstraintKind::ConformsTo:
261264
case ConstraintKind::LiteralConformsTo:
265+
case ConstraintKind::TransitivelyConformsTo:
262266
case ConstraintKind::CheckedCast:
263267
case ConstraintKind::DynamicTypeOf:
264268
case ConstraintKind::EscapableFunctionOf:
@@ -357,6 +361,7 @@ void Constraint::print(llvm::raw_ostream &Out, SourceManager *sm) const {
357361
Out << " operator arg conv "; break;
358362
case ConstraintKind::ConformsTo: Out << " conforms to "; break;
359363
case ConstraintKind::LiteralConformsTo: Out << " literal conforms to "; break;
364+
case ConstraintKind::TransitivelyConformsTo: Out << " transitive conformance to "; break;
360365
case ConstraintKind::CheckedCast: Out << " checked cast to "; break;
361366
case ConstraintKind::SelfObjectOfProtocol: Out << " Self type of "; break;
362367
case ConstraintKind::ApplicableFunction: Out << " applicable fn "; break;
@@ -599,6 +604,7 @@ gatherReferencedTypeVars(Constraint *constraint,
599604
case ConstraintKind::Defaultable:
600605
case ConstraintKind::ConformsTo:
601606
case ConstraintKind::LiteralConformsTo:
607+
case ConstraintKind::TransitivelyConformsTo:
602608
case ConstraintKind::SelfObjectOfProtocol:
603609
case ConstraintKind::FunctionInput:
604610
case ConstraintKind::FunctionResult:
@@ -659,6 +665,7 @@ Constraint *Constraint::create(ConstraintSystem &cs, ConstraintKind kind,
659665

660666
// Conformance constraints expect an existential on the right-hand side.
661667
assert((kind != ConstraintKind::ConformsTo &&
668+
kind != ConstraintKind::TransitivelyConformsTo &&
662669
kind != ConstraintKind::SelfObjectOfProtocol) ||
663670
second->isExistentialType());
664671

0 commit comments

Comments
 (0)