Skip to content

Commit 27bb586

Browse files
committed
Improve expression diagnostics for incorrect module selectors
1 parent 385f4b2 commit 27bb586

File tree

3 files changed

+72
-13
lines changed

3 files changed

+72
-13
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,8 +1161,14 @@ ERROR(cannot_find_type_in_scope_did_you_mean,none,
11611161
"cannot find type %0 in scope; did you mean to use '%1'?", (DeclNameRef, StringRef))
11621162
ERROR(type_not_in_module,none,
11631163
"type %0 is not imported through module %1", (DeclName, Identifier))
1164+
ERROR(decl_not_in_module,none,
1165+
"declaration %0 is not imported through module %1", (DeclName, Identifier))
11641166
NOTE(note_change_module_selector,none,
11651167
"did you mean module %0?", (Identifier))
1168+
NOTE(note_remove_module_selector,none,
1169+
"did you mean the local declaration?", ())
1170+
NOTE(note_add_explicit_self_with_module_selector,none,
1171+
"did you mean the member of 'self'?", ())
11661172
NOTE(note_typo_candidate_implicit_member,none,
11671173
"did you mean the implicitly-synthesized %kindbase0?", (const ValueDecl *))
11681174
NOTE(note_remapped_type,none,

lib/Sema/PreCheckTarget.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,52 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
637637
return errorResult();
638638
}
639639

640+
// Is there an incorrect module selector?
641+
if (Name.hasModuleSelector()) {
642+
auto anyModuleName = DeclNameRef(LookupName.getFullName());
643+
auto anyModuleResults = TypeChecker::lookupUnqualified(DC, anyModuleName,
644+
Loc,
645+
lookupOptions);
646+
if (!anyModuleResults.empty()) {
647+
Context.Diags.diagnose(UDRE->getNameLoc(), diag::decl_not_in_module,
648+
LookupName.getFullName(),
649+
LookupName.getModuleSelector());
650+
651+
SourceLoc moduleSelectorLoc = UDRE->getNameLoc().getModuleSelectorLoc();
652+
653+
for (auto result : anyModuleResults) {
654+
ValueDecl * decl = result.getValueDecl();
655+
Identifier moduleName = decl->getModuleContext()->getName();
656+
657+
if (moduleName != Name.getModuleSelector()) {
658+
SmallString<64> replacement;
659+
if (decl->isInstanceMember())
660+
replacement += "self.";
661+
replacement += moduleName.str();
662+
663+
Context.Diags.diagnose(moduleSelectorLoc,
664+
diag::note_change_module_selector,
665+
moduleName)
666+
.fixItReplace(moduleSelectorLoc, replacement);
667+
} else {
668+
// It's just something we need to pick up contextually.
669+
if (decl->getDeclContext()->getLocalContext())
670+
decl->diagnose(diag::note_remove_module_selector)
671+
.fixItRemoveChars(moduleSelectorLoc,
672+
UDRE->getNameLoc().getBaseNameLoc());
673+
674+
if (decl->isInstanceMember())
675+
Context.Diags.diagnose(moduleSelectorLoc,
676+
diag::note_add_explicit_self_with_module_selector)
677+
.fixItInsert(moduleSelectorLoc, "self.");
678+
}
679+
}
680+
681+
// FIXME: Can we recover by assuming the first/best result is correct?
682+
return new (Context) ErrorExpr(UDRE->getSourceRange());
683+
}
684+
}
685+
640686
// Try ignoring access control.
641687
NameLookupOptions relookupOptions = lookupOptions;
642688
relookupOptions |= NameLookupFlags::IgnoreAccessControl;

test/NameLookup/module_selector.swift

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,15 +93,18 @@ extension B: main::Equatable {
9393
// FIXME incorrect: expected-error@-3 {{variable used within its own initial value}}
9494

9595
if main::Bool.main::random() {
96-
// FIXME improve: expected-error@-1 {{use of unresolved identifier 'main::Bool'}}
96+
// expected-error@-1 {{declaration 'Bool' is not imported through module 'main'}}
97+
// expected-note@-2 {{did you mean module 'Swift'?}} {{8-12=Swift}}
9798

9899
main::negate()
99-
// FIXME improve, suggest adding 'self.': expected-error@-1 {{use of unresolved identifier 'main::negate'}}
100+
// expected-error@-1 {{declaration 'negate' is not imported through module 'main'}}
101+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{7-11=self.ModuleSelectorTestingKit}}
100102
}
101103
else {
102104
self = main::B(value: .main::min)
103-
// FIXME improve: expected-error@-1 {{use of unresolved identifier 'main::B'}}
104-
// expected-error@-2 {{cannot infer contextual base in reference to member 'main::min'}}
105+
// expected-error@-1 {{declaration 'B' is not imported through module 'main'}}
106+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{14-18=ModuleSelectorTestingKit}}
107+
// expected-error@-3 {{cannot infer contextual base in reference to member 'main::min'}}
105108
}
106109

