@@ -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;
@@ -10113,18 +10128,8 @@ ConstraintSystem::simplifyOpenedExistentialOfConstraint(
1011310128 if (type2->isAnyExistentialType()) {
1011410129 // We have the existential side. Produce an opened archetype and bind
1011510130 // 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;
1012810133 return matchTypes(type1, openedTy, ConstraintKind::Bind, subflags, locator);
1012910134 }
1013010135 if (!type2->isTypeVariableOrMember())
0 commit comments