Skip to content

Commit 864ba8b

Browse files
committed
Improve expression diagnostics for incorrect module selectors
1 parent 7de85ee commit 864ba8b

File tree

3 files changed

+70
-13
lines changed

3 files changed

+70
-13
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,8 +905,14 @@ ERROR(cannot_find_type_in_scope_did_you_mean,none,
905905
"cannot find type %0 in scope; did you mean to use '%1'?", (DeclNameRef, StringRef))
906906
ERROR(type_not_in_module,none,
907907
"type %0 is not imported through module %1", (DeclName, Identifier))
908+
ERROR(decl_not_in_module,none,
909+
"declaration %0 is not imported through module %1", (DeclName, Identifier))
908910
NOTE(note_change_module_selector,none,
909911
"did you mean module %0?", (Identifier))
912+
NOTE(note_remove_module_selector,none,
913+
"did you mean the local declaration?", ())
914+
NOTE(note_add_explicit_self_with_module_selector,none,
915+
"did you mean the member of 'self'?", ())
910916
NOTE(note_typo_candidate_implicit_member,none,
911917
"did you mean the implicitly-synthesized %1 '%0'?", (StringRef, StringRef))
912918
NOTE(note_remapped_type,none,

lib/Sema/PreCheckExpr.cpp

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
430430
auto &Context = DC->getASTContext();
431431

432432
// First, look for a local binding in scope.
433-
if (Loc.isValid() && !Name.isOperator()) {
433+
if (Loc.isValid() && !Name.isOperator() && !Name.hasModuleSelector()) {
434434
SmallVector<ValueDecl *, 2> localDecls;
435435
ASTScope::lookupLocalDecls(DC->getParentSourceFile(),
436436
LookupName.getFullName(), Loc,
@@ -494,6 +494,50 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
494494
return errorResult();
495495
}
496496

497+
// Is there an incorrect module selector?
498+
if (Name.hasModuleSelector()) {
499+
auto anyModuleName = DeclNameRef(Name.getFullName());
500+
auto anyModuleResults = TypeChecker::lookupUnqualified(DC, anyModuleName,
501+
Loc,
502+
lookupOptions);
503+
if (!anyModuleResults.empty()) {
504+
Context.Diags.diagnose(UDRE->getNameLoc(), diag::decl_not_in_module,
505+
Name.getFullName(), Name.getModuleSelector());
506+
507+
SourceLoc moduleSelectorLoc = UDRE->getNameLoc().getModuleSelectorLoc();
508+
509+
for (auto result : anyModuleResults) {
510+
ValueDecl * decl = result.getValueDecl();
511+
Identifier moduleName = decl->getModuleContext()->getName();
512+
513+
if (moduleName != Name.getModuleSelector()) {
514+
SmallString<64> replacement;
515+
if (decl->isInstanceMember())
516+
replacement += "self.";
517+
replacement += moduleName.str();
518+
519+
Context.Diags.diagnose(moduleSelectorLoc,
520+
diag::note_change_module_selector,
521+
moduleName)
522+
.fixItReplace(moduleSelectorLoc, replacement);
523+
} else {
524+
// It's just something we need to pick up contextually.
525+
if (decl->getDeclContext()->getLocalContext())
526+
decl->diagnose(diag::note_remove_module_selector)
527+
.fixItRemove(moduleSelectorLoc);
528+
529+
if (decl->isInstanceMember())
530+
Context.Diags.diagnose(moduleSelectorLoc,
531+
diag::note_add_explicit_self_with_module_selector)
532+
.fixItInsert(moduleSelectorLoc, "self.");
533+
}
534+
}
535+
536+
// FIXME: Can we recover by assuming the first/best result is correct?
537+
return new (Context) ErrorExpr(UDRE->getSourceRange());
538+
}
539+
}
540+
497541
// Try ignoring access control.
498542
NameLookupOptions relookupOptions = lookupOptions;
499543
relookupOptions |= NameLookupFlags::IgnoreAccessControl;

test/NameLookup/module_selector.swift

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,17 @@ extension B: main::Equatable {
9494
// FIXME incorrect: expected-error@-3 {{variable used within its own initial value}}
9595

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

99100
main::negate()
100-
// FIXME improve, suggest adding 'self.': expected-error@-1 {{use of unresolved identifier 'main::negate'}}
101+
// expected-error@-1 {{declaration 'negate' is not imported through module 'main'}}
102+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{7-11=self.ModuleSelectorTestingKit}}
101103
}
102104
else {
103105
self = main::B(value: .main::min)
104-
// FIXME improve: expected-error@-1 {{use of unresolved identifier 'main::B'}}
106+
// expected-error@-1 {{declaration 'B' is not imported through module 'main'}}
107+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{14-18=ModuleSelectorTestingKit}}
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)
@@ -176,7 +181,7 @@ extension Swift::D {}
176181
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{11-16=ModuleSelectorTestingKit}}
177182

178183
extension D: Swift::Equatable {
179-
// FIXME wat: expected-error@-1 2{{implementation of 'Equatable' cannot be automatically synthesized in an extension in a different file to the type}}
184+
// FIXME wat: expected-error@-1 {{implementation of 'Equatable' cannot be automatically synthesized in an extension in a different file to the type}}
180185

181186
@_implements(Swift::Equatable, Swift::==(_:_:))
182187
// expected-error@-1 {{name cannot be qualified with module selector here}} {{34-41=}}
@@ -205,11 +210,13 @@ extension D: 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: .ModuleSelectorTestingKit::min)
212-
// FIXME improve: expected-error@-1 {{use of unresolved identifier 'Swift::D'}}
218+
// expected-error@-1 {{declaration 'D' is not imported through module 'Swift'}}
219+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{14-19=ModuleSelectorTestingKit}}
213220
}
214221

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

316323
// From uses in the switch statements below:
317-
// expected-note@-5 3{{did you mean 'decl1g'?}}
324+
// expected-note@-5 3{{did you mean the local declaration?}}
318325

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

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

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

0 commit comments

Comments
 (0)