Auto merge of #81889 - m-ou-se:rollup-k63log3, r=m-ou-se

Rollup of 9 pull requests

Successful merges:

 - #71531 (Move treat err as bug tests to ui)
 - #81356 (libtest: allow multiple filters)
 - #81735 (faster few span methods)
 - #81779 (improve error message for disallowed ptr-to-int casts in const eval)
 - #81817 (Add option to emit compiler stderr per bitwidth.)
 - #81828 (parse_format: treat r" as a literal)
 - #81840 (fix formatting of std::iter::Map)
 - #81861 (Show MIR bytes separately in -Zmeta-stats output)
 - #81865 (Clean up weird Option mapping)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-02-08 20:52:54 +00:00
commit 0fc6756b42
35 changed files with 205 additions and 73 deletions

View File

@ -572,10 +572,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let tcx = self.tcx;
// Encode MIR.
i = self.position();
self.encode_mir();
let mir_bytes = self.position() - i;
// Encode the items.
i = self.position();
self.encode_def_ids();
self.encode_mir();
self.encode_info_for_items();
let item_bytes = self.position() - i;
@ -700,6 +704,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
println!(" exp. symbols bytes: {}", exported_symbols_bytes);
println!(" def-path table bytes: {}", def_path_table_bytes);
println!(" proc-macro-data-bytes: {}", proc_macro_data_bytes);
println!(" mir bytes: {}", mir_bytes);
println!(" item bytes: {}", item_bytes);
println!(" table bytes: {}", tables_bytes);
println!(" hygiene bytes: {}", hygiene_bytes);

View File

