@@ -1348,7 +1348,8 @@ namespace {
1348
1348
static Optional<
1349
1349
std::tuple<TypeVariableType *, Type, OpenedExistentialAdjustments>>
1350
1350
shouldOpenExistentialCallArgument(
1351
- ValueDecl *callee, unsigned paramIdx, Type paramTy, Type argTy) {
1351
+ ValueDecl *callee, unsigned paramIdx, Type paramTy, Type argTy,
1352
+ Expr *argExpr, ConstraintSystem &cs) {
1352
1353
if (!callee)
1353
1354
return None;
1354
1355
@@ -1382,6 +1383,20 @@ shouldOpenExistentialCallArgument(
1382
1383
if (!paramTy->hasTypeVariable())
1383
1384
return None;
1384
1385
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
+
1385
1400
OpenedExistentialAdjustments adjustments;
1386
1401
1387
1402
// If the argument is inout, strip it off and we can add it back.
@@ -1670,10 +1685,10 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
1670
1685
auto argTy = argument.getOldType();
1671
1686
1672
1687
bool matchingAutoClosureResult = param.isAutoClosure();
1688
+ auto *argExpr = getArgumentExpr(locator.getAnchor(), argIdx);
1673
1689
if (param.isAutoClosure() && !isSynthesizedArgument(argument)) {
1674
1690
auto &ctx = cs.getASTContext();
1675
1691
auto *fnType = paramTy->castTo<FunctionType>();
1676
- auto *argExpr = getArgumentExpr(locator.getAnchor(), argIdx);
1677
1692
1678
1693
// If this is a call to a function with a closure argument and the
1679
1694
// parameter is an autoclosure, let's just increment the score here
@@ -1715,7 +1730,7 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
1715
1730
// If the argument is an existential type and the parameter is generic,
1716
1731
// consider opening the existential type.
1717
1732
if (auto existentialArg = shouldOpenExistentialCallArgument(
1718
- callee, paramIdx, paramTy, argTy)) {
1733
+ callee, paramIdx, paramTy, argTy, argExpr, cs )) {
1719
1734
// My kingdom for a decent "if let" in C++.
1720
1735
TypeVariableType *openedTypeVar;
1721
1736
Type existentialType;
@@ -10113,18 +10128,8 @@ ConstraintSystem::simplifyOpenedExistentialOfConstraint(
10113
10128
if (type2->isAnyExistentialType()) {
10114
10129
// We have the existential side. Produce an opened archetype and bind
10115
10130
// type1 to it.
10116
- bool isMetatype = false;
10117
- auto instanceTy = type2;
10118
- if (auto metaTy = type2->getAs<ExistentialMetatypeType>()) {
10119
- isMetatype = true;
10120
- instanceTy = metaTy->getExistentialInstanceType();
10121
- }
10122
- assert(instanceTy->isExistentialType());
10123
- Type openedTy =
10124
- OpenedArchetypeType::get(instanceTy->getCanonicalType(),
10125
- DC->getGenericSignatureOfContext());
10126
- if (isMetatype)
10127
- openedTy = MetatypeType::get(openedTy, getASTContext());
10131
+ Type openedTy = openExistentialType(type2, getConstraintLocator(locator))
10132
+ .first;
10128
10133
return matchTypes(type1, openedTy, ConstraintKind::Bind, subflags, locator);
10129
10134
}
10130
10135
if (!type2->isTypeVariableOrMember())
0 commit comments