Skip to content

Commit 5af89a2

Browse files
committed
Improve module selector expr lookup diagnostics
1 parent d860c70 commit 5af89a2

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
@@ -1195,8 +1195,14 @@ ERROR(cannot_find_type_in_scope_did_you_mean,none,
11951195
"cannot find type %0 in scope; did you mean to use '%1'?", (DeclNameRef, StringRef))
11961196
ERROR(type_not_in_module,none,
11971197
"type %0 is not imported through module %1", (DeclName, Identifier))
1198+
ERROR(decl_not_in_module,none,
1199+
"declaration %0 is not imported through module %1", (DeclName, Identifier))
11981200
NOTE(note_change_module_selector,none,
11991201
"did you mean module %0?", (Identifier))
1202+
NOTE(note_remove_module_selector,none,
1203+
"did you mean the local declaration?", ())
1204+
NOTE(note_add_explicit_self_with_module_selector,none,
1205+
"did you mean the member of 'self'?", ())
12001206
NOTE(note_typo_candidate_implicit_member,none,
12011207
"did you mean the implicitly-synthesized %kindbase0?", (const ValueDecl *))
12021208
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
@@ -106,15 +106,18 @@ extension B: @retroactive main::Equatable {
106106
_ = (fn, magnitude)
107107

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

111112
main::negate()
112-
// FIXME improve: expected-error@-1 {{cannot find 'main::negate' in scope}}
113+
// expected-error@-1 {{declaration 'negate' is not imported through module 'main'}}
114+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{7-11=self.ModuleSelectorTestingKit}}
113115
}
114116
else {
115117
self = main::B(value: .main::min)
116-
// FIXME improve: expected-error@-1 {{cannot find 'main::B' in scope}}
117-
// expected-error@-2 {{cannot infer contextual base in reference to member 'main::min'}}
118+
// expected-error@-1 {{declaration 'B' is not imported through module 'main'}}
119+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{14-18=ModuleSelectorTestingKit}}
120+
// expected-error@-3 {{cannot infer contextual base in reference to member 'main::min'}}
118121

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

126129
main::fatalError()
127-
// FIXME improve: expected-error@-1 {{cannot find 'main::fatalError' in scope}}
130+
// expected-error@-1 {{declaration 'fatalError' is not imported through module 'main'}}
131+
// expected-note@-2 {{did you mean module 'Swift'?}} {{5-9=Swift}}
128132
}
129133

