@@ -2177,6 +2177,9 @@ static ConstraintFix *fixPropertyWrapperFailure(
2177
2177
if (!decl->hasValidSignature () || !type)
2178
2178
return nullptr ;
2179
2179
2180
+ if (baseTy->isEqual (type))
2181
+ return nullptr ;
2182
+
2180
2183
if (!attemptFix (resolvedOverload, decl, type))
2181
2184
return nullptr ;
2182
2185
@@ -5143,12 +5146,33 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
5143
5146
// If the lookup found no hits at all (either viable or unviable), diagnose it
5144
5147
// as such and try to recover in various ways.
5145
5148
if (shouldAttemptFixes ()) {
5146
- // Let's record missing member in constraint system, this helps to prevent
5147
- // stacking up fixes for the same member, because e.g. if its base was of
5148
- // optional type, we'd re-introduce member constraint with optional stripped
5149
- // off to see if the problem is related to base not being explicitly unwrapped.
5150
- if (!MissingMembers.insert (locator))
5151
- return SolutionKind::Error;
5149
+ auto fixMissingMember = [&](Type baseTy, Type memberTy,
5150
+ ConstraintLocator *locator) -> SolutionKind {
5151
+ // Let's check whether there are any generic parameters
5152
+ // associated with base type, we'd have to default them
5153
+ // to `Any` and record as potential holes if so.
5154
+ baseTy.transform ([&](Type type) -> Type {
5155
+ if (auto *typeVar = type->getAs <TypeVariableType>()) {
5156
+ if (typeVar->getImpl ().hasRepresentativeOrFixed ())
5157
+ return type;
5158
+ recordHole (typeVar);
5159
+ }
5160
+ return type;
5161
+ });
5162
+
5163
+ auto *fix =
5164
+ DefineMemberBasedOnUse::create (*this , baseTy, member, locator);
5165
+ if (recordFix (fix))
5166
+ return SolutionKind::Error;
5167
+
5168
+ // Allow member type to default to `Any` to make it possible to form
5169
+ // solutions when contextual type of the result cannot be deduced e.g.
5170
+ // `let _ = x.foo`.
5171
+ if (auto *memberTypeVar = memberTy->getAs <TypeVariableType>())
5172
+ recordHole (memberTypeVar);
5173
+
5174
+ return SolutionKind::Solved;
5175
+ };
5152
5176
5153
5177
if (baseObjTy->getOptionalObjectType ()) {
5154
5178
// If the base type was an optional, look through it.
@@ -5170,6 +5194,18 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
5170
5194
}
5171
5195
}
5172
5196
5197
+ // Let's check whether the problem is related to optionality of base
5198
+ // type, or there is no member with a given name.
5199
+ result =
5200
+ performMemberLookup (kind, member, baseObjTy->getOptionalObjectType (),
5201
+ functionRefKind, locator,
5202
+ /* includeInaccessibleMembers*/ true );
5203
+
5204
+ // If uwrapped type still couldn't find anything for a given name,
5205
+ // let's fallback to a "not such member" fix.
5206
+ if (result.ViableCandidates .empty () && result.UnviableCandidates .empty ())
5207
+ return fixMissingMember (origBaseTy, memberTy, locator);
5208
+
5173
5209
// The result of the member access can either be the expected member type
5174
5210
// (for '!' or optional members with '?'), or the original member type
5175
5211
// with one extra level of optionality ('?' with non-optional members).
@@ -5197,26 +5233,27 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
5197
5233
return SolutionKind::Solved;
5198
5234
}
5199
5235
5200
- auto solveWithNewBaseOrName = [&](Type baseType, DeclName memberName,
5201
- bool allowFixes = true ) -> SolutionKind {
5202
- // Let's re-enable fixes for this member, because
5203
- // the base or member name has been changed.
5204
- if (allowFixes)
5205
- MissingMembers.remove (locator);
5236
+ auto solveWithNewBaseOrName = [&](Type baseType,
5237
+ DeclName memberName) -> SolutionKind {
5206
5238
return simplifyMemberConstraint (kind, baseType, memberName, memberTy,
5207
5239
useDC, functionRefKind, outerAlternatives,
5208
- flags, locatorB);
5240
+ flags | TMF_ApplyingFix , locatorB);
5209
5241
};
5210
5242
5243
+ // If this member reference is a result of a previous fix, let's not allow
5244
+ // any more fixes expect when base is optional, because it could also be
5245
+ // an IUO which requires a separate fix.
5246
+ if (flags.contains (TMF_ApplyingFix))
5247
+ return SolutionKind::Error;
5248
+
5211
5249
// Check if any property wrappers on the base of the member lookup have
5212
5250
// matching members that we can fall back to, or if the type wraps any
5213
5251
// properties that have matching members.
5214
5252
if (auto *fix = fixPropertyWrapperFailure (
5215
5253
*this , baseTy, locator,
5216
5254
[&](ResolvedOverloadSetListItem *overload, VarDecl *decl,
5217
5255
Type newBase) {
5218
- return solveWithNewBaseOrName (newBase, member,
5219
- /* allowFixes=*/ false ) ==
5256
+ return solveWithNewBaseOrName (newBase, member) ==
5220
5257
SolutionKind::Solved;
5221
5258
})) {
5222
5259
return recordFix (fix) ? SolutionKind::Error : SolutionKind::Solved;
@@ -5283,38 +5320,20 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
5283
5320
// fake its presence based on use, that makes it possible to diagnose
5284
5321
// problems related to member lookup more precisely.
5285
5322
5286
- auto defaultTypeVariableToAny = [&](TypeVariableType *typeVar) {
5287
- // Recording this generic parameter is a potential "hole" in
5288
- // the constraint system.
5289
- recordHole (typeVar);
5290
- // Default all of the generic parameters found in base to `Any`.
5291
- addConstraint (ConstraintKind::Defaultable, typeVar,
5292
- getASTContext ().TheAnyType ,
5293
- typeVar->getImpl ().getLocator ());
5294
- };
5295
-
5296
- origBaseTy.transform ([&](Type type) -> Type {
5297
- if (auto *typeVar = type->getAs <TypeVariableType>()) {
5298
- if (typeVar->getImpl ().hasRepresentativeOrFixed ())
5299
- return type;
5300
-
5301
- defaultTypeVariableToAny (typeVar);
5323
+ // If base type is a "hole" there is no reason to record any
5324
+ // more "member not found" fixes for chained member references.
5325
+ if (auto *baseType = origBaseTy->getMetatypeInstanceType ()
5326
+ ->getRValueType ()
5327
+ ->getAs <TypeVariableType>()) {
5328
+ if (isHole (baseType)) {
5329
+ increaseScore (SK_Fix);
5330
+ if (auto *memberTypeVar = memberTy->getAs <TypeVariableType>())
5331
+ recordHole (memberTypeVar);
5332
+ return SolutionKind::Solved;
5302
5333
}
5303
- return type;
5304
- });
5305
-
5306
- auto *fix =
5307
- DefineMemberBasedOnUse::create (*this , origBaseTy, member, locator);
5308
- if (recordFix (fix))
5309
- return SolutionKind::Error;
5310
-
5311
- // Allow member type to default to `Any` to make it possible to form
5312
- // solutions when contextual type of the result cannot be deduced e.g.
5313
- // `let _ = x.foo`.
5314
- if (auto *memberTypeVar = memberTy->getAs <TypeVariableType>())
5315
- defaultTypeVariableToAny (memberTypeVar);
5334
+ }
5316
5335
5317
- return SolutionKind::Solved ;
5336
+ return fixMissingMember (origBaseTy, memberTy, locator) ;
5318
5337
}
5319
5338
return SolutionKind::Error;
5320
5339
}
@@ -6260,18 +6279,19 @@ ConstraintSystem::simplifyApplicableFnConstraint(
6260
6279
// Let's check if this member couldn't be found and is fixed
6261
6280
// to exist based on its usage.
6262
6281
if (auto *memberTy = type2->getAs <TypeVariableType>()) {
6263
- auto *locator = memberTy->getImpl ().getLocator ();
6264
- if (MissingMembers.count (locator)) {
6282
+ if (isHole (memberTy)) {
6265
6283
auto *funcTy = type1->castTo <FunctionType>();
6284
+ auto *locator = memberTy->getImpl ().getLocator ();
6266
6285
// Bind type variable associated with member to a type of argument
6267
6286
// application, which makes it seem like member exists with the
6268
6287
// types of the parameters matching argument types exactly.
6269
6288
addConstraint (ConstraintKind::Bind, memberTy, funcTy, locator);
6270
6289
// There might be no contextual type for result of the application,
6271
6290
// in cases like `let _ = x.foo()`, so let's default result to `Any`
6272
6291
// to make expressions like that type-check.
6273
- addConstraint (ConstraintKind::Defaultable, funcTy->getResult (),
6274
- getASTContext ().TheAnyType , locator);
6292
+ auto resultTy = funcTy->getResult ();
6293
+ if (auto *typeVar = resultTy->getAs <TypeVariableType>())
6294
+ recordHole (typeVar);
6275
6295
return SolutionKind::Solved;
6276
6296
}
6277
6297
}
@@ -7174,6 +7194,15 @@ bool ConstraintSystem::recordFix(ConstraintFix *fix) {
7174
7194
return false ;
7175
7195
}
7176
7196
7197
+ void ConstraintSystem::recordHole (TypeVariableType *typeVar) {
7198
+ assert (typeVar);
7199
+ auto *locator = typeVar->getImpl ().getLocator ();
7200
+ if (Holes.insert (locator)) {
7201
+ addConstraint (ConstraintKind::Defaultable, typeVar,
7202
+ getASTContext ().TheAnyType , locator);
7203
+ }
7204
+ }
7205
+
7177
7206
ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint (
7178
7207
ConstraintFix *fix, Type type1, Type type2, ConstraintKind matchKind,
7179
7208
TypeMatchOptions flags, ConstraintLocatorBuilder locator) {
0 commit comments