@@ -1877,8 +1877,11 @@ bool CalleeCandidateInfo::diagnoseSimpleErrors(const Expr *E) {
1877
1877
CS->TC .diagnose (loc, diag::candidate_inaccessible, decl->getName (),
1878
1878
decl->getFormalAccess ());
1879
1879
}
1880
- for (auto cand : candidates)
1881
- CS->TC .diagnose (cand.getDecl (),diag::decl_declared_here, decl->getName ());
1880
+ for (auto cand : candidates) {
1881
+ if (auto decl = cand.getDecl ()) {
1882
+ CS->TC .diagnose (decl, diag::decl_declared_here, decl->getFullName ());
1883
+ }
1884
+ }
1882
1885
1883
1886
return true ;
1884
1887
}
@@ -2235,7 +2238,8 @@ bool FailureDiagnosis::diagnoseGeneralMemberFailure(Constraint *constraint) {
2235
2238
assert (isMemberConstraint (constraint));
2236
2239
2237
2240
auto memberName = constraint->getMember ();
2238
-
2241
+ auto isInitializer = memberName.isSimpleName (CS->TC .Context .Id_init );
2242
+
2239
2243
// Get the referenced base expression from the failed constraint, along with
2240
2244
// the SourceRange for the member ref. In "x.y", this returns the expr for x
2241
2245
// and the source range for y.
@@ -2328,12 +2332,21 @@ bool FailureDiagnosis::diagnoseGeneralMemberFailure(Constraint *constraint) {
2328
2332
.highlight (anchor->getSourceRange ()).highlight (memberRange);
2329
2333
return true ;
2330
2334
}
2331
-
2332
- MemberLookupResult result =
2333
- CS->performMemberLookup (constraint->getKind (), constraint->getMember (),
2334
- baseTy, constraint->getFunctionRefKind (),
2335
- constraint->getLocator (),
2336
- /* includeInaccessibleMembers*/ true );
2335
+
2336
+ // If this is initializer/constructor lookup we are dealing this.
2337
+ if (isInitializer) {
2338
+ // Let's check what is the base type we are trying to look it up on
2339
+ // because only MetatypeType is viable to find constructor on, as per
2340
+ // rules in ConstraintSystem::performMemberLookup.
2341
+ if (!baseTy->is <AnyMetatypeType>()) {
2342
+ baseTy = MetatypeType::get (baseTy, CS->getASTContext ());
2343
+ }
2344
+ }
2345
+
2346
+ MemberLookupResult result = CS->performMemberLookup (
2347
+ constraint->getKind (), memberName, baseTy,
2348
+ constraint->getFunctionRefKind (), constraint->getLocator (),
2349
+ /* includeInaccessibleMembers*/ true );
2337
2350
2338
2351
switch (result.OverallResult ) {
2339
2352
case MemberLookupResult::Unsolved:
@@ -2349,48 +2362,72 @@ bool FailureDiagnosis::diagnoseGeneralMemberFailure(Constraint *constraint) {
2349
2362
case MemberLookupResult::HasResults:
2350
2363
break ;
2351
2364
}
2352
-
2353
- // If this is a failing lookup, it has no viable candidates here.
2354
- if (result.ViableCandidates .empty ()) {
2355
- // Diagnose 'super.init', which can only appear inside another initializer,
2356
- // specially.
2357
- if (result.UnviableCandidates .empty () &&
2358
- memberName.isSimpleName (CS->TC .Context .Id_init ) &&
2359
- !baseObjTy->is <MetatypeType>()) {
2360
- if (auto ctorRef = dyn_cast<UnresolvedDotExpr>(expr)) {
2361
- if (isa<SuperRefExpr>(ctorRef->getBase ())) {
2362
- diagnose (anchor->getLoc (),
2363
- diag::super_initializer_not_in_initializer);
2364
- return true ;
2365
- }
2366
-
2367
- // Suggest inserting a call to 'type(of:)' to construct another object
2368
- // of the same dynamic type.
2369
- SourceRange fixItRng = ctorRef->getNameLoc ().getSourceRange ();
2370
-
2371
- // Surround the caller in `type(of:)`.
2372
- diagnose (anchor->getLoc (), diag::init_not_instance_member)
2373
- .fixItInsert (fixItRng.Start , " type(of: " )
2374
- .fixItInsertAfter (fixItRng.End , " )" );
2365
+
2366
+ // Since the lookup was allowing inaccessible members, let's check
2367
+ // if it found anything of that sort, which is easy to diagnose.
2368
+ bool allUnavailable = !CS->TC .getLangOpts ().DisableAvailabilityChecking ;
2369
+ for (auto &member : result.ViableCandidates ) {
2370
+ if (!member.isDecl ()) {
2371
+ // if there is no declaration, this choice is implicitly available.
2372
+ allUnavailable = false ;
2373
+ continue ;
2374
+ }
2375
+
2376
+ auto decl = member.getDecl ();
2377
+ // Check availability of the found choice.
2378
+ if (!decl->getAttrs ().isUnavailable (CS->getASTContext ()))
2379
+ allUnavailable = false ;
2380
+
2381
+ if (decl->isAccessibleFrom (CS->DC ))
2382
+ continue ;
2383
+
2384
+ if (auto *CD = dyn_cast<ConstructorDecl>(decl)) {
2385
+ CS->TC .diagnose (anchor->getLoc (), diag::init_candidate_inaccessible,
2386
+ CD->getResultType (), decl->getFormalAccess ());
2387
+ } else {
2388
+ CS->TC .diagnose (anchor->getLoc (), diag::candidate_inaccessible,
2389
+ decl->getName (), decl->getFormalAccess ());
2390
+ }
2391
+
2392
+ for (auto &candidate : result.ViableCandidates ) {
2393
+ if (auto decl = candidate.getDecl ()) {
2394
+ CS->TC .diagnose (decl, diag::decl_declared_here, decl->getFullName ());
2395
+ }
2396
+ }
2397
+
2398
+ return true ;
2399
+ }
2400
+
2401
+ // Diagnose 'super.init', which can only appear inside another initializer,
2402
+ // specially.
2403
+ if (result.UnviableCandidates .empty () && isInitializer &&
2404
+ !baseObjTy->is <MetatypeType>()) {
2405
+ if (auto ctorRef = dyn_cast<UnresolvedDotExpr>(expr)) {
2406
+ if (isa<SuperRefExpr>(ctorRef->getBase ())) {
2407
+ diagnose (anchor->getLoc (), diag::super_initializer_not_in_initializer);
2375
2408
return true ;
2376
2409
}
2410
+
2411
+ // Suggest inserting a call to 'type(of:)' to construct another object
2412
+ // of the same dynamic type.
2413
+ SourceRange fixItRng = ctorRef->getNameLoc ().getSourceRange ();
2414
+
2415
+ // Surround the caller in `type(of:)`.
2416
+ diagnose (anchor->getLoc (), diag::init_not_instance_member)
2417
+ .fixItInsert (fixItRng.Start , " type(of: " )
2418
+ .fixItInsertAfter (fixItRng.End , " )" );
2419
+ return true ;
2377
2420
}
2421
+ }
2378
2422
2423
+ if (result.ViableCandidates .empty ()) {
2379
2424
// FIXME: Dig out the property DeclNameLoc.
2380
2425
diagnoseUnviableLookupResults (result, baseObjTy, anchor, memberName,
2381
2426
DeclNameLoc (memberRange.Start ),
2382
2427
anchor->getLoc ());
2383
2428
return true ;
2384
2429
}
2385
2430
2386
-
2387
- bool allUnavailable = !CS->TC .getLangOpts ().DisableAvailabilityChecking ;
2388
- for (auto match : result.ViableCandidates ) {
2389
- if (!match.isDecl () ||
2390
- !match.getDecl ()->getAttrs ().isUnavailable (CS->getASTContext ()))
2391
- allUnavailable = false ;
2392
- }
2393
-
2394
2431
if (allUnavailable) {
2395
2432
auto firstDecl = result.ViableCandidates [0 ].getDecl ();
2396
2433
// FIXME: We need the enclosing CallExpr to rewrite the argument labels.
0 commit comments