Rollup merge of #140622 - petrochenkov:annusexp, r=jieyouxu

compiletest: Improve diagnostics for line annotation mismatches

When some line annotations are missing or misplaced, compiletest reports an error, but the error is not very convenient.
This PR attempts to improve the user experience.

- The "expected ... not found" messages are no longer duplicated.
- The `proc_res.status` and `proc_res.cmdline` message is no longer put in the middle of other messages describing the annotation mismatches, it's now put into the end.
- Compiletest now makes suggestions if there are fuzzy matches between expected and actually reported errors (e.g. the annotation is put on a wrong line).
- Missing diagnostic kinds are no longer produce an error eagerly, but instead treated as always mismatching kinds, so they can produce suggestions telling the right kind.

I'll post screenshots in the thread below, but the behavior shown on the screenshots can be reproduced locally using the new test `tests/ui/compiletest-self-test/line-annotation-mismatches.rs`.

This also fixes https://github.com/rust-lang/rust/issues/140940.

r? ``@jieyouxu``
This commit is contained in:
Guillaume Gomez 2025-06-24 11:20:06 +02:00 committed by GitHub
commit 5f2dae19c4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 297 additions and 111 deletions

View file

@ -1,7 +1,7 @@
//@ revisions: rpass cfail
enum A {
//[cfail]~^ ERROR 3:1: 3:7: recursive types `A` and `C` have infinite size [E0072]
//[cfail]~^ ERROR recursive types `A` and `C` have infinite size [E0072]
B(C),
}

View file