@ -16,6 +16,7 @@ use crate::interpret::{
#[derive(Clone, Debug)]
pub enum ConstEvalErrKind {
NeedsRfc(String),
PtrToIntCast,
ConstAccessesStatic,
ModifiedGlobal,
AssertFailure(AssertKind<ConstInt>),
@ -39,6 +40,12 @@ impl fmt::Display for ConstEvalErrKind {
NeedsRfc(ref msg) => {
write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg)
}
PtrToIntCast => {
write!(
f,
"cannot cast pointer to integer because it was not created by cast from integer"
)
}
ConstAccessesStatic => write!(f, "constant accesses static"),
ModifiedGlobal => {
write!(f, "modifying a static's initial value from another static's initializer")

View File

@ -352,7 +352,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}
fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> {
Err(ConstEvalErrKind::NeedsRfc("pointer-to-integer cast".to_string()).into())
Err(ConstEvalErrKind::PtrToIntCast.into())
}
fn binary_ptr_op(

View File

@ -730,7 +730,7 @@ fn find_skips_from_snippet(
str_style: Option<usize>,
) -> (Vec<usize>, bool) {
let snippet = match snippet {
Some(ref s) if s.starts_with('"') || s.starts_with("r#") => s,
Some(ref s) if s.starts_with('"') || s.starts_with("r\"") || s.starts_with("r#") => s,
_ => return (vec![], false),
};

View File

@ -22,6 +22,7 @@
#![feature(nll)]
#![feature(min_specialization)]
#![feature(option_expect_none)]
#![feature(str_split_once)]
#[macro_use]
extern crate rustc_macros;

View File

@ -539,7 +539,7 @@ impl SourceMap {
pub fn is_line_before_span_empty(&self, sp: Span) -> bool {
match self.span_to_prev_source(sp) {
Ok(s) => s.split('\n').last().map_or(false, |l| l.trim_start().is_empty()),
Ok(s) => s.rsplit_once('\n').unwrap_or(("", &s)).1.trim_start().is_empty(),
Err(_) => false,
}
}
@ -632,10 +632,11 @@ impl SourceMap {
pub fn span_to_margin(&self, sp: Span) -> Option<usize> {
match self.span_to_prev_source(sp) {
Err(_) => None,
Ok(source) => source
.split('\n')
.last()
.map(|last_line| last_line.len() - last_line.trim_start().len()),
Ok(source) => {
let last_line = source.rsplit_once('\n').unwrap_or(("", &source)).1;
Some(last_line.len() - last_line.trim_start().len())
}
}
}
@ -651,7 +652,7 @@ impl SourceMap {
pub fn span_extend_to_prev_char(&self, sp: Span, c: char, accept_newlines: bool) -> Span {
if let Ok(prev_source) = self.span_to_prev_source(sp) {
let prev_source = prev_source.rsplit(c).next().unwrap_or("");
if !prev_source.is_empty() && (!prev_source.contains('\n') || accept_newlines) {
if !prev_source.is_empty() && (accept_newlines || !prev_source.contains('\n')) {
return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32));
}
}
@ -673,7 +674,7 @@ impl SourceMap {
let prev_source = prev_source.rsplit(&pat).next().unwrap_or("").trim_start();
if prev_source.is_empty() && sp.lo().0 != 0 {
return sp.with_lo(BytePos(sp.lo().0 - 1));
} else if !prev_source.contains('\n') || accept_newlines {
} else if accept_newlines || !prev_source.contains('\n') {
return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32));
}
}
@ -693,7 +694,7 @@ impl SourceMap {
pub fn span_extend_to_next_char(&self, sp: Span, c: char, accept_newlines: bool) -> Span {
if let Ok(next_source) = self.span_to_next_source(sp) {
let next_source = next_source.split(c).next().unwrap_or("");
if !next_source.is_empty() && (!next_source.contains('\n') || accept_newlines) {
if !next_source.is_empty() && (accept_newlines || !next_source.contains('\n')) {
return sp.with_hi(BytePos(sp.hi().0 + next_source.len() as u32));
}
}

View File

@ -285,13 +285,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_expr_eq_type(&e, ty);
ty
}
ExprKind::If(ref cond, ref then_expr, ref opt_else_expr) => self.check_then_else(
&cond,
then_expr,
opt_else_expr.as_ref().map(|e| &**e),
expr.span,
expected,
),
ExprKind::If(cond, then_expr, opt_else_expr) => {
self.check_then_else(cond, then_expr, opt_else_expr, expr.span, expected)
}
ExprKind::DropTemps(ref e) => self.check_expr_with_expectation(e, expected),
ExprKind::Array(ref args) => self.check_expr_array(args, expected, expr),
ExprKind::ConstBlock(ref anon_const) => self.to_const(anon_const).ty,

View File

@ -60,6 +60,7 @@ pub struct Map<I, F> {
iter: I,
f: F,
}
impl<I, F> Map<I, F> {
pub(in crate::iter) fn new(iter: I, f: F) -> Map<I, F> {
Map { iter, f }

View File

@ -10,7 +10,7 @@ use super::time::TestTimeOptions;
#[derive(Debug)]
pub struct TestOpts {
pub list: bool,
pub filter: Option<String>,
pub filters: Vec<String>,
pub filter_exact: bool,
pub force_run_in_process: bool,
pub exclude_should_panic: bool,
@ -148,12 +148,13 @@ fn optgroups() -> getopts::Options {
}
fn usage(binary: &str, options: &getopts::Options) {
let message = format!("Usage: {} [OPTIONS] [FILTER]", binary);
let message = format!("Usage: {} [OPTIONS] [FILTERS...]", binary);
println!(
r#"{usage}
The FILTER string is tested against the name of all tests, and only those
tests whose names contain the filter are run.
tests whose names contain the filter are run. Multiple filter strings may
be passed, which will run all tests matching any of the filters.
By default, all tests are run in parallel. This can be altered with the
--test-threads flag or the RUST_TEST_THREADS environment variable when running
@ -243,7 +244,7 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes {
let logfile = get_log_file(&matches)?;
let run_ignored = get_run_ignored(&matches, include_ignored)?;
let filter = get_filter(&matches)?;
let filters = matches.free.clone();
let nocapture = get_nocapture(&matches)?;
let test_threads = get_test_threads(&matches)?;
let color = get_color_config(&matches)?;
@ -253,7 +254,7 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes {
let test_opts = TestOpts {
list,
filter,
filters,
filter_exact: exact,
force_run_in_process,
exclude_should_panic,
@ -397,12 +398,6 @@ fn get_run_ignored(matches: &getopts::Matches, include_ignored: bool) -> OptPart
Ok(run_ignored)
}
fn get_filter(matches: &getopts::Matches) -> OptPartRes<Option<String>> {
let filter = if !matches.free.is_empty() { Some(matches.free[0].clone()) } else { None };
Ok(filter)
}
fn get_allow_unstable(matches: &getopts::Matches) -> OptPartRes<bool> {
let mut allow_unstable = false;

View File

@ -396,8 +396,8 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
};
// Remove tests that don't match the test filter
if let Some(ref filter) = opts.filter {
filtered.retain(|test| matches_filter(test, filter));
if !opts.filters.is_empty() {
filtered.retain(|test| opts.filters.iter().any(|filter| matches_filter(test, filter)));
}
// Skip tests that match any of the skip filters

View File

@ -34,7 +34,7 @@ impl TestOpts {
fn new() -> TestOpts {
TestOpts {
list: false,
filter: None,
filters: vec![],
filter_exact: false,
force_run_in_process: false,
exclude_should_panic: false,
@ -473,43 +473,60 @@ pub fn exact_filter_match() {
}
let substr =
filter_tests(&TestOpts { filter: Some("base".into()), ..TestOpts::new() }, tests());
assert_eq!(substr.len(), 4);
let substr = filter_tests(&TestOpts { filter: Some("bas".into()), ..TestOpts::new() }, tests());
filter_tests(&TestOpts { filters: vec!["base".into()], ..TestOpts::new() }, tests());
assert_eq!(substr.len(), 4);
let substr =
filter_tests(&TestOpts { filter: Some("::test".into()), ..TestOpts::new() }, tests());
filter_tests(&TestOpts { filters: vec!["bas".into()], ..TestOpts::new() }, tests());
assert_eq!(substr.len(), 4);
let substr =
filter_tests(&TestOpts { filters: vec!["::test".into()], ..TestOpts::new() }, tests());
assert_eq!(substr.len(), 3);
let substr =
filter_tests(&TestOpts { filter: Some("base::test".into()), ..TestOpts::new() }, tests());
filter_tests(&TestOpts { filters: vec!["base::test".into()], ..TestOpts::new() }, tests());
assert_eq!(substr.len(), 3);
let substr = filter_tests(
&TestOpts { filters: vec!["test1".into(), "test2".into()], ..TestOpts::new() },
tests(),
);
assert_eq!(substr.len(), 2);
let exact = filter_tests(
&TestOpts { filter: Some("base".into()), filter_exact: true, ..TestOpts::new() },
&TestOpts { filters: vec!["base".into()], filter_exact: true, ..TestOpts::new() },
tests(),
);
assert_eq!(exact.len(), 1);
let exact = filter_tests(
&TestOpts { filter: Some("bas".into()), filter_exact: true, ..TestOpts::new() },
&TestOpts { filters: vec!["bas".into()], filter_exact: true, ..TestOpts::new() },
tests(),
);
assert_eq!(exact.len(), 0);
let exact = filter_tests(
&TestOpts { filter: Some("::test".into()), filter_exact: true, ..TestOpts::new() },
&TestOpts { filters: vec!["::test".into()], filter_exact: true, ..TestOpts::new() },
tests(),
);
assert_eq!(exact.len(), 0);
let exact = filter_tests(
&TestOpts { filter: Some("base::test".into()), filter_exact: true, ..TestOpts::new() },
&TestOpts { filters: vec!["base::test".into()], filter_exact: true, ..TestOpts::new() },
tests(),
);
assert_eq!(exact.len(), 1);
let exact = filter_tests(
&TestOpts {
filters: vec!["base".into(), "base::test".into()],
filter_exact: true,
..TestOpts::new()
},
tests(),
);
assert_eq!(exact.len(), 2);
}
#[test]

View File

@ -1,7 +0,0 @@
-include ../tools.mk
all:
$(RUSTC) err.rs -Z treat-err-as-bug 2>&1 \
| $(CGREP) "panicked at 'aborting due to \`-Z treat-err-as-bug=1\`'"
$(RUSTC) delay_span_bug.rs -Z treat-err-as-bug 2>&1 \
| $(CGREP) "panicked at 'aborting due to \`-Z treat-err-as-bug=1\`'"

View File

@ -1,4 +0,0 @@
#![feature(rustc_attrs)]
#[rustc_error(delay_span_bug_from_inside_query)]
fn main() {}

View File

@ -1,3 +0,0 @@
#![crate_type="rlib"]
pub static C: u32 = 0-1;

View File

@ -0,0 +1,13 @@
#![feature(const_raw_ptr_to_usize_cast)]
fn main() {
const OK: usize = unsafe { 0 as *const i32 as usize };
const _ERROR: usize = unsafe { &0 as *const i32 as usize };
//~^ ERROR [const_err]
//~| NOTE cannot cast pointer to integer because it was not created by cast from integer
//~| NOTE
//~| NOTE `#[deny(const_err)]` on by default
//~| WARN this was previously accepted by the compiler but is being phased out
//~| NOTE see issue #71800
}

View File

@ -0,0 +1,14 @@
error: any use of this value will cause an error
--> $DIR/ptr_to_usize_cast.rs:6:36
|
LL | const _ERROR: usize = unsafe { &0 as *const i32 as usize };
| -------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^---
| |
| cannot cast pointer to integer because it was not created by cast from integer
|
= note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to previous error

View File

@ -4,7 +4,7 @@ error: any use of this value will cause an error
LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 };
| ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^-------
| |
| "pointer-to-integer cast" needs an rfc before being allowed inside constants
| cannot cast pointer to integer because it was not created by cast from integer
|
= note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

View File

@ -4,7 +4,7 @@ error: any use of this value will cause an error
LL | pub const FOO: usize = unsafe { BAR as usize };
| --------------------------------^^^^^^^^^^^^---
| |
| "pointer-to-integer cast" needs an rfc before being allowed inside constants
| cannot cast pointer to integer because it was not created by cast from integer
|
= note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

View File

@ -20,7 +20,7 @@ error[E0080]: evaluation of constant value failed
--> $DIR/issue-52432.rs:7:10
|
LL | [(); &(static || {}) as *const _ as usize];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot cast pointer to integer because it was not created by cast from integer
error: aborting due to 4 previous errors

View File

@ -15,7 +15,7 @@ static INT_PTR_ARITH: () = unsafe {
let x: usize = std::mem::transmute(&0);
let _v = x + 0;
//~^ ERROR could not evaluate static initializer
//~| NOTE pointer-to-integer cast
//~| NOTE cannot cast pointer to integer
};
fn main() {}

View File

@ -8,7 +8,7 @@ error[E0080]: could not evaluate static initializer
--> $DIR/ptr_arith.rs:16:14
|
LL | let _v = x + 0;
| ^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants
| ^^^^^ cannot cast pointer to integer because it was not created by cast from integer
warning: skipping const checks
|

View File

@ -71,14 +71,14 @@ const _: *const u8 =
const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
//~^ ERROR any use of this value will cause an error
//~| NOTE "pointer-to-integer cast" needs an rfc
//~| NOTE cannot cast pointer to integer
//~| NOTE
//~| WARN this was previously accepted by the compiler but is being phased out
//~| NOTE
const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
//~^ ERROR any use of this value will cause an error
//~| NOTE "pointer-to-integer cast" needs an rfc
//~| NOTE cannot cast pointer to integer
//~| NOTE
//~| WARN this was previously accepted by the compiler but is being phased out
//~| NOTE

View File

@ -36,7 +36,7 @@ error: any use of this value will cause an error
LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
| --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
| |
| "pointer-to-integer cast" needs an rfc before being allowed inside constants
| cannot cast pointer to integer because it was not created by cast from integer
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
@ -47,7 +47,7 @@ error: any use of this value will cause an error
LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
| --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
| |
| "pointer-to-integer cast" needs an rfc before being allowed inside constants
| cannot cast pointer to integer because it was not created by cast from integer
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>

View File

@ -5,6 +5,7 @@
fn main() {
named_argument_takes_precedence_to_captured();
formatting_parameters_can_be_captured();
capture_raw_strings_and_idents();
#[cfg(panic = "unwind")]
{
@ -25,6 +26,16 @@ fn named_argument_takes_precedence_to_captured() {
assert_eq!(&s, "positional-named-captured");
}
fn capture_raw_strings_and_idents() {
let r#type = "apple";
let s = format!(r#"The fruit is an {type}"#);
assert_eq!(&s, "The fruit is an apple");
let r#type = "orange";
let s = format!(r"The fruit is an {type}");
assert_eq!(&s, "The fruit is an orange");
}
#[cfg(panic = "unwind")]
fn panic_with_single_argument_does_not_get_formatted() {
// panic! with a single argument does not perform string formatting.

View File

@ -1,8 +1,8 @@
error: invalid reference to positional arguments 1 and 2 (there is 1 argument)
--> $DIR/issue-75307.rs:2:13
--> $DIR/issue-75307.rs:2:17
|
LL | format!(r"{}{}{}", named_arg=1);
| ^^^^^^^^^
| ^^^^
|
= note: positional arguments are zero-based

View File

@ -0,0 +1,17 @@
// run-pass
// compile-flags: --test
// run-flags: --test-threads=1 test1 test2
// check-run-results
// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
// ignore-emscripten no threads support
#[test]
fn test1() {}
#[test]
fn test2() {}
#[test]
fn test3() {
panic!("this should not run");
}

View File

@ -0,0 +1,7 @@
running 2 tests
test test1 ... ok
test test2 ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in $TIME

View File

@ -0,0 +1,11 @@
// compile-flags: -Ztreat-err-as-bug
// failure-status: 101
// error-pattern: aborting due to `-Z treat-err-as-bug=1`
// error-pattern: [trigger_delay_span_bug] trigger a delay span bug
// normalize-stderr-test "note: .*\n\n" -> ""
// normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
#![feature(rustc_attrs)]
#[rustc_error(delay_span_bug_from_inside_query)]
fn main() {}

View File

@ -0,0 +1,11 @@
error: internal compiler error: delayed span bug triggered by #[rustc_error(delay_span_bug_from_inside_query)]
--> $DIR/delay_span_bug.rs:11:1
|
LL | fn main() {}
| ^^^^^^^^^
error: internal compiler error: unexpected panic
query stack during panic:
#0 [trigger_delay_span_bug] trigger a delay span bug
end of query stack

View File

@ -0,0 +1,11 @@
// compile-flags: -Ztreat-err-as-bug
// failure-status: 101
// error-pattern: aborting due to `-Z treat-err-as-bug=1`
// error-pattern: [eval_to_allocation_raw] const-evaluating + checking `C`
// normalize-stderr-test "note: .*\n\n" -> ""
// normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
#![crate_type = "rlib"]
pub static C: u32 = 0 - 1;
//~^ ERROR could not evaluate static initializer

View File

@ -0,0 +1,12 @@
error[E0080]: could not evaluate static initializer
--> $DIR/err.rs:10:21
|
LL | pub static C: u32 = 0 - 1;
| ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
error: internal compiler error: unexpected panic
query stack during panic:
#0 [eval_to_allocation_raw] const-evaluating + checking `C`
#1 [eval_to_allocation_raw] const-evaluating + checking `C`
end of query stack

View File

@ -240,8 +240,8 @@ pub struct Config {
/// Run ignored tests
pub run_ignored: bool,
/// Only run tests that match this filter
pub filter: Option<String>,
/// Only run tests that match these filters
pub filters: Vec<String>,
/// Exactly match the filter, rather than a substring
pub filter_exact: bool,

View File

@ -333,6 +333,8 @@ pub struct TestProps {
pub assembly_output: Option<String>,
// If true, the test is expected to ICE
pub should_ice: bool,
// If true, the stderr is expected to be different across bit-widths.
pub stderr_per_bitwidth: bool,
}
impl TestProps {
@ -372,6 +374,7 @@ impl TestProps {
rustfix_only_machine_applicable: false,
assembly_output: None,
should_ice: false,
stderr_per_bitwidth: false,
}
}
@ -538,6 +541,10 @@ impl TestProps {
if self.assembly_output.is_none() {
self.assembly_output = config.parse_assembly_output(ln);
}
if !self.stderr_per_bitwidth {
self.stderr_per_bitwidth = config.parse_stderr_per_bitwidth(ln);
}
});
}
@ -774,6 +781,10 @@ impl Config {
self.parse_name_directive(line, "ignore-pass")
}
fn parse_stderr_per_bitwidth(&self, line: &str) -> bool {
self.parse_name_directive(line, "stderr-per-bitwidth")
}
fn parse_assembly_output(&self, line: &str) -> Option<String> {
self.parse_name_value_directive(line, "assembly-output").map(|r| r.trim().to_string())
}

View File

@ -221,7 +221,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
suite: matches.opt_str("suite").unwrap(),
debugger: None,
run_ignored,
filter: matches.free.first().cloned(),
filters: matches.free.clone(),
filter_exact: matches.opt_present("exact"),
force_pass_mode: matches.opt_str("pass").map(|mode| {
mode.parse::<PassMode>()
@ -280,7 +280,7 @@ pub fn log_config(config: &Config) {
logv(c, format!("stage_id: {}", config.stage_id));
logv(c, format!("mode: {}", config.mode));
logv(c, format!("run_ignored: {}", config.run_ignored));
logv(c, format!("filter: {}", opt_str(&config.filter)));
logv(c, format!("filters: {:?}", config.filters));
logv(c, format!("filter_exact: {}", config.filter_exact));
logv(
c,
@ -465,7 +465,7 @@ fn configure_lldb(config: &Config) -> Option<Config> {
pub fn test_opts(config: &Config) -> test::TestOpts {
test::TestOpts {
exclude_should_panic: false,
filter: config.filter.clone(),
filters: config.filters.clone(),
filter_exact: config.filter_exact,
run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No },
format: if config.quiet { test::OutputFormat::Terse } else { test::OutputFormat::Pretty },

View File

@ -3124,7 +3124,12 @@ impl<'test> TestCx<'test> {
errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout);
}
if !self.props.dont_check_compiler_stderr {
errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr);
let kind = if self.props.stderr_per_bitwidth {
format!("{}bit.stderr", get_pointer_width(&self.config.target))
} else {
String::from("stderr")
};
errors += self.compare_output(&kind, &normalized_stderr, &expected_stderr);
}
}
TestOutput::Run => {