@@ -893,7 +893,8 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
893
893
// / Attempt to produce a diagnostic for a mismatch between an expression's
894
894
// / type and its assumed contextual type.
895
895
bool diagnoseContextualConversionError (Expr *expr, Type contextualType,
896
- ContextualTypePurpose CTP);
896
+ ContextualTypePurpose CTP,
897
+ Type suggestedType = Type());
897
898
898
899
// / For an expression being type checked with a CTP_CalleeResult contextual
899
900
// / type, try to diagnose a problem.
@@ -2788,7 +2789,8 @@ static bool tryDiagnoseNonEscapingParameterToEscaping(
2788
2789
}
2789
2790
2790
2791
bool FailureDiagnosis::diagnoseContextualConversionError (
2791
- Expr *expr, Type contextualType, ContextualTypePurpose CTP) {
2792
+ Expr *expr, Type contextualType, ContextualTypePurpose CTP,
2793
+ Type suggestedType) {
2792
2794
// If the constraint system has a contextual type, then we can test to see if
2793
2795
// this is the problem that prevents us from solving the system.
2794
2796
if (!contextualType) {
@@ -2807,11 +2809,16 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
2807
2809
if (contextualType->is <InOutType>())
2808
2810
options |= TCC_AllowLValue;
2809
2811
2810
- auto recheckedExpr = typeCheckChildIndependently (expr, options);
2812
+ auto * recheckedExpr = typeCheckChildIndependently (expr, options);
2811
2813
auto exprType = recheckedExpr ? CS.getType (recheckedExpr) : Type ();
2812
2814
2815
+ // If there is a suggested type and re-typecheck failed, let's use it.
2816
+ if (!exprType)
2817
+ exprType = suggestedType;
2818
+
2813
2819
// If it failed and diagnosed something, then we're done.
2814
- if (!exprType) return true ;
2820
+ if (!exprType)
2821
+ return CS.TC .Diags .hadAnyError ();
2815
2822
2816
2823
// If we contextually had an inout type, and got a non-lvalue result, then
2817
2824
// we fail with a mutability error.
@@ -5274,7 +5281,7 @@ bool FailureDiagnosis::diagnoseTrailingClosureErrors(ApplyExpr *callExpr) {
5274
5281
}
5275
5282
};
5276
5283
5277
- SmallVector<Type , 4 > possibleTypes;
5284
+ SmallPtrSet<TypeBase * , 4 > possibleTypes;
5278
5285
auto currentType = CS.getType (fnExpr);
5279
5286
5280
5287
// If current type has type variables or unresolved types
@@ -5294,10 +5301,10 @@ bool FailureDiagnosis::diagnoseTrailingClosureErrors(ApplyExpr *callExpr) {
5294
5301
return diagnoseContextualConversionError (callExpr, contextualType,
5295
5302
CS.getContextualTypePurpose ());
5296
5303
} else {
5297
- possibleTypes.push_back (currentType);
5304
+ possibleTypes.insert (currentType. getPointer () );
5298
5305
}
5299
5306
5300
- for (auto type : possibleTypes) {
5307
+ for (Type type : possibleTypes) {
5301
5308
auto *fnType = type->getAs <AnyFunctionType>();
5302
5309
if (!fnType)
5303
5310
continue ;
@@ -5388,7 +5395,7 @@ bool FailureDiagnosis::diagnoseCallContextualConversionErrors(
5388
5395
auto *DC = CS.DC ;
5389
5396
5390
5397
auto typeCheckExpr = [](TypeChecker &TC, Expr *expr, DeclContext *DC,
5391
- SmallVectorImpl<Type > &types,
5398
+ SmallPtrSetImpl<TypeBase * > &types,
5392
5399
Type contextualType = Type ()) {
5393
5400
CalleeListener listener (contextualType);
5394
5401
TC.getPossibleTypesOfExpressionWithoutApplying (
@@ -5398,7 +5405,7 @@ bool FailureDiagnosis::diagnoseCallContextualConversionErrors(
5398
5405
// First let's type-check expression without contextual type, and
5399
5406
// see if that's going to produce a type, if so, let's type-check
5400
5407
// again, this time using given contextual type.
5401
- SmallVector<Type , 4 > withoutContextual;
5408
+ SmallPtrSet<TypeBase * , 4 > withoutContextual;
5402
5409
typeCheckExpr (TC, callExpr, DC, withoutContextual);
5403
5410
5404
5411
// If there are no types returned, it means that problem was
@@ -5407,12 +5414,17 @@ bool FailureDiagnosis::diagnoseCallContextualConversionErrors(
5407
5414
if (withoutContextual.empty ())
5408
5415
return false ;
5409
5416
5410
- SmallVector<Type , 4 > withContextual;
5417
+ SmallPtrSet<TypeBase * , 4 > withContextual;
5411
5418
typeCheckExpr (TC, callExpr, DC, withContextual, contextualType);
5412
5419
// If type-checking with contextual type didn't produce any results
5413
5420
// it means that we have a contextual mismatch.
5414
- if (withContextual.empty ())
5415
- return diagnoseContextualConversionError (callExpr, contextualType, CTP);
5421
+ if (withContextual.empty ()) {
5422
+ // If there is just a single choice, we can hit contextual diagnostics
5423
+ // about it in case re-typecheck fails.
5424
+ Type exprType = withoutContextual.size () == 1 ? *withoutContextual.begin () : Type ();
5425
+ return diagnoseContextualConversionError (callExpr, contextualType, CTP,
5426
+ exprType);
5427
+ }
5416
5428
5417
5429
// If call produces a single type when type-checked with contextual
5418
5430
// expression, it means that the problem is elsewhere, any other
@@ -5431,15 +5443,15 @@ static bool shouldTypeCheckFunctionExpr(TypeChecker &TC, DeclContext *DC,
5431
5443
if (!isa<UnresolvedDotExpr>(fnExpr))
5432
5444
return true ;
5433
5445
5434
- SmallVector<Type , 4 > fnTypes;
5446
+ SmallPtrSet<TypeBase * , 4 > fnTypes;
5435
5447
TC.getPossibleTypesOfExpressionWithoutApplying (fnExpr, DC, fnTypes,
5436
5448
FreeTypeVariableBinding::UnresolvedType);
5437
5449
5438
5450
if (fnTypes.size () == 1 ) {
5439
5451
// Some member types depend on the arguments to produce a result type,
5440
5452
// type-checking such expressions without associated arguments is
5441
5453
// going to produce unrelated diagnostics.
5442
- if (auto fn = fnTypes[ 0 ] ->getAs <AnyFunctionType>()) {
5454
+ if (auto fn = (* fnTypes. begin ()) ->getAs <AnyFunctionType>()) {
5443
5455
auto resultType = fn->getResult ();
5444
5456
if (resultType->hasUnresolvedType () || resultType->hasTypeVariable ())
5445
5457
return false ;
@@ -5494,7 +5506,7 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
5494
5506
isa<UnresolvedDotExpr>(callExpr->getFn ())) {
5495
5507
fnExpr = callExpr->getFn ();
5496
5508
5497
- SmallVector<Type , 4 > types;
5509
+ SmallPtrSet<TypeBase * , 4 > types;
5498
5510
CS.TC .getPossibleTypesOfExpressionWithoutApplying (fnExpr, CS.DC , types);
5499
5511
5500
5512
auto isFunctionType = [getFuncType](Type type) -> bool {
0 commit comments