diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c51ca9c..fb85faa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - rust: [1.56.0, stable, beta] + rust: [1.63.0, stable, beta] timeout-minutes: 45 steps: - uses: actions/checkout@v4 @@ -78,6 +78,29 @@ jobs: env: RUSTFLAGS: -Z allow-features= --cfg procmacro2_backtrace ${{env.RUSTFLAGS}} + msrv: + name: Rust 1.56.0 + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@1.56.0 + with: + components: rust-src + - run: cargo check + - run: cargo check --no-default-features + - run: cargo check --features span-locations + - name: RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo check + run: cargo check + env: + RUSTFLAGS: --cfg procmacro2_semver_exempt ${{env.RUSTFLAGS}} + - name: RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo check --no-default-features + run: cargo check --no-default-features + env: + RUSTFLAGS: --cfg procmacro2_semver_exempt ${{env.RUSTFLAGS}} + minimal: name: Minimal versions needs: pre_ci diff --git a/Cargo.toml b/Cargo.toml index 6f7c786..b0cf584 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,8 +24,11 @@ features = ["span-locations"] unicode-ident = "1.0" [dev-dependencies] +flate2 = "1.0" quote = { version = "1.0", default_features = false } +rayon = "1.0" rustversion = "1" +tar = "0.4" [features] proc-macro = [] diff --git a/src/extra.rs b/src/extra.rs index d3496f2..543ec1d 100644 --- a/src/extra.rs +++ b/src/extra.rs @@ -20,6 +20,50 @@ use core::fmt::{self, Debug}; /// gigabytes). After a wraparound, `Span` methods such as `source_text()` can /// return wrong data. /// +/// # Example +/// +/// As of late 2023, there is 200 GB of Rust code published on crates.io. +/// Looking at just the newest version of every crate, it is 16 GB of code. So a +/// workload that involves parsing it all would overflow a 32-bit source +/// location unless spans are being invalidated. +/// +/// ``` +/// use flate2::read::GzDecoder; +/// use std::ffi::OsStr; +/// use std::io::{BufReader, Read}; +/// use std::str::FromStr; +/// use tar::Archive; +/// +/// rayon::scope(|s| { +/// for krate in every_version_of_every_crate() { +/// s.spawn(move |_| { +/// proc_macro2::extra::invalidate_current_thread_spans(); +/// +/// let reader = BufReader::new(krate); +/// let tar = GzDecoder::new(reader); +/// let mut archive = Archive::new(tar); +/// for entry in archive.entries().unwrap() { +/// let mut entry = entry.unwrap(); +/// let path = entry.path().unwrap(); +/// if path.extension() != Some(OsStr::new("rs")) { +/// continue; +/// } +/// let mut content = String::new(); +/// entry.read_to_string(&mut content).unwrap(); +/// match proc_macro2::TokenStream::from_str(&content) { +/// Ok(tokens) => {/* ... */}, +/// Err(_) => continue, +/// } +/// } +/// }); +/// } +/// }); +/// # +/// # fn every_version_of_every_crate() -> Vec { +/// # Vec::new() +/// # } +/// ``` +/// /// # Panics /// /// This function is not applicable to and will panic if called from a