Skip to content

Commit 8a899e6

Browse files
committed
feat: Respect edition of input crate
1 parent 4c94d18 commit 8a899e6

4 files changed

Lines changed: 116 additions & 75 deletions

File tree

mutest-driver/src/passes/analysis.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use rustc_hash::FxHashSet;
44
use rustc_interface::{create_and_enter_global_ctxt, passes, run_compiler};
55
use rustc_interface::interface::Result as CompilerResult;
66
use rustc_span::ErrorGuaranteed;
7-
use rustc_span::edition::Edition;
87
use rustc_span::fatal_error::FatalError;
98
use mutest_emit::codegen::symbols::span_diagnostic_ord;
109

@@ -416,7 +415,7 @@ pub fn run(config: &mut Config) -> CompilerResult<Option<AnalysisPassResult>> {
416415
"".to_owned(),
417416
&NoAnn,
418417
true,
419-
Edition::Edition2021,
418+
sess.edition(),
420419
&sess.psess.attr_id_generator,
421420
),
422421
);

mutest-emit/src/codegen/hygiene.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1620,7 +1620,7 @@ fn register_builtin_macros(syntax_extensions: &mut Vec<SyntaxExtension>) {
16201620
stability: None,
16211621
deprecation: None,
16221622
helper_attrs,
1623-
edition: Edition::Edition2021,
1623+
edition: Edition::Edition2024,
16241624
builtin_name: Some(name),
16251625
allow_internal_unsafe: false,
16261626
local_inner_macros: false,

tests/src/main.rs

Lines changed: 113 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![feature(if_let_guard)]
12
#![feature(iter_collect_into)]
23
#![feature(iter_intersperse)]
34
#![feature(let_chains)]
@@ -157,6 +158,22 @@ fn log_test(test_name: &str, result: TestResult, reason: Option<&str>) {
157158
);
158159
}
159160