107110
self.main::myNegate()
@@ -152,10 +155,12 @@ extension ModuleSelectorTestingKit::C: ModuleSelectorTestingKit::Equatable {
152155
// FIXME incorrect: expected-error@-3 {{variable used within its own initial value}}
153156

154157
if ModuleSelectorTestingKit::Bool.ModuleSelectorTestingKit::random() {
155-
// FIXME improve: expected-error@-1 {{use of unresolved identifier 'ModuleSelectorTestingKit::Bool'}}
158+
// expected-error@-1 {{declaration 'Bool' is not imported through module 'ModuleSelectorTestingKit'}}
159+
// expected-note@-2 {{did you mean module 'Swift'?}} {{8-31=Swift}}
156160

157161
ModuleSelectorTestingKit::negate()
158-
// FIXME improve, suggest adding 'self.': expected-error@-1 {{use of unresolved identifier 'ModuleSelectorTestingKit::negate'}}
162+
// expected-error@-1 {{declaration 'negate' is not imported through module 'ModuleSelectorTestingKit'}}
163+
// expected-note@-2 {{did you mean the member of 'self'?}} {{7-7=self.}}
159164
}
160165
else {
161166
self = ModuleSelectorTestingKit::C(value: .ModuleSelectorTestingKit::min)
@@ -205,12 +210,14 @@ extension D: @retroactive Swift::Equatable {
205210
// FIXME: expected-error@-2 {{variable used within its own initial value}}
206211
if Swift::Bool.Swift::random() {
207212
Swift::negate()
208-
// FIXME improve: expected-error@-1 {{use of unresolved identifier 'Swift::negate'}}
213+
// expected-error@-1 {{declaration 'negate' is not imported through module 'Swift'}}
214+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{7-12=self.ModuleSelectorTestingKit}}
209215
}
210216
else {
211217
self = Swift::D(value: .Swift::min)
212-
// FIXME improve: expected-error@-1 {{use of unresolved identifier 'Swift::D'}}
213-
// expected-error@-2 {{cannot infer contextual base in reference to member 'Swift::min'}}
218+
// expected-error@-1 {{declaration 'D' is not imported through module 'Swift'}}
219+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{14-19=ModuleSelectorTestingKit}}
220+
// expected-error@-3 {{cannot infer contextual base in reference to member 'Swift::min'}}
214221
}
215222

216223
self.Swift::myNegate()
@@ -315,10 +322,10 @@ func main::decl1(
315322
// expected-error@-2 {{name of constant declaration cannot be qualified with module selector}}
316323

317324
// From uses in the switch statements below:
318-
// expected-note@-5 3{{did you mean 'decl1g'?}}
325+
// expected-note@-5 3{{did you mean the local declaration?}}
319326

320327
switch Optional(main::decl1g) {
321-
// expected-error@-1 {{use of unresolved identifier 'main::decl1g'}}
328+
// expected-error@-1 {{declaration 'decl1g' is not imported through module 'main'}}
322329
case Optional.some(let main::decl1i):
323330
// expected-error@-1 {{name of constant declaration cannot be qualified with module selector}}
324331
break
@@ -327,7 +334,7 @@ func main::decl1(
327334
}
328335

329336
switch Optional(main::decl1g) {
330-
// expected-error@-1 {{use of unresolved identifier 'main::decl1g'}}
337+
// expected-error@-1 {{declaration 'decl1g' is not imported through module 'main'}}
331338
case let Optional.some(main::decl1j):
332339
// expected-error@-1 {{name of constant declaration cannot be qualified with module selector}}
333340
break
@@ -336,7 +343,7 @@ func main::decl1(
336343
}
337344

338345
switch Optional(main::decl1g) {
339-
// expected-error@-1 {{use of unresolved identifier 'main::decl1g'}}
346+
// expected-error@-1 {{declaration 'decl1g' is not imported through module 'main'}}
340347
case let main::decl1k?:
341348
// expected-error@-1 {{name of constant declaration cannot be qualified with module selector}}
342349
break

0 commit comments

Comments
 (0)