1
Fork 0

compiletest: Support matching diagnostics on lines below

This commit is contained in:
Vadim Petrochenkov 2025-03-29 12:52:10 +03:00
parent 928468c47c
commit cf451f0830
31 changed files with 62 additions and 48 deletions

View file

@ -202,6 +202,9 @@ several ways to match the message with the line (see the examples below):
* `~|`: Associates the error level and message with the *same* line as the * `~|`: Associates the error level and message with the *same* line as the
*previous comment*. This is more convenient than using multiple carets when *previous comment*. This is more convenient than using multiple carets when
there are multiple messages associated with the same line. there are multiple messages associated with the same line.
* `~v`: Associates the error level and message with the *next* error
annotation line. Each symbol (`v`) that you add adds a line to this, so `~vvv`
is three lines below the error annotation line.
* `~?`: Used to match error levels and messages with errors not having line * `~?`: Used to match error levels and messages with errors not having line
information. These can be placed on any line in the test file, but are information. These can be placed on any line in the test file, but are
conventionally placed at the end. conventionally placed at the end.
@ -273,6 +276,18 @@ fn main() {
//~| ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields [E0023] //~| ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields [E0023]
``` ```
#### Positioned above error line
Use the `//~v` idiom with number of v's in the string to indicate the number
of lines below. This is typically used in lexer or parser tests matching on errors like unclosed
delimiter or unclosed literal happening at the end of file.
```rust,ignore
// ignore-tidy-trailing-newlines
//~v ERROR this file contains an unclosed delimiter
fn main((ؼ
```
#### Error without line information #### Error without line information
Use `//~?` to match an error without line information. Use `//~?` to match an error without line information.

View file

@ -122,13 +122,17 @@ fn parse_expected(
// //~| // //~|
// //~^ // //~^
// //~^^^^^ // //~^^^^^
// //~v
// //~vvvvv
// //~? // //~?
// //[rev1]~ // //[rev1]~
// //[rev1,rev2]~^^ // //[rev1,rev2]~^^
static RE: OnceLock<Regex> = OnceLock::new(); static RE: OnceLock<Regex> = OnceLock::new();
let captures = RE let captures = RE
.get_or_init(|| Regex::new(r"//(?:\[(?P<revs>[\w\-,]+)])?~(?P<adjust>\?|\||\^*)").unwrap()) .get_or_init(|| {
Regex::new(r"//(?:\[(?P<revs>[\w\-,]+)])?~(?P<adjust>\?|\||[v\^]*)").unwrap()
})
.captures(line)?; .captures(line)?;
match (test_revision, captures.name("revs")) { match (test_revision, captures.name("revs")) {
@ -164,6 +168,8 @@ fn parse_expected(
(true, Some(last_nonfollow_error.expect("encountered //~| without preceding //~^ line"))) (true, Some(last_nonfollow_error.expect("encountered //~| without preceding //~^ line")))
} else if line_num_adjust == "?" { } else if line_num_adjust == "?" {
(false, None) (false, None)
} else if line_num_adjust.starts_with('v') {
(false, Some(line_num + line_num_adjust.len()))
} else { } else {
(false, Some(line_num - line_num_adjust.len())) (false, Some(line_num - line_num_adjust.len()))
}; };

View file

@ -1,4 +1,4 @@
//@ error-pattern: this file contains an unclosed delimiter
struct R { } struct R { }
//~vv ERROR this file contains an unclosed delimiter
struct S { struct S {
x: [u8; R x: [u8; R

View file

@ -1,7 +1,7 @@
//@ error-pattern: mismatched closing delimiter: `}`
// FIXME(31528) we emit a bunch of silly errors here due to continuing past the // FIXME(31528) we emit a bunch of silly errors here due to continuing past the
// first one. This would be easy-ish to address by better recovery in tokenisation. // first one. This would be easy-ish to address by better recovery in tokenisation.
//~vvvvv ERROR mismatched closing delimiter: `}`
pub fn trace_option(option: Option<isize>) { pub fn trace_option(option: Option<isize>) {
option.map(|some| 42; option.map(|some| 42;

View file

@ -1,5 +1,4 @@
// Fixed in #66054. // Fixed in #66054.
// ignore-tidy-trailing-newlines // ignore-tidy-trailing-newlines
//@ error-pattern: this file contains an unclosed delimiter //~v ERROR this file contains an unclosed delimiter
//@ error-pattern: aborting due to 1 previous error
#[Ѕ #[Ѕ

View file

@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter error: this file contains an unclosed delimiter
--> $DIR/issue-58094-missing-right-square-bracket.rs:5:4 --> $DIR/issue-58094-missing-right-square-bracket.rs:4:4
| |
LL | #[Ѕ LL | #[Ѕ
| - ^ | - ^

View file

@ -1,6 +1,7 @@
// ignore-tidy-trailing-newlines // ignore-tidy-trailing-newlines
//@ error-pattern: aborting due to 1 previous error
#![allow(uncommon_codepoints)] #![allow(uncommon_codepoints)]
//~vv ERROR this file contains an unclosed delimiter
y![ y![
Ϥ, Ϥ,

View file

@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter error: this file contains an unclosed delimiter
--> $DIR/issue-62524.rs:6:3 --> $DIR/issue-62524.rs:7:3
| |
LL | y![ LL | y![
| - unclosed delimiter | - unclosed delimiter

View file

@ -1,5 +1,4 @@
//@ error-pattern:this file contains an unclosed delimiter
fn main() {} fn main() {}
//~v ERROR this file contains an unclosed delimiter
fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {

View file

@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter error: this file contains an unclosed delimiter
--> $DIR/issue-62554.rs:5:89 --> $DIR/issue-62554.rs:4:89
| |
LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
| - - - - -^ | - - - - -^

View file

@ -1,6 +1,6 @@
// Regression test for #62894, shouldn't crash. // Regression test for #62894, shouldn't crash.
//@ error-pattern: this file contains an unclosed delimiter
//~vvv ERROR this file contains an unclosed delimiter
fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
fn main() {} fn main() {}

View file

@ -1,8 +1,10 @@
// ignore-tidy-trailing-newlines // ignore-tidy-trailing-newlines
//@ error-pattern: aborting due to 3 previous errors
fn main() {} fn main() {}
//~vvv ERROR mismatched closing delimiter: `)`
//~vv ERROR mismatched closing delimiter: `)`
//~vvv ERROR this file contains an unclosed delimiter
fn p() { match s { v, E { [) {) } fn p() { match s { v, E { [) {) }

View file

@ -1,5 +1,5 @@
error: mismatched closing delimiter: `)` error: mismatched closing delimiter: `)`
--> $DIR/issue-62973.rs:6:27 --> $DIR/issue-62973.rs:8:27
| |
LL | fn p() { match s { v, E { [) {) } LL | fn p() { match s { v, E { [) {) }
| ^^ mismatched closing delimiter | ^^ mismatched closing delimiter
@ -7,7 +7,7 @@ LL | fn p() { match s { v, E { [) {) }
| unclosed delimiter | unclosed delimiter
error: mismatched closing delimiter: `)` error: mismatched closing delimiter: `)`
--> $DIR/issue-62973.rs:6:30 --> $DIR/issue-62973.rs:8:30
| |
LL | fn p() { match s { v, E { [) {) } LL | fn p() { match s { v, E { [) {) }
| ^^ mismatched closing delimiter | ^^ mismatched closing delimiter
@ -15,7 +15,7 @@ LL | fn p() { match s { v, E { [) {) }
| unclosed delimiter | unclosed delimiter
error: this file contains an unclosed delimiter error: this file contains an unclosed delimiter
--> $DIR/issue-62973.rs:8:2 --> $DIR/issue-62973.rs:10:2
| |
LL | fn p() { match s { v, E { [) {) } LL | fn p() { match s { v, E { [) {) }
| - - - - missing open `(` for this delimiter | - - - - missing open `(` for this delimiter

View file

@ -1,3 +1,4 @@
// fixed by #66361 // fixed by #66361
//@ error-pattern: aborting due to 2 previous errors //~vv ERROR mismatched closing delimiter: `]`
//~v ERROR this file contains an unclosed delimiter
impl W <s(f;Y(;] impl W <s(f;Y(;]

View file

@ -1,5 +1,5 @@
error: mismatched closing delimiter: `]` error: mismatched closing delimiter: `]`
--> $DIR/issue-63116.rs:3:14 --> $DIR/issue-63116.rs:4:14
| |
LL | impl W <s(f;Y(;] LL | impl W <s(f;Y(;]
| ^ ^ mismatched closing delimiter | ^ ^ mismatched closing delimiter
@ -7,7 +7,7 @@ LL | impl W <s(f;Y(;]
| unclosed delimiter | unclosed delimiter
error: this file contains an unclosed delimiter error: this file contains an unclosed delimiter
--> $DIR/issue-63116.rs:3:18 --> $DIR/issue-63116.rs:4:18
| |
LL | impl W <s(f;Y(;] LL | impl W <s(f;Y(;]
| - -^ | - -^

View file

@ -1,3 +1,2 @@
//@ error-pattern: this file contains an unclosed delimiter //~v ERROR this file contains an unclosed delimiter
//@ error-pattern: aborting due to 1 previous error
fn i(n{...,f # fn i(n{...,f #

View file

@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter error: this file contains an unclosed delimiter
--> $DIR/issue-63135.rs:3:16 --> $DIR/issue-63135.rs:2:16
| |
LL | fn i(n{...,f # LL | fn i(n{...,f #
| - - ^ | - - ^

View file

@ -1,6 +1,5 @@
//@ error-pattern: this file contains an unclosed delimiter
//@ error-pattern: this file contains an unclosed delimiter
fn main() {} fn main() {}
//~vv ERROR mismatched closing delimiter: `}`
//~v ERROR this file contains an unclosed delimiter
fn p([=(} fn p([=(}

View file

@ -1,5 +1,5 @@
error: mismatched closing delimiter: `}` error: mismatched closing delimiter: `}`
--> $DIR/issue-81804.rs:6:8 --> $DIR/issue-81804.rs:5:8
| |
LL | fn p([=(} LL | fn p([=(}
| ^^ mismatched closing delimiter | ^^ mismatched closing delimiter
@ -7,7 +7,7 @@ LL | fn p([=(}
| unclosed delimiter | unclosed delimiter
error: this file contains an unclosed delimiter error: this file contains an unclosed delimiter
--> $DIR/issue-81804.rs:6:11 --> $DIR/issue-81804.rs:5:11
| |
LL | fn p([=(} LL | fn p([=(}
| -- ^ | -- ^

View file

@ -1,10 +1,7 @@
//@ error-pattern: this file contains an unclosed delimiter
//@ error-pattern: mismatched closing delimiter: `]`
#![crate_name="0"] #![crate_name="0"]
fn main() {} fn main() {}
//~vv ERROR mismatched closing delimiter: `]`
//~v ERROR this file contains an unclosed delimiter
fn r()->i{0|{#[cfg(r(0{]0 fn r()->i{0|{#[cfg(r(0{]0

View file

@ -1,5 +1,5 @@
error: mismatched closing delimiter: `]` error: mismatched closing delimiter: `]`
--> $DIR/issue-81827.rs:10:23 --> $DIR/issue-81827.rs:7:23
| |
LL | fn r()->i{0|{#[cfg(r(0{]0 LL | fn r()->i{0|{#[cfg(r(0{]0
| - ^^ mismatched closing delimiter | - ^^ mismatched closing delimiter
@ -8,7 +8,7 @@ LL | fn r()->i{0|{#[cfg(r(0{]0
| closing delimiter possibly meant for this | closing delimiter possibly meant for this
error: this file contains an unclosed delimiter error: this file contains an unclosed delimiter
--> $DIR/issue-81827.rs:10:27 --> $DIR/issue-81827.rs:7:27
| |
LL | fn r()->i{0|{#[cfg(r(0{]0 LL | fn r()->i{0|{#[cfg(r(0{]0
| - - - ^ | - - - ^

View file

@ -1,2 +1,2 @@
//@ error-pattern: this file contains an unclosed delimiter //~v ERROR this file contains an unclosed delimiter
#[i=i::<ښܖ< #[i=i::<ښܖ<

View file

@ -1,2 +1,2 @@
//@ error-pattern: this file contains an unclosed delimiter //~v ERROR this file contains an unclosed delimiter
fn f(t:for<>t? fn f(t:for<>t?

View file

@ -1,7 +1,6 @@
// Regression test for the ICE described in #88770. // Regression test for the ICE described in #88770.
//@ error-pattern:this file contains an unclosed delimiter //~vvvv ERROR this file contains an unclosed delimiter
fn m(){print!("",(c for&g fn m(){print!("",(c for&g
u u
e e

View file

@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter error: this file contains an unclosed delimiter
--> $DIR/issue-88770.rs:8:3 --> $DIR/issue-88770.rs:7:3
| |
LL | fn m(){print!("",(c for&g LL | fn m(){print!("",(c for&g
| - - - unclosed delimiter | - - - unclosed delimiter

View file

@ -1,3 +1,3 @@
// ignore-tidy-trailing-newlines // ignore-tidy-trailing-newlines
//@ error-pattern: this file contains an unclosed delimiter //~v ERROR this file contains an unclosed delimiter
macro_rules! abc(ؼ macro_rules! abc(ؼ

View file

@ -1,4 +1,3 @@
// ignore-tidy-trailing-newlines // ignore-tidy-trailing-newlines
//@ error-pattern: this file contains an unclosed delimiter //~v ERROR this file contains an unclosed delimiter
//@ error-pattern: aborting due to 1 previous error
fn main((ؼ fn main((ؼ

View file

@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter error: this file contains an unclosed delimiter
--> $DIR/missing_right_paren.rs:4:11 --> $DIR/missing_right_paren.rs:3:11
| |
LL | fn main((ؼ LL | fn main((ؼ
| -- ^ | -- ^

View file

@ -1,6 +1,4 @@
//@ error-pattern: unterminated double quote string //~vv ERROR unterminated double quote string
fn main() { fn main() {
" "
} }

View file

@ -1,5 +1,5 @@
error[E0765]: unterminated double quote string error[E0765]: unterminated double quote string
--> $DIR/unbalanced-doublequote.rs:5:5 --> $DIR/unbalanced-doublequote.rs:3:5
| |
LL | / " LL | / "
LL | | } LL | | }

View file

@ -1,4 +1,3 @@
//@ error-pattern: this file contains an unclosed delimiter
use foo::{bar, baz; use foo::{bar, baz;
use std::fmt::Display; use std::fmt::Display;
@ -7,4 +6,5 @@ mod bar { }
mod baz { } mod baz { }
//~v ERROR this file contains an unclosed delimiter
fn main() {} fn main() {}