Skip to content

Commit dd0b140

Browse files
authored
Merge pull request #42077 from DougGregor/implicit-opening-cleanups
2 parents d00ea98 + 5b0d1fd commit dd0b140

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,18 @@ 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+
14241436
/// Determine whether we should open up the existential argument to the
14251437
/// given parameters.
14261438
///
@@ -1457,6 +1469,14 @@ shouldOpenExistentialCallArgument(
14571469
return None;
14581470

14591471
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+
14601480
case DeclTypeCheckingSemantics::WithoutActuallyEscaping:
14611481
break;
14621482
}
@@ -1501,15 +1521,22 @@ shouldOpenExistentialCallArgument(
15011521
if (!argTy->isAnyExistentialType())
15021522
return None;
15031523

1504-
if (argTy->isExistentialType()) {
1505-
// If the existential argument type conforms to all of its protocol
1506-
// requirements, don't open the existential.
1507-
auto layout = argTy->getExistentialLayout();
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();
15081534
auto module = cs.DC->getParentModule();
15091535
bool containsNonSelfConformance = false;
15101536
for (auto proto : layout.getProtocols()) {
15111537
auto protoDecl = proto->getDecl();
1512-
auto conformance = module->lookupExistentialConformance(argTy, protoDecl);
1538+
auto conformance = module->lookupExistentialConformance(
1539+
existentialObjectType, protoDecl);
15131540
if (conformance.isInvalid()) {
15141541
containsNonSelfConformance = true;
15151542
break;

test/Constraints/opened_existentials_suppression.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ protocol P { }
44
extension Optional: P where Wrapped: P { }
55

66
func acceptsBox<T>(_ value: T) { }
7+
func acceptsBoxType<T>(_ value: T.Type) { }
78

89
// CHECK: passBox
910
// CHECK-NOT: open_existential_expr
@@ -13,4 +14,6 @@ func passBox(p: P, obj: AnyObject, err: Error) {
1314
acceptsBox(p as? P)
1415
acceptsBox(obj)
1516
acceptsBox(err)
17+
acceptsBoxType(Any.self)
18+
acceptsBoxType(AnyObject.self)
1619
}

0 commit comments

Comments
 (0)