Skip to content

Commit 3bb5a86

Browse files
committed
Auto merge of #74005 - estebank:type-ascription-redux, r=petrochenkov
Clean up errors in typeck and resolve * Tweak ordering of suggestions * Do not suggest similarly named enclosing item * Point at item definition in foreign crates * Add missing primary label CC #34255.
2 parents 770bd3d + 54f1b43 commit 3bb5a86

26 files changed

+225
-146
lines changed

src/librustc_resolve/diagnostics.rs

+34-13
Original file line numberDiff line numberDiff line change
@@ -942,17 +942,6 @@ impl<'a> Resolver<'a> {
942942
Some(suggestion) if suggestion.candidate == kw::Underscore => return false,
943943
Some(suggestion) => suggestion,
944944
};
945-
let msg = format!(
946-
"{} {} with a similar name exists",
947-
suggestion.res.article(),
948-
suggestion.res.descr()
949-
);
950-
err.span_suggestion(
951-
span,
952-
&msg,
953-
suggestion.candidate.to_string(),
954-
Applicability::MaybeIncorrect,
955-
);
956945
let def_span = suggestion.res.opt_def_id().and_then(|def_id| match def_id.krate {
957946
LOCAL_CRATE => self.opt_span(def_id),
958947
_ => Some(
@@ -961,16 +950,48 @@ impl<'a> Resolver<'a> {
961950
.guess_head_span(self.cstore().get_span_untracked(def_id, self.session)),
962951
),
963952
});
964-
if let Some(span) = def_span {
953+
if let Some(def_span) = def_span {
954+
if span.overlaps(def_span) {
955+
// Don't suggest typo suggestion for itself like in the followoing:
956+
// error[E0423]: expected function, tuple struct or tuple variant, found struct `X`
957+
// --> $DIR/issue-64792-bad-unicode-ctor.rs:3:14
958+
// |
959+
// LL | struct X {}
960+
// | ----------- `X` defined here
961+
// LL |
962+
// LL | const Y: X = X("ö");
963+
// | -------------^^^^^^- similarly named constant `Y` defined here
964+
// |
965+
// help: use struct literal syntax instead
966+
// |
967+
// LL | const Y: X = X {};
968+
// | ^^^^
969+
// help: a constant with a similar name exists
970+
// |
971+
// LL | const Y: X = Y("ö");
972+
// | ^
973+
return false;
974+
}
965975
err.span_label(
966-
self.session.source_map().guess_head_span(span),
976+
self.session.source_map().guess_head_span(def_span),
967977
&format!(
968978
"similarly named {} `{}` defined here",
969979
suggestion.res.descr(),
970980
suggestion.candidate.as_str(),
971981
),
972982
);
973983
}
984+
let msg = format!(
985+
"{} {} with a similar name exists",
986+
suggestion.res.article(),
987+
suggestion.res.descr()
988+
);
989+
err.span_suggestion(
990+
span,
991+
&msg,
992+
suggestion.candidate.to_string(),
993+
Applicability::MaybeIncorrect,
994+
);
974995
true
975996
}
976997

src/librustc_resolve/late/diagnostics.rs

+31-11
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}
1212
use rustc_hir as hir;
1313
use rustc_hir::def::Namespace::{self, *};
1414
use rustc_hir::def::{self, CtorKind, DefKind};
15-
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
15+
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
1616
use rustc_hir::PrimTy;
1717
use rustc_session::config::nightly_options;
1818
use rustc_span::hygiene::MacroKind;
@@ -88,6 +88,18 @@ fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, Str
8888
}
8989

9090
impl<'a> LateResolutionVisitor<'a, '_, '_> {
91+
fn def_span(&self, def_id: DefId) -> Option<Span> {
92+
match def_id.krate {
93+
LOCAL_CRATE => self.r.opt_span(def_id),
94+
_ => Some(
95+
self.r
96+
.session
97+
.source_map()
98+
.guess_head_span(self.r.cstore().get_span_untracked(def_id, self.r.session)),
99+
),
100+
}
101+
}
102+
91103
/// Handles error reporting for `smart_resolve_path_fragment` function.
92104
/// Creates base error and amends it with one short label and possibly some longer helps/notes.
93105
pub(crate) fn smart_resolve_report_errors(
@@ -339,8 +351,6 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
339351

340352
// Try Levenshtein algorithm.
341353
let typo_sugg = self.lookup_typo_candidate(path, ns, is_expected, span);
342-
let levenshtein_worked = self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span);
343-
344354
// Try context-dependent help if relaxed lookup didn't work.
345355
if let Some(res) = res {
346356
if self.smart_resolve_context_dependent_help(
@@ -351,14 +361,18 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
351361
&path_str,
352362
&fallback_label,
353363
) {
364+
// We do this to avoid losing a secondary span when we override the main error span.
365+
self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span);
354366
return (err, candidates);
355367
}
356368
}
357369

