-
Notifications
You must be signed in to change notification settings - Fork 1.7k
minor: sync from downstream #18317
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
minor: sync from downstream #18317
Conversation
Subtree update of `rust-analyzer` r? `@ghost`
Rollup of 3 pull requests Successful merges: - #131348 (More `rustc_infer` cleanups) - #131392 (Drop compiletest legacy directive check) - #131395 (Add a mailmap entry for bjorn3) r? `@ghost` `@rustbot` modify labels: rollup
…r=Mark-Simulacrum use precompiled rustc for non-dist builders Makes non-dist builders to use precompiled CI rustc by default if they are available for the target triple. As we are going to make `rust.download-rustc=if-unchanged` default option with rust-lang/rust#119899, we need to make sure `if-unchanged` logic never breaks and works as expected. As an addition, this will significantly improve the build times on CI when there's no change on the compiler. blocker for #119899 try-job: x86_64-gnu-nopt try-job: aarch64-apple
Prevent building cargo from invalidating build cache of other tools due to conditionally applied `-Zon-broken-pipe=kill` via tracked `RUSTFLAGS` This PR fixes #130980 where building cargo invalidated the tool build caches of other tools (such as rustdoc) because `-Zon-broken-pipe=kill` was conditionally passed via `RUSTFLAGS` for other tools *except* for cargo. The differing `RUSTFLAGS` triggered tool build cache invalidation as `RUSTFLAGS` is a tracked env var -- any changes in `RUSTFLAGS` requires a rebuild. `-Zon-broken-pipe=kill` is load-bearing for rustc and rustdoc to not ICE on broken pipes due to usages of raw std `println!` that panics without the flag being set, which manifests in ICEs. I can't say I like the changes here, but it is what it is... See detailed discussions and history of `-Zon-broken-pipe=kill` usage in https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Internal.20lint.20for.20raw.20.60print!.60.20and.20.60println!.60.3F/near/474593815. ## Approach This PR fixes the tool build cache invalidation by informing the `rustc` binary shim when to apply `-Zon-broken-pipe=kill` (i.e. when the rustc binary shim is not used to build cargo). This information is not communicated by `RUSTFLAGS`, which is an env var tracked by cargo, and instead uses an untracked env var `UNTRACKED_BROKEN_PIPE_FLAG` so we won't trigger tool build cache invalidation. We preserve bootstrap's behavior of not setting that flag for cargo by conditionally omitting setting `UNTRACKED_BROKEN_PIPE_FLAG` when building cargo. Notably, the `-Zon-broken-pipe=kill` instance in https://github.com/rust-lang/rust/blob/1e5719bdc40bb553089ce83525f07dfe0b2e71e9/src/bootstrap/src/core/build_steps/compile.rs#L1058 is not modified because that is used to build rustc only and not cargo itself. Thanks to `@cuviper` for the idea! ## Testing ### Integration testing This PR introduces a run-make test for rustc and rustdoc that checks that when they do not ICE/panic when they encounter a broken pipe of the stdout stream. I checked this test will catch the broken pipe ICE regression for rustc on Linux (at least) by commenting out https://github.com/rust-lang/rust/blob/1e5719bdc40bb553089ce83525f07dfe0b2e71e9/src/bootstrap/src/core/build_steps/compile.rs#L1058, and the test failed because rustc ICE'd. ### Manual testing I have manually tried: 1. `./x clean && `./x test build --stage 1` -> `rustc +stage1 --print=sysroot | false`: no ICE. 2. `./x clean` -> `./x test run-make` twice: no stage 1 cargo rebuilds. 3. `./x clean` -> `./x build rustdoc` -> `rustdoc +stage1 --version | false`: no panics. 4. `./x test src/tools/cargo`: tests pass, notably `build::close_output` and `cargo_command::closed_output_ok` do not fail which would fail if cargo was built with `-Zon-broken-pipe=kill`. ## Related discussions Thanks to everyone who helped! - https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo/topic/Applying.20.60-Zon-broken-pipe.3Dkill.60.20flags.20in.20bootstrap.3F - https://rust-lang.zulipchat.com/#narrow/stream/326414-t-infra.2Fbootstrap/topic/Modifying.20run-make.20tests.20unnecessarily.20rebuild.20stage.201.20.2E.2E.2E - https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Internal.20lint.20for.20raw.20.60print!.60.20and.20.60println!.60.3F Fixes rust-lang/rust#130980 Closes rust-lang/rust#131059 --- try-job: aarch64-apple try-job: x86_64-msvc try-job: x86_64-mingw
Reserve guarded string literals (RFC 3593) Implementation for RFC 3593, including: - lexer / parser changes - diagnostics - migration lint - tests We reserve `#"`, `##"`, `###"`, `####`, and any other string of four or more repeated `#`. This avoids infinite lookahead in the lexer, though we still use infinite lookahead in the parser to provide better forward compatibility diagnostics. This PR does not implement any special lexing of the string internals: - strings preceded by one or more `#` are denied - regardless of the number of trailing `#` - string contents are lexed as if it was just a bare `"string"` Tracking issue: #123735 RFC: rust-lang/rfcs#3593
…raheemdev Library: Rename "object safe" to "dyn compatible" Completed T-lang FCP: rust-lang/lang-team#286 (comment). Tracking issue: rust-lang/rust#130852 Regarding https://github.com/rust-lang/rust/labels/relnotes, I guess I will manually open a https://github.com/rust-lang/rust/labels/relnotes-tracking-issue since this change affects everything (compiler, library, tools, docs, books, everyday language). r? ghost
…icing_at_ends, r=cuviper Add docs about slicing slices at the ends Closes rust-lang/rust#60783
…trochenkov Fix needless_lifetimes in rustc_serialize Hi, This PR fixes the following clipy warnings: ``` warning: the following explicit lifetimes could be elided: 'a --> compiler/rustc_serialize/src/serialize.rs:328:6 | 328 | impl<'a, S: Encoder, T: Encodable<S>> Encodable<S> for Cow<'a, [T]> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes = note: `#[warn(clippy::needless_lifetimes)]` on by default help: elide the lifetimes | 328 - impl<'a, S: Encoder, T: Encodable<S>> Encodable<S> for Cow<'a, [T]> 328 + impl<S: Encoder, T: Encodable<S>> Encodable<S> for Cow<'_, [T]> | warning: the following explicit lifetimes could be elided: 'a --> compiler/rustc_serialize/src/serialize.rs:348:6 | 348 | impl<'a, S: Encoder> Encodable<S> for Cow<'a, str> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 348 - impl<'a, S: Encoder> Encodable<S> for Cow<'a, str> { 348 + impl<S: Encoder> Encodable<S> for Cow<'_, str> { | warning: the following explicit lifetimes could be elided: 'a --> compiler/rustc_serialize/src/serialize.rs:355:6 | 355 | impl<'a, D: Decoder> Decodable<D> for Cow<'a, str> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 355 - impl<'a, D: Decoder> Decodable<D> for Cow<'a, str> { 355 + impl<D: Decoder> Decodable<D> for Cow<'_, str> { ``` Best regards, Michal
…r=notriddle Fix methods alignment on mobile I realized that on mobile, the methods are not aligned the same depending if they have documentation or not: | before | after | |-|-| |  |  | r? `@notriddle`
Decouple WASIp2 sockets from WasiFd This is a follow up to #129638, decoupling WASIp2's socket implementation from WASIp1's `WasiFd` as discussed with `@alexcrichton.` Quite a few trait implementations in `std::os::fd` rely on the fact that there is an additional layer of abstraction between `Socket` and `OwnedFd`. I thus had to add a thin `WasiSocket` wrapper struct that just "forwards" to `OwnedFd`. Alternatively, I could have added a lot of conditional compilation to `std::os::fd`, which feels even worse. Since `WasiFd::sock_accept` is no longer accessible from `TcpListener` and since WASIp2 has proper support for accepting sockets through `Socket::accept`, the `std::os::wasi::net` module has been removed from WASIp2, which only contains a single `TcpListenerExt` trait with a `sock_accept` method as well as an implementation for `TcpListener`. Let me know if this is an acceptable solution.
Mention allocation errors for `open_buffered` This documents that `File::open_buffered` may return an error on allocation failure.
Rollup of 7 pull requests Successful merges: - #123951 (Reserve guarded string literals (RFC 3593)) - #130827 (Library: Rename "object safe" to "dyn compatible") - #131383 (Add docs about slicing slices at the ends) - #131403 (Fix needless_lifetimes in rustc_serialize) - #131417 (Fix methods alignment on mobile) - #131449 (Decouple WASIp2 sockets from WasiFd) - #131462 (Mention allocation errors for `open_buffered`) r? `@ghost` `@rustbot` modify labels: rollup
disable `download-rustc` if LLVM submodule has changes in CI We can't use CI rustc while using in-tree LLVM (which happens in LLVM submodule update PRs) and this PR handles that by ignoring CI-rustc in CI and failing in non-CI environments.
…eywiser Retire the `unnamed_fields` feature for now `#![feature(unnamed_fields)]` was implemented in part in #115131 and #115367, however work on that feature has (afaict) stalled and in the mean time there have been some concerns raised (e.g.[^1][^2]) about whether `unnamed_fields` is worthwhile to have in the language, especially in its current desugaring. Because it represents a compiler implementation burden including a new kind of anonymous ADT and additional complication to field selection, and is quite prone to bugs today, I'm choosing to remove the feature. However, since I'm not one to really write a bunch of words, I'm specifically *not* going to de-RFC this feature. This PR essentially *rolls back* the state of this feature to "RFC accepted but not yet implemented"; however if anyone wants to formally unapprove the RFC from the t-lang side, then please be my guest. I'm just not totally willing to summarize the various language-facing reasons for why this feature is or is not worthwhile, since I'm coming from the compiler side mostly. Fixes #117942 Fixes #121161 Fixes #121263 Fixes #121299 Fixes #121722 Fixes #121799 Fixes #126969 Fixes #131041 Tracking: * rust-lang/rust#49804 [^1]: https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Unnamed.20struct.2Funion.20fields [^2]: rust-lang/rust#49804 (comment)
Optimize `escape_ascii` using a lookup table Based upon my suggestion here: rust-lang/rust#125340 (comment) Effectively, we can take advantage of the fact that ASCII only needs 7 bits to make the eighth bit store whether the value should be escaped or not. This adds a 256-byte lookup table, but 256 bytes *should* be small enough that very few people will mind, according to my probably not incontrovertible opinion. The generated assembly isn't clearly better (although has fewer branches), so, I decided to benchmark on three inputs: first on a random 200KiB, then on `/bin/cat`, then on `Cargo.toml` for this repo. In all cases, the generated code ran faster on my machine. (an old i7-8700) But, if you want to try my benchmarking code for yourself: <details><summary>Criterion code below. Replace <code>/home/ltdk/rustsrc</code> with the appropriate directory.</summary> ```rust #![feature(ascii_char)] #![feature(ascii_char_variants)] #![feature(const_option)] #![feature(let_chains)] use core::ascii; use core::ops::Range; use criterion::{criterion_group, criterion_main, Criterion}; use rand::{thread_rng, Rng}; const HEX_DIGITS: [ascii::Char; 16] = *b"0123456789abcdef".as_ascii().unwrap(); #[inline] const fn backslash<const N: usize>(a: ascii::Char) -> ([ascii::Char; N], Range<u8>) { const { assert!(N >= 2) }; let mut output = [ascii::Char::Null; N]; output[0] = ascii::Char::ReverseSolidus; output[1] = a; (output, 0..2) } #[inline] const fn hex_escape<const N: usize>(byte: u8) -> ([ascii::Char; N], Range<u8>) { const { assert!(N >= 4) }; let mut output = [ascii::Char::Null; N]; let hi = HEX_DIGITS[(byte >> 4) as usize]; let lo = HEX_DIGITS[(byte & 0xf) as usize]; output[0] = ascii::Char::ReverseSolidus; output[1] = ascii::Char::SmallX; output[2] = hi; output[3] = lo; (output, 0..4) } #[inline] const fn verbatim<const N: usize>(a: ascii::Char) -> ([ascii::Char; N], Range<u8>) { const { assert!(N >= 1) }; let mut output = [ascii::Char::Null; N]; output[0] = a; (output, 0..1) } /// Escapes an ASCII character. /// /// Returns a buffer and the length of the escaped representation. const fn escape_ascii_old<const N: usize>(byte: u8) -> ([ascii::Char; N], Range<u8>) { const { assert!(N >= 4) }; match byte { b'\t' => backslash(ascii::Char::SmallT), b'\r' => backslash(ascii::Char::SmallR), b'\n' => backslash(ascii::Char::SmallN), b'\\' => backslash(ascii::Char::ReverseSolidus), b'\'' => backslash(ascii::Char::Apostrophe), b'\"' => backslash(ascii::Char::QuotationMark), 0x00..=0x1F => hex_escape(byte), _ => match ascii::Char::from_u8(byte) { Some(a) => verbatim(a), None => hex_escape(byte), }, } } /// Escapes an ASCII character. /// /// Returns a buffer and the length of the escaped representation. const fn escape_ascii_new<const N: usize>(byte: u8) -> ([ascii::Char; N], Range<u8>) { /// Lookup table helps us determine how to display character. /// /// Since ASCII characters will always be 7 bits, we can exploit this to store the 8th bit to /// indicate whether the result is escaped or unescaped. /// /// We additionally use 0x80 (escaped NUL character) to indicate hex-escaped bytes, since /// escaped NUL will not occur. const LOOKUP: [u8; 256] = { let mut arr = [0; 256]; let mut idx = 0; loop { arr[idx as usize] = match idx { // use 8th bit to indicate escaped b'\t' => 0x80 | b't', b'\r' => 0x80 | b'r', b'\n' => 0x80 | b'n', b'\\' => 0x80 | b'\\', b'\'' => 0x80 | b'\'', b'"' => 0x80 | b'"', // use NUL to indicate hex-escaped 0x00..=0x1F | 0x7F..=0xFF => 0x80 | b'\0', _ => idx, }; if idx == 255 { break; } idx += 1; } arr }; let lookup = LOOKUP[byte as usize]; // 8th bit indicates escape let lookup_escaped = lookup & 0x80 != 0; // SAFETY: We explicitly mask out the eighth bit to get a 7-bit ASCII character. let lookup_ascii = unsafe { ascii::Char::from_u8_unchecked(lookup & 0x7F) }; if lookup_escaped { // NUL indicates hex-escaped if matches!(lookup_ascii, ascii::Char::Null) { hex_escape(byte) } else { backslash(lookup_ascii) } } else { verbatim(lookup_ascii) } } fn escape_bytes(bytes: &[u8], f: impl Fn(u8) -> ([ascii::Char; 4], Range<u8>)) -> Vec<ascii::Char> { let mut vec = Vec::new(); for b in bytes { let (buf, range) = f(*b); vec.extend_from_slice(&buf[range.start as usize..range.end as usize]); } vec } pub fn criterion_benchmark(c: &mut Criterion) { let mut group = c.benchmark_group("escape_ascii"); group.sample_size(1000); let rand_200k = &mut [0; 200 * 1024]; thread_rng().fill(&mut rand_200k[..]); let cat = include_bytes!("/bin/cat"); let cargo_toml = include_bytes!("/home/ltdk/rustsrc/Cargo.toml"); group.bench_function("old_rand", |b| { b.iter(|| escape_bytes(rand_200k, escape_ascii_old)); }); group.bench_function("new_rand", |b| { b.iter(|| escape_bytes(rand_200k, escape_ascii_new)); }); group.bench_function("old_bin", |b| { b.iter(|| escape_bytes(cat, escape_ascii_old)); }); group.bench_function("new_bin", |b| { b.iter(|| escape_bytes(cat, escape_ascii_new)); }); group.bench_function("old_cargo_toml", |b| { b.iter(|| escape_bytes(cargo_toml, escape_ascii_old)); }); group.bench_function("new_cargo_toml", |b| { b.iter(|| escape_bytes(cargo_toml, escape_ascii_new)); }); group.finish(); } criterion_group!(benches, criterion_benchmark); criterion_main!(benches); ``` </details> My benchmark results: ``` escape_ascii/old_rand time: [1.6965 ms 1.7006 ms 1.7053 ms] Found 22 outliers among 1000 measurements (2.20%) 4 (0.40%) high mild 18 (1.80%) high severe escape_ascii/new_rand time: [1.6749 ms 1.6953 ms 1.7158 ms] Found 38 outliers among 1000 measurements (3.80%) 38 (3.80%) high mild escape_ascii/old_bin time: [224.59 µs 225.40 µs 226.33 µs] Found 39 outliers among 1000 measurements (3.90%) 17 (1.70%) high mild 22 (2.20%) high severe escape_ascii/new_bin time: [164.86 µs 165.63 µs 166.58 µs] Found 107 outliers among 1000 measurements (10.70%) 43 (4.30%) high mild 64 (6.40%) high severe escape_ascii/old_cargo_toml time: [23.397 µs 23.699 µs 24.014 µs] Found 204 outliers among 1000 measurements (20.40%) 21 (2.10%) high mild 183 (18.30%) high severe escape_ascii/new_cargo_toml time: [16.404 µs 16.438 µs 16.483 µs] Found 88 outliers among 1000 measurements (8.80%) 56 (5.60%) high mild 32 (3.20%) high severe ``` Random: 1.7006ms => 1.6953ms (<1% speedup) Binary: 225.40µs => 165.63µs (26% speedup) Text: 23.699µs => 16.438µs (30% speedup)
Add `#[track_caller]` to allocating methods of `Vec` & `VecDeque` Part 4 in a lengthy saga. r? `@joshtriplett` because they were the reviewer the last 3 times. `@bors` rollup=never "[just in case this has perf effects, Vec is hot](rust-lang/rust#79323 (comment))" This was first attempted in #79323 by `@nvzqz.` It got approval from `@joshtriplett,` but rotted with merge conflicts and got closed. Then it got picked up by `@Dylan-DPC-zz` in #83359. A benchmark was run[^perf], the results (after a bit of thinking[^thinking]) were deemed ok[^ok], but there was a typo[^typo] and the PR was made from a wrong remote in the first place[^remote], so #83909 was opened instead. By the time #83909 rolled around, the methods in question had received some optimizations[^optimizations], so another perf run was conducted[^perf2]. The results were ok[^ok2]. There was a suggestion to add regression tests for panic behavior [^tests], but before it could be addressed, the PR fell victim to merge conflicts[^conflicts] and died again[^rip]. 3 years have passed, and (from what I can tell) this has not been tried again, so here I am now, reviving this old effort. Given how much time has passed and the fact that I've also touched `VecDeque` this time, it probably makes sense to `@bors` try `@rust-timer` [^perf]: rust-lang/rust#83359 (comment) [^thinking]: rust-lang/rust#83359 (comment) [^ok]: rust-lang/rust#83359 (comment) [^typo]: rust-lang/rust#83359 (comment) [^remote]: rust-lang/rust#83359 (comment) [^optimizations]: rust-lang/rust#83909 (comment) [^perf2]: rust-lang/rust#83909 (comment) [^ok2]: rust-lang/rust#83909 (comment) [^tests]: rust-lang/rust#83909 (comment) [^conflicts]: rust-lang/rust#83909 (comment) [^rip]: rust-lang/rust#83909 (comment)
Optimize `Box::default` and `Arc::default` to construct more types in place Both the `Arc` and `Box` `Default` impls currently call `T::default()` before allocating, and then moving the resulting `T` into the allocation. Most `Default` impls are trivial, which should in theory allow LLVM to construct `T: Default` directly in the `Box` allocation when calling `<Box<T>>::default()`. However, the allocation may fail, which necessitates calling `T`'s destructor if it has one. If the destructor is non-trivial, then LLVM has a hard time proving that it's sound to elide, which makes it construct `T` on the stack first, and then copy it into the allocation. Change both of these impls to allocate first, and then call `T::default` into the uninitialized allocation, so that LLVM doesn't have to prove that it's sound to elide the destructor/initial stack copy. For example, given the following Rust code: ```rust #[derive(Default, Clone)] struct Foo { x: Vec<u8>, z: String, y: Vec<u8>, } #[no_mangle] pub fn src() -> Box<Foo> { Box::default() } ``` <details open> <summary>Before this PR:</summary> ```llvm `@__rust_no_alloc_shim_is_unstable` = external global i8 ; drop_in_place() generated in case the allocation fails ; core::ptr::drop_in_place<playground::Foo> ; Function Attrs: nounwind nonlazybind uwtable define internal fastcc void `@"_ZN4core3ptr36drop_in_place$LT$playground..Foo$GT$17hff376aece491233bE"(ptr` noalias nocapture noundef readonly align 8 dereferenceable(72) %_1) unnamed_addr #0 personality ptr `@rust_eh_personality` { start: %_1.val = load i64, ptr %_1, align 8 %0 = icmp eq i64 %_1.val, 0 br i1 %0, label %bb6, label %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i" "_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i": ; preds = %start %1 = getelementptr inbounds i8, ptr %_1, i64 8 %_1.val6 = load ptr, ptr %1, align 8, !nonnull !3, !noundef !3 tail call void `@__rust_dealloc(ptr` noundef nonnull %_1.val6, i64 noundef %_1.val, i64 noundef 1) rust-lang#8 br label %bb6 bb6: ; preds = %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i", %start %2 = getelementptr inbounds i8, ptr %_1, i64 24 %.val9 = load i64, ptr %2, align 8 %3 = icmp eq i64 %.val9, 0 br i1 %3, label %bb5, label %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i.i11" "_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i.i11": ; preds = %bb6 %4 = getelementptr inbounds i8, ptr %_1, i64 32 %.val10 = load ptr, ptr %4, align 8, !nonnull !3, !noundef !3 tail call void `@__rust_dealloc(ptr` noundef nonnull %.val10, i64 noundef %.val9, i64 noundef 1) rust-lang#8 br label %bb5 bb5: ; preds = %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i.i11", %bb6 %5 = getelementptr inbounds i8, ptr %_1, i64 48 %.val4 = load i64, ptr %5, align 8 %6 = icmp eq i64 %.val4, 0 br i1 %6, label %"_ZN4core3ptr46drop_in_place$LT$alloc..vec..Vec$LT$u8$GT$$GT$17hb5ca95423e113cf7E.exit16", label %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i15" "_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i15": ; preds = %bb5 %7 = getelementptr inbounds i8, ptr %_1, i64 56 %.val5 = load ptr, ptr %7, align 8, !nonnull !3, !noundef !3 tail call void `@__rust_dealloc(ptr` noundef nonnull %.val5, i64 noundef %.val4, i64 noundef 1) rust-lang#8 br label %"_ZN4core3ptr46drop_in_place$LT$alloc..vec..Vec$LT$u8$GT$$GT$17hb5ca95423e113cf7E.exit16" "_ZN4core3ptr46drop_in_place$LT$alloc..vec..Vec$LT$u8$GT$$GT$17hb5ca95423e113cf7E.exit16": ; preds = %bb5, %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i15" ret void } ; Function Attrs: nonlazybind uwtable define noalias noundef nonnull align 8 ptr `@src()` unnamed_addr rust-lang#1 personality ptr `@rust_eh_personality` { start: ; alloca to place `Foo` in. %_1 = alloca [72 x i8], align 8 call void `@llvm.lifetime.start.p0(i64` 72, ptr nonnull %_1) store i64 0, ptr %_1, align 8 %_2.sroa.4.0._1.sroa_idx = getelementptr inbounds i8, ptr %_1, i64 8 store ptr inttoptr (i64 1 to ptr), ptr %_2.sroa.4.0._1.sroa_idx, align 8 %_2.sroa.5.0._1.sroa_idx = getelementptr inbounds i8, ptr %_1, i64 16 %_3.sroa.4.0..sroa_idx = getelementptr inbounds i8, ptr %_1, i64 32 call void `@llvm.memset.p0.i64(ptr` noundef nonnull align 8 dereferenceable(16) %_2.sroa.5.0._1.sroa_idx, i8 0, i64 16, i1 false) store ptr inttoptr (i64 1 to ptr), ptr %_3.sroa.4.0..sroa_idx, align 8 %_3.sroa.5.0..sroa_idx = getelementptr inbounds i8, ptr %_1, i64 40 %_4.sroa.4.0..sroa_idx = getelementptr inbounds i8, ptr %_1, i64 56 call void `@llvm.memset.p0.i64(ptr` noundef nonnull align 8 dereferenceable(16) %_3.sroa.5.0..sroa_idx, i8 0, i64 16, i1 false) store ptr inttoptr (i64 1 to ptr), ptr %_4.sroa.4.0..sroa_idx, align 8 %_4.sroa.5.0..sroa_idx = getelementptr inbounds i8, ptr %_1, i64 64 store i64 0, ptr %_4.sroa.5.0..sroa_idx, align 8 %0 = load volatile i8, ptr `@__rust_no_alloc_shim_is_unstable,` align 1, !noalias !4 %_0.i.i.i = tail call noalias noundef align 8 dereferenceable_or_null(72) ptr `@__rust_alloc(i64` noundef 72, i64 noundef 8) rust-lang#8, !noalias !4 %1 = icmp eq ptr %_0.i.i.i, null br i1 %1, label %bb2.i, label %"_ZN5alloc5boxed12Box$LT$T$GT$3new17h0864de14f863a27aE.exit" bb2.i: ; preds = %start ; invoke alloc::alloc::handle_alloc_error invoke void `@_ZN5alloc5alloc18handle_alloc_error17h98142d0d8d74161bE(i64` noundef 8, i64 noundef 72) rust-lang#9 to label %.noexc unwind label %cleanup.i .noexc: ; preds = %bb2.i unreachable cleanup.i: ; preds = %bb2.i %2 = landingpad { ptr, i32 } cleanup ; call core::ptr::drop_in_place<playground::Foo> call fastcc void `@"_ZN4core3ptr36drop_in_place$LT$playground..Foo$GT$17hff376aece491233bE"(ptr` noalias noundef nonnull align 8 dereferenceable(72) %_1) rust-lang#10 resume { ptr, i32 } %2 "_ZN5alloc5boxed12Box$LT$T$GT$3new17h0864de14f863a27aE.exit": ; preds = %start ; Copy from stack to heap if allocation is successful call void `@llvm.memcpy.p0.p0.i64(ptr` noundef nonnull align 8 dereferenceable(72) %_0.i.i.i, ptr noundef nonnull align 8 dereferenceable(72) %_1, i64 72, i1 false) call void `@llvm.lifetime.end.p0(i64` 72, ptr nonnull %_1) ret ptr %_0.i.i.i } ``` </details> <details> <summary>After this PR</summary> ```llvm ; Notice how there's no `drop_in_place()` generated as well define noalias noundef nonnull align 8 ptr `@src()` unnamed_addr #0 personality ptr `@rust_eh_personality` { start: ; no stack allocation %0 = load volatile i8, ptr `@__rust_no_alloc_shim_is_unstable,` align 1 %_0.i.i.i.i.i = tail call noalias noundef align 8 dereferenceable_or_null(72) ptr `@__rust_alloc(i64` noundef 72, i64 noundef 8) rust-lang#5 %1 = icmp eq ptr %_0.i.i.i.i.i, null br i1 %1, label %bb3.i, label %"_ZN5alloc5boxed16Box$LT$T$C$A$GT$13new_uninit_in17h80d6355ef4b73ea3E.exit" bb3.i: ; preds = %start ; call alloc::alloc::handle_alloc_error tail call void `@_ZN5alloc5alloc18handle_alloc_error17h98142d0d8d74161bE(i64` noundef 8, i64 noundef 72) rust-lang#6 unreachable "_ZN5alloc5boxed16Box$LT$T$C$A$GT$13new_uninit_in17h80d6355ef4b73ea3E.exit": ; preds = %start ; construct `Foo` directly into the allocation if successful store i64 0, ptr %_0.i.i.i.i.i, align 8 %_8.sroa.4.0._1.sroa_idx = getelementptr inbounds i8, ptr %_0.i.i.i.i.i, i64 8 store ptr inttoptr (i64 1 to ptr), ptr %_8.sroa.4.0._1.sroa_idx, align 8 %_8.sroa.5.0._1.sroa_idx = getelementptr inbounds i8, ptr %_0.i.i.i.i.i, i64 16 %_8.sroa.7.0._1.sroa_idx = getelementptr inbounds i8, ptr %_0.i.i.i.i.i, i64 32 tail call void `@llvm.memset.p0.i64(ptr` noundef nonnull align 8 dereferenceable(16) %_8.sroa.5.0._1.sroa_idx, i8 0, i64 16, i1 false) store ptr inttoptr (i64 1 to ptr), ptr %_8.sroa.7.0._1.sroa_idx, align 8 %_8.sroa.8.0._1.sroa_idx = getelementptr inbounds i8, ptr %_0.i.i.i.i.i, i64 40 %_8.sroa.10.0._1.sroa_idx = getelementptr inbounds i8, ptr %_0.i.i.i.i.i, i64 56 tail call void `@llvm.memset.p0.i64(ptr` noundef nonnull align 8 dereferenceable(16) %_8.sroa.8.0._1.sroa_idx, i8 0, i64 16, i1 false) store ptr inttoptr (i64 1 to ptr), ptr %_8.sroa.10.0._1.sroa_idx, align 8 %_8.sroa.11.0._1.sroa_idx = getelementptr inbounds i8, ptr %_0.i.i.i.i.i, i64 64 store i64 0, ptr %_8.sroa.11.0._1.sroa_idx, align 8 ret ptr %_0.i.i.i.i.i } ``` </details>
@bors r+ |
💔 Test failed - checks-actions |
bench_data/numerous_macro_rules
Outdated
@@ -528,7 +528,7 @@ macro_rules! __ra_macro_fixture526 {($expr : expr )=>{|| -> _ { Some ($expr )}( | |||
macro_rules! __ra_macro_fixture527 {($($arg : tt )*)=>($crate :: io :: _print ($crate :: format_args ! ($($arg )*))); } | |||
macro_rules! __ra_macro_fixture528 {($fmt : literal , $($tt : tt ),*)=>{ mbe :: ExpandError :: ProcMacroError ( tt :: ExpansionError :: Unknown ( format ! ($fmt , $($tt ),*)))}; ($fmt : literal )=>{ mbe :: ExpandError :: ProcMacroError ( tt :: ExpansionError :: Unknown ($fmt . to_string ()))}} | |||
macro_rules! __ra_macro_fixture529 {($($tt : tt )* )=>{$crate :: quote :: IntoTt :: to_subtree ($crate :: __quote ! ($($tt )*))}} | |||
macro_rules! __ra_macro_fixture530 {()=>{ Vec ::< tt :: TokenTree >:: new ()}; (@ SUBTREE $delim : ident $($tt : tt )* )=>{{ let children = $crate :: __quote ! ($($tt )*); tt :: Subtree { delimiter : Some ( tt :: Delimiter { kind : tt :: DelimiterKind ::$delim , id : tt :: TokenId :: unspecified (), }), token_trees : $crate :: quote :: IntoTt :: to_tokens ( children ), }}}; (@ PUNCT $first : literal )=>{{ vec ! [ tt :: Leaf :: Punct ( tt :: Punct { char : $first , spacing : tt :: Spacing :: Alone , id : tt :: TokenId :: unspecified (), }). into ()]}}; (@ PUNCT $first : literal , $sec : literal )=>{{ vec ! [ tt :: Leaf :: Punct ( tt :: Punct { char : $first , spacing : tt :: Spacing :: Joint , id : tt :: TokenId :: unspecified (), }). into (), tt :: Leaf :: Punct ( tt :: Punct { char : $sec , spacing : tt :: Spacing :: Alone , id : tt :: TokenId :: unspecified (), }). into ()]}}; (# $first : ident $($tail : tt )* )=>{{ let token = $crate :: quote :: ToTokenTree :: to_token ($first ); let mut tokens = vec ! [ token . into ()]; let mut tail_tokens = $crate :: quote :: IntoTt :: to_tokens ($crate :: __quote ! ($($tail )*)); tokens . append (& mut tail_tokens ); tokens }}; (## $first : ident $($tail : tt )* )=>{{ let mut tokens = $first . into_iter (). map ($crate :: quote :: ToTokenTree :: to_token ). collect ::< Vec < tt :: TokenTree >> (); let mut tail_tokens = $crate :: quote :: IntoTt :: to_tokens ($crate :: __quote ! ($($tail )*)); tokens . append (& mut tail_tokens ); tokens }}; ({$($tt : tt )* })=>{$crate :: __quote ! (@ SUBTREE Brace $($tt )*)}; ([$($tt : tt )* ])=>{$crate :: __quote ! (@ SUBTREE Bracket $($tt )*)}; (($($tt : tt )* ))=>{$crate :: __quote ! (@ SUBTREE Parenthesis $($tt )*)}; ($tt : literal )=>{ vec ! [$crate :: quote :: ToTokenTree :: to_token ($tt ). into ()]}; ($tt : ident )=>{ vec ! [{ tt :: Leaf :: Ident ( tt :: Ident { text : stringify ! ($tt ). into (), id : tt :: TokenId :: unspecified (), }). into ()}]}; (-> )=>{$crate :: __quote ! (@ PUNCT '-' , '>' )}; (& )=>{$crate :: __quote ! (@ PUNCT '&' )}; (, )=>{$crate :: __quote ! (@ PUNCT ',' )}; (: )=>{$crate :: __quote ! (@ PUNCT ':' )}; (; )=>{$crate :: __quote ! (@ PUNCT ';' )}; (:: )=>{$crate :: __quote ! (@ PUNCT ':' , ':' )}; (. )=>{$crate :: __quote ! (@ PUNCT '.' )}; (< )=>{$crate :: __quote ! (@ PUNCT '<' )}; (> )=>{$crate :: __quote ! (@ PUNCT '>' )}; ($first : tt $($tail : tt )+ )=>{{ let mut tokens = $crate :: quote :: IntoTt :: to_tokens ($crate :: __quote ! ($first )); let mut tail_tokens = $crate :: quote :: IntoTt :: to_tokens ($crate :: __quote ! ($($tail )*)); tokens . append (& mut tail_tokens ); tokens }}; } | |||
macro_rules! __ra_macro_fixture530 {()=>{ Vec ::< tt :: TokenTree >:: new ()}; (@ SUBTREE $delim : ident $($tt : tt )* )=>{{ let children = $crate :: __quote ! ($($tt )*); tt :: Subtree { delimiter : Some ( tt :: Delimiter { kind : tt :: DelimiterKind ::$delim , id : tt :: TokenId :: unspecified (), }), token_trees : $crate :: quote :: IntoTt :: to_tokens ( children ), }}}; (@ PUNCT $first : literal )=>{{ vec ! [ tt :: Leaf :: Punct ( tt :: Punct { char : $first , spacing : tt :: Spacing :: Alone , id : tt :: TokenId :: unspecified (), }). into ()]}}; (@ PUNCT $first : literal , $sec : literal )=>{{ vec ! [ tt :: Leaf :: Punct ( tt :: Punct { char : $first , spacing : tt :: Spacing :: Joint , id : tt :: TokenId :: unspecified (), }). into (), tt :: Leaf :: Punct ( tt :: Punct { char : $sec , spacing : tt :: Spacing :: Alone , id : tt :: TokenId :: unspecified (), }). into ()]}}; (! $first : ident $($tail : tt )* )=>{{ let token = $crate :: quote :: ToTokenTree :: to_token ($first ); let mut tokens = vec ! [ token . into ()]; let mut tail_tokens = $crate :: quote :: IntoTt :: to_tokens ($crate :: __quote ! ($($tail )*)); tokens . append (& mut tail_tokens ); tokens }}; (!! $first : ident $($tail : tt )* )=>{{ let mut tokens = $first . into_iter (). map ($crate :: quote :: ToTokenTree :: to_token ). collect ::< Vec < tt :: TokenTree >> (); let mut tail_tokens = $crate :: quote :: IntoTt :: to_tokens ($crate :: __quote ! ($($tail )*)); tokens . append (& mut tail_tokens ); tokens }}; ({$($tt : tt )* })=>{$crate :: __quote ! (@ SUBTREE Brace $($tt )*)}; ([$($tt : tt )* ])=>{$crate :: __quote ! (@ SUBTREE Bracket $($tt )*)}; (($($tt : tt )* ))=>{$crate :: __quote ! (@ SUBTREE Parenthesis $($tt )*)}; ($tt : literal )=>{ vec ! [$crate :: quote :: ToTokenTree :: to_token ($tt ). into ()]}; ($tt : ident )=>{ vec ! [{ tt :: Leaf :: Ident ( tt :: Ident { text : stringify ! ($tt ). into (), id : tt :: TokenId :: unspecified (), }). into ()}]}; (-> )=>{$crate :: __quote ! (@ PUNCT '-' , '>' )}; (& )=>{$crate :: __quote ! (@ PUNCT '&' )}; (, )=>{$crate :: __quote ! (@ PUNCT ',' )}; (: )=>{$crate :: __quote ! (@ PUNCT ':' )}; (; )=>{$crate :: __quote ! (@ PUNCT ';' )}; (:: )=>{$crate :: __quote ! (@ PUNCT ':' , ':' )}; (. )=>{$crate :: __quote ! (@ PUNCT '.' )}; (< )=>{$crate :: __quote ! (@ PUNCT '<' )}; (> )=>{$crate :: __quote ! (@ PUNCT '>' )}; ($first : tt $($tail : tt )+ )=>{{ let mut tokens = $crate :: quote :: IntoTt :: to_tokens ($crate :: __quote ! ($first )); let mut tail_tokens = $crate :: quote :: IntoTt :: to_tokens ($crate :: __quote ! ($($tail )*)); tokens . append (& mut tail_tokens ); tokens }}; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed (## $first : ident $($tail : tt )* )
to (!! $first : ident $($tail : tt )* )
here.
@bors r+ |
💔 Test failed - checks-actions |
crates/parser/src/lexed_str.rs
Outdated
@@ -187,6 +187,12 @@ impl<'a> Converter<'a> { | |||
} | |||
|
|||
rustc_lexer::TokenKind::RawIdent => IDENT, | |||
|
|||
rustc_lexer::TokenKind::GuardedStrPrefix => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yuck we need to break the token apart here in < Edition2024 (https://github.com/rust-lang/rust/pull/123951/files#diff-36d0ff95049fa1b66bdd47ec2c03e1588268303571a9561d1ba664ca29034dacR792)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm afraid I'm gonna let you handle that 😅. And we need to drop my fixture change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will see when I get to that (up for grabs for other readers). I was also confused as to how this didn't break our test upstream but I forgot upstream doesn't run our tests (except for proc-macro-srv) ... We should make them run them :^)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought they were disabled because of the impact on CI time, but no, it was because they were failing on 32-bit, and RA was being built with optimizations: rust-lang/rust#113244.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay nvm, its merely the prefix so we should be able to just treat it as a # token
4fe13a3
to
2fe603e
Compare
@bors r+ |
☀️ Test successful - checks-actions |
No description provided.