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