Skip to content

Commit 485ccd6

Browse files
authored
Merge pull request #4970 from jrose-apple/swift-3-ignore-access-when-you-find-nothing
Add "IgnoreAccessControl" to UnqualifiedLookup, and use it for diagnostics
2 parents f2c565c + 6928479 commit 485ccd6

File tree

7 files changed

+89
-29
lines changed

7 files changed

+89
-29
lines changed

include/swift/AST/NameLookup.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ class UnqualifiedLookup {
6868
bool IsKnownPrivate = false,
6969
SourceLoc Loc = SourceLoc(),
7070
bool IsTypeLookup = false,
71-
bool AllowProtocolMembers = false);
71+
bool AllowProtocolMembers = false,
72+
bool IgnoreAccessControl = false);
7273

7374
SmallVector<UnqualifiedLookupResult, 4> Results;
7475

lib/AST/NameLookup.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,8 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
399399
LazyResolver *TypeResolver,
400400
bool IsKnownNonCascading,
401401
SourceLoc Loc, bool IsTypeLookup,
402-
bool AllowProtocolMembers) {
402+
bool AllowProtocolMembers,
403+
bool IgnoreAccessControl) {
403404
Module &M = *DC->getParentModule();
404405
ASTContext &Ctx = M.getASTContext();
405406
const SourceManager &SM = Ctx.SourceMgr;
@@ -563,6 +564,8 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
563564
options |= NL_ProtocolMembers;
564565
if (IsTypeLookup)
565566
options |= NL_OnlyTypes;
567+
if (IgnoreAccessControl)
568+
options |= NL_IgnoreAccessibility;
566569

567570
if (!ExtendedType)
568571
ExtendedType = ErrorType::get(Ctx);

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -425,10 +425,10 @@ resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *DC) {
425425
SourceLoc Loc = UDRE->getLoc();
426426

427427
// Perform standard value name lookup.
428-
NameLookupOptions LookupOptions = defaultUnqualifiedLookupOptions;
428+
NameLookupOptions lookupOptions = defaultUnqualifiedLookupOptions;
429429
if (isa<AbstractFunctionDecl>(DC))
430-
LookupOptions |= NameLookupFlags::KnownPrivate;
431-
auto Lookup = lookupUnqualified(DC, Name, Loc, LookupOptions);
430+
lookupOptions |= NameLookupFlags::KnownPrivate;
431+
auto Lookup = lookupUnqualified(DC, Name, Loc, lookupOptions);
432432

433433
if (!Lookup) {
434434
// If we failed lookup of an operator, check to see it to see if it is
@@ -438,12 +438,36 @@ resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *DC) {
438438
return new (Context) ErrorExpr(UDRE->getSourceRange());
439439
}
440440

441+
// Try ignoring access control.
442+
NameLookupOptions relookupOptions = lookupOptions;
443+
relookupOptions |= NameLookupFlags::KnownPrivate;
444+
relookupOptions |= NameLookupFlags::IgnoreAccessibility;
445+
LookupResult inaccessibleResults = lookupUnqualified(DC, Name, Loc,
446+
relookupOptions);
447+
if (inaccessibleResults) {
448+
// FIXME: What if the unviable candidates have different levels of access?
449+
const ValueDecl *first = inaccessibleResults.front().Decl;
450+
diagnose(Loc, diag::candidate_inaccessible,
451+
Name, first->getFormalAccess());
452+
453+
// FIXME: If any of the candidates (usually just one) are in the same
454+
// module we could offer a fix-it.
455+
for (auto lookupResult : inaccessibleResults) {
456+
diagnose(lookupResult.Decl, diag::decl_declared_here,
457+
lookupResult.Decl->getFullName());
458+
}
459+
460+
// Don't try to recover here; we'll get more access-related diagnostics
461+
// downstream if the type of the inaccessible decl is also inaccessible.
462+
return new (Context) ErrorExpr(UDRE->getSourceRange());
463+
}
464+
441465
// TODO: Name will be a compound name if it was written explicitly as
442466
// one, but we should also try to propagate labels into this.
443467
DeclNameLoc nameLoc = UDRE->getNameLoc();
444468

445469
performTypoCorrection(DC, UDRE->getRefKind(), Type(), Name, Loc,
446-
LookupOptions, Lookup);
470+
lookupOptions, Lookup);
447471

448472
diagnose(Loc, diag::use_unresolved_identifier, Name, Name.isOperator())
449473
.highlight(UDRE->getSourceRange());

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,13 @@ LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclName name,
199199
}
200200
}
201201

