Skip to content

Commit 312dfcd

Browse files
committed
Sema: Fix unsound transformation of generic parameter types in inferAbstractTypeWitnesses()
1 parent 5dd8307 commit 312dfcd

File tree

1 file changed

+32
-14
lines changed

1 file changed

+32
-14
lines changed

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,6 +1384,19 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
13841384
for (auto *assocType : unresolvedAssocTypes) {
13851385
auto resolvedTy = system.getResolvedTypeWitness(assocType->getName());
13861386

1387+
resolvedTy = resolvedTy.transformRec([&](Type ty) -> llvm::Optional<Type> {
1388+
if (auto *gp = ty->getAs<GenericTypeParamType>()) {
1389+
// FIXME: 'computeFixedTypeWitness' uses 'getReducedType',
1390+
// so if a generic parameter is canonical here, it's 'Self'.
1391+
if (gp->isCanonical() ||
1392+
isa<ProtocolDecl>(gp->getDecl()->getDeclContext()->getAsDecl())) {
1393+
return adoptee;
1394+
}
1395+
}
1396+
1397+
return llvm::None;
1398+
});
1399+
13871400
typeWitnesses.insert(assocType, {resolvedTy, reqDepth});
13881401

13891402
if (auto *defaultedAssocType =
@@ -1399,11 +1412,27 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
13991412
// Try to compute the type without the aid of a specific potential
14001413
// witness.
14011414
if (const auto &typeWitness = computeAbstractTypeWitness(assocType)) {
1415+
auto resolvedTy = typeWitness->getType();
1416+
1417+
resolvedTy = resolvedTy.transformRec([&](Type ty) -> llvm::Optional<Type> {
1418+
if (auto *gp = ty->getAs<GenericTypeParamType>()) {
1419+
// FIXME: 'computeFixedTypeWitness' uses 'getReducedType',
1420+
// so if a generic parameter is canonical here, it's 'Self'.
1421+
if (gp->isCanonical() ||
1422+
isa<ProtocolDecl>(gp->getDecl()->getDeclContext()->getAsDecl())) {
1423+
return adoptee;
1424+
}
1425+
}
1426+
1427+
return llvm::None;
1428+
});
1429+
14021430
// Record the type witness immediately to make it available
14031431
// for substitutions into other tentative type witnesses.
1404-
typeWitnesses.insert(assocType, {typeWitness->getType(), reqDepth});
1432+
typeWitnesses.insert(assocType, {resolvedTy, reqDepth});
14051433

1406-
abstractTypeWitnesses.push_back(std::move(typeWitness.value()));
1434+
abstractTypeWitnesses.emplace_back(assocType, resolvedTy,
1435+
typeWitness->getDefaultedAssocType());
14071436
continue;
14081437
}
14091438

@@ -1431,7 +1460,7 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
14311460
Type type = witness.getType();
14321461

14331462
// Replace type parameters with other known or tentative type witnesses.
1434-
if (type->hasTypeParameter()) {
1463+
if (type->hasDependentMember() || type->hasTypeParameter()) {
14351464
// FIXME: We should find a better way to detect and reason about these
14361465
// cyclic solutions so that we can spot them earlier and express them in
14371466
// diagnostics.
@@ -1440,17 +1469,6 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
14401469

14411470
std::function<Type(Type)> substCurrentTypeWitnesses;
14421471
substCurrentTypeWitnesses = [&](Type ty) -> Type {
1443-
if (auto *gp = ty->getAs<GenericTypeParamType>()) {
1444-
// FIXME: 'computeFixedTypeWitness' uses 'getReducedType',
1445-
// so if a generic parameter is canonical here, it's 'Self'.
1446-
if (gp->isCanonical() ||
1447-
isa<ProtocolDecl>(gp->getDecl()->getDeclContext()->getAsDecl())) {
1448-
return adoptee;
1449-
}
1450-
1451-
return ty;
1452-
}
1453-
14541472
auto *const dmt = ty->getAs<DependentMemberType>();
14551473
if (!dmt) {
14561474
return ty;

0 commit comments

Comments
 (0)