Skip to content

Commit 2fd3aa1

Browse files
committed
[QoI] Improve diagnostics when all .init candidates are inaccessible
1 parent 564fde4 commit 2fd3aa1

File tree

3 files changed

+23
-15
lines changed

3 files changed

+23
-15
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,19 @@ ERROR(candidate_inaccessible,none,
122122
"'%select{private|fileprivate|internal|PUBLIC}1' protection level",
123123
(DeclName, Accessibility))
124124

125+
NOTE(note_candidate_inaccessible,none,
126+
"%0 is inaccessible due to "
127+
"'%select{private|fileprivate|internal|PUBLIC}1' protection level",
128+
(DeclName, Accessibility))
129+
125130
ERROR(init_candidate_inaccessible,none,
126131
"%0 initializer is inaccessible due to "
127132
"'%select{private|fileprivate|internal|PUBLIC}1' protection level",
128133
(Type, Accessibility))
129134

135+
ERROR(all_candidates_inaccessible,none,
136+
"all %0 candidates are inaccessible",
137+
(DeclName))
130138

131139
ERROR(cannot_pass_rvalue_mutating_subelement,none,
132140
"cannot use mutating member on immutable value: %0",

lib/Sema/CSDiag.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,6 +2364,7 @@ bool FailureDiagnosis::diagnoseGeneralMemberFailure(Constraint *constraint) {
23642364
// Since the lookup was allowing inaccessible members, let's check
23652365
// if it found anything of that sort, which is easy to diagnose.
23662366
bool allUnavailable = !CS->TC.getLangOpts().DisableAvailabilityChecking;
2367+
bool allInaccessible = true;
23672368
for (auto &member : result.ViableCandidates) {
23682369
if (!member.isDecl()) {
23692370
// if there is no declaration, this choice is implicitly available.
@@ -2377,30 +2378,29 @@ bool FailureDiagnosis::diagnoseGeneralMemberFailure(Constraint *constraint) {
23772378
allUnavailable = false;
23782379

23792380
if (decl->isAccessibleFrom(CS->DC))
2380-
continue;
2381-
2382-
if (auto *CD = dyn_cast<ConstructorDecl>(decl)) {
2383-
CS->TC.diagnose(anchor->getLoc(), diag::init_candidate_inaccessible,
2384-
CD->getResultType(), decl->getFormalAccess());
2385-
} else {
2386-
CS->TC.diagnose(anchor->getLoc(), diag::candidate_inaccessible,
2387-
decl->getName(), decl->getFormalAccess());
2388-
}
2381+
allInaccessible = false;
2382+
}
2383+
2384+
// If no candidates were accessible, say so.
2385+
if (allInaccessible && !result.ViableCandidates.empty()) {
2386+
CS->TC.diagnose(anchor->getLoc(), diag::all_candidates_inaccessible,
2387+
memberName);
23892388

23902389
for (auto &candidate : result.ViableCandidates) {
23912390
if (auto decl = candidate.getDecl()) {
2392-
CS->TC.diagnose(decl, diag::decl_declared_here, decl->getFullName());
2391+
CS->TC.diagnose(decl, diag::note_candidate_inaccessible,
2392+
decl->getFullName(), decl->getFormalAccess());
23932393
}
23942394
}
23952395

23962396
return true;
23972397
}
23982398

2399-
// Diagnose 'super.init', which can only appear inside another initializer,
2400-
// specially.
24012399
if (result.UnviableCandidates.empty() && isInitializer &&
24022400
!baseObjTy->is<MetatypeType>()) {
24032401
if (auto ctorRef = dyn_cast<UnresolvedDotExpr>(expr)) {
2402+
// Diagnose 'super.init', which can only appear inside another
2403+
// initializer, specially.
24042404
if (isa<SuperRefExpr>(ctorRef->getBase())) {
24052405
diagnose(anchor->getLoc(), diag::super_initializer_not_in_initializer);
24062406
return true;

test/Constraints/super_constructor.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ class B {
5555

5656
// SR-2484: Bad diagnostic for incorrectly calling private init
5757
class SR_2484 {
58-
private init() {} // expected-note {{'init()' declared here}}
59-
private init(a: Int) {} // expected-note {{'init(a:)' declared here}}
58+
private init() {} // expected-note {{'init()' is inaccessible due to 'private' protection level}}
59+
private init(a: Int) {} // expected-note {{'init(a:)' is inaccessible due to 'private' protection level}}
6060
}
6161

6262
class Impl_2484 : SR_2484 {
6363
init() {
64-
super.init() // expected-error {{'SR_2484' initializer is inaccessible due to 'private' protection level}}
64+
super.init() // expected-error {{all 'init' candidates are inaccessible}}
6565
}
6666
}

0 commit comments

Comments
 (0)