358-
// Fallback label.
359-
if !levenshtein_worked {
370+
if !self.type_ascription_suggestion(&mut err, base_span)
371+
&& !self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span)
372+
{
373+
// Fallback label.
360374
err.span_label(base_span, fallback_label);
361-
self.type_ascription_suggestion(&mut err, base_span);
375+
362376
match self.diagnostic_metadata.current_let_binding {
363377
Some((pat_sp, Some(ty_sp), None)) if ty_sp.contains(base_span) && could_be_expr => {
364378
err.span_suggestion_short(
@@ -518,6 +532,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
518532
}),
519533
) if followed_by_brace => {
520534
if let Some(sp) = closing_brace {
535+
err.span_label(span, fallback_label);
521536
err.multipart_suggestion(
522537
"surround the struct literal with parentheses",
523538
vec![
@@ -550,7 +565,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
550565
}
551566
_ => span,
552567
};
553-
if let Some(span) = self.r.opt_span(def_id) {
568+
if let Some(span) = self.def_span(def_id) {
554569
err.span_label(span, &format!("`{}` defined here", path_str));
555570
}
556571
let (tail, descr, applicability) = match source {
@@ -581,12 +596,15 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
581596
applicability,
582597
);
583598
}
584-
_ => {}
599+
_ => {
600+
err.span_label(span, fallback_label);
601+
}
585602
}
586603
};
587604

588605
match (res, source) {
589606
(Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => {
607+
err.span_label(span, fallback_label);
590608
err.span_suggestion_verbose(
591609
span.shrink_to_hi(),
592610
"use `!` to invoke the macro",
@@ -602,7 +620,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
602620
if nightly_options::is_nightly_build() {
603621
let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \
604622
`type` alias";
605-
if let Some(span) = self.r.opt_span(def_id) {
623+
if let Some(span) = self.def_span(def_id) {
606624
err.span_help(span, msg);
607625
} else {
608626
err.help(msg);
@@ -680,7 +698,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
680698
bad_struct_syntax_suggestion(def_id);
681699
}
682700
(Res::Def(DefKind::Ctor(_, CtorKind::Fn), def_id), _) if ns == ValueNS => {
683-
if let Some(span) = self.r.opt_span(def_id) {
701+
if let Some(span) = self.def_span(def_id) {
684702
err.span_label(span, &format!("`{}` defined here", path_str));
685703
}
686704
err.span_label(span, format!("did you mean `{}( /* fields */ )`?", path_str));
@@ -869,7 +887,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
869887
start.to(sm.next_point(start))
870888
}
871889

872-
fn type_ascription_suggestion(&self, err: &mut DiagnosticBuilder<'_>, base_span: Span) {
890+
fn type_ascription_suggestion(&self, err: &mut DiagnosticBuilder<'_>, base_span: Span) -> bool {
873891
let sm = self.r.session.source_map();
874892
let base_snippet = sm.span_to_snippet(base_span);
875893
if let Some(&sp) = self.diagnostic_metadata.current_type_ascription.last() {
@@ -939,9 +957,11 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
939957
"expecting a type here because of type ascription",
940958
);
941959
}
960+
return show_label;
942961
}
943962
}
944963
}
964+
false
945965
}
946966

947967
fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> {

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

+1-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ 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-
| ----------------------^--
6-
| | |
7-
| | help: a struct with a similar name exists: `S`
8-
| similarly named struct `S` defined here
5+
| ^ not a type
96

107
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
118
--> $DIR/struct-with-invalid-const-param.rs:1:12

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

+29-15
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ LL | let e1 = Empty1;
1212
LL | pub struct XEmpty2;
1313
| ------------------- similarly named unit struct `XEmpty2` defined here
1414
|
15-
help: a unit struct with a similar name exists
16-
|
17-
LL | let e1 = XEmpty2;
18-
| ^^^^^^^
1915
help: use struct literal syntax instead
2016
|
2117
LL | let e1 = Empty1 {};
2218
| ^^^^^^^^^
19+
help: a unit struct with a similar name exists
20+
|
21+
LL | let e1 = XEmpty2;
22+
| ^^^^^^^
2323

2424
error[E0423]: expected function, tuple struct or tuple variant, found struct `Empty1`
2525
--> $DIR/empty-struct-braces-expr.rs:16:14
@@ -29,15 +29,20 @@ LL | struct Empty1 {}
2929
...
3030
LL | let e1 = Empty1();
3131
| ^^^^^^^^
32+
|
33+
::: $DIR/auxiliary/empty-struct.rs:2:1
3234
|
33-
help: a unit struct with a similar name exists
35+
LL | pub struct XEmpty2;
36+
| ------------------- similarly named unit struct `XEmpty2` defined here
3437
|
35-
LL | let e1 = XEmpty2();
36-
| ^^^^^^^
3738
help: use struct literal syntax instead
3839
|
3940
LL | let e1 = Empty1 {};
4041
| ^^^^^^^^^
42+
help: a unit struct with a similar name exists
43+
|
44+
LL | let e1 = XEmpty2();
45+
| ^^^^^^^
4146

4247
error[E0423]: expected value, found struct variant `E::Empty3`
4348
--> $DIR/empty-struct-braces-expr.rs:18:14
@@ -63,34 +68,43 @@ error[E0423]: expected value, found struct `XEmpty1`
6368
LL | let xe1 = XEmpty1;
6469
| ^^^^^^^
6570
|
66-
::: $DIR/auxiliary/empty-struct.rs:2:1
71+
::: $DIR/auxiliary/empty-struct.rs:1:1
6772
|
73+
LL | pub struct XEmpty1 {}
74+
| ------------------ `XEmpty1` defined here
6875
LL | pub struct XEmpty2;
6976
| ------------------- similarly named unit struct `XEmpty2` defined here
7077
|
71-
help: a unit struct with a similar name exists
72-
|
73-
LL | let xe1 = XEmpty2;
74-
| ^^^^^^^
7578
help: use struct literal syntax instead
7679
|
7780
LL | let xe1 = XEmpty1 {};
7881
| ^^^^^^^^^^
82+
help: a unit struct with a similar name exists
83+
|
84+
LL | let xe1 = XEmpty2;
85+
| ^^^^^^^
7986

8087
error[E0423]: expected function, tuple struct or tuple variant, found struct `XEmpty1`
8188
--> $DIR/empty-struct-braces-expr.rs:23:15
8289
|
8390
LL | let xe1 = XEmpty1();
8491
| ^^^^^^^^^
92+
|
93+
::: $DIR/auxiliary/empty-struct.rs:1:1
8594
|
86-
help: a unit struct with a similar name exists
95+
LL | pub struct XEmpty1 {}
96+
| ------------------ `XEmpty1` defined here
97+
LL | pub struct XEmpty2;
98+
| ------------------- similarly named unit struct `XEmpty2` defined here
8799
|
88-
LL | let xe1 = XEmpty2();
89-
| ^^^^^^^
90100
help: use struct literal syntax instead
91101
|
92102
LL | let xe1 = XEmpty1 {};
93103
| ^^^^^^^^^^
104+
help: a unit struct with a similar name exists
105+
|
106+
LL | let xe1 = XEmpty2();
107+
| ^^^^^^^
94108

95109
error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
96110
--> $DIR/empty-struct-braces-expr.rs:25:19

src/test/ui/empty/empty-struct-braces-pat-1.stderr

+7-5
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,21 @@ error[E0532]: expected unit struct, unit variant or constant, found struct varia
1313
LL | XE::XEmpty3 => ()
1414
| ^^^^^^^^^^^
1515
|
16-
::: $DIR/auxiliary/empty-struct.rs:7:5
16+
::: $DIR/auxiliary/empty-struct.rs:6:5
1717
|
18+
LL | XEmpty3 {},
19+
| ------- `XE::XEmpty3` defined here
1820
LL | XEmpty4,
1921
| ------- similarly named unit variant `XEmpty4` defined here
2022
|
21-
help: a unit variant with a similar name exists
22-
|
23-
LL | XE::XEmpty4 => ()
24-
| ^^^^^^^
2523
help: use struct pattern syntax instead
2624
|
2725
LL | XE::XEmpty3 { /* fields */ } => ()
2826
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27+
help: a unit variant with a similar name exists
28+
|
29+
LL | XE::XEmpty4 => ()
30+
| ^^^^^^^
2931

3032
error: aborting due to 2 previous errors
3133

0 commit comments

Comments
 (0)