@@ -1348,7 +1348,8 @@ namespace {
13481348static Optional<
13491349 std::tuple<TypeVariableType *, Type, OpenedExistentialAdjustments>>
13501350shouldOpenExistentialCallArgument(
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;
0 commit comments