@@ -2075,6 +2075,20 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
2075
2075
bool diagnoseCalleeResultContextualConversionError ();
2076
2076
2077
2077
private:
2078
+ // / Validate potential contextual type for type-checking one of the
2079
+ // / sub-expressions, usually correct/valid types are the ones which
2080
+ // / either don't have type variables or are not generic, because
2081
+ // / generic types with left-over type variables or unresolved types
2082
+ // / degrade quality of diagnostics if allowed to be used as contextual.
2083
+ // /
2084
+ // / \param contextualType The candidate contextual type.
2085
+ // / \param CTP The contextual purpose attached to the given candidate.
2086
+ // /
2087
+ // / \returns Pair of validated type and it's purpose, potentially nullified
2088
+ // / if it wasn't an appropriate type to be used.
2089
+ std::pair<Type, ContextualTypePurpose>
2090
+ validateContextualType (Type contextualType, ContextualTypePurpose CTP);
2091
+
2078
2092
// / Check the specified closure to see if it is a multi-statement closure with
2079
2093
// / an uninferred type. If so, diagnose the problem with an error and return
2080
2094
// / true.
@@ -3433,29 +3447,11 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
3433
3447
3434
3448
CS->TC .addExprForDiagnosis (subExpr, subExpr);
3435
3449
}
3436
-
3437
- // If we have a conversion type, but it has type variables (from the current
3438
- // ConstraintSystem), then we can't use it.
3439
- if (convertType) {
3440
- // If we're asked to convert to an autoclosure, then we really want to
3441
- // convert to the result of it.
3442
- if (auto *FT = convertType->getAs <AnyFunctionType>())
3443
- if (FT->isAutoClosure ())
3444
- convertType = FT->getResult ();
3445
3450
3446
- // Replace archetypes and type parameters with UnresolvedType.
3447
- convertType = replaceTypeParametersWithUnresolved (convertType);
3448
- convertType = replaceTypeVariablesWithUnresolved (convertType);
3449
-
3450
- // If the conversion type contains no info, drop it.
3451
- if (convertType->is <UnresolvedType>() ||
3452
- (convertType->is <MetatypeType>() && convertType->hasUnresolvedType ())) {
3453
- convertType = Type ();
3454
- convertTypePurpose = CTP_Unused;
3455
- }
3456
- }
3451
+ // Validate contextual type before trying to use it.
3452
+ std::tie (convertType, convertTypePurpose) =
3453
+ validateContextualType (convertType, convertTypePurpose);
3457
3454
3458
-
3459
3455
// If we have no contextual type information and the subexpr is obviously a
3460
3456
// overload set, don't recursively simplify this. The recursive solver will
3461
3457
// sometimes pick one based on arbitrary ranking behavior (e.g. like
@@ -7376,6 +7372,61 @@ static void noteArchetypeSource(const TypeLoc &loc, ArchetypeType *archetype,
7376
7372
}
7377
7373
}
7378
7374
7375
+ std::pair<Type, ContextualTypePurpose>
7376
+ FailureDiagnosis::validateContextualType (Type contextualType,
7377
+ ContextualTypePurpose CTP) {
7378
+ if (!contextualType)
7379
+ return {contextualType, CTP};
7380
+
7381
+ // If we're asked to convert to an autoclosure, then we really want to
7382
+ // convert to the result of it.
7383
+ if (auto *FT = contextualType->getAs <AnyFunctionType>())
7384
+ if (FT->isAutoClosure ())
7385
+ contextualType = FT->getResult ();
7386
+
7387
+ bool shouldNullify = false ;
7388
+ if (auto objectType = contextualType->getLValueOrInOutObjectType ()) {
7389
+ // Note that simply checking for `objectType->hasUnresolvedType()` is not
7390
+ // appropriate in this case standalone, because if it's in a function,
7391
+ // for example, or inout type, we still want to preserve it's skeleton
7392
+ // / because that helps to diagnose inout argument issues. Complete
7393
+ // nullification is only appropriate for generic types with unresolved
7394
+ // types or standalone archetypes because that's going to give
7395
+ // sub-expression solver a chance to try and compute type as it sees fit
7396
+ // and higher level code would have a chance to check it, which avoids
7397
+ // diagnostic messages like `cannot convert (_) -> _ to (Int) -> Void`.
7398
+ switch (objectType->getDesugaredType ()->getKind ()) {
7399
+ case TypeKind::Archetype:
7400
+ case TypeKind::Unresolved:
7401
+ shouldNullify = true ;
7402
+ break ;
7403
+
7404
+ case TypeKind::BoundGenericEnum:
7405
+ case TypeKind::BoundGenericClass:
7406
+ case TypeKind::BoundGenericStruct:
7407
+ case TypeKind::UnboundGeneric:
7408
+ case TypeKind::GenericFunction:
7409
+ case TypeKind::Metatype:
7410
+ shouldNullify = objectType->hasUnresolvedType ();
7411
+ break ;
7412
+
7413
+ default :
7414
+ shouldNullify = false ;
7415
+ break ;
7416
+ }
7417
+ }
7418
+
7419
+ // If the conversion type contains no info, drop it.
7420
+ if (shouldNullify)
7421
+ return {Type (), CTP_Unused};
7422
+
7423
+ // Remove all of the potentially leftover type variables or type parameters
7424
+ // from the contextual type to be used by new solver.
7425
+ contextualType = replaceTypeParametersWithUnresolved (contextualType);
7426
+ contextualType = replaceTypeVariablesWithUnresolved (contextualType);
7427
+
7428
+ return {contextualType, CTP};
7429
+ }
7379
7430
7380
7431
// / Check the specified closure to see if it is a multi-statement closure with
7381
7432
// / an uninferred type. If so, diagnose the problem with an error and return
0 commit comments