Skip to content

Commit 635d253

Browse files
committed
Unify ParameterizedProtocolTypes
Add deep equality typing rules for P =~= Q, T == X, U == Y, V == Z, ... -------------------------------- P<T, U, V, ...> == Q<X, Y, Z, ...> Also add existential matching rules to discharge the constraints on parameterized protocols against concrete types. e.g. class C: P { typealias T = Int } func foo<T>(_ x: P<T>) {} foo(C()) Should cause T to unify against C.T = Int
1 parent e3119a8 commit 635d253

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3135,8 +3135,18 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
31353135
return result;
31363136
}
31373137

3138+
// Arguments of parameterized protocol types have to match on the nose.
3139+
if (auto ppt1 = type1->getAs<ParameterizedProtocolType>()) {
3140+
auto ppt2 = type2->castTo<ParameterizedProtocolType>();
3141+
return matchDeepTypeArguments(*this, subflags,
3142+
ppt1->getArgs(),
3143+
ppt2->getArgs(),
3144+
locator);
3145+
}
3146+
31383147
return getTypeMatchSuccess();
31393148
}
3149+
31403150
// Handle nominal types that are not directly generic.
31413151
if (auto nominal1 = type1->getAs<NominalType>()) {
31423152
auto nominal2 = type2->castTo<NominalType>();
@@ -3450,6 +3460,40 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
34503460
}
34513461
}
34523462

3463+
auto constraintType1 = type1;
3464+
if (auto existential = constraintType1->getAs<ExistentialType>())
3465+
constraintType1 = existential->getConstraintType();
3466+
3467+
auto constraintType2 = type2;
3468+
if (auto existential = constraintType2->getAs<ExistentialType>())
3469+
constraintType2 = existential->getConstraintType();
3470+
3471+
auto ppt1 = constraintType1->getAs<ParameterizedProtocolType>();
3472+
auto ppt2 = constraintType2->getAs<ParameterizedProtocolType>();
3473+
3474+
// With two parameterized protocols, we've already made sure conformance
3475+
// constraints are satisified. Try to match the arguments!
3476+
if (ppt1 && ppt2) {
3477+
return matchDeepTypeArguments(*this, subflags,
3478+
ppt1->getArgs(), ppt2->getArgs(),
3479+
locator);
3480+
} else if (!type1->isExistentialType() && ppt2) {
3481+
// Discharge the requirements of parameterized protocols.
3482+
// FIXME: Extend the locator path to point to the argument
3483+
// inducing the requirement.
3484+
SmallVector<Requirement, 2> reqs;
3485+
ppt2->getRequirements(type1, reqs);
3486+
for (const auto &req : reqs) {
3487+
auto result = matchTypes(req.getFirstType(), req.getSecondType(),
3488+
ConstraintKind::Bind,
3489+
subflags, locator);
3490+
if (result.isFailure())
3491+
return result;
3492+
}
3493+
} else if (ppt1 && !type2->isExistentialType()) {
3494+
llvm_unreachable("Malformed constraint!");
3495+
}
3496+
34533497
return getTypeMatchSuccess();
34543498
}
34553499

0 commit comments

Comments
 (0)