@@ -886,7 +886,8 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
886
886
// / Attempt to produce a diagnostic for a mismatch between an expression's
887
887
// / type and its assumed contextual type.
888
888
bool diagnoseContextualConversionError (Expr *expr, Type contextualType,
889
- ContextualTypePurpose CTP);
889
+ ContextualTypePurpose CTP,
890
+ Type suggestedType = Type());
890
891
891
892
// / For an expression being type checked with a CTP_CalleeResult contextual
892
893
// / type, try to diagnose a problem.
@@ -2780,7 +2781,8 @@ static bool tryDiagnoseNonEscapingParameterToEscaping(
2780
2781
}
2781
2782
2782
2783
bool FailureDiagnosis::diagnoseContextualConversionError (
2783
- Expr *expr, Type contextualType, ContextualTypePurpose CTP) {
2784
+ Expr *expr, Type contextualType, ContextualTypePurpose CTP,
2785
+ Type suggestedType) {
2784
2786
// If the constraint system has a contextual type, then we can test to see if
2785
2787
// this is the problem that prevents us from solving the system.
2786
2788
if (!contextualType) {
@@ -2799,11 +2801,16 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
2799
2801
if (contextualType->is <InOutType>())
2800
2802
options |= TCC_AllowLValue;
2801
2803
2802
- auto recheckedExpr = typeCheckChildIndependently (expr, options);
2804
+ auto * recheckedExpr = typeCheckChildIndependently (expr, options);
2803
2805
auto exprType = recheckedExpr ? CS.getType (recheckedExpr) : Type ();
2804
2806
2807
+ // If there is a suggested type and re-typecheck failed, let's use it.
2808
+ if (!exprType)
2809
+ exprType = suggestedType;
2810
+
2805
2811
// If it failed and diagnosed something, then we're done.
2806
- if (!exprType) return true ;
2812
+ if (!exprType)
2813
+ return CS.TC .Diags .hadAnyError ();
2807
2814
2808
2815
// If we contextually had an inout type, and got a non-lvalue result, then
2809
2816
// we fail with a mutability error.
@@ -5263,7 +5270,7 @@ bool FailureDiagnosis::diagnoseTrailingClosureErrors(ApplyExpr *callExpr) {
5263
5270
}
5264
5271
};
5265
5272
5266
- SmallVector<Type , 4 > possibleTypes;
5273
+ SmallPtrSet<TypeBase * , 4 > possibleTypes;
5267
5274
auto currentType = CS.getType (fnExpr);
5268
5275
5269
5276
// If current type has type variables or unresolved types
@@ -5283,10 +5290,10 @@ bool FailureDiagnosis::diagnoseTrailingClosureErrors(ApplyExpr *callExpr) {
5283
5290
return diagnoseContextualConversionError (callExpr, contextualType,
5284
5291
CS.getContextualTypePurpose ());
5285
5292
} else {
5286
- possibleTypes.push_back (currentType);
5293
+ possibleTypes.insert (currentType. getPointer () );
5287
5294
}
5288
5295
5289
- for (auto type : possibleTypes) {
5296
+ for (Type type : possibleTypes) {
5290
5297
auto *fnType = type->getAs <AnyFunctionType>();
5291
5298
if (!fnType)
5292
5299
continue ;
@@ -5377,7 +5384,7 @@ bool FailureDiagnosis::diagnoseCallContextualConversionErrors(
5377
5384
auto *DC = CS.DC ;
5378
5385
5379
5386
auto typeCheckExpr = [](TypeChecker &TC, Expr *expr, DeclContext *DC,
5380
- SmallVectorImpl<Type > &types,
5387
+ SmallPtrSetImpl<TypeBase * > &types,
5381
5388
Type contextualType = Type ()) {
5382
5389
CalleeListener listener (contextualType);
5383
5390
TC.getPossibleTypesOfExpressionWithoutApplying (
@@ -5387,7 +5394,7 @@ bool FailureDiagnosis::diagnoseCallContextualConversionErrors(
5387
5394
// First let's type-check expression without contextual type, and
5388
5395
// see if that's going to produce a type, if so, let's type-check
5389
5396
// again, this time using given contextual type.
5390
- SmallVector<Type , 4 > withoutContextual;
5397
+ SmallPtrSet<TypeBase * , 4 > withoutContextual;
5391
5398
typeCheckExpr (TC, callExpr, DC, withoutContextual);
5392
5399
5393
5400
// If there are no types returned, it means that problem was
@@ -5396,12 +5403,17 @@ bool FailureDiagnosis::diagnoseCallContextualConversionErrors(
5396
5403
if (withoutContextual.empty ())
5397
5404
return false ;
5398
5405
5399
- SmallVector<Type , 4 > withContextual;
5406
+ SmallPtrSet<TypeBase * , 4 > withContextual;
5400
5407
typeCheckExpr (TC, callExpr, DC, withContextual, contextualType);
5401
5408
// If type-checking with contextual type didn't produce any results
5402
5409
// it means that we have a contextual mismatch.
5403
- if (withContextual.empty ())
5404
- return diagnoseContextualConversionError (callExpr, contextualType, CTP);
5410
+ if (withContextual.empty ()) {
5411
+ // If there is just a single choice, we can hit contextual diagnostics
5412
+ // about it in case re-typecheck fails.
5413
+ Type exprType = withoutContextual.size () == 1 ? *withoutContextual.begin () : Type ();
5414
+ return diagnoseContextualConversionError (callExpr, contextualType, CTP,
5415
+ exprType);
5416
+ }
5405
5417
5406
5418
// If call produces a single type when type-checked with contextual
5407
5419
// expression, it means that the problem is elsewhere, any other
@@ -5420,15 +5432,15 @@ static bool shouldTypeCheckFunctionExpr(TypeChecker &TC, DeclContext *DC,
5420
5432
if (!isa<UnresolvedDotExpr>(fnExpr))
5421
5433
return true ;
5422
5434
5423
- SmallVector<Type , 4 > fnTypes;
5435
+ SmallPtrSet<TypeBase * , 4 > fnTypes;
5424
5436
TC.getPossibleTypesOfExpressionWithoutApplying (fnExpr, DC, fnTypes,
5425
5437
FreeTypeVariableBinding::UnresolvedType);
5426
5438
5427
5439
if (fnTypes.size () == 1 ) {
5428
5440
// Some member types depend on the arguments to produce a result type,
5429
5441
// type-checking such expressions without associated arguments is
5430
5442
// going to produce unrelated diagnostics.
5431
- if (auto fn = fnTypes[ 0 ] ->getAs <AnyFunctionType>()) {
5443
+ if (auto fn = (* fnTypes. begin ()) ->getAs <AnyFunctionType>()) {
5432
5444
auto resultType = fn->getResult ();
5433
5445
if (resultType->hasUnresolvedType () || resultType->hasTypeVariable ())
5434
5446
return false ;
@@ -5483,7 +5495,7 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
5483
5495
isa<UnresolvedDotExpr>(callExpr->getFn ())) {
5484
5496
fnExpr = callExpr->getFn ();
5485
5497
5486
- SmallVector<Type , 4 > types;
5498
+ SmallPtrSet<TypeBase * , 4 > types;
5487
5499
CS.TC .getPossibleTypesOfExpressionWithoutApplying (fnExpr, CS.DC , types);
5488
5500
5489
5501
auto isFunctionType = [getFuncType](Type type) -> bool {
0 commit comments