Skip to content

Commit b26ddb8

Browse files
committed
Point at local similarly named element and tweak references to variants
Point at the span for the definition of ADTs internal to the current crate. Look at the leading char of the ident to determine whether we're expecting a likely fn or any of a fn, a tuple struct or a tuple variant. Turn fn `add_typo_suggestion` into a `Resolver` method.
1 parent 0f677c6 commit b26ddb8

File tree

132 files changed

+600
-331
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

132 files changed

+600
-331
lines changed

src/librustc_resolve/build_reduced_graph.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -850,12 +850,14 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
850850
Res::Def(kind @ DefKind::Mod, def_id)
851851
| Res::Def(kind @ DefKind::Enum, def_id)
852852
| Res::Def(kind @ DefKind::Trait, def_id) => {
853-
let module = self.r.new_module(parent,
854-
ModuleKind::Def(kind, def_id, ident.name),
855-
def_id,
856-
expansion,
857-
span);
858-
self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
853+
let module = self.r.new_module(
854+
parent,
855+
ModuleKind::Def(kind, def_id, ident.name),
856+
def_id,
857+
expansion,
858+
span,
859+
);
860+
self.r.define(parent, ident, TypeNS, (module, vis, span, expansion));
859861
}
860862
Res::Def(DefKind::Struct, _)
861863
| Res::Def(DefKind::Union, _)
@@ -868,17 +870,17 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
868870
| Res::Def(DefKind::AssocOpaqueTy, _)
869871
| Res::PrimTy(..)
870872
| Res::ToolMod =>
871-
self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion)),
873+
self.r.define(parent, ident, TypeNS, (res, vis, span, expansion)),
872874
Res::Def(DefKind::Fn, _)
873875
| Res::Def(DefKind::Method, _)
874876
| Res::Def(DefKind::Static, _)
875877
| Res::Def(DefKind::Const, _)
876878
| Res::Def(DefKind::AssocConst, _)
877879
| Res::Def(DefKind::Ctor(..), _) =>
878-
self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion)),
880+
self.r.define(parent, ident, ValueNS, (res, vis, span, expansion)),
879881
Res::Def(DefKind::Macro(..), _)
880882
| Res::NonMacroAttr(..) =>
881-
self.r.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion)),
883+
self.r.define(parent, ident, MacroNS, (res, vis, span, expansion)),
882884
Res::Def(DefKind::TyParam, _) | Res::Def(DefKind::ConstParam, _)
883885
| Res::Local(..) | Res::SelfTy(..) | Res::SelfCtor(..) | Res::Err =>
884886
bug!("unexpected resolution: {:?}", res)

src/librustc_resolve/diagnostics.rs

+28-16
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,6 @@ fn reduce_impl_span_to_impl_keyword(cm: &SourceMap, impl_span: Span) -> Span {
5858
impl_span
5959
}
6060

