add tracing

This commit is contained in:
nora 2022-12-18 12:03:46 +01:00
parent 1cb5114557
commit e1fd83b4d9
8 changed files with 264 additions and 33 deletions

133
Cargo.lock generated
View file

@ -159,6 +159,9 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"syn", "syn",
"tracing",
"tracing-subscriber",
"tracing-tree",
"walkdir", "walkdir",
] ]
@ -802,6 +805,15 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "matchers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
"regex-automata",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.5.0" version = "2.5.0"
@ -826,6 +838,16 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.13.1" version = "1.13.1"
@ -914,6 +936,12 @@ version = "6.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]] [[package]]
name = "pathdiff" name = "pathdiff"
version = "0.2.1" version = "0.2.1"
@ -926,6 +954,12 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "pin-project-lite"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.25" version = "0.3.25"
@ -1024,6 +1058,9 @@ name = "regex-automata"
version = "0.1.10" version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
"regex-syntax",
]
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
@ -1146,6 +1183,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "sharded-slab"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
dependencies = [
"lazy_static",
]
[[package]] [[package]]
name = "shell-escape" name = "shell-escape"
version = "0.1.5" version = "0.1.5"
@ -1162,6 +1208,12 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "smallvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.4.7" version = "0.4.7"
@ -1280,6 +1332,81 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "tracing"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [
"cfg-if",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
dependencies = [
"lazy_static",
"log",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
[[package]]
name = "tracing-tree"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "758e983ab7c54fee18403994507e7f212b9005e957ce7984996fac8d11facedb"
dependencies = [
"atty",
"nu-ansi-term",
"tracing-core",
"tracing-log",
"tracing-subscriber",
]
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.15.0" version = "1.15.0"
@ -1336,6 +1463,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.15" version = "0.2.15"

View file

@ -5,7 +5,7 @@ exclude = ["test-cases/*"]
name = "cargo-minimize" name = "cargo-minimize"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
about = "A tool for minimizing rustc ICEs" description = "A tool for minimizing rustc ICEs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -20,4 +20,7 @@ rustfix = "0.6.1"
serde = { version = "1.0.151", features = ["derive"] } serde = { version = "1.0.151", features = ["derive"] }
serde_json = "1.0.90" serde_json = "1.0.90"
syn = { version = "1.0.101", features = ["full", "visit", "visit-mut"] } syn = { version = "1.0.101", features = ["full", "visit", "visit-mut"] }
tracing = "0.1.37"
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
tracing-tree = "0.2.2"
walkdir = "2.3.2" walkdir = "2.3.2"

View file

@ -1,9 +1,9 @@
use anyhow::{Context, Result}; use anyhow::{bail, Context, Result};
use rustfix::diagnostics::Diagnostic; use rustfix::diagnostics::Diagnostic;
use serde::Deserialize; use serde::Deserialize;
use std::{collections::HashSet, fmt::Display, path::PathBuf, process::Command, rc::Rc}; use std::{collections::HashSet, fmt::Display, path::PathBuf, process::Command, rc::Rc};
use crate::Options; use crate::{EnvVar, Options};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Build { pub struct Build {
@ -15,6 +15,7 @@ struct BuildInner {
mode: BuildMode, mode: BuildMode,
input_path: PathBuf, input_path: PathBuf,
no_verify: bool, no_verify: bool,
env: Vec<EnvVar>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -38,11 +39,13 @@ impl Build {
.map(|cmd| cmd.split_whitespace().map(ToString::to_string).collect()), .map(|cmd| cmd.split_whitespace().map(ToString::to_string).collect()),
} }
}; };
Self { Self {
inner: Rc::new(BuildInner { inner: Rc::new(BuildInner {
mode, mode,
input_path: options.path.clone(), input_path: options.path.clone(),
no_verify: options.no_verify, no_verify: options.no_verify,
env: options.env.clone(),
}), }),
} }
} }
@ -52,10 +55,11 @@ impl Build {
return Ok(BuildResult { return Ok(BuildResult {
reproduces_issue: false, reproduces_issue: false,
no_verify: true, no_verify: true,
output: String::new(),
}); });
} }
let reproduces_issue = match &self.inner.mode { let (reproduces_issue, output) = match &self.inner.mode {
BuildMode::Cargo { args } => { BuildMode::Cargo { args } => {
let mut cmd = Command::new("cargo"); let mut cmd = Command::new("cargo");
cmd.arg("build"); cmd.arg("build");
@ -64,33 +68,58 @@ impl Build {
cmd.arg(arg); cmd.arg(arg);
} }
let output = for env in &self.inner.env {
String::from_utf8(cmd.output().context("spawning rustc process")?.stderr) cmd.env(&env.key, &env.value);
.unwrap(); }
output.contains("internal compiler error") let outputs = cmd.output().context("spawning rustc process")?;
let output = String::from_utf8(outputs.stderr)?;
(
outputs.status.code() == Some(101)
|| output.contains("internal compiler error"),
output,
)
} }
BuildMode::Script(script_path) => { BuildMode::Script(script_path) => {
let mut cmd = Command::new(script_path); let mut cmd = Command::new(script_path);
cmd.output().context("spawning script")?.status.success() for env in &self.inner.env {
cmd.env(&env.key, &env.value);
}
let outputs = cmd.output().context("spawning script")?;
let output = String::from_utf8(outputs.stderr)?;
(outputs.status.success(), output)
} }
BuildMode::Rustc => { BuildMode::Rustc => {
let mut cmd = Command::new("rustc"); let mut cmd = Command::new("rustc");
cmd.args(["--edition", "2018"]); cmd.args(["--edition", "2021"]);
cmd.arg(&self.inner.input_path); cmd.arg(&self.inner.input_path);
cmd.output() for env in &self.inner.env {
.context("spawning rustc process")? cmd.env(&env.key, &env.value);
.status }
.code()
== Some(101) let outputs = cmd.output().context("spawning rustc process")?;
let output = String::from_utf8(outputs.stderr)?;
(
outputs.status.code() == Some(101)
|| output.contains("internal compiler error"),
output,
)
} }
}; };
Ok(BuildResult { Ok(BuildResult {
reproduces_issue, reproduces_issue,
no_verify: self.inner.no_verify, no_verify: self.inner.no_verify,
output,
}) })
} }
@ -104,6 +133,10 @@ impl Build {
cmd.arg(arg); cmd.arg(arg);
} }
for env in &self.inner.env {
cmd.env(&env.key, &env.value);
}
let cmd_output = cmd.output()?; let cmd_output = cmd.output()?;
let output = String::from_utf8(cmd_output.stdout.clone())?; let output = String::from_utf8(cmd_output.stdout.clone())?;
@ -121,9 +154,13 @@ impl Build {
} }
BuildMode::Rustc => { BuildMode::Rustc => {
let mut cmd = std::process::Command::new("rustc"); let mut cmd = std::process::Command::new("rustc");
cmd.args(["--edition", "2018", "--error-format=json"]); cmd.args(["--edition", "2021", "--error-format=json"]);
cmd.arg(&self.inner.input_path); cmd.arg(&self.inner.input_path);
for env in &self.inner.env {
cmd.env(&env.key, &env.value);
}
let output = cmd.output()?.stderr; let output = cmd.output()?.stderr;
let output = String::from_utf8(output)?; let output = String::from_utf8(output)?;
@ -153,9 +190,20 @@ impl Build {
pub struct BuildResult { pub struct BuildResult {
reproduces_issue: bool, reproduces_issue: bool,
no_verify: bool, no_verify: bool,
output: String,
} }
impl BuildResult { impl BuildResult {
pub fn require_reproduction(&self, build: &str) -> Result<()> {
if !self.reproduces_issue() {
bail!(
"{build} build must reproduce issue. Output:\n{}",
self.output
);
}
Ok(())
}
pub fn reproduces_issue(&self) -> bool { pub fn reproduces_issue(&self) -> bool {
self.reproduces_issue || self.no_verify self.reproduces_issue || self.no_verify
} }

View file

@ -1,4 +1,7 @@
use std::path::PathBuf; #[macro_use]
extern crate tracing;
use std::{path::PathBuf, str::FromStr};
mod build; mod build;
mod everybody_loops; mod everybody_loops;
@ -31,10 +34,35 @@ pub struct Options {
#[arg(long)] #[arg(long)]
no_verify: bool, no_verify: bool,
#[arg(long)]
env: Vec<EnvVar>,
#[arg(default_value = "src")] #[arg(default_value = "src")]
path: PathBuf, path: PathBuf,
} }
#[derive(Debug, Clone)]
struct EnvVar {
key: String,
value: String,
}
impl FromStr for EnvVar {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut split = s.split("=");
let key = split
.next()
.ok_or("env var must have KEY=VALUE format")?
.to_string();
let value = split
.next()
.ok_or("env var must have KEY=VALUE format")?
.to_string();
Ok(Self { key, value })
}
}
pub fn minimize() -> Result<()> { pub fn minimize() -> Result<()> {
let Cargo::Minimize(options) = Cargo::parse(); let Cargo::Minimize(options) = Cargo::parse();

View file

@ -1,6 +1,18 @@
use anyhow::Result; use anyhow::Result;
use tracing::info;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Registry};
fn main() -> Result<()> { fn main() -> Result<()> {
let registry = Registry::default().with(EnvFilter::from_default_env());
info!("Starting cargo-minimize");
let tree_layer = tracing_tree::HierarchicalLayer::new(2)
.with_targets(true)
.with_bracketed_fields(true);
registry.with(tree_layer).init();
cargo_minimize::minimize()?; cargo_minimize::minimize()?;
Ok(()) Ok(())

View file

@ -1,9 +1,9 @@
mod files; mod files;
mod reaper; mod reaper;
use std::{borrow::Borrow, collections::HashSet, ffi::OsStr, mem, path::Path}; use std::{borrow::Borrow, collections::HashSet, ffi::OsStr, fmt::Debug, mem, path::Path};
use anyhow::{ensure, Context, Result}; use anyhow::{Context, Result};
use crate::{build::Build, processor::files::Changes}; use crate::{build::Build, processor::files::Changes};
@ -27,6 +27,12 @@ pub trait Processor {
fn name(&self) -> &'static str; fn name(&self) -> &'static str;
} }
impl Debug for dyn Processor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.name())
}
}
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum ProcessState { pub enum ProcessState {
NoChange, NoChange,
@ -71,10 +77,7 @@ impl Minimizer {
) -> Result<()> { ) -> Result<()> {
let inital_build = self.build.build()?; let inital_build = self.build.build()?;
println!("Initial build: {}", inital_build); println!("Initial build: {}", inital_build);
ensure!( inital_build.require_reproduction("Initial")?;
inital_build.reproduces_issue(),
"Initial build must reproduce issue"
);
for mut pass in passes { for mut pass in passes {
self.run_pass(&mut *pass)?; self.run_pass(&mut *pass)?;
@ -89,7 +92,9 @@ impl Minimizer {
let mut refresh_and_try_again = false; let mut refresh_and_try_again = false;
loop { loop {
println!("Starting a round of {}", pass.name()); let span = info_span!("Starting round of pass", name = pass.name());
let _enter = span.enter();
let mut changes = Changes::default(); let mut changes = Changes::default();
for file in &self.files { for file in &self.files {
@ -176,7 +181,7 @@ impl Minimizer {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
struct AstPath(Vec<String>); struct AstPath(Vec<String>);
impl Borrow<[String]> for AstPath { impl Borrow<[String]> for AstPath {
@ -185,6 +190,12 @@ impl Borrow<[String]> for AstPath {
} }
} }
impl Debug for AstPath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "AstPath({:?})", self.0)
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct PassController { pub struct PassController {
state: PassControllerState, state: PassControllerState,

View file

@ -5,7 +5,7 @@ use crate::build::Build;
use super::{ use super::{
files::Changes, tracking, Minimizer, PassController, ProcessState, Processor, SourceFile, files::Changes, tracking, Minimizer, PassController, ProcessState, Processor, SourceFile,
}; };
use anyhow::{ensure, Context, Result}; use anyhow::{Context, Result};
use proc_macro2::Span; use proc_macro2::Span;
use quote::ToTokens; use quote::ToTokens;
use rustfix::{diagnostics::Diagnostic, Suggestion}; use rustfix::{diagnostics::Diagnostic, Suggestion};
@ -24,10 +24,8 @@ impl Minimizer {
pub fn delete_dead_code(&mut self) -> Result<()> { pub fn delete_dead_code(&mut self) -> Result<()> {
let inital_build = self.build.build()?; let inital_build = self.build.build()?;
println!("Before reaper: {}", inital_build); println!("Before reaper: {}", inital_build);
ensure!(
inital_build.reproduces_issue(), inital_build.require_reproduction("Initial")?;
"Initial build must reproduce issue"
);
let (diags, suggestions) = self let (diags, suggestions) = self
.build .build

View file

@ -1,3 +1 @@
pub fn unused() { pub(crate) fn unused() {}
}