@ -32,8 +32,8 @@ fn four_shuffle(_a: T1, _b: T2, _c: T3, _d: T4) {}
fn main() {
three_diff(T2::new(0)); //~ ERROR function takes
four_shuffle(T3::default(), T4::default(), T1::default(), T2::default()); //~ ERROR 35:5: 35:17: arguments to this function are incorrect [E0308]
four_shuffle(T3::default(), T2::default(), T1::default(), T3::default()); //~ ERROR 36:5: 36:17: arguments to this function are incorrect [E0308]
four_shuffle(T3::default(), T4::default(), T1::default(), T2::default()); //~ ERROR arguments to this function are incorrect [E0308]
four_shuffle(T3::default(), T2::default(), T1::default(), T3::default()); //~ ERROR arguments to this function are incorrect [E0308]
let p1 = T1::new(0);
let p2 = Arc::new(T2::new(0));

View file

@ -4,5 +4,5 @@
// Regression test for issue 79694
fn main() {
let _ = async move { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect
let _ = async move { }; //~ ERROR the order of `move` and `async` is incorrect
}

View file

@ -4,5 +4,5 @@
// Regression test for issue 79694
fn main() {
let _ = move async { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect
let _ = move async { }; //~ ERROR the order of `move` and `async` is incorrect
}

View file

@ -0,0 +1,42 @@
//@ should-fail
// The warning is reported with unknown line
//@ compile-flags: -D raw_pointer_derive
//~? WARN kind and unknown line match the reported warning, but we do not suggest it
// The error is expected but not reported at all.
//~ ERROR this error does not exist
// The error is reported but not expected at all.
// "`main` function not found in crate" (the main function is intentionally not added)
// An "unimportant" diagnostic is expected on a wrong line.
//~ ERROR aborting due to
// An "unimportant" diagnostic is expected with a wrong kind.
//~? ERROR For more information about an error
fn wrong_line_or_kind() {
// A diagnostic expected on a wrong line.
unresolved1;
//~ ERROR cannot find value `unresolved1` in this scope
// A diagnostic expected with a wrong kind.
unresolved2; //~ WARN cannot find value `unresolved2` in this scope
// A diagnostic expected with a missing kind (treated as a wrong kind).
unresolved3; //~ cannot find value `unresolved3` in this scope
// A diagnostic expected with a wrong line and kind.
unresolved4;
//~ WARN cannot find value `unresolved4` in this scope
}
fn wrong_message() {
// A diagnostic expected with a wrong message, but the line is known and right.
unresolvedA; //~ ERROR stub message 1
// A diagnostic expected with a wrong message, but the line is known and right,
// even if the kind doesn't match.
unresolvedB; //~ WARN stub message 2
}

View file

@ -0,0 +1,61 @@
warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
|
= note: requested on the command line with `-D raw_pointer_derive`
= note: `#[warn(renamed_and_removed_lints)]` on by default
error[E0425]: cannot find value `unresolved1` in this scope
--> $DIR/line-annotation-mismatches.rs:21:5
|
LL | unresolved1;
| ^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find value `unresolved2` in this scope
--> $DIR/line-annotation-mismatches.rs:25:5
|
LL | unresolved2;
| ^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find value `unresolved3` in this scope
--> $DIR/line-annotation-mismatches.rs:28:5
|
LL | unresolved3;
| ^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find value `unresolved4` in this scope
--> $DIR/line-annotation-mismatches.rs:31:5
|
LL | unresolved4;
| ^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find value `unresolvedA` in this scope
--> $DIR/line-annotation-mismatches.rs:37:5
|
LL | unresolvedA;
| ^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find value `unresolvedB` in this scope
--> $DIR/line-annotation-mismatches.rs:41:5
|
LL | unresolvedB;
| ^^^^^^^^^^^ not found in this scope
warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
|
= note: requested on the command line with `-D raw_pointer_derive`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0601]: `main` function not found in crate `line_annotation_mismatches`
--> $DIR/line-annotation-mismatches.rs:42:2
|
LL | }
| ^ consider adding a `main` function to `$DIR/line-annotation-mismatches.rs`
warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
|
= note: requested on the command line with `-D raw_pointer_derive`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 7 previous errors; 3 warnings emitted
Some errors have detailed explanations: E0425, E0601.
For more information about an error, try `rustc --explain E0425`.

View file

@ -1,4 +1,4 @@
#![crate_type = "lib"]
#[cfi_encoding = "3Bar"] //~ERROR 3:1: 3:25: the `#[cfi_encoding]` attribute is an experimental feature [E0658]
#[cfi_encoding = "3Bar"] //~ ERROR the `#[cfi_encoding]` attribute is an experimental feature [E0658]
pub struct Foo(i32);

View file

@ -1,4 +1,4 @@
fn main() {
let _ : &(dyn Send,) = &((),);
//~^ ERROR 2:28: 2:34: mismatched types [E0308]
//~^ ERROR mismatched types [E0308]
}

View file

@ -9,7 +9,7 @@ trait MyTrait {
impl MyTrait for &i32 {
type Output = &i32;
//~^ ERROR 11:19: 11:20: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
//~^ ERROR in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
}
impl MyTrait for &u32 {

View file

@ -2,4 +2,4 @@
#![allow(soft_unstable)]
#![test]
//~^ ERROR 4:1: 4:9: `test` attribute cannot be used at crate level
//~^ ERROR `test` attribute cannot be used at crate level

View file

@ -3,7 +3,7 @@ fn main() {
//~^ NOTE: the found closure
let x: fn(i32) = x;
//~^ ERROR: 5:22: 5:23: mismatched types [E0308]
//~^ ERROR: mismatched types [E0308]
//~| NOTE: incorrect number of function parameters
//~| NOTE: expected due to this
//~| NOTE: expected fn pointer `fn(i32)`

View file

@ -3,14 +3,14 @@ pub fn main() {
let s: String = "abcdef".to_string();
v[3_usize];
v[3];
v[3u8]; //~ERROR : the type `[isize]` cannot be indexed by `u8`
v[3i8]; //~ERROR : the type `[isize]` cannot be indexed by `i8`
v[3u32]; //~ERROR : the type `[isize]` cannot be indexed by `u32`
v[3i32]; //~ERROR : the type `[isize]` cannot be indexed by `i32`
v[3u8]; //~ ERROR the type `[isize]` cannot be indexed by `u8`
v[3i8]; //~ ERROR the type `[isize]` cannot be indexed by `i8`
v[3u32]; //~ ERROR the type `[isize]` cannot be indexed by `u32`
v[3i32]; //~ ERROR the type `[isize]` cannot be indexed by `i32`
s.as_bytes()[3_usize];
s.as_bytes()[3];
s.as_bytes()[3u8]; //~ERROR : the type `[u8]` cannot be indexed by `u8`
s.as_bytes()[3i8]; //~ERROR : the type `[u8]` cannot be indexed by `i8`
s.as_bytes()[3u32]; //~ERROR : the type `[u8]` cannot be indexed by `u32`
s.as_bytes()[3i32]; //~ERROR : the type `[u8]` cannot be indexed by `i32`
s.as_bytes()[3u8]; //~ ERROR the type `[u8]` cannot be indexed by `u8`
s.as_bytes()[3i8]; //~ ERROR the type `[u8]` cannot be indexed by `i8`
s.as_bytes()[3u32]; //~ ERROR the type `[u8]` cannot be indexed by `u32`
s.as_bytes()[3i32]; //~ ERROR the type `[u8]` cannot be indexed by `i32`
}

View file

@ -1,17 +1,17 @@
//@ run-rustfix
fn main() {}
fn _foo() -> bool {
& //~ ERROR 4:5: 6:36: mismatched types [E0308]
& //~ ERROR mismatched types [E0308]
mut
if true { true } else { false }
}
fn _bar() -> bool {
& //~ ERROR 10:5: 11:40: mismatched types [E0308]
& //~ ERROR mismatched types [E0308]
mut if true { true } else { false }
}
fn _baz() -> bool {
& mut //~ ERROR 15:5: 16:36: mismatched types [E0308]
& mut //~ ERROR mismatched types [E0308]
if true { true } else { false }
}

View file

@ -2,7 +2,7 @@ struct Data(String);
impl Iterator for Data {
type Item = &str;
//~^ ERROR 4:17: 4:18: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
//~^ ERROR associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
fn next(&mut self) -> Option<Self::Item> {
Some(&self.0)
@ -16,7 +16,7 @@ trait Bar {
impl Bar for usize {
type Item = &usize;
//~^ ERROR 18:17: 18:18: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
//~^ ERROR in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
fn poke(&mut self, item: Self::Item) {
self += *item;
@ -25,7 +25,7 @@ impl Bar for usize {
impl Bar for isize {
type Item<'a> = &'a isize;
//~^ ERROR 27:14: 27:18: lifetime parameters or bounds on associated type `Item` do not match the trait declaration [E0195]
//~^ ERROR lifetime parameters or bounds on associated type `Item` do not match the trait declaration [E0195]
fn poke(&mut self, item: Self::Item) {
self += *item;

View file

@ -2,17 +2,17 @@
#![crate_type = "lib"]
pub fn foo(arg: Option<&Vec<i32>>) -> Option<&[i32]> {
arg //~ ERROR 5:5: 5:8: mismatched types [E0308]
arg //~ ERROR mismatched types [E0308]
}
pub fn bar(arg: Option<&Vec<i32>>) -> &[i32] {
arg.unwrap_or(&[]) //~ ERROR 9:19: 9:22: mismatched types [E0308]
arg.unwrap_or(&[]) //~ ERROR mismatched types [E0308]
}
pub fn barzz<'a>(arg: Option<&'a Vec<i32>>, v: &'a [i32]) -> &'a [i32] {
arg.unwrap_or(v) //~ ERROR 13:19: 13:20: mismatched types [E0308]
arg.unwrap_or(v) //~ ERROR mismatched types [E0308]
}
pub fn convert_result(arg: Result<&Vec<i32>, ()>) -> &[i32] {
arg.unwrap_or(&[]) //~ ERROR 17:19: 17:22: mismatched types [E0308]
arg.unwrap_or(&[]) //~ ERROR mismatched types [E0308]
}

View file

@ -7,5 +7,5 @@
#![no_core]
#![no_main]
#[cfi_encoding] //~ERROR 10:1: 10:16: malformed `cfi_encoding` attribute input
#[cfi_encoding] //~ ERROR malformed `cfi_encoding` attribute input
pub struct Type1(i32);

View file

@ -2,7 +2,7 @@ fn main() {
let mut buf = [0u8; 50];
let mut bref = buf.as_slice();
foo(&mut bref);
//~^ ERROR 4:9: 4:18: the trait bound `&[u8]: std::io::Write` is not satisfied [E0277]
//~^ ERROR the trait bound `&[u8]: std::io::Write` is not satisfied [E0277]
}
fn foo(_: &mut impl std::io::Write) {}

View file

@ -6,5 +6,5 @@ mod option {
}
fn main() {
let _: option::O<()> = (); //~ ERROR 9:28: 9:30: mismatched types [E0308]
let _: option::O<()> = (); //~ ERROR mismatched types [E0308]
}

View file

@ -3,9 +3,9 @@
fn takes_option(_arg: Option<&String>) {}
fn main() {
takes_option(&None); //~ ERROR 6:18: 6:23: mismatched types [E0308]
takes_option(&None); //~ ERROR mismatched types [E0308]
let x = String::from("x");
let res = Some(x);
takes_option(&res); //~ ERROR 10:18: 10:22: mismatched types [E0308]
takes_option(&res); //~ ERROR mismatched types [E0308]
}

View file

@ -25,6 +25,6 @@ fn downcast<'a, W: ?Sized>() -> std::io::Result<&'a W> {
struct Other;
fn main() -> std::io::Result<()> {
let other: Other = downcast()?;//~ERROR 28:24: 28:35: `?` operator has incompatible types
let other: Other = downcast()?; //~ ERROR `?` operator has incompatible types
Ok(())
}

View file

@ -25,5 +25,5 @@ fn downcast<'a, W: ?Sized>() -> &'a W {
struct Other;
fn main() {
let other: &mut Other = downcast();//~ERROR 28:29: 28:39: mismatched types [E0308]
let other: &mut Other = downcast();//~ ERROR mismatched types [E0308]
}