@@ -8354,17 +8354,53 @@ static Type getOpenedResultBuilderTypeFor(ConstraintSystem &cs,
83548354bool ConstraintSystem::resolveClosure (TypeVariableType *typeVar,
83558355 Type contextualType,
83568356 ConstraintLocatorBuilder locator) {
8357+ auto *closureLocator = typeVar->getImpl ().getLocator ();
8358+ auto *closure = castToExpr<ClosureExpr>(closureLocator->getAnchor ());
8359+ auto *inferredClosureType = getClosureType (closure);
8360+
83578361 auto getContextualParamAt =
8358- [&contextualType](unsigned index) -> Optional<AnyFunctionType::Param> {
8362+ [&contextualType, &inferredClosureType](
8363+ unsigned index) -> Optional<AnyFunctionType::Param> {
83598364 auto *fnType = contextualType->getAs <FunctionType>();
8360- return fnType && fnType->getNumParams () > index
8361- ? fnType->getParams ()[index]
8362- : Optional<AnyFunctionType::Param>();
8365+ if (!fnType)
8366+ return None;
8367+
8368+ auto numContextualParams = fnType->getNumParams ();
8369+ if (numContextualParams != inferredClosureType->getNumParams () ||
8370+ numContextualParams <= index)
8371+ return None;
8372+
8373+ return fnType->getParams ()[index];
83638374 };
83648375
8365- auto *closureLocator = typeVar->getImpl ().getLocator ();
8366- auto *closure = castToExpr<ClosureExpr>(closureLocator->getAnchor ());
8367- auto *inferredClosureType = getClosureType (closure);
8376+ // Check whether given contextual parameter type could be
8377+ // used to bind external closure parameter type.
8378+ auto isSuitableContextualType = [](Type contextualTy) {
8379+ // We need to wait until contextual type
8380+ // is fully resolved before binding it.
8381+ if (contextualTy->isTypeVariableOrMember ())
8382+ return false ;
8383+
8384+ // If contextual type has an error, let's wait for inference,
8385+ // otherwise contextual would interfere with diagnostics.
8386+ if (contextualTy->hasError ())
8387+ return false ;
8388+
8389+ if (isa<TypeAliasType>(contextualTy.getPointer ())) {
8390+ auto underlyingTy = contextualTy->getDesugaredType ();
8391+ // FIXME: typealias pointing to an existential type is special
8392+ // because if the typealias has type variables then we'd end up
8393+ // opening existential from a type with unresolved generic
8394+ // parameter(s), which CSApply can't currently simplify while
8395+ // building type-checked AST because `OpenedArchetypeType` doesn't
8396+ // propagate flags. Example is as simple as `{ $0.description }`
8397+ // where `$0` is `Error` that inferred from a (generic) typealias.
8398+ if (underlyingTy->isExistentialType () && contextualTy->hasTypeVariable ())
8399+ return false ;
8400+ }
8401+
8402+ return true ;
8403+ };
83688404
83698405 // Determine whether a result builder will be applied.
83708406 auto resultBuilderType = getOpenedResultBuilderTypeFor (*this , locator);
@@ -8456,6 +8492,24 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
84568492 param.isVariadic () ? ArraySliceType::get (typeVar) : Type (typeVar);
84578493
84588494 auto externalType = param.getOldType ();
8495+
8496+ // Performance optimization.
8497+ //
8498+ // If there is a concrete contextual type we could use, let's bind
8499+ // it to the external type right away because internal type has to
8500+ // be equal to that type anyway (through `BindParam` on external type
8501+ // i.e. <internal> bind param <external> conv <concrete contextual>).
8502+ //
8503+ // Note: it's correct to avoid doing this, but it would result
8504+ // in (a lot) more checking since solver would have to re-discover,
8505+ // re-attempt and fail parameter type while solving for overloaded
8506+ // choices in the body.
8507+ if (auto contextualParam = getContextualParamAt (i)) {
8508+ auto paramTy = simplifyType (contextualParam->getOldType ());
8509+ if (isSuitableContextualType (paramTy))
8510+ addConstraint (ConstraintKind::Bind, externalType, paramTy, paramLoc);
8511+ }
8512+
84598513 if (oneWayConstraints) {
84608514 addConstraint (
84618515 ConstraintKind::OneWayBindParam, typeVar, externalType, paramLoc);
0 commit comments