202-
UnqualifiedLookup lookup(name, dc, this,
203-
options.contains(NameLookupFlags::KnownPrivate),
204-
loc,
205-
options.contains(NameLookupFlags::OnlyTypes),
206-
options.contains(NameLookupFlags::ProtocolMembers));
202+
UnqualifiedLookup lookup(
203+
name, dc, this,
204+
options.contains(NameLookupFlags::KnownPrivate),
205+
loc,
206+
options.contains(NameLookupFlags::OnlyTypes),
207+
options.contains(NameLookupFlags::ProtocolMembers),
208+
options.contains(NameLookupFlags::IgnoreAccessibility));
207209

208210
LookupResult result;
209211
bool considerProtocolMembers

lib/Sema/TypeCheckType.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,35 @@ static Type diagnoseUnknownType(TypeChecker &tc, DeclContext *dc,
745745
comp->setValue(nominal);
746746
return type;
747747
}
748-
748+
749+
750+
// Try ignoring access control.
751+
DeclContext *lookupDC = dc;
752+
if (options.contains(TR_GenericSignature))
753+
lookupDC = dc->getParent();
754+
755+
NameLookupOptions relookupOptions = lookupOptions;
756+
relookupOptions |= NameLookupFlags::KnownPrivate;
757+
relookupOptions |= NameLookupFlags::IgnoreAccessibility;
758+
LookupResult inaccessibleResults =
759+
tc.lookupUnqualified(lookupDC, comp->getIdentifier(), comp->getIdLoc(),
760+
relookupOptions);
761+
if (inaccessibleResults) {
762+
// FIXME: What if the unviable candidates have different levels of access?
763+
auto first = cast<TypeDecl>(inaccessibleResults.front().Decl);
764+
tc.diagnose(comp->getIdLoc(), diag::candidate_inaccessible,
765+
comp->getIdentifier(), first->getFormalAccess());
766+
767+
// FIXME: If any of the candidates (usually just one) are in the same
768+
// module we could offer a fix-it.
769+
for (auto lookupResult : inaccessibleResults)
770+
tc.diagnose(lookupResult.Decl, diag::type_declared_here);
771+
772+
// Don't try to recover here; we'll get more access-related diagnostics
773+
// downstream if we do.
774+
return ErrorType::get(tc.Context);
775+
}
776+
749777
// Fallback.
750778
SourceLoc L = comp->getIdLoc();
751779
SourceRange R = SourceRange(comp->getIdLoc());

