From eef284be59bbbe50e4d5369542a80e1ccd2ba7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 9 Aug 2020 20:29:39 -0700 Subject: [PATCH] Tweak ordering of suggestions Modify logic to make it easier to follow and recover labels that would otherwise be lost. --- src/librustc_resolve/late/diagnostics.rs | 16 ++++--- .../ui/empty/empty-struct-braces-expr.stderr | 38 ++++++++++------ .../ui/empty/empty-struct-braces-pat-1.stderr | 8 ++-- .../ui/empty/empty-struct-braces-pat-2.stderr | 44 ++++++++++++++----- .../ui/empty/empty-struct-braces-pat-3.stderr | 22 +++++++--- src/test/ui/error-codes/E0423.stderr | 11 +++-- .../issue-64792-bad-unicode-ctor.stderr | 10 ++--- src/test/ui/namespace/namespace-mix.stderr | 16 +++---- src/test/ui/resolve/issue-39226.stderr | 8 ++-- src/test/ui/resolve/privacy-enum-ctor.stderr | 16 +++---- ...uggest-path-instead-of-mod-dot-item.stderr | 16 +++---- .../fn-or-tuple-struct-without-args.stderr | 8 ++-- .../type/type-ascription-with-fn-call.stderr | 5 +-- 13 files changed, 131 insertions(+), 87 deletions(-) diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index ec6dbb070df..1ea0a6ff218 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -339,8 +339,6 @@ pub(crate) fn smart_resolve_report_errors( // Try Levenshtein algorithm. let typo_sugg = self.lookup_typo_candidate(path, ns, is_expected, span); - let levenshtein_worked = self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span); - // Try context-dependent help if relaxed lookup didn't work. if let Some(res) = res { if self.smart_resolve_context_dependent_help( @@ -351,14 +349,18 @@ pub(crate) fn smart_resolve_report_errors( &path_str, &fallback_label, ) { + // We do this to avoid losing a secondary span when we override the main error span. + self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span); return (err, candidates); } } - // Fallback label. - if !levenshtein_worked { + if !self.type_ascription_suggestion(&mut err, base_span) + && !self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span) + { + // Fallback label. err.span_label(base_span, fallback_label); - self.type_ascription_suggestion(&mut err, base_span); + match self.diagnostic_metadata.current_let_binding { Some((pat_sp, Some(ty_sp), None)) if ty_sp.contains(base_span) && could_be_expr => { err.span_suggestion_short( @@ -869,7 +871,7 @@ fn get_colon_suggestion_span(&self, start: Span) -> Span { start.to(sm.next_point(start)) } - fn type_ascription_suggestion(&self, err: &mut DiagnosticBuilder<'_>, base_span: Span) { + fn type_ascription_suggestion(&self, err: &mut DiagnosticBuilder<'_>, base_span: Span) -> bool { let sm = self.r.session.source_map(); let base_snippet = sm.span_to_snippet(base_span); if let Some(&sp) = self.diagnostic_metadata.current_type_ascription.last() { @@ -939,9 +941,11 @@ fn type_ascription_suggestion(&self, err: &mut DiagnosticBuilder<'_>, base_span: "expecting a type here because of type ascription", ); } + return show_label; } } } + false } fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> { diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr index c0ba9716fb0..af783996f76 100644 --- a/src/test/ui/empty/empty-struct-braces-expr.stderr +++ b/src/test/ui/empty/empty-struct-braces-expr.stderr @@ -12,14 +12,14 @@ LL | let e1 = Empty1; LL | pub struct XEmpty2; | ------------------- similarly named unit struct `XEmpty2` defined here | -help: a unit struct with a similar name exists - | -LL | let e1 = XEmpty2; - | ^^^^^^^ help: use struct literal syntax instead | LL | let e1 = Empty1 {}; | ^^^^^^^^^ +help: a unit struct with a similar name exists + | +LL | let e1 = XEmpty2; + | ^^^^^^^ error[E0423]: expected function, tuple struct or tuple variant, found struct `Empty1` --> $DIR/empty-struct-braces-expr.rs:16:14 @@ -29,15 +29,20 @@ LL | struct Empty1 {} ... LL | let e1 = Empty1(); | ^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:2:1 | -help: a unit struct with a similar name exists +LL | pub struct XEmpty2; + | ------------------- similarly named unit struct `XEmpty2` defined here | -LL | let e1 = XEmpty2(); - | ^^^^^^^ help: use struct literal syntax instead | LL | let e1 = Empty1 {}; | ^^^^^^^^^ +help: a unit struct with a similar name exists + | +LL | let e1 = XEmpty2(); + | ^^^^^^^ error[E0423]: expected value, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-expr.rs:18:14 @@ -68,29 +73,34 @@ LL | let xe1 = XEmpty1; LL | pub struct XEmpty2; | ------------------- similarly named unit struct `XEmpty2` defined here | -help: a unit struct with a similar name exists - | -LL | let xe1 = XEmpty2; - | ^^^^^^^ help: use struct literal syntax instead | LL | let xe1 = XEmpty1 {}; | ^^^^^^^^^^ +help: a unit struct with a similar name exists + | +LL | let xe1 = XEmpty2; + | ^^^^^^^ error[E0423]: expected function, tuple struct or tuple variant, found struct `XEmpty1` --> $DIR/empty-struct-braces-expr.rs:23:15 | LL | let xe1 = XEmpty1(); | ^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:2:1 | -help: a unit struct with a similar name exists +LL | pub struct XEmpty2; + | ------------------- similarly named unit struct `XEmpty2` defined here | -LL | let xe1 = XEmpty2(); - | ^^^^^^^ help: use struct literal syntax instead | LL | let xe1 = XEmpty1 {}; | ^^^^^^^^^^ +help: a unit struct with a similar name exists + | +LL | let xe1 = XEmpty2(); + | ^^^^^^^ error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope --> $DIR/empty-struct-braces-expr.rs:25:19 diff --git a/src/test/ui/empty/empty-struct-braces-pat-1.stderr b/src/test/ui/empty/empty-struct-braces-pat-1.stderr index b027c82f7dd..70847ca45d0 100644 --- a/src/test/ui/empty/empty-struct-braces-pat-1.stderr +++ b/src/test/ui/empty/empty-struct-braces-pat-1.stderr @@ -18,14 +18,14 @@ LL | XE::XEmpty3 => () LL | XEmpty4, | ------- similarly named unit variant `XEmpty4` defined here | -help: a unit variant with a similar name exists - | -LL | XE::XEmpty4 => () - | ^^^^^^^ help: use struct pattern syntax instead | LL | XE::XEmpty3 { /* fields */ } => () | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: a unit variant with a similar name exists + | +LL | XE::XEmpty4 => () + | ^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/empty/empty-struct-braces-pat-2.stderr b/src/test/ui/empty/empty-struct-braces-pat-2.stderr index a53b88db7d1..19792bc9fc5 100644 --- a/src/test/ui/empty/empty-struct-braces-pat-2.stderr +++ b/src/test/ui/empty/empty-struct-braces-pat-2.stderr @@ -6,30 +6,40 @@ LL | struct Empty1 {} ... LL | Empty1() => () | ^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:3:1 | -help: a tuple struct with a similar name exists +LL | pub struct XEmpty6(); + | --------------------- similarly named tuple struct `XEmpty6` defined here | -LL | XEmpty6() => () - | ^^^^^^^ help: use struct pattern syntax instead | LL | Empty1 {} => () | ^^^^^^^^^ +help: a tuple struct with a similar name exists + | +LL | XEmpty6() => () + | ^^^^^^^ error[E0532]: expected tuple struct or tuple variant, found struct `XEmpty1` --> $DIR/empty-struct-braces-pat-2.rs:18:9 | LL | XEmpty1() => () | ^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:3:1 | -help: a tuple struct with a similar name exists +LL | pub struct XEmpty6(); + | --------------------- similarly named tuple struct `XEmpty6` defined here | -LL | XEmpty6() => () - | ^^^^^^^ help: use struct pattern syntax instead | LL | XEmpty1 {} => () | ^^^^^^^^^^ +help: a tuple struct with a similar name exists + | +LL | XEmpty6() => () + | ^^^^^^^ error[E0532]: expected tuple struct or tuple variant, found struct `Empty1` --> $DIR/empty-struct-braces-pat-2.rs:21:9 @@ -39,30 +49,40 @@ LL | struct Empty1 {} ... LL | Empty1(..) => () | ^^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:3:1 | -help: a tuple struct with a similar name exists +LL | pub struct XEmpty6(); + | --------------------- similarly named tuple struct `XEmpty6` defined here | -LL | XEmpty6(..) => () - | ^^^^^^^ help: use struct pattern syntax instead | LL | Empty1 {} => () | ^^^^^^^^^ +help: a tuple struct with a similar name exists + | +LL | XEmpty6(..) => () + | ^^^^^^^ error[E0532]: expected tuple struct or tuple variant, found struct `XEmpty1` --> $DIR/empty-struct-braces-pat-2.rs:24:9 | LL | XEmpty1(..) => () | ^^^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:3:1 | -help: a tuple struct with a similar name exists +LL | pub struct XEmpty6(); + | --------------------- similarly named tuple struct `XEmpty6` defined here | -LL | XEmpty6(..) => () - | ^^^^^^^ help: use struct pattern syntax instead | LL | XEmpty1 {} => () | ^^^^^^^^^^ +help: a tuple struct with a similar name exists + | +LL | XEmpty6(..) => () + | ^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/empty/empty-struct-braces-pat-3.stderr b/src/test/ui/empty/empty-struct-braces-pat-3.stderr index 93ace3eccef..066c42d8181 100644 --- a/src/test/ui/empty/empty-struct-braces-pat-3.stderr +++ b/src/test/ui/empty/empty-struct-braces-pat-3.stderr @@ -12,15 +12,20 @@ error[E0532]: expected tuple struct or tuple variant, found struct variant `XE:: | LL | XE::XEmpty3() => () | ^^^^^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:8:5 | -help: a tuple variant with a similar name exists +LL | XEmpty5(), + | --------- similarly named tuple variant `XEmpty5` defined here | -LL | XE::XEmpty5() => () - | ^^^^^^^ help: use struct pattern syntax instead | LL | XE::XEmpty3 { /* fields */ } => () | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: a tuple variant with a similar name exists + | +LL | XE::XEmpty5() => () + | ^^^^^^^ error[E0532]: expected tuple struct or tuple variant, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-pat-3.rs:25:9 @@ -36,15 +41,20 @@ error[E0532]: expected tuple struct or tuple variant, found struct variant `XE:: | LL | XE::XEmpty3(..) => () | ^^^^^^^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:8:5 | -help: a tuple variant with a similar name exists +LL | XEmpty5(), + | --------- similarly named tuple variant `XEmpty5` defined here | -LL | XE::XEmpty5(..) => () - | ^^^^^^^ help: use struct pattern syntax instead | LL | XE::XEmpty3 { /* fields */ } => () | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: a tuple variant with a similar name exists + | +LL | XE::XEmpty5(..) => () + | ^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr index 077367de9d8..e43b3c3546b 100644 --- a/src/test/ui/error-codes/E0423.stderr +++ b/src/test/ui/error-codes/E0423.stderr @@ -34,15 +34,18 @@ LL | struct Foo { a: bool }; LL | LL | let f = Foo(); | ^^^^^ +... +LL | fn foo() { + | -------- similarly named function `foo` defined here | -help: a function with a similar name exists - | -LL | let f = foo(); - | ^^^ help: use struct literal syntax instead | LL | let f = Foo { a: val }; | ^^^^^^^^^^^^^^ +help: a function with a similar name exists + | +LL | let f = foo(); + | ^^^ error[E0423]: expected value, found struct `T` --> $DIR/E0423.rs:14:8 diff --git a/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr b/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr index 12053d8a129..aa30a7e0d64 100644 --- a/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr +++ b/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr @@ -5,16 +5,16 @@ LL | struct X {} | ----------- `X` defined here LL | LL | const Y: X = X("ö"); - | ^^^^^^ + | -------------^^^^^^- similarly named constant `Y` defined here | -help: a constant with a similar name exists - | -LL | const Y: X = Y("ö"); - | ^ help: use struct literal syntax instead | LL | const Y: X = X {}; | ^^^^ +help: a constant with a similar name exists + | +LL | const Y: X = Y("ö"); + | ^ error: aborting due to previous error diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index 636789c9cc3..2e25ffa168f 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -53,14 +53,14 @@ LL | TV(), LL | check(m7::V); | ^^^^^ | -help: a tuple variant with a similar name exists - | -LL | check(m7::TV); - | ^^ help: use struct literal syntax instead | LL | check(m7::V {}); | ^^^^^^^^ +help: a tuple variant with a similar name exists + | +LL | check(m7::TV); + | ^^ help: consider importing one of these items instead | LL | use m8::V; @@ -79,14 +79,14 @@ LL | check(xm7::V); LL | TV(), | ---- similarly named tuple variant `TV` defined here | -help: a tuple variant with a similar name exists - | -LL | check(xm7::TV); - | ^^ help: use struct literal syntax instead | LL | check(xm7::V { /* fields */ }); | ^^^^^^^^^^^^^^^^^^^^^^^ +help: a tuple variant with a similar name exists + | +LL | check(xm7::TV); + | ^^ help: consider importing one of these items instead | LL | use m8::V; diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr index c9b9aeb45ba..72d66b0f6a2 100644 --- a/src/test/ui/resolve/issue-39226.stderr +++ b/src/test/ui/resolve/issue-39226.stderr @@ -7,14 +7,14 @@ LL | struct Handle {} LL | handle: Handle | ^^^^^^ | -help: a local variable with a similar name exists - | -LL | handle: handle - | ^^^^^^ help: use struct literal syntax instead | LL | handle: Handle {} | ^^^^^^^^^ +help: a local variable with a similar name exists + | +LL | handle: handle + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 3904a00dde1..f3cc338f13c 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -22,10 +22,6 @@ LL | fn f() { LL | Z; | ^ | -help: a function with a similar name exists - | -LL | f; - | ^ help: try using one of the enum's variants | LL | m::Z::Fn; @@ -34,6 +30,10 @@ LL | m::Z::Struct; | ^^^^^^^^^^^^ LL | m::Z::Unit; | ^^^^^^^^^^ +help: a function with a similar name exists + | +LL | f; + | ^ error[E0423]: expected value, found struct variant `Z::Struct` --> $DIR/privacy-enum-ctor.rs:29:20 @@ -55,10 +55,6 @@ LL | fn f() { LL | let _: E = m::E; | ^^^^ | -help: a function with a similar name exists - | -LL | let _: E = m::f; - | ^ help: try using one of the enum's variants | LL | let _: E = E::Fn; @@ -67,6 +63,10 @@ LL | let _: E = E::Struct; | ^^^^^^^^^ LL | let _: E = E::Unit; | ^^^^^^^ +help: a function with a similar name exists + | +LL | let _: E = m::f; + | ^ help: consider importing one of these items instead | LL | use std::f32::consts::E; diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr index 33080340cb6..2d35159ec9a 100644 --- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr +++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr @@ -31,14 +31,14 @@ LL | pub const I: i32 = 1; LL | a::b.J | ^^^^ | -help: a constant with a similar name exists - | -LL | a::I.J - | ^ help: use the path separator to refer to an item | LL | a::b::J | +help: a constant with a similar name exists + | +LL | a::I.J + | ^ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:37:5 @@ -68,14 +68,14 @@ LL | pub const I: i32 = 1; LL | a::b.f() | ^^^^ | -help: a constant with a similar name exists - | -LL | a::I.f() - | ^ help: use the path separator to refer to an item | LL | a::b::f() | ^^^^^^^ +help: a constant with a similar name exists + | +LL | a::I.f() + | ^ error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:50:5 diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index 45309486db4..9b2febb1393 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -9,14 +9,14 @@ LL | B { a: usize }, LL | let _: E = E::B; | ^^^^ | -help: a tuple variant with a similar name exists - | -LL | let _: E = E::A; - | ^ help: use struct literal syntax instead | LL | let _: E = E::B { a: val }; | ^^^^^^^^^^^^^^^ +help: a tuple variant with a similar name exists + | +LL | let _: E = E::A; + | ^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:29:20 diff --git a/src/test/ui/type/type-ascription-with-fn-call.stderr b/src/test/ui/type/type-ascription-with-fn-call.stderr index 5f74724b59e..d78fd08fd60 100644 --- a/src/test/ui/type/type-ascription-with-fn-call.stderr +++ b/src/test/ui/type/type-ascription-with-fn-call.stderr @@ -4,10 +4,7 @@ error[E0573]: expected type, found function `f` LL | f() : | - help: maybe you meant to write `;` here LL | f(); - | ^^^ - | | - | not a type - | expecting a type here because of type ascription + | ^^^ expecting a type here because of type ascription error: aborting due to previous error