@@ -1948,10 +1948,13 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
1948
1948
// / the exact expression kind).
1949
1949
bool diagnoseGeneralMemberFailure (Constraint *constraint);
1950
1950
1951
- // / Diagnose the lookup of an enum element as instance member where only a
1952
- // / static member is allowed
1953
- void diagnoseEnumInstanceMemberLookup (EnumElementDecl *enumElementDecl,
1954
- SourceLoc loc);
1951
+ // / Diagnose the lookup of an static member or enum element as instance member.
1952
+ void diagnoseTypeMemberOnInstanceLookup (Type baseObjTy,
1953
+ Expr *baseExpr,
1954
+ DeclName memberName,
1955
+ DeclNameLoc nameLoc,
1956
+ ValueDecl *member,
1957
+ SourceLoc loc);
1955
1958
1956
1959
// / Given a result of name lookup that had no viable results, diagnose the
1957
1960
// / unviable ones.
@@ -2338,12 +2341,54 @@ bool FailureDiagnosis::diagnoseGeneralMemberFailure(Constraint *constraint) {
2338
2341
}
2339
2342
2340
2343
void FailureDiagnosis::
2341
- diagnoseEnumInstanceMemberLookup (EnumElementDecl *enumElementDecl,
2342
- SourceLoc loc) {
2343
- auto diag = diagnose (loc, diag::could_not_use_enum_element_on_instance,
2344
- enumElementDecl->getName ());
2345
- auto parentEnum = enumElementDecl->getParentEnum ();
2346
- auto enumMetatype = parentEnum->getType ()->castTo <AnyMetatypeType>();
2344
+ diagnoseTypeMemberOnInstanceLookup (Type baseObjTy,
2345
+ Expr *baseExpr,
2346
+ DeclName memberName,
2347
+ DeclNameLoc nameLoc,
2348
+ ValueDecl *member,
2349
+ SourceLoc loc) {
2350
+ SourceRange baseRange = baseExpr ? baseExpr->getSourceRange () : SourceRange ();
2351
+
2352
+ // If the base of the lookup is a protocol metatype, suggest
2353
+ // to replace the metatype with 'Self'
2354
+ // error saying the lookup cannot be on a protocol metatype
2355
+ if (auto metatypeTy = baseObjTy->getAs <MetatypeType>()) {
2356
+ auto Diag = diagnose (loc,
2357
+ diag::could_not_use_type_member_on_protocol_metatype,
2358
+ baseObjTy, memberName);
2359
+ Diag.highlight (baseRange).highlight (nameLoc.getSourceRange ());
2360
+
2361
+ // See through function decl context
2362
+ if (auto parent = CS->DC ->getInnermostTypeContext ()) {
2363
+ // If we are in a protocol extension of 'Proto' and we see
2364
+ // 'Proto.static', suggest 'Self.static'
2365
+ if (auto extensionContext = parent->getAsProtocolExtensionContext ()) {
2366
+ if (extensionContext->getDeclaredType ()->getCanonicalType ()
2367
+ == metatypeTy->getInstanceType ()->getCanonicalType ()) {
2368
+ Diag.fixItReplace (baseRange, " Self" );
2369
+ }
2370
+ }
2371
+ }
2372
+
2373
+ return ;
2374
+ }
2375
+
2376
+ // Otherwise the static member lookup was invalid because it was
2377
+ // called on an instance
2378
+ Optional<InFlightDiagnostic> Diag;
2379
+
2380
+ if (isa<EnumElementDecl>(member))
2381
+ Diag.emplace (diagnose (loc, diag::could_not_use_enum_element_on_instance,
2382
+ memberName));
2383
+ else
2384
+ Diag.emplace (diagnose (loc, diag::could_not_use_type_member_on_instance,
2385
+ baseObjTy, memberName));
2386
+
2387
+ Diag->highlight (nameLoc.getSourceRange ());
2388
+
2389
+ // No fix-it if the lookup was qualified
2390
+ if (baseExpr && !baseExpr->isImplicit ())
2391
+ return ;
2347
2392
2348
2393
// Determine the contextual type of the expression
2349
2394
Type contextualType;
@@ -2355,8 +2400,8 @@ diagnoseEnumInstanceMemberLookup(EnumElementDecl *enumElementDecl,
2355
2400
2356
2401
// Try to provide a fix-it that only contains a '.'
2357
2402
if (contextualType) {
2358
- if (enumMetatype-> getInstanceType () ->isEqual (contextualType)) {
2359
- diag. fixItInsert (loc, " ." );
2403
+ if (baseObjTy ->isEqual (contextualType)) {
2404
+ Diag-> fixItInsert (loc, " ." );
2360
2405
return ;
2361
2406
}
2362
2407
}
@@ -2382,8 +2427,8 @@ diagnoseEnumInstanceMemberLookup(EnumElementDecl *enumElementDecl,
2382
2427
// If the rhs of '~=' is the enum type, a single dot suffixes
2383
2428
// since the type can be inferred
2384
2429
Type secondArgType = binaryExpr->getArg ()->getElement (1 )->getType ();
2385
- if (secondArgType->isEqual (enumMetatype-> getInstanceType () )) {
2386
- diag. fixItInsert (loc, " ." );
2430
+ if (secondArgType->isEqual (baseObjTy )) {
2431
+ Diag-> fixItInsert (loc, " ." );
2387
2432
return ;
2388
2433
}
2389
2434
}
@@ -2392,12 +2437,14 @@ diagnoseEnumInstanceMemberLookup(EnumElementDecl *enumElementDecl,
2392
2437
}
2393
2438
2394
2439
// Fall back to a fix-it with a full type qualifier
2395
- SmallString<32 > enumTypeName;
2396
- llvm::raw_svector_ostream typeNameStream (enumTypeName);
2397
- typeNameStream << parentEnum->getName ();
2398
- typeNameStream << " ." ;
2399
-
2400
- diag.fixItInsert (loc, typeNameStream.str ());
2440
+ auto nominal =
2441
+ member->getDeclContext ()
2442
+ ->getAsNominalTypeOrNominalTypeExtensionContext ();
2443
+ SmallString<32 > typeName;
2444
+ llvm::raw_svector_ostream typeNameStream (typeName);
2445
+ typeNameStream << nominal->getName () << " ." ;
2446
+
2447
+ Diag->fixItInsert (loc, typeNameStream.str ());
2401
2448
return ;
2402
2449
}
2403
2450
@@ -2461,8 +2508,12 @@ diagnoseUnviableLookupResults(MemberLookupResult &result, Type baseObjTy,
2461
2508
// because there is exactly one candidate!) diagnose this.
2462
2509
bool sameProblem = true ;
2463
2510
auto firstProblem = result.UnviableCandidates [0 ].second ;
2464
- for (auto cand : result.UnviableCandidates )
2511
+ ValueDecl *member = nullptr ;
2512
+ for (auto cand : result.UnviableCandidates ) {
2513
+ if (member == nullptr )
2514
+ member = cand.first ;
2465
2515
sameProblem &= cand.second == firstProblem;
2516
+ }
2466
2517
2467
2518
auto instanceTy = baseObjTy;
2468
2519
if (auto *MTT = instanceTy->getAs <AnyMetatypeType>())
@@ -2527,48 +2578,11 @@ diagnoseUnviableLookupResults(MemberLookupResult &result, Type baseObjTy,
2527
2578
instanceTy, memberName)
2528
2579
.highlight (baseRange).highlight (nameLoc.getSourceRange ());
2529
2580
return ;
2530
-
2531
- case MemberLookupResult::UR_TypeMemberOnInstance:
2532
- if (instanceTy->isExistentialType () && baseObjTy->is <AnyMetatypeType>()) {
2533
- // If the base of the lookup is an existential metatype, emit an
2534
- // error saying the lookup cannot be on a protocol metatype
2535
- auto Diag = diagnose (loc, diag::could_not_use_type_member_on_existential,
2536
- baseObjTy, memberName);
2537
- Diag.highlight (baseRange).highlight (nameLoc.getSourceRange ());
2538
-
2539
- // See through function decl context
2540
- if (auto parent = CS->DC ->getParent ())
2541
- // If we are in a protocol extension of 'Proto' and we see
2542
- // 'Proto.static', suggest 'Self.static'
2543
- if (auto extensionContext = parent->getAsProtocolExtensionContext ()) {
2544
- if (extensionContext->getDeclaredType ()->getCanonicalType ()
2545
- == instanceTy->getCanonicalType ()) {
2546
- Diag.fixItReplace (baseRange, " Self" );
2547
- }
2548
- }
2549
2581
2550
- } else {
2551
- // Otherwise the static member lookup was invalid because it was
2552
- // called on an instance
2553
-
2554
- // Handle enum element lookup on instance type
2555
- auto lookThroughBaseObjTy = baseObjTy->lookThroughAllAnyOptionalTypes ();
2556
- if (lookThroughBaseObjTy->is <EnumType>()
2557
- || lookThroughBaseObjTy->is <BoundGenericEnumType>()) {
2558
- for (auto cand : result.UnviableCandidates ) {
2559
- ValueDecl *decl = cand.first ;
2560
- if (auto enumElementDecl = dyn_cast<EnumElementDecl>(decl)) {
2561
- diagnoseEnumInstanceMemberLookup (enumElementDecl, loc);
2562
- return ;
2563
- }
2564
- }
2565
- }
2566
-
2567
- // Provide diagnostic other static member lookups on instance type
2568
- diagnose (loc, diag::could_not_use_type_member_on_instance,
2569
- baseObjTy, memberName)
2570
- .highlight (baseRange).highlight (nameLoc.getSourceRange ());
2571
- }
2582
+ case MemberLookupResult::UR_TypeMemberOnInstance:
2583
+ diagnoseTypeMemberOnInstanceLookup (baseObjTy, baseExpr,
2584
+ memberName, nameLoc,
2585
+ member, loc);
2572
2586
return ;
2573
2587
2574
2588
case MemberLookupResult::UR_MutatingMemberOnRValue:
0 commit comments