Auto merge of #108905 - ferrocene:pa-compiletest-ignore, r=ehuss

Validate `ignore` and `only` compiletest directive, and add human-readable ignore reasons

This PR adds strict validation for the `ignore` and `only` compiletest directives, failing if an unknown value is provided to them. Doing so uncovered 79 tests in `tests/ui` that had invalid directives, so this PR also fixes them.

Finally, this PR adds human-readable ignore reasons when tests are ignored due to `ignore` or `only` directives, like *"only executed when the architecture is aarch64"* or *"ignored when the operative system is windows"*. This was the original reason why I started working on this PR and #108659, as we need both of them for Ferrocene.

The PR is a draft because the code is extremely inefficient: it calls `rustc --print=cfg --target $target` for every rustc target (to gather the list of allowed ignore values), which on my system takes between 4s and 5s, and performs a lot of allocations of constant values. I'll fix both of them in the coming days.

r? `@ehuss`
This commit is contained in:
bors 2023-04-05 16:15:25 +00:00
commit b2b676d886
75 changed files with 722 additions and 508 deletions

View File

@ -44,8 +44,10 @@ use rustc_session::{early_error, early_error_no_abort, early_warn};
use rustc_span::source_map::{FileLoader, FileName};
use rustc_span::symbol::sym;
use rustc_target::json::ToJson;
use rustc_target::spec::{Target, TargetTriple};
use std::cmp::max;
use std::collections::BTreeMap;
use std::env;
use std::ffi::OsString;
use std::fs;
@ -648,6 +650,15 @@ fn print_crate_info(
TargetSpec => {
println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
}
AllTargetSpecs => {
let mut targets = BTreeMap::new();
for name in rustc_target::spec::TARGETS {
let triple = TargetTriple::from_triple(name);
let target = Target::expect_builtin(&triple);
targets.insert(name, target.to_json());
}
println!("{}", serde_json::to_string_pretty(&targets).unwrap());
}
FileNames | CrateName => {
let Some(attrs) = attrs.as_ref() else {
// no crate attributes, print out an error and exit

View File

@ -582,6 +582,7 @@ pub enum PrintRequest {
CodeModels,
TlsModels,
TargetSpec,
AllTargetSpecs,
NativeStaticLibs,
StackProtectorStrategies,
LinkArgs,
@ -1441,8 +1442,8 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
"Compiler information to print on stdout",
"[crate-name|file-names|sysroot|target-libdir|cfg|calling-conventions|\
target-list|target-cpus|target-features|relocation-models|code-models|\
tls-models|target-spec-json|native-static-libs|stack-protector-strategies|\
link-args]",
tls-models|target-spec-json|all-target-specs-json|native-static-libs|\
stack-protector-strategies|link-args]",
),
opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"),
opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
@ -1889,6 +1890,7 @@ fn collect_print_requests(
("native-static-libs", PrintRequest::NativeStaticLibs),
("stack-protector-strategies", PrintRequest::StackProtectorStrategies),
("target-spec-json", PrintRequest::TargetSpec),
("all-target-specs-json", PrintRequest::AllTargetSpecs),
("link-args", PrintRequest::LinkArgs),
("split-debuginfo", PrintRequest::SplitDebuginfo),
];
@ -1902,7 +1904,18 @@ fn collect_print_requests(
early_error(
error_format,
"the `-Z unstable-options` flag must also be passed to \
enable the target-spec-json print option",
enable the target-spec-json print option",
);
}
}
Some((_, PrintRequest::AllTargetSpecs)) => {
if unstable_opts.unstable_options {
PrintRequest::AllTargetSpecs
} else {
early_error(
error_format,
"the `-Z unstable-options` flag must also be passed to \
enable the all-target-specs-json print option",
);
}
}

View File

@ -694,7 +694,7 @@ impl Step for CompiletestTest {
/// Runs `cargo test` for compiletest.
fn run(self, builder: &Builder<'_>) {
let host = self.host;
let compiler = builder.compiler(0, host);
let compiler = builder.compiler(1, host);
// We need `ToolStd` for the locally-built sysroot because
// compiletest uses unstable features of the `test` crate.

View File

@ -8,24 +8,65 @@ use std::process::Command;
use std::str::FromStr;
use crate::util::{add_dylib_path, PathBufExt};
use lazycell::LazyCell;
use lazycell::AtomicLazyCell;
use serde::de::{Deserialize, Deserializer, Error as _};
use std::collections::{HashMap, HashSet};
use test::{ColorConfig, OutputFormat};
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Mode {
RunPassValgrind,
Pretty,
DebugInfo,
Codegen,
Rustdoc,
RustdocJson,
CodegenUnits,
Incremental,
RunMake,
Ui,
JsDocTest,
MirOpt,
Assembly,
macro_rules! string_enum {
($(#[$meta:meta])* $vis:vis enum $name:ident { $($variant:ident => $repr:expr,)* }) => {
$(#[$meta])*
$vis enum $name {
$($variant,)*
}
impl $name {
$vis const VARIANTS: &'static [Self] = &[$(Self::$variant,)*];
$vis const STR_VARIANTS: &'static [&'static str] = &[$(Self::$variant.to_str(),)*];
$vis const fn to_str(&self) -> &'static str {
match self {
$(Self::$variant => $repr,)*
}
}
}
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.to_str(), f)
}
}
impl FromStr for $name {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
match s {
$($repr => Ok(Self::$variant),)*
_ => Err(()),
}
}
}
}
}
string_enum! {
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Mode {
RunPassValgrind => "run-pass-valgrind",
Pretty => "pretty",
DebugInfo => "debuginfo",
Codegen => "codegen",
Rustdoc => "rustdoc",
RustdocJson => "rustdoc-json",
CodegenUnits => "codegen-units",
Incremental => "incremental",
RunMake => "run-make",
Ui => "ui",
JsDocTest => "js-doc-test",
MirOpt => "mir-opt",
Assembly => "assembly",
}
}
impl Mode {
@ -39,76 +80,12 @@ impl Mode {
}
}
impl FromStr for Mode {
type Err = ();
fn from_str(s: &str) -> Result<Mode, ()> {
match s {
"run-pass-valgrind" => Ok(RunPassValgrind),
"pretty" => Ok(Pretty),
"debuginfo" => Ok(DebugInfo),
"codegen" => Ok(Codegen),
"rustdoc" => Ok(Rustdoc),
"rustdoc-json" => Ok(RustdocJson),
"codegen-units" => Ok(CodegenUnits),
"incremental" => Ok(Incremental),
"run-make" => Ok(RunMake),
"ui" => Ok(Ui),
"js-doc-test" => Ok(JsDocTest),
"mir-opt" => Ok(MirOpt),
"assembly" => Ok(Assembly),
_ => Err(()),
}
}
}
impl fmt::Display for Mode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match *self {
RunPassValgrind => "run-pass-valgrind",
Pretty => "pretty",
DebugInfo => "debuginfo",
Codegen => "codegen",
Rustdoc => "rustdoc",
RustdocJson => "rustdoc-json",
CodegenUnits => "codegen-units",
Incremental => "incremental",
RunMake => "run-make",
Ui => "ui",
JsDocTest => "js-doc-test",
MirOpt => "mir-opt",
Assembly => "assembly",
};
fmt::Display::fmt(s, f)
}
}
#[derive(Clone, Copy, PartialEq, Debug, Hash)]
pub enum PassMode {
Check,
Build,
Run,
}
impl FromStr for PassMode {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
match s {
"check" => Ok(PassMode::Check),
"build" => Ok(PassMode::Build),
"run" => Ok(PassMode::Run),
_ => Err(()),
}
}
}
impl fmt::Display for PassMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match *self {
PassMode::Check => "check",
PassMode::Build => "build",
PassMode::Run => "run",
};
fmt::Display::fmt(s, f)
string_enum! {
#[derive(Clone, Copy, PartialEq, Debug, Hash)]
pub enum PassMode {
Check => "check",
Build => "build",
Run => "run",
}
}
@ -119,63 +96,30 @@ pub enum FailMode {
Run,
}
#[derive(Clone, Debug, PartialEq)]
pub enum CompareMode {
Polonius,
Chalk,
NextSolver,
SplitDwarf,
SplitDwarfSingle,
}
impl CompareMode {
pub(crate) fn to_str(&self) -> &'static str {
match *self {
CompareMode::Polonius => "polonius",
CompareMode::Chalk => "chalk",
CompareMode::NextSolver => "next-solver",
CompareMode::SplitDwarf => "split-dwarf",
CompareMode::SplitDwarfSingle => "split-dwarf-single",
}
}
pub fn parse(s: String) -> CompareMode {
match s.as_str() {
"polonius" => CompareMode::Polonius,
"chalk" => CompareMode::Chalk,
"next-solver" => CompareMode::NextSolver,
"split-dwarf" => CompareMode::SplitDwarf,
"split-dwarf-single" => CompareMode::SplitDwarfSingle,
x => panic!("unknown --compare-mode option: {}", x),
}
string_enum! {
#[derive(Clone, Debug, PartialEq)]
pub enum CompareMode {
Polonius => "polonius",
Chalk => "chalk",
NextSolver => "next-solver",
SplitDwarf => "split-dwarf",
SplitDwarfSingle => "split-dwarf-single",
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Debugger {
Cdb,
Gdb,
Lldb,
}
impl Debugger {
fn to_str(&self) -> &'static str {
match self {
Debugger::Cdb => "cdb",
Debugger::Gdb => "gdb",
Debugger::Lldb => "lldb",
}
string_enum! {
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Debugger {
Cdb => "cdb",
Gdb => "gdb",
Lldb => "lldb",
}
}
impl fmt::Display for Debugger {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.to_str(), f)
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, Debug, PartialEq, Default, serde::Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum PanicStrategy {
#[default]
Unwind,
Abort,
}
@ -383,7 +327,7 @@ pub struct Config {
/// Only rerun the tests that result has been modified accoring to Git status
pub only_modified: bool,
pub target_cfg: LazyCell<TargetCfg>,
pub target_cfgs: AtomicLazyCell<TargetCfgs>,
pub nocapture: bool,
}
@ -396,8 +340,18 @@ impl Config {
})
}
fn target_cfg(&self) -> &TargetCfg {
self.target_cfg.borrow_with(|| TargetCfg::new(self))
pub fn target_cfgs(&self) -> &TargetCfgs {
match self.target_cfgs.borrow() {
Some(cfgs) => cfgs,
None => {
let _ = self.target_cfgs.fill(TargetCfgs::new(self));
self.target_cfgs.borrow().unwrap()
}
}
}
pub fn target_cfg(&self) -> &TargetCfg {
&self.target_cfgs().current
}
pub fn matches_arch(&self, arch: &str) -> bool {
@ -449,94 +403,154 @@ impl Config {
}
}
#[derive(Clone, Debug)]
#[derive(Debug, Clone)]
pub struct TargetCfgs {
pub current: TargetCfg,
pub all_targets: HashSet<String>,
pub all_archs: HashSet<String>,
pub all_oses: HashSet<String>,
pub all_oses_and_envs: HashSet<String>,
pub all_envs: HashSet<String>,
pub all_abis: HashSet<String>,
pub all_families: HashSet<String>,
pub all_pointer_widths: HashSet<String>,
}
impl TargetCfgs {
fn new(config: &Config) -> TargetCfgs {
let targets: HashMap<String, TargetCfg> = if config.stage_id.starts_with("stage0-") {
// #[cfg(bootstrap)]
// Needed only for one cycle, remove during the bootstrap bump.
Self::collect_all_slow(config)
} else {
serde_json::from_str(&rustc_output(
config,
&["--print=all-target-specs-json", "-Zunstable-options"],
))
.unwrap()
};
let mut current = None;
let mut all_targets = HashSet::new();
let mut all_archs = HashSet::new();
let mut all_oses = HashSet::new();
let mut all_oses_and_envs = HashSet::new();
let mut all_envs = HashSet::new();
let mut all_abis = HashSet::new();
let mut all_families = HashSet::new();
let mut all_pointer_widths = HashSet::new();
for (target, cfg) in targets.into_iter() {
all_archs.insert(cfg.arch.clone());
all_oses.insert(cfg.os.clone());
all_oses_and_envs.insert(cfg.os_and_env());
all_envs.insert(cfg.env.clone());
all_abis.insert(cfg.abi.clone());
for family in &cfg.families {
all_families.insert(family.clone());
}
all_pointer_widths.insert(format!("{}bit", cfg.pointer_width));
if target == config.target {
current = Some(cfg);
}
all_targets.insert(target.into());
}
Self {
current: current.expect("current target not found"),
all_targets,
all_archs,
all_oses,
all_oses_and_envs,
all_envs,
all_abis,
all_families,
all_pointer_widths,
}
}
// #[cfg(bootstrap)]
// Needed only for one cycle, remove during the bootstrap bump.
fn collect_all_slow(config: &Config) -> HashMap<String, TargetCfg> {
let mut result = HashMap::new();
for target in rustc_output(config, &["--print=target-list"]).trim().lines() {
let json = rustc_output(
config,
&["--print=target-spec-json", "-Zunstable-options", "--target", target],
);
match serde_json::from_str(&json) {
Ok(res) => {
result.insert(target.into(), res);
}
Err(err) => panic!("failed to parse target spec for {target}: {err}"),
}
}
result
}
}
#[derive(Clone, Debug, serde::Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct TargetCfg {
arch: String,
os: String,
env: String,
abi: String,
families: Vec<String>,
pointer_width: u32,
pub(crate) arch: String,
#[serde(default = "default_os")]
pub(crate) os: String,
#[serde(default)]
pub(crate) env: String,
#[serde(default)]
pub(crate) abi: String,
#[serde(rename = "target-family", default)]
pub(crate) families: Vec<String>,
#[serde(rename = "target-pointer-width", deserialize_with = "serde_parse_u32")]
pub(crate) pointer_width: u32,
#[serde(rename = "target-endian", default)]
endian: Endian,
#[serde(rename = "panic-strategy", default)]
panic: PanicStrategy,
}
#[derive(Eq, PartialEq, Clone, Debug)]
impl TargetCfg {
pub(crate) fn os_and_env(&self) -> String {
format!("{}-{}", self.os, self.env)
}
}
fn default_os() -> String {
"none".into()
}
#[derive(Eq, PartialEq, Clone, Debug, Default, serde::Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum Endian {
#[default]
Little,
Big,
}
impl TargetCfg {
fn new(config: &Config) -> TargetCfg {
let mut command = Command::new(&config.rustc_path);
add_dylib_path(&mut command, iter::once(&config.compile_lib_path));
let output = match command
.arg("--print=cfg")
.arg("--target")
.arg(&config.target)
.args(&config.target_rustcflags)
.output()
{
Ok(output) => output,
Err(e) => panic!("error: failed to get cfg info from {:?}: {e}", config.rustc_path),
};
if !output.status.success() {
panic!(
"error: failed to get cfg info from {:?}\n--- stdout\n{}\n--- stderr\n{}",
config.rustc_path,
String::from_utf8(output.stdout).unwrap(),
String::from_utf8(output.stderr).unwrap(),
);
}
let print_cfg = String::from_utf8(output.stdout).unwrap();
let mut arch = None;
let mut os = None;
let mut env = None;
let mut abi = None;
let mut families = Vec::new();
let mut pointer_width = None;
let mut endian = None;
let mut panic = None;
for line in print_cfg.lines() {
if let Some((name, value)) = line.split_once('=') {
let value = value.trim_matches('"');
match name {
"target_arch" => arch = Some(value),
"target_os" => os = Some(value),
"target_env" => env = Some(value),
"target_abi" => abi = Some(value),
"target_family" => families.push(value.to_string()),
"target_pointer_width" => pointer_width = Some(value.parse().unwrap()),
"target_endian" => {
endian = Some(match value {
"little" => Endian::Little,
"big" => Endian::Big,
s => panic!("unexpected {s}"),
})
}
"panic" => {
panic = match value {
"abort" => Some(PanicStrategy::Abort),
"unwind" => Some(PanicStrategy::Unwind),
s => panic!("unexpected {s}"),
}
}
_ => {}
}
}
}
TargetCfg {
arch: arch.unwrap().to_string(),
os: os.unwrap().to_string(),
env: env.unwrap().to_string(),
abi: abi.unwrap().to_string(),
families,
pointer_width: pointer_width.unwrap(),
endian: endian.unwrap(),
panic: panic.unwrap(),
}
fn rustc_output(config: &Config, args: &[&str]) -> String {
let mut command = Command::new(&config.rustc_path);
add_dylib_path(&mut command, iter::once(&config.compile_lib_path));
command.args(&config.target_rustcflags).args(args);
command.env("RUSTC_BOOTSTRAP", "1");
let output = match command.output() {
Ok(output) => output,
Err(e) => panic!("error: failed to run {command:?}: {e}"),
};
if !output.status.success() {
panic!(
"error: failed to run {command:?}\n--- stdout\n{}\n--- stderr\n{}",
String::from_utf8(output.stdout).unwrap(),
String::from_utf8(output.stderr).unwrap(),
);
}
String::from_utf8(output.stdout).unwrap()
}
fn serde_parse_u32<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u32, D::Error> {
let string = String::deserialize(deserializer)?;
string.parse().map_err(D::Error::custom)
}
#[derive(Debug, Clone)]

View File

@ -8,22 +8,16 @@ use std::process::Command;
use tracing::*;
use crate::common::{CompareMode, Config, Debugger, FailMode, Mode, PassMode};
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
use crate::header::cfg::parse_cfg_name_directive;
use crate::header::cfg::MatchOutcome;
use crate::util;
use crate::{extract_cdb_version, extract_gdb_version};
mod cfg;
#[cfg(test)]
mod tests;
/// The result of parse_cfg_name_directive.
#[derive(Clone, Copy, PartialEq, Debug)]
enum ParsedNameDirective {
/// No match.
NoMatch,
/// Match.
Match,
}
/// Properties which must be known very early, before actually running
/// the test.
#[derive(Default)]
@ -647,7 +641,7 @@ impl Config {
}
fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> {
if self.parse_cfg_name_directive(line, prefix) == ParsedNameDirective::Match {
if parse_cfg_name_directive(self, line, prefix).outcome == MatchOutcome::Match {
let from = parse_normalization_string(&mut line)?;
let to = parse_normalization_string(&mut line)?;
Some((from, to))
@ -664,68 +658,6 @@ impl Config {
self.parse_name_directive(line, "needs-profiler-support")
}
/// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86`
/// or `normalize-stderr-32bit`.
fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> ParsedNameDirective {
if !line.as_bytes().starts_with(prefix.as_bytes()) {
return ParsedNameDirective::NoMatch;
}
if line.as_bytes().get(prefix.len()) != Some(&b'-') {
return ParsedNameDirective::NoMatch;
}
let name = line[prefix.len() + 1..].split(&[':', ' '][..]).next().unwrap();
let matches_pointer_width = || {
name.strip_suffix("bit")
.and_then(|width| width.parse::<u32>().ok())
.map(|width| self.get_pointer_width() == width)
.unwrap_or(false)
};
// If something is ignored for emscripten, it likely also needs to be
// ignored for wasm32-unknown-unknown.
// `wasm32-bare` is an alias to refer to just wasm32-unknown-unknown
// (in contrast to `wasm32` which also matches non-bare targets like
// asmjs-unknown-emscripten).
let matches_wasm32_alias = || {
self.target == "wasm32-unknown-unknown" && matches!(name, "emscripten" | "wasm32-bare")
};
let is_match = name == "test" ||
self.target == name || // triple
self.matches_os(name) ||
self.matches_env(name) ||
self.matches_abi(name) ||
self.matches_family(name) ||
self.target.ends_with(name) || // target and env
self.matches_arch(name) ||
matches_wasm32_alias() ||
matches_pointer_width() ||
name == self.stage_id.split('-').next().unwrap() || // stage
name == self.channel || // channel
(self.target != self.host && name == "cross-compile") ||
(name == "endian-big" && self.is_big_endian()) ||
(self.remote_test_client.is_some() && name == "remote") ||
match self.compare_mode {
Some(CompareMode::Polonius) => name == "compare-mode-polonius",
Some(CompareMode::Chalk) => name == "compare-mode-chalk",
Some(CompareMode::NextSolver) => name == "compare-mode-next-solver",
Some(CompareMode::SplitDwarf) => name == "compare-mode-split-dwarf",
Some(CompareMode::SplitDwarfSingle) => name == "compare-mode-split-dwarf-single",
None => false,
} ||
(cfg!(debug_assertions) && name == "debug") ||
match self.debugger {
Some(Debugger::Cdb) => name == "cdb",
Some(Debugger::Gdb) => name == "gdb",
Some(Debugger::Lldb) => name == "lldb",
None => false,
};
if is_match { ParsedNameDirective::Match } else { ParsedNameDirective::NoMatch }
}
fn has_cfg_prefix(&self, line: &str, prefix: &str) -> bool {
// returns whether this line contains this prefix or not. For prefix
// "ignore", returns true if line says "ignore-x86_64", "ignore-arch",
@ -992,21 +924,44 @@ pub fn make_test_description<R: Read>(
}
};
}
ignore = match config.parse_cfg_name_directive(ln, "ignore") {
ParsedNameDirective::Match => {
ignore_message = Some("cfg -> ignore => Match");
true
}
ParsedNameDirective::NoMatch => ignore,
};
if config.has_cfg_prefix(ln, "only") {
ignore = match config.parse_cfg_name_directive(ln, "only") {
ParsedNameDirective::Match => ignore,
ParsedNameDirective::NoMatch => {
ignore_message = Some("cfg -> only => NoMatch");
{
let parsed = parse_cfg_name_directive(config, ln, "ignore");
ignore = match parsed.outcome {
MatchOutcome::Match => {
let reason = parsed.pretty_reason.unwrap();
// The ignore reason must be a &'static str, so we have to leak memory to
// create it. This is fine, as the header is parsed only at the start of
// compiletest so it won't grow indefinitely.
ignore_message = Some(Box::leak(Box::<str>::from(match parsed.comment {
Some(comment) => format!("ignored {reason} ({comment})"),
None => format!("ignored {reason}"),
})) as &str);
true
}
MatchOutcome::NoMatch => ignore,
MatchOutcome::External => ignore,
MatchOutcome::Invalid => panic!("invalid line in {}: {ln}", path.display()),
};
}
if config.has_cfg_prefix(ln, "only") {
let parsed = parse_cfg_name_directive(config, ln, "only");
ignore = match parsed.outcome {
MatchOutcome::Match => ignore,
MatchOutcome::NoMatch => {
let reason = parsed.pretty_reason.unwrap();
// The ignore reason must be a &'static str, so we have to leak memory to
// create it. This is fine, as the header is parsed only at the start of
// compiletest so it won't grow indefinitely.
ignore_message = Some(Box::leak(Box::<str>::from(match parsed.comment {
Some(comment) => format!("only executed {reason} ({comment})"),
None => format!("only executed {reason}"),
})) as &str);
true
}
MatchOutcome::External => ignore,
MatchOutcome::Invalid => panic!("invalid line in {}: {ln}", path.display()),
};
}

View File

@ -0,0 +1,320 @@
use crate::common::{CompareMode, Config, Debugger};
use std::collections::HashSet;
const EXTRA_ARCHS: &[&str] = &["spirv"];
/// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86`
/// or `normalize-stderr-32bit`.
pub(super) fn parse_cfg_name_directive<'a>(
config: &Config,
line: &'a str,
prefix: &str,
) -> ParsedNameDirective<'a> {
if !line.as_bytes().starts_with(prefix.as_bytes()) {
return ParsedNameDirective::invalid();
}
if line.as_bytes().get(prefix.len()) != Some(&b'-') {
return ParsedNameDirective::invalid();
}
let line = &line[prefix.len() + 1..];
let (name, comment) =
line.split_once(&[':', ' ']).map(|(l, c)| (l, Some(c))).unwrap_or((line, None));
// Some of the matchers might be "" depending on what the target information is. To avoid
// problems we outright reject empty directives.
if name == "" {
return ParsedNameDirective::invalid();
}
let mut outcome = MatchOutcome::Invalid;
let mut message = None;
macro_rules! condition {
(
name: $name:expr,
$(allowed_names: $allowed_names:expr,)?
$(condition: $condition:expr,)?
message: $($message:tt)*
) => {{
// This is not inlined to avoid problems with macro repetitions.
let format_message = || format!($($message)*);
if outcome != MatchOutcome::Invalid {
// Ignore all other matches if we already found one
} else if $name.custom_matches(name) {
message = Some(format_message());
if true $(&& $condition)? {
outcome = MatchOutcome::Match;
} else {
outcome = MatchOutcome::NoMatch;
}
}
$(else if $allowed_names.custom_contains(name) {
message = Some(format_message());
outcome = MatchOutcome::NoMatch;
})?
}};
}
let target_cfgs = config.target_cfgs();
let target_cfg = config.target_cfg();
condition! {
name: "test",
message: "always"
}
condition! {
name: &config.target,
allowed_names: &target_cfgs.all_targets,
message: "when the target is {name}"
}
condition! {
name: &[
Some(&*target_cfg.os),
// If something is ignored for emscripten, it likely also needs to be
// ignored for wasm32-unknown-unknown.
(config.target == "wasm32-unknown-unknown").then_some("emscripten"),
],
allowed_names: &target_cfgs.all_oses,
message: "when the operative system is {name}"
}
condition! {
name: &target_cfg.env,
allowed_names: &target_cfgs.all_envs,
message: "when the target environment is {name}"
}
condition! {
name: &target_cfg.os_and_env(),
allowed_names: &target_cfgs.all_oses_and_envs,
message: "when the operative system and target environment are {name}"
}
condition! {
name: &target_cfg.abi,
allowed_names: &target_cfgs.all_abis,
message: "when the ABI is {name}"
}
condition! {
name: &target_cfg.arch,
allowed_names: ContainsEither { a: &target_cfgs.all_archs, b: &EXTRA_ARCHS },
message: "when the architecture is {name}"
}
condition! {
name: format!("{}bit", target_cfg.pointer_width),
allowed_names: &target_cfgs.all_pointer_widths,
message: "when the pointer width is {name}"
}
condition! {
name: &*target_cfg.families,
allowed_names: &target_cfgs.all_families,
message: "when the target family is {name}"
}
// `wasm32-bare` is an alias to refer to just wasm32-unknown-unknown
// (in contrast to `wasm32` which also matches non-bare targets like
// asmjs-unknown-emscripten).
condition! {
name: "wasm32-bare",
condition: config.target == "wasm32-unknown-unknown",
message: "when the target is WASM"
}
condition! {
name: "asmjs",
condition: config.target.starts_with("asmjs"),
message: "when the architecture is asm.js",
}
condition! {
name: "thumb",
condition: config.target.starts_with("thumb"),
message: "when the architecture is part of the Thumb family"
}
condition! {
name: &config.channel,
allowed_names: &["stable", "beta", "nightly"],
message: "when the release channel is {name}",
}
condition! {
name: "cross-compile",
condition: config.target != config.host,
message: "when cross-compiling"
}
condition! {
name: "endian-big",
condition: config.is_big_endian(),
message: "on big-endian targets",
}
condition! {
name: config.stage_id.split('-').next().unwrap(),
allowed_names: &["stage0", "stage1", "stage2"],
message: "when the bootstrapping stage is {name}",
}
condition! {
name: "remote",
condition: config.remote_test_client.is_some(),
message: "when running tests remotely",
}
condition! {
name: "debug",
condition: cfg!(debug_assertions),
message: "when building with debug assertions",
}
condition! {
name: config.debugger.as_ref().map(|d| d.to_str()),
allowed_names: &Debugger::STR_VARIANTS,
message: "when the debugger is {name}",
}
condition! {
name: config.compare_mode
.as_ref()
.map(|d| format!("compare-mode-{}", d.to_str())),
allowed_names: ContainsPrefixed {
prefix: "compare-mode-",
inner: CompareMode::STR_VARIANTS,
},
message: "when comparing with {name}",
}
if prefix == "ignore" && outcome == MatchOutcome::Invalid {
// Don't error out for ignore-tidy-* diretives, as those are not handled by compiletest.
if name.starts_with("tidy-") {
outcome = MatchOutcome::External;
}
// Don't error out for ignore-pass, as that is handled elsewhere.
if name == "pass" {
outcome = MatchOutcome::External;
}
// Don't error out for ignore-llvm-version, that has a custom syntax and is handled
// elsewhere.
if name == "llvm-version" {
outcome = MatchOutcome::External;
}
// Don't error out for ignore-llvm-version, that has a custom syntax and is handled
// elsewhere.
if name == "gdb-version" {
outcome = MatchOutcome::External;
}
}
ParsedNameDirective {
name: Some(name),
comment: comment.map(|c| c.trim().trim_start_matches('-').trim()),
outcome,
pretty_reason: message,
}
}
/// The result of parse_cfg_name_directive.
#[derive(Clone, PartialEq, Debug)]
pub(super) struct ParsedNameDirective<'a> {
pub(super) name: Option<&'a str>,
pub(super) pretty_reason: Option<String>,
pub(super) comment: Option<&'a str>,
pub(super) outcome: MatchOutcome,
}
impl ParsedNameDirective<'_> {
fn invalid() -> Self {
Self { name: None, pretty_reason: None, comment: None, outcome: MatchOutcome::NoMatch }
}
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub(super) enum MatchOutcome {
/// No match.
NoMatch,
/// Match.
Match,
/// The directive was invalid.
Invalid,
/// The directive is handled by other parts of our tooling.
External,
}
trait CustomContains {
fn custom_contains(&self, item: &str) -> bool;
}
impl CustomContains for HashSet<String> {
fn custom_contains(&self, item: &str) -> bool {
self.contains(item)
}
}
impl CustomContains for &[&str] {
fn custom_contains(&self, item: &str) -> bool {
self.contains(&item)
}
}
impl<const N: usize> CustomContains for [&str; N] {
fn custom_contains(&self, item: &str) -> bool {
self.contains(&item)
}
}
struct ContainsPrefixed<T: CustomContains> {
prefix: &'static str,
inner: T,
}
impl<T: CustomContains> CustomContains for ContainsPrefixed<T> {
fn custom_contains(&self, item: &str) -> bool {
match item.strip_prefix(self.prefix) {
Some(stripped) => self.inner.custom_contains(stripped),
None => false,
}
}
}
struct ContainsEither<'a, A: CustomContains, B: CustomContains> {
a: &'a A,
b: &'a B,
}
impl<A: CustomContains, B: CustomContains> CustomContains for ContainsEither<'_, A, B> {
fn custom_contains(&self, item: &str) -> bool {
self.a.custom_contains(item) || self.b.custom_contains(item)
}
}
trait CustomMatches {
fn custom_matches(&self, name: &str) -> bool;
}
impl CustomMatches for &str {
fn custom_matches(&self, name: &str) -> bool {
name == *self
}
}
impl CustomMatches for String {
fn custom_matches(&self, name: &str) -> bool {
name == self
}
}
impl<T: CustomMatches> CustomMatches for &[T] {
fn custom_matches(&self, name: &str) -> bool {
self.iter().any(|m| m.custom_matches(name))
}
}
impl<const N: usize, T: CustomMatches> CustomMatches for [T; N] {
fn custom_matches(&self, name: &str) -> bool {
self.iter().any(|m| m.custom_matches(name))
}
}
impl<T: CustomMatches> CustomMatches for Option<T> {
fn custom_matches(&self, name: &str) -> bool {
match self {
Some(inner) => inner.custom_matches(name),
None => false,
}
}
}

View File

@ -47,7 +47,7 @@ fn config() -> Config {
"--src-base=",
"--build-base=",
"--sysroot-base=",
"--stage-id=stage2",
"--stage-id=stage2-x86_64-unknown-linux-gnu",
"--cc=c",
"--cxx=c++",
"--cflags=",
@ -174,7 +174,7 @@ fn ignore_target() {
assert!(check_ignore(&config, "// ignore-gnu"));
assert!(check_ignore(&config, "// ignore-64bit"));
assert!(!check_ignore(&config, "// ignore-i686"));
assert!(!check_ignore(&config, "// ignore-x86"));
assert!(!check_ignore(&config, "// ignore-windows"));
assert!(!check_ignore(&config, "// ignore-msvc"));
assert!(!check_ignore(&config, "// ignore-32bit"));
@ -200,7 +200,7 @@ fn only_target() {
#[test]
fn stage() {
let mut config = config();
config.stage_id = "stage1".to_owned();
config.stage_id = "stage1-x86_64-unknown-linux-gnu".to_owned();
assert!(check_ignore(&config, "// ignore-stage1"));
assert!(!check_ignore(&config, "// ignore-stage2"));

View File

@ -6,12 +6,12 @@
extern crate test;
use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
use crate::common::{CompareMode, Config, Debugger, Mode, PassMode, TestPaths};
use crate::common::{Config, Debugger, Mode, PassMode, TestPaths};
use crate::util::logv;
use build_helper::git::{get_git_modified_files, get_git_untracked_files};
use core::panic;
use getopts::Options;
use lazycell::LazyCell;
use lazycell::AtomicLazyCell;
use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs;
@ -25,6 +25,7 @@ use tracing::*;
use walkdir::WalkDir;
use self::header::{make_test_description, EarlyProps};
use std::sync::Arc;
#[cfg(test)]
mod tests;
@ -42,7 +43,7 @@ pub mod util;
fn main() {
tracing_subscriber::fmt::init();
let config = parse_config(env::args().collect());
let config = Arc::new(parse_config(env::args().collect()));
if config.valgrind_path.is_none() && config.force_valgrind {
panic!("Can't find Valgrind to run Valgrind tests");
@ -293,7 +294,9 @@ pub fn parse_config(args: Vec<String>) -> Config {
only_modified: matches.opt_present("only-modified"),
color,
remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
compare_mode: matches.opt_str("compare-mode").map(CompareMode::parse),
compare_mode: matches
.opt_str("compare-mode")
.map(|s| s.parse().expect("invalid --compare-mode provided")),
rustfix_coverage: matches.opt_present("rustfix-coverage"),
has_tidy,
channel: matches.opt_str("channel").unwrap(),
@ -311,7 +314,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
force_rerun: matches.opt_present("force-rerun"),
target_cfg: LazyCell::new(),
target_cfgs: AtomicLazyCell::new(),
nocapture: matches.opt_present("nocapture"),
}
@ -367,7 +370,7 @@ pub fn opt_str2(maybestr: Option<String>) -> String {
}
}
pub fn run_tests(config: Config) {
pub fn run_tests(config: Arc<Config>) {
// If we want to collect rustfix coverage information,
// we first make sure that the coverage file does not exist.
// It will be created later on.
@ -409,7 +412,7 @@ pub fn run_tests(config: Config) {
};
let mut tests = Vec::new();
for c in &configs {
for c in configs {
let mut found_paths = BTreeSet::new();
make_tests(c, &mut tests, &mut found_paths);
check_overlapping_tests(&found_paths);
@ -431,7 +434,11 @@ pub fn run_tests(config: Config) {
println!(
"Some tests failed in compiletest suite={}{} mode={} host={} target={}",
config.suite,
config.compare_mode.map(|c| format!(" compare_mode={:?}", c)).unwrap_or_default(),
config
.compare_mode
.as_ref()
.map(|c| format!(" compare_mode={:?}", c))
.unwrap_or_default(),
config.mode,
config.host,
config.target
@ -451,13 +458,13 @@ pub fn run_tests(config: Config) {
}
}
fn configure_cdb(config: &Config) -> Option<Config> {
fn configure_cdb(config: &Config) -> Option<Arc<Config>> {
config.cdb.as_ref()?;
Some(Config { debugger: Some(Debugger::Cdb), ..config.clone() })
Some(Arc::new(Config { debugger: Some(Debugger::Cdb), ..config.clone() }))
}
fn configure_gdb(config: &Config) -> Option<Config> {
fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
config.gdb_version?;
if config.matches_env("msvc") {
@ -488,10 +495,10 @@ fn configure_gdb(config: &Config) -> Option<Config> {
env::set_var("RUST_TEST_THREADS", "1");
}
Some(Config { debugger: Some(Debugger::Gdb), ..config.clone() })
Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() }))
}
fn configure_lldb(config: &Config) -> Option<Config> {
fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
config.lldb_python_dir.as_ref()?;
if let Some(350) = config.lldb_version {
@ -504,7 +511,7 @@ fn configure_lldb(config: &Config) -> Option<Config> {
return None;
}
Some(Config { debugger: Some(Debugger::Lldb), ..config.clone() })
Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() }))
}
pub fn test_opts(config: &Config) -> test::TestOpts {
@ -539,17 +546,17 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
}
pub fn make_tests(
config: &Config,
config: Arc<Config>,
tests: &mut Vec<test::TestDescAndFn>,
found_paths: &mut BTreeSet<PathBuf>,
) {
debug!("making tests from {:?}", config.src_base.display());
let inputs = common_inputs_stamp(config);
let modified_tests = modified_tests(config, &config.src_base).unwrap_or_else(|err| {
let inputs = common_inputs_stamp(&config);
let modified_tests = modified_tests(&config, &config.src_base).unwrap_or_else(|err| {
panic!("modified_tests got error from dir: {}, error: {}", config.src_base.display(), err)
});
collect_tests_from_dir(
config,
config.clone(),
&config.src_base,
&PathBuf::new(),
&inputs,
@ -620,7 +627,7 @@ fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
}
fn collect_tests_from_dir(
config: &Config,
config: Arc<Config>,
dir: &Path,
relative_dir_path: &Path,
inputs: &Stamp,
@ -648,7 +655,7 @@ fn collect_tests_from_dir(
// sequential loop because otherwise, if we do it in the
// tests themselves, they race for the privilege of
// creating the directories and sometimes fail randomly.
let build_dir = output_relative_path(config, relative_dir_path);
let build_dir = output_relative_path(&config, relative_dir_path);
fs::create_dir_all(&build_dir).unwrap();
// Add each `.rs` file as a test, and recurse further on any
@ -664,13 +671,13 @@ fn collect_tests_from_dir(
let paths =
TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() };
tests.extend(make_test(config, &paths, inputs))
tests.extend(make_test(config.clone(), &paths, inputs))
} else if file_path.is_dir() {
let relative_file_path = relative_dir_path.join(file.file_name());
if &file_name != "auxiliary" {
debug!("found directory: {:?}", file_path.display());
collect_tests_from_dir(
config,
config.clone(),
&file_path,
&relative_file_path,
inputs,
@ -699,14 +706,18 @@ pub fn is_test(file_name: &OsString) -> bool {
!invalid_prefixes.iter().any(|p| file_name.starts_with(p))
}
fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test::TestDescAndFn> {
fn make_test(
config: Arc<Config>,
testpaths: &TestPaths,
inputs: &Stamp,
) -> Vec<test::TestDescAndFn> {
let test_path = if config.mode == Mode::RunMake {
// Parse directives in the Makefile
testpaths.file.join("Makefile")
} else {
PathBuf::from(&testpaths.file)
};
let early_props = EarlyProps::from_file(config, &test_path);
let early_props = EarlyProps::from_file(&config, &test_path);
// Incremental tests are special, they inherently cannot be run in parallel.
// `runtest::run` will be responsible for iterating over revisions.
@ -721,19 +732,22 @@ fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test
let src_file =
std::fs::File::open(&test_path).expect("open test file to parse ignores");
let cfg = revision.map(|v| &**v);
let test_name = crate::make_test_name(config, testpaths, revision);
let mut desc = make_test_description(config, test_name, &test_path, src_file, cfg);
let test_name = crate::make_test_name(&config, testpaths, revision);
let mut desc = make_test_description(&config, test_name, &test_path, src_file, cfg);
// Ignore tests that already run and are up to date with respect to inputs.
if !config.force_rerun {
desc.ignore |= is_up_to_date(
config,
&config,
testpaths,
&early_props,
revision.map(|s| s.as_str()),
inputs,
);
}
test::TestDescAndFn { desc, testfn: make_test_closure(config, testpaths, revision) }
test::TestDescAndFn {
desc,
testfn: make_test_closure(config.clone(), testpaths, revision),
}
})
.collect()
}
@ -867,7 +881,7 @@ fn make_test_name(
}
fn make_test_closure(
config: &Config,
config: Arc<Config>,
testpaths: &TestPaths,
revision: Option<&String>,
) -> test::TestFn {

View File

@ -30,6 +30,7 @@ use std::iter;
use std::path::{Path, PathBuf};
use std::process::{Child, Command, ExitStatus, Output, Stdio};
use std::str;
use std::sync::Arc;
use glob::glob;
use once_cell::sync::Lazy;
@ -96,7 +97,7 @@ pub fn get_lib_name(lib: &str, dylib: bool) -> String {
}
}
pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) {
pub fn run(config: Arc<Config>, testpaths: &TestPaths, revision: Option<&str>) {
match &*config.target {
"arm-linux-androideabi"
| "armv7-linux-androideabi"

View File

@ -17,7 +17,6 @@
// ignore-wasm32
// ignore-x86
// ignore-x86_64
// ignore-xcore
fn main() {
}

View File

@ -1,39 +1,20 @@
// ignore-aarch64
// ignore-aarch64_be
// ignore-arm
// ignore-armeb
// ignore-avr
// ignore-bpfel
// ignore-bpfeb
// ignore-bpf
// ignore-bpf
// ignore-hexagon
// ignore-mips
// ignore-mips64
// ignore-msp430
// ignore-powerpc64
// ignore-powerpc64le
// ignore-powerpc
// ignore-r600
// ignore-amdgcn
// ignore-sparc
// ignore-sparcv9
// ignore-sparcel
// ignore-sparc64
// ignore-s390x
// ignore-tce
// ignore-thumb
// ignore-thumbeb
// ignore-xcore
// ignore-nvptx
// ignore-nvptx64
// ignore-le32
// ignore-le64
// ignore-amdil
// ignore-amdil64
// ignore-hsail
// ignore-hsail64
// ignore-spir
// ignore-spir64
// ignore-kalimba
// ignore-shave
// ignore-spirv
// ignore-wasm32
// ignore-wasm64
// ignore-emscripten

View File

@ -1,39 +1,20 @@
// ignore-aarch64
// ignore-aarch64_be
// ignore-arm
// ignore-armeb
// ignore-avr
// ignore-bpfel
// ignore-bpfeb
// ignore-bpf
// ignore-bpf
// ignore-hexagon
// ignore-mips
// ignore-mips64
// ignore-msp430
// ignore-powerpc64
// ignore-powerpc64le
// ignore-powerpc
// ignore-r600
// ignore-amdgcn
// ignore-sparc
// ignore-sparcv9
// ignore-sparcel
// ignore-sparc64
// ignore-s390x
// ignore-tce
// ignore-thumb
// ignore-thumbeb
// ignore-xcore
// ignore-nvptx
// ignore-nvptx64
// ignore-le32
// ignore-le64
// ignore-amdil
// ignore-amdil64
// ignore-hsail
// ignore-hsail64
// ignore-spir
// ignore-spir64
// ignore-kalimba
// ignore-shave
// ignore-spirv
// ignore-wasm32
// ignore-wasm64
// ignore-emscripten

View File

@ -1,39 +1,20 @@
// ignore-aarch64
// ignore-aarch64_be
// ignore-arm
// ignore-armeb
// ignore-avr
// ignore-bpfel
// ignore-bpfeb
// ignore-bpf
// ignore-bpf
// ignore-hexagon
// ignore-mips
// ignore-mips64
// ignore-msp430
// ignore-powerpc64
// ignore-powerpc64le
// ignore-powerpc
// ignore-r600
// ignore-amdgcn
// ignore-sparc
// ignore-sparcv9
// ignore-sparcel
// ignore-sparc64
// ignore-s390x
// ignore-tce
// ignore-thumb
// ignore-thumbeb
// ignore-xcore
// ignore-nvptx
// ignore-nvptx64
// ignore-le32
// ignore-le64
// ignore-amdil
// ignore-amdil64
// ignore-hsail
// ignore-hsail64
// ignore-spir
// ignore-spir64
// ignore-kalimba
// ignore-shave
// ignore-spirv
// ignore-wasm32
// ignore-wasm64
// ignore-emscripten

View File

@ -1,9 +1,5 @@
// compile-flags: -O -Zmerge-functions=disabled
// ignore-x86
// ignore-arm
// ignore-emscripten
// ignore-gnux32
// ignore 32-bit platforms (LLVM has a bug with them)
// ignore-32bit LLVM has a bug with them
// ignore-debug
// Check that LLVM understands that `Iter` pointer is not null. Issue #37945.

View File

@ -6,7 +6,6 @@
// ignore-mips64
// ignore-powerpc
// ignore-powerpc64
// ignore-powerpc64le
// ignore-riscv64 see codegen/riscv-abi
// ignore-s390x
// ignore-sparc

View File

@ -2,7 +2,7 @@ include ../tools.mk
# only-x86_64
# only-linux
# ignore-gnux32
# ignore-32bit
# How to manually run this
# $ ./x.py test --target x86_64-unknown-linux-[musl,gnu] tests/run-make/static-pie

View File

@ -2,7 +2,7 @@ include ../tools.mk
# ignore-freebsd
# ignore-openbsd
# ignore-sunos
# ignore-solaris
HOST := $(shell $(RUSTC) -vV | grep 'host:' | sed 's/host: //')
ifeq ($(findstring i686,$(HOST)),i686)

View File

@ -1,2 +1,2 @@
error: unknown print request `uwu`. Valid print requests are: `crate-name`, `file-names`, `sysroot`, `target-libdir`, `cfg`, `calling-conventions`, `target-list`, `target-cpus`, `target-features`, `relocation-models`, `code-models`, `tls-models`, `native-static-libs`, `stack-protector-strategies`, `target-spec-json`, `link-args`, `split-debuginfo`
error: unknown print request `uwu`. Valid print requests are: `crate-name`, `file-names`, `sysroot`, `target-libdir`, `cfg`, `calling-conventions`, `target-list`, `target-cpus`, `target-features`, `relocation-models`, `code-models`, `tls-models`, `native-static-libs`, `stack-protector-strategies`, `target-spec-json`, `all-target-specs-json`, `link-args`, `split-debuginfo`

View File

@ -1,7 +1,7 @@
// run-pass
// Test that users are able to use stable mir APIs to retrieve information of the current crate
// ignore-stage-1
// ignore-stage1
// ignore-cross-compile
// ignore-remote
// edition: 2021

View File

@ -9,7 +9,6 @@
// ignore-emscripten no processes
// ignore-sgx no processes
// ignore-musl FIXME #31506
// ignore-pretty
// ignore-fuchsia no exception handler registered for segfault
// compile-flags: -C lto
// no-prefer-dynamic

View File

@ -1,7 +1,7 @@
// This checks that the attribute validation ICE in issue #105594 doesn't
// recur.
//
// ignore-thumbv8m.base
// ignore-thumbv8m.base-none-eabi
#![feature(cmse_nonsecure_entry)]
fn main() {}

View File

@ -1,6 +1,5 @@
// run-pass
#![allow(unused_unsafe)]
// ignore-pretty issue #37199
#![allow(while_true)]
fn main() {

View File

@ -1,6 +1,5 @@
// run-pass
#![allow(dead_code)]
// ignore-pretty issue #37199
fn match_ref(v: Option<isize>) -> isize {
match v {

View File

@ -2,7 +2,6 @@
#![allow(stable_features)]
// ignore-windows - this is a unix-specific test
// ignore-pretty issue #37199
// ignore-emscripten no processes
// ignore-sgx no processes
// ignore-fuchsia no execvp syscall provided

View File

@ -1,5 +1,3 @@
// ignore-pretty pretty-printing is unhygienic
#![feature(decl_macro)]
macro m($t:ty, $e:expr) {

View File

@ -1,5 +1,5 @@
error[E0412]: cannot find type `S` in this scope
--> $DIR/arguments.rs:16:8
--> $DIR/arguments.rs:14:8
|
LL | m!(S, S);
| ^ not found in this scope

View File

@ -1,5 +1,3 @@
// ignore-pretty pretty-printing is unhygienic
#![feature(decl_macro)]
#![allow(unused)]

View File

@ -1,5 +1,5 @@
error[E0407]: method `method` is not a member of trait `Tr`
--> $DIR/assoc_item_ctxt.rs:35:13
--> $DIR/assoc_item_ctxt.rs:33:13
|
LL | fn method() {}
| ^^^------^^^^^
@ -13,7 +13,7 @@ LL | mac_trait_impl!();
= note: this error originates in the macro `mac_trait_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0046]: not all trait items implemented, missing: `method`
--> $DIR/assoc_item_ctxt.rs:34:9
--> $DIR/assoc_item_ctxt.rs:32:9
|
LL | fn method();
| ------------ `method` from trait

View File

@ -1,5 +1,4 @@
// check-pass
// ignore-pretty pretty-printing is unhygienic
#![feature(decl_macro, associated_type_defaults)]

View File

@ -1,5 +1,3 @@
// ignore-pretty pretty-printing is unhygienic
#[macro_export]
macro_rules! m {
() => {

View File

@ -1,5 +1,3 @@
// ignore-pretty pretty-printing is unhygienic
#![feature(decl_macro)]
mod foo {

View File

@ -1,5 +1,5 @@
error: type `foo::S` is private
--> $DIR/fields.rs:15:17
--> $DIR/fields.rs:13:17
|
LL | let s = S { x: 0 };
| ^^^^^^^^^^ private type
@ -10,7 +10,7 @@ LL | let s = foo::m!(S, x);
= note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `foo::S` is private
--> $DIR/fields.rs:16:17
--> $DIR/fields.rs:14:17
|
LL | let _ = s.x;
| ^ private type
@ -21,7 +21,7 @@ LL | let s = foo::m!(S, x);
= note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `T` is private
--> $DIR/fields.rs:18:17
--> $DIR/fields.rs:16:17
|
LL | let t = T(0);
| ^^^^ private type
@ -32,7 +32,7 @@ LL | let s = foo::m!(S, x);
= note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info)
error: type `T` is private
--> $DIR/fields.rs:19:17
--> $DIR/fields.rs:17:17
|
LL | let _ = t.0;
| ^ private type

View File

@ -1,7 +1,6 @@
// Ensure that generic parameters always have modern hygiene.
// check-pass
// ignore-pretty pretty-printing is unhygienic
#![feature(decl_macro, rustc_attrs)]

View File

@ -1,5 +1,3 @@
// ignore-pretty pretty-printing is unhygienic
#![feature(decl_macro)]
mod foo {

View File

@ -1,5 +1,5 @@
error: type `for<'a> fn(&'a foo::S) {foo::S::f}` is private
--> $DIR/impl_items.rs:12:23
--> $DIR/impl_items.rs:10:23
|
LL | let _: () = S.f();
| ^ private type

View File

@ -1,5 +1,3 @@
// ignore-pretty pretty-printing is unhygienic
// aux-build:intercrate.rs
#![feature(decl_macro)]

View File

@ -1,5 +1,5 @@
error: type `fn() -> u32 {foo::bar::f}` is private
--> $DIR/intercrate.rs:10:16
--> $DIR/intercrate.rs:8:16
|
LL | assert_eq!(intercrate::foo::m!(), 1);
| ^^^^^^^^^^^^^^^^^^^^^ private type

View File

@ -1,5 +1,4 @@
// check-pass
// ignore-pretty pretty-printing is unhygienic
#![feature(decl_macro)]
#![allow(unused)]

View File

@ -1,5 +1,4 @@
// check-pass
// ignore-pretty pretty-printing is unhygienic
#![feature(decl_macro)]
#![allow(unused)]

View File

@ -1,5 +1,4 @@
// check-pass
// ignore-pretty pretty-printing is unhygienic
#![feature(decl_macro)]

View File

@ -1,6 +1,5 @@
// check-pass
#![allow(dead_code)]
// ignore-pretty pretty-printing is unhygienic
// aux-build:legacy_interaction.rs

View File

@ -1,5 +1,4 @@
// check-pass
// ignore-pretty pretty-printing is unhygienic
#![feature(decl_macro)]

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty pretty-printing is unhygienic
#![feature(decl_macro)]

View File

@ -1,5 +1,4 @@
// check-pass
// ignore-pretty pretty-printing is unhygienic
#![feature(decl_macro)]

View File

@ -1,5 +1,4 @@
// check-pass
// ignore-pretty pretty-printing is unhygienic
// aux-build:my_crate.rs
// aux-build:unhygienic_example.rs

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty pretty-printing is unhygienic
// aux-build:xcrate.rs

View File

@ -3,7 +3,6 @@
#![allow(unused_imports)]
#![allow(non_snake_case)]
// ignore-pretty issue #37195
#[path = "issue-26873-multifile/mod.rs"]
mod multifile;

View File

@ -1,6 +1,5 @@
// run-pass
#![allow(dead_code)]
// ignore-pretty issue #37199
// Don't panic on blocks without results
// There are several tests in this run-pass that raised

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty issue #37199
pub struct Foo;

View File

@ -1,6 +1,5 @@
// run-pass
// aux-build:issue-38190.rs
// ignore-pretty issue #37195
#[macro_use]
extern crate issue_38190;

View File

@ -2,7 +2,6 @@
#![allow(dead_code)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
// ignore-pretty unreported
pub trait bomb { fn boom(&self, _: Ident); }
pub struct S;

View File

@ -6,7 +6,6 @@
// N.B., this file needs CRLF line endings. The .gitattributes file in
// this directory should enforce it.
// ignore-pretty issue #37195
/// Doc comment that ends in CRLF
pub fn foo() {}

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty issue #37195
#![allow(dead_code)]

View File

@ -8,7 +8,6 @@
// implementations for some macro_rules! macros as an implementation
// detail.
// ignore-pretty issue #37195
// compile-flags: --test -C debug_assertions=yes
// revisions: std core

View File

@ -1,7 +1,6 @@
// run-pass
#![allow(non_camel_case_types)]
// ignore-pretty issue #37195
fn bar() {}

View File

@ -1,7 +1,6 @@
// run-pass
#![allow(stable_features)]
// ignore-pretty issue #37195
pub mod m1 {
pub mod m2 {
@ -14,9 +13,9 @@ pub mod m1 {
macro_rules! indirect_line { () => ( line!() ) }
pub fn main() {
assert_eq!(line!(), 17);
assert_eq!(line!(), 16);
assert_eq!(column!(), 16);
assert_eq!(indirect_line!(), 19);
assert_eq!(indirect_line!(), 18);
assert!((file!().ends_with("syntax-extension-source-utils.rs")));
assert_eq!(stringify!((2*3) + 5).to_string(), "(2 * 3) + 5".to_string());
assert!(include!("syntax-extension-source-utils-files/includeme.\
@ -33,5 +32,5 @@ pub fn main() {
// The Windows tests are wrapped in an extra module for some reason
assert!((m1::m2::where_am_i().ends_with("m1::m2")));
assert_eq!((36, "(2 * 3) + 5"), (line!(), stringify!((2*3) + 5)));
assert_eq!((35, "(2 * 3) + 5"), (line!(), stringify!((2*3) + 5)));
}

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty issue #37195
mod mod_dir_implicit_aux;

View File

@ -1,6 +1,5 @@
// run-pass
#![allow(unused_macros)]
// ignore-pretty issue #37195
mod mod_dir_simple {
#[path = "test.rs"]

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty issue #37195
#[path = "mod_dir_simple"]
mod pancakes {

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty issue #37195
#[path = "mod_dir_simple"]
mod pancakes {

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty issue #37195
#[path = "mod_dir_simple"]
mod biscuits {

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty issue #37195
// Testing that the parser for each file tracks its modules
// and paths independently. The load_another_mod module should

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty issue #37195
mod mod_dir_simple {
pub mod test;

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty issue #37195
// Testing that a plain .rs file can load modules from other source files

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty issue #37195
// Testing that a plain .rs file can load modules from other source files

View File

@ -1,6 +1,5 @@
// run-pass
//
// ignore-pretty issue #37195
pub mod modrs_mod;
pub mod foors_mod;
#[path = "some_crazy_attr_mod_dir/arbitrary_name.rs"]

View File

@ -7,7 +7,6 @@
// issue-48508-aux.rs
// compile-flags:-g
// ignore-pretty issue #37195
// ignore-asmjs wasm2js does not support source maps yet
#![allow(uncommon_codepoints)]

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty
// aux-build:span-api-tests.rs
// aux-build:span-test-macros.rs
// compile-flags: -Ztranslate-remapped-path-to-local-path=yes

View File

@ -9,7 +9,6 @@
// compile-flags:-g -Copt-level=0 -Cllvm-args=-enable-tail-merge=0
// compile-flags:-Cforce-frame-pointers=yes
// compile-flags:-Cstrip=none
// ignore-pretty issue #37195
// ignore-emscripten spawning processes is not supported
// ignore-sgx no processes
// ignore-fuchsia Backtrace not symbolized, trace different line alignment

View File

@ -1,5 +1,7 @@
// build-pass
// only-x86-windows
// only-x86
// only-windows
// ignore-gnu - vectorcall is not supported by GCC: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485
#![crate_type = "cdylib"]
#![feature(abi_vectorcall)]

View File

@ -6,7 +6,6 @@
// ignore-mips64
// ignore-powerpc
// ignore-powerpc64
// ignore-powerpc64le
// ignore-riscv64
// ignore-sparc
// ignore-sparc64

View File

@ -1,5 +1,5 @@
error[E0658]: the target feature `avx512bw` is currently unstable
--> $DIR/gate.rs:32:18
--> $DIR/gate.rs:31:18
|
LL | #[target_feature(enable = "avx512bw")]
| ^^^^^^^^^^^^^^^^^^^

View File

@ -6,7 +6,6 @@
// ignore-mips64
// ignore-powerpc
// ignore-powerpc64
// ignore-powerpc64le
// ignore-riscv64
// ignore-s390x
// ignore-sparc

View File

@ -1,11 +1,11 @@
error: malformed `target_feature` attribute input
--> $DIR/invalid-attribute.rs:32:1
--> $DIR/invalid-attribute.rs:31:1
|
LL | #[target_feature = "+sse2"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[target_feature(enable = "name")]`
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:17:1
--> $DIR/invalid-attribute.rs:16:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -14,7 +14,7 @@ LL | extern crate alloc;
| ------------------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:22:1
--> $DIR/invalid-attribute.rs:21:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -23,7 +23,7 @@ LL | use alloc::alloc::alloc;
| ------------------------ not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:27:1
--> $DIR/invalid-attribute.rs:26:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -32,7 +32,7 @@ LL | extern "Rust" {}
| ---------------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:49:1
--> $DIR/invalid-attribute.rs:48:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -41,7 +41,7 @@ LL | mod another {}
| -------------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:54:1
--> $DIR/invalid-attribute.rs:53:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -50,7 +50,7 @@ LL | const FOO: usize = 7;
| --------------------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:59:1
--> $DIR/invalid-attribute.rs:58:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -59,7 +59,7 @@ LL | struct Foo;
| ----------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:64:1
--> $DIR/invalid-attribute.rs:63:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -68,7 +68,7 @@ LL | enum Bar {}
| ----------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:69:1
--> $DIR/invalid-attribute.rs:68:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -81,7 +81,7 @@ LL | | }
| |_- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:77:1
--> $DIR/invalid-attribute.rs:76:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -90,7 +90,7 @@ LL | type Uwu = ();
| -------------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:82:1
--> $DIR/invalid-attribute.rs:81:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -99,7 +99,7 @@ LL | trait Baz {}
| ------------ not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:92:1
--> $DIR/invalid-attribute.rs:91:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -108,7 +108,7 @@ LL | static A: () = ();
| ------------------ not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:97:1
--> $DIR/invalid-attribute.rs:96:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -117,7 +117,7 @@ LL | impl Quux for u8 {}
| ------------------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:102:1
--> $DIR/invalid-attribute.rs:101:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -126,7 +126,7 @@ LL | impl Foo {}
| ----------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:120:5
--> $DIR/invalid-attribute.rs:119:5
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -138,7 +138,7 @@ LL | | }
| |_____- not a function definition
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:128:5
--> $DIR/invalid-attribute.rs:127:5
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -147,25 +147,25 @@ LL | || {};
| ----- not a function definition
error: the feature named `foo` is not valid for this target
--> $DIR/invalid-attribute.rs:34:18
--> $DIR/invalid-attribute.rs:33:18
|
LL | #[target_feature(enable = "foo")]
| ^^^^^^^^^^^^^^ `foo` is not valid for this target
error: malformed `target_feature` attribute input
--> $DIR/invalid-attribute.rs:37:18
--> $DIR/invalid-attribute.rs:36:18
|
LL | #[target_feature(bar)]
| ^^^ help: must be of the form: `enable = ".."`
error: malformed `target_feature` attribute input
--> $DIR/invalid-attribute.rs:39:18
--> $DIR/invalid-attribute.rs:38:18
|
LL | #[target_feature(disable = "baz")]
| ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."`
error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
--> $DIR/invalid-attribute.rs:43:1
--> $DIR/invalid-attribute.rs:42:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -177,13 +177,13 @@ LL | fn bar() {}
= help: add `#![feature(target_feature_11)]` to the crate attributes to enable
error: cannot use `#[inline(always)]` with `#[target_feature]`
--> $DIR/invalid-attribute.rs:87:1
--> $DIR/invalid-attribute.rs:86:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
--> $DIR/invalid-attribute.rs:112:5
--> $DIR/invalid-attribute.rs:111:5
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,5 +1,4 @@
// run-pass
// ignore-pretty `dyn ::foo` parses differently in the current edition
use std::fmt::Display;