Rollup merge of #143661 - Muscraft:other-suggestion-message, r=estebank
chore: Improve how the other suggestions message gets rendered
Note: This change is part of my ongoing work to use `annotate-snippets` as `rustc`'s emitter
This change started as a way to remove some specialty code paths from `annotate-snippets`, by making the "and {} other candidates" message get rendered like a secondary message with no level, but turned into a fix for the message's Unicode output. Before this change, when using the Unicode output, the other suggestions message would get rendered outside of the main suggestion block, making it feel disconnected from what it was referring to. This change makes it so that the message is on the last line of the block, aligning its rendering with other secondary messages, and making it clear what the message is referring to.
Before:
```
error[E0433]: failed to resolve: use of undeclared type `IntoIter`
╭▸ $DIR/issue-82956.rs:28:24
│
LL │ let mut iter = IntoIter::new(self);
│ ━━━━━━━━ use of undeclared type `IntoIter`
╰╴
help: consider importing one of these structs
╭╴
LL + use std::array::IntoIter;
├╴
LL + use std::collections::binary_heap::IntoIter;
├╴
LL + use std::collections::btree_map::IntoIter;
├╴
LL + use std::collections::btree_set::IntoIter;
╰╴
and 9 other candidates
```
After:
```
error[E0433]: failed to resolve: use of undeclared type `IntoIter`
╭▸ $DIR/issue-82956.rs:28:24
│
LL │ let mut iter = IntoIter::new(self);
│ ━━━━━━━━ use of undeclared type `IntoIter`
╰╴
help: consider importing one of these structs
╭╴
LL + use std::array::IntoIter;
├╴
LL + use std::collections::binary_heap::IntoIter;
├╴
LL + use std::collections::btree_map::IntoIter;
├╴
LL + use std::collections::btree_set::IntoIter;
│
╰ and 9 other candidates
```
This commit is contained in:
commit
140f2fa5ae
13 changed files with 301 additions and 14 deletions
|
|
@ -2446,17 +2446,22 @@ impl HumanEmitter {
|
|||
| DisplaySuggestion::Underline => row_num - 1,
|
||||
DisplaySuggestion::None => row_num,
|
||||
};
|
||||
self.draw_col_separator_end(&mut buffer, row, max_line_num_len + 1);
|
||||
if other_suggestions > 0 {
|
||||
self.draw_col_separator_no_space(&mut buffer, row, max_line_num_len + 1);
|
||||
} else {
|
||||
self.draw_col_separator_end(&mut buffer, row, max_line_num_len + 1);
|
||||
}
|
||||
row_num = row + 1;
|
||||
}
|
||||
}
|
||||
if other_suggestions > 0 {
|
||||
self.draw_note_separator(&mut buffer, row_num, max_line_num_len + 1, false);
|
||||
let msg = format!(
|
||||
"and {} other candidate{}",
|
||||
other_suggestions,
|
||||
pluralize!(other_suggestions)
|
||||
);
|
||||
buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle);
|
||||
buffer.append(row_num, &msg, Style::NoStyle);
|
||||
}
|
||||
|
||||
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ LL + type X = <CString as Deref>::Target;
|
|||
LL - type X = std::ops::Deref::Target;
|
||||
LL + type X = <IoSlice<'_> as Deref>::Target;
|
||||
|
|
||||
and N other candidates
|
||||
= and N other candidates
|
||||
|
||||
error[E0223]: ambiguous associated type
|
||||
--> $DIR/associated-types-in-ambiguous-context.rs:13:23
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ LL + use std::collections::btree_map::IntoIter;
|
|||
|
|
||||
LL + use std::collections::btree_set::IntoIter;
|
||||
|
|
||||
and 9 other candidates
|
||||
= and 9 other candidates
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ LL + fn setup() -> Determine { Set }
|
|||
LL - fn setup() -> Set { Set }
|
||||
LL + fn setup() -> PutDown { Set }
|
||||
|
|
||||
and 3 other candidates
|
||||
= and 3 other candidates
|
||||
|
||||
error[E0425]: cannot find value `Set` in this scope
|
||||
--> $DIR/issue-56028-there-is-an-enum-variant.rs:9:21
|
||||
|
|
@ -36,7 +36,7 @@ LL + use Determine::Set;
|
|||
|
|
||||
LL + use PutDown::Set;
|
||||
|
|
||||
and 3 other candidates
|
||||
= and 3 other candidates
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ LL + use std::fmt::Display;
|
|||
|
|
||||
LL + use std::fmt::LowerExp;
|
||||
|
|
||||
and 5 other candidates
|
||||
= and 5 other candidates
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ LL + use ::issue_56125::issue_56125;
|
|||
LL - use empty::issue_56125;
|
||||
LL + use ::issue_56125::last_segment::issue_56125;
|
||||
|
|
||||
and 1 other candidate
|
||||
= and 1 other candidate
|
||||
|
||||
error[E0659]: `issue_56125` is ambiguous
|
||||
--> $DIR/issue-56125.rs:6:9
|
||||
|
|
|
|||
|
|
@ -419,7 +419,7 @@ mod foo {
|
|||
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
|
||||
\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[38;5;10m+ use std::collections::hash_map::Iter;\u001b[0m
|
||||
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
|
||||
\u001b[0m and 9 other candidates\u001b[0m
|
||||
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0mand 9 other candidates\u001b[0m
|
||||
|
||||
"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ LL - x: (),
|
|||
LL - })),
|
||||
LL + wtf: Some(Box::new_in(_, _)),
|
||||
|
|
||||
and 12 other candidates
|
||||
= and 12 other candidates
|
||||
help: consider using the `Default` trait
|
||||
|
|
||||
LL - wtf: Some(Box(U {
|
||||
|
|
@ -118,7 +118,7 @@ LL + let _ = Box::new_zeroed();
|
|||
LL - let _ = Box {};
|
||||
LL + let _ = Box::new_in(_, _);
|
||||
|
|
||||
and 12 other candidates
|
||||
= and 12 other candidates
|
||||
help: consider using the `Default` trait
|
||||
|
|
||||
LL - let _ = Box {};
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ LL + use std::collections::hash_map::Drain;
|
|||
|
|
||||
LL + use std::collections::hash_set::Drain;
|
||||
|
|
||||
and 3 other candidates
|
||||
= and 3 other candidates
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
130
tests/ui/suggestions/multi-suggestion.ascii.stderr
Normal file
130
tests/ui/suggestions/multi-suggestion.ascii.stderr
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
error[E0423]: expected function, tuple struct or tuple variant, found struct `std::collections::HashMap`
|
||||
--> $DIR/multi-suggestion.rs:17:13
|
||||
|
|
||||
LL | let _ = std::collections::HashMap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
|
||||
|
|
||||
= note: `std::collections::HashMap` defined here
|
||||
|
|
||||
help: you might have meant to use an associated function to build this type
|
||||
|
|
||||
LL | let _ = std::collections::HashMap::new();
|
||||
| +++++
|
||||
LL - let _ = std::collections::HashMap();
|
||||
LL + let _ = std::collections::HashMap::with_capacity(_);
|
||||
|
|
||||
LL - let _ = std::collections::HashMap();
|
||||
LL + let _ = std::collections::HashMap::with_hasher(_);
|
||||
|
|
||||
LL - let _ = std::collections::HashMap();
|
||||
LL + let _ = std::collections::HashMap::with_capacity_and_hasher(_, _);
|
||||
|
|
||||
help: consider using the `Default` trait
|
||||
|
|
||||
LL | let _ = <std::collections::HashMap as std::default::Default>::default();
|
||||
| + ++++++++++++++++++++++++++++++++++
|
||||
|
||||
error[E0423]: cannot initialize a tuple struct which contains private fields
|
||||
--> $DIR/multi-suggestion.rs:11:19
|
||||
|
|
||||
LL | wtf: Some(Box(U {
|
||||
| ^^^
|
||||
|
|
||||
note: constructor is not visible here due to private fields
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
= note: private field
|
||||
|
|
||||
= note: private field
|
||||
help: you might have meant to use an associated function to build this type
|
||||
|
|
||||
LL - wtf: Some(Box(U {
|
||||
LL - wtf: None,
|
||||
LL - x: (),
|
||||
LL - })),
|
||||
LL + wtf: Some(Box::new(_)),
|
||||
|
|
||||
LL - wtf: Some(Box(U {
|
||||
LL - wtf: None,
|
||||
LL - x: (),
|
||||
LL - })),
|
||||
LL + wtf: Some(Box::new_uninit()),
|
||||
|
|
||||
LL - wtf: Some(Box(U {
|
||||
LL - wtf: None,
|
||||
LL - x: (),
|
||||
LL - })),
|
||||
LL + wtf: Some(Box::new_zeroed()),
|
||||
|
|
||||
LL - wtf: Some(Box(U {
|
||||
LL - wtf: None,
|
||||
LL - x: (),
|
||||
LL - })),
|
||||
LL + wtf: Some(Box::new_in(_, _)),
|
||||
|
|
||||
= and 12 other candidates
|
||||
help: consider using the `Default` trait
|
||||
|
|
||||
LL - wtf: Some(Box(U {
|
||||
LL + wtf: Some(<Box as std::default::Default>::default()),
|
||||
|
|
||||
|
||||
error: cannot construct `HashMap<_, _, _>` with struct literal syntax due to private fields
|
||||
--> $DIR/multi-suggestion.rs:19:13
|
||||
|
|
||||
LL | let _ = std::collections::HashMap {};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: private field `base` that was not provided
|
||||
help: you might have meant to use an associated function to build this type
|
||||
|
|
||||
LL - let _ = std::collections::HashMap {};
|
||||
LL + let _ = std::collections::HashMap::new();
|
||||
|
|
||||
LL - let _ = std::collections::HashMap {};
|
||||
LL + let _ = std::collections::HashMap::with_capacity(_);
|
||||
|
|
||||
LL - let _ = std::collections::HashMap {};
|
||||
LL + let _ = std::collections::HashMap::with_hasher(_);
|
||||
|
|
||||
LL - let _ = std::collections::HashMap {};
|
||||
LL + let _ = std::collections::HashMap::with_capacity_and_hasher(_, _);
|
||||
|
|
||||
help: consider using the `Default` trait
|
||||
|
|
||||
LL - let _ = std::collections::HashMap {};
|
||||
LL + let _ = <std::collections::HashMap as std::default::Default>::default();
|
||||
|
|
||||
|
||||
error: cannot construct `Box<_, _>` with struct literal syntax due to private fields
|
||||
--> $DIR/multi-suggestion.rs:21:13
|
||||
|
|
||||
LL | let _ = Box {};
|
||||
| ^^^
|
||||
|
|
||||
= note: private fields `0` and `1` that were not provided
|
||||
help: you might have meant to use an associated function to build this type
|
||||
|
|
||||
LL - let _ = Box {};
|
||||
LL + let _ = Box::new(_);
|
||||
|
|
||||
LL - let _ = Box {};
|
||||
LL + let _ = Box::new_uninit();
|
||||
|
|
||||
LL - let _ = Box {};
|
||||
LL + let _ = Box::new_zeroed();
|
||||
|
|
||||
LL - let _ = Box {};
|
||||
LL + let _ = Box::new_in(_, _);
|
||||
|
|
||||
= and 12 other candidates
|
||||
help: consider using the `Default` trait
|
||||
|
|
||||
LL - let _ = Box {};
|
||||
LL + let _ = <Box as std::default::Default>::default();
|
||||
|
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0423`.
|
||||
22
tests/ui/suggestions/multi-suggestion.rs
Normal file
22
tests/ui/suggestions/multi-suggestion.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//@ revisions: ascii unicode
|
||||
//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode
|
||||
|
||||
#![allow(dead_code)]
|
||||
struct U <T> {
|
||||
wtf: Option<Box<U<T>>>,
|
||||
x: T,
|
||||
}
|
||||
fn main() {
|
||||
U {
|
||||
wtf: Some(Box(U { //[ascii]~ ERROR cannot initialize a tuple struct which contains private fields
|
||||
wtf: None,
|
||||
x: (),
|
||||
})),
|
||||
x: ()
|
||||
};
|
||||
let _ = std::collections::HashMap();
|
||||
//[ascii]~^ ERROR expected function, tuple struct or tuple variant, found struct `std::collections::HashMap`
|
||||
let _ = std::collections::HashMap {};
|
||||
//[ascii]~^ ERROR cannot construct `HashMap<_, _, _>` with struct literal syntax due to private fields
|
||||
let _ = Box {}; //[ascii]~ ERROR cannot construct `Box<_, _>` with struct literal syntax due to private fields
|
||||
}
|
||||
130
tests/ui/suggestions/multi-suggestion.unicode.stderr
Normal file
130
tests/ui/suggestions/multi-suggestion.unicode.stderr
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
error[E0423]: expected function, tuple struct or tuple variant, found struct `std::collections::HashMap`
|
||||
╭▸ $DIR/multi-suggestion.rs:17:13
|
||||
│
|
||||
LL │ let _ = std::collections::HashMap();
|
||||
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
╭▸ $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
|
||||
│
|
||||
╰ note: `std::collections::HashMap` defined here
|
||||
╰╴
|
||||
help: you might have meant to use an associated function to build this type
|
||||
╭╴
|
||||
LL │ let _ = std::collections::HashMap::new();
|
||||
├╴ +++++
|
||||
LL - let _ = std::collections::HashMap();
|
||||
LL + let _ = std::collections::HashMap::with_capacity(_);
|
||||
├╴
|
||||
LL - let _ = std::collections::HashMap();
|
||||
LL + let _ = std::collections::HashMap::with_hasher(_);
|
||||
├╴
|
||||
LL - let _ = std::collections::HashMap();
|
||||
LL + let _ = std::collections::HashMap::with_capacity_and_hasher(_, _);
|
||||
╰╴
|
||||
help: consider using the `Default` trait
|
||||
╭╴
|
||||
LL │ let _ = <std::collections::HashMap as std::default::Default>::default();
|
||||
╰╴ + ++++++++++++++++++++++++++++++++++
|
||||
|
||||
error[E0423]: cannot initialize a tuple struct which contains private fields
|
||||
╭▸ $DIR/multi-suggestion.rs:11:19
|
||||
│
|
||||
LL │ wtf: Some(Box(U {
|
||||
│ ━━━
|
||||
╰╴
|
||||
note: constructor is not visible here due to private fields
|
||||
╭▸ $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
│
|
||||
╰ note: private field
|
||||
│
|
||||
╰ note: private field
|
||||
help: you might have meant to use an associated function to build this type
|
||||
╭╴
|
||||
LL - wtf: Some(Box(U {
|
||||
LL - wtf: None,
|
||||
LL - x: (),
|
||||
LL - })),
|
||||
LL + wtf: Some(Box::new(_)),
|
||||
├╴
|
||||
LL - wtf: Some(Box(U {
|
||||
LL - wtf: None,
|
||||
LL - x: (),
|
||||
LL - })),
|
||||
LL + wtf: Some(Box::new_uninit()),
|
||||
├╴
|
||||
LL - wtf: Some(Box(U {
|
||||
LL - wtf: None,
|
||||
LL - x: (),
|
||||
LL - })),
|
||||
LL + wtf: Some(Box::new_zeroed()),
|
||||
├╴
|
||||
LL - wtf: Some(Box(U {
|
||||
LL - wtf: None,
|
||||
LL - x: (),
|
||||
LL - })),
|
||||
LL + wtf: Some(Box::new_in(_, _)),
|
||||
│
|
||||
╰ and 12 other candidates
|
||||
help: consider using the `Default` trait
|
||||
╭╴
|
||||
LL - wtf: Some(Box(U {
|
||||
LL + wtf: Some(<Box as std::default::Default>::default()),
|
||||
╰╴
|
||||
|
||||
error: cannot construct `HashMap<_, _, _>` with struct literal syntax due to private fields
|
||||
╭▸ $DIR/multi-suggestion.rs:19:13
|
||||
│
|
||||
LL │ let _ = std::collections::HashMap {};
|
||||
│ ━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
│
|
||||
╰ note: private field `base` that was not provided
|
||||
help: you might have meant to use an associated function to build this type
|
||||
╭╴
|
||||
LL - let _ = std::collections::HashMap {};
|
||||
LL + let _ = std::collections::HashMap::new();
|
||||
├╴
|
||||
LL - let _ = std::collections::HashMap {};
|
||||
LL + let _ = std::collections::HashMap::with_capacity(_);
|
||||
├╴
|
||||
LL - let _ = std::collections::HashMap {};
|
||||
LL + let _ = std::collections::HashMap::with_hasher(_);
|
||||
├╴
|
||||
LL - let _ = std::collections::HashMap {};
|
||||
LL + let _ = std::collections::HashMap::with_capacity_and_hasher(_, _);
|
||||
╰╴
|
||||
help: consider using the `Default` trait
|
||||
╭╴
|
||||
LL - let _ = std::collections::HashMap {};
|
||||
LL + let _ = <std::collections::HashMap as std::default::Default>::default();
|
||||
╰╴
|
||||
|
||||
error: cannot construct `Box<_, _>` with struct literal syntax due to private fields
|
||||
╭▸ $DIR/multi-suggestion.rs:21:13
|
||||
│
|
||||
LL │ let _ = Box {};
|
||||
│ ━━━
|
||||
│
|
||||
╰ note: private fields `0` and `1` that were not provided
|
||||
help: you might have meant to use an associated function to build this type
|
||||
╭╴
|
||||
LL - let _ = Box {};
|
||||
LL + let _ = Box::new(_);
|
||||
├╴
|
||||
LL - let _ = Box {};
|
||||
LL + let _ = Box::new_uninit();
|
||||
├╴
|
||||
LL - let _ = Box {};
|
||||
LL + let _ = Box::new_zeroed();
|
||||
├╴
|
||||
LL - let _ = Box {};
|
||||
LL + let _ = Box::new_in(_, _);
|
||||
│
|
||||
╰ and 12 other candidates
|
||||
help: consider using the `Default` trait
|
||||
╭╴
|
||||
LL - let _ = Box {};
|
||||
LL + let _ = <Box as std::default::Default>::default();
|
||||
╰╴
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0423`.
|
||||
|
|
@ -17,7 +17,7 @@ LL | t.a2.bar();
|
|||
| +++
|
||||
LL | t.a3.bar();
|
||||
| +++
|
||||
and 6 other candidates
|
||||
= and 6 other candidates
|
||||
|
||||
error[E0609]: no field `field` on type `Thing`
|
||||
--> $DIR/too-many-field-suggestions.rs:26:7
|
||||
|
|
@ -35,7 +35,7 @@ LL | t.a2.field;
|
|||
| +++
|
||||
LL | t.a3.field;
|
||||
| +++
|
||||
and 6 other candidates
|
||||
= and 6 other candidates
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue