From 4cd2267497b68105581d806e52fe6ef978dbc2f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 16 May 2026 20:30:31 +0200 Subject: [PATCH] first commit --- .gitignore | 2 + Cargo.lock | 408 ++++++++++++++++++++++++++++++++ Cargo.toml | 9 + examples/borrow.rs | 8 + examples/coinductive.rs | 13 + examples/local.rs | 5 + examples/nora.rs | 1 + examples/private_field_deref.rs | 26 ++ examples/traits.rs | 4 + src/main.rs | 168 +++++++++++++ 10 files changed, 644 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 examples/borrow.rs create mode 100644 examples/coinductive.rs create mode 100644 examples/local.rs create mode 100644 examples/nora.rs create mode 100644 examples/private_field_deref.rs create mode 100644 examples/traits.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..abb8af4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +*.rcgu.o diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..a2e6c08 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,408 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crossterm" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" +dependencies = [ + "bitflags", + "crossterm_winapi", + "derive_more", + "document-features", + "mio", + "parking_lot", + "rustix", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "errorversion" +version = "0.1.0" +dependencies = [ + "crossterm", + "rayon", + "strip-ansi-escapes", +] + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "strip-ansi-escapes" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025" +dependencies = [ + "vte", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "vte" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077" +dependencies = [ + "memchr", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7a97f34 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "errorversion" +version = "0.1.0" +edition = "2024" + +[dependencies] +rayon = "1.12" +crossterm = "0.29" +strip-ansi-escapes = "0.2" diff --git a/examples/borrow.rs b/examples/borrow.rs new file mode 100644 index 0000000..5dbaa51 --- /dev/null +++ b/examples/borrow.rs @@ -0,0 +1,8 @@ +#![allow(unused)] + +fn main() { + let mut a = 5; + let b = &mut a; + let x = &a; + println!("{}", b); +} diff --git a/examples/coinductive.rs b/examples/coinductive.rs new file mode 100644 index 0000000..18c15a9 --- /dev/null +++ b/examples/coinductive.rs @@ -0,0 +1,13 @@ +#![allow(unused)] + +enum List { + Nil, + Cons(T, Box>), +} + +fn is_send(x: impl Send) {} + +fn main() { + let x = 3; + is_send(List::Cons(&mut x as *mut _, Box::new(List::Nil))) +} diff --git a/examples/local.rs b/examples/local.rs new file mode 100644 index 0000000..edfffef --- /dev/null +++ b/examples/local.rs @@ -0,0 +1,5 @@ +fn main() { + let x = 3; + println!("{}", x + y); +} + diff --git a/examples/nora.rs b/examples/nora.rs new file mode 100644 index 0000000..f328e4d --- /dev/null +++ b/examples/nora.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/examples/private_field_deref.rs b/examples/private_field_deref.rs new file mode 100644 index 0000000..3e347ce --- /dev/null +++ b/examples/private_field_deref.rs @@ -0,0 +1,26 @@ +mod private { + pub struct Foo { + field: i32, + bar: Bar, + } + + pub struct Bar { + pub field: u32, + } + + impl std::ops::Deref for Foo { + type Target = Bar; + + fn deref(&self) -> &Self::Target { + &self.bar + } + } +} + +use private::Foo; + +fn example(f: Foo) { + let a: i32 = f.field; +} + +fn main() {} diff --git a/examples/traits.rs b/examples/traits.rs new file mode 100644 index 0000000..fa3901b --- /dev/null +++ b/examples/traits.rs @@ -0,0 +1,4 @@ +fn main() { + let _: &dyn Eq = &123; + let _: &dyn Iterator = &vec![123].into_iter(); +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..1ebede4 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,168 @@ +use std::{ + fmt::Display, + io::{self, Write}, + panic::{catch_unwind, resume_unwind}, + process::Command, + sync::Arc, +}; + +use crossterm::{ + cursor, + event::{Event, KeyCode, KeyEventKind, KeyModifiers, read}, + execute, + terminal::*, +}; +use rayon::iter::{ParallelBridge, ParallelIterator}; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum Version { + Stable(usize), + Beta, + Nightly, +} + +impl Version { + fn iterate() -> impl Iterator { + (0..=95) + .filter(|i| *i != 32) + .map(Self::Stable) + .chain([Self::Beta, Self::Nightly]) + } +} + +impl Display for Version { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Version::Stable(v) => write!(f, "1.{v}.0"), + Version::Beta => write!(f, "beta"), + Version::Nightly => write!(f, "nightly"), + } + } +} + +#[derive(Clone, PartialEq, Eq)] +struct Entry { + output: Arc>, + output_noansi: Arc>, + version: Version, +} + +fn run_rustc(version: Version, args: &[String]) -> io::Result { + let mut cmd = Command::new("rustc"); + cmd.arg(format!("+{version}")) + .args(["--color", "always"]) + .args(args); + + let output = cmd.output()?; + + Ok(Entry { + output: Arc::new(output.stderr.clone()), + output_noansi: Arc::new(strip_ansi_escapes::strip(output.stderr)), + version, + }) +} + +fn tui(changes: Vec) -> io::Result<()> { + let mut curr = 0; + + loop { + { + let mut stdout = io::stdout().lock(); + execute!(&mut stdout, Clear(ClearType::All))?; + execute!(&mut stdout, cursor::MoveTo(0, 0))?; + + let entry = &changes[curr]; + writeln!(&mut stdout, "in version {}\r", entry.version)?; + stdout.write_all( + &entry + .output + .as_ref() + .iter() + .flat_map(|&i| if i == b'\n' { vec![b'\r', i] } else { vec![i] }) + .collect::>(), + )?; + writeln!(&mut stdout)?; + } + + match read()? { + Event::Key(event) if let KeyEventKind::Press = event.kind => match event.code { + KeyCode::Esc | KeyCode::Char('q') => break, + KeyCode::Char('c') if event.modifiers.contains(KeyModifiers::CONTROL) => break, + KeyCode::Left => { + curr = curr.saturating_sub(1); + } + KeyCode::Right => { + if curr < changes.len() - 1 { + curr += 1; + } + } + KeyCode::Home => { + curr = 0; + } + KeyCode::End => { + curr = changes.len() - 1; + } + _ => {} + }, + _ => {} + } + } + + Ok(()) +} + +fn main() -> io::Result<()> { + let args = std::env::args().skip(1).collect::>(); + + let mut outputs = Version::iterate() + .par_bridge() + .flat_map(|version| { + eprintln!("compiling {version}"); + let output = match run_rustc(version, &args) { + Ok(i) => i, + Err(e) => { + eprintln!("{e}"); + return None; + } + }; + + Some(output) + }) + .collect::>(); + + outputs.sort_by_key(|i| i.version); + + let mut changes = Vec::new(); + let mut last = None::; + for curr in outputs { + if let Some(last) = &last + // && last.output_noansi == curr.output_noansi + && last.output == curr.output + { + continue; + } + + last = Some(curr.clone()); + changes.push(curr); + } + + if changes.is_empty() { + eprintln!("no changes"); + return Ok(()); + } + + enable_raw_mode()?; + let unwind = catch_unwind(move || -> io::Result<()> { + execute!(io::stdout(), EnterAlternateScreen)?; + tui(changes)?; + Ok(()) + }); + let _ = execute!(io::stdout(), LeaveAlternateScreen); + let _ = disable_raw_mode(); + match unwind { + Err(e) => resume_unwind(e), + Ok(r) => r?, + } + + Ok(()) +}