61-
crate fn add_typo_suggestion(
62-
err: &mut DiagnosticBuilder<'_>, suggestion: Option<TypoSuggestion>, span: Span
63-
) -> bool {
64-
if let Some(suggestion) = suggestion {
65-
let msg = format!(
66-
"{} {} with a similar name exists", suggestion.res.article(), suggestion.res.descr()
67-
);
68-
err.span_suggestion(
69-
span, &msg, suggestion.candidate.to_string(), Applicability::MaybeIncorrect
70-
);
71-
return true;
72-
}
73-
false
74-
}
75-
7661
impl<'a> Resolver<'a> {
7762
crate fn add_module_candidates(
7863
&mut self,
@@ -641,7 +626,7 @@ impl<'a> Resolver<'a> {
641626
let suggestion = self.early_lookup_typo_candidate(
642627
ScopeSet::Macro(macro_kind), parent_scope, ident, is_expected
643628
);
644-
add_typo_suggestion(err, suggestion, ident.span);
629+
self.add_typo_suggestion(err, suggestion, ident.span);
645630

646631
if macro_kind == MacroKind::Derive &&
647632
(ident.as_str() == "Send" || ident.as_str() == "Sync") {
@@ -652,6 +637,33 @@ impl<'a> Resolver<'a> {
652637
err.help("have you added the `#[macro_use]` on the module/import?");
653638
}
654639
}
640+
641+
crate fn add_typo_suggestion(
642+
&self,
643+
err: &mut DiagnosticBuilder<'_>,
644+
suggestion: Option<TypoSuggestion>,
645+
span: Span,
646+
) -> bool {
647+
if let Some(suggestion) = suggestion {
648+
let msg = format!(
649+
"{} {} with a similar name exists", suggestion.res.article(), suggestion.res.descr()
650+
);
651+
err.span_suggestion(
652+
span, &msg, suggestion.candidate.to_string(), Applicability::MaybeIncorrect
653+
);
654+
let def_span = suggestion.res.opt_def_id()
655+
.and_then(|def_id| self.definitions.opt_span(def_id));
656+
if let Some(span) = def_span {
657+
err.span_label(span, &format!(
658+
"similarly named {} `{}` defined here",
659+
suggestion.res.descr(),
660+
suggestion.candidate.as_str(),
661+
));
662+
}
663+
return true;
664+
}
665+
false
666+
}
655667
}
656668

657669
impl<'a, 'b> ImportResolver<'a, 'b> {

src/librustc_resolve/error_codes.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,7 @@ function:
974974
struct Foo { a: bool };
975975
976976
let f = Foo();
977-
// error: expected function, found `Foo`
977+
// error: expected function, tuple struct or tuple variant, found `Foo`
978978
// `Foo` is a struct name, but this expression uses it like a function name
979979
```
980980
@@ -992,7 +992,8 @@ yield this error:
992992
993993
```compile_fail,E0423
994994
println("");
995-
// error: expected function, found macro `println`
995+
// error: expected function, tuple struct or tuple variant,
996+
// found macro `println`
996997
// did you mean `println!(...)`? (notice the trailing `!`)
997998
```
998999
@@ -1592,7 +1593,7 @@ enum State {
15921593
15931594
fn print_on_failure(state: &State) {
15941595
match *state {
1595-
// error: expected unit struct/variant or constant, found tuple
1596+
// error: expected unit struct, unit variant or constant, found tuple
15961597
// variant `State::Failed`
15971598
State::Failed => println!("Failed"),
15981599
_ => ()

src/librustc_resolve/late.rs

+20-5
Original file line numberDiff line numberDiff line change
@@ -199,21 +199,36 @@ impl<'a> PathSource<'a> {
199199
}
200200

201201
fn descr_expected(self) -> &'static str {
202-
match self {
202+
match &self {
203203
PathSource::Type => "type",
204204
PathSource::Trait(_) => "trait",
205-
PathSource::Pat => "unit struct/variant or constant",
205+
PathSource::Pat => "unit struct, unit variant or constant",
206206
PathSource::Struct => "struct, variant or union type",
207-
PathSource::TupleStruct => "tuple struct/variant",
207+
PathSource::TupleStruct => "tuple struct or tuple variant",
208208
PathSource::TraitItem(ns) => match ns {
209209
TypeNS => "associated type",
210210
ValueNS => "method or associated constant",
211211
MacroNS => bug!("associated macro"),
212212
},
213-
PathSource::Expr(parent) => match parent.map(|p| &p.kind) {
213+
PathSource::Expr(parent) => match &parent.as_ref().map(|p| &p.kind) {
214214
// "function" here means "anything callable" rather than `DefKind::Fn`,
215215
// this is not precise but usually more helpful than just "value".
216-
Some(&ExprKind::Call(..)) => "function",
216+
Some(ExprKind::Call(call_expr, _)) => {
217+
match &call_expr.kind {
218+
ExprKind::Path(_, path) => {
219+
let mut msg = "function";
220+
if let Some(segment) = path.segments.iter().last() {
221+
if let Some(c) = segment.ident.to_string().chars().next() {
222+
if c.is_uppercase() {
223+
msg = "function, tuple struct or tuple variant";
224+
}
225+
}
226+
}
227+
msg
228+
}
229+
_ => "function"
230+
}
231+
}
217232
_ => "value",
218233
},
219234
}

src/librustc_resolve/late/diagnostics.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
22
use crate::{PathResult, PathSource, Segment};
33
use crate::path_names_to_string;
4-
use crate::diagnostics::{add_typo_suggestion, ImportSuggestion, TypoSuggestion};
4+
use crate::diagnostics::{ImportSuggestion, TypoSuggestion};
55
use crate::late::{LateResolutionVisitor, RibKind};
66

77
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
@@ -237,18 +237,19 @@ impl<'a> LateResolutionVisitor<'a, '_> {
237237
}
238238

239239
// Try Levenshtein algorithm.
240-
let levenshtein_worked = add_typo_suggestion(
241-
&mut err, self.lookup_typo_candidate(path, ns, is_expected, span), ident_span
242-
);
240+
let typo_sugg = self.lookup_typo_candidate(path, ns, is_expected, span);
241+
let levenshtein_worked = self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span);
243242

244243
// Try context-dependent help if relaxed lookup didn't work.
245244
if let Some(res) = res {
246-
if self.smart_resolve_context_dependent_help(&mut err,
247-
span,
248-
source,
249-
res,
250-
&path_str,
251-
&fallback_label) {
245+
if self.smart_resolve_context_dependent_help(
246+
&mut err,
247+
span,
248+
source,
249+
res,
250+
&path_str,
251+
&fallback_label,
252+
) {
252253
return (err, candidates);
253254
}
254255
}

src/librustc_typeck/check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2269,7 +2269,7 @@ pub fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, vs: &'tcx [hir::Variant], i
22692269

22702270
fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span, qpath: &QPath) {
22712271
span_err!(tcx.sess, span, E0533,
2272-
"expected unit struct/variant or constant, found {} `{}`",
2272+
"expected unit struct, unit variant or constant, found {} `{}`",
22732273
res.descr(),
22742274
hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
22752275
}

src/librustc_typeck/check/pat.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -613,9 +613,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
613613
}
614614
};
615615
let report_unexpected_res = |res: Res| {
616-
let msg = format!("expected tuple struct/variant, found {} `{}`",
617-
res.descr(),
618-
hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
616+
let msg = format!(
617+
"expected tuple struct or tuple variant, found {} `{}`",
618+
res.descr(),
619+
hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)),
620+
);
619621
let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg);
620622
match (res, &pat.kind) {
621623
(Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::Method, _), _) => {

src/librustc_typeck/error_codes.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -4346,11 +4346,12 @@ enum X {
43464346
Entry,
43474347
}
43484348
4349-
X::Entry(); // error: expected function, found `X::Entry`
4349+
X::Entry(); // error: expected function, tuple struct or tuple variant,
4350+
// found `X::Entry`
43504351
43514352
// Or even simpler:
43524353
let x = 0i32;
4353-
x(); // error: expected function, found `i32`
4354+
x(); // error: expected function, tuple struct or tuple variant, found `i32`
43544355
```
43554356
43564357
Only functions and methods can be called using `()`. Example:

src/test/ui/associated-types/associated-types-eq-1.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
error[E0412]: cannot find type `A` in this scope
22
--> $DIR/associated-types-eq-1.rs:10:12
33
|
4+
LL | fn foo2<I: Foo>(x: I) {
5+
| - similarly named type parameter `I` defined here
46
LL | let _: A = x.boo();
57
| ^ help: a type parameter with a similar name exists: `I`
68

src/test/ui/class-missing-self.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ impl Cat {
77
fn meow(&self) {
88
println!("Meow");
99
meows += 1; //~ ERROR cannot find value `meows` in this scope
10-
sleep(); //~ ERROR cannot find function `sleep` in this scope
10+
sleep(); //~ ERROR cannot find function `sleep` in this
1111
}
1212

1313
}

src/test/ui/const-generics/struct-with-invalid-const-param.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error[E0573]: expected type, found const parameter `C`
22
--> $DIR/struct-with-invalid-const-param.rs:4:23
33
|
44
LL | struct S<const C: u8>(C);
5-
| ^ help: a struct with a similar name exists: `S`
5+
| ----------------------^--
6+
| | |
7+
| | help: a struct with a similar name exists: `S`
8+
| similarly named struct `S` defined here
69

710
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
811
--> $DIR/struct-with-invalid-const-param.rs:1:12

src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,21 @@ enum ManyVariants {
1616
}
1717

1818
fn result_test() {
19-
let x = Option(1); //~ ERROR expected function, found enum
19+
let x = Option(1); //~ ERROR expected function, tuple struct or tuple variant, found enum
2020

21-
if let Option(_) = x { //~ ERROR expected tuple struct/variant, found enum
21+
if let Option(_) = x { //~ ERROR expected tuple struct or tuple variant, found enum
2222
println!("It is OK.");
2323
}
2424

2525
let y = Example::Ex(String::from("test"));
2626

27-
if let Example(_) = y { //~ ERROR expected tuple struct/variant, found enum
27+
if let Example(_) = y { //~ ERROR expected tuple struct or tuple variant, found enum
2828
println!("It is OK.");
2929
}
3030

31-
let y = Void(); //~ ERROR expected function, found enum
31+
let y = Void(); //~ ERROR expected function, tuple struct or tuple variant, found enum
3232

33-
let z = ManyVariants(); //~ ERROR expected function, found enum
33+
let z = ManyVariants(); //~ ERROR expected function, tuple struct or tuple variant, found enum
3434
}
3535

3636
fn main() {}

src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0423]: expected function, found enum `Option`
1+
error[E0423]: expected function, tuple struct or tuple variant, found enum `Option`
22
--> $DIR/issue-43871-enum-instead-of-variant.rs:19:13
33
|
44
LL | let x = Option(1);
@@ -11,7 +11,7 @@ LL | let x = std::option::Option::None(1);
1111
LL | let x = std::option::Option::Some(1);
1212
| ^^^^^^^^^^^^^^^^^^^^^^^^^
1313

14-
error[E0532]: expected tuple struct/variant, found enum `Option`
14+
error[E0532]: expected tuple struct or tuple variant, found enum `Option`
1515
--> $DIR/issue-43871-enum-instead-of-variant.rs:21:12
1616
|
1717
LL | if let Option(_) = x {
@@ -24,7 +24,7 @@ LL | if let std::option::Option::None(_) = x {
2424
LL | if let std::option::Option::Some(_) = x {
2525
| ^^^^^^^^^^^^^^^^^^^^^^^^^
2626

27-
error[E0532]: expected tuple struct/variant, found enum `Example`
27+
error[E0532]: expected tuple struct or tuple variant, found enum `Example`
2828
--> $DIR/issue-43871-enum-instead-of-variant.rs:27:12
2929
|
3030
LL | if let Example(_) = y {
@@ -37,13 +37,13 @@ LL | if let Example::Ex(_) = y {
3737
LL | if let Example::NotEx(_) = y {
3838
| ^^^^^^^^^^^^^^
3939

40-
error[E0423]: expected function, found enum `Void`
40+
error[E0423]: expected function, tuple struct or tuple variant, found enum `Void`
4141
--> $DIR/issue-43871-enum-instead-of-variant.rs:31:13
4242
|
4343
LL | let y = Void();
4444
| ^^^^
4545

46-
error[E0423]: expected function, found enum `ManyVariants`
46+
error[E0423]: expected function, tuple struct or tuple variant, found enum `ManyVariants`
4747
--> $DIR/issue-43871-enum-instead-of-variant.rs:33:13
4848
|
4949
LL | let z = ManyVariants();

src/test/ui/empty/empty-struct-braces-expr.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ enum E {
1313

1414
fn main() {
1515
let e1 = Empty1; //~ ERROR expected value, found struct `Empty1`
16-
let e1 = Empty1(); //~ ERROR expected function, found struct `Empty1`
16+
let e1 = Empty1();
17+
//~^ ERROR expected function, tuple struct or tuple variant, found struct `Empty1`
1718
let e3 = E::Empty3; //~ ERROR expected value, found struct variant `E::Empty3`
18-
let e3 = E::Empty3(); //~ ERROR expected function, found struct variant `E::Empty3`
19+
let e3 = E::Empty3();
20+
//~^ ERROR expected function, tuple struct or tuple variant, found struct variant `E::Empty3`
1921

2022
let xe1 = XEmpty1; //~ ERROR expected value, found struct `XEmpty1`
21-
let xe1 = XEmpty1(); //~ ERROR expected function, found struct `XEmpty1`
23+
let xe1 = XEmpty1();
24+
//~^ ERROR expected function, tuple struct or tuple variant, found struct `XEmpty1`
2225
let xe3 = XE::Empty3; //~ ERROR no variant or associated item named `Empty3` found for type
2326
let xe3 = XE::Empty3(); //~ ERROR no variant or associated item named `Empty3` found for type
2427

0 commit comments

Comments
 (0)