130134
// FIXME: Can we test @convention(witness_method:)?
@@ -172,10 +176,12 @@ extension C: @retroactive ModuleSelectorTestingKit::Equatable {
172176
_ = (fn, magnitude)
173177

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

177182
ModuleSelectorTestingKit::negate()
178-
// expected-error@-1 {{cannot find 'ModuleSelectorTestingKit::negate' in scope}}
183+
// expected-error@-1 {{declaration 'negate' is not imported through module 'ModuleSelectorTestingKit'}}
184+
// expected-note@-2 {{did you mean the member of 'self'?}} {{7-7=self.}}
179185
}
180186
else {
181187
self = ModuleSelectorTestingKit::C(value: .ModuleSelectorTestingKit::min)
@@ -188,7 +194,8 @@ extension C: @retroactive ModuleSelectorTestingKit::Equatable {
188194
// FIXME improve: expected-error@-1 {{value of type 'C' has no member 'ModuleSelectorTestingKit::myNegate'}}
189195

190196
ModuleSelectorTestingKit::fatalError()
191-
// FIXME improve: expected-error@-1 {{cannot find 'ModuleSelectorTestingKit::fatalError' in scope}}
197+
// expected-error@-1 {{declaration 'fatalError' is not imported through module 'ModuleSelectorTestingKit'}}
198+
// expected-note@-2 {{did you mean module 'Swift'?}} {{5-29=Swift}}
192199
}
193200

194201
// FIXME: Can we test @convention(witness_method:)?
@@ -218,24 +225,28 @@ extension D: @retroactive Swift::Equatable {
218225
// FIXME improve: expected-error@-1 {{replaced function 'Swift::negate()' could not be found}}
219226

220227
mutating func myNegate() {
228+
// expected-note@-1 {{did you mean 'myNegate'?}}
221229

222230
let fn: (Swift::Int, Swift::Int) -> Swift::Int =
223231
(Swift::+)
224232

225233
let magnitude: Int.Swift::Magnitude = Swift::magnitude
226-
// expected-error@-1 {{cannot find 'Swift::magnitude' in scope}}
234+
// expected-error@-1 {{declaration 'magnitude' is not imported through module 'Swift'}}
235+
// expected-note@-2 {{did you mean module 'main'?}} {{43-48=main}}
227236

228237
_ = (fn, magnitude)
229238

230239
if Swift::Bool.Swift::random() {
231240

232241
Swift::negate()
233-
// FIXME improve: expected-error@-1 {{cannot find 'Swift::negate' in scope}}
242+
// expected-error@-1 {{declaration 'negate' is not imported through module 'Swift'}}
243+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{7-12=self.ModuleSelectorTestingKit}}
234244
}
235245
else {
236246
self = Swift::D(value: .Swift::min)
237-
// FIXME improve: expected-error@-1 {{cannot find 'Swift::D' in scope}}
238-
// expected-error@-2 {{cannot infer contextual base in reference to member 'Swift::min'}}
247+
// expected-error@-1 {{declaration 'D' is not imported through module 'Swift'}}
248+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{14-19=ModuleSelectorTestingKit}}
249+
// expected-error@-3 {{cannot infer contextual base in reference to member 'Swift::min'}}
239250

240251
self = D.Swift::init(value: .min)
241252
// FIXME improve: expected-error@-1 {{'D' cannot be constructed because it has no accessible initializers}}
@@ -255,7 +266,8 @@ let mog: Never = fatalError()
255266

256267
func localVarsCantBeAccessedByModuleSelector() {
257268
let mag: Int.Swift::Magnitude = main::mag
258-
// expected-error@-1 {{cannot find 'main::mag' in scope}}
269+
// expected-error@-1 {{declaration 'mag' is not imported through module 'main'}}
270+
// expected-note@-2 {{did you mean the local declaration?}} {{35-41=}}
259271

260272
let mog: Never = main::mog
261273
}
@@ -291,26 +303,27 @@ func decl1(
291303
// expected-error@-1 {{type 'A' is not imported through module 'main'}}
292304
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{7-11=ModuleSelectorTestingKit}}
293305
label p2: inout A,
306+
// From uses in the switch statements below: expected-note@-1 3 {{did you mean the local declaration?}}
294307
label p3: @escaping () -> A
295308
) {
296309
switch Optional(main::p2) {
297-
// expected-error@-1 {{cannot find 'main::p2' in scope}}
310+
// expected-error@-1 {{declaration 'p2' is not imported through module 'main'}}
298311
case Optional.some(let decl1i):
299312
break
300313
case .none:
301314
break
302315
}
303316

304317
switch Optional(main::p2) {
305-
// expected-error@-1 {{cannot find 'main::p2' in scope}}
318+
// expected-error@-1 {{declaration 'p2' is not imported through module 'main'}}
306319
case let Optional.some(decl1j):
307320
break
308321
case .none:
309322
break
310323
}
311324

312325
switch Optional(main::p2) {
313-
// expected-error@-1 {{cannot find 'main::p2' in scope}}
326+
// expected-error@-1 {{declaration 'p2' is not imported through module 'main'}}
314327
case let decl1k?:
315328
break
316329
case .none:
@@ -324,7 +337,9 @@ typealias decl5 = main::Bool
324337

325338
func badModuleNames() {
326339
NonexistentModule::print()
327-
// expected-error@-1 {{cannot find 'NonexistentModule::print' in scope}}
340+
// expected-error@-1 {{declaration 'print' is not imported through module 'NonexistentModule'}}
341+
// expected-note@-2 {{did you mean module 'Swift'?}} {{3-20=Swift}}
342+
// FIXME redundant: expected-note@-3 {{did you mean module 'Swift'?}}
328343

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

0 commit comments

Comments
 (0)