161+
fn parse_directives(path: &Path) -> Vec<String> {
162+
let source = fs::File::open(path).expect(&format!("cannot open `{}`", path.display()));
163+
let mut reader = BufReader::with_capacity(1024, source);
164+
165+
let mut directives = vec![];
166+
let mut line = String::new();
167+
while reader.read_line(&mut line).expect(&format!("cannot read contents of `{}`", path.display())) >= 1 {
168+
if let Some(directive) = line.trim_start().strip_prefix("//@").map(str::trim) {
169+
directives.push(directive.to_owned());
170+
}
171+
line.clear();
172+
}
173+
174+
directives
175+
}
176+
160177
fn run_test(path: &Path, aux_dir_path: &Path, root_dir: &Path, opts: &Opts, results: &mut TestRunResults) {
161178
if !path.is_file() { return; }
162179
if !path.extension().is_some_and(|v| v == "rs") { return; }
@@ -192,96 +209,95 @@ fn run_test(path: &Path, aux_dir_path: &Path, root_dir: &Path, opts: &Opts, resu
192209
crate_name = &unmangled_crate_name[..unmangled_crate_name.floor_char_boundary(48)],
193210
);
194211

195-
let source = fs::File::open(&path).expect(&format!("cannot open `{}`", path.display()));
196-
let mut reader = BufReader::with_capacity(1024, source);
197-
198-
let mut directives = vec![];
199-
let mut line = String::new();
200-
while reader.read_line(&mut line).expect(&format!("cannot read contents of `{}`", path.display())) >= 1 {
201-
if let Some(directive) = line.trim_start().strip_prefix("//@").map(str::trim) {
202-
directives.push(directive.to_owned());
203-
}
204-
line.clear();
205-
}
212+
let directives = parse_directives(&path);
206213

207214
if directives.iter().any(|d| d == "ignore") {
208215
results.ignored_tests_count += 1;
209216
log_test(&name, TestResult::Ignored, None);
210217
return;
211218
}
212219

220+
let mut edition: Option<&str> = None;
213221
let mut expect_command_fail = false;
214222
let mut expectations = BTreeSet::new();
215223
let mut mutest_prints = BTreeSet::new();
216-
let mutest_subcommand = {
217-
let mut mutest_subcommand: Option<&str> = None;
218-
219-
for directive in &directives {
220-
match directive.as_str() {
221-
subcommand @ ("print-tests" | "print-call-graph" | "print-targets" | "print-mutants" | "print-code" | "build" | "run") => {
222-
if let Some(previous_subcommand) = mutest_subcommand && previous_subcommand != "print" {
223-
results.ignored_tests_count += 1;
224-
log_test(&name, TestResult::Ignored, Some("invalid directives"));
225-
return;
226-
}
227-
match subcommand {
228-
"run" => mutest_subcommand = Some("build"),
229-
"print-tests" => {
230-
mutest_prints.insert("tests");
231-
mutest_subcommand.get_or_insert("print");
232-
}
233-
"print-call-graph" => {
234-
mutest_prints.insert("call-graph");
235-
mutest_subcommand.get_or_insert("print");
236-
}
237-
"print-targets" => {
238-
mutest_prints.insert("targets");
239-
mutest_subcommand.get_or_insert("print");
240-
}
241-
"print-mutants" => {
242-
mutest_prints.insert("mutants");
243-
mutest_subcommand.get_or_insert("print");
244-
}
245-
"print-code" => {
246-
mutest_prints.insert("code");
247-
mutest_subcommand.get_or_insert("print");
248-
}
249-
subcommand => mutest_subcommand = Some(subcommand),
250-
};
224+
let mut mutest_subcommand: Option<&str> = None;
225+
for directive in &directives {
226+
match directive.as_str() {
227+
subcommand @ ("print-tests" | "print-call-graph" | "print-targets" | "print-mutants" | "print-code" | "build" | "run") => {
228+
if let Some(previous_subcommand) = mutest_subcommand && previous_subcommand != "print" {
229+
results.ignored_tests_count += 1;
230+
log_test(&name, TestResult::Ignored, Some("invalid directives"));
231+
return;
251232
}
252-
253-
"fail" => {
254-
if let Some(_previous_subcommand) = mutest_subcommand {
255-
results.ignored_tests_count += 1;
256-
log_test(&name, TestResult::Ignored, Some("invalid directives"));
257-
return;
233+
match subcommand {
234+
"run" => mutest_subcommand = Some("build"),
235+
"print-tests" => {
236+
mutest_prints.insert("tests");
237+
mutest_subcommand.get_or_insert("print");
258238
}
259-
expect_command_fail = true;
260-
mutest_subcommand = Some("build");
261-
}
262-
263-
"stdout" => { expectations.insert(Expectation::StdOut { empty: false }); }
264-
"stdout: empty" => { expectations.insert(Expectation::StdOut { empty: true }); }
265-
"stderr" => { expectations.insert(Expectation::StdErr { empty: false }); }
266-
"stderr: empty" => { expectations.insert(Expectation::StdErr { empty: true }); }
239+
"print-call-graph" => {
240+
mutest_prints.insert("call-graph");
241+
mutest_subcommand.get_or_insert("print");
242+
}
243+
"print-targets" => {
244+
mutest_prints.insert("targets");
245+
mutest_subcommand.get_or_insert("print");
246+
}
247+
"print-mutants" => {
248+
mutest_prints.insert("mutants");
249+
mutest_subcommand.get_or_insert("print");
250+
}
251+
"print-code" => {
252+
mutest_prints.insert("code");
253+
mutest_subcommand.get_or_insert("print");
254+
}
255+
subcommand => mutest_subcommand = Some(subcommand),
256+
};
257+
}
267258

268-
_ if directive.starts_with("aux-build:") => {}
269-
_ if directive.starts_with("rustc-flags:") => {}
270-
_ if directive.starts_with("verify:") => {}
271-
_ if directive.starts_with("mutation-operators:") => {}
272-
_ if directive.starts_with("mutest-flags:") => {}
273-
_ if directive.starts_with("mutest-subcommand-flags:") => {}
259+
"fail" => {
260+
if let Some(_previous_subcommand) = mutest_subcommand {
261+
results.ignored_tests_count += 1;
262+
log_test(&name, TestResult::Ignored, Some("invalid directives"));
263+
return;
264+
}
265+
expect_command_fail = true;
266+
mutest_subcommand = Some("build");
267+
}
274268

275-
_ => {
269+
_ if let Some(edition_str) = directive.strip_prefix("edition:").map(str::trim) => {
270+
if let Some(_previous_edition) = edition {
276271
results.ignored_tests_count += 1;
277-
log_test(&name, TestResult::Ignored, Some(&format!("unknown directive: `{directive}`")));
272+
log_test(&name, TestResult::Ignored, Some("invalid directives: multiple editions"));
278273
return;
279274
}
275+
edition = Some(edition_str);
276+
}
277+
278+
"stdout" => { expectations.insert(Expectation::StdOut { empty: false }); }
279+
"stdout: empty" => { expectations.insert(Expectation::StdOut { empty: true }); }
280+
"stderr" => { expectations.insert(Expectation::StdErr { empty: false }); }
281+
"stderr: empty" => { expectations.insert(Expectation::StdErr { empty: true }); }
282+
283+
_ if directive.starts_with("aux-build:") => {}
284+
_ if directive.starts_with("rustc-flags:") => {}
285+
_ if directive.starts_with("verify:") => {}
286+
_ if directive.starts_with("mutation-operators:") => {}
287+
_ if directive.starts_with("mutest-flags:") => {}
288+
_ if directive.starts_with("mutest-subcommand-flags:") => {}
289+
290+
_ => {
291+
results.ignored_tests_count += 1;
292+
log_test(&name, TestResult::Ignored, Some(&format!("unknown directive: `{directive}`")));
293+
return;
280294
}
281295
}
296+
}
282297

283-
mutest_subcommand.unwrap_or("build")
284-
};
298+
// Set defaults.
299+
let edition = edition.unwrap_or("2018");
300+
let mutest_subcommand = mutest_subcommand.unwrap_or("build");
285301

286302
// HACK: We invoke mutest-driver directly, rather than through Cargo, which means
287303
// we have to add `windows.lib` to the linker search path manually.
@@ -308,13 +324,38 @@ fn run_test(path: &Path, aux_dir_path: &Path, root_dir: &Path, opts: &Opts, resu
308324
let aux_path = aux_dir_path.join(aux_build);
309325
let aux_crate_name = Path::new(aux_build).file_stem().expect("invalid aux path").to_str().expect("invalid aux path");
310326

327+
let aux_directives = parse_directives(&aux_path);
328+
329+
let mut edition = None;
330+
for aux_directive in &aux_directives {
331+
match aux_directive.as_str() {
332+
_ if let Some(edition_str) = directive.strip_prefix("edition:").map(str::trim) => {
333+
if let Some(_previous_edition) = edition {
334+
results.ignored_tests_count += 1;
335+
log_test(&name, TestResult::Ignored, Some("invalid directives: multiple editions"));
336+
return;
337+
}
338+
edition = Some(edition_str);
339+
}
340+
341+
_ => {
342+
results.ignored_tests_count += 1;
343+
log_test(&name, TestResult::Ignored, Some(&format!("unknown directive: `{directive}`")));
344+
return;
345+
}
346+
}
347+
}
348+
349+
// Set defaults.
350+
let edition = edition.unwrap_or("2018");
351+
311352
let mut cmd = Command::new("target/release/mutest-driver");
312353
// We need to invoke mutest-driver as a rustc wrapper. This must be the first argument.
313354
cmd.arg("/dummy/rustc");
314355

315356
cmd.arg(&aux_path);
316357
cmd.args(["--crate-name", aux_crate_name]);
317-
cmd.arg("--edition=2021");
358+
cmd.arg(format!("--edition={edition}"));
318359

319360
cmd.args(["--out-dir", AUX_OUT_DIR]);
320361

@@ -356,7 +397,7 @@ fn run_test(path: &Path, aux_dir_path: &Path, root_dir: &Path, opts: &Opts, resu
356397

357398
cmd.arg(&path);
358399
cmd.args(["--crate-name".to_owned(), test_crate_name]);
359-
cmd.arg("--edition=2021");
400+
cmd.arg(format!("--edition={edition}"));
360401

361402
cmd.args(["--crate-type", "lib"]);
362403

tests/ui/call_graph/use_reveal_all_param_env_for_instance_resolution.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//@ print-call-graph
22
//@ stderr: empty
3+
//@ edition: 2021
34

45
//! Since we are performing monomorphising call graph construction after type checking,
56
//! we do so by querying monomorphic obligations.

0 commit comments

Comments
 (0)