test/NameBinding/accessibility.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class Sub : Base {
6666
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
6767
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
6868

69-
method() // expected-error {{use of unresolved identifier 'method'}}
69+
method() // expected-error {{'method' is inaccessible due to 'internal' protection level}}
7070
self.method() // expected-error {{'method' is inaccessible due to 'internal' protection level}}
7171
super.method() // expected-error {{'method' is inaccessible due to 'internal' protection level}}
7272
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:

test/Sema/accessibility_private.swift

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class Container {
1515
_ = self.bar
1616
self.bar = 5
1717

18-
privateExtensionMethod() // FIXME expected-error {{use of unresolved identifier 'privateExtensionMethod'}}
18+
privateExtensionMethod() // expected-error {{'privateExtensionMethod' is inaccessible due to 'private' protection level}}
1919
self.privateExtensionMethod() // expected-error {{'privateExtensionMethod' is inaccessible due to 'private' protection level}}
2020

2121
_ = PrivateInner()
@@ -54,23 +54,23 @@ extension Container {
5454
private func privateExtensionMethod() {} // expected-note * {{declared here}}
5555

5656
func extensionTest() {
57-
foo() // FIXME expected-error {{use of unresolved identifier 'foo'}}
57+
foo() // expected-error {{'foo' is inaccessible due to 'private' protection level}}
5858
self.foo() // expected-error {{'foo' is inaccessible due to 'private' protection level}}
5959

60-
_ = bar // FIXME expected-error {{use of unresolved identifier 'bar'}}
61-
bar = 5 // FIXME expected-error {{use of unresolved identifier 'bar'}}
60+
_ = bar // expected-error {{'bar' is inaccessible due to 'private' protection level}}
61+
bar = 5 // expected-error {{'bar' is inaccessible due to 'private' protection level}}
6262
_ = self.bar // expected-error {{'bar' is inaccessible due to 'private' protection level}}
6363
self.bar = 5 // expected-error {{'bar' is inaccessible due to 'private' protection level}}
6464

6565
privateExtensionMethod()
6666
self.privateExtensionMethod()
6767

68-
_ = PrivateInner() // FIXME expected-error {{use of unresolved identifier 'PrivateInner'}}
68+
_ = PrivateInner() // expected-error {{'PrivateInner' is inaccessible due to 'private' protection level}}
6969
_ = Container.PrivateInner() // expected-error {{'PrivateInner' is inaccessible due to 'private' protection level}}
7070
}
7171

7272
// FIXME: Why do these errors happen twice?
73-
var extensionInner: PrivateInner? { return nil } // FIXME expected-error 2 {{use of undeclared type 'PrivateInner'}}
73+
var extensionInner: PrivateInner? { return nil } // expected-error 2 {{'PrivateInner' is inaccessible due to 'private' protection level}}
7474
var extensionInnerQualified: Container.PrivateInner? { return nil } // expected-error 2 {{'PrivateInner' is inaccessible due to 'private' protection level}}
7575
}
7676

@@ -81,33 +81,35 @@ extension Container.Inner {
8181
obj.bar = 5 // expected-error {{'bar' is inaccessible due to 'private' protection level}}
8282
obj.privateExtensionMethod() // expected-error {{'privateExtensionMethod' is inaccessible due to 'private' protection level}}
8383

84-
_ = PrivateInner() // FIXME expected-error {{use of unresolved identifier 'PrivateInner'}}
84+
// FIXME: Unqualified lookup won't look into Container from here.
85+
_ = PrivateInner() // expected-error {{use of unresolved identifier 'PrivateInner'}}
8586
_ = Container.PrivateInner() // expected-error {{'PrivateInner' is inaccessible due to 'private' protection level}}
8687
}
8788

8889
// FIXME: Why do these errors happen twice?
89-
var inner: PrivateInner? { return nil } // FIXME expected-error 2 {{use of undeclared type 'PrivateInner'}}
90+
// FIXME: Unqualified lookup won't look into Container from here.
91+
var inner: PrivateInner? { return nil } // expected-error 2 {{use of undeclared type 'PrivateInner'}}
9092
var innerQualified: Container.PrivateInner? { return nil } // expected-error 2 {{'PrivateInner' is inaccessible due to 'private' protection level}}
9193
}
9294

9395
class Sub : Container {
9496
func subTest() {
95-
foo() // FIXME expected-error {{use of unresolved identifier 'foo'}}
97+
foo() // expected-error {{'foo' is inaccessible due to 'private' protection level}}
9698
self.foo() // expected-error {{'foo' is inaccessible due to 'private' protection level}}
9799

98-
_ = bar // FIXME expected-error {{use of unresolved identifier 'bar'}}
99-
bar = 5 // FIXME expected-error {{use of unresolved identifier 'bar'}}
100+
_ = bar // expected-error {{'bar' is inaccessible due to 'private' protection level}}
101+
bar = 5 // expected-error {{'bar' is inaccessible due to 'private' protection level}}
100102
_ = self.bar // expected-error {{'bar' is inaccessible due to 'private' protection level}}
101103
self.bar = 5 // expected-error {{'bar' is inaccessible due to 'private' protection level}}
102104

103-
privateExtensionMethod() // FIXME expected-error {{use of unresolved identifier 'privateExtensionMethod'}}
105+
privateExtensionMethod() // expected-error {{'privateExtensionMethod' is inaccessible due to 'private' protection level}}
104106
self.privateExtensionMethod() // expected-error {{'privateExtensionMethod' is inaccessible due to 'private' protection level}}
105107

106-
_ = PrivateInner() // FIXME expected-error {{use of unresolved identifier 'PrivateInner'}}
108+
_ = PrivateInner() // expected-error {{'PrivateInner' is inaccessible due to 'private' protection level}}
107109
_ = Container.PrivateInner() // expected-error {{'PrivateInner' is inaccessible due to 'private' protection level}}
108110
}
109111

110-
var subInner: PrivateInner? // FIXME expected-error {{use of undeclared type 'PrivateInner'}}
112+
var subInner: PrivateInner? // expected-error {{'PrivateInner' is inaccessible due to 'private' protection level}}
111113
var subInnerQualified: Container.PrivateInner? // expected-error {{'PrivateInner' is inaccessible due to 'private' protection level}}
112114
}
113115

@@ -154,9 +156,9 @@ extension Container {
154156
}
155157
extension Container {
156158
func test() {
157-
let a: ExtensionConflictingType? = nil // FIXME expected-error {{use of undeclared type 'ExtensionConflictingType'}}
159+
let a: ExtensionConflictingType? = nil // expected-error {{'ExtensionConflictingType' is inaccessible due to 'private' protection level}}
158160
let b: Container.ExtensionConflictingType? = nil // expected-error {{'ExtensionConflictingType' is inaccessible due to 'private' protection level}}
159-
_ = ExtensionConflictingType() // FIXME expected-error {{use of unresolved identifier 'ExtensionConflictingType'}}
161+
_ = ExtensionConflictingType() // expected-error {{'ExtensionConflictingType' is inaccessible due to 'private' protection level}}
160162
_ = Container.ExtensionConflictingType() // expected-error {{'ExtensionConflictingType' is inaccessible due to 'private' protection level}}
161163
}
162164
}

0 commit comments

Comments
 (0)