@@ -93,6 +93,47 @@ static Optional<unsigned> scoreParamAndArgNameTypo(StringRef paramName,
93
93
return dist;
94
94
}
95
95
96
+ bool constraints::areConservativelyCompatibleArgumentLabels (
97
+ OverloadChoice choice,
98
+ ArrayRef<Identifier> labels,
99
+ bool hasTrailingClosure) {
100
+ ValueDecl *decl = nullptr ;
101
+ Type baseType;
102
+ switch (choice.getKind ()) {
103
+ case OverloadChoiceKind::Decl:
104
+ case OverloadChoiceKind::DeclViaBridge:
105
+ case OverloadChoiceKind::DeclViaDynamic:
106
+ case OverloadChoiceKind::DeclViaUnwrappedOptional:
107
+ decl = choice.getDecl ();
108
+ baseType = choice.getBaseType ();
109
+ if (baseType)
110
+ baseType = baseType->getRValueType ();
111
+ break ;
112
+
113
+ case OverloadChoiceKind::BaseType:
114
+ case OverloadChoiceKind::DynamicMemberLookup:
115
+ case OverloadChoiceKind::KeyPathApplication:
116
+ case OverloadChoiceKind::TupleIndex:
117
+ return true ;
118
+ }
119
+
120
+ // This is a member lookup, which generally means that the call arguments
121
+ // (if we have any) will apply to the second level of parameters, with
122
+ // the member lookup binding the first level. But there are cases where
123
+ // we can get an unapplied declaration reference back.
124
+ bool hasCurriedSelf;
125
+ if (!baseType || baseType->is <ModuleType>()) {
126
+ hasCurriedSelf = false ;
127
+ } else if (baseType->is <AnyMetatypeType>() && decl->isInstanceMember ()) {
128
+ hasCurriedSelf = false ;
129
+ } else {
130
+ hasCurriedSelf = true ;
131
+ }
132
+
133
+ return areConservativelyCompatibleArgumentLabels (
134
+ decl, hasCurriedSelf, labels, hasTrailingClosure);
135
+ }
136
+
96
137
bool constraints::
97
138
areConservativelyCompatibleArgumentLabels (ValueDecl *decl,
98
139
bool hasCurriedSelf,
@@ -3430,31 +3471,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
3430
3471
}
3431
3472
}
3432
3473
3433
- // / Determine whether the given declaration has compatible argument
3434
- // / labels.
3435
- auto hasCompatibleArgumentLabels = [&argumentLabels](Type baseObjTy,
3436
- ValueDecl *decl) -> bool {
3437
- if (!argumentLabels)
3438
- return true ;
3439
-
3440
- // This is a member lookup, which generally means that the call arguments
3441
- // (if we have any) will apply to the second level of parameters, with
3442
- // the member lookup binding the first level. But there are cases where
3443
- // we can get an unapplied declaration reference back.
3444
- bool hasCurriedSelf;
3445
- if (baseObjTy->is <ModuleType>()) {
3446
- hasCurriedSelf = false ;
3447
- } else if (baseObjTy->is <AnyMetatypeType>() && decl->isInstanceMember ()) {
3448
- hasCurriedSelf = false ;
3449
- } else {
3450
- hasCurriedSelf = true ;
3451
- }
3452
-
3453
- return areConservativelyCompatibleArgumentLabels (decl, hasCurriedSelf,
3454
- argumentLabels->Labels ,
3455
- argumentLabels->HasTrailingClosure );
3456
- };
3457
-
3458
3474
// Look for members within the base.
3459
3475
LookupResult &lookup = lookupMember (instanceTy, memberName);
3460
3476
@@ -3557,7 +3573,10 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
3557
3573
3558
3574
// If the argument labels for this result are incompatible with
3559
3575
// the call site, skip it.
3560
- if (!hasCompatibleArgumentLabels (baseObjTy, decl)) {
3576
+ if (argumentLabels &&
3577
+ !areConservativelyCompatibleArgumentLabels (
3578
+ candidate, argumentLabels->Labels ,
3579
+ argumentLabels->HasTrailingClosure )) {
3561
3580
labelMismatch = true ;
3562
3581
result.addUnviable (candidate, MemberLookupResult::UR_LabelMismatch);
3563
3582
return ;
@@ -4768,6 +4787,145 @@ ConstraintSystem::simplifyKeyPathApplicationConstraint(
4768
4787
return unsolved ();
4769
4788
}
4770
4789
4790
+ Type ConstraintSystem::simplifyAppliedOverloads (
4791
+ Type fnType,
4792
+ const FunctionType *argFnType,
4793
+ Optional<ArgumentLabelState> argumentLabels,
4794
+ ConstraintLocatorBuilder locator) {
4795
+ auto fnTypeVar = fnType->getAs <TypeVariableType>();
4796
+ if (!fnTypeVar)
4797
+ return fnType;
4798
+
4799
+ // Always work on the representation.
4800
+ fnTypeVar = getRepresentative (fnTypeVar);
4801
+
4802
+ // Dig out the disjunction that describes this overload.
4803
+ auto disjunction = getUnboundBindOverloadDisjunction (fnTypeVar);
4804
+ if (!disjunction) return fnType;
4805
+
4806
+ // / The common result type amongst all function overloads.
4807
+ Optional<Type> commonResultType;
4808
+ auto updateCommonResultType = [&](Type choiceType) {
4809
+ auto markFailure = [&] {
4810
+ commonResultType = Type ();
4811
+ };
4812
+
4813
+ auto choiceFnType = choiceType->getAs <FunctionType>();
4814
+ if (!choiceFnType)
4815
+ return markFailure ();
4816
+
4817
+ // For now, don't attempt to establish a common result type when there
4818
+ // are type parameters.
4819
+ Type choiceResultType = choiceFnType->getResult ();
4820
+ if (choiceResultType->hasTypeParameter ())
4821
+ return markFailure ();
4822
+
4823
+ // If we haven't seen a common result type yet, record what we found.
4824
+ if (!commonResultType) {
4825
+ commonResultType = choiceResultType;
4826
+ return ;
4827
+ }
4828
+
4829
+ // If we already failed, we're done.
4830
+ if (commonResultType->isNull ())
4831
+ return ;
4832
+
4833
+ // If we found something different, fail.
4834
+ if (!commonResultType.getValue ()->isEqual (choiceResultType))
4835
+ return markFailure ();
4836
+ };
4837
+
4838
+ // Consider each of the constraints in the disjunction.
4839
+ retry_after_fail:
4840
+ bool skippedAnyConstraints = false ;
4841
+ bool labelMismatch = false ;
4842
+ auto filterResult =
4843
+ filterDisjunctions (disjunction, /* restoreOnFail=*/ shouldAttemptFixes (),
4844
+ [&](Constraint *constraint) {
4845
+ // We must have bind-overload constraints.
4846
+ // FIXME: This isn't entirely true.
4847
+ if (constraint->getKind () != ConstraintKind::BindOverload) {
4848
+ skippedAnyConstraints = true ;
4849
+ return true ;
4850
+ }
4851
+
4852
+ // We must be binding the type variable (or a type variable
4853
+ // equivalent to it).
4854
+ auto boundTypeVar = constraint->getFirstType ()->getAs <TypeVariableType>();
4855
+ if (!boundTypeVar || getRepresentative (boundTypeVar) != fnTypeVar) {
4856
+ skippedAnyConstraints = true ;
4857
+ return true ;
4858
+ }
4859
+
4860
+ auto choice = constraint->getOverloadChoice ();
4861
+
4862
+ // Determine whether the argument labels we have conflict with those of
4863
+ // this overload choice.
4864
+ if (argumentLabels &&
4865
+ !areConservativelyCompatibleArgumentLabels (
4866
+ choice, argumentLabels->Labels ,
4867
+ argumentLabels->HasTrailingClosure )) {
4868
+ labelMismatch = true ;
4869
+ return false ;
4870
+ }
4871
+
4872
+ // Determine the type that this choice will have.
4873
+ Type choiceType =
4874
+ getEffectiveOverloadType (choice, /* allowMembers=*/ true ,
4875
+ constraint->getOverloadUseDC ());
4876
+ if (!choiceType) {
4877
+ skippedAnyConstraints = true ;
4878
+ return true ;
4879
+ }
4880
+
4881
+ // If we have a function type, we can compute a common result type.
4882
+ updateCommonResultType (choiceType);
4883
+ return true ;
4884
+ });
4885
+
4886
+ switch (filterResult) {
4887
+ case SolutionKind::Error:
4888
+ if (labelMismatch && shouldAttemptFixes ()) {
4889
+ argumentLabels = None;
4890
+ goto retry_after_fail;
4891
+ }
4892
+
4893
+ return Type ();
4894
+
4895
+ case SolutionKind::Solved:
4896
+ // We should now have a type for the one remaining overload.
4897
+ fnType = getFixedTypeRecursive (fnType, /* wantRValue=*/ true );
4898
+ break ;
4899
+
4900
+ case SolutionKind::Unsolved:
4901
+ break ;
4902
+ }
4903
+
4904
+
4905
+ // If there was a constraint that we couldn't reason about, don't use the
4906
+ // results of any common-type computations.
4907
+ if (skippedAnyConstraints)
4908
+ return fnType;
4909
+
4910
+ // If we have a common result type, bind the expected result type to it.
4911
+ if (commonResultType && *commonResultType) {
4912
+ ASTContext &ctx = getASTContext ();
4913
+ if (ctx.LangOpts .DebugConstraintSolver ) {
4914
+ auto &log = ctx.TypeCheckerDebug ->getStream ();
4915
+ log.indent (solverState ? solverState->depth * 2 + 2 : 0 )
4916
+ << " (common result type for $T" << fnTypeVar->getID () << " is "
4917
+ << commonResultType->getString ()
4918
+ << " )\n " ;
4919
+ }
4920
+
4921
+ // FIXME: Could also rewrite fnType to include this result type.
4922
+ addConstraint (ConstraintKind::Bind, argFnType->getResult (),
4923
+ *commonResultType, locator);
4924
+ }
4925
+
4926
+ return fnType;
4927
+ }
4928
+
4771
4929
ConstraintSystem::SolutionKind
4772
4930
ConstraintSystem::simplifyApplicableFnConstraint (
4773
4931
Type type1,
@@ -4821,23 +4979,16 @@ ConstraintSystem::simplifyApplicableFnConstraint(
4821
4979
4822
4980
};
4823
4981
4824
- // If the right-hand side is a type variable, try to find a common result
4825
- // type in the overload set.
4982
+ // If the right-hand side is a type variable, try to simplify the overload
4983
+ // set.
4826
4984
if (auto typeVar = desugar2->getAs <TypeVariableType>()) {
4827
- auto choices = getUnboundBindOverloads (typeVar);
4828
- if (Type resultType = findCommonResultType (choices)) {
4829
- ASTContext &ctx = getASTContext ();
4830
- if (ctx.LangOpts .DebugConstraintSolver ) {
4831
- auto &log = ctx.TypeCheckerDebug ->getStream ();
4832
- log.indent (solverState ? solverState->depth * 2 + 2 : 0 )
4833
- << " (common result type for $T" << typeVar->getID () << " is "
4834
- << resultType.getString ()
4835
- << " )\n " ;
4836
- }
4985
+ auto argumentLabels = getArgumentLabels (*this , locator);
4986
+ Type newType2 =
4987
+ simplifyAppliedOverloads (type2, func1, argumentLabels, locator);
4988
+ if (!newType2)
4989
+ return SolutionKind::Error;
4837
4990
4838
- addConstraint (ConstraintKind::Bind, func1->getResult (), resultType,
4839
- locator);
4840
- }
4991
+ desugar2 = newType2->getDesugaredType ();
4841
4992
}
4842
4993
4843
4994
// If right-hand side is a type variable, the constraint is unsolved.
@@ -4992,7 +5143,7 @@ lookupDynamicCallableMethods(Type type, ConstraintSystem &CS,
4992
5143
// / Returns the @dynamicCallable required methods (if they exist) implemented
4993
5144
// / by a type.
4994
5145
// / This function may be slow for deep class hierarchies and multiple protocol
4995
- // / conformances, but it is invoked only after other constraint simplification
5146
+ // / conformances, but it is invoked only after other constraint simplification
4996
5147
// / rules fail.
4997
5148
static DynamicCallableMethods
4998
5149
getDynamicCallableMethods (Type type, ConstraintSystem &CS,
@@ -6170,11 +6321,13 @@ void ConstraintSystem::simplifyDisjunctionChoice(Constraint *choice) {
6170
6321
case ConstraintSystem::SolutionKind::Error:
6171
6322
if (!failedConstraint)
6172
6323
failedConstraint = choice;
6173
- solverState->retireConstraint (choice);
6324
+ if (solverState)
6325
+ solverState->retireConstraint (choice);
6174
6326
break ;
6175
6327
6176
6328
case ConstraintSystem::SolutionKind::Solved:
6177
- solverState->retireConstraint (choice);
6329
+ if (solverState)
6330
+ solverState->retireConstraint (choice);
6178
6331
break ;
6179
6332
6180
6333
case ConstraintSystem::SolutionKind::Unsolved:
@@ -6184,5 +6337,6 @@ void ConstraintSystem::simplifyDisjunctionChoice(Constraint *choice) {
6184
6337
}
6185
6338
6186
6339
// Record this as a generated constraint.
6187
- solverState->addGeneratedConstraint (choice);
6340
+ if (solverState)
6341
+ solverState->addGeneratedConstraint (choice);
6188
6342
}
0 commit comments