Skip to content

Commit 02a13f3

Browse files
committed
Allow explicit "as <existential-type>" to disable implicit opening of existentials
1 parent 15d96ef commit 02a13f3

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,7 +1348,8 @@ namespace {
13481348
static Optional<
13491349
std::tuple<TypeVariableType *, Type, OpenedExistentialAdjustments>>
13501350
shouldOpenExistentialCallArgument(
1351-
ValueDecl *callee, unsigned paramIdx, Type paramTy, Type argTy) {
1351+
ValueDecl *callee, unsigned paramIdx, Type paramTy, Type argTy,
1352+
Expr *argExpr, ConstraintSystem &cs) {
13521353
if (!callee)
13531354
return None;
13541355

@@ -1382,6 +1383,20 @@ shouldOpenExistentialCallArgument(
13821383
if (!paramTy->hasTypeVariable())
13831384
return None;
13841385

1386+
// An argument expression that explicitly coerces to an existential
1387+
// disables the implicit opening of the existential.
1388+
if (argExpr) {
1389+
if (auto argCoercion = dyn_cast<CoerceExpr>(
1390+
argExpr->getSemanticsProvidingExpr())) {
1391+
if (auto typeRepr = argCoercion->getCastTypeRepr()) {
1392+
if (auto toType = cs.getType(typeRepr)) {
1393+
if (toType->isAnyExistentialType())
1394+
return None;
1395+
}
1396+
}
1397+
}
1398+
}
1399+
13851400
OpenedExistentialAdjustments adjustments;
13861401

13871402
// If the argument is inout, strip it off and we can add it back.
@@ -1670,10 +1685,10 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
16701685
auto argTy = argument.getOldType();
16711686

16721687
bool matchingAutoClosureResult = param.isAutoClosure();
1688+
auto *argExpr = getArgumentExpr(locator.getAnchor(), argIdx);
16731689
if (param.isAutoClosure() && !isSynthesizedArgument(argument)) {
16741690
auto &ctx = cs.getASTContext();
16751691
auto *fnType = paramTy->castTo<FunctionType>();
1676-
auto *argExpr = getArgumentExpr(locator.getAnchor(), argIdx);
16771692

16781693
// If this is a call to a function with a closure argument and the
16791694
// parameter is an autoclosure, let's just increment the score here
@@ -1715,7 +1730,7 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
17151730
// If the argument is an existential type and the parameter is generic,
17161731
// consider opening the existential type.
17171732
if (auto existentialArg = shouldOpenExistentialCallArgument(
1718-
callee, paramIdx, paramTy, argTy)) {
1733+
callee, paramIdx, paramTy, argTy, argExpr, cs)) {
17191734
// My kingdom for a decent "if let" in C++.
17201735
TypeVariableType *openedTypeVar;
17211736
Type existentialType;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-swift-frontend -enable-experimental-opened-existential-types -typecheck -dump-ast -parse-as-library %s | %FileCheck %s
2+
3+
protocol P { }
4+
5+
func acceptsBox<T>(_ value: T) { }
6+
7+
// CHECK: passBox
8+
// CHECK-NOT: open_existential_expr
9+
func passBox(p: P) {
10+
acceptsBox(p as P)
11+
}

0 commit comments

Comments
 (0)