Skip to content

Commit 8b5c217

Browse files
committed
Improve module selector expr lookup diagnostics
1 parent 82d21ef commit 8b5c217

File tree

3 files changed

+84
-17
lines changed

3 files changed

+84
-17
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
@@ -635,6 +635,52 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
635635
return errorResult();
636636
}
637637

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

test/NameLookup/module_selector.swift

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,18 @@ extension B: @retroactive main::Equatable {
109109
_ = (fn, magnitude)
110110

111111
if main::Bool.main::random() {
112-
// FIXME improve: expected-error@-1 {{cannot find 'main::Bool' in scope}}
112+
// expected-error@-1 {{declaration 'Bool' is not imported through module 'main'}}
113+
// expected-note@-2 {{did you mean module 'Swift'?}} {{8-12=Swift}}
113114

114115
main::negate()
115-
// FIXME improve: expected-error@-1 {{cannot find 'main::negate' in scope}}
116+
// expected-error@-1 {{declaration 'negate' is not imported through module 'main'}}
117+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{7-11=self.ModuleSelectorTestingKit}}
116118
}
117119
else {
118120
self = main::B(value: .main::min)
119-
// FIXME improve: expected-error@-1 {{cannot find 'main::B' in scope}}
120-
// expected-error@-2 {{cannot infer contextual base in reference to member 'main::min'}}
121+
// expected-error@-1 {{declaration 'B' is not imported through module 'main'}}
122+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{14-18=ModuleSelectorTestingKit}}
123+
// expected-error@-3 {{cannot infer contextual base in reference to member 'main::min'}}
121124

122125
self = B.main::init(value: .min)
123126
// FIXME improve: expected-error@-1 {{'B' cannot be constructed because it has no accessible initializers}}
@@ -127,7 +130,8 @@ extension B: @retroactive main::Equatable {
127130
self.main::myNegate()
128131

129132
main::fatalError()
130-
// FIXME improve: expected-error@-1 {{cannot find 'main::fatalError' in scope}}
133+
// expected-error@-1 {{declaration 'fatalError' is not imported through module 'main'}}
134+
// expected-note@-2 {{did you mean module 'Swift'?}} {{5-9=Swift}}
131135
}
132136

133137
// FIXME: Can we test @convention(witness_method:)?
@@ -176,10 +180,12 @@ extension C: @retroactive ModuleSelectorTestingKit::Equatable {
176180
_ = (fn, magnitude)
177181

178182
if ModuleSelectorTestingKit::Bool.ModuleSelectorTestingKit::random() {
179-
// FIXME improve: expected-error@-1 {{cannot find 'ModuleSelectorTestingKit::Bool' in scope}}
183+
// expected-error@-1 {{declaration 'Bool' is not imported through module 'ModuleSelectorTestingKit'}}
184+
// expected-note@-2 {{did you mean module 'Swift'?}} {{8-32=Swift}}
180185

181186
ModuleSelectorTestingKit::negate()
182-
// expected-error@-1 {{cannot find 'ModuleSelectorTestingKit::negate' in scope}}
187+
// expected-error@-1 {{declaration 'negate' is not imported through module 'ModuleSelectorTestingKit'}}
188+
// expected-note@-2 {{did you mean the member of 'self'?}} {{7-7=self.}}
183189
}
184190
else {
185191
self = ModuleSelectorTestingKit::C(value: .ModuleSelectorTestingKit::min)
@@ -192,7 +198,8 @@ extension C: @retroactive ModuleSelectorTestingKit::Equatable {
192198
// FIXME improve: expected-error@-1 {{value of type 'C' has no member 'ModuleSelectorTestingKit::myNegate'}}
193199

194200
ModuleSelectorTestingKit::fatalError()
195-
// FIXME improve: expected-error@-1 {{cannot find 'ModuleSelectorTestingKit::fatalError' in scope}}
201+
// expected-error@-1 {{declaration 'fatalError' is not imported through module 'ModuleSelectorTestingKit'}}
202+
// expected-note@-2 {{did you mean module 'Swift'?}} {{5-29=Swift}}
196203
}
197204

198205
// FIXME: Can we test @convention(witness_method:)?
@@ -224,24 +231,28 @@ extension D: @retroactive Swift::Equatable {
224231
// FIXME improve: expected-error@-1 {{replaced function 'Swift::negate()' could not be found}}
225232

226233
mutating func myNegate() {
234+
// expected-note@-1 {{did you mean 'myNegate'?}}
227235

228236
let fn: (Swift::Int, Swift::Int) -> Swift::Int =
229237
(Swift::+)
230238

231239
let magnitude: Int.Swift::Magnitude = Swift::magnitude
232-
// expected-error@-1 {{cannot find 'Swift::magnitude' in scope}}
240+
// expected-error@-1 {{declaration 'magnitude' is not imported through module 'Swift'}}
241+
// expected-note@-2 {{did you mean module 'main'?}} {{43-48=main}}
233242

234243
_ = (fn, magnitude)
235244

236245
if Swift::Bool.Swift::random() {
237246

238247
Swift::negate()
239-
// FIXME improve: expected-error@-1 {{cannot find 'Swift::negate' in scope}}
248+
// expected-error@-1 {{declaration 'negate' is not imported through module 'Swift'}}
249+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{7-12=self.ModuleSelectorTestingKit}}
240250
}
241251
else {
242252
self = Swift::D(value: .Swift::min)
243-
// FIXME improve: expected-error@-1 {{cannot find 'Swift::D' in scope}}
244-
// expected-error@-2 {{cannot infer contextual base in reference to member 'Swift::min'}}
253+
// expected-error@-1 {{declaration 'D' is not imported through module 'Swift'}}
254+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{14-19=ModuleSelectorTestingKit}}
255+
// expected-error@-3 {{cannot infer contextual base in reference to member 'Swift::min'}}
245256

246257
self = D.Swift::init(value: .min)
247258
// FIXME improve: expected-error@-1 {{'D' cannot be constructed because it has no accessible initializers}}
@@ -261,7 +272,8 @@ let mog: Never = fatalError()
261272

262273
func localVarsCantBeAccessedByModuleSelector() {
263274
let mag: Int.Swift::Magnitude = main::mag
264-
// expected-error@-1 {{cannot find 'main::mag' in scope}}
275+
// expected-error@-1 {{declaration 'mag' is not imported through module 'main'}}
276+
// expected-note@-2 {{did you mean the local declaration?}} {{35-41=}}
265277

266278
let mog: Never = main::mog
267279
}
@@ -346,9 +358,10 @@ func main::decl1(
346358
guard let (main::decl1g, main::decl1h) = Optional(("g", "h")) else { return }
347359
// expected-error@-1 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{14-20=}}
348360
// expected-error@-2 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-2 {{remove module selector from this name}} {{28-34=}}
361+
// From uses in the switch statements below: expected-note@-3 3 {{did you mean the local declaration?}}
349362

350363
switch Optional(main::decl1g) {
351-
// expected-error@-1 {{cannot find 'main::decl1g' in scope}}
364+
// expected-error@-1 {{declaration 'decl1g' is not imported through module 'main'}}
352365
case Optional.some(let main::decl1i):
353366
// expected-error@-1 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{26-32=}}
354367
break
@@ -357,7 +370,7 @@ func main::decl1(
357370
}
358371

359372
switch Optional(main::decl1g) {
360-
// expected-error@-1 {{cannot find 'main::decl1g' in scope}}
373+
// expected-error@-1 {{declaration 'decl1g' is not imported through module 'main'}}
361374
case let Optional.some(main::decl1j):
362375
// expected-error@-1 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{26-32=}}
363376
break
@@ -366,7 +379,7 @@ func main::decl1(
366379
}
367380

368381
switch Optional(main::decl1g) {
369-
// expected-error@-1 {{cannot find 'main::decl1g' in scope}}
382+
// expected-error@-1 {{declaration 'decl1g' is not imported through module 'main'}}
370383
case let main::decl1k?:
371384
// expected-error@-1 {{name in constant declaration cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{11-17=}}
372385
break
@@ -472,7 +485,9 @@ precedencegroup main::PG1 {
472485

473486
func badModuleNames() {
474487
NonexistentModule::print()
475-
// expected-error@-1 {{cannot find 'NonexistentModule::print' in scope}}
488+
// expected-error@-1 {{declaration 'print' is not imported through module 'NonexistentModule'}}
489+
// expected-note@-2 {{did you mean module 'Swift'?}} {{3-20=Swift}}
490+
// FIXME redundant: expected-note@-3 {{did you mean module 'Swift'?}}
476491

477492
_ = "foo".NonexistentModule::count
478493
// FIXME improve: expected-error@-1 {{value of type 'String' has no member 'NonexistentModule::count'}}

0 commit comments

Comments
 (0)