Skip to content

Commit 75015b0

Browse files
authored
Attribute panics to the mdtests that cause them (#15241)
This updates the mdtest harness to catch any panics that occur during type checking, and to display the panic message as an mdtest failure. (We don't know which specific line causes the failure, so we attribute panics to the first line of the test case.)
1 parent 706d87f commit 75015b0

File tree

7 files changed

+24
-10
lines changed

7 files changed

+24
-10
lines changed

crates/red_knot_test/src/lib.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ use red_knot_python_semantic::types::check_types;
66
use red_knot_python_semantic::Program;
77
use ruff_db::diagnostic::{Diagnostic, ParseDiagnostic};
88
use ruff_db::files::{system_path_to_file, File, Files};
9+
use ruff_db::panic::catch_unwind;
910
use ruff_db::parsed::parsed_module;
1011
use ruff_db::system::{DbWithTestSystem, SystemPathBuf};
1112
use ruff_db::testing::{setup_logging, setup_logging_with_filter};
12-
use ruff_source_file::LineIndex;
13+
use ruff_source_file::{LineIndex, OneIndexed};
1314
use ruff_text_size::TextSize;
1415
use salsa::Setter;
1516

@@ -136,7 +137,20 @@ fn run_test(db: &mut db::Db, test: &parser::MarkdownTest) -> Result<(), Failures
136137
})
137138
.collect();
138139

139-
let type_diagnostics = check_types(db, test_file.file);
140+
let type_diagnostics = match catch_unwind(|| check_types(db, test_file.file)) {
141+
Ok(type_diagnostics) => type_diagnostics,
142+
Err(info) => {
143+
let mut by_line = matcher::FailuresByLine::default();
144+
by_line.push(
145+
OneIndexed::from_zero_indexed(0),
146+
info.info.split('\n').map(String::from).collect(),
147+
);
148+
return Some(FileFailures {
149+
backtick_offset: test_file.backtick_offset,
150+
by_line,
151+
});
152+
}
153+
};
140154
diagnostics.extend(type_diagnostics.into_iter().map(|diagnostic| {
141155
let diagnostic: Box<dyn Diagnostic> = Box::new((*diagnostic).clone());
142156
diagnostic

crates/red_knot_test/src/matcher.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ impl FailuresByLine {
2727
})
2828
}
2929

30-
fn push(&mut self, line_number: OneIndexed, messages: Vec<String>) {
30+
pub(super) fn push(&mut self, line_number: OneIndexed, messages: Vec<String>) {
3131
let start = self.failures.len();
3232
self.failures.extend(messages);
3333
self.lines.push(LineFailures {

crates/ruff/src/commands/check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use log::{debug, error, warn};
1111
use rayon::prelude::*;
1212
use rustc_hash::FxHashMap;
1313

14+
use ruff_db::panic::catch_unwind;
1415
use ruff_diagnostics::Diagnostic;
1516
use ruff_linter::message::Message;
1617
use ruff_linter::package::PackageRoot;
@@ -27,7 +28,6 @@ use ruff_workspace::resolver::{
2728
use crate::args::ConfigArguments;
2829
use crate::cache::{Cache, PackageCacheMap, PackageCaches};
2930
use crate::diagnostics::Diagnostics;
30-
use crate::panic::catch_unwind;
3131

3232
/// Run the linter over a collection of files.
3333
#[allow(clippy::too_many_arguments)]

crates/ruff/src/commands/format.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use rustc_hash::FxHashSet;
1515
use thiserror::Error;
1616
use tracing::debug;
1717

18+
use ruff_db::panic::{catch_unwind, PanicError};
1819
use ruff_diagnostics::SourceMap;
1920
use ruff_linter::fs;
2021
use ruff_linter::logging::{DisplayParseError, LogLevel};
@@ -32,7 +33,6 @@ use ruff_workspace::FormatterSettings;
3233

3334
use crate::args::{ConfigArguments, FormatArguments, FormatRange};
3435
use crate::cache::{Cache, FileCacheKey, PackageCacheMap, PackageCaches};
35-
use crate::panic::{catch_unwind, PanicError};
3636
use crate::resolve::resolve;
3737
use crate::{resolve_default_files, ExitStatus};
3838

crates/ruff/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ pub mod args;
2929
mod cache;
3030
mod commands;
3131
mod diagnostics;
32-
mod panic;
3332
mod printer;
3433
pub mod resolve;
3534
mod stdin;

crates/ruff_db/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub mod diagnostic;
1010
pub mod display;
1111
pub mod file_revision;
1212
pub mod files;
13+
pub mod panic;
1314
pub mod parsed;
1415
pub mod source;
1516
pub mod system;

crates/ruff/src/panic.rs renamed to crates/ruff_db/src/panic.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#[derive(Default, Debug)]
2-
pub(crate) struct PanicError {
3-
pub(crate) info: String,
4-
pub(crate) backtrace: Option<std::backtrace::Backtrace>,
2+
pub struct PanicError {
3+
pub info: String,
4+
pub backtrace: Option<std::backtrace::Backtrace>,
55
}
66

77
impl std::fmt::Display for PanicError {
@@ -21,7 +21,7 @@ thread_local! {
2121

2222
/// [`catch_unwind`](std::panic::catch_unwind) wrapper that sets a custom [`set_hook`](std::panic::set_hook)
2323
/// to extract the backtrace. The original panic-hook gets restored before returning.
24-
pub(crate) fn catch_unwind<F, R>(f: F) -> Result<R, PanicError>
24+
pub fn catch_unwind<F, R>(f: F) -> Result<R, PanicError>
2525
where
2626
F: FnOnce() -> R + std::panic::UnwindSafe,
2727
{

0 commit comments

Comments
 (0)