@@ -2205,6 +2205,9 @@ static ConstraintFix *fixPropertyWrapperFailure(
2205
2205
if (!decl->hasValidSignature () || !type)
2206
2206
return nullptr ;
2207
2207
2208
+ if (baseTy->isEqual (type))
2209
+ return nullptr ;
2210
+
2208
2211
if (!attemptFix (resolvedOverload, decl, type))
2209
2212
return nullptr ;
2210
2213
@@ -3765,6 +3768,23 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
3765
3768
ConstraintKind kind,
3766
3769
ConstraintLocatorBuilder locator,
3767
3770
TypeMatchOptions flags) {
3771
+ if (shouldAttemptFixes ()) {
3772
+ auto *typeVar = type->getAs <TypeVariableType>();
3773
+ // If type variable, associated with this conformance check,
3774
+ // has been determined to be a "hole" in constraint system,
3775
+ // let's consider this check a success without recording
3776
+ // a fix, because it's just a consequence of other failure
3777
+ // e.g.
3778
+ //
3779
+ // func foo<T: BinaryInteger>(_: T) {}
3780
+ // foo(Foo.bar) <- if `Foo` doesn't have `bar` there is
3781
+ // no reason to complain about missing conformance.
3782
+ if (typeVar && isHole (typeVar)) {
3783
+ increaseScore (SK_Fix);
3784
+ return SolutionKind::Solved;
3785
+ }
3786
+ }
3787
+
3768
3788
// Dig out the fixed type to which this type refers.
3769
3789
type = getFixedTypeRecursive (type, flags, /* wantRValue=*/ true );
3770
3790
@@ -5176,12 +5196,33 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
5176
5196
// If the lookup found no hits at all (either viable or unviable), diagnose it
5177
5197
// as such and try to recover in various ways.
5178
5198
if (shouldAttemptFixes ()) {
5179
- // Let's record missing member in constraint system, this helps to prevent
5180
- // stacking up fixes for the same member, because e.g. if its base was of
5181
- // optional type, we'd re-introduce member constraint with optional stripped
5182
- // off to see if the problem is related to base not being explicitly unwrapped.
5183
- if (!MissingMembers.insert (locator))
5184
- return SolutionKind::Error;
5199
+ auto fixMissingMember = [&](Type baseTy, Type memberTy,
5200
+ ConstraintLocator *locator) -> SolutionKind {
5201
+ // Let's check whether there are any generic parameters
5202
+ // associated with base type, we'd have to default them
5203
+ // to `Any` and record as potential holes if so.
5204
+ baseTy.transform ([&](Type type) -> Type {
5205
+ if (auto *typeVar = type->getAs <TypeVariableType>()) {
5206
+ if (typeVar->getImpl ().hasRepresentativeOrFixed ())
5207
+ return type;
5208
+ recordHole (typeVar);
5209
+ }
5210
+ return type;
5211
+ });
5212
+
5213
+ auto *fix =
5214
+ DefineMemberBasedOnUse::create (*this , baseTy, member, locator);
5215
+ if (recordFix (fix))
5216
+ return SolutionKind::Error;
5217
+
5218
+ // Allow member type to default to `Any` to make it possible to form
5219
+ // solutions when contextual type of the result cannot be deduced e.g.
5220
+ // `let _ = x.foo`.
5221
+ if (auto *memberTypeVar = memberTy->getAs <TypeVariableType>())
5222
+ recordHole (memberTypeVar);
5223
+
5224
+ return SolutionKind::Solved;
5225
+ };
5185
5226
5186
5227
if (baseObjTy->getOptionalObjectType ()) {
5187
5228
// If the base type was an optional, look through it.
@@ -5203,6 +5244,18 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
5203
5244
}
5204
5245
}
5205
5246
5247
+ // Let's check whether the problem is related to optionality of base
5248
+ // type, or there is no member with a given name.
5249
+ result =
5250
+ performMemberLookup (kind, member, baseObjTy->getOptionalObjectType (),
5251
+ functionRefKind, locator,
5252
+ /* includeInaccessibleMembers*/ true );
5253
+
5254
+ // If uwrapped type still couldn't find anything for a given name,
5255
+ // let's fallback to a "not such member" fix.
5256
+ if (result.ViableCandidates .empty () && result.UnviableCandidates .empty ())
5257
+ return fixMissingMember (origBaseTy, memberTy, locator);
5258
+
5206
5259
// The result of the member access can either be the expected member type
5207
5260
// (for '!' or optional members with '?'), or the original member type
5208
5261
// with one extra level of optionality ('?' with non-optional members).
@@ -5230,26 +5283,27 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
5230
5283
return SolutionKind::Solved;
5231
5284
}
5232
5285
5233
- auto solveWithNewBaseOrName = [&](Type baseType, DeclName memberName,
5234
- bool allowFixes = true ) -> SolutionKind {
5235
- // Let's re-enable fixes for this member, because
5236
- // the base or member name has been changed.
5237
- if (allowFixes)
5238
- MissingMembers.remove (locator);
5286
+ auto solveWithNewBaseOrName = [&](Type baseType,
5287
+ DeclName memberName) -> SolutionKind {
5239
5288
return simplifyMemberConstraint (kind, baseType, memberName, memberTy,
5240
5289
useDC, functionRefKind, outerAlternatives,
5241
- flags, locatorB);
5290
+ flags | TMF_ApplyingFix , locatorB);
5242
5291
};
5243
5292
5293
+ // If this member reference is a result of a previous fix, let's not allow
5294
+ // any more fixes expect when base is optional, because it could also be
5295
+ // an IUO which requires a separate fix.
5296
+ if (flags.contains (TMF_ApplyingFix))
5297
+ return SolutionKind::Error;
5298
+
5244
5299
// Check if any property wrappers on the base of the member lookup have
5245
5300
// matching members that we can fall back to, or if the type wraps any
5246
5301
// properties that have matching members.
5247
5302
if (auto *fix = fixPropertyWrapperFailure (
5248
5303
*this , baseTy, locator,
5249
5304
[&](ResolvedOverloadSetListItem *overload, VarDecl *decl,
5250
5305
Type newBase) {
5251
- return solveWithNewBaseOrName (newBase, member,
5252
- /* allowFixes=*/ false ) ==
5306
+ return solveWithNewBaseOrName (newBase, member) ==
5253
5307
SolutionKind::Solved;
5254
5308
})) {
5255
5309
return recordFix (fix) ? SolutionKind::Error : SolutionKind::Solved;
@@ -5316,29 +5370,20 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
5316
5370
// fake its presence based on use, that makes it possible to diagnose
5317
5371
// problems related to member lookup more precisely.
5318
5372
5319
- origBaseTy.transform ([&](Type type) -> Type {
5320
- if (auto *typeVar = type->getAs <TypeVariableType>()) {
5321
- if (typeVar->getImpl ().hasRepresentativeOrFixed ())
5322
- return type;
5323
- // Default all of the generic parameters found in base to `Any`.
5324
- addConstraint (ConstraintKind::Defaultable, typeVar,
5325
- getASTContext ().TheAnyType ,
5326
- typeVar->getImpl ().getLocator ());
5373
+ // If base type is a "hole" there is no reason to record any
5374
+ // more "member not found" fixes for chained member references.
5375
+ if (auto *baseType = origBaseTy->getMetatypeInstanceType ()
5376
+ ->getRValueType ()
5377
+ ->getAs <TypeVariableType>()) {
5378
+ if (isHole (baseType)) {
5379
+ increaseScore (SK_Fix);
5380
+ if (auto *memberTypeVar = memberTy->getAs <TypeVariableType>())
5381
+ recordHole (memberTypeVar);
5382
+ return SolutionKind::Solved;
5327
5383
}
5328
- return type;
5329
- });
5330
-
5331
- auto *fix =
5332
- DefineMemberBasedOnUse::create (*this , origBaseTy, member, locator);
5333
- if (recordFix (fix))
5334
- return SolutionKind::Error;
5384
+ }
5335
5385
5336
- // Allow member type to default to `Any` to make it possible to form
5337
- // solutions when contextual type of the result cannot be deduced e.g.
5338
- // `let _ = x.foo`.
5339
- addConstraint (ConstraintKind::Defaultable, memberTy,
5340
- getASTContext ().TheAnyType , locator);
5341
- return SolutionKind::Solved;
5386
+ return fixMissingMember (origBaseTy, memberTy, locator);
5342
5387
}
5343
5388
return SolutionKind::Error;
5344
5389
}
@@ -6285,18 +6330,19 @@ ConstraintSystem::simplifyApplicableFnConstraint(
6285
6330
// Let's check if this member couldn't be found and is fixed
6286
6331
// to exist based on its usage.
6287
6332
if (auto *memberTy = type2->getAs <TypeVariableType>()) {
6288
- auto *locator = memberTy->getImpl ().getLocator ();
6289
- if (MissingMembers.count (locator)) {
6333
+ if (isHole (memberTy)) {
6290
6334
auto *funcTy = type1->castTo <FunctionType>();
6335
+ auto *locator = memberTy->getImpl ().getLocator ();
6291
6336
// Bind type variable associated with member to a type of argument
6292
6337
// application, which makes it seem like member exists with the
6293
6338
// types of the parameters matching argument types exactly.
6294
6339
addConstraint (ConstraintKind::Bind, memberTy, funcTy, locator);
6295
6340
// There might be no contextual type for result of the application,
6296
6341
// in cases like `let _ = x.foo()`, so let's default result to `Any`
6297
6342
// to make expressions like that type-check.
6298
- addConstraint (ConstraintKind::Defaultable, funcTy->getResult (),
6299
- getASTContext ().TheAnyType , locator);
6343
+ auto resultTy = funcTy->getResult ();
6344
+ if (auto *typeVar = resultTy->getAs <TypeVariableType>())
6345
+ recordHole (typeVar);
6300
6346
return SolutionKind::Solved;
6301
6347
}
6302
6348
}
@@ -7241,6 +7287,15 @@ bool ConstraintSystem::recordFix(ConstraintFix *fix) {
7241
7287
return false ;
7242
7288
}
7243
7289
7290
+ void ConstraintSystem::recordHole (TypeVariableType *typeVar) {
7291
+ assert (typeVar);
7292
+ auto *locator = typeVar->getImpl ().getLocator ();
7293
+ if (Holes.insert (locator)) {
7294
+ addConstraint (ConstraintKind::Defaultable, typeVar,
7295
+ getASTContext ().TheAnyType , locator);
7296
+ }
7297
+ }
7298
+
7244
7299
ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint (
7245
7300
ConstraintFix *fix, Type type1, Type type2, ConstraintKind matchKind,
7246
7301
TypeMatchOptions flags, ConstraintLocatorBuilder locator) {
0 commit comments