@@ -1121,9 +1121,8 @@ CalleeCandidateInfo::evaluateCloseness(DeclContext *dc, Type candArgListType,
1121
1121
continue ;
1122
1122
1123
1123
// FIXME: Right now, a "matching" overload is one with a parameter whose
1124
- // type is identical to the argument type, or substitutable via
1125
- // rudimentary handling of functions with a single archetype in one or
1126
- // more parameters.
1124
+ // type is identical to the argument type, or substitutable via handling
1125
+ // of functions with a single archetype in one or more parameters.
1127
1126
// We can still do something more sophisticated with this.
1128
1127
// FIXME: Use TC.isConvertibleTo?
1129
1128
@@ -1151,13 +1150,9 @@ CalleeCandidateInfo::evaluateCloseness(DeclContext *dc, Type candArgListType,
1151
1150
if (nonSubstitutableArgs == 0 )
1152
1151
continue ;
1153
1152
++nonSubstitutableArgs;
1154
- // Fallthrough, this is nonsubstitutable, so mismatches as well.
1153
+ mismatchesAreNearMisses = false ;
1155
1154
} else {
1156
- if (nonSubstitutableArgs == 0 ) {
1157
- paramType = matchingArgType;
1158
- // Fallthrough as mismatched arg, comparing nearness to archetype
1159
- // bound type.
1160
- } else if (nonSubstitutableArgs == 1 ) {
1155
+ if (nonSubstitutableArgs == 1 ) {
1161
1156
// If we have only one nonSubstitutableArg so far, then this different
1162
1157
// type might be the one that we should be substituting for instead.
1163
1158
// Note that failureInfo is already set correctly for that case.
@@ -1167,23 +1162,37 @@ CalleeCandidateInfo::evaluateCloseness(DeclContext *dc, Type candArgListType,
1167
1162
continue ;
1168
1163
}
1169
1164
}
1165
+
1166
+ // This substitution doesn't match a previous substitution. Set up the nearMiss
1167
+ // and failureInfo.paramType with the expected substitution inserted.
1168
+ // (Note that this transform assumes only a single archetype.)
1169
+ mismatchesAreNearMisses &= argumentMismatchIsNearMiss (substitution, matchingArgType);
1170
+ paramType = paramType.transform (([&](Type type) -> Type {
1171
+ if (type->is <SubstitutableType>())
1172
+ return matchingArgType;
1173
+ return type;
1174
+ }));
1170
1175
}
1171
1176
} else {
1172
1177
matchingArgType = substitution;
1173
1178
singleArchetype = archetype;
1174
1179
1175
- if (CS->TC .isSubstitutableFor (substitution, archetype, CS->DC )) {
1180
+ if (CS->TC .isSubstitutableFor (substitution, archetype, CS->DC ))
1176
1181
continue ;
1177
- }
1182
+
1183
+ if (auto argOptType = argType->getOptionalObjectType ())
1184
+ mismatchesAreNearMisses &= CS->TC .isSubstitutableFor (argOptType, archetype, CS->DC );
1185
+ else
1186
+ mismatchesAreNearMisses = false ;
1178
1187
++nonSubstitutableArgs;
1179
1188
}
1189
+ } else {
1190
+ // Keep track of whether this argument was a near miss or not.
1191
+ mismatchesAreNearMisses &= argumentMismatchIsNearMiss (argType, paramType);
1180
1192
}
1181
1193
1182
1194
++mismatchingArgs;
1183
-
1184
- // Keep track of whether this argument was a near miss or not.
1185
- mismatchesAreNearMisses &= argumentMismatchIsNearMiss (argType, paramType);
1186
-
1195
+
1187
1196
failureInfo.argumentNumber = argNo;
1188
1197
failureInfo.parameterType = paramType;
1189
1198
if (paramType->hasTypeParameter ())
@@ -1196,7 +1205,8 @@ CalleeCandidateInfo::evaluateCloseness(DeclContext *dc, Type candArgListType,
1196
1205
1197
1206
// Check to see if the first argument expects an inout argument, but is not
1198
1207
// an lvalue.
1199
- if (candArgs[0 ].Ty ->is <InOutType>() && !actualArgs[0 ].Ty ->isLValueType ())
1208
+ Type firstArg = actualArgs[0 ].Ty ;
1209
+ if (candArgs[0 ].Ty ->is <InOutType>() && !(firstArg->isLValueType () || firstArg->is <InOutType>()))
1200
1210
return { CC_NonLValueInOut, {}};
1201
1211
1202
1212
// If we have exactly one argument mismatching, classify it specially, so that
@@ -1588,14 +1598,28 @@ bool CalleeCandidateInfo::diagnoseGenericParameterErrors(Expr *badArgExpr) {
1588
1598
1589
1599
for (unsigned i = 0 , c = archetypes.size (); i < c; i++) {
1590
1600
auto archetype = archetypes[i];
1591
- auto argType = substitutions[i];
1601
+ auto substitution = substitutions[i];
1592
1602
1593
1603
// FIXME: Add specific error for not subclass, if the archetype has a superclass?
1604
+
1605
+ // Check for optional near miss.
1606
+ if (auto argOptType = substitution->getOptionalObjectType ()) {
1607
+ if (CS->TC .isSubstitutableFor (argOptType, archetype, CS->DC )) {
1608
+ CS->TC .diagnose (badArgExpr->getLoc (), diag::missing_unwrap_optional, argType);
1609
+ foundFailure = true ;
1610
+ continue ;
1611
+ }
1612
+ }
1594
1613
1595
1614
for (auto proto : archetype->getConformsTo ()) {
1596
- if (!CS->TC .conformsToProtocol (argType, proto, CS->DC , ConformanceCheckOptions (TR_InExpression))) {
1597
- CS->TC .diagnose (badArgExpr->getLoc (), diag::cannot_convert_argument_value_protocol,
1598
- argType, proto->getDeclaredType ());
1615
+ if (!CS->TC .conformsToProtocol (substitution, proto, CS->DC , ConformanceCheckOptions (TR_InExpression))) {
1616
+ if (substitution->isEqual (argType)) {
1617
+ CS->TC .diagnose (badArgExpr->getLoc (), diag::cannot_convert_argument_value_protocol,
1618
+ substitution, proto->getDeclaredType ());
1619
+ } else {
1620
+ CS->TC .diagnose (badArgExpr->getLoc (), diag::cannot_convert_partial_argument_value_protocol,
1621
+ argType, substitution, proto->getDeclaredType ());
1622
+ }
1599
1623
foundFailure = true ;
1600
1624
}
1601
1625
}
@@ -1647,7 +1671,11 @@ enum TCCFlags {
1647
1671
// / Re-type-check the given subexpression even if the expression has already
1648
1672
// / been checked already. The client is asserting that infinite recursion is
1649
1673
// / not possible because it has relaxed a constraint on the system.
1650
- TCC_ForceRecheck = 0x02
1674
+ TCC_ForceRecheck = 0x02 ,
1675
+
1676
+ // / tell typeCheckExpression that it is ok to produce an ambiguous result,
1677
+ // / it can just fill in holes with UnresolvedType and we'll deal with it.
1678
+ TCC_AllowUnresolvedTypeVariables = 0x04
1651
1679
};
1652
1680
1653
1681
typedef OptionSet<TCCFlags> TCCOptions;
@@ -1716,7 +1744,8 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
1716
1744
1717
1745
// / Special magic to handle inout exprs and tuples in argument lists.
1718
1746
Expr *typeCheckArgumentChildIndependently (Expr *argExpr, Type argType,
1719
- const CalleeCandidateInfo &candidates);
1747
+ const CalleeCandidateInfo &candidates,
1748
+ TCCOptions options = TCCOptions());
1720
1749
1721
1750
// / Diagnose common failures due to applications of an argument list to an
1722
1751
// / ApplyExpr or SubscriptExpr.
@@ -2781,7 +2810,7 @@ typeCheckChildIndependently(Expr *subExpr, Type convertType,
2781
2810
// If there is no contextual type available, tell typeCheckExpression that it
2782
2811
// is ok to produce an ambiguous result, it can just fill in holes with
2783
2812
// UnresolvedType and we'll deal with it.
2784
- if (!convertType)
2813
+ if (!convertType || options. contains (TCC_AllowUnresolvedTypeVariables) )
2785
2814
TCEOptions |= TypeCheckExprFlags::AllowUnresolvedTypeVariables;
2786
2815
2787
2816
bool hadError = CS->TC .typeCheckExpression (subExpr, CS->DC , convertType,
@@ -3169,7 +3198,8 @@ void ConstraintSystem::diagnoseAssignmentFailure(Expr *dest, Type destTy,
3169
3198
// / Special magic to handle inout exprs and tuples in argument lists.
3170
3199
Expr *FailureDiagnosis::
3171
3200
typeCheckArgumentChildIndependently (Expr *argExpr, Type argType,
3172
- const CalleeCandidateInfo &candidates) {
3201
+ const CalleeCandidateInfo &candidates,
3202
+ TCCOptions options) {
3173
3203
// Grab one of the candidates (if present) and get its input list to help
3174
3204
// identify operators that have implicit inout arguments.
3175
3205
Type exampleInputType;
@@ -3203,7 +3233,6 @@ typeCheckArgumentChildIndependently(Expr *argExpr, Type argType,
3203
3233
if (!TE) {
3204
3234
// If the argument isn't a tuple, it is some scalar value for a
3205
3235
// single-argument call.
3206
- TCCOptions options;
3207
3236
if (exampleInputType && exampleInputType->is <InOutType>())
3208
3237
options |= TCC_AllowLValue;
3209
3238
@@ -3276,7 +3305,6 @@ typeCheckArgumentChildIndependently(Expr *argExpr, Type argType,
3276
3305
unsigned inArgNo = sources[i];
3277
3306
auto actualType = argTypeTT->getElementType (i);
3278
3307
3279
- TCCOptions options;
3280
3308
if (actualType->is <InOutType>())
3281
3309
options |= TCC_AllowLValue;
3282
3310
@@ -3341,7 +3369,6 @@ typeCheckArgumentChildIndependently(Expr *argExpr, Type argType,
3341
3369
exampleInputTuple = exampleInputType->getAs <TupleType>();
3342
3370
3343
3371
for (unsigned i = 0 , e = TE->getNumElements (); i != e; i++) {
3344
- TCCOptions options;
3345
3372
if (exampleInputTuple && i < exampleInputTuple->getNumElements () &&
3346
3373
exampleInputTuple->getElementType (i)->is <InOutType>())
3347
3374
options |= TCC_AllowLValue;
@@ -3761,18 +3788,17 @@ bool FailureDiagnosis::diagnoseParameterErrors(CalleeCandidateInfo &CCI,
3761
3788
badArgExpr = argExpr;
3762
3789
}
3763
3790
3791
+ // It could be that the argument doesn't conform to an archetype.
3792
+ if (CCI.diagnoseGenericParameterErrors (badArgExpr))
3793
+ return true ;
3794
+
3764
3795
// Re-type-check the argument with the expected type of the candidate set.
3765
3796
// This should produce a specific and tailored diagnostic saying that the
3766
3797
// type mismatches with expectations.
3767
3798
Type paramType = CCI.failedArgument .parameterType ;
3768
3799
if (!typeCheckChildIndependently (badArgExpr, paramType,
3769
3800
CTP_CallArgument, options))
3770
3801
return true ;
3771
-
3772
- // If that fails, it could be that the argument doesn't conform to an
3773
- // archetype.
3774
- if (CCI.diagnoseGenericParameterErrors (badArgExpr))
3775
- return true ;
3776
3802
}
3777
3803
3778
3804
return false ;
@@ -4059,8 +4085,9 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
4059
4085
// Get the expression result of type checking the arguments to the call
4060
4086
// independently, so we have some idea of what we're working with.
4061
4087
//
4062
- auto argExpr = typeCheckArgumentChildIndependently (callExpr->getArg (),
4063
- argType, calleeInfo);
4088
+ auto argExpr = typeCheckArgumentChildIndependently (callExpr->getArg (), argType,
4089
+ calleeInfo,
4090
+ TCC_AllowUnresolvedTypeVariables);
4064
4091
if (!argExpr)
4065
4092
return true ; // already diagnosed.
4066
4093
@@ -4069,6 +4096,14 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
4069
4096
if (diagnoseParameterErrors (calleeInfo, callExpr->getFn (), argExpr))
4070
4097
return true ;
4071
4098
4099
+ // Force recheck of the arg expression because we allowed unresolved types
4100
+ // before, and that turned out not to help, and now we want any diagnoses
4101
+ // from disallowing them.
4102
+ argExpr = typeCheckArgumentChildIndependently (callExpr->getArg (), argType,
4103
+ calleeInfo, TCC_ForceRecheck);
4104
+ if (!argExpr)
4105
+ return true ; // already diagnosed.
4106
+
4072
4107
// Diagnose some simple and common errors.
4073
4108
if (calleeInfo.diagnoseSimpleErrors (callExpr->getLoc ()))
4074
4109
return true ;
0 commit comments