Skip to content

Commit edc49bc

Browse files
authored
Merge pull request #42085 from DougGregor/implicit-open-generic-func-reqs-check
Restrict implicit opening of existentials based on the generic function's requirements
2 parents 937f6d6 + 0927c9f commit edc49bc

File tree

2 files changed

+26
-46
lines changed

2 files changed

+26
-46
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 25 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,18 +1421,6 @@ namespace {
14211421
OptionSet<OpenedExistentialAdjustmentFlags>;
14221422
}
14231423

1424-
/// Determine if this function is part of the _isUnique family of functions in
1425-
/// the standard library.
1426-
static bool isStdlibUniqueFunction(ValueDecl *callee) {
1427-
if (!callee->isStdlibDecl())
1428-
return false;
1429-
1430-
auto baseName = callee->getName().getBaseName().userFacingName();
1431-
return baseName == "_isUnique" || baseName == "_isUnique_native" ||
1432-
baseName == "_COWBufferForReading" ||
1433-
baseName == "_unsafeDowncastToAnyObject";
1434-
}
1435-
14361424
/// Determine whether we should open up the existential argument to the
14371425
/// given parameters.
14381426
///
@@ -1469,14 +1457,6 @@ shouldOpenExistentialCallArgument(
14691457
return None;
14701458

14711459
case DeclTypeCheckingSemantics::Normal:
1472-
// _isUnique and friends are special because opening an existential when
1473-
// calling them would make them non-unique.
1474-
// FIXME: Borrowing properly from the existential box would probably
1475-
// eliminate this.
1476-
if (isStdlibUniqueFunction(callee))
1477-
return None;
1478-
break;
1479-
14801460
case DeclTypeCheckingSemantics::WithoutActuallyEscaping:
14811461
break;
14821462
}
@@ -1521,32 +1501,6 @@ shouldOpenExistentialCallArgument(
15211501
if (!argTy->isAnyExistentialType())
15221502
return None;
15231503

1524-
1525-
// If the existential argument type conforms to all of its protocol
1526-
// requirements, don't open the existential.
1527-
{
1528-
Type existentialObjectType;
1529-
if (auto existentialMetaTy = argTy->getAs<ExistentialMetatypeType>())
1530-
existentialObjectType = existentialMetaTy->getInstanceType();
1531-
else
1532-
existentialObjectType = argTy;
1533-
auto layout = existentialObjectType->getExistentialLayout();
1534-
auto module = cs.DC->getParentModule();
1535-
bool containsNonSelfConformance = false;
1536-
for (auto proto : layout.getProtocols()) {
1537-
auto protoDecl = proto->getDecl();
1538-
auto conformance = module->lookupExistentialConformance(
1539-
existentialObjectType, protoDecl);
1540-
if (conformance.isInvalid()) {
1541-
containsNonSelfConformance = true;
1542-
break;
1543-
}
1544-
}
1545-
1546-
if (!containsNonSelfConformance)
1547-
return None;
1548-
}
1549-
15501504
auto param = getParameterAt(callee, paramIdx);
15511505
if (!param)
15521506
return None;
@@ -1588,6 +1542,31 @@ shouldOpenExistentialCallArgument(
15881542
genericSig.getGenericParams().back()->getDepth())
15891543
return None;
15901544

1545+
// If the existential argument conforms to all of protocol requirements on
1546+
// the formal parameter's type, don't open.
1547+
// If all of the conformance requirements on the formal parameter's type
1548+
// are self-conforming, don't open.
1549+
{
1550+
Type existentialObjectType;
1551+
if (auto existentialMetaTy = argTy->getAs<ExistentialMetatypeType>())
1552+
existentialObjectType = existentialMetaTy->getInstanceType();
1553+
else
1554+
existentialObjectType = argTy;
1555+
auto module = cs.DC->getParentModule();
1556+
bool containsNonSelfConformance = false;
1557+
for (auto proto : genericSig->getRequiredProtocols(genericParam)) {
1558+
auto conformance = module->lookupExistentialConformance(
1559+
existentialObjectType, proto);
1560+
if (conformance.isInvalid()) {
1561+
containsNonSelfConformance = true;
1562+
break;
1563+
}
1564+
}
1565+
1566+
if (!containsNonSelfConformance)
1567+
return None;
1568+
}
1569+
15911570
// Ensure that the formal parameter is only used in covariant positions,
15921571
// because it won't match anywhere else.
15931572
auto referenceInfo = findGenericParameterReferences(

test/Constraints/opened_existentials_suppression.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ func acceptsBoxType<T>(_ value: T.Type) { }
99
// CHECK: passBox
1010
// CHECK-NOT: open_existential_expr
1111
func passBox(p: P, obj: AnyObject, err: Error) {
12+
acceptsBox(p)
1213
acceptsBox(p as P)
1314
acceptsBox(p as! P)
1415
acceptsBox(p as? P)

0 commit comments

Comments
 (0)