From 0d49862998b3695297dffba21c80b35fb73e245d Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 10 Jul 2024 13:05:03 -0500 Subject: [PATCH 01/62] Clarify/add `must_use` messages for more `into_raw*` functions of `alloc` types. --- library/alloc/src/boxed.rs | 2 ++ library/alloc/src/rc.rs | 2 ++ library/alloc/src/string.rs | 2 +- library/alloc/src/vec/mod.rs | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 65bcb241e4ae..21fd8d24af3d 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1097,6 +1097,7 @@ impl Box { /// ``` /// /// [memory layout]: self#memory-layout + #[must_use = "losing the pointer will leak memory"] #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub fn into_raw(b: Self) -> *mut T { @@ -1150,6 +1151,7 @@ impl Box { /// ``` /// /// [memory layout]: self#memory-layout + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) { diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 3745ecb48c18..af3ace96d9c2 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1372,6 +1372,7 @@ impl Rc { /// let x = unsafe { Rc::from_raw_in(ptr, alloc) }; /// assert_eq!(&*x, "hello"); /// ``` + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "allocator_api", issue = "32838")] pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { let this = mem::ManuallyDrop::new(this); @@ -3100,6 +3101,7 @@ impl Weak { /// /// [`from_raw_in`]: Weak::from_raw_in /// [`as_ptr`]: Weak::as_ptr + #[must_use = "losing the pointer will leak memory"] #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub fn into_raw_with_allocator(self) -> (*const T, A) { diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 36078da7c35a..ede2a42d12fe 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -903,7 +903,7 @@ impl String { /// let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) }; /// assert_eq!(rebuilt, "hello"); /// ``` - #[must_use = "`self` will be dropped if the result is not used"] + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] pub fn into_raw_parts(self) -> (*mut u8, usize, usize) { self.vec.into_raw_parts() diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 6e9b017ad75c..b01ccb384834 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -879,6 +879,7 @@ impl Vec { /// }; /// assert_eq!(rebuilt, [4294967295, 0, 1]); /// ``` + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] pub fn into_raw_parts(self) -> (*mut T, usize, usize) { let mut me = ManuallyDrop::new(self); @@ -922,6 +923,7 @@ impl Vec { /// }; /// assert_eq!(rebuilt, [4294967295, 0, 1]); /// ``` + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) { From 6d477d3a9de714d877a9eda48b0eda3e12e301be Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 10 Jul 2024 13:08:24 -0500 Subject: [PATCH 02/62] Add `must_use` to IntoRawFd/IntoRawSocket/IntoRawHandle's methods. --- library/std/src/os/fd/raw.rs | 1 + library/std/src/os/solid/io.rs | 1 + library/std/src/os/windows/io/raw.rs | 2 ++ 3 files changed, 4 insertions(+) diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index ef896ea95c9c..9d6fcaa3634d 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -138,6 +138,7 @@ pub trait IntoRawFd { /// let raw_fd: RawFd = f.into_raw_fd(); /// # Ok::<(), io::Error>(()) /// ``` + #[must_use = "losing the raw file descriptor may leak resources"] #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_fd(self) -> RawFd; } diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index 19b4fe22093c..13d8419830df 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -347,6 +347,7 @@ pub trait IntoRawFd { /// This function **transfers ownership** of the underlying file descriptor /// to the caller. Callers are then the unique owners of the file descriptor /// and must close the descriptor once it's no longer needed. + #[must_use = "losing the raw file descriptor may leak resources"] fn into_raw_fd(self) -> RawFd; } diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index 770583a9ce3e..e76650be742a 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -89,6 +89,7 @@ pub trait IntoRawHandle { /// However, transferring ownership is not strictly required. Use a /// `Into::into` implementation for an API which strictly /// transfers ownership. + #[must_use = "losing the raw handle may leak resources"] #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_handle(self) -> RawHandle; } @@ -230,6 +231,7 @@ pub trait IntoRawSocket { /// However, transferring ownership is not strictly required. Use a /// `Into::into` implementation for an API which strictly /// transfers ownership. + #[must_use = "losing the raw socket may leak resources"] #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_socket(self) -> RawSocket; } From 84d84daf1735d8996cdaf3aea487051215cffdf3 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 10 Jul 2024 21:03:25 -0500 Subject: [PATCH 03/62] Explicitly ignore `into_raw_handle()` using `let _ =` in sys/pal/windows. --- library/std/src/sys/pal/windows/process.rs | 2 +- library/std/src/sys/pal/windows/stdio.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/windows/process.rs b/library/std/src/sys/pal/windows/process.rs index c62764696b86..6b3b79149ce2 100644 --- a/library/std/src/sys/pal/windows/process.rs +++ b/library/std/src/sys/pal/windows/process.rs @@ -571,7 +571,7 @@ impl Stdio { Ok(io) => unsafe { let io = Handle::from_raw_handle(io); let ret = io.duplicate(0, true, c::DUPLICATE_SAME_ACCESS); - io.into_raw_handle(); + let _ = io.into_raw_handle(); // Don't close the handle ret }, // If no stdio handle is available, then propagate the null value. diff --git a/library/std/src/sys/pal/windows/stdio.rs b/library/std/src/sys/pal/windows/stdio.rs index 10aeeac07ea2..88b3996466ff 100644 --- a/library/std/src/sys/pal/windows/stdio.rs +++ b/library/std/src/sys/pal/windows/stdio.rs @@ -101,7 +101,7 @@ fn write( unsafe { let handle = Handle::from_raw_handle(handle); let ret = handle.write(data); - handle.into_raw_handle(); // Don't close the handle + let _ = handle.into_raw_handle(); // Don't close the handle return ret; } } @@ -250,7 +250,7 @@ impl io::Read for Stdin { unsafe { let handle = Handle::from_raw_handle(handle); let ret = handle.read(buf); - handle.into_raw_handle(); // Don't close the handle + let _ = handle.into_raw_handle(); // Don't close the handle return ret; } } From 8366c7fe9c2db004224648239644f0fbecc185ea Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 18 Jul 2024 11:54:04 -0300 Subject: [PATCH 04/62] Stabilize unsafe extern blocks (RFC 3484) --- .../rustc_ast_passes/src/ast_validation.rs | 42 ++++++------------- compiler/rustc_ast_passes/src/feature_gate.rs | 4 -- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/unstable.rs | 2 - compiler/rustc_lint_defs/src/builtin.rs | 1 - compiler/rustc_parse/src/parser/mod.rs | 3 -- tests/rustdoc/unsafe-extern-blocks.rs | 3 +- .../feature-gate-unsafe-extern-blocks.rs | 13 ------ .../feature-gate-unsafe-extern-blocks.stderr | 23 ---------- .../lint/unsafe_code/unsafe-extern-blocks.rs | 1 - .../unsafe_code/unsafe-extern-blocks.stderr | 4 +- tests/ui/parser/unsafe-foreign-mod-2.rs | 2 - tests/ui/parser/unsafe-foreign-mod-2.stderr | 18 +------- tests/ui/parser/unsafe-foreign-mod.rs | 6 +-- tests/ui/parser/unsafe-foreign-mod.stderr | 12 ------ tests/ui/rust-2024/safe-outside-extern.rs | 8 ---- tests/ui/rust-2024/safe-outside-extern.stderr | 38 +++++++++++++++++ .../extern-items-unsafe.edition2021.stderr | 4 +- .../extern-items-unsafe.edition2024.stderr | 4 +- .../extern-items-unsafe.rs | 2 - .../extern-items.edition2024.stderr | 2 +- .../unsafe-extern-blocks/extern-items.rs | 2 - .../unsafe-extern-blocks/safe-impl-trait.rs | 3 -- ...it.gated.stderr => safe-impl-trait.stderr} | 2 +- .../unsafe-extern-blocks/safe-items.rs | 2 - .../unsafe-extern-blocks/safe-trait.rs | 3 -- .../unsafe-extern-blocks/safe-trait.stderr | 8 ++++ ...-unadorned-extern-block.edition2021.stderr | 4 +- ...-unadorned-extern-block.edition2024.stderr | 6 +-- .../safe-unsafe-on-unadorned-extern-block.rs | 2 - .../unsafe-extern-suggestion.fixed | 1 - .../unsafe-extern-suggestion.rs | 1 - .../unsafe-extern-suggestion.stderr | 4 +- .../unsafe-items.edition2021.stderr | 4 +- .../unsafe-items.edition2024.stderr | 4 +- .../unsafe-extern-blocks/unsafe-items.rs | 2 - .../unsafe-on-extern-block-issue-126756.fixed | 1 - .../unsafe-on-extern-block-issue-126756.rs | 1 - ...unsafe-on-extern-block-issue-126756.stderr | 2 +- tests/ui/unpretty/expanded-exhaustive.rs | 1 - tests/ui/unpretty/expanded-exhaustive.stdout | 1 - 41 files changed, 85 insertions(+), 163 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs delete mode 100644 tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr delete mode 100644 tests/ui/parser/unsafe-foreign-mod.stderr create mode 100644 tests/ui/rust-2024/safe-outside-extern.stderr rename tests/ui/rust-2024/unsafe-extern-blocks/{safe-impl-trait.gated.stderr => safe-impl-trait.stderr} (83%) create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 34aac6e44730..af1d9beb527b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -452,11 +452,6 @@ impl<'a> AstValidator<'a> { item_span: span, block: Some(self.current_extern_span().shrink_to_lo()), }); - } else if !self.features.unsafe_extern_blocks { - self.dcx().emit_err(errors::InvalidSafetyOnExtern { - item_span: span, - block: None, - }); } } } @@ -1053,32 +1048,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> { errors::VisibilityNotPermittedNote::IndividualForeignItems, ); - if this.features.unsafe_extern_blocks { - if &Safety::Default == safety { - if item.span.at_least_rust_2024() { - this.dcx() - .emit_err(errors::MissingUnsafeOnExtern { span: item.span }); - } else { - this.lint_buffer.buffer_lint( - MISSING_UNSAFE_ON_EXTERN, - item.id, - item.span, - BuiltinLintDiag::MissingUnsafeOnExtern { - suggestion: item.span.shrink_to_lo(), - }, - ); - } + if &Safety::Default == safety { + if item.span.at_least_rust_2024() { + this.dcx().emit_err(errors::MissingUnsafeOnExtern { span: item.span }); + } else { + this.lint_buffer.buffer_lint( + MISSING_UNSAFE_ON_EXTERN, + item.id, + item.span, + BuiltinLintDiag::MissingUnsafeOnExtern { + suggestion: item.span.shrink_to_lo(), + }, + ); } - } else if let &Safety::Unsafe(span) = safety { - let mut diag = this - .dcx() - .create_err(errors::UnsafeItem { span, kind: "extern block" }); - rustc_session::parse::add_feature_diagnostics( - &mut diag, - self.session, - sym::unsafe_extern_blocks, - ); - diag.emit(); } if abi.is_none() { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index e91dfb277666..f9119c06fcf7 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -561,10 +561,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental"); gate_all!(global_registration, "global registration is experimental"); gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental"); - gate_all!( - unsafe_extern_blocks, - "`unsafe extern {}` blocks and `safe` keyword are experimental" - ); gate_all!(return_type_notation, "return type notation is experimental"); if !visitor.features.never_patterns { diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index e671c7682391..d5874f79a22c 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -387,6 +387,8 @@ declare_features! ( (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208)), /// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block. (accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668)), + /// Allows unsafe on extern declarations and safety qualifiers over internal items. + (accepted, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)), /// Allows importing and reexporting macros with `use`, /// enables macro modularization in general. (accepted, use_extern_macros, "1.30.0", Some(35896)), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 741c621db081..e1433a66556b 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -628,8 +628,6 @@ declare_features! ( (incomplete, unnamed_fields, "1.74.0", Some(49804)), /// Allows unsafe attributes. (unstable, unsafe_attributes, "1.80.0", Some(123757)), - /// Allows unsafe on extern declarations and safety qualifiers over internal items. - (unstable, unsafe_extern_blocks, "1.80.0", Some(123743)), /// Allows const generic parameters to be defined with types that /// are not `Sized`, e.g. `fn foo() {`. (incomplete, unsized_const_params, "CURRENT_RUSTC_VERSION", Some(95174)), diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 04764b71b100..4e1fbe8ae9d6 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4865,7 +4865,6 @@ declare_lint! { /// ### Example /// /// ```rust - /// #![feature(unsafe_extern_blocks)] /// #![warn(missing_unsafe_on_extern)] /// #![allow(dead_code)] /// diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 7326b9ec51f2..b46653717a4f 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1205,9 +1205,6 @@ impl<'a> Parser<'a> { if self.eat_keyword_case(kw::Unsafe, case) { Safety::Unsafe(self.prev_token.uninterpolated_span()) } else if self.eat_keyword_case(kw::Safe, case) { - self.psess - .gated_spans - .gate(sym::unsafe_extern_blocks, self.prev_token.uninterpolated_span()); Safety::Safe(self.prev_token.uninterpolated_span()) } else { Safety::Default diff --git a/tests/rustdoc/unsafe-extern-blocks.rs b/tests/rustdoc/unsafe-extern-blocks.rs index 22d3beea6c3a..829095f300f2 100644 --- a/tests/rustdoc/unsafe-extern-blocks.rs +++ b/tests/rustdoc/unsafe-extern-blocks.rs @@ -1,6 +1,5 @@ // Test to ensure the feature is working as expected. -#![feature(unsafe_extern_blocks)] #![crate_name = "foo"] // @has 'foo/index.html' @@ -13,7 +12,7 @@ // @count - '//ul[@class="item-table"]//sup[@title="unsafe function"]' 1 // @has - '//ul[@class="item-table"]//sup[@title="unsafe function"]' '⚠' -unsafe extern { +unsafe extern "C" { // @has 'foo/static.FOO.html' // @has - '//pre[@class="rust item-decl"]' 'pub static FOO: i32' pub safe static FOO: i32; diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs deleted file mode 100644 index 3ea62e875b8e..000000000000 --- a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs +++ /dev/null @@ -1,13 +0,0 @@ -unsafe extern "C" { - //~^ ERROR extern block cannot be declared unsafe -} - -// We can't gate `unsafe extern` blocks themselves since they were previously -// allowed, but we should gate the `safe` soft keyword. -#[cfg(any())] -unsafe extern "C" { - safe fn foo(); - //~^ ERROR `unsafe extern {}` blocks and `safe` keyword are experimental -} - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr deleted file mode 100644 index 565349463089..000000000000 --- a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error: extern block cannot be declared unsafe - --> $DIR/feature-gate-unsafe-extern-blocks.rs:1:1 - | -LL | unsafe extern "C" { - | ^^^^^^ - | - = note: see issue #123743 for more information - = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental - --> $DIR/feature-gate-unsafe-extern-blocks.rs:9:5 - | -LL | safe fn foo(); - | ^^^^ - | - = note: see issue #123743 for more information - = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs index 6f2ead70db80..c264fa1c8daf 100644 --- a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs +++ b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs @@ -1,4 +1,3 @@ -#![feature(unsafe_extern_blocks)] #![deny(unsafe_code)] #[allow(unsafe_code)] diff --git a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr index 5439a3112560..6d3b064da344 100644 --- a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr +++ b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr @@ -1,5 +1,5 @@ error: usage of an `unsafe extern` block - --> $DIR/unsafe-extern-blocks.rs:9:1 + --> $DIR/unsafe-extern-blocks.rs:8:1 | LL | / unsafe extern "C" { LL | | @@ -8,7 +8,7 @@ LL | | } | |_^ | note: the lint level is defined here - --> $DIR/unsafe-extern-blocks.rs:2:9 + --> $DIR/unsafe-extern-blocks.rs:1:9 | LL | #![deny(unsafe_code)] | ^^^^^^^^^^^ diff --git a/tests/ui/parser/unsafe-foreign-mod-2.rs b/tests/ui/parser/unsafe-foreign-mod-2.rs index 0b63a993c5b9..6d339cd90881 100644 --- a/tests/ui/parser/unsafe-foreign-mod-2.rs +++ b/tests/ui/parser/unsafe-foreign-mod-2.rs @@ -1,8 +1,6 @@ extern "C" unsafe { //~^ ERROR expected `{`, found keyword `unsafe` - //~| ERROR extern block cannot be declared unsafe unsafe fn foo(); - //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers } fn main() {} diff --git a/tests/ui/parser/unsafe-foreign-mod-2.stderr b/tests/ui/parser/unsafe-foreign-mod-2.stderr index 8bd592b5d431..0625e3362ed7 100644 --- a/tests/ui/parser/unsafe-foreign-mod-2.stderr +++ b/tests/ui/parser/unsafe-foreign-mod-2.stderr @@ -4,21 +4,5 @@ error: expected `{`, found keyword `unsafe` LL | extern "C" unsafe { | ^^^^^^ expected `{` -error: extern block cannot be declared unsafe - --> $DIR/unsafe-foreign-mod-2.rs:1:12 - | -LL | extern "C" unsafe { - | ^^^^^^ - | - = note: see issue #123743 for more information - = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/unsafe-foreign-mod-2.rs:4:5 - | -LL | unsafe fn foo(); - | ^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/parser/unsafe-foreign-mod.rs b/tests/ui/parser/unsafe-foreign-mod.rs index eab134a4a4de..623c3bb81e45 100644 --- a/tests/ui/parser/unsafe-foreign-mod.rs +++ b/tests/ui/parser/unsafe-foreign-mod.rs @@ -1,5 +1,5 @@ -unsafe extern "C" { - //~^ ERROR extern block cannot be declared unsafe -} +//@ check-pass + +unsafe extern "C" {} fn main() {} diff --git a/tests/ui/parser/unsafe-foreign-mod.stderr b/tests/ui/parser/unsafe-foreign-mod.stderr deleted file mode 100644 index 60b918a89b34..000000000000 --- a/tests/ui/parser/unsafe-foreign-mod.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error: extern block cannot be declared unsafe - --> $DIR/unsafe-foreign-mod.rs:1:1 - | -LL | unsafe extern "C" { - | ^^^^^^ - | - = note: see issue #123743 for more information - = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - diff --git a/tests/ui/rust-2024/safe-outside-extern.rs b/tests/ui/rust-2024/safe-outside-extern.rs index 6773df5ef03b..674b78dc571e 100644 --- a/tests/ui/rust-2024/safe-outside-extern.rs +++ b/tests/ui/rust-2024/safe-outside-extern.rs @@ -1,29 +1,21 @@ -//@ revisions: gated ungated -#![cfg_attr(gated, feature(unsafe_extern_blocks))] - safe fn foo() {} //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier -//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] safe static FOO: i32 = 1; //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier -//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] trait Foo { safe fn foo(); //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier - //[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] } impl Foo for () { safe fn foo() {} //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier - //[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] } type FnPtr = safe fn(i32, i32) -> i32; //~^ ERROR: function pointers cannot be declared with `safe` safety qualifier -//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] unsafe static LOL: u8 = 0; //~^ ERROR: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block diff --git a/tests/ui/rust-2024/safe-outside-extern.stderr b/tests/ui/rust-2024/safe-outside-extern.stderr new file mode 100644 index 000000000000..19d7c5fde0bd --- /dev/null +++ b/tests/ui/rust-2024/safe-outside-extern.stderr @@ -0,0 +1,38 @@ +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:1:1 + | +LL | safe fn foo() {} + | ^^^^^^^^^^^^^^^^ + +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:4:1 + | +LL | safe static FOO: i32 = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:8:5 + | +LL | safe fn foo(); + | ^^^^^^^^^^^^^^ + +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:13:5 + | +LL | safe fn foo() {} + | ^^^^^^^^^^^^^^^^ + +error: function pointers cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:17:14 + | +LL | type FnPtr = safe fn(i32, i32) -> i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block + --> $DIR/safe-outside-extern.rs:20:1 + | +LL | unsafe static LOL: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr index 3a99caa719b5..77554da10e60 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block - --> $DIR/extern-items-unsafe.rs:14:5 + --> $DIR/extern-items-unsafe.rs:12:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe function or block - --> $DIR/extern-items-unsafe.rs:14:11 + --> $DIR/extern-items-unsafe.rs:12:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr index fcf937b7ac57..33b752782d59 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block - --> $DIR/extern-items-unsafe.rs:14:5 + --> $DIR/extern-items-unsafe.rs:12:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe block - --> $DIR/extern-items-unsafe.rs:14:11 + --> $DIR/extern-items-unsafe.rs:12:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs index ad569a256db9..721e07acca58 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs @@ -3,8 +3,6 @@ //@[edition2024] edition:2024 //@[edition2024] compile-flags: -Zunstable-options -#![feature(unsafe_extern_blocks)] - unsafe extern "C" { static TEST1: i32; fn test1(i: i32); diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr index d456cfc6829e..8ef7c2caf21e 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr @@ -1,5 +1,5 @@ error: extern blocks must be unsafe - --> $DIR/extern-items.rs:9:1 + --> $DIR/extern-items.rs:7:1 | LL | / extern "C" { LL | | diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs index 16fa1bbb8a40..08805c363476 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs @@ -4,8 +4,6 @@ //@[edition2024] edition:2024 //@[edition2024] compile-flags: -Zunstable-options -#![feature(unsafe_extern_blocks)] - extern "C" { //[edition2024]~^ ERROR extern blocks must be unsafe static TEST1: i32; diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs index 57c03e4d896b..67df8c14b39f 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs @@ -1,6 +1,3 @@ -//@ revisions: gated ungated -#![cfg_attr(gated, feature(unsafe_extern_blocks))] - trait Bar {} safe impl Bar for () { } //~^ ERROR expected one of `!` or `::`, found keyword `impl` diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr similarity index 83% rename from tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr rename to tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr index 80e7a45f57e7..f1021726b181 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr @@ -1,5 +1,5 @@ error: expected one of `!` or `::`, found keyword `impl` - --> $DIR/safe-impl-trait.rs:5:6 + --> $DIR/safe-impl-trait.rs:2:6 | LL | safe impl Bar for () { } | ^^^^ expected one of `!` or `::` diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs index 74cd5621fce9..b0b8a8b012a6 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs @@ -4,8 +4,6 @@ //@[edition2024] compile-flags: -Zunstable-options //@ check-pass -#![feature(unsafe_extern_blocks)] - unsafe extern "C" { safe static TEST1: i32; safe fn test1(i: i32); diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs index e73cb45b1887..52773b4cbbbb 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs @@ -1,6 +1,3 @@ -//@ revisions: gated ungated -#![cfg_attr(gated, feature(unsafe_extern_blocks))] - safe trait Foo {} //~^ ERROR expected one of `!` or `::`, found keyword `trait` diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr new file mode 100644 index 000000000000..1733336a797b --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found keyword `trait` + --> $DIR/safe-trait.rs:1:6 + | +LL | safe trait Foo {} + | ^^^^^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr index e90613357b1c..937979872866 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr @@ -1,5 +1,5 @@ error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5 | LL | safe static TEST1: i32; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | unsafe extern "C" { | ++++++ error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 | LL | safe fn test1(i: i32); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr index 1207ee158cc1..e9db6006c0b5 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr @@ -1,5 +1,5 @@ error: extern blocks must be unsafe - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:1 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:6:1 | LL | / extern "C" { LL | | @@ -11,7 +11,7 @@ LL | | } | |_^ error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5 | LL | safe static TEST1: i32; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | unsafe extern "C" { | ++++++ error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 | LL | safe fn test1(i: i32); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs index 11f55cb195f2..4badb50b2673 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs @@ -3,8 +3,6 @@ //@[edition2024] edition:2024 //@[edition2024] compile-flags: -Zunstable-options -#![feature(unsafe_extern_blocks)] - extern "C" { //[edition2024]~^ ERROR extern blocks must be unsafe safe static TEST1: i32; diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed index 10c19759d8aa..f686809615fb 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed @@ -1,6 +1,5 @@ //@ run-rustfix -#![feature(unsafe_extern_blocks)] #![deny(missing_unsafe_on_extern)] #![allow(unused)] diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs index b81e52ddc584..00f1cbdab54f 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs @@ -1,6 +1,5 @@ //@ run-rustfix -#![feature(unsafe_extern_blocks)] #![deny(missing_unsafe_on_extern)] #![allow(unused)] diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr index 0a3c2cd25e3f..bb1d068ceb91 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr @@ -1,5 +1,5 @@ error: extern blocks should be unsafe - --> $DIR/unsafe-extern-suggestion.rs:7:1 + --> $DIR/unsafe-extern-suggestion.rs:6:1 | LL | extern "C" { | ^ @@ -16,7 +16,7 @@ LL | | } = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! = note: for more information, see issue #123743 note: the lint level is defined here - --> $DIR/unsafe-extern-suggestion.rs:4:9 + --> $DIR/unsafe-extern-suggestion.rs:3:9 | LL | #![deny(missing_unsafe_on_extern)] | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr index 8bb7ffefeea9..e3626bb497e4 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block - --> $DIR/unsafe-items.rs:20:5 + --> $DIR/unsafe-items.rs:18:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe function or block - --> $DIR/unsafe-items.rs:20:11 + --> $DIR/unsafe-items.rs:18:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr index 9a30142a632c..89bc501b7b5a 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block - --> $DIR/unsafe-items.rs:20:5 + --> $DIR/unsafe-items.rs:18:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe block - --> $DIR/unsafe-items.rs:20:11 + --> $DIR/unsafe-items.rs:18:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs index 9066953abc61..dc2bae892a98 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs @@ -3,8 +3,6 @@ //@[edition2024] edition:2024 //@[edition2024] compile-flags: -Zunstable-options -#![feature(unsafe_extern_blocks)] - unsafe extern "C" { unsafe static TEST1: i32; unsafe fn test1(i: i32); diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed index 2ff595cc44d1..857d34eef852 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed @@ -1,6 +1,5 @@ //@ run-rustfix -#![feature(unsafe_extern_blocks)] #![allow(dead_code)] unsafe extern "C" { diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs index 6fe43f7a5b46..edab9850d796 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs @@ -1,6 +1,5 @@ //@ run-rustfix -#![feature(unsafe_extern_blocks)] #![allow(dead_code)] extern "C" { diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr index 05d23d001ada..073245e650b1 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr @@ -1,5 +1,5 @@ error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/unsafe-on-extern-block-issue-126756.rs:7:5 + --> $DIR/unsafe-on-extern-block-issue-126756.rs:6:5 | LL | unsafe fn foo(); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index 92c2e7b48847..29472df897a1 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -25,7 +25,6 @@ #![feature(trait_alias)] #![feature(try_blocks)] #![feature(unnamed_fields)] -#![feature(unsafe_extern_blocks)] #![feature(yeet_expr)] #![allow(incomplete_features)] diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 137a8aa5510d..cf2f6f8cbaa9 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -26,7 +26,6 @@ #![feature(trait_alias)] #![feature(try_blocks)] #![feature(unnamed_fields)] -#![feature(unsafe_extern_blocks)] #![feature(yeet_expr)] #![allow(incomplete_features)] #[prelude_import] From 649b4310a3f0913a72e6a83cb54482d994ed248a Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Sun, 28 Jul 2024 22:20:01 +1000 Subject: [PATCH 05/62] Enable `std::io::copy` specialisation for `std::pipe::{PipeReader, PipeWriter}` Signed-off-by: Jiahao XU --- library/std/src/sys/pal/unix/kernel_copy.rs | 25 +++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/library/std/src/sys/pal/unix/kernel_copy.rs b/library/std/src/sys/pal/unix/kernel_copy.rs index cd38b7c07e2b..ae6b88b44753 100644 --- a/library/std/src/sys/pal/unix/kernel_copy.rs +++ b/library/std/src/sys/pal/unix/kernel_copy.rs @@ -54,6 +54,7 @@ use crate::net::TcpStream; use crate::os::unix::fs::FileTypeExt; use crate::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use crate::os::unix::net::UnixStream; +use crate::pipe::{PipeReader, PipeWriter}; use crate::process::{ChildStderr, ChildStdin, ChildStdout}; use crate::ptr; use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering}; @@ -404,6 +405,30 @@ impl CopyWrite for &UnixStream { } } +impl CopyRead for PipeReader { + fn properties(&self) -> CopyParams { + CopyParams(FdMeta::Pipe, Some(self.as_raw_fd())) + } +} + +impl CopyRead for &PipeReader { + fn properties(&self) -> CopyParams { + CopyParams(FdMeta::Pipe, Some(self.as_raw_fd())) + } +} + +impl CopyWrite for PipeWriter { + fn properties(&self) -> CopyParams { + CopyParams(FdMeta::Pipe, Some(self.as_raw_fd())) + } +} + +impl CopyWrite for &PipeWriter { + fn properties(&self) -> CopyParams { + CopyParams(FdMeta::Pipe, Some(self.as_raw_fd())) + } +} + impl CopyWrite for ChildStdin { fn properties(&self) -> CopyParams { CopyParams(FdMeta::Pipe, Some(self.as_raw_fd())) From 794434ec639277273d2154607bdcbe033691cc29 Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Wed, 24 Jul 2024 21:52:32 +0000 Subject: [PATCH 06/62] initial implementation of rustdoc nested aux-build --- src/tools/compiletest/src/command-list.rs | 2 + src/tools/compiletest/src/header.rs | 13 +++ src/tools/compiletest/src/runtest.rs | 104 ++++++++++++------ src/tools/compiletest/src/runtest/coverage.rs | 2 +- .../cargo-transitive-no-index/auxiliary/q.rs | 4 + .../cargo-transitive-no-index/auxiliary/t.rs | 6 + .../cargo-transitive-no-index/s.rs | 17 +++ .../cargo-transitive/auxiliary/q.rs | 6 + .../cargo-transitive/auxiliary/t.rs | 8 ++ .../cross-crate-info/cargo-transitive/s.rs | 24 ++++ .../cargo-two-no-index/auxiliary/f.rs | 4 + .../cross-crate-info/cargo-two-no-index/e.rs | 15 +++ .../cross-crate-info/cargo-two/auxiliary/f.rs | 6 + tests/rustdoc/cross-crate-info/cargo-two/e.rs | 21 ++++ .../index-on-last/auxiliary/f.rs | 4 + .../cross-crate-info/index-on-last/e.rs | 21 ++++ .../kitchen-sink/auxiliary/q.rs | 6 + .../kitchen-sink/auxiliary/r.rs | 8 ++ .../kitchen-sink/auxiliary/s.rs | 9 ++ .../kitchen-sink/auxiliary/t.rs | 8 ++ .../cross-crate-info/kitchen-sink/i.rs | 32 ++++++ .../single-crate-baseline/q.rs | 13 +++ .../single-crate-no-index/q.rs | 8 ++ .../transitive/auxiliary/q.rs | 4 + .../transitive/auxiliary/t.rs | 6 + .../rustdoc/cross-crate-info/transitive/s.rs | 9 ++ .../cross-crate-info/two/auxiliary/f.rs | 4 + tests/rustdoc/cross-crate-info/two/e.rs | 9 ++ .../working-dir-examples/q.rs | 10 ++ .../write-docs-somewhere-else/auxiliary/f.rs | 5 + .../write-docs-somewhere-else/e.rs | 15 +++ 31 files changed, 369 insertions(+), 34 deletions(-) create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive/s.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs create mode 100644 tests/rustdoc/cross-crate-info/cargo-two/e.rs create mode 100644 tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs create mode 100644 tests/rustdoc/cross-crate-info/index-on-last/e.rs create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/i.rs create mode 100644 tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs create mode 100644 tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs create mode 100644 tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs create mode 100644 tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs create mode 100644 tests/rustdoc/cross-crate-info/transitive/s.rs create mode 100644 tests/rustdoc/cross-crate-info/two/auxiliary/f.rs create mode 100644 tests/rustdoc/cross-crate-info/two/e.rs create mode 100644 tests/rustdoc/cross-crate-info/working-dir-examples/q.rs create mode 100644 tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs create mode 100644 tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index c356f4266f01..305bf9c228c4 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -9,6 +9,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "aux-codegen-backend", "aux-crate", "build-aux-docs", + "unique-doc-out-dir", "build-fail", "build-pass", "check-fail", @@ -18,6 +19,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "check-test-line-numbers-match", "compare-output-lines-by-subset", "compile-flags", + "doc-flags", "dont-check-compiler-stderr", "dont-check-compiler-stdout", "dont-check-failure-status", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 0208ed34ac18..3a08a8e38950 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -95,6 +95,8 @@ pub struct TestProps { pub compile_flags: Vec, // Extra flags to pass when the compiled code is run (such as --bench) pub run_flags: Vec, + /// Extra flags to pass to rustdoc but not the compiler. + pub doc_flags: Vec, // If present, the name of a file that this test should match when // pretty-printed pub pp_exact: Option, @@ -122,6 +124,9 @@ pub struct TestProps { pub unset_exec_env: Vec, // Build documentation for all specified aux-builds as well pub build_aux_docs: bool, + /// Build the documentation for each crate in a unique output directory. + /// Uses /docs//doc + pub unique_doc_out_dir: bool, // Flag to force a crate to be built with the host architecture pub force_host: bool, // Check stdout for error-pattern output as well as stderr @@ -220,8 +225,10 @@ mod directives { pub const REGEX_ERROR_PATTERN: &'static str = "regex-error-pattern"; pub const COMPILE_FLAGS: &'static str = "compile-flags"; pub const RUN_FLAGS: &'static str = "run-flags"; + pub const DOC_FLAGS: &'static str = "doc-flags"; pub const SHOULD_ICE: &'static str = "should-ice"; pub const BUILD_AUX_DOCS: &'static str = "build-aux-docs"; + pub const UNIQUE_DOC_OUT_DIR: &'static str = "unique-doc-out-dir"; pub const FORCE_HOST: &'static str = "force-host"; pub const CHECK_STDOUT: &'static str = "check-stdout"; pub const CHECK_RUN_RESULTS: &'static str = "check-run-results"; @@ -267,6 +274,7 @@ impl TestProps { regex_error_patterns: vec![], compile_flags: vec![], run_flags: vec![], + doc_flags: vec![], pp_exact: None, aux_builds: vec![], aux_bins: vec![], @@ -281,6 +289,7 @@ impl TestProps { exec_env: vec![], unset_exec_env: vec![], build_aux_docs: false, + unique_doc_out_dir: false, force_host: false, check_stdout: false, check_run_results: false, @@ -377,6 +386,8 @@ impl TestProps { |r| r, ); + config.push_name_value_directive(ln, DOC_FLAGS, &mut self.doc_flags, |r| r); + fn split_flags(flags: &str) -> Vec { // Individual flags can be single-quoted to preserve spaces; see // . @@ -414,6 +425,8 @@ impl TestProps { config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice); config.set_name_directive(ln, BUILD_AUX_DOCS, &mut self.build_aux_docs); + config.set_name_directive(ln, UNIQUE_DOC_OUT_DIR, &mut self.unique_doc_out_dir); + config.set_name_directive(ln, FORCE_HOST, &mut self.force_host); config.set_name_directive(ln, CHECK_STDOUT, &mut self.check_stdout); config.set_name_directive(ln, CHECK_RUN_RESULTS, &mut self.check_run_results); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f6e8fdd62443..2d298dfbc06f 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1,5 +1,17 @@ // ignore-tidy-filelength +use crate::compute_diff::{write_diff, write_filtered_diff}; +use crate::errors::{self, Error, ErrorKind}; +use crate::header::TestProps; +use crate::json; +use crate::read2::{read2_abbreviated, Truncated}; +use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, static_regex, PathBufExt}; +use crate::ColorConfig; +use colored::Colorize; +use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile}; +use regex::{Captures, Regex}; +use rustfix::{apply_suggestions, get_suggestions_from_json, Filter}; +use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use std::ffi::{OsStr, OsString}; use std::fs::{self, create_dir_all, File, OpenOptions}; @@ -723,7 +735,7 @@ impl<'test> TestCx<'test> { self.maybe_add_external_args(&mut rustc, &self.config.target_rustcflags); rustc.args(&self.props.compile_flags); - self.compose_and_run_compiler(rustc, Some(src)) + self.compose_and_run_compiler(rustc, Some(src), self.testpaths) } fn run_debuginfo_test(&self) { @@ -1579,13 +1591,15 @@ impl<'test> TestCx<'test> { passes, ); - self.compose_and_run_compiler(rustc, None) + self.compose_and_run_compiler(rustc, None, self.testpaths) } - fn document(&self, out_dir: &Path) -> ProcRes { + /// `root_out_dir` and `root_testpaths` refer to the parameters of the actual test being run. + /// Auxiliaries, no matter how deep, have the same root_out_dir and root_testpaths. + fn document(&self, root_out_dir: &Path, root_testpaths: &TestPaths) -> ProcRes { if self.props.build_aux_docs { for rel_ab in &self.props.aux_builds { - let aux_testpaths = self.compute_aux_test_paths(&self.testpaths, rel_ab); + let aux_testpaths = self.compute_aux_test_paths(root_testpaths, rel_ab); let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); let aux_cx = TestCx { @@ -1596,7 +1610,7 @@ impl<'test> TestCx<'test> { }; // Create the directory for the stdout/stderr files. create_dir_all(aux_cx.output_base_dir()).unwrap(); - let auxres = aux_cx.document(out_dir); + let auxres = aux_cx.document(&root_out_dir, root_testpaths); if !auxres.status.success() { return auxres; } @@ -1606,21 +1620,47 @@ impl<'test> TestCx<'test> { let aux_dir = self.aux_output_dir_name(); let rustdoc_path = self.config.rustdoc_path.as_ref().expect("--rustdoc-path not passed"); - let mut rustdoc = Command::new(rustdoc_path); + // actual --out-dir given to the auxiliary or test, as opposed to the root out dir for the entire + // test + let out_dir: Cow<'_, Path> = if self.props.unique_doc_out_dir { + let file_name = self + .testpaths + .file + .file_name() + .expect("file name should not be empty") + .to_str() + .expect("file name utf8") + .trim_end_matches(".rs"); + let out_dir = PathBuf::from_iter([ + root_out_dir, + Path::new("docs"), + Path::new(file_name), + Path::new("doc"), + ]); + create_dir_all(&out_dir).unwrap(); + Cow::Owned(out_dir) + } else { + Cow::Borrowed(root_out_dir) + }; + + let mut rustdoc = Command::new(rustdoc_path); + let current_dir = output_base_dir(self.config, root_testpaths, self.safe_revision()); + rustdoc.current_dir(current_dir); rustdoc .arg("-L") .arg(self.config.run_lib_path.to_str().unwrap()) .arg("-L") .arg(aux_dir) .arg("-o") - .arg(out_dir) + .arg(out_dir.as_ref()) .arg("--deny") .arg("warnings") .arg(&self.testpaths.file) .arg("-A") .arg("internal_features") - .args(&self.props.compile_flags); + .args(&self.props.compile_flags) + .args(&self.props.doc_flags); if self.config.mode == RustdocJson { rustdoc.arg("--output-format").arg("json").arg("-Zunstable-options"); @@ -1630,7 +1670,7 @@ impl<'test> TestCx<'test> { rustdoc.arg(format!("-Clinker={}", linker)); } - self.compose_and_run_compiler(rustdoc, None) + self.compose_and_run_compiler(rustdoc, None, root_testpaths) } fn exec_compiled_test(&self) -> ProcRes { @@ -1828,9 +1868,16 @@ impl<'test> TestCx<'test> { } } - fn compose_and_run_compiler(&self, mut rustc: Command, input: Option) -> ProcRes { + /// `root_testpaths` refers to the path of the original test. + /// the auxiliary and the test with an aux-build have the same `root_testpaths`. + fn compose_and_run_compiler( + &self, + mut rustc: Command, + input: Option, + root_testpaths: &TestPaths, + ) -> ProcRes { let aux_dir = self.aux_output_dir(); - self.build_all_auxiliary(&self.testpaths, &aux_dir, &mut rustc); + self.build_all_auxiliary(root_testpaths, &aux_dir, &mut rustc); rustc.envs(self.props.rustc_env.clone()); self.props.unset_rustc_env.iter().fold(&mut rustc, Command::env_remove); @@ -2545,7 +2592,7 @@ impl<'test> TestCx<'test> { Vec::new(), ); - let proc_res = self.compose_and_run_compiler(rustc, None); + let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths); let output_path = self.get_filecheck_file("ll"); (proc_res, output_path) } @@ -2581,7 +2628,7 @@ impl<'test> TestCx<'test> { Vec::new(), ); - let proc_res = self.compose_and_run_compiler(rustc, None); + let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths); let output_path = self.get_filecheck_file("s"); (proc_res, output_path) } @@ -2664,7 +2711,7 @@ impl<'test> TestCx<'test> { let out_dir = self.output_base_dir(); remove_and_create_dir_all(&out_dir); - let proc_res = self.document(&out_dir); + let proc_res = self.document(&out_dir, &self.testpaths); if !proc_res.status.success() { self.fatal_proc_rec("rustdoc failed!", &proc_res); } @@ -2723,7 +2770,7 @@ impl<'test> TestCx<'test> { let aux_dir = new_rustdoc.aux_output_dir(); new_rustdoc.build_all_auxiliary(&new_rustdoc.testpaths, &aux_dir, &mut rustc); - let proc_res = new_rustdoc.document(&compare_dir); + let proc_res = new_rustdoc.document(&compare_dir, &new_rustdoc.testpaths); if !proc_res.status.success() { eprintln!("failed to run nightly rustdoc"); return; @@ -2846,7 +2893,7 @@ impl<'test> TestCx<'test> { let out_dir = self.output_base_dir(); remove_and_create_dir_all(&out_dir); - let proc_res = self.document(&out_dir); + let proc_res = self.document(&out_dir, &self.testpaths); if !proc_res.status.success() { self.fatal_proc_rec("rustdoc failed!", &proc_res); } @@ -2922,24 +2969,15 @@ impl<'test> TestCx<'test> { fn check_rustdoc_test_option(&self, res: ProcRes) { let mut other_files = Vec::new(); let mut files: HashMap> = HashMap::new(); - let cwd = env::current_dir().unwrap(); - files.insert( - self.testpaths - .file - .strip_prefix(&cwd) - .unwrap_or(&self.testpaths.file) - .to_str() - .unwrap() - .replace('\\', "/"), - self.get_lines(&self.testpaths.file, Some(&mut other_files)), - ); + let normalized = fs::canonicalize(&self.testpaths.file).expect("failed to canonicalize"); + let normalized = normalized.to_str().unwrap().replace('\\', "/"); + files.insert(normalized, self.get_lines(&self.testpaths.file, Some(&mut other_files))); for other_file in other_files { let mut path = self.testpaths.file.clone(); path.set_file_name(&format!("{}.rs", other_file)); - files.insert( - path.strip_prefix(&cwd).unwrap_or(&path).to_str().unwrap().replace('\\', "/"), - self.get_lines(&path, None), - ); + let path = fs::canonicalize(path).expect("failed to canonicalize"); + let normalized = path.to_str().unwrap().replace('\\', "/"); + files.insert(normalized, self.get_lines(&path, None)); } let mut tested = 0; @@ -3778,7 +3816,7 @@ impl<'test> TestCx<'test> { if let Some(nodejs) = &self.config.nodejs { let out_dir = self.output_base_dir(); - self.document(&out_dir); + self.document(&out_dir, &self.testpaths); let root = self.config.find_rust_src_root().unwrap(); let file_stem = @@ -4094,7 +4132,7 @@ impl<'test> TestCx<'test> { rustc.arg(crate_name); } - let res = self.compose_and_run_compiler(rustc, None); + let res = self.compose_and_run_compiler(rustc, None, self.testpaths); if !res.status.success() { self.fatal_proc_rec("failed to compile fixed code", &res); } diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs index 6ee147da5a96..05191a159801 100644 --- a/src/tools/compiletest/src/runtest/coverage.rs +++ b/src/tools/compiletest/src/runtest/coverage.rs @@ -191,7 +191,7 @@ impl<'test> TestCx<'test> { rustdoc_cmd.arg(&self.testpaths.file); - let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None); + let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None, self.testpaths); if !proc_res.status.success() { self.fatal_proc_rec("rustdoc --test failed!", &proc_res) } diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs new file mode 100644 index 000000000000..32ad96d3e8e3 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs @@ -0,0 +1,4 @@ +//@ build-aux-docs + + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs new file mode 100644 index 000000000000..e03c9a1c68c3 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs @@ -0,0 +1,6 @@ +//@ aux-build:q.rs +//@ build-aux-docs + + +extern crate q; +pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs new file mode 100644 index 000000000000..af0d31c733ee --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs @@ -0,0 +1,17 @@ +//@ aux-build:t.rs +//@ build-aux-docs + +//@ has t/trait.Tango.html +//@ hasraw search-index.js 'Quebec' +//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' +//@ hasraw s/struct.Sierra.html 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Tango' +//@ has q/struct.Quebec.html +//@ has s/struct.Sierra.html + +// We document multiple crates into the same output directory, which merges the cross-crate information. Everything is available. + +extern crate t; +pub struct Sierra; +impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs new file mode 100644 index 000000000000..e32fdbaabfe2 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs @@ -0,0 +1,6 @@ +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs new file mode 100644 index 000000000000..0a49072b68a6 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs @@ -0,0 +1,8 @@ +//@ aux-build:q.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +extern crate q; +pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs new file mode 100644 index 000000000000..b050fbdf67d9 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs @@ -0,0 +1,24 @@ +//@ aux-build:t.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has t/trait.Tango.html +//@ hasraw search-index.js 'Quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' +//@ hasraw s/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' +//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't' +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Tango' +//@ has index.html +//@ has q/struct.Quebec.html +//@ has s/struct.Sierra.html + +// We document multiple crates into the same output directory, which merges the cross-crate information. Everything is available. + +extern crate t; +pub struct Sierra; +impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs new file mode 100644 index 000000000000..1bfc785535b5 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs @@ -0,0 +1,4 @@ +//@ build-aux-docs + + +pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs new file mode 100644 index 000000000000..d3e42989b777 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs @@ -0,0 +1,15 @@ +//@ aux-build:f.rs +//@ build-aux-docs + +//@ hasraw search-index.js 'Echo' +//@ hasraw search-index.js 'Foxtrot' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ has f/trait.Foxtrot.html +//@ has e/enum.Echo.html +//@ hasraw e/enum.Echo.html 'Foxtrot' + +// document two crates in the same way that cargo does. do not provide --enable-index-page + +extern crate f; +pub enum Echo {} +impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs new file mode 100644 index 000000000000..e84835b3e310 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs @@ -0,0 +1,6 @@ +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two/e.rs b/tests/rustdoc/cross-crate-info/cargo-two/e.rs new file mode 100644 index 000000000000..bb845877b52f --- /dev/null +++ b/tests/rustdoc/cross-crate-info/cargo-two/e.rs @@ -0,0 +1,21 @@ +//@ aux-build:f.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ hasraw search-index.js 'Echo' +//@ hasraw search-index.js 'Foxtrot' +//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e' +//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ has f/trait.Foxtrot.html +//@ has index.html '//h1' 'List of all crates' +//@ has e/enum.Echo.html +//@ has index.html +//@ hasraw e/enum.Echo.html 'Foxtrot' + +// document two crates in the same way that cargo does, writing them both into the same output directory + +extern crate f; +pub enum Echo {} +impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs new file mode 100644 index 000000000000..1bfc785535b5 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs @@ -0,0 +1,4 @@ +//@ build-aux-docs + + +pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/index-on-last/e.rs b/tests/rustdoc/cross-crate-info/index-on-last/e.rs new file mode 100644 index 000000000000..876b94464c37 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/index-on-last/e.rs @@ -0,0 +1,21 @@ +//@ aux-build:f.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ hasraw search-index.js 'Echo' +//@ hasraw search-index.js 'Foxtrot' +//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e' +//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ has f/trait.Foxtrot.html +//@ has index.html '//h1' 'List of all crates' +//@ has e/enum.Echo.html +//@ has index.html +//@ hasraw e/enum.Echo.html 'Foxtrot' + +// only declare --enable-index-page to the last rustdoc invocation + +extern crate f; +pub enum Echo {} +impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs new file mode 100644 index 000000000000..e32fdbaabfe2 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs @@ -0,0 +1,6 @@ +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs new file mode 100644 index 000000000000..c0ada1aea1a8 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs @@ -0,0 +1,8 @@ +//@ aux-build:s.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +extern crate s; +pub type Romeo = s::Sierra; diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs new file mode 100644 index 000000000000..6b414a289f5a --- /dev/null +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs @@ -0,0 +1,9 @@ +//@ aux-build:t.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +extern crate t; +pub struct Sierra; +impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs new file mode 100644 index 000000000000..0a49072b68a6 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs @@ -0,0 +1,8 @@ +//@ aux-build:q.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + + +extern crate q; +pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs new file mode 100644 index 000000000000..9df0e9779ffa --- /dev/null +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs @@ -0,0 +1,32 @@ +//@ aux-build:q.rs +//@ aux-build:r.rs +//@ aux-build:t.rs +//@ aux-build:s.rs +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ hasraw search-index.js 'Quebec' +//@ hasraw search-index.js 'Sierra' +//@ has index.html +//@ has s/struct.Sierra.html +//@ hasraw s/struct.Sierra.html 'Tango' +//@ has index.html '//ul[@class="all-items"]//a[@href="i/index.html"]' 'i' +//@ has q/struct.Quebec.html +//@ has type.impl/s/struct.Sierra.js +//@ hasraw type.impl/s/struct.Sierra.js 'Romeo' +//@ hasraw type.impl/s/struct.Sierra.js 'Tango' +//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' +//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't' +//@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's' +//@ has r/type.Romeo.html +//@ has t/trait.Tango.html +//@ hasraw search-index.js 'Romeo' +//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' +//@ has index.html '//h1' 'List of all crates' +//@ hasraw search-index.js 'Tango' +//@ has index.html '//ul[@class="all-items"]//a[@href="r/index.html"]' 'r' + +// document everything in the default mode + + diff --git a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs new file mode 100644 index 000000000000..a9e03852f229 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs @@ -0,0 +1,13 @@ +//@ build-aux-docs +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ hasraw search-index.js 'Quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' +//@ has index.html '//h1' 'List of all crates' +//@ has index.html +//@ has q/struct.Quebec.html + +// there's nothing cross-crate going on here + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs new file mode 100644 index 000000000000..38471e02a282 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs @@ -0,0 +1,8 @@ +//@ build-aux-docs + +//@ hasraw search-index.js 'Quebec' +//@ has q/struct.Quebec.html + +// there's nothing cross-crate going on here + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs new file mode 100644 index 000000000000..32ad96d3e8e3 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs @@ -0,0 +1,4 @@ +//@ build-aux-docs + + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs new file mode 100644 index 000000000000..e03c9a1c68c3 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs @@ -0,0 +1,6 @@ +//@ aux-build:q.rs +//@ build-aux-docs + + +extern crate q; +pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/transitive/s.rs b/tests/rustdoc/cross-crate-info/transitive/s.rs new file mode 100644 index 000000000000..a758bd68be22 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/transitive/s.rs @@ -0,0 +1,9 @@ +//@ aux-build:t.rs +//@ build-aux-docs + + +// simple test to see if we support building transitive crates + +extern crate t; +pub struct Sierra; +impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs new file mode 100644 index 000000000000..1bfc785535b5 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs @@ -0,0 +1,4 @@ +//@ build-aux-docs + + +pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/two/e.rs b/tests/rustdoc/cross-crate-info/two/e.rs new file mode 100644 index 000000000000..431e73c390d4 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/two/e.rs @@ -0,0 +1,9 @@ +//@ aux-build:f.rs +//@ build-aux-docs + + +// simple test to assert that we can do a two-level aux-build + +extern crate f; +pub enum Echo {} +impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs new file mode 100644 index 000000000000..89d1349e520f --- /dev/null +++ b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs @@ -0,0 +1,10 @@ +//@ build-aux-docs +//@ doc-flags:--scrape-examples-output-path=examples +//@ doc-flags:--scrape-examples-target-crate=q +//@ doc-flags:-Zunstable-options + +//@ has examples + +// where will --scrape-examples-output-path resolve the path to be? should be the root output directory + +pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs new file mode 100644 index 000000000000..52e02e8b8971 --- /dev/null +++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs @@ -0,0 +1,5 @@ +//@ build-aux-docs +//@ unique-doc-out-dir + + +pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs new file mode 100644 index 000000000000..0480a02bf22f --- /dev/null +++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs @@ -0,0 +1,15 @@ +//@ aux-build:f.rs +//@ build-aux-docs + +//@ hasraw search-index.js 'Echo' +//@ !hasraw search-index.js 'Foxtrot' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ !has f/trait.Foxtrot.html +//@ has e/enum.Echo.html +//@ hasraw e/enum.Echo.html 'Foxtrot' + +// test the fact that our test runner will document this crate somewhere else + +extern crate f; +pub enum Echo {} +impl f::Foxtrot for Echo {} From d8211def61d2b436d2a8335d745105e2de3ac172 Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Wed, 24 Jul 2024 22:16:01 +0000 Subject: [PATCH 07/62] ordering and wrapping cross-crate-info tests --- src/tools/compiletest/src/command-list.rs | 2 +- .../cargo-transitive-no-index/s.rs | 15 ++++---- .../cross-crate-info/cargo-transitive/s.rs | 23 +++++------ .../cross-crate-info/cargo-two-no-index/e.rs | 11 +++--- tests/rustdoc/cross-crate-info/cargo-two/e.rs | 19 +++++----- .../cross-crate-info/index-on-last/e.rs | 16 ++++---- .../cross-crate-info/kitchen-sink/i.rs | 38 +++++++++---------- .../single-crate-baseline/q.rs | 6 +-- .../single-crate-no-index/q.rs | 2 +- .../working-dir-examples/q.rs | 3 +- .../write-docs-somewhere-else/e.rs | 11 +++--- 11 files changed, 76 insertions(+), 70 deletions(-) diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index 305bf9c228c4..68443c300fc5 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -9,7 +9,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "aux-codegen-backend", "aux-crate", "build-aux-docs", - "unique-doc-out-dir", "build-fail", "build-pass", "check-fail", @@ -227,6 +226,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "should-ice", "stderr-per-bitwidth", "test-mir-pass", + "unique-doc-out-dir", "unset-exec-env", "unset-rustc-env", // Used by the tidy check `unknown_revision`. diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs index af0d31c733ee..639b772374fc 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs @@ -1,16 +1,17 @@ //@ aux-build:t.rs //@ build-aux-docs -//@ has t/trait.Tango.html -//@ hasraw search-index.js 'Quebec' -//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' -//@ hasraw s/struct.Sierra.html 'Tango' -//@ hasraw search-index.js 'Sierra' -//@ hasraw search-index.js 'Tango' //@ has q/struct.Quebec.html //@ has s/struct.Sierra.html +//@ has t/trait.Tango.html +//@ hasraw s/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Quebec' -// We document multiple crates into the same output directory, which merges the cross-crate information. Everything is available. +// We document multiple crates into the same output directory, which +// merges the cross-crate information. Everything is available. extern crate t; pub struct Sierra; diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs index b050fbdf67d9..4383d089c4c7 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs @@ -3,21 +3,22 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options -//@ has t/trait.Tango.html -//@ hasraw search-index.js 'Quebec' -//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' -//@ hasraw s/struct.Sierra.html 'Tango' -//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' -//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't' -//@ has index.html '//h1' 'List of all crates' -//@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's' -//@ hasraw search-index.js 'Sierra' -//@ hasraw search-index.js 'Tango' //@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' +//@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's' +//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't' //@ has q/struct.Quebec.html //@ has s/struct.Sierra.html +//@ has t/trait.Tango.html +//@ hasraw s/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Quebec' -// We document multiple crates into the same output directory, which merges the cross-crate information. Everything is available. +// We document multiple crates into the same output directory, which +// merges the cross-crate information. Everything is available. extern crate t; pub struct Sierra; diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs index d3e42989b777..7d64f9481fb8 100644 --- a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs +++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs @@ -1,14 +1,15 @@ //@ aux-build:f.rs //@ build-aux-docs -//@ hasraw search-index.js 'Echo' -//@ hasraw search-index.js 'Foxtrot' -//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' -//@ has f/trait.Foxtrot.html //@ has e/enum.Echo.html +//@ has f/trait.Foxtrot.html //@ hasraw e/enum.Echo.html 'Foxtrot' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ hasraw search-index.js 'Foxtrot' +//@ hasraw search-index.js 'Echo' -// document two crates in the same way that cargo does. do not provide --enable-index-page +// document two crates in the same way that cargo does. do not provide +// --enable-index-page extern crate f; pub enum Echo {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two/e.rs b/tests/rustdoc/cross-crate-info/cargo-two/e.rs index bb845877b52f..29e3571e6c20 100644 --- a/tests/rustdoc/cross-crate-info/cargo-two/e.rs +++ b/tests/rustdoc/cross-crate-info/cargo-two/e.rs @@ -3,18 +3,19 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options -//@ hasraw search-index.js 'Echo' -//@ hasraw search-index.js 'Foxtrot' -//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e' -//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f' -//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' -//@ has f/trait.Foxtrot.html -//@ has index.html '//h1' 'List of all crates' -//@ has e/enum.Echo.html //@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f' +//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e' +//@ has e/enum.Echo.html +//@ has f/trait.Foxtrot.html //@ hasraw e/enum.Echo.html 'Foxtrot' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ hasraw search-index.js 'Foxtrot' +//@ hasraw search-index.js 'Echo' -// document two crates in the same way that cargo does, writing them both into the same output directory +// document two crates in the same way that cargo does, writing them both +// into the same output directory extern crate f; pub enum Echo {} diff --git a/tests/rustdoc/cross-crate-info/index-on-last/e.rs b/tests/rustdoc/cross-crate-info/index-on-last/e.rs index 876b94464c37..fee9f4bcddbe 100644 --- a/tests/rustdoc/cross-crate-info/index-on-last/e.rs +++ b/tests/rustdoc/cross-crate-info/index-on-last/e.rs @@ -3,16 +3,16 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options -//@ hasraw search-index.js 'Echo' -//@ hasraw search-index.js 'Foxtrot' -//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e' -//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f' -//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' -//@ has f/trait.Foxtrot.html -//@ has index.html '//h1' 'List of all crates' -//@ has e/enum.Echo.html //@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f' +//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e' +//@ has e/enum.Echo.html +//@ has f/trait.Foxtrot.html //@ hasraw e/enum.Echo.html 'Foxtrot' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ hasraw search-index.js 'Foxtrot' +//@ hasraw search-index.js 'Echo' // only declare --enable-index-page to the last rustdoc invocation diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs index 9df0e9779ffa..558f47ab7c4c 100644 --- a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs @@ -1,31 +1,31 @@ //@ aux-build:q.rs //@ aux-build:r.rs -//@ aux-build:t.rs //@ aux-build:s.rs +//@ aux-build:t.rs //@ build-aux-docs //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options -//@ hasraw search-index.js 'Quebec' -//@ hasraw search-index.js 'Sierra' -//@ has index.html -//@ has s/struct.Sierra.html -//@ hasraw s/struct.Sierra.html 'Tango' -//@ has index.html '//ul[@class="all-items"]//a[@href="i/index.html"]' 'i' -//@ has q/struct.Quebec.html -//@ has type.impl/s/struct.Sierra.js -//@ hasraw type.impl/s/struct.Sierra.js 'Romeo' -//@ hasraw type.impl/s/struct.Sierra.js 'Tango' -//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' -//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't' -//@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's' -//@ has r/type.Romeo.html -//@ has t/trait.Tango.html -//@ hasraw search-index.js 'Romeo' -//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' //@ has index.html '//h1' 'List of all crates' -//@ hasraw search-index.js 'Tango' +//@ has index.html +//@ has index.html '//ul[@class="all-items"]//a[@href="i/index.html"]' 'i' +//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' //@ has index.html '//ul[@class="all-items"]//a[@href="r/index.html"]' 'r' +//@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's' +//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't' +//@ has q/struct.Quebec.html +//@ has r/type.Romeo.html +//@ has s/struct.Sierra.html +//@ has t/trait.Tango.html +//@ hasraw s/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Quebec' +//@ hasraw search-index.js 'Romeo' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Tango' +//@ has type.impl/s/struct.Sierra.js +//@ hasraw type.impl/s/struct.Sierra.js 'Tango' +//@ hasraw type.impl/s/struct.Sierra.js 'Romeo' // document everything in the default mode diff --git a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs index a9e03852f229..aa5cff73e746 100644 --- a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs +++ b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs @@ -2,11 +2,11 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options -//@ hasraw search-index.js 'Quebec' -//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' -//@ has index.html '//h1' 'List of all crates' //@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q' //@ has q/struct.Quebec.html +//@ hasraw search-index.js 'Quebec' // there's nothing cross-crate going on here diff --git a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs index 38471e02a282..0cd126e8247d 100644 --- a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs +++ b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs @@ -1,7 +1,7 @@ //@ build-aux-docs -//@ hasraw search-index.js 'Quebec' //@ has q/struct.Quebec.html +//@ hasraw search-index.js 'Quebec' // there's nothing cross-crate going on here diff --git a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs index 89d1349e520f..ceced1fc46dc 100644 --- a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs +++ b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs @@ -5,6 +5,7 @@ //@ has examples -// where will --scrape-examples-output-path resolve the path to be? should be the root output directory +// where will --scrape-examples-output-path resolve the path to be? +// should be the root output directory pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs index 0480a02bf22f..6247ed5fd966 100644 --- a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs +++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs @@ -1,14 +1,15 @@ //@ aux-build:f.rs //@ build-aux-docs -//@ hasraw search-index.js 'Echo' -//@ !hasraw search-index.js 'Foxtrot' -//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' -//@ !has f/trait.Foxtrot.html //@ has e/enum.Echo.html +//@ !has f/trait.Foxtrot.html //@ hasraw e/enum.Echo.html 'Foxtrot' +//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html' +//@ !hasraw search-index.js 'Foxtrot' +//@ hasraw search-index.js 'Echo' -// test the fact that our test runner will document this crate somewhere else +// test the fact that our test runner will document this crate somewhere +// else extern crate f; pub enum Echo {} From f6f0ef46f5a9f368183e8c59ee82d0319af7ec9c Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Wed, 24 Jul 2024 22:35:14 +0000 Subject: [PATCH 08/62] reformatted rustdoc/cross-crate-info, fixing trailing newline issue --- .../cargo-transitive-no-index/auxiliary/q.rs | 2 -- .../cargo-transitive-no-index/auxiliary/t.rs | 2 -- .../rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs | 2 -- .../cross-crate-info/cargo-transitive/auxiliary/q.rs | 1 - .../cross-crate-info/cargo-transitive/auxiliary/t.rs | 1 - tests/rustdoc/cross-crate-info/cargo-transitive/s.rs | 1 - .../cross-crate-info/cargo-two-no-index/auxiliary/f.rs | 2 -- tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs | 2 -- tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs | 1 - tests/rustdoc/cross-crate-info/cargo-two/e.rs | 1 - tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs | 2 -- tests/rustdoc/cross-crate-info/index-on-last/e.rs | 1 - tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs | 1 - tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs | 1 - tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs | 1 - tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs | 1 - tests/rustdoc/cross-crate-info/kitchen-sink/i.rs | 6 ++---- tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs | 1 - tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs | 2 -- tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs | 2 -- tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs | 2 -- tests/rustdoc/cross-crate-info/transitive/s.rs | 3 --- tests/rustdoc/cross-crate-info/two/auxiliary/f.rs | 2 -- tests/rustdoc/cross-crate-info/two/e.rs | 3 --- tests/rustdoc/cross-crate-info/working-dir-examples/q.rs | 1 - .../write-docs-somewhere-else/auxiliary/f.rs | 2 -- .../rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs | 2 -- 27 files changed, 2 insertions(+), 46 deletions(-) diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs index 32ad96d3e8e3..5d0881029cb2 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs @@ -1,4 +1,2 @@ //@ build-aux-docs - - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs index e03c9a1c68c3..fab9ec4a92b9 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs @@ -1,6 +1,4 @@ //@ aux-build:q.rs //@ build-aux-docs - - extern crate q; pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs index 639b772374fc..85c460ace642 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs @@ -1,6 +1,5 @@ //@ aux-build:t.rs //@ build-aux-docs - //@ has q/struct.Quebec.html //@ has s/struct.Sierra.html //@ has t/trait.Tango.html @@ -12,7 +11,6 @@ // We document multiple crates into the same output directory, which // merges the cross-crate information. Everything is available. - extern crate t; pub struct Sierra; impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs index e32fdbaabfe2..932a0b17206d 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs @@ -2,5 +2,4 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs index 0a49072b68a6..c21a59c65188 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs @@ -3,6 +3,5 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - extern crate q; pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs index 4383d089c4c7..68bfc34883bd 100644 --- a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs +++ b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs @@ -19,7 +19,6 @@ // We document multiple crates into the same output directory, which // merges the cross-crate information. Everything is available. - extern crate t; pub struct Sierra; impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs index 1bfc785535b5..abc580a388cd 100644 --- a/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs +++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs @@ -1,4 +1,2 @@ //@ build-aux-docs - - pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs index 7d64f9481fb8..c93298f969ea 100644 --- a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs +++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs @@ -1,6 +1,5 @@ //@ aux-build:f.rs //@ build-aux-docs - //@ has e/enum.Echo.html //@ has f/trait.Foxtrot.html //@ hasraw e/enum.Echo.html 'Foxtrot' @@ -10,7 +9,6 @@ // document two crates in the same way that cargo does. do not provide // --enable-index-page - extern crate f; pub enum Echo {} impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs index e84835b3e310..a2a7033b1311 100644 --- a/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs +++ b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs @@ -2,5 +2,4 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/cargo-two/e.rs b/tests/rustdoc/cross-crate-info/cargo-two/e.rs index 29e3571e6c20..00f86cbc3488 100644 --- a/tests/rustdoc/cross-crate-info/cargo-two/e.rs +++ b/tests/rustdoc/cross-crate-info/cargo-two/e.rs @@ -16,7 +16,6 @@ // document two crates in the same way that cargo does, writing them both // into the same output directory - extern crate f; pub enum Echo {} impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs index 1bfc785535b5..abc580a388cd 100644 --- a/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs +++ b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs @@ -1,4 +1,2 @@ //@ build-aux-docs - - pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/index-on-last/e.rs b/tests/rustdoc/cross-crate-info/index-on-last/e.rs index fee9f4bcddbe..ffee898cd966 100644 --- a/tests/rustdoc/cross-crate-info/index-on-last/e.rs +++ b/tests/rustdoc/cross-crate-info/index-on-last/e.rs @@ -15,7 +15,6 @@ //@ hasraw search-index.js 'Echo' // only declare --enable-index-page to the last rustdoc invocation - extern crate f; pub enum Echo {} impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs index e32fdbaabfe2..932a0b17206d 100644 --- a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs @@ -2,5 +2,4 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs index c0ada1aea1a8..2c0db2abc53d 100644 --- a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs @@ -3,6 +3,5 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - extern crate s; pub type Romeo = s::Sierra; diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs index 6b414a289f5a..355d3f1aaa88 100644 --- a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs @@ -3,7 +3,6 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - extern crate t; pub struct Sierra; impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs index 0a49072b68a6..c21a59c65188 100644 --- a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs @@ -3,6 +3,5 @@ //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options - extern crate q; pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs index 558f47ab7c4c..bcb9464795af 100644 --- a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs +++ b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs @@ -1,7 +1,7 @@ -//@ aux-build:q.rs //@ aux-build:r.rs -//@ aux-build:s.rs +//@ aux-build:q.rs //@ aux-build:t.rs +//@ aux-build:s.rs //@ build-aux-docs //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options @@ -28,5 +28,3 @@ //@ hasraw type.impl/s/struct.Sierra.js 'Romeo' // document everything in the default mode - - diff --git a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs index aa5cff73e746..c5e3dc0a0f4e 100644 --- a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs +++ b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs @@ -9,5 +9,4 @@ //@ hasraw search-index.js 'Quebec' // there's nothing cross-crate going on here - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs index 0cd126e8247d..d3e71fa0ce35 100644 --- a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs +++ b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs @@ -1,8 +1,6 @@ //@ build-aux-docs - //@ has q/struct.Quebec.html //@ hasraw search-index.js 'Quebec' // there's nothing cross-crate going on here - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs index 32ad96d3e8e3..5d0881029cb2 100644 --- a/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs +++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs @@ -1,4 +1,2 @@ //@ build-aux-docs - - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs index e03c9a1c68c3..fab9ec4a92b9 100644 --- a/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs +++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs @@ -1,6 +1,4 @@ //@ aux-build:q.rs //@ build-aux-docs - - extern crate q; pub trait Tango {} diff --git a/tests/rustdoc/cross-crate-info/transitive/s.rs b/tests/rustdoc/cross-crate-info/transitive/s.rs index a758bd68be22..0a4e5f646dda 100644 --- a/tests/rustdoc/cross-crate-info/transitive/s.rs +++ b/tests/rustdoc/cross-crate-info/transitive/s.rs @@ -1,9 +1,6 @@ //@ aux-build:t.rs //@ build-aux-docs - - // simple test to see if we support building transitive crates - extern crate t; pub struct Sierra; impl t::Tango for Sierra {} diff --git a/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs index 1bfc785535b5..abc580a388cd 100644 --- a/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs +++ b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs @@ -1,4 +1,2 @@ //@ build-aux-docs - - pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/two/e.rs b/tests/rustdoc/cross-crate-info/two/e.rs index 431e73c390d4..9665af62706d 100644 --- a/tests/rustdoc/cross-crate-info/two/e.rs +++ b/tests/rustdoc/cross-crate-info/two/e.rs @@ -1,9 +1,6 @@ //@ aux-build:f.rs //@ build-aux-docs - - // simple test to assert that we can do a two-level aux-build - extern crate f; pub enum Echo {} impl f::Foxtrot for Echo {} diff --git a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs index ceced1fc46dc..a7ab062fd9e2 100644 --- a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs +++ b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs @@ -7,5 +7,4 @@ // where will --scrape-examples-output-path resolve the path to be? // should be the root output directory - pub struct Quebec; diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs index 52e02e8b8971..f8c9adcaf9ca 100644 --- a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs +++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs @@ -1,5 +1,3 @@ //@ build-aux-docs //@ unique-doc-out-dir - - pub trait Foxtrot {} diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs index 6247ed5fd966..9dcec211e178 100644 --- a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs +++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs @@ -1,6 +1,5 @@ //@ aux-build:f.rs //@ build-aux-docs - //@ has e/enum.Echo.html //@ !has f/trait.Foxtrot.html //@ hasraw e/enum.Echo.html 'Foxtrot' @@ -10,7 +9,6 @@ // test the fact that our test runner will document this crate somewhere // else - extern crate f; pub enum Echo {} impl f::Foxtrot for Echo {} From 12d87ee237a1f79c00ccd22424432f5ab869ed22 Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Thu, 25 Jul 2024 17:59:32 +0000 Subject: [PATCH 09/62] file_stem and comment per notriddle --- src/tools/compiletest/src/runtest.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2d298dfbc06f..2beff593f08a 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1610,6 +1610,8 @@ impl<'test> TestCx<'test> { }; // Create the directory for the stdout/stderr files. create_dir_all(aux_cx.output_base_dir()).unwrap(); + // use root_testpaths here, because aux-builds should have the + // same --out-dir and auxiliary directory. let auxres = aux_cx.document(&root_out_dir, root_testpaths); if !auxres.status.success() { return auxres; @@ -1624,14 +1626,7 @@ impl<'test> TestCx<'test> { // actual --out-dir given to the auxiliary or test, as opposed to the root out dir for the entire // test let out_dir: Cow<'_, Path> = if self.props.unique_doc_out_dir { - let file_name = self - .testpaths - .file - .file_name() - .expect("file name should not be empty") - .to_str() - .expect("file name utf8") - .trim_end_matches(".rs"); + let file_name = self.testpaths.file.file_stem().expect("file name should not be empty"); let out_dir = PathBuf::from_iter([ root_out_dir, Path::new("docs"), From f91da72cb75f03739985926c5e5561611f783b80 Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Mon, 29 Jul 2024 14:41:09 +0000 Subject: [PATCH 10/62] merge conflicts; fix rebase duplicating imports --- src/tools/compiletest/src/runtest.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2beff593f08a..55f676e70867 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1,16 +1,5 @@ // ignore-tidy-filelength -use crate::compute_diff::{write_diff, write_filtered_diff}; -use crate::errors::{self, Error, ErrorKind}; -use crate::header::TestProps; -use crate::json; -use crate::read2::{read2_abbreviated, Truncated}; -use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, static_regex, PathBufExt}; -use crate::ColorConfig; -use colored::Colorize; -use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile}; -use regex::{Captures, Regex}; -use rustfix::{apply_suggestions, get_suggestions_from_json, Filter}; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use std::ffi::{OsStr, OsString}; From e9f45e1eb2e6ef09034453f4a7a0998c65ce5736 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 29 Jul 2024 14:33:54 -0400 Subject: [PATCH 11/62] rewrite link-cfg to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/link-cfg/Makefile | 23 ---------- tests/run-make/link-cfg/rmake.rs | 43 +++++++++++++++++++ 3 files changed, 43 insertions(+), 24 deletions(-) delete mode 100644 tests/run-make/link-cfg/Makefile create mode 100644 tests/run-make/link-cfg/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 7284feadf9cd..dc4db13902da 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -25,7 +25,6 @@ run-make/libs-through-symlinks/Makefile run-make/libtest-json/Makefile run-make/libtest-junit/Makefile run-make/libtest-thread-limit/Makefile -run-make/link-cfg/Makefile run-make/long-linker-command-lines-cmd-exe/Makefile run-make/long-linker-command-lines/Makefile run-make/macos-deployment-target/Makefile diff --git a/tests/run-make/link-cfg/Makefile b/tests/run-make/link-cfg/Makefile deleted file mode 100644 index a40997011443..000000000000 --- a/tests/run-make/link-cfg/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: $(call DYLIB,return1) $(call DYLIB,return2) $(call NATIVE_STATICLIB,return3) - ls $(TMPDIR) - $(BARE_RUSTC) --print cfg --target x86_64-unknown-linux-musl | $(CGREP) crt-static - - $(RUSTC) no-deps.rs --cfg foo - $(call RUN,no-deps) - $(RUSTC) no-deps.rs --cfg bar - $(call RUN,no-deps) - - $(RUSTC) dep.rs - $(RUSTC) with-deps.rs --cfg foo - $(call RUN,with-deps) - $(RUSTC) with-deps.rs --cfg bar - $(call RUN,with-deps) - - $(RUSTC) dep-with-staticlib.rs - $(RUSTC) with-staticlib-deps.rs --cfg foo - $(call RUN,with-staticlib-deps) - $(RUSTC) with-staticlib-deps.rs --cfg bar - $(call RUN,with-staticlib-deps) diff --git a/tests/run-make/link-cfg/rmake.rs b/tests/run-make/link-cfg/rmake.rs new file mode 100644 index 000000000000..732de5dbd0b8 --- /dev/null +++ b/tests/run-make/link-cfg/rmake.rs @@ -0,0 +1,43 @@ +// The `#[link(cfg(..))]` annotation means that the `#[link]` +// directive is only active in a compilation unit if that `cfg` value is satisfied. +// For example, when compiling an rlib, these directives are just encoded and +// ignored for dylibs, and all staticlibs are continued to be put into the rlib as +// usual. When placing that rlib into a staticlib, executable, or dylib, however, +// the `cfg` is evaluated *as if it were defined in the final artifact* and the +// library is decided to be linked or not. +// This test exercises this new feature by testing it with no dependencies, then +// with only dynamic libraries, then with both a staticlib and dylibs. Compilation +// and execution should be successful. +// See https://github.com/rust-lang/rust/pull/37545 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +use run_make_support::{bare_rustc, build_native_dynamic_lib, build_native_static_lib, run, rustc}; + +fn main() { + build_native_dynamic_lib("return1"); + build_native_dynamic_lib("return2"); + build_native_static_lib("return3"); + bare_rustc() + .print("cfg") + .target("x86_64-unknown-linux-musl") + .run() + .assert_stdout_contains("crt-static"); + rustc().input("no-deps.rs").cfg("foo").run(); + run("no-deps"); + rustc().input("no-deps.rs").cfg("bar").run(); + run("no-deps"); + + rustc().input("dep.rs").run(); + rustc().input("with-deps.rs").cfg("foo").run(); + run("with-deps"); + rustc().input("with-deps.rs").cfg("bar").run(); + run("with-deps"); + + rustc().input("dep-with-staticlib.rs").run(); + rustc().input("with-staticlib-deps.rs").cfg("foo").run(); + run("with-staticlib-deps"); + rustc().input("with-staticlib-deps.rs").cfg("bar").run(); + run("with-staticlib-deps"); +} From bd24763aaf32fe92e79491aba05346b570301647 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jul 2024 07:20:17 +1000 Subject: [PATCH 12/62] Move a comment. In #125443 this comment ended up in the wrong spot. I'm not sure why; after careful checking this was the only case I could find like this. --- library/std/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ee6f5a6f3c0d..5a33a243743e 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -671,7 +671,6 @@ mod panicking; #[allow(dead_code, unused_attributes, fuzzy_provenance_casts, unsafe_op_in_unsafe_fn)] mod backtrace_rs; -// Re-export macros defined in core. #[unstable(feature = "cfg_match", issue = "115585")] pub use core::cfg_match; #[unstable( @@ -690,6 +689,7 @@ pub use core::{ env, file, format_args, format_args_nl, include, include_bytes, include_str, line, log_syntax, module_path, option_env, stringify, trace_macros, }; +// Re-export macros defined in core. #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated, deprecated_in_future)] pub use core::{ From 70fcf9e7908cfa3da975a322b4aa533ad67d52ec Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jul 2024 07:21:13 +1000 Subject: [PATCH 13/62] Insert some blank lines. After things that are immediately followed by a `use` declaration and look like they might apply to that `use` item but actually don't. --- .../src/macro_expr_fragment_specifier_2024_migration.rs | 4 ++-- library/std/src/sys/pal/sgx/thread.rs | 1 + library/std/src/sys/pal/windows/net.rs | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs b/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs index c39c86f6fe8f..e3b1967da09c 100644 --- a/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs +++ b/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs @@ -1,5 +1,5 @@ -//! Migration code for the `expr_fragment_specifier_2024` -//! rule. +//! Migration code for the `expr_fragment_specifier_2024` rule. + use rustc_ast::token::{Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_session::lint::FutureIncompatibilityReason; diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs index df65d1cc8fc4..cecd53c352c5 100644 --- a/library/std/src/sys/pal/sgx/thread.rs +++ b/library/std/src/sys/pal/sgx/thread.rs @@ -1,4 +1,5 @@ #![cfg_attr(test, allow(dead_code))] // why is this necessary? + use super::abi::usercalls; use super::unsupported; use crate::ffi::CStr; diff --git a/library/std/src/sys/pal/windows/net.rs b/library/std/src/sys/pal/windows/net.rs index e27fdb72256f..ce995f5ed5af 100644 --- a/library/std/src/sys/pal/windows/net.rs +++ b/library/std/src/sys/pal/windows/net.rs @@ -21,6 +21,7 @@ pub mod netc { //! //! Some Windows API types are not quite what's expected by our cross-platform //! net code. E.g. naming differences or different pointer types. + use core::ffi::{c_char, c_int, c_uint, c_ulong, c_ushort, c_void}; use crate::sys::c::{self, ADDRESS_FAMILY, ADDRINFOA, SOCKADDR, SOCKET}; From bb584882070f2f45b35f0af172069e7c00d63983 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 26 Jul 2024 23:35:48 +0100 Subject: [PATCH 14/62] Rewrite binary search implementation This restores the original binary search implementation from #45333 which has the nice property of having a loop count that only depends on the size of the slice. This, along with explicit conditional moves from #128250, means that the entire binary search loop can be perfectly predicted by the branch predictor. Additionally, LLVM is able to unroll the loop when the slice length is known at compile-time. This results in a very compact code sequence of 3-4 instructions per binary search step and zero branches. Fixes #53823 --- library/core/src/slice/mod.rs | 71 +++++++++++++++++++++-------------- library/core/tests/slice.rs | 12 +++--- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 0b0a416ea243..45dc828eb2ed 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -7,7 +7,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::cmp::Ordering::{self, Equal, Greater, Less}; -use crate::intrinsics::{exact_div, unchecked_sub}; +use crate::intrinsics::{exact_div, select_unpredictable, unchecked_sub}; use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZero; use crate::ops::{Bound, OneSidedRange, Range, RangeBounds}; @@ -2770,41 +2770,54 @@ impl [T] { where F: FnMut(&'a T) -> Ordering, { - // INVARIANTS: - // - 0 <= left <= left + size = right <= self.len() - // - f returns Less for everything in self[..left] - // - f returns Greater for everything in self[right..] let mut size = self.len(); - let mut left = 0; - let mut right = size; - while left < right { - let mid = left + size / 2; + if size == 0 { + return Err(0); + } + let mut base = 0usize; - // SAFETY: the while condition means `size` is strictly positive, so - // `size/2 < size`. Thus `left + size/2 < left + size`, which - // coupled with the `left + size <= self.len()` invariant means - // we have `left + size/2 < self.len()`, and this is in-bounds. + // This loop intentionally doesn't have an early exit if the comparison + // returns Equal. We want the number of loop iterations to depend *only* + // on the size of the input slice so that the CPU can reliably predict + // the loop count. + while size > 1 { + let half = size / 2; + let mid = base + half; + + // SAFETY: the call is made safe by the following inconstants: + // - `mid >= 0`: by definition + // - `mid < size`: `mid = size / 2 + size / 4 + size / 8 ...` let cmp = f(unsafe { self.get_unchecked(mid) }); - // This control flow produces conditional moves, which results in - // fewer branches and instructions than if/else or matching on - // cmp::Ordering. - // This is x86 asm for u8: https://rust.godbolt.org/z/698eYffTx. - left = if cmp == Less { mid + 1 } else { left }; - right = if cmp == Greater { mid } else { right }; - if cmp == Equal { - // SAFETY: same as the `get_unchecked` above - unsafe { hint::assert_unchecked(mid < self.len()) }; - return Ok(mid); - } + // Binary search interacts poorly with branch prediction, so force + // the compiler to use conditional moves if supported by the target + // architecture. + base = select_unpredictable(cmp == Greater, base, mid); - size = right - left; + // This is imprecise in the case where `size` is odd and the + // comparison returns Greater: the mid element still gets included + // by `size` even though it's known to be larger than the element + // being searched for. + // + // This is fine though: we gain more performance by keeping the + // loop iteration count invariant (and thus predictable) than we + // lose from considering one additional element. + size -= half; } - // SAFETY: directly true from the overall invariant. - // Note that this is `<=`, unlike the assume in the `Ok` path. - unsafe { hint::assert_unchecked(left <= self.len()) }; - Err(left) + // SAFETY: base is always in [0, size) because base <= mid. + let cmp = f(unsafe { self.get_unchecked(base) }); + if cmp == Equal { + // SAFETY: same as the `get_unchecked` above. + unsafe { hint::assert_unchecked(base < self.len()) }; + Ok(base) + } else { + let result = base + (cmp == Less) as usize; + // SAFETY: same as the `get_unchecked` above. + // Note that this is `<=`, unlike the assume in the `Ok` path. + unsafe { hint::assert_unchecked(result <= self.len()) }; + Err(result) + } } /// Binary searches this slice with a key extraction function. diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index acabedcdc266..cdefb5d3eb20 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -69,13 +69,13 @@ fn test_binary_search() { assert_eq!(b.binary_search(&8), Err(5)); let b = [(); usize::MAX]; - assert_eq!(b.binary_search(&()), Ok(usize::MAX / 2)); + assert_eq!(b.binary_search(&()), Ok(usize::MAX - 1)); } #[test] fn test_binary_search_by_overflow() { let b = [(); usize::MAX]; - assert_eq!(b.binary_search_by(|_| Ordering::Equal), Ok(usize::MAX / 2)); + assert_eq!(b.binary_search_by(|_| Ordering::Equal), Ok(usize::MAX - 1)); assert_eq!(b.binary_search_by(|_| Ordering::Greater), Err(0)); assert_eq!(b.binary_search_by(|_| Ordering::Less), Err(usize::MAX)); } @@ -87,13 +87,13 @@ fn test_binary_search_implementation_details() { let b = [1, 1, 2, 2, 3, 3, 3]; assert_eq!(b.binary_search(&1), Ok(1)); assert_eq!(b.binary_search(&2), Ok(3)); - assert_eq!(b.binary_search(&3), Ok(5)); + assert_eq!(b.binary_search(&3), Ok(6)); let b = [1, 1, 1, 1, 1, 3, 3, 3, 3]; assert_eq!(b.binary_search(&1), Ok(4)); - assert_eq!(b.binary_search(&3), Ok(7)); + assert_eq!(b.binary_search(&3), Ok(8)); let b = [1, 1, 1, 1, 3, 3, 3, 3, 3]; - assert_eq!(b.binary_search(&1), Ok(2)); - assert_eq!(b.binary_search(&3), Ok(4)); + assert_eq!(b.binary_search(&1), Ok(3)); + assert_eq!(b.binary_search(&3), Ok(8)); } #[test] From bd23e0eb2694752f573eafd0d894a2b16d10fd7b Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Wed, 31 Jul 2024 00:20:56 +0000 Subject: [PATCH 15/62] canonicalize path in another place to fix #128411 --- src/tools/compiletest/src/runtest.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 55f676e70867..2b7601a7c73b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2968,7 +2968,9 @@ impl<'test> TestCx<'test> { for _ in res.stdout.split('\n').filter(|s| s.starts_with("test ")).inspect(|s| { if let Some((left, right)) = s.split_once(" - ") { let path = left.rsplit("test ").next().unwrap(); - if let Some(ref mut v) = files.get_mut(&path.replace('\\', "/")) { + let path = fs::canonicalize(&path).expect("failed to canonicalize"); + let path = path.to_str().unwrap().replace('\\', "/"); + if let Some(ref mut v) = files.get_mut(&path) { tested += 1; let mut iter = right.split("(line "); iter.next(); From 281c2fd5bf1604392bde16e32c7d57d2772406e6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 31 Jul 2024 12:08:55 +1000 Subject: [PATCH 16/62] Inline and remove `parse_local_mk`. It has a single use. This makes the `let` handling case in `parse_stmt_without_recovery` more similar to the statement path and statement expression cases. --- compiler/rustc_parse/src/parser/stmt.rs | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 7b0daaa14335..28122a3ae294 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -66,7 +66,12 @@ impl<'a> Parser<'a> { } Ok(Some(if self.token.is_keyword(kw::Let) { - self.parse_local_mk(lo, attrs, capture_semi, force_collect)? + self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { + this.expect_keyword(kw::Let)?; + let local = this.parse_local(attrs)?; + let trailing = capture_semi && this.token.kind == token::Semi; + Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), trailing)) + })? } else if self.is_kw_followed_by_ident(kw::Mut) && self.may_recover() { self.recover_stmt_local_after_let( lo, @@ -247,21 +252,6 @@ impl<'a> Parser<'a> { Ok(stmt) } - fn parse_local_mk( - &mut self, - lo: Span, - attrs: AttrWrapper, - capture_semi: bool, - force_collect: ForceCollect, - ) -> PResult<'a, Stmt> { - self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { - this.expect_keyword(kw::Let)?; - let local = this.parse_local(attrs)?; - let trailing = capture_semi && this.token.kind == token::Semi; - Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), trailing)) - }) - } - /// Parses a local variable declaration. fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P> { let lo = self.prev_token.span; From fe647f053882f5745dfb339f22f13435bf8c4ca5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 31 Jul 2024 12:56:25 +1000 Subject: [PATCH 17/62] Remove `LhsExpr`. `parse_expr_assoc_with` has an awkward structure -- sometimes the lhs is already parsed. This commit splits the post-lhs part into a new method `parse_expr_assoc_rest_with`, which makes everything shorter and simpler. --- compiler/rustc_parse/src/parser/expr.rs | 57 ++++++++++--------------- compiler/rustc_parse/src/parser/pat.rs | 7 +-- compiler/rustc_parse/src/parser/stmt.rs | 6 +-- 3 files changed, 28 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a242dc5cd582..24e56c5bdee6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -40,14 +40,6 @@ use super::{ }; use crate::{errors, maybe_recover_from_interpolated_ty_qpath}; -#[derive(Debug)] -pub(super) enum LhsExpr { - // Already parsed just the outer attributes. - Unparsed { attrs: AttrWrapper }, - // Already parsed the expression. - Parsed { expr: P, starts_statement: bool }, -} - #[derive(Debug)] enum DestructuredFloat { /// 1e2 @@ -113,30 +105,31 @@ impl<'a> Parser<'a> { r: Restrictions, attrs: AttrWrapper, ) -> PResult<'a, P> { - self.with_res(r, |this| this.parse_expr_assoc_with(0, LhsExpr::Unparsed { attrs })) + self.with_res(r, |this| this.parse_expr_assoc_with(0, attrs)) } /// Parses an associative expression with operators of at least `min_prec` precedence. pub(super) fn parse_expr_assoc_with( &mut self, min_prec: usize, - lhs: LhsExpr, + attrs: AttrWrapper, ) -> PResult<'a, P> { - let mut starts_stmt = false; - let mut lhs = match lhs { - LhsExpr::Parsed { expr, starts_statement } => { - starts_stmt = starts_statement; - expr - } - LhsExpr::Unparsed { attrs } => { - if self.token.is_range_separator() { - return self.parse_expr_prefix_range(attrs); - } else { - self.parse_expr_prefix(attrs)? - } - } + let lhs = if self.token.is_range_separator() { + return self.parse_expr_prefix_range(attrs); + } else { + self.parse_expr_prefix(attrs)? }; + self.parse_expr_assoc_rest_with(min_prec, false, lhs) + } + /// Parses the rest of an associative expression (i.e. the part after the lhs) with operators + /// of at least `min_prec` precedence. + pub(super) fn parse_expr_assoc_rest_with( + &mut self, + min_prec: usize, + starts_stmt: bool, + mut lhs: P, + ) -> PResult<'a, P> { if !self.should_continue_as_assoc_expr(&lhs) { return Ok(lhs); } @@ -272,7 +265,7 @@ impl<'a> Parser<'a> { }; let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| { let attrs = this.parse_outer_attributes()?; - this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::Unparsed { attrs }) + this.parse_expr_assoc_with(prec + prec_adjustment, attrs) })?; let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span); @@ -447,7 +440,7 @@ impl<'a> Parser<'a> { let maybe_lt = self.token.clone(); let attrs = self.parse_outer_attributes()?; Some( - self.parse_expr_assoc_with(prec + 1, LhsExpr::Unparsed { attrs }) + self.parse_expr_assoc_with(prec + 1, attrs) .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?, ) } else { @@ -504,12 +497,9 @@ impl<'a> Parser<'a> { let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() { // RHS must be parsed with more associativity than the dots. let attrs = this.parse_outer_attributes()?; - this.parse_expr_assoc_with( - op.unwrap().precedence() + 1, - LhsExpr::Unparsed { attrs }, - ) - .map(|x| (lo.to(x.span), Some(x))) - .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))? + this.parse_expr_assoc_with(op.unwrap().precedence() + 1, attrs) + .map(|x| (lo.to(x.span), Some(x))) + .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))? } else { (lo, None) }; @@ -2645,10 +2635,7 @@ impl<'a> Parser<'a> { self.expect(&token::Eq)?; } let attrs = self.parse_outer_attributes()?; - let expr = self.parse_expr_assoc_with( - 1 + prec_let_scrutinee_needs_par(), - LhsExpr::Unparsed { attrs }, - )?; + let expr = self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), attrs)?; let span = lo.to(expr.span); Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, recovered))) } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index b6f85cc90324..5bfb8bdf776a 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -25,7 +25,7 @@ use crate::errors::{ UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens, }; -use crate::parser::expr::{could_be_unclosed_char_literal, LhsExpr}; +use crate::parser::expr::could_be_unclosed_char_literal; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; #[derive(PartialEq, Copy, Clone)] @@ -403,8 +403,9 @@ impl<'a> Parser<'a> { // Parse an associative expression such as `+ expr`, `% expr`, ... // Assignements, ranges and `|` are disabled by [`Restrictions::IS_PAT`]. - let lhs = LhsExpr::Parsed { expr, starts_statement: false }; - if let Ok(expr) = snapshot.parse_expr_assoc_with(0, lhs).map_err(|err| err.cancel()) { + if let Ok(expr) = + snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel()) + { // We got a valid expression. self.restore_snapshot(snapshot); self.restrictions.remove(Restrictions::IS_PAT); diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 28122a3ae294..e0676b72634e 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -17,7 +17,6 @@ use thin_vec::{thin_vec, ThinVec}; use super::attr::InnerAttrForbiddenReason; use super::diagnostics::AttemptLocalParseRecovery; -use super::expr::LhsExpr; use super::pat::{PatternLocation, RecoverComma}; use super::path::PathStyle; use super::{ @@ -178,7 +177,7 @@ impl<'a> Parser<'a> { // Perform this outside of the `collect_tokens_trailing_token` closure, // since our outer attributes do not apply to this part of the expression let expr = self.with_res(Restrictions::STMT_EXPR, |this| { - this.parse_expr_assoc_with(0, LhsExpr::Parsed { expr, starts_statement: true }) + this.parse_expr_assoc_rest_with(0, true, expr) })?; Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr))) } else { @@ -211,8 +210,7 @@ impl<'a> Parser<'a> { let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac)); let e = self.maybe_recover_from_bad_qpath(e)?; let e = self.parse_expr_dot_or_call_with(attrs, e, lo)?; - let e = self - .parse_expr_assoc_with(0, LhsExpr::Parsed { expr: e, starts_statement: false })?; + let e = self.parse_expr_assoc_rest_with(0, false, e)?; StmtKind::Expr(e) }; Ok(self.mk_stmt(lo.to(hi), kind)) From 152db2760cbd21b6c4fcd2c22ee1dcb422fb9965 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 29 Jul 2024 12:03:14 -0400 Subject: [PATCH 18/62] rewrite cross-lang-lto to rmake --- .../src/external_deps/llvm.rs | 36 ++++++ src/tools/run-make-support/src/lib.rs | 4 +- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/cross-lang-lto/Makefile | 57 --------- tests/run-make/cross-lang-lto/rmake.rs | 110 ++++++++++++++++++ 5 files changed, 148 insertions(+), 60 deletions(-) delete mode 100644 tests/run-make/cross-lang-lto/Makefile create mode 100644 tests/run-make/cross-lang-lto/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index 259bb6159461..c06cefa91a92 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -42,6 +42,12 @@ pub fn llvm_nm() -> LlvmNm { LlvmNm::new() } +/// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available +/// at `$LLVM_BIN_DIR/llvm-bcanalyzer`. +pub fn llvm_bcanalyzer() -> LlvmBcanalyzer { + LlvmBcanalyzer::new() +} + /// A `llvm-readobj` invocation builder. #[derive(Debug)] #[must_use] @@ -84,12 +90,20 @@ pub struct LlvmNm { cmd: Command, } +/// A `llvm-bcanalyzer` invocation builder. +#[derive(Debug)] +#[must_use] +pub struct LlvmBcanalyzer { + cmd: Command, +} + crate::macros::impl_common_helpers!(LlvmReadobj); crate::macros::impl_common_helpers!(LlvmProfdata); crate::macros::impl_common_helpers!(LlvmFilecheck); crate::macros::impl_common_helpers!(LlvmObjdump); crate::macros::impl_common_helpers!(LlvmAr); crate::macros::impl_common_helpers!(LlvmNm); +crate::macros::impl_common_helpers!(LlvmBcanalyzer); /// Generate the path to the bin directory of LLVM. #[must_use] @@ -250,6 +264,12 @@ impl LlvmAr { self } + /// Extract archive members back to files. + pub fn extract(&mut self) -> &mut Self { + self.cmd.arg("x"); + self + } + /// Provide an output, then an input file. Bundled in one function, as llvm-ar has /// no "--output"-style flag. pub fn output_input(&mut self, out: impl AsRef, input: impl AsRef) -> &mut Self { @@ -274,3 +294,19 @@ impl LlvmNm { self } } + +impl LlvmBcanalyzer { + /// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available + /// at `$LLVM_BIN_DIR/llvm-bcanalyzer`. + pub fn new() -> Self { + let llvm_bcanalyzer = llvm_bin_dir().join("llvm-bcanalyzer"); + let cmd = Command::new(llvm_bcanalyzer); + Self { cmd } + } + + /// Provide an input file. + pub fn input>(&mut self, path: P) -> &mut Self { + self.cmd.arg(path.as_ref()); + self + } +} diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index f28f2a120a44..2c9c3e175fe3 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -48,8 +48,8 @@ pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc}; pub use clang::{clang, Clang}; pub use htmldocck::htmldocck; pub use llvm::{ - llvm_ar, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr, - LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj, + llvm_ar, llvm_bcanalyzer, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj, + LlvmAr, LlvmBcanalyzer, LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj, }; pub use python::python_command; pub use rustc::{aux_build, bare_rustc, rustc, Rustc}; diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 84436e96767a..9e1c520a2c00 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -4,7 +4,6 @@ run-make/cdylib-dylib-linkage/Makefile run-make/cross-lang-lto-clang/Makefile run-make/cross-lang-lto-pgo-smoketest/Makefile run-make/cross-lang-lto-upstream-rlibs/Makefile -run-make/cross-lang-lto/Makefile run-make/dep-info-doesnt-run-much/Makefile run-make/dep-info-spaces/Makefile run-make/dep-info/Makefile diff --git a/tests/run-make/cross-lang-lto/Makefile b/tests/run-make/cross-lang-lto/Makefile deleted file mode 100644 index 92058f952a9f..000000000000 --- a/tests/run-make/cross-lang-lto/Makefile +++ /dev/null @@ -1,57 +0,0 @@ - -include ../tools.mk - -# ignore windows due to libLLVM being present in PATH and the PATH and library path being the same -# (so fixing it is harder). See #57765 for context -ifndef IS_WINDOWS - -# This test makes sure that the object files we generate are actually -# LLVM bitcode files (as used by linker LTO plugins) when compiling with -# -Clinker-plugin-lto. - -# this only succeeds for bitcode files -ASSERT_IS_BITCODE_OBJ=("$(LLVM_BIN_DIR)"/llvm-bcanalyzer $(1)) -EXTRACT_OBJS=(cd $(TMPDIR); rm -f ./*.o; "$(LLVM_BIN_DIR)"/llvm-ar x $(1)) - -BUILD_LIB=$(RUSTC) lib.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1 -BUILD_EXE=$(RUSTC) main.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1 --emit=obj - -all: staticlib staticlib-fat-lto staticlib-thin-lto rlib exe cdylib rdylib - -staticlib: lib.rs - $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib.a - $(call EXTRACT_OBJS, liblib.a) - for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done - -staticlib-fat-lto: lib.rs - $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-fat-lto.a -Clto=fat - $(call EXTRACT_OBJS, liblib-fat-lto.a) - for file in $(TMPDIR)/liblib-fat-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done - -staticlib-thin-lto: lib.rs - $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-thin-lto.a -Clto=thin - $(call EXTRACT_OBJS, liblib-thin-lto.a) - for file in $(TMPDIR)/liblib-thin-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done - -rlib: lib.rs - $(BUILD_LIB) --crate-type=rlib -o $(TMPDIR)/liblib.rlib - $(call EXTRACT_OBJS, liblib.rlib) - for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done - -cdylib: lib.rs - $(BUILD_LIB) --crate-type=cdylib --emit=obj -o $(TMPDIR)/cdylib.o - $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/cdylib.o) - -rdylib: lib.rs - $(BUILD_LIB) --crate-type=dylib --emit=obj -o $(TMPDIR)/rdylib.o - $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/rdylib.o) - -exe: lib.rs - $(BUILD_EXE) -o $(TMPDIR)/exe.o - $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/exe.o) - -else - -all: - -endif diff --git a/tests/run-make/cross-lang-lto/rmake.rs b/tests/run-make/cross-lang-lto/rmake.rs new file mode 100644 index 000000000000..dc376b561e43 --- /dev/null +++ b/tests/run-make/cross-lang-lto/rmake.rs @@ -0,0 +1,110 @@ +// This test checks that the object files we generate are actually +// LLVM bitcode files (as used by linker LTO plugins) when compiling with +// -Clinker-plugin-lto. +// See https://github.com/rust-lang/rust/pull/50000 + +#![feature(path_file_prefix)] + +use std::path::PathBuf; + +use run_make_support::{ + cwd, has_extension, has_prefix, llvm_ar, llvm_bcanalyzer, path, rfs, rust_lib_name, rustc, + shallow_find_files, static_lib_name, +}; + +fn main() { + check_bitcode(LibBuild { + source: path("lib.rs"), + crate_type: Some("staticlib"), + output: path(static_lib_name("liblib")), + lto: None, + emit_obj: false, + }); + check_bitcode(LibBuild { + source: path("lib.rs"), + crate_type: Some("staticlib"), + output: path(static_lib_name("liblib-fat-lto")), + lto: Some("fat"), + emit_obj: false, + }); + check_bitcode(LibBuild { + source: path("lib.rs"), + crate_type: Some("staticlib"), + output: path(static_lib_name("liblib-thin-lto")), + lto: Some("thin"), + emit_obj: false, + }); + check_bitcode(LibBuild { + source: path("lib.rs"), + crate_type: Some("rlib"), + output: path(rust_lib_name("liblib")), + lto: None, + emit_obj: false, + }); + check_bitcode(LibBuild { + source: path("lib.rs"), + crate_type: Some("cdylib"), + output: path("cdylib.o"), + lto: None, + emit_obj: true, + }); + check_bitcode(LibBuild { + source: path("lib.rs"), + crate_type: Some("dylib"), + output: path("rdylib.o"), + lto: None, + emit_obj: true, + }); + check_bitcode(LibBuild { + source: path("main.rs"), + crate_type: None, + output: path("exe.o"), + lto: None, + emit_obj: true, + }); +} + +#[track_caller] +fn check_bitcode(instructions: LibBuild) { + let mut rustc = rustc(); + rustc + .input(instructions.source) + .output(&instructions.output) + .opt_level("2") + .codegen_units(1) + .arg("-Clinker-plugin-lto"); + if instructions.emit_obj { + rustc.emit("obj"); + } + if let Some(crate_type) = instructions.crate_type { + rustc.crate_type(crate_type); + } + if let Some(lto) = instructions.lto { + rustc.arg(format!("-Clto={lto}")); + } + rustc.run(); + + if instructions.output.extension().unwrap() != "o" { + // Remove all potential leftover object files, then turn the output into an object file. + for object in shallow_find_files(cwd(), |path| has_extension(path, "o")) { + rfs::remove_file(object); + } + llvm_ar().extract().arg(&instructions.output).run(); + } + + for object in shallow_find_files(cwd(), |path| { + has_prefix(path, instructions.output.file_prefix().unwrap().to_str().unwrap()) + && has_extension(path, "o") + }) { + // All generated object files should be LLVM bitcode files - this will fail otherwise. + llvm_bcanalyzer().input(object).run(); + } +} + +struct LibBuild { + source: PathBuf, + crate_type: Option<&'static str>, + output: PathBuf, + lto: Option<&'static str>, + emit_obj: bool, +} From f97aba2271baf1876940b42cc68f1b60ac97bf98 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 31 Jul 2024 20:26:08 +0200 Subject: [PATCH 19/62] raw_eq: using it on bytes with provenance is not UB (outside const-eval) --- compiler/rustc_const_eval/messages.ftl | 3 --- .../rustc_const_eval/src/interpret/intrinsics.rs | 3 --- library/core/src/intrinsics.rs | 6 ++++-- .../miri/tests/fail/intrinsics/raw_eq_on_ptr.rs | 10 ---------- .../tests/fail/intrinsics/raw_eq_on_ptr.stderr | 15 --------------- tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs | 2 +- .../intrinsics/intrinsic-raw_eq-const-bad.stderr | 5 ++++- 7 files changed, 9 insertions(+), 35 deletions(-) delete mode 100644 src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.rs delete mode 100644 src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 43f405b22350..18687dfdd376 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -301,9 +301,6 @@ const_eval_range_upper = less or equal to {$hi} const_eval_range_wrapping = less or equal to {$hi}, or greater or equal to {$lo} const_eval_raw_bytes = the raw bytes of the constant (size: {$size}, align: {$align}) {"{"}{$bytes}{"}"} -const_eval_raw_eq_with_provenance = - `raw_eq` on bytes with provenance - const_eval_raw_ptr_comparison = pointers cannot be reliably compared during const eval .note = see issue #53020 for more information diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 1e3de224380b..6b78e49aed29 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -693,9 +693,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // zero-sized access return Ok(&[]); }; - if alloc_ref.has_provenance() { - throw_ub_custom!(fluent::const_eval_raw_eq_with_provenance); - } alloc_ref.get_bytes_strip_provenance() }; diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 13c7f0855d8f..e9eacbcd25a0 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2436,11 +2436,13 @@ extern "rust-intrinsic" { /// /// # Safety /// - /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized or carry a - /// pointer value. + /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized. /// Note that this is a stricter criterion than just the *values* being /// fully-initialized: if `T` has padding, it's UB to call this intrinsic. /// + /// At compile-time, it is furthermore UB to call this if any of the bytes + /// in `*a` or `*b` have provenance. + /// /// (The implementation is allowed to branch on the results of comparisons, /// which is UB if any of their inputs are `undef`.) #[rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none")] diff --git a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.rs b/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.rs deleted file mode 100644 index c14f86147dbb..000000000000 --- a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(intrinsics)] - -extern "rust-intrinsic" { - fn raw_eq(a: &T, b: &T) -> bool; -} - -fn main() { - let x = &0; - unsafe { raw_eq(&x, &x) }; //~ERROR: `raw_eq` on bytes with provenance -} diff --git a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr deleted file mode 100644 index 83f81fa726ea..000000000000 --- a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: Undefined Behavior: `raw_eq` on bytes with provenance - --> $DIR/raw_eq_on_ptr.rs:LL:CC - | -LL | unsafe { raw_eq(&x, &x) }; - | ^^^^^^^^^^^^^^ `raw_eq` on bytes with provenance - | - = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior - = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: BACKTRACE: - = note: inside `main` at $DIR/raw_eq_on_ptr.rs:LL:CC - -note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace - -error: aborting due to 1 previous error - diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs index 0e894ef581c3..ab46fd796c53 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs @@ -10,7 +10,7 @@ const RAW_EQ_PADDING: bool = unsafe { const RAW_EQ_PTR: bool = unsafe { std::intrinsics::raw_eq(&(&0), &(&1)) //~^ ERROR evaluation of constant value failed -//~| `raw_eq` on bytes with provenance +//~| unable to turn pointer into integer }; pub fn main() { diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr index 317466eb3226..af16c2bc64a9 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr @@ -8,7 +8,10 @@ error[E0080]: evaluation of constant value failed --> $DIR/intrinsic-raw_eq-const-bad.rs:11:5 | LL | std::intrinsics::raw_eq(&(&0), &(&1)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `raw_eq` on bytes with provenance + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: aborting due to 2 previous errors From 2eb2ef1684e4df67389432fe0c1cc2776c790cd7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 31 Jul 2024 19:16:09 +1000 Subject: [PATCH 20/62] Streamline attribute stitching on AST nodes. It can be done more concisely. --- .../rustc_parse/src/parser/attr_wrapper.rs | 7 +++---- compiler/rustc_parse/src/parser/expr.rs | 18 +++++++----------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 611dbc0535c6..ba20bd9daf70 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -53,10 +53,9 @@ impl AttrWrapper { /// Prepend `self.attrs` to `attrs`. // FIXME: require passing an NT to prevent misuse of this method - pub(crate) fn prepend_to_nt_inner(self, attrs: &mut AttrVec) { - let mut self_attrs = self.attrs; - mem::swap(attrs, &mut self_attrs); - attrs.extend(self_attrs); + pub(crate) fn prepend_to_nt_inner(mut self, attrs: &mut AttrVec) { + mem::swap(attrs, &mut self.attrs); + attrs.extend(self.attrs); } pub fn is_empty(&self) -> bool { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 24e56c5bdee6..ae5c8af7c2d0 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -877,7 +877,7 @@ impl<'a> Parser<'a> { mut e: P, lo: Span, ) -> PResult<'a, P> { - let res = ensure_sufficient_stack(|| { + let mut res = ensure_sufficient_stack(|| { loop { let has_question = if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) { @@ -924,17 +924,13 @@ impl<'a> Parser<'a> { // Stitch the list of outer attributes onto the return value. A little // bit ugly, but the best way given the current code structure. - if attrs.is_empty() { - res - } else { - res.map(|expr| { - expr.map(|mut expr| { - attrs.extend(expr.attrs); - expr.attrs = attrs; - expr - }) - }) + if !attrs.is_empty() + && let Ok(expr) = &mut res + { + mem::swap(&mut expr.attrs, &mut attrs); + expr.attrs.extend(attrs) } + res } pub(super) fn parse_dot_suffix_expr( From 9d77d17f7127def53c6a3555ae9a6a1f271a8e37 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Aug 2024 15:41:51 +1000 Subject: [PATCH 21/62] Move a comment to a better spot. --- compiler/rustc_parse/src/parser/stmt.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index e0676b72634e..b3efb87a4a26 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -116,13 +116,12 @@ impl<'a> Parser<'a> { } } } else if let Some(item) = self.parse_item_common( - attrs.clone(), + attrs.clone(), // FIXME: unwanted clone of attrs false, true, FnParseMode { req_name: |_| true, req_body: true }, force_collect, )? { - // FIXME: Bad copy of attrs self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) } else if self.eat(&token::Semi) { // Do not attempt to parse an expression if we're done here. From d1f05fd1848fc68ed89d17f7937e358dacd8aed4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Aug 2024 06:44:39 +1000 Subject: [PATCH 22/62] Distinguish the two kinds of token range. When collecting tokens there are two kinds of range: - a range relative to the parser's full token stream (which we get when we are parsing); - a range relative to a single AST node's token stream (which we use within `LazyAttrTokenStreamImpl` when replacing tokens). These are currently both represented with `Range` and it's easy to mix them up -- until now I hadn't properly understood the difference. This commit introduces `ParserRange` and `NodeRange` to distinguish them. This also requires splitting `ReplaceRange` in two, giving the new types `ParserReplacement` and `NodeReplacement`. (These latter two names reduce the overloading of the word "range".) The commit also rewrites some comments to be clearer. The end result is a little more verbose, but much clearer. --- compiler/rustc_builtin_macros/src/cfg_eval.rs | 2 +- compiler/rustc_parse/src/parser/attr.rs | 6 +- .../rustc_parse/src/parser/attr_wrapper.rs | 124 ++++++++++-------- compiler/rustc_parse/src/parser/mod.rs | 70 +++++++--- 4 files changed, 124 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index dc1874bfecbd..4b05c144d37d 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -202,7 +202,7 @@ impl CfgEval<'_> { } // Now that we have our re-parsed `AttrTokenStream`, recursively configuring - // our attribute target will correctly the tokens as well. + // our attribute target will correctly configure the tokens as well. flat_map_annotatable(self, annotatable) } } diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 12b9414d1f76..a98382efc3eb 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -8,7 +8,7 @@ use rustc_span::{sym, BytePos, Span}; use thin_vec::ThinVec; use tracing::debug; -use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle}; +use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, ParserRange, PathStyle}; use crate::{errors, fluent_generated as fluent, maybe_whole}; // Public for rustfmt usage @@ -307,8 +307,8 @@ impl<'a> Parser<'a> { // inner attribute, for possible later processing in a `LazyAttrTokenStream`. if let Capturing::Yes = self.capture_state.capturing { let end_pos = self.num_bump_calls; - let range = start_pos..end_pos; - self.capture_state.inner_attr_ranges.insert(attr.id, range); + let parser_range = ParserRange(start_pos..end_pos); + self.capture_state.inner_attr_parser_ranges.insert(attr.id, parser_range); } attrs.push(attr); } else { diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index ba20bd9daf70..abf61036c2de 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -10,7 +10,10 @@ use rustc_errors::PResult; use rustc_session::parse::ParseSess; use rustc_span::{sym, Span, DUMMY_SP}; -use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCursor}; +use super::{ + Capturing, FlatToken, ForceCollect, NodeRange, NodeReplacement, Parser, ParserRange, + TokenCursor, +}; /// A wrapper type to ensure that the parser handles outer attributes correctly. /// When we parse outer attributes, we need to ensure that we capture tokens @@ -28,8 +31,8 @@ use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCurso #[derive(Debug, Clone)] pub struct AttrWrapper { attrs: AttrVec, - // The start of the outer attributes in the token cursor. - // This allows us to create a `ReplaceRange` for the entire attribute + // The start of the outer attributes in the parser's token stream. + // This lets us create a `NodeReplacement` for the entire attribute // target, including outer attributes. start_pos: u32, } @@ -88,7 +91,7 @@ struct LazyAttrTokenStreamImpl { cursor_snapshot: TokenCursor, num_calls: u32, break_last_token: bool, - replace_ranges: Box<[ReplaceRange]>, + node_replacements: Box<[NodeReplacement]>, } impl ToAttrTokenStream for LazyAttrTokenStreamImpl { @@ -103,21 +106,24 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { .chain(iter::repeat_with(|| FlatToken::Token(cursor_snapshot.next()))) .take(self.num_calls as usize); - if self.replace_ranges.is_empty() { + if self.node_replacements.is_empty() { make_attr_token_stream(tokens, self.break_last_token) } else { let mut tokens: Vec<_> = tokens.collect(); - let mut replace_ranges = self.replace_ranges.to_vec(); - replace_ranges.sort_by_key(|(range, _)| range.start); + let mut node_replacements = self.node_replacements.to_vec(); + node_replacements.sort_by_key(|(range, _)| range.0.start); #[cfg(debug_assertions)] - for [(range, tokens), (next_range, next_tokens)] in replace_ranges.array_windows() { + for [(node_range, tokens), (next_node_range, next_tokens)] in + node_replacements.array_windows() + { assert!( - range.end <= next_range.start || range.end >= next_range.end, - "Replace ranges should either be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})", - range, + node_range.0.end <= next_node_range.0.start + || node_range.0.end >= next_node_range.0.end, + "Node ranges should be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})", + node_range, tokens, - next_range, + next_node_range, next_tokens, ); } @@ -135,20 +141,23 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { // start position, we ensure that any (outer) replace range which // encloses another (inner) replace range will fully overwrite the // inner range's replacement. - for (range, target) in replace_ranges.into_iter().rev() { - assert!(!range.is_empty(), "Cannot replace an empty range: {range:?}"); + for (node_range, target) in node_replacements.into_iter().rev() { + assert!( + !node_range.0.is_empty(), + "Cannot replace an empty node range: {:?}", + node_range.0 + ); // Replace the tokens in range with zero or one `FlatToken::AttrsTarget`s, plus // enough `FlatToken::Empty`s to fill up the rest of the range. This keeps the // total length of `tokens` constant throughout the replacement process, allowing - // us to use all of the `ReplaceRanges` entries without adjusting indices. + // us to do all replacements without adjusting indices. let target_len = target.is_some() as usize; tokens.splice( - (range.start as usize)..(range.end as usize), - target - .into_iter() - .map(|target| FlatToken::AttrsTarget(target)) - .chain(iter::repeat(FlatToken::Empty).take(range.len() - target_len)), + (node_range.0.start as usize)..(node_range.0.end as usize), + target.into_iter().map(|target| FlatToken::AttrsTarget(target)).chain( + iter::repeat(FlatToken::Empty).take(node_range.0.len() - target_len), + ), ); } make_attr_token_stream(tokens.into_iter(), self.break_last_token) @@ -215,7 +224,7 @@ impl<'a> Parser<'a> { let cursor_snapshot = self.token_cursor.clone(); let start_pos = self.num_bump_calls; let has_outer_attrs = !attrs.attrs.is_empty(); - let replace_ranges_start = self.capture_state.replace_ranges.len(); + let parser_replacements_start = self.capture_state.parser_replacements.len(); // We set and restore `Capturing::Yes` on either side of the call to // `f`, so we can distinguish the outermost call to @@ -270,7 +279,7 @@ impl<'a> Parser<'a> { return Ok(ret); } - let replace_ranges_end = self.capture_state.replace_ranges.len(); + let parser_replacements_end = self.capture_state.parser_replacements.len(); assert!( !(self.break_last_token && capture_trailing), @@ -287,15 +296,16 @@ impl<'a> Parser<'a> { let num_calls = end_pos - start_pos; - // Take the captured ranges for any inner attributes that we parsed in - // `Parser::parse_inner_attributes`, and pair them in a `ReplaceRange` - // with `None`, which means the relevant tokens will be removed. (More - // details below.) - let mut inner_attr_replace_ranges = Vec::new(); + // Take the captured `ParserRange`s for any inner attributes that we parsed in + // `Parser::parse_inner_attributes`, and pair them in a `ParserReplacement` with `None`, + // which means the relevant tokens will be removed. (More details below.) + let mut inner_attr_parser_replacements = Vec::new(); for attr in ret.attrs() { if attr.style == ast::AttrStyle::Inner { - if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&attr.id) { - inner_attr_replace_ranges.push((attr_range, None)); + if let Some(inner_attr_parser_range) = + self.capture_state.inner_attr_parser_ranges.remove(&attr.id) + { + inner_attr_parser_replacements.push((inner_attr_parser_range, None)); } else { self.dcx().span_delayed_bug(attr.span, "Missing token range for attribute"); } @@ -304,37 +314,41 @@ impl<'a> Parser<'a> { // This is hot enough for `deep-vector` that checking the conditions for an empty iterator // is measurably faster than actually executing the iterator. - let replace_ranges: Box<[ReplaceRange]> = - if replace_ranges_start == replace_ranges_end && inner_attr_replace_ranges.is_empty() { - Box::new([]) - } else { - // Grab any replace ranges that occur *inside* the current AST node. We will - // perform the actual replacement only when we convert the `LazyAttrTokenStream` to - // an `AttrTokenStream`. - self.capture_state.replace_ranges[replace_ranges_start..replace_ranges_end] - .iter() - .cloned() - .chain(inner_attr_replace_ranges.iter().cloned()) - .map(|(range, data)| ((range.start - start_pos)..(range.end - start_pos), data)) - .collect() - }; + let node_replacements: Box<[_]> = if parser_replacements_start == parser_replacements_end + && inner_attr_parser_replacements.is_empty() + { + Box::new([]) + } else { + // Grab any replace ranges that occur *inside* the current AST node. Convert them + // from `ParserRange` form to `NodeRange` form. We will perform the actual + // replacement only when we convert the `LazyAttrTokenStream` to an + // `AttrTokenStream`. + self.capture_state.parser_replacements + [parser_replacements_start..parser_replacements_end] + .iter() + .cloned() + .chain(inner_attr_parser_replacements.iter().cloned()) + .map(|(parser_range, data)| (NodeRange::new(parser_range, start_pos), data)) + .collect() + }; // What is the status here when parsing the example code at the top of this method? // // When parsing `g`: // - `start_pos..end_pos` is `12..33` (`fn g { ... }`, excluding the outer attr). - // - `inner_attr_replace_ranges` has one entry (`5..15`, when counting from `fn`), to + // - `inner_attr_parser_replacements` has one entry (`ParserRange(17..27)`), to // delete the inner attr's tokens. - // - This entry is put into the lazy tokens for `g`, i.e. deleting the inner attr from - // those tokens (if they get evaluated). + // - This entry is converted to `NodeRange(5..15)` (relative to the `fn`) and put into + // the lazy tokens for `g`, i.e. deleting the inner attr from those tokens (if they get + // evaluated). // - Those lazy tokens are also put into an `AttrsTarget` that is appended to `self`'s // replace ranges at the bottom of this function, for processing when parsing `m`. - // - `replace_ranges_start..replace_ranges_end` is empty. + // - `parser_replacements_start..parser_replacements_end` is empty. // // When parsing `m`: // - `start_pos..end_pos` is `0..34` (`mod m`, excluding the `#[cfg_eval]` attribute). - // - `inner_attr_replace_ranges` is empty. - // - `replace_range_start..replace_ranges_end` has one entry. + // - `inner_attr_parser_replacements` is empty. + // - `parser_replacements_start..parser_replacements_end` has one entry. // - One `AttrsTarget` (added below when parsing `g`) to replace all of `g` (`3..33`, // including its outer attribute), with: // - `attrs`: includes the outer and the inner attr. @@ -345,7 +359,7 @@ impl<'a> Parser<'a> { num_calls, cursor_snapshot, break_last_token: self.break_last_token, - replace_ranges, + node_replacements, }); // If we support tokens and don't already have them, store the newly captured tokens. @@ -366,7 +380,7 @@ impl<'a> Parser<'a> { // What is the status here when parsing the example code at the top of this method? // // When parsing `g`, we add one entry: - // - The `start_pos..end_pos` (`3..33`) entry has a new `AttrsTarget` with: + // - The pushed entry (`ParserRange(3..33)`) has a new `AttrsTarget` with: // - `attrs`: includes the outer and the inner attr. // - `tokens`: lazy tokens for `g` (with its inner attr deleted). // @@ -377,12 +391,14 @@ impl<'a> Parser<'a> { // cfg-expand this AST node. let start_pos = if has_outer_attrs { attrs.start_pos } else { start_pos }; let target = AttrsTarget { attrs: ret.attrs().iter().cloned().collect(), tokens }; - self.capture_state.replace_ranges.push((start_pos..end_pos, Some(target))); + self.capture_state + .parser_replacements + .push((ParserRange(start_pos..end_pos), Some(target))); } else if matches!(self.capture_state.capturing, Capturing::No) { // Only clear the ranges once we've finished capturing entirely, i.e. we've finished // the outermost call to this method. - self.capture_state.replace_ranges.clear(); - self.capture_state.inner_attr_ranges.clear(); + self.capture_state.parser_replacements.clear(); + self.capture_state.inner_attr_parser_ranges.clear(); } Ok(ret) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 26ee5bfdee42..722fb41cd81e 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -192,24 +192,54 @@ struct ClosureSpans { body: Span, } -/// Indicates a range of tokens that should be replaced by -/// the tokens in the provided `AttrsTarget`. This is used in two -/// places during token collection: +/// A token range within a `Parser`'s full token stream. +#[derive(Clone, Debug)] +struct ParserRange(Range); + +/// A token range within an individual AST node's (lazy) token stream, i.e. +/// relative to that node's first token. Distinct from `ParserRange` so the two +/// kinds of range can't be mixed up. +#[derive(Clone, Debug)] +struct NodeRange(Range); + +/// Indicates a range of tokens that should be replaced by an `AttrsTarget` +/// (replacement) or be replaced by nothing (deletion). This is used in two +/// places during token collection. /// -/// 1. During the parsing of an AST node that may have a `#[derive]` -/// attribute, we parse a nested AST node that has `#[cfg]` or `#[cfg_attr]` -/// In this case, we use a `ReplaceRange` to replace the entire inner AST node -/// with `FlatToken::AttrsTarget`, allowing us to perform eager cfg-expansion -/// on an `AttrTokenStream`. +/// 1. Replacement. During the parsing of an AST node that may have a +/// `#[derive]` attribute, when we parse a nested AST node that has `#[cfg]` +/// or `#[cfg_attr]`, we replace the entire inner AST node with +/// `FlatToken::AttrsTarget`. This lets us perform eager cfg-expansion on an +/// `AttrTokenStream`. /// -/// 2. When we parse an inner attribute while collecting tokens. We -/// remove inner attributes from the token stream entirely, and -/// instead track them through the `attrs` field on the AST node. -/// This allows us to easily manipulate them (for example, removing -/// the first macro inner attribute to invoke a proc-macro). -/// When create a `TokenStream`, the inner attributes get inserted -/// into the proper place in the token stream. -type ReplaceRange = (Range, Option); +/// 2. Deletion. We delete inner attributes from all collected token streams, +/// and instead track them through the `attrs` field on the AST node. This +/// lets us manipulate them similarly to outer attributes. When we create a +/// `TokenStream`, the inner attributes are inserted into the proper place +/// in the token stream. +/// +/// Each replacement starts off in `ParserReplacement` form but is converted to +/// `NodeReplacement` form when it is attached to a single AST node, via +/// `LazyAttrTokenStreamImpl`. +type ParserReplacement = (ParserRange, Option); + +/// See the comment on `ParserReplacement`. +type NodeReplacement = (NodeRange, Option); + +impl NodeRange { + // Converts a range within a parser's tokens to a range within a + // node's tokens beginning at `start_pos`. + // + // For example, imagine a parser with 50 tokens in its token stream, a + // function that spans `ParserRange(20..40)` and an inner attribute within + // that function that spans `ParserRange(30..35)`. We would find the inner + // attribute's range within the function's tokens by subtracting 20, which + // is the position of the function's start token. This gives + // `NodeRange(10..15)`. + fn new(ParserRange(parser_range): ParserRange, start_pos: u32) -> NodeRange { + NodeRange((parser_range.start - start_pos)..(parser_range.end - start_pos)) + } +} /// Controls how we capture tokens. Capturing can be expensive, /// so we try to avoid performing capturing in cases where @@ -226,8 +256,8 @@ enum Capturing { #[derive(Clone, Debug)] struct CaptureState { capturing: Capturing, - replace_ranges: Vec, - inner_attr_ranges: FxHashMap>, + parser_replacements: Vec, + inner_attr_parser_ranges: FxHashMap, } /// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that @@ -417,8 +447,8 @@ impl<'a> Parser<'a> { subparser_name, capture_state: CaptureState { capturing: Capturing::No, - replace_ranges: Vec::new(), - inner_attr_ranges: Default::default(), + parser_replacements: Vec::new(), + inner_attr_parser_ranges: Default::default(), }, current_closure: None, recovery: Recovery::Allowed, From 6d312d7bd17598153c018e4879ccaa657eb48853 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 1 Aug 2024 14:01:17 +0200 Subject: [PATCH 23/62] MIR required_consts, mentioned_items: ensure we do not forget to fill these lists --- .../src/interpret/eval_context.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 48 ++++++++++++++++--- compiler/rustc_middle/src/mir/visit.rs | 8 ++-- .../rustc_mir_build/src/build/custom/mod.rs | 4 +- compiler/rustc_mir_transform/src/inline.rs | 13 +++-- compiler/rustc_mir_transform/src/lib.rs | 36 +++++++++----- .../src/mentioned_items.rs | 3 +- .../rustc_mir_transform/src/promote_consts.rs | 14 ++++-- .../src/required_consts.rs | 13 ++++- compiler/rustc_mir_transform/src/shim.rs | 12 +++-- compiler/rustc_monomorphize/src/collector.rs | 4 +- 11 files changed, 113 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 85f9b2341d91..9b4a437bf775 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -888,7 +888,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { body: &'tcx mir::Body<'tcx>, ) -> InterpResult<'tcx> { // Make sure all the constants required by this frame evaluate successfully (post-monomorphization check). - for &const_ in &body.required_consts { + for &const_ in body.required_consts() { let c = self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?; c.eval(*self.tcx, self.param_env, const_.span).map_err(|err| { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index b9c93edcd80e..46c4d586f6ad 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -383,15 +383,17 @@ pub struct Body<'tcx> { /// Constants that are required to evaluate successfully for this MIR to be well-formed. /// We hold in this field all the constants we are not able to evaluate yet. + /// `None` indicates that the list has not been computed yet. /// /// This is soundness-critical, we make a guarantee that all consts syntactically mentioned in a /// function have successfully evaluated if the function ever gets executed at runtime. - pub required_consts: Vec>, + pub required_consts: Option>>, /// Further items that were mentioned in this function and hence *may* become monomorphized, /// depending on optimizations. We use this to avoid optimization-dependent compile errors: the /// collector recursively traverses all "mentioned" items and evaluates all their /// `required_consts`. + /// `None` indicates that the list has not been computed yet. /// /// This is *not* soundness-critical and the contents of this list are *not* a stable guarantee. /// All that's relevant is that this set is optimization-level-independent, and that it includes @@ -399,7 +401,7 @@ pub struct Body<'tcx> { /// set after drop elaboration, so some drop calls that can never be reached are not considered /// "mentioned".) See the documentation of `CollectionMode` in /// `compiler/rustc_monomorphize/src/collector.rs` for more context. - pub mentioned_items: Vec>>, + pub mentioned_items: Option>>>, /// Does this body use generic parameters. This is used for the `ConstEvaluatable` check. /// @@ -477,8 +479,8 @@ impl<'tcx> Body<'tcx> { spread_arg: None, var_debug_info, span, - required_consts: Vec::new(), - mentioned_items: Vec::new(), + required_consts: None, + mentioned_items: None, is_polymorphic: false, injection_phase: None, tainted_by_errors, @@ -507,8 +509,8 @@ impl<'tcx> Body<'tcx> { arg_count: 0, spread_arg: None, span: DUMMY_SP, - required_consts: Vec::new(), - mentioned_items: Vec::new(), + required_consts: None, + mentioned_items: None, var_debug_info: Vec::new(), is_polymorphic: false, injection_phase: None, @@ -785,6 +787,40 @@ impl<'tcx> Body<'tcx> { // No inlined `SourceScope`s, or all of them were `#[track_caller]`. caller_location.unwrap_or_else(|| from_span(source_info.span)) } + + #[track_caller] + pub fn set_required_consts(&mut self, required_consts: Vec>) { + assert!( + self.required_consts.is_none(), + "required_consts for {:?} have already been set", + self.source.def_id() + ); + self.required_consts = Some(required_consts); + } + #[track_caller] + pub fn required_consts(&self) -> &[ConstOperand<'tcx>] { + match &self.required_consts { + Some(l) => l, + None => panic!("required_consts for {:?} have not yet been set", self.source.def_id()), + } + } + + #[track_caller] + pub fn set_mentioned_items(&mut self, mentioned_items: Vec>>) { + assert!( + self.mentioned_items.is_none(), + "mentioned_items for {:?} have already been set", + self.source.def_id() + ); + self.mentioned_items = Some(mentioned_items); + } + #[track_caller] + pub fn mentioned_items(&self) -> &[Spanned>] { + match &self.mentioned_items { + Some(l) => l, + None => panic!("mentioned_items for {:?} have not yet been set", self.source.def_id()), + } + } } impl<'tcx> Index for Body<'tcx> { diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 0031ded24406..3921176873c8 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1066,9 +1066,11 @@ macro_rules! super_body { $self.visit_span($(& $mutability)? $body.span); - for const_ in &$($mutability)? $body.required_consts { - let location = Location::START; - $self.visit_const_operand(const_, location); + if let Some(required_consts) = &$($mutability)? $body.required_consts { + for const_ in required_consts { + let location = Location::START; + $self.visit_const_operand(const_, location); + } } } } diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 38acb6f44f95..28477e527c72 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -54,8 +54,8 @@ pub(super) fn build_custom_mir<'tcx>( spread_arg: None, var_debug_info: Vec::new(), span, - required_consts: Vec::new(), - mentioned_items: Vec::new(), + required_consts: None, + mentioned_items: None, is_polymorphic: false, tainted_by_errors: None, injection_phase: None, diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 36b2b3b7c446..f30732e6aaf3 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -744,8 +744,8 @@ impl<'tcx> Inliner<'tcx> { // Copy required constants from the callee_body into the caller_body. Although we are only // pushing unevaluated consts to `required_consts`, here they may have been evaluated // because we are calling `instantiate_and_normalize_erasing_regions` -- so we filter again. - caller_body.required_consts.extend( - callee_body.required_consts.into_iter().filter(|ct| ct.const_.is_required_const()), + caller_body.required_consts.as_mut().unwrap().extend( + callee_body.required_consts().into_iter().filter(|ct| ct.const_.is_required_const()), ); // Now that we incorporated the callee's `required_consts`, we can remove the callee from // `mentioned_items` -- but we have to take their `mentioned_items` in return. This does @@ -755,12 +755,11 @@ impl<'tcx> Inliner<'tcx> { // We need to reconstruct the `required_item` for the callee so that we can find and // remove it. let callee_item = MentionedItem::Fn(func.ty(caller_body, self.tcx)); - if let Some(idx) = - caller_body.mentioned_items.iter().position(|item| item.node == callee_item) - { + let caller_mentioned_items = caller_body.mentioned_items.as_mut().unwrap(); + if let Some(idx) = caller_mentioned_items.iter().position(|item| item.node == callee_item) { // We found the callee, so remove it and add its items instead. - caller_body.mentioned_items.remove(idx); - caller_body.mentioned_items.extend(callee_body.mentioned_items); + caller_mentioned_items.remove(idx); + caller_mentioned_items.extend(callee_body.mentioned_items()); } else { // If we can't find the callee, there's no point in adding its items. Probably it // already got removed by being inlined elsewhere in the same function, so we already diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index ac3a44c803a5..1f214bc42cbe 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -28,11 +28,10 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_index::IndexVec; -use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{ - traversal, AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs, - LocalDecl, MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, - SourceInfo, Statement, StatementKind, TerminatorKind, START_BLOCK, + AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs, LocalDecl, + MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, + Statement, StatementKind, TerminatorKind, START_BLOCK, }; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_middle::util::Providers; @@ -339,12 +338,15 @@ fn mir_promoted( // Collect `required_consts` *before* promotion, so if there are any consts being promoted // we still add them to the list in the outer MIR body. - let mut required_consts = Vec::new(); - let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts); - for (bb, bb_data) in traversal::reverse_postorder(&body) { - required_consts_visitor.visit_basic_block_data(bb, bb_data); + RequiredConstsVisitor::compute_required_consts(&mut body); + // If this has an associated by-move async closure body, that doesn't get run through these + // passes itself, it gets "tagged along" by the pass manager. `RequiredConstsVisitor` is not + // a regular pass so we have to also apply it manually to the other body. + if let Some(coroutine) = body.coroutine.as_mut() { + if let Some(by_move_body) = coroutine.by_move_body.as_mut() { + RequiredConstsVisitor::compute_required_consts(by_move_body); + } } - body.required_consts = required_consts; // What we need to run borrowck etc. let promote_pass = promote_consts::PromoteTemps::default(); @@ -561,9 +563,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { tcx, body, &[ - // Before doing anything, remember which items are being mentioned so that the set of items - // visited does not depend on the optimization level. - &mentioned_items::MentionedItems, // Add some UB checks before any UB gets optimized away. &check_alignment::CheckAlignment, // Before inlining: trim down MIR with passes to reduce inlining work. @@ -657,6 +656,19 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { return body; } + // Before doing anything, remember which items are being mentioned so that the set of items + // visited does not depend on the optimization level. + // We do not use `run_passes` for this as that might skip the pass if `injection_phase` is set. + mentioned_items::MentionedItems.run_pass(tcx, &mut body); + // If this has an associated by-move async closure body, that doesn't get run through these + // passes itself, it gets "tagged along" by the pass manager. Since we're not using the pass + // manager we have to do this by hand. + if let Some(coroutine) = body.coroutine.as_mut() { + if let Some(by_move_body) = coroutine.by_move_body.as_mut() { + mentioned_items::MentionedItems.run_pass(tcx, by_move_body); + } + } + // If `mir_drops_elaborated_and_const_checked` found that the current body has unsatisfiable // predicates, it will shrink the MIR to a single `unreachable` terminator. // More generally, if MIR is a lone `unreachable`, there is nothing to optimize. diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index e33bdd994219..32c8064ebca5 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -23,10 +23,9 @@ impl<'tcx> MirPass<'tcx> for MentionedItems { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { - debug_assert!(body.mentioned_items.is_empty()); let mut mentioned_items = Vec::new(); MentionedItemsVisitor { tcx, body, mentioned_items: &mut mentioned_items }.visit_body(body); - body.mentioned_items = mentioned_items; + body.set_mentioned_items(mentioned_items); } } diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index f8971387ea4d..dc8e50ac8cd2 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -702,6 +702,9 @@ struct Promoter<'a, 'tcx> { temps: &'a mut IndexVec, extra_statements: &'a mut Vec<(Location, Statement<'tcx>)>, + /// Used to assemble the required_consts list while building the promoted. + required_consts: Vec>, + /// If true, all nested temps are also kept in the /// source MIR, not moved to the promoted MIR. keep_original: bool, @@ -924,11 +927,14 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let span = self.promoted.span; self.assign(RETURN_PLACE, rvalue, span); - // Now that we did promotion, we know whether we'll want to add this to `required_consts`. + // Now that we did promotion, we know whether we'll want to add this to `required_consts` of + // the surrounding MIR body. if self.add_to_required { - self.source.required_consts.push(promoted_op); + self.source.required_consts.as_mut().unwrap().push(promoted_op); } + self.promoted.set_required_consts(self.required_consts); + self.promoted } } @@ -947,7 +953,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>, _location: Location) { if constant.const_.is_required_const() { - self.promoted.required_consts.push(*constant); + self.required_consts.push(*constant); } // Skipping `super_constant` as the visitor is otherwise only looking for locals. @@ -1011,9 +1017,9 @@ fn promote_candidates<'tcx>( extra_statements: &mut extra_statements, keep_original: false, add_to_required: false, + required_consts: Vec::new(), }; - // `required_consts` of the promoted itself gets filled while building the MIR body. let mut promoted = promoter.promote_candidate(candidate, promotions.len()); promoted.source.promoted = Some(promotions.next_index()); promotions.push(promoted); diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs index 00bfb5e66008..50637e2ac03b 100644 --- a/compiler/rustc_mir_transform/src/required_consts.rs +++ b/compiler/rustc_mir_transform/src/required_consts.rs @@ -1,14 +1,23 @@ use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::{ConstOperand, Location}; +use rustc_middle::mir::{traversal, Body, ConstOperand, Location}; pub struct RequiredConstsVisitor<'a, 'tcx> { required_consts: &'a mut Vec>, } impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> { - pub fn new(required_consts: &'a mut Vec>) -> Self { + fn new(required_consts: &'a mut Vec>) -> Self { RequiredConstsVisitor { required_consts } } + + pub fn compute_required_consts(body: &mut Body<'tcx>) { + let mut required_consts = Vec::new(); + let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts); + for (bb, bb_data) in traversal::reverse_postorder(&body) { + required_consts_visitor.visit_basic_block_data(bb, bb_data); + } + body.set_required_consts(required_consts); + } } impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index e2fafa3a1a30..f41f3ef656c5 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -305,7 +305,7 @@ fn new_body<'tcx>( arg_count: usize, span: Span, ) -> Body<'tcx> { - Body::new( + let mut body = Body::new( source, basic_blocks, IndexVec::from_elem_n( @@ -326,7 +326,10 @@ fn new_body<'tcx>( None, // FIXME(compiler-errors): is this correct? None, - ) + ); + // Shims do not directly mention any consts. + body.set_required_consts(Vec::new()); + body } pub struct DropShimElaborator<'a, 'tcx> { @@ -969,13 +972,16 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { }; let source = MirSource::item(ctor_id); - let body = new_body( + let mut body = new_body( source, IndexVec::from_elem_n(start_block, 1), local_decls, sig.inputs().len(), span, ); + // A constructor doesn't mention any other items (and we don't run the usual optimization passes + // so this would otherwise not get filled). + body.set_mentioned_items(Vec::new()); crate::pass_manager::dump_mir_for_phase_change(tcx, &body); diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 99cac67f5b1c..df2abf6dc9cc 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1229,7 +1229,7 @@ fn collect_items_of_instance<'tcx>( // Always visit all `required_consts`, so that we evaluate them and abort compilation if any of // them errors. - for const_op in &body.required_consts { + for const_op in body.required_consts() { if let Some(val) = collector.eval_constant(const_op) { collect_const_value(tcx, val, mentioned_items); } @@ -1237,7 +1237,7 @@ fn collect_items_of_instance<'tcx>( // Always gather mentioned items. We try to avoid processing items that we have already added to // `used_items` above. - for item in &body.mentioned_items { + for item in body.mentioned_items() { if !collector.used_mentioned_items.contains(&item.node) { let item_mono = collector.monomorphize(item.node); visit_mentioned_item(tcx, &item_mono, item.span, mentioned_items); From f44958679a59eacf7a8c4356983df042d890fc1d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 31 Jul 2024 16:08:31 +0200 Subject: [PATCH 24/62] Update sysinfo version to 0.31.2 --- Cargo.lock | 87 ++++++++++++++++------ src/bootstrap/Cargo.lock | 111 +++++++++++++++++++++-------- src/bootstrap/Cargo.toml | 2 +- src/bootstrap/src/utils/metrics.rs | 17 +++-- src/tools/opt-dist/Cargo.toml | 2 +- 5 files changed, 158 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a7d7e3f5d7d..316926e584e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -771,7 +771,7 @@ dependencies = [ "tracing-subscriber", "unified-diff", "walkdir", - "windows", + "windows 0.52.0", ] [[package]] @@ -1713,7 +1713,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -2436,15 +2436,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -3717,7 +3708,7 @@ dependencies = [ "thorin-dwp", "tracing", "wasm-encoder 0.210.0", - "windows", + "windows 0.52.0", ] [[package]] @@ -3774,7 +3765,7 @@ dependencies = [ "tempfile", "thin-vec", "tracing", - "windows", + "windows 0.52.0", ] [[package]] @@ -3835,7 +3826,7 @@ dependencies = [ "shlex", "time", "tracing", - "windows", + "windows 0.52.0", ] [[package]] @@ -3886,7 +3877,7 @@ dependencies = [ "termcolor", "termize", "tracing", - "windows", + "windows 0.52.0", ] [[package]] @@ -4607,7 +4598,7 @@ dependencies = [ "smallvec", "termize", "tracing", - "windows", + "windows 0.52.0", ] [[package]] @@ -5365,16 +5356,13 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.30.12" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732ffa00f53e6b2af46208fba5718d9662a421049204e156328b66791ffa15ae" +checksum = "d4115055da5f572fff541dd0c4e61b0262977f453cc9fe04be83aba25a89bdab" dependencies = [ - "cfg-if", "core-foundation-sys", "libc", - "ntapi", - "once_cell", - "windows", + "windows 0.57.0", ] [[package]] @@ -6299,7 +6287,17 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", + "windows-core 0.52.0", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", "windows-targets 0.52.5", ] @@ -6326,12 +6324,55 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.67", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.67", +] + [[package]] name = "windows-metadata" version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e837f3c3012cfe9e7086302a93f441a7999439be1ad4c530d55d2f6d2921809" +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index de0924c0f423..60453764d82d 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -65,7 +65,7 @@ dependencies = [ "termcolor", "toml", "walkdir", - "windows", + "windows 0.52.0", "xz2", ] @@ -378,12 +378,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - [[package]] name = "opener" version = "0.5.2" @@ -549,16 +543,15 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.30.5" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb4f3438c8f6389c864e61221cbc97e9bca98b4daf39a5beb7bea660f528bb2" +checksum = "d4115055da5f572fff541dd0c4e61b0262977f453cc9fe04be83aba25a89bdab" dependencies = [ - "cfg-if", "core-foundation-sys", "libc", + "memchr", "ntapi", - "once_cell", - "windows", + "windows 0.57.0", ] [[package]] @@ -655,7 +648,17 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", + "windows-core 0.52.0", + "windows-targets", +] + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", "windows-targets", ] @@ -668,6 +671,49 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -679,13 +725,14 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -694,45 +741,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "xattr" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index f723407c3ce3..84262c115b12 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -63,7 +63,7 @@ walkdir = "2.4" xz2 = "0.1" # Dependencies needed by the build-metrics feature -sysinfo = { version = "0.30", default-features = false, optional = true } +sysinfo = { version = "0.31.2", default-features = false, optional = true, features = ["system"] } [target.'cfg(windows)'.dependencies.junction] version = "1.0.0" diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs index bd18eb35c1f2..e9acb93363e7 100644 --- a/src/bootstrap/src/utils/metrics.rs +++ b/src/bootstrap/src/utils/metrics.rs @@ -13,7 +13,7 @@ use build_helper::metrics::{ JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, Test, TestOutcome, TestSuite, TestSuiteMetadata, }; -use sysinfo::System; +use sysinfo::{CpuRefreshKind, RefreshKind, System}; use crate::core::builder::{Builder, Step}; use crate::utils::helpers::t; @@ -55,7 +55,9 @@ impl BuildMetrics { finished_steps: Vec::new(), running_steps: Vec::new(), - system_info: System::new(), + system_info: System::new_with_specifics( + RefreshKind::new().with_cpu(CpuRefreshKind::everything()), + ), timer_start: None, invocation_timer_start: Instant::now(), invocation_start: SystemTime::now(), @@ -77,7 +79,7 @@ impl BuildMetrics { self.collect_stats(&mut *state); } - state.system_info.refresh_cpu(); + state.system_info.refresh_cpu_usage(); state.timer_start = Some(Instant::now()); state.running_steps.push(StepMetrics { @@ -110,7 +112,7 @@ impl BuildMetrics { state.running_steps.last_mut().unwrap().children.push(step); // Start collecting again for the parent step. - state.system_info.refresh_cpu(); + state.system_info.refresh_cpu_usage(); state.timer_start = Some(Instant::now()); } } @@ -148,7 +150,7 @@ impl BuildMetrics { let elapsed = state.timer_start.unwrap().elapsed(); step.duration_excluding_children_sec += elapsed; - state.system_info.refresh_cpu(); + state.system_info.refresh_cpu_usage(); let cpu = state.system_info.cpus().iter().map(|p| p.cpu_usage()).sum::(); step.cpu_usage_time_sec += cpu as f64 / 100.0 * elapsed.as_secs_f64(); } @@ -159,8 +161,9 @@ impl BuildMetrics { let dest = build.out.join("metrics.json"); - let mut system = System::new(); - system.refresh_cpu(); + let mut system = + System::new_with_specifics(RefreshKind::new().with_cpu(CpuRefreshKind::everything())); + system.refresh_cpu_usage(); system.refresh_memory(); let system_stats = JsonInvocationSystemStats { diff --git a/src/tools/opt-dist/Cargo.toml b/src/tools/opt-dist/Cargo.toml index 88e8640d56ab..d34f8ad05208 100644 --- a/src/tools/opt-dist/Cargo.toml +++ b/src/tools/opt-dist/Cargo.toml @@ -10,7 +10,7 @@ log = "0.4" anyhow = { version = "1", features = ["backtrace"] } humantime = "2" humansize = "2" -sysinfo = { version = "0.30", default-features = false } +sysinfo = { version = "0.31.2", default-features = false, features = ["disk"] } fs_extra = "1" camino = "1" tar = "0.4" From 8ce8c42e0bf66d32504659cbbe91ad2a0c315891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 22 Jun 2024 04:32:49 +0000 Subject: [PATCH 25/62] Do not underline suggestions for code that is already there When a suggestion part is for already present code, do not highlight it. If after that there are no highlights left, do not show the suggestion at all. Fix clippy lint suggestion incorrectly treated as `span_help`. --- compiler/rustc_errors/src/emitter.rs | 21 +++++++++- compiler/rustc_errors/src/lib.rs | 22 ++++++++--- .../clippy_lints/src/unnecessary_wraps.rs | 4 +- .../ui/unnecessary_literal_unwrap.stderr | 4 +- .../clippy/tests/ui/unnecessary_wraps.stderr | 8 ++-- .../generic_const_exprs/issue-105608.stderr | 4 -- tests/ui/imports/issue-55884-2.stderr | 4 -- tests/ui/lint/wide_pointer_comparisons.stderr | 38 +++++++++---------- tests/ui/privacy/issue-75907.stderr | 2 +- tests/ui/privacy/privacy5.stderr | 20 +++++----- ...ue-42234-unknown-receiver-type.full.stderr | 4 -- ...-turbofish-surrounding-angle-braket.stderr | 2 +- 12 files changed, 75 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 73908e580856..8963b009c31e 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1767,7 +1767,10 @@ impl HumanEmitter { debug!(?suggestions); if suggestions.is_empty() { - // Suggestions coming from macros can have malformed spans. This is a heavy handed + // Here we check if there are suggestions that have actual code changes. We sometimes + // suggest the same code that is already there, instead of changing how we produce the + // suggestions and filtering there, we just don't emit the suggestion. + // Suggestions coming from macros can also have malformed spans. This is a heavy handed // approach to avoid ICEs by ignoring the suggestion outright. return Ok(()); } @@ -2046,7 +2049,9 @@ impl HumanEmitter { assert!(underline_start >= 0 && underline_end >= 0); let padding: usize = max_line_num_len + 3; for p in underline_start..underline_end { - if let DisplaySuggestion::Underline = show_code_change { + if let DisplaySuggestion::Underline = show_code_change + && is_different(sm, &part.snippet, part.span) + { // If this is a replacement, underline with `~`, if this is an addition // underline with `+`. buffer.putc( @@ -2824,6 +2829,18 @@ impl Style { } } +/// Whether the original and suggested code are the same. +pub fn is_different(sm: &SourceMap, suggested: &str, sp: Span) -> bool { + let found = match sm.span_to_snippet(sp) { + Ok(snippet) => snippet, + Err(e) => { + warn!(error = ?e, "Invalid span {:?}", sp); + return true; + } + }; + found != suggested +} + /// Whether the original and suggested code are visually similar enough to warrant extra wording. pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool { // FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode. diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 09855394cdb2..ceebcd46a6f7 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -50,7 +50,7 @@ pub use diagnostic_impls::{ IndicateAnonymousLifetime, SingleLabelManySpans, }; pub use emitter::ColorConfig; -use emitter::{is_case_difference, DynEmitter, Emitter}; +use emitter::{is_case_difference, is_different, DynEmitter, Emitter}; use registry::Registry; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; @@ -357,10 +357,16 @@ impl CodeSuggestion { _ => 1, }) .sum(); - line_highlight.push(SubstitutionHighlight { - start: (cur_lo.col.0 as isize + acc) as usize, - end: (cur_lo.col.0 as isize + acc + len) as usize, - }); + if !is_different(sm, &part.snippet, part.span) { + // Account for cases where we are suggesting the same code that's already + // there. This shouldn't happen often, but in some cases for multipart + // suggestions it's much easier to handle it here than in the origin. + } else { + line_highlight.push(SubstitutionHighlight { + start: (cur_lo.col.0 as isize + acc) as usize, + end: (cur_lo.col.0 as isize + acc + len) as usize, + }); + } buf.push_str(&part.snippet); let cur_hi = sm.lookup_char_pos(part.span.hi()); // Account for the difference between the width of the current code and the @@ -392,7 +398,11 @@ impl CodeSuggestion { while buf.ends_with('\n') { buf.pop(); } - Some((buf, substitution.parts, highlights, only_capitalization)) + if highlights.iter().all(|parts| parts.is_empty()) { + None + } else { + Some((buf, substitution.parts, highlights, only_capitalization)) + } }) .collect() } diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs index e4e7f7d06e70..080efe983c2a 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs @@ -145,7 +145,9 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { ( "this function's return value is unnecessary".to_string(), "remove the return type...".to_string(), - snippet(cx, fn_decl.output.span(), "..").to_string(), + // FIXME: we should instead get the span including the `->` and suggest an + // empty string for this case. + "()".to_string(), "...and then remove returned values", ) } else { diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr index 15708090361e..37ee9195fce6 100644 --- a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr @@ -63,7 +63,7 @@ LL | let _val = None::<()>.expect("this always happens"); help: remove the `None` and `expect()` | LL | let _val = panic!("this always happens"); - | ~~~~~~~ ~ + | ~~~~~~~ error: used `unwrap_or_default()` on `None` value --> tests/ui/unnecessary_literal_unwrap.rs:22:24 @@ -134,7 +134,7 @@ LL | None::<()>.expect("this always happens"); help: remove the `None` and `expect()` | LL | panic!("this always happens"); - | ~~~~~~~ ~ + | ~~~~~~~ error: used `unwrap_or_default()` on `None` value --> tests/ui/unnecessary_literal_unwrap.rs:30:5 diff --git a/src/tools/clippy/tests/ui/unnecessary_wraps.stderr b/src/tools/clippy/tests/ui/unnecessary_wraps.stderr index a55a23d449f5..59986d895b30 100644 --- a/src/tools/clippy/tests/ui/unnecessary_wraps.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_wraps.stderr @@ -118,8 +118,8 @@ LL | | } | help: remove the return type... | -LL | fn issue_6640_1(a: bool, b: bool) -> Option<()> { - | ~~~~~~~~~~ +LL | fn issue_6640_1(a: bool, b: bool) -> () { + | ~~ help: ...and then remove returned values | LL ~ return ; @@ -145,8 +145,8 @@ LL | | } | help: remove the return type... | -LL | fn issue_6640_2(a: bool, b: bool) -> Result<(), i32> { - | ~~~~~~~~~~~~~~~ +LL | fn issue_6640_2(a: bool, b: bool) -> () { + | ~~ help: ...and then remove returned values | LL ~ return ; diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr index 09b618fb3f05..1c97eaddfe1b 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr @@ -4,10 +4,6 @@ error[E0282]: type annotations needed LL | Combination::<0>.and::<_>().and::<_>(); | ^^^ cannot infer type of the type parameter `M` declared on the method `and` | -help: consider specifying the generic argument - | -LL | Combination::<0>.and::<_>().and::<_>(); - | ~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-55884-2.stderr b/tests/ui/imports/issue-55884-2.stderr index 8a9d5f2a6d8a..0d4f01aeafc6 100644 --- a/tests/ui/imports/issue-55884-2.stderr +++ b/tests/ui/imports/issue-55884-2.stderr @@ -24,10 +24,6 @@ note: ...and refers to the struct `ParseOptions` which is defined here | LL | pub struct ParseOptions {} | ^^^^^^^^^^^^^^^^^^^^^^^ you could import this directly -help: import `ParseOptions` through the re-export - | -LL | pub use parser::ParseOptions; - | ~~~~~~~~~~~~~~~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/lint/wide_pointer_comparisons.stderr b/tests/ui/lint/wide_pointer_comparisons.stderr index 81a221c0ee64..7fe382393d7e 100644 --- a/tests/ui/lint/wide_pointer_comparisons.stderr +++ b/tests/ui/lint/wide_pointer_comparisons.stderr @@ -74,7 +74,7 @@ LL | let _ = PartialEq::eq(&a, &b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(a, b); - | ~~~~~~~~~~~~~~~~~~ ~ ~ + | ~~~~~~~~~~~~~~~~~~ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:35:13 @@ -85,7 +85,7 @@ LL | let _ = PartialEq::ne(&a, &b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(a, b); - | ~~~~~~~~~~~~~~~~~~~ ~ ~ + | ~~~~~~~~~~~~~~~~~~~ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:37:13 @@ -96,7 +96,7 @@ LL | let _ = a.eq(&b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(a, b); - | ++++++++++++++++++ ~ ~ + | ++++++++++++++++++ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:39:13 @@ -107,7 +107,7 @@ LL | let _ = a.ne(&b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(a, b); - | +++++++++++++++++++ ~ ~ + | +++++++++++++++++++ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:41:13 @@ -283,7 +283,7 @@ LL | let _ = PartialEq::eq(a, b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(*a, *b); - | ~~~~~~~~~~~~~~~~~~~ ~~~ ~ + | ~~~~~~~~~~~~~~~~~~~ ~~~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:85:17 @@ -294,7 +294,7 @@ LL | let _ = PartialEq::ne(a, b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(*a, *b); - | ~~~~~~~~~~~~~~~~~~~~ ~~~ ~ + | ~~~~~~~~~~~~~~~~~~~~ ~~~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:87:17 @@ -305,7 +305,7 @@ LL | let _ = PartialEq::eq(&a, &b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(*a, *b); - | ~~~~~~~~~~~~~~~~~~~ ~~~ ~ + | ~~~~~~~~~~~~~~~~~~~ ~~~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:89:17 @@ -316,7 +316,7 @@ LL | let _ = PartialEq::ne(&a, &b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(*a, *b); - | ~~~~~~~~~~~~~~~~~~~~ ~~~ ~ + | ~~~~~~~~~~~~~~~~~~~~ ~~~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:91:17 @@ -327,7 +327,7 @@ LL | let _ = a.eq(b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(*a, *b); - | +++++++++++++++++++ ~~~ ~ + | +++++++++++++++++++ ~~~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:93:17 @@ -338,7 +338,7 @@ LL | let _ = a.ne(b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(*a, *b); - | ++++++++++++++++++++ ~~~ ~ + | ++++++++++++++++++++ ~~~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:95:17 @@ -519,11 +519,11 @@ LL | let _ = PartialEq::eq(&a, &b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(a, b); - | ~~~~~~~~~~~~~~~~~~ ~ ~ + | ~~~~~~~~~~~~~~~~~~ ~ help: use explicit `std::ptr::eq` method to compare metadata and addresses | LL | let _ = std::ptr::eq(a, b); - | ~~~~~~~~~~~~~ ~ ~ + | ~~~~~~~~~~~~~ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:133:17 @@ -534,11 +534,11 @@ LL | let _ = PartialEq::ne(&a, &b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(a, b); - | ~~~~~~~~~~~~~~~~~~~ ~ ~ + | ~~~~~~~~~~~~~~~~~~~ ~ help: use explicit `std::ptr::eq` method to compare metadata and addresses | LL | let _ = !std::ptr::eq(a, b); - | ~~~~~~~~~~~~~~ ~ ~ + | ~~~~~~~~~~~~~~ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:135:17 @@ -549,11 +549,11 @@ LL | let _ = a.eq(&b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(a, b); - | ++++++++++++++++++ ~ ~ + | ++++++++++++++++++ ~ help: use explicit `std::ptr::eq` method to compare metadata and addresses | LL | let _ = std::ptr::eq(a, b); - | +++++++++++++ ~ ~ + | +++++++++++++ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:137:17 @@ -564,11 +564,11 @@ LL | let _ = a.ne(&b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(a, b); - | +++++++++++++++++++ ~ ~ + | +++++++++++++++++++ ~ help: use explicit `std::ptr::eq` method to compare metadata and addresses | LL | let _ = !std::ptr::eq(a, b); - | ++++++++++++++ ~ ~ + | ++++++++++++++ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:142:9 @@ -594,7 +594,7 @@ LL | cmp!(a, b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | cmp!(std::ptr::addr_eq(a, b)); - | ++++++++++++++++++ ~ + + | ++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:159:39 diff --git a/tests/ui/privacy/issue-75907.stderr b/tests/ui/privacy/issue-75907.stderr index f7cb874c2cc0..3121cc04478a 100644 --- a/tests/ui/privacy/issue-75907.stderr +++ b/tests/ui/privacy/issue-75907.stderr @@ -14,7 +14,7 @@ LL | let Bar(x, y, Foo(z)) = make_bar(); help: consider making the fields publicly accessible | LL | pub(crate) struct Bar(pub u8, pub u8, pub Foo); - | ~~~ ~~~ +++ + | ~~~ +++ error[E0532]: cannot match against a tuple struct which contains private fields --> $DIR/issue-75907.rs:15:19 diff --git a/tests/ui/privacy/privacy5.stderr b/tests/ui/privacy/privacy5.stderr index 615b0af2762d..ec3abe9b8162 100644 --- a/tests/ui/privacy/privacy5.stderr +++ b/tests/ui/privacy/privacy5.stderr @@ -53,7 +53,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:56:12 @@ -262,7 +262,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:69:12 @@ -281,7 +281,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:70:12 @@ -300,7 +300,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:71:12 @@ -319,7 +319,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:72:18 @@ -338,7 +338,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:73:18 @@ -357,7 +357,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:74:18 @@ -376,7 +376,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:75:18 @@ -395,7 +395,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:83:17 @@ -452,7 +452,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:90:20 diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr index e01e1edab5aa..6559845c23ec 100644 --- a/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr +++ b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr @@ -17,10 +17,6 @@ error[E0282]: type annotations needed LL | .sum::<_>() | ^^^ cannot infer type of the type parameter `S` declared on the method `sum` | -help: consider specifying the generic argument - | -LL | .sum::<_>() - | ~~~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr index 618ccba0d3d1..dde6060c4334 100644 --- a/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr +++ b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr @@ -40,7 +40,7 @@ LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>(); help: surround the type parameters with angle brackets | LL | let _ = vec![1, 2, 3].into_iter().collect::>(); - | + ~ + | + error: aborting due to 4 previous errors From 41b017ec9945ce6b514e44b8dd26c9d0c0952c9c Mon Sep 17 00:00:00 2001 From: sayantn Date: Thu, 1 Aug 2024 23:13:51 +0530 Subject: [PATCH 26/62] Add the `sha512`, `sm3` and `sm4` target features Add the feature in `core/lib.rs` --- compiler/rustc_codegen_ssa/src/target_features.rs | 1 + compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/target_features.rs | 3 +++ library/core/src/arch.rs | 9 +++++++++ library/core/src/lib.rs | 1 + tests/ui/check-cfg/mix.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- .../ui/feature-gates/feature-gate-sha512_sm_x86.rs | 6 ++++++ .../feature-gates/feature-gate-sha512_sm_x86.stderr | 13 +++++++++++++ 10 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs create mode 100644 tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 77da4e4caea0..b52e6259944d 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -78,6 +78,7 @@ pub fn from_target_feature( Some(sym::loongarch_target_feature) => rust_features.loongarch_target_feature, Some(sym::lahfsahf_target_feature) => rust_features.lahfsahf_target_feature, Some(sym::prfchw_target_feature) => rust_features.prfchw_target_feature, + Some(sym::sha512_sm_x86) => rust_features.sha512_sm_x86, Some(sym::x86_amx_intrinsics) => rust_features.x86_amx_intrinsics, Some(sym::xop_target_feature) => rust_features.xop_target_feature, Some(sym::s390x_target_feature) => rust_features.s390x_target_feature, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 03210085a12c..86102bbecd04 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -591,6 +591,8 @@ declare_features! ( (incomplete, return_type_notation, "1.70.0", Some(109417)), /// Allows `extern "rust-cold"`. (unstable, rust_cold_cc, "1.63.0", Some(97544)), + /// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics + (unstable, sha512_sm_x86, "CURRENT_RUSTC_VERSION", Some(126624)), /// Shortern the tail expression lifetime (unstable, shorter_tail_lifetimes, "1.79.0", Some(123739)), /// Allows the use of SIMD types in functions declared in `extern` blocks. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e8563f50158a..9977fa7425a3 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1705,6 +1705,7 @@ symbols! { self_in_typedefs, self_struct_ctor, semitransparent, + sha512_sm_x86, shadow_call_stack, shl, shl_assign, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 532507cb1824..e52f2fc06df0 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -238,6 +238,9 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("rdseed", Stable), ("rtm", Unstable(sym::rtm_target_feature)), ("sha", Stable), + ("sha512", Unstable(sym::sha512_sm_x86)), + ("sm3", Unstable(sym::sha512_sm_x86)), + ("sm4", Unstable(sym::sha512_sm_x86)), ("sse", Stable), ("sse2", Stable), ("sse3", Stable), diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index 31d6bc36fc8b..d681bd124fe1 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -4,6 +4,15 @@ #[stable(feature = "simd_arch", since = "1.27.0")] pub use crate::core_arch::arch::*; +#[cfg(bootstrap)] +#[allow(dead_code)] +#[unstable(feature = "sha512_sm_x86", issue = "126624")] +fn dummy() { + // AArch64 also has a target feature named `sm4`, so we need `#![feature(sha512_sm_x86)]` in lib.rs + // But as the bootstrap compiler doesn't know about this feature yet, we need to convert it to a + // library feature until bootstrap gets bumped +} + /// Inline assembly. /// /// Refer to [Rust By Example] for a usage guide and the [reference] for diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0917631e0450..9306581dca93 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -260,6 +260,7 @@ #![feature(powerpc_target_feature)] #![feature(riscv_target_feature)] #![feature(rtm_target_feature)] +#![feature(sha512_sm_x86)] #![feature(sse4a_target_feature)] #![feature(tbm_target_feature)] #![feature(wasm_target_feature)] diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 57cbe173c789..520cffc4b026 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 199 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 201 more = note: see for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 00abb5f5e5ca..d780e04e729a 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -165,7 +165,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs new file mode 100644 index 000000000000..176a40ecf537 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs @@ -0,0 +1,6 @@ +//@ only-x86_64 +#[target_feature(enable = "sha512")] +//~^ ERROR: currently unstable +unsafe fn foo() {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr new file mode 100644 index 000000000000..da9eea095a33 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr @@ -0,0 +1,13 @@ +error[E0658]: the target feature `sha512` is currently unstable + --> $DIR/feature-gate-sha512_sm_x86.rs:2:18 + | +LL | #[target_feature(enable = "sha512")] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #126624 for more information + = help: add `#![feature(sha512_sm_x86)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. From b72685bcff449a96fddbc3bc476fbe3551d2314f Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Thu, 1 Aug 2024 23:04:56 +0000 Subject: [PATCH 27/62] rustdoc: Remove dead opaque_tys rendering logic --- src/librustdoc/html/render/mod.rs | 10 ---------- src/librustdoc/html/static/js/main.js | 1 - 2 files changed, 11 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6961261d7128..9617f0d9a1f2 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -332,7 +332,6 @@ struct AllTypes { macros: FxHashSet, functions: FxHashSet, type_aliases: FxHashSet, - opaque_tys: FxHashSet, statics: FxHashSet, constants: FxHashSet, attribute_macros: FxHashSet, @@ -352,7 +351,6 @@ impl AllTypes { macros: new_set(100), functions: new_set(100), type_aliases: new_set(100), - opaque_tys: new_set(100), statics: new_set(100), constants: new_set(100), attribute_macros: new_set(100), @@ -415,9 +413,6 @@ impl AllTypes { if !self.type_aliases.is_empty() { sections.insert(ItemSection::TypeAliases); } - if !self.opaque_tys.is_empty() { - sections.insert(ItemSection::OpaqueTypes); - } if !self.statics.is_empty() { sections.insert(ItemSection::Statics); } @@ -471,7 +466,6 @@ impl AllTypes { print_entries(f, &self.functions, ItemSection::Functions); print_entries(f, &self.type_aliases, ItemSection::TypeAliases); print_entries(f, &self.trait_aliases, ItemSection::TraitAliases); - print_entries(f, &self.opaque_tys, ItemSection::OpaqueTypes); print_entries(f, &self.statics, ItemSection::Statics); print_entries(f, &self.constants, ItemSection::Constants); } @@ -2174,7 +2168,6 @@ pub(crate) enum ItemSection { AssociatedConstants, ForeignTypes, Keywords, - OpaqueTypes, AttributeMacros, DeriveMacros, TraitAliases, @@ -2207,7 +2200,6 @@ impl ItemSection { AssociatedConstants, ForeignTypes, Keywords, - OpaqueTypes, AttributeMacros, DeriveMacros, TraitAliases, @@ -2237,7 +2229,6 @@ impl ItemSection { Self::AssociatedConstants => "associated-consts", Self::ForeignTypes => "foreign-types", Self::Keywords => "keywords", - Self::OpaqueTypes => "opaque-types", Self::AttributeMacros => "attributes", Self::DeriveMacros => "derives", Self::TraitAliases => "trait-aliases", @@ -2267,7 +2258,6 @@ impl ItemSection { Self::AssociatedConstants => "Associated Constants", Self::ForeignTypes => "Foreign Types", Self::Keywords => "Keywords", - Self::OpaqueTypes => "Opaque Types", Self::AttributeMacros => "Attribute Macros", Self::DeriveMacros => "Derive Macros", Self::TraitAliases => "Trait Aliases", diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index e0ea234f9e71..2356ae109bed 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -568,7 +568,6 @@ function preLoadCss(cssUrl) { //block("associatedconstant", "associated-consts", "Associated Constants"); block("foreigntype", "foreign-types", "Foreign Types"); block("keyword", "keywords", "Keywords"); - block("opaque", "opaque-types", "Opaque Types"); block("attr", "attributes", "Attribute Macros"); block("derive", "derives", "Derive Macros"); block("traitalias", "trait-aliases", "Trait Aliases"); From b2f7e71f0b38bbd0c43177802810ed90af58b93f Mon Sep 17 00:00:00 2001 From: Caio Date: Thu, 1 Aug 2024 21:32:12 -0300 Subject: [PATCH 28/62] Dogfood --- library/std/src/lib.rs | 1 + library/std/src/sys/pal/unix/weak.rs | 18 ++---------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6bd9c59a949c..37ba7e7065d4 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -302,6 +302,7 @@ #![feature(let_chains)] #![feature(link_cfg)] #![feature(linkage)] +#![feature(macro_metavar_expr_concat)] #![feature(min_exhaustive_patterns)] #![feature(min_specialization)] #![feature(must_not_suspend)] diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs index b1b6aae757c5..35762f5a53b5 100644 --- a/library/std/src/sys/pal/unix/weak.rs +++ b/library/std/src/sys/pal/unix/weak.rs @@ -168,14 +168,7 @@ pub(crate) macro syscall { if let Some(fun) = $name.get() { fun($($arg_name),*) } else { - // This looks like a hack, but concat_idents only accepts idents - // (not paths). - use libc::*; - - syscall( - concat_idents!(SYS_, $name), - $($arg_name),* - ) as $ret + libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret } } ) @@ -185,14 +178,7 @@ pub(crate) macro syscall { pub(crate) macro raw_syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( unsafe fn $name($($arg_name:$t),*) -> $ret { - // This looks like a hack, but concat_idents only accepts idents - // (not paths). - use libc::*; - - syscall( - concat_idents!(SYS_, $name), - $($arg_name),* - ) as $ret + libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret } ) } From 2f0aaaf2b9fc401708946e60e0f7dabf3c1bf30e Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 1 Aug 2024 20:43:02 -0700 Subject: [PATCH 29/62] std: Remove has_cpuid The one use of it was guaranteed to be always true. --- library/std/src/lib.rs | 4 ---- library/std/src/sys/pal/uefi/time.rs | 8 -------- 2 files changed, 12 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6bd9c59a949c..a760fee42c83 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -269,10 +269,6 @@ #![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))] #![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))] #![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))] -#![cfg_attr( - all(any(target_arch = "x86_64", target_arch = "x86"), target_os = "uefi"), - feature(stdarch_x86_has_cpuid) -)] // // Language features: // tidy-alphabetical-start diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index a97d69f997bf..495ff2dc930e 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -175,10 +175,6 @@ pub(crate) mod instant_internal { #[cfg(target_arch = "x86_64")] fn timestamp_rdtsc() -> Option { - if !crate::arch::x86_64::has_cpuid() { - return None; - } - static FREQUENCY: crate::sync::OnceLock = crate::sync::OnceLock::new(); // Get Frequency in Mhz @@ -200,10 +196,6 @@ pub(crate) mod instant_internal { #[cfg(target_arch = "x86")] fn timestamp_rdtsc() -> Option { - if !crate::arch::x86::has_cpuid() { - return None; - } - static FREQUENCY: crate::sync::OnceLock = crate::sync::OnceLock::new(); let freq = FREQUENCY From 77ca30f1950a062e9eb1caeff790618488058057 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 1 Aug 2024 21:58:34 -0700 Subject: [PATCH 30/62] Implement `UncheckedIterator` directly for `RepeatN` --- library/core/src/iter/sources/repeat_n.rs | 33 +++++++++++++-------- tests/codegen/iter-repeat-n-trivial-drop.rs | 15 +++++++++- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs index 8390dab8e543..4c4ae39f836c 100644 --- a/library/core/src/iter/sources/repeat_n.rs +++ b/library/core/src/iter/sources/repeat_n.rs @@ -114,19 +114,12 @@ impl Iterator for RepeatN { #[inline] fn next(&mut self) -> Option { - if self.count == 0 { - return None; - } - - self.count -= 1; - Some(if self.count == 0 { - // SAFETY: the check above ensured that the count used to be non-zero, - // so element hasn't been dropped yet, and we just lowered the count to - // zero so it won't be dropped later, and thus it's okay to take it here. - unsafe { ManuallyDrop::take(&mut self.element) } + if self.count > 0 { + // SAFETY: Just checked it's not empty + unsafe { Some(self.next_unchecked()) } } else { - A::clone(&self.element) - }) + None + } } #[inline] @@ -194,4 +187,18 @@ impl FusedIterator for RepeatN {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for RepeatN {} #[unstable(feature = "trusted_len_next_unchecked", issue = "37572")] -impl UncheckedIterator for RepeatN {} +impl UncheckedIterator for RepeatN { + #[inline] + unsafe fn next_unchecked(&mut self) -> Self::Item { + // SAFETY: The caller promised the iterator isn't empty + self.count = unsafe { self.count.unchecked_sub(1) }; + if self.count == 0 { + // SAFETY: the check above ensured that the count used to be non-zero, + // so element hasn't been dropped yet, and we just lowered the count to + // zero so it won't be dropped later, and thus it's okay to take it here. + unsafe { ManuallyDrop::take(&mut self.element) } + } else { + A::clone(&self.element) + } + } +} diff --git a/tests/codegen/iter-repeat-n-trivial-drop.rs b/tests/codegen/iter-repeat-n-trivial-drop.rs index 31020b77984b..7de224b92d85 100644 --- a/tests/codegen/iter-repeat-n-trivial-drop.rs +++ b/tests/codegen/iter-repeat-n-trivial-drop.rs @@ -1,8 +1,9 @@ -//@ compile-flags: -O +//@ compile-flags: -C opt-level=3 //@ only-x86_64 #![crate_type = "lib"] #![feature(iter_repeat_n)] +#![feature(array_repeat)] #[derive(Clone)] pub struct NotCopy(u16); @@ -54,3 +55,15 @@ pub fn vec_extend_via_iter_repeat_n() -> Vec { v.extend(std::iter::repeat_n(42_u8, n)); v } + +// Array repeat uses `RepeatN::next_unchecked` internally, +// so also check that the distinction disappears there. + +#[no_mangle] +// CHECK-LABEL: @array_repeat_not_copy +pub unsafe fn array_repeat_not_copy(item: NotCopy) -> [NotCopy; 8] { + // CHECK: insertelement {{.+}} i16 %item + // CHECK: shufflevector <8 x i16> {{.+}} zeroinitializer + // CHECK: store <8 x i16> + std::array::repeat(item) +} From 36527d691e381403c75bc5e30ad1bfd97de2cf12 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 2 Aug 2024 02:12:29 -0700 Subject: [PATCH 31/62] rustfmt: Remove `has_cpuid` from test --- src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs | 9 --------- src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs | 9 --------- 2 files changed, 18 deletions(-) diff --git a/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs index 9257b8a4be63..b9adc67221ae 100644 --- a/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs +++ b/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs @@ -34,15 +34,6 @@ pub fn check_for(x: Feature) -> bool { fn detect_features() -> cache::Initializer { let mut value = cache::Initializer::default(); - // If the x86 CPU does not support the CPUID instruction then it is too - // old to support any of the currently-detectable features. - if !has_cpuid() { - return value; - } - - // Calling `__cpuid`/`__cpuid_count` from here on is safe because the CPU - // has `cpuid` support. - // 0. EAX = 0: Basic Information: // - EAX returns the "Highest Function Parameter", that is, the maximum // leaf value for subsequent calls of `cpuinfo` in range [0, diff --git a/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs index 2e228aa37452..944b51615f8e 100644 --- a/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs +++ b/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs @@ -34,15 +34,6 @@ pub fn check_for(x: Feature) -> bool { fn detect_features() -> cache::Initializer { let mut value = cache::Initializer::default(); - // If the x86 CPU does not support the CPUID instruction then it is too - // old to support any of the currently-detectable features. - if !has_cpuid() { - return value; - } - - // Calling `__cpuid`/`__cpuid_count` from here on is safe because the CPU - // has `cpuid` support. - // 0. EAX = 0: Basic Information: // - EAX returns the "Highest Function Parameter", that is, the maximum // leaf value for subsequent calls of `cpuinfo` in range [0, From 8f641b1b953e04eefc0cede84af169088ebc1401 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 18 Jul 2024 12:10:38 -0400 Subject: [PATCH 32/62] rewrite foreign-double-unwind to rmake --- .../src/external_deps/c_build.rs | 27 ++++++++++++ .../run-make-support/src/external_deps/cc.rs | 38 ++++++++++++++++ .../src/external_deps/rustc.rs | 43 +++++++++++++++++++ src/tools/run-make-support/src/lib.rs | 2 +- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/foreign-double-unwind/Makefile | 12 ------ tests/run-make/foreign-double-unwind/rmake.rs | 21 +++++++++ 7 files changed, 130 insertions(+), 14 deletions(-) delete mode 100644 tests/run-make/foreign-double-unwind/Makefile create mode 100644 tests/run-make/foreign-double-unwind/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/c_build.rs b/src/tools/run-make-support/src/external_deps/c_build.rs index 86c9c0818319..901aede49013 100644 --- a/src/tools/run-make-support/src/external_deps/c_build.rs +++ b/src/tools/run-make-support/src/external_deps/c_build.rs @@ -1,8 +1,13 @@ use std::path::PathBuf; +<<<<<<< HEAD use super::cygpath::get_windows_path; use crate::artifact_names::{dynamic_lib_name, static_lib_name}; use crate::external_deps::cc::cc; +======= +use crate::artifact_names::static_lib_name; +use crate::external_deps::cc::{cc, cxx}; +>>>>>>> e3cf7e53339 (rewrite foreign-double-unwind to rmake) use crate::external_deps::llvm::llvm_ar; use crate::path_helpers::path; use crate::targets::{is_darwin, is_msvc, is_windows}; @@ -10,6 +15,7 @@ use crate::targets::{is_darwin, is_msvc, is_windows}; // FIXME(Oneirical): These native build functions should take a Path-based generic. /// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name. +/// Built from a C file. #[track_caller] pub fn build_native_static_lib(lib_name: &str) -> PathBuf { let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") }; @@ -58,3 +64,24 @@ pub fn build_native_dynamic_lib(lib_name: &str) -> PathBuf { } path(lib_path) } + +/// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name. +/// Built from a C++ file. +#[track_caller] +pub fn build_native_static_lib_cxx(lib_name: &str) -> PathBuf { + let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") }; + let src = format!("{lib_name}.cpp"); + let lib_path = static_lib_name(lib_name); + if is_msvc() { + cxx().arg("-EHs").arg("-c").out_exe(&obj_file).input(src).run(); + } else { + cxx().arg("-c").out_exe(&obj_file).input(src).run(); + }; + let obj_file = if is_msvc() { + PathBuf::from(format!("{lib_name}.obj")) + } else { + PathBuf::from(format!("{lib_name}.o")) + }; + llvm_ar().obj_to_ar().output_input(&lib_path, &obj_file).run(); + path(lib_path) +} diff --git a/src/tools/run-make-support/src/external_deps/cc.rs b/src/tools/run-make-support/src/external_deps/cc.rs index 39ac3efef394..941a43854a09 100644 --- a/src/tools/run-make-support/src/external_deps/cc.rs +++ b/src/tools/run-make-support/src/external_deps/cc.rs @@ -214,3 +214,41 @@ pub fn extra_cxx_flags() -> Vec<&'static str> { } } } + +/// `EXTRARSCXXFLAGS` +pub fn extra_rs_cxx_flags() -> Vec<&'static str> { + // Adapted from tools.mk (trimmed): + // + // ```makefile + // ifdef IS_WINDOWS + // ifdef IS_MSVC + // else + // EXTRARSCXXFLAGS := -lstatic:-bundle=stdc++ + // endif + // else + // ifeq ($(UNAME),Darwin) + // EXTRARSCXXFLAGS := -lc++ + // else + // ifeq ($(UNAME),FreeBSD) + // else + // ifeq ($(UNAME),SunOS) + // else + // ifeq ($(UNAME),OpenBSD) + // else + // EXTRARSCXXFLAGS := -lstdc++ + // endif + // endif + // endif + // endif + // endif + // ``` + if is_windows() { + if is_msvc() { vec![] } else { vec!["-lstatic:-bundle=stdc++"] } + } else { + match &uname()[..] { + "Darwin" => vec!["-lc++"], + "FreeBSD" | "SunOS" | "OpenBSD" => vec![], + _ => vec!["-lstdc++"], + } + } +} diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index 71d28dd9675f..cabfbd59c482 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -5,6 +5,7 @@ use crate::command::Command; use crate::env::env_var; use crate::path_helpers::cwd; use crate::util::set_host_rpath; +use crate::{is_msvc, is_windows, uname}; /// Construct a new `rustc` invocation. This will automatically set the library /// search path as `-L cwd()`. Use [`bare_rustc`] to avoid this. @@ -314,4 +315,46 @@ impl Rustc { self.cmd.arg(format!("-Clinker-flavor={linker_flavor}")); self } + + /// `EXTRARSCXXFLAGS` + pub fn extra_rs_cxx_flags(&mut self) -> &mut Self { + // Adapted from tools.mk (trimmed): + // + // ```makefile + // ifdef IS_WINDOWS + // ifdef IS_MSVC + // else + // EXTRARSCXXFLAGS := -lstatic:-bundle=stdc++ + // endif + // else + // ifeq ($(UNAME),Darwin) + // EXTRARSCXXFLAGS := -lc++ + // else + // ifeq ($(UNAME),FreeBSD) + // else + // ifeq ($(UNAME),SunOS) + // else + // ifeq ($(UNAME),OpenBSD) + // else + // EXTRARSCXXFLAGS := -lstdc++ + // endif + // endif + // endif + // endif + // endif + // ``` + let flag = if is_windows() { + if is_msvc() { None } else { Some("-lstatic:-bundle=stdc++") } + } else { + match &uname()[..] { + "Darwin" => Some("-lc++"), + "FreeBSD" | "SunOS" | "OpenBSD" => None, + _ => Some("-lstdc++"), + } + }; + if let Some(flag) = flag { + self.cmd.arg(flag); + } + self + } } diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 97c6bfe86d2b..63c4c4d88638 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -44,8 +44,8 @@ pub use wasmparser; pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rustdoc}; // These rely on external dependencies. -pub use c_build::{build_native_dynamic_lib, build_native_static_lib}; pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc}; +pub use c_build::{build_native_dynamic_lib, build_native_static_lib, build_native_static_lib_cxx}; pub use clang::{clang, Clang}; pub use htmldocck::htmldocck; pub use llvm::{ diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index a7c8df3e2747..d0824d973062 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -9,7 +9,6 @@ run-make/dep-info-spaces/Makefile run-make/dep-info/Makefile run-make/emit-to-stdout/Makefile run-make/extern-fn-reachable/Makefile -run-make/foreign-double-unwind/Makefile run-make/foreign-exceptions/Makefile run-make/incr-add-rust-src-component/Makefile run-make/issue-36710/Makefile diff --git a/tests/run-make/foreign-double-unwind/Makefile b/tests/run-make/foreign-double-unwind/Makefile deleted file mode 100644 index b5e52808d2fc..000000000000 --- a/tests/run-make/foreign-double-unwind/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# ignore-cross-compile -# needs-unwind -include ../tools.mk - -all: foo - $(call RUN,foo) | $(CGREP) -v unreachable - -foo: foo.rs $(call NATIVE_STATICLIB,foo) - $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) - -$(TMPDIR)/libfoo.o: foo.cpp - $(call COMPILE_OBJ_CXX,$@,$<) diff --git a/tests/run-make/foreign-double-unwind/rmake.rs b/tests/run-make/foreign-double-unwind/rmake.rs new file mode 100644 index 000000000000..b2ac8bfbeadf --- /dev/null +++ b/tests/run-make/foreign-double-unwind/rmake.rs @@ -0,0 +1,21 @@ +// When using foreign function interface (FFI) with C++, it is possible +// to run into a "double unwind" if either both Rust and C++ run into a panic +// and exception at the same time, or C++ encounters two exceptions. In this case, +// one of the panic unwinds would be leaked and the other would be kept, leading +// to undefined behaviour. After this was fixed in #92911, this test checks that +// the keyword "unreachable" indicative of this bug triggering in this specific context +// does not appear after successfully compiling and executing the program. +// See https://github.com/rust-lang/rust/pull/92911 + +//@ needs-unwind +// Reason: this test exercises panic unwinding +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +use run_make_support::{build_native_static_lib_cxx, run, rustc}; + +fn main() { + build_native_static_lib_cxx("foo"); + rustc().input("foo.rs").arg("-lfoo").extra_rs_cxx_flags().run(); + run("foo").assert_stdout_not_contains("unreachable"); +} From 5b44f800f37e0d3093aa5b89c10eb401bbc600eb Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 18 Jul 2024 13:04:45 -0400 Subject: [PATCH 33/62] rewrite and rename issue-36710 to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../foo.cpp | 0 .../foo.rs | 0 .../run-make/cpp-global-destructors/rmake.rs | 27 +++++++++++++++++++ tests/run-make/issue-36710/Makefile | 19 ------------- 5 files changed, 27 insertions(+), 20 deletions(-) rename tests/run-make/{issue-36710 => cpp-global-destructors}/foo.cpp (100%) rename tests/run-make/{issue-36710 => cpp-global-destructors}/foo.rs (100%) create mode 100644 tests/run-make/cpp-global-destructors/rmake.rs delete mode 100644 tests/run-make/issue-36710/Makefile diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index d0824d973062..2d5f7b9ae9e9 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -11,7 +11,6 @@ run-make/emit-to-stdout/Makefile run-make/extern-fn-reachable/Makefile run-make/foreign-exceptions/Makefile run-make/incr-add-rust-src-component/Makefile -run-make/issue-36710/Makefile run-make/issue-84395-lto-embed-bitcode/Makefile run-make/issue-88756-default-output/Makefile run-make/jobserver-error/Makefile diff --git a/tests/run-make/issue-36710/foo.cpp b/tests/run-make/cpp-global-destructors/foo.cpp similarity index 100% rename from tests/run-make/issue-36710/foo.cpp rename to tests/run-make/cpp-global-destructors/foo.cpp diff --git a/tests/run-make/issue-36710/foo.rs b/tests/run-make/cpp-global-destructors/foo.rs similarity index 100% rename from tests/run-make/issue-36710/foo.rs rename to tests/run-make/cpp-global-destructors/foo.rs diff --git a/tests/run-make/cpp-global-destructors/rmake.rs b/tests/run-make/cpp-global-destructors/rmake.rs new file mode 100644 index 000000000000..02928b9de9df --- /dev/null +++ b/tests/run-make/cpp-global-destructors/rmake.rs @@ -0,0 +1,27 @@ +// Some start files were missed when originally writing the logic to swap in musl start files. +// This caused #36710. After the fix in #50105, this test checks that linking to C++ code +// with global destructors works. +// See https://github.com/rust-lang/rust/pull/50105 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +// FIXME(Oneirical): are these really necessary? This test is supposed to test a musl +// bug... and it ignores musl? This wasn't part of the original test at its creation, which +// had no ignores. + +//# ignore-none no-std is not supported +//# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM +//# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM +//# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std` +//# ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain +//# (see dist-i586-gnu-i586-i686-musl Dockerfile) +//# ignore-sgx + +use run_make_support::{build_native_static_lib_cxx, run, rustc}; + +fn main() { + build_native_static_lib_cxx("foo"); + rustc().input("foo.rs").arg("-lfoo").extra_rs_cxx_flags().run(); + run("foo"); +} diff --git a/tests/run-make/issue-36710/Makefile b/tests/run-make/issue-36710/Makefile deleted file mode 100644 index 7b91107a2349..000000000000 --- a/tests/run-make/issue-36710/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# ignore-cross-compile -# ignore-none no-std is not supported -# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM -# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM -# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std` -# ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain -# (see dist-i586-gnu-i586-i686-musl Dockerfile) -# ignore-sgx - -include ../tools.mk - -all: foo - $(call RUN,foo) - -foo: foo.rs $(call NATIVE_STATICLIB,foo) - $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) --target $(TARGET) - -$(TMPDIR)/libfoo.o: foo.cpp - $(call COMPILE_OBJ_CXX,$@,$<) From 46b4083e6fa64445d714fff001ce92907980deb1 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 18 Jul 2024 13:12:38 -0400 Subject: [PATCH 34/62] rewrite foreign-exceptions to rmake --- .../src/external_deps/c_build.rs | 5 --- .../run-make-support/src/external_deps/cc.rs | 38 ------------------- .../src/external_deps/rustc.rs | 20 +++++++++- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../run-make/cpp-global-destructors/rmake.rs | 19 +++++----- tests/run-make/foreign-double-unwind/rmake.rs | 4 +- tests/run-make/foreign-exceptions/Makefile | 12 ------ tests/run-make/foreign-exceptions/rmake.rs | 19 ++++++++++ 8 files changed, 48 insertions(+), 70 deletions(-) delete mode 100644 tests/run-make/foreign-exceptions/Makefile create mode 100644 tests/run-make/foreign-exceptions/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/c_build.rs b/src/tools/run-make-support/src/external_deps/c_build.rs index 901aede49013..15e02d04393c 100644 --- a/src/tools/run-make-support/src/external_deps/c_build.rs +++ b/src/tools/run-make-support/src/external_deps/c_build.rs @@ -1,13 +1,8 @@ use std::path::PathBuf; -<<<<<<< HEAD use super::cygpath::get_windows_path; use crate::artifact_names::{dynamic_lib_name, static_lib_name}; -use crate::external_deps::cc::cc; -======= -use crate::artifact_names::static_lib_name; use crate::external_deps::cc::{cc, cxx}; ->>>>>>> e3cf7e53339 (rewrite foreign-double-unwind to rmake) use crate::external_deps::llvm::llvm_ar; use crate::path_helpers::path; use crate::targets::{is_darwin, is_msvc, is_windows}; diff --git a/src/tools/run-make-support/src/external_deps/cc.rs b/src/tools/run-make-support/src/external_deps/cc.rs index 941a43854a09..39ac3efef394 100644 --- a/src/tools/run-make-support/src/external_deps/cc.rs +++ b/src/tools/run-make-support/src/external_deps/cc.rs @@ -214,41 +214,3 @@ pub fn extra_cxx_flags() -> Vec<&'static str> { } } } - -/// `EXTRARSCXXFLAGS` -pub fn extra_rs_cxx_flags() -> Vec<&'static str> { - // Adapted from tools.mk (trimmed): - // - // ```makefile - // ifdef IS_WINDOWS - // ifdef IS_MSVC - // else - // EXTRARSCXXFLAGS := -lstatic:-bundle=stdc++ - // endif - // else - // ifeq ($(UNAME),Darwin) - // EXTRARSCXXFLAGS := -lc++ - // else - // ifeq ($(UNAME),FreeBSD) - // else - // ifeq ($(UNAME),SunOS) - // else - // ifeq ($(UNAME),OpenBSD) - // else - // EXTRARSCXXFLAGS := -lstdc++ - // endif - // endif - // endif - // endif - // endif - // ``` - if is_windows() { - if is_msvc() { vec![] } else { vec!["-lstatic:-bundle=stdc++"] } - } else { - match &uname()[..] { - "Darwin" => vec!["-lc++"], - "FreeBSD" | "SunOS" | "OpenBSD" => vec![], - _ => vec!["-lstdc++"], - } - } -} diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index cabfbd59c482..cece58d29566 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -5,7 +5,7 @@ use crate::command::Command; use crate::env::env_var; use crate::path_helpers::cwd; use crate::util::set_host_rpath; -use crate::{is_msvc, is_windows, uname}; +use crate::{is_darwin, is_msvc, is_windows, uname}; /// Construct a new `rustc` invocation. This will automatically set the library /// search path as `-L cwd()`. Use [`bare_rustc`] to avoid this. @@ -344,10 +344,26 @@ impl Rustc { // endif // ``` let flag = if is_windows() { + // So this is a bit hacky: we can't use the DLL version of libstdc++ because + // it pulls in the DLL version of libgcc, which means that we end up with 2 + // instances of the DW2 unwinding implementation. This is a problem on + // i686-pc-windows-gnu because each module (DLL/EXE) needs to register its + // unwind information with the unwinding implementation, and libstdc++'s + // __cxa_throw won't see the unwinding info we registered with our statically + // linked libgcc. + // + // Now, simply statically linking libstdc++ would fix this problem, except + // that it is compiled with the expectation that pthreads is dynamically + // linked as a DLL and will fail to link with a statically linked libpthread. + // + // So we end up with the following hack: we link use static:-bundle to only + // link the parts of libstdc++ that we actually use, which doesn't include + // the dependency on the pthreads DLL. if is_msvc() { None } else { Some("-lstatic:-bundle=stdc++") } + } else if is_darwin() { + Some("-lc++") } else { match &uname()[..] { - "Darwin" => Some("-lc++"), "FreeBSD" | "SunOS" | "OpenBSD" => None, _ => Some("-lstdc++"), } diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 2d5f7b9ae9e9..bd4f54d22da7 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -9,7 +9,6 @@ run-make/dep-info-spaces/Makefile run-make/dep-info/Makefile run-make/emit-to-stdout/Makefile run-make/extern-fn-reachable/Makefile -run-make/foreign-exceptions/Makefile run-make/incr-add-rust-src-component/Makefile run-make/issue-84395-lto-embed-bitcode/Makefile run-make/issue-88756-default-output/Makefile diff --git a/tests/run-make/cpp-global-destructors/rmake.rs b/tests/run-make/cpp-global-destructors/rmake.rs index 02928b9de9df..9bc5c84e10db 100644 --- a/tests/run-make/cpp-global-destructors/rmake.rs +++ b/tests/run-make/cpp-global-destructors/rmake.rs @@ -6,17 +6,16 @@ //@ ignore-cross-compile // Reason: the compiled binary is executed -// FIXME(Oneirical): are these really necessary? This test is supposed to test a musl -// bug... and it ignores musl? This wasn't part of the original test at its creation, which -// had no ignores. +//@ ignore-none +// Reason: no-std is not supported. +//@ ignore-wasm32 +//@ ignore-wasm64 +// Reason: compiling C++ to WASM may cause problems. -//# ignore-none no-std is not supported -//# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM -//# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM -//# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std` -//# ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain -//# (see dist-i586-gnu-i586-i686-musl Dockerfile) -//# ignore-sgx +// Neither of these are tested in full CI. +//@ ignore-nvptx64-nvidia-cuda +// Reason: can't find crate "std" +//@ ignore-sgx use run_make_support::{build_native_static_lib_cxx, run, rustc}; diff --git a/tests/run-make/foreign-double-unwind/rmake.rs b/tests/run-make/foreign-double-unwind/rmake.rs index b2ac8bfbeadf..9bd3b4c0fea5 100644 --- a/tests/run-make/foreign-double-unwind/rmake.rs +++ b/tests/run-make/foreign-double-unwind/rmake.rs @@ -12,10 +12,10 @@ //@ ignore-cross-compile // Reason: the compiled binary is executed -use run_make_support::{build_native_static_lib_cxx, run, rustc}; +use run_make_support::{build_native_static_lib_cxx, run_fail, rustc}; fn main() { build_native_static_lib_cxx("foo"); rustc().input("foo.rs").arg("-lfoo").extra_rs_cxx_flags().run(); - run("foo").assert_stdout_not_contains("unreachable"); + run_fail("foo").assert_stdout_not_contains("unreachable"); } diff --git a/tests/run-make/foreign-exceptions/Makefile b/tests/run-make/foreign-exceptions/Makefile deleted file mode 100644 index 56c41b274fb2..000000000000 --- a/tests/run-make/foreign-exceptions/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# ignore-cross-compile -# needs-unwind -include ../tools.mk - -all: foo - $(call RUN,foo) - -foo: foo.rs $(call NATIVE_STATICLIB,foo) - $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) - -$(TMPDIR)/libfoo.o: foo.cpp - $(call COMPILE_OBJ_CXX,$@,$<) diff --git a/tests/run-make/foreign-exceptions/rmake.rs b/tests/run-make/foreign-exceptions/rmake.rs new file mode 100644 index 000000000000..929319f049fe --- /dev/null +++ b/tests/run-make/foreign-exceptions/rmake.rs @@ -0,0 +1,19 @@ +// This test was created to check that compilation and execution still works +// after the addition of a new feature, in #65646: the ability to unwind panics +// and exceptions back and forth between Rust and C++. This is a basic smoke test, +// this feature being broken in quiet or subtle ways could still result in this test +// passing. +// See https://github.com/rust-lang/rust/pull/65646 + +//@ needs-unwind +// Reason: this test exercises panic unwinding +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +use run_make_support::{build_native_static_lib_cxx, run, rustc}; + +fn main() { + build_native_static_lib_cxx("foo"); + rustc().input("foo.rs").arg("-lfoo").extra_rs_cxx_flags().run(); + run("foo"); +} From 6264d2eba9d5b237a5c5c9a9527fbda54d751203 Mon Sep 17 00:00:00 2001 From: binarycat Date: Sat, 27 Jul 2024 15:15:02 -0400 Subject: [PATCH 35/62] bootstrap: fix bug preventing the use of custom targets the bug was caused by two factors: 1. only checking the RUST_TARGET_PATH form, not the full filepath form 2. indirectly trying to use the Debug presentation to get the file path --- src/bootstrap/src/core/config/config.rs | 5 +++++ src/bootstrap/src/core/sanity.rs | 12 +++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 1343e257efe0..776e2c5cb17d 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -512,6 +512,11 @@ impl TargetSelection { pub fn is_windows(&self) -> bool { self.contains("windows") } + + /// Path to the file defining the custom target, if any. + pub fn filepath(&self) -> Option<&Path> { + self.file.as_ref().map(Path::new) + } } impl fmt::Display for TargetSelection { diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 45f4090ef228..c42d4c56c381 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -260,7 +260,9 @@ than building it. if !has_target { // This might also be a custom target, so check the target file that could have been specified by the user. - if let Some(custom_target_path) = env::var_os("RUST_TARGET_PATH") { + if target.filepath().is_some_and(|p| p.exists()) { + has_target = true; + } else if let Some(custom_target_path) = env::var_os("RUST_TARGET_PATH") { let mut target_filename = OsString::from(&target_str); // Target filename ends with `.json`. target_filename.push(".json"); @@ -275,8 +277,12 @@ than building it. if !has_target { panic!( - "No such target exists in the target list, - specify a correct location of the JSON specification file for custom targets!" + "No such target exists in the target list,\n\ + make sure to correctly specify the location \ + of the JSON specification file \ + for custom targets!\n\ + Use BOOTSTRAP_SKIP_TARGET_SANITY=1 to \ + bypass this check." ); } } From c27fa5c3329d4f7fce200043c3117bc1a548f025 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 29 Jul 2024 15:37:45 -0400 Subject: [PATCH 36/62] rewrite rustdoc-default-output to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../run-make/issue-88756-default-output/Makefile | 4 ---- .../issue-88756-default-output/README.md | 1 - tests/run-make/issue-88756-default-output/x.rs | 1 - .../output-default.stdout | 0 tests/run-make/rustdoc-default-output/rmake.rs | 16 ++++++++++++++++ 6 files changed, 16 insertions(+), 7 deletions(-) delete mode 100644 tests/run-make/issue-88756-default-output/Makefile delete mode 100644 tests/run-make/issue-88756-default-output/README.md delete mode 100644 tests/run-make/issue-88756-default-output/x.rs rename tests/run-make/{issue-88756-default-output => rustdoc-default-output}/output-default.stdout (100%) create mode 100644 tests/run-make/rustdoc-default-output/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index dc4db13902da..d8eb5667ab89 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -19,7 +19,6 @@ run-make/issue-36710/Makefile run-make/issue-47551/Makefile run-make/issue-69368/Makefile run-make/issue-84395-lto-embed-bitcode/Makefile -run-make/issue-88756-default-output/Makefile run-make/jobserver-error/Makefile run-make/libs-through-symlinks/Makefile run-make/libtest-json/Makefile diff --git a/tests/run-make/issue-88756-default-output/Makefile b/tests/run-make/issue-88756-default-output/Makefile deleted file mode 100644 index d1c3d0fe0824..000000000000 --- a/tests/run-make/issue-88756-default-output/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -include ../tools.mk - -all: - $(BARE_RUSTDOC) 2>&1 | sed -E 's@/nightly/|/beta/|/stable/|/1\.[0-9]+\.[0-9]+/@/$$CHANNEL/@g' | diff - output-default.stdout diff --git a/tests/run-make/issue-88756-default-output/README.md b/tests/run-make/issue-88756-default-output/README.md deleted file mode 100644 index 8cbfac4f7d2f..000000000000 --- a/tests/run-make/issue-88756-default-output/README.md +++ /dev/null @@ -1 +0,0 @@ -This is a test to verify that the default behavior of `rustdoc` is printing out help output instead of erroring out (#88756). diff --git a/tests/run-make/issue-88756-default-output/x.rs b/tests/run-make/issue-88756-default-output/x.rs deleted file mode 100644 index 5df7576133a6..000000000000 --- a/tests/run-make/issue-88756-default-output/x.rs +++ /dev/null @@ -1 +0,0 @@ -// nothing to see here diff --git a/tests/run-make/issue-88756-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout similarity index 100% rename from tests/run-make/issue-88756-default-output/output-default.stdout rename to tests/run-make/rustdoc-default-output/output-default.stdout diff --git a/tests/run-make/rustdoc-default-output/rmake.rs b/tests/run-make/rustdoc-default-output/rmake.rs new file mode 100644 index 000000000000..06720445a35c --- /dev/null +++ b/tests/run-make/rustdoc-default-output/rmake.rs @@ -0,0 +1,16 @@ +// Calling rustdoc with no arguments, which should bring up a help menu, used to +// cause an error as rustdoc expects an input file. Fixed in #98331, this test +// ensures the output of rustdoc's help menu is as expected. +// See https://github.com/rust-lang/rust/issues/88756 + +use run_make_support::{bare_rustdoc, diff}; + +fn main() { + let out = bare_rustdoc().run().stdout_utf8(); + diff() + .expected_file("output-default.stdout") + .actual_text("actual", out) + // replace the channel type in the URL with $CHANNEL + .normalize(r"nightly/|beta/|stable/|1\.[0-9]+\.[0-9]+/", "$$CHANNEL/") + .run(); +} From c0d9357a4cc2bd41b0f31b997ad6131aaac98d67 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 29 Jul 2024 13:06:06 -0400 Subject: [PATCH 37/62] rewrite cross-lang-lto-clang to rmake --- src/tools/run-make-support/src/command.rs | 7 +++ .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/cross-lang-lto-clang/Makefile | 25 -------- tests/run-make/cross-lang-lto-clang/rmake.rs | 61 +++++++++++++++++++ 4 files changed, 68 insertions(+), 26 deletions(-) delete mode 100644 tests/run-make/cross-lang-lto-clang/Makefile create mode 100644 tests/run-make/cross-lang-lto-clang/rmake.rs diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index a0b96e25a0cb..6582c3c7e8e6 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -258,6 +258,13 @@ impl CompletedProcess { self } + /// Checks that `stderr` does not contain the regex pattern `unexpected`. + #[track_caller] + pub fn assert_stderr_not_contains_regex>(&self, unexpected: S) -> &Self { + assert_not_contains_regex(&self.stdout_utf8(), unexpected); + self + } + #[track_caller] pub fn assert_exit_code(&self, code: i32) -> &Self { assert!(self.output.status.code() == Some(code)); diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index a7c8df3e2747..b04f472e5bf0 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1,7 +1,6 @@ run-make/branch-protection-check-IBT/Makefile run-make/cat-and-grep-sanity-check/Makefile run-make/cdylib-dylib-linkage/Makefile -run-make/cross-lang-lto-clang/Makefile run-make/cross-lang-lto-pgo-smoketest/Makefile run-make/cross-lang-lto-upstream-rlibs/Makefile run-make/dep-info-doesnt-run-much/Makefile diff --git a/tests/run-make/cross-lang-lto-clang/Makefile b/tests/run-make/cross-lang-lto-clang/Makefile deleted file mode 100644 index acf49c8f5c85..000000000000 --- a/tests/run-make/cross-lang-lto-clang/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# needs-force-clang-based-tests - -# This test makes sure that cross-language inlining actually works by checking -# the generated machine code. - -include ../tools.mk - -all: cpp-executable rust-executable - -cpp-executable: - $(RUSTC) -Clinker-plugin-lto=on -o $(TMPDIR)/librustlib-xlto.a -Copt-level=2 -Ccodegen-units=1 ./rustlib.rs - $(CLANG) -flto=thin -fuse-ld=lld -L $(TMPDIR) -lrustlib-xlto -o $(TMPDIR)/cmain ./cmain.c -O3 - # Make sure we don't find a call instruction to the function we expect to - # always be inlined. - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -v -e "call.*rust_always_inlined" - # As a sanity check, make sure we do find a call instruction to a - # non-inlined function - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -e "call.*rust_never_inlined" - -rust-executable: - $(CLANG) ./clib.c -flto=thin -c -o $(TMPDIR)/clib.o -O2 - (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) - $(RUSTC) -Clinker-plugin-lto=on -L$(TMPDIR) -Copt-level=2 -Clinker=$(CLANG) -Clink-arg=-fuse-ld=lld ./main.rs -o $(TMPDIR)/rsmain - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -e "call.*c_never_inlined" - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -v -e "call.*c_always_inlined" diff --git a/tests/run-make/cross-lang-lto-clang/rmake.rs b/tests/run-make/cross-lang-lto-clang/rmake.rs new file mode 100644 index 000000000000..114b2d355793 --- /dev/null +++ b/tests/run-make/cross-lang-lto-clang/rmake.rs @@ -0,0 +1,61 @@ +// This test checks that cross-language inlining actually works by checking +// the generated machine code. +// See https://github.com/rust-lang/rust/pull/57514 + +//@ needs-force-clang-based-tests +// FIXME(#126180): This test doesn't actually run anywhere, because the only +// CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. + +use run_make_support::{clang, env_var, llvm_ar, llvm_objdump, rustc, static_lib_name}; + +fn main() { + rustc() + .linker_plugin_lto("on") + .output(static_lib_name("rustlib-xlto")) + .opt_level("2") + .codegen_units(1) + .input("rustlib.rs") + .run(); + clang() + .lto("thin") + .use_ld("lld") + .arg("-lrustlib-xlto") + .out_exe("cmain") + .input("cmain.c") + .arg("-O3") + .run(); + // Make sure we don't find a call instruction to the function we expect to + // always be inlined. + llvm_objdump() + .arg("-d") + .input("cmain") + .run() + .assert_stdout_not_contains_regex("call.*rust_always_inlined"); + // As a sanity check, make sure we do find a call instruction to a + // non-inlined function + llvm_objdump() + .arg("-d") + .input("cmain") + .run() + .assert_stdout_contains_regex("call.*rust_never_inlined"); + clang().input("clib.c").lto("thin").arg("-c").out_exe("clib.o").arg("-O2").run(); + llvm_ar().obj_to_ar().output_input(static_lib_name("xyz"), "clib.o").run(); + rustc() + .linker_plugin_lto("on") + .opt_level("2") + .linker(&env_var("CLANG")) + .link_arg("-fuse-ld=lld") + .input("main.rs") + .output("rsmain") + .run(); + llvm_objdump() + .arg("-d") + .input("rsmain") + .run() + .assert_stdout_not_contains_regex("call.*c_always_inlined"); + llvm_objdump() + .arg("-d") + .input("rsmain") + .run() + .assert_stdout_contains_regex("call.*c_never_inlined"); +} From 560e86d753b79b0ba63e470aabb84049439b3793 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 29 Jul 2024 14:08:43 -0400 Subject: [PATCH 38/62] rewrite cross-lang-lto-pgo-smoketest to rmake --- .../src/external_deps/clang.rs | 5 +- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/cross-lang-lto-clang/_Makefile | 29 +++++ .../{Makefile => _Makefile} | 4 + .../cross-lang-lto-pgo-smoketest/rmake.rs | 111 ++++++++++++++++++ 5 files changed, 147 insertions(+), 3 deletions(-) create mode 100644 tests/run-make/cross-lang-lto-clang/_Makefile rename tests/run-make/cross-lang-lto-pgo-smoketest/{Makefile => _Makefile} (94%) create mode 100644 tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/clang.rs b/src/tools/run-make-support/src/external_deps/clang.rs index 2b0712541cd5..2d110c6825e0 100644 --- a/src/tools/run-make-support/src/external_deps/clang.rs +++ b/src/tools/run-make-support/src/external_deps/clang.rs @@ -1,7 +1,7 @@ use std::path::Path; use crate::command::Command; -use crate::{bin_name, env_var}; +use crate::{bin_name, cwd, env_var}; /// Construct a new `clang` invocation. `clang` is not always available for all targets. #[track_caller] @@ -23,7 +23,8 @@ impl Clang { #[track_caller] pub fn new() -> Self { let clang = env_var("CLANG"); - let cmd = Command::new(clang); + let mut cmd = Command::new(clang); + cmd.arg("-L").arg(cwd()); Self { cmd } } diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index b04f472e5bf0..46fe73ee5ae4 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1,7 +1,6 @@ run-make/branch-protection-check-IBT/Makefile run-make/cat-and-grep-sanity-check/Makefile run-make/cdylib-dylib-linkage/Makefile -run-make/cross-lang-lto-pgo-smoketest/Makefile run-make/cross-lang-lto-upstream-rlibs/Makefile run-make/dep-info-doesnt-run-much/Makefile run-make/dep-info-spaces/Makefile diff --git a/tests/run-make/cross-lang-lto-clang/_Makefile b/tests/run-make/cross-lang-lto-clang/_Makefile new file mode 100644 index 000000000000..b039328b0f9e --- /dev/null +++ b/tests/run-make/cross-lang-lto-clang/_Makefile @@ -0,0 +1,29 @@ +# FIXME(Oneirical): This is already implemented as an rmake.rs file, but due to #126180, +# the rmake.rs is not ran on CI. Once the rmake test has been proven to work, remove this +# Makefile. + +# needs-force-clang-based-tests + +# This test makes sure that cross-language inlining actually works by checking +# the generated machine code. + +include ../tools.mk + +all: cpp-executable rust-executable + +cpp-executable: + $(RUSTC) -Clinker-plugin-lto=on -o $(TMPDIR)/librustlib-xlto.a -Copt-level=2 -Ccodegen-units=1 ./rustlib.rs + $(CLANG) -flto=thin -fuse-ld=lld -L $(TMPDIR) -lrustlib-xlto -o $(TMPDIR)/cmain ./cmain.c -O3 + # Make sure we don't find a call instruction to the function we expect to + # always be inlined. + "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -v -e "call.*rust_always_inlined" + # As a sanity check, make sure we do find a call instruction to a + # non-inlined function + "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -e "call.*rust_never_inlined" + +rust-executable: + $(CLANG) ./clib.c -flto=thin -c -o $(TMPDIR)/clib.o -O2 + (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) + $(RUSTC) -Clinker-plugin-lto=on -L$(TMPDIR) -Copt-level=2 -Clinker=$(CLANG) -Clink-arg=-fuse-ld=lld ./main.rs -o $(TMPDIR)/rsmain + "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -e "call.*c_never_inlined" + "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -v -e "call.*c_always_inlined" diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/Makefile b/tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile similarity index 94% rename from tests/run-make/cross-lang-lto-pgo-smoketest/Makefile rename to tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile index 738e23f9c661..737f066b4da0 100644 --- a/tests/run-make/cross-lang-lto-pgo-smoketest/Makefile +++ b/tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile @@ -1,3 +1,7 @@ +# FIXME(Oneirical): This is already implemented as an rmake.rs file, but due to #126180, +# the rmake.rs is not ran on CI. Once the rmake test has been proven to work, remove this +# Makefile. + # needs-force-clang-based-tests # FIXME(#126180): This test doesn't actually run anywhere, because the only diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs b/tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs new file mode 100644 index 000000000000..e4d8879607fd --- /dev/null +++ b/tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs @@ -0,0 +1,111 @@ +// This test makes sure that cross-language inlining can be used in conjunction +// with profile-guided optimization. The test only tests that the whole workflow +// can be executed without anything crashing. It does not test whether PGO or +// xLTO have any specific effect on the generated code. +// See https://github.com/rust-lang/rust/pull/61036 + +//@ needs-force-clang-based-tests +// FIXME(#126180): This test doesn't actually run anywhere, because the only +// CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. + +//FIXME(Oneirical): There was a strange workaround for MSVC on this test +// which added -C panic=abort to every RUSTC call. It was justified as follows: +// LLVM doesn't support instrumenting binaries that use SEH: +// https://bugs.llvm.org/show_bug.cgi?id=41279 +// Things work fine with -Cpanic=abort though. + +use run_make_support::{ + clang, env_var, has_extension, has_prefix, llvm_ar, llvm_profdata, rfs, run, rustc, + shallow_find_files, static_lib_name, +}; + +fn main() { + rustc() + .linker_plugin_lto("on") + .output(static_lib_name("rustlib-xlto")) + .opt_level("3") + .codegen_units(1) + .input("rustlib.rs") + .arg("-Cprofile-generate=cpp-profdata") + .run(); + clang() + .lto("thin") + .arg("-fprofile-generate=cpp-profdata") + .use_ld("lld") + .arg("-lrustlib-xlto") + .out_exe("cmain") + .input("cmain.c") + .arg("-O3") + .run(); + run("cmain"); + // Postprocess the profiling data so it can be used by the compiler + let profraw_files = shallow_find_files("cpp-profdata", |path| { + has_prefix(path, "default") && has_extension(path, "profraw") + }); + let profraw_file = profraw_files.get(0).unwrap(); + llvm_profdata().merge().output("cpp-profdata/merged.profdata").input(profraw_file).run(); + rustc() + .linker_plugin_lto("on") + .profile_use("cpp-profdata/merged.profdata") + .output(static_lib_name("rustlib-xlto")) + .opt_level("3") + .codegen_units(1) + .input("rustlib.rs") + .run(); + clang() + .lto("thin") + .arg("-fprofile-use=cpp-profdata/merged.profdata") + .use_ld("lld") + .arg("-lrustlib-xlto") + .out_exe("cmain") + .input("cmain.c") + .arg("-O3") + .run(); + + clang() + .input("clib.c") + .arg("-fprofile-generate=rs-profdata") + .lto("thin") + .arg("-c") + .out_exe("clib.o") + .arg("-O3") + .run(); + llvm_ar().obj_to_ar().output_input(static_lib_name("xyz"), "clib.o").run(); + rustc() + .linker_plugin_lto("on") + .opt_level("3") + .codegen_units(1) + .arg("-Cprofile-generate=rs-profdata") + .linker(&env_var("CLANG")) + .link_arg("-fuse-ld=lld") + .input("main.rs") + .output("rsmain") + .run(); + run("rsmain"); + // Postprocess the profiling data so it can be used by the compiler + let profraw_files = shallow_find_files("rs-profdata", |path| { + has_prefix(path, "default") && has_extension(path, "profraw") + }); + let profraw_file = profraw_files.get(0).unwrap(); + llvm_profdata().merge().output("rs-profdata/merged.profdata").input(profraw_file).run(); + clang() + .input("clib.c") + .arg("-fprofile-use=rs-profdata/merged.profdata") + .arg("-c") + .lto("thin") + .out_exe("clib.o") + .arg("-O3") + .run(); + rfs::remove_file(static_lib_name("xyz")); + llvm_ar().obj_to_ar().output_input(static_lib_name("xyz"), "clib.o").run(); + rustc() + .linker_plugin_lto("on") + .opt_level("3") + .codegen_units(1) + .arg("-Cprofile-use=rs-profdata/merged.profdata") + .linker(&env_var("CLANG")) + .link_arg("-fuse-ld=lld") + .input("main.rs") + .output("rsmain") + .run(); +} From 290a260721591338e7acbd207c0c96283b5ec0fb Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 1 Aug 2024 11:51:31 -0400 Subject: [PATCH 39/62] run cross-lang-lto-pgo-smoketest in CI by renaming it --- src/tools/run-make-support/src/command.rs | 7 -- .../src/external_deps/llvm.rs | 6 ++ tests/run-make/cross-lang-lto-clang/_Makefile | 29 ------ tests/run-make/cross-lang-lto-clang/rmake.rs | 13 +-- .../clib.c | 0 .../cmain.c | 0 .../main.rs | 0 .../rmake.rs | 17 +++- .../rustlib.rs | 0 .../cross-lang-lto-pgo-smoketest/_Makefile | 94 ------------------- .../cross-lang-lto-riscv-abi/rmake.rs | 7 +- tests/run-make/wasm-override-linker/rmake.rs | 4 + 12 files changed, 35 insertions(+), 142 deletions(-) delete mode 100644 tests/run-make/cross-lang-lto-clang/_Makefile rename tests/run-make/{cross-lang-lto-pgo-smoketest => cross-lang-lto-pgo-smoketest-clang}/clib.c (100%) rename tests/run-make/{cross-lang-lto-pgo-smoketest => cross-lang-lto-pgo-smoketest-clang}/cmain.c (100%) rename tests/run-make/{cross-lang-lto-pgo-smoketest => cross-lang-lto-pgo-smoketest-clang}/main.rs (100%) rename tests/run-make/{cross-lang-lto-pgo-smoketest => cross-lang-lto-pgo-smoketest-clang}/rmake.rs (85%) rename tests/run-make/{cross-lang-lto-pgo-smoketest => cross-lang-lto-pgo-smoketest-clang}/rustlib.rs (100%) delete mode 100644 tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index 6582c3c7e8e6..a0b96e25a0cb 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -258,13 +258,6 @@ impl CompletedProcess { self } - /// Checks that `stderr` does not contain the regex pattern `unexpected`. - #[track_caller] - pub fn assert_stderr_not_contains_regex>(&self, unexpected: S) -> &Self { - assert_not_contains_regex(&self.stdout_utf8(), unexpected); - self - } - #[track_caller] pub fn assert_exit_code(&self, code: i32) -> &Self { assert!(self.output.status.code() == Some(code)); diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index c06cefa91a92..56021cec269b 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -246,6 +246,12 @@ impl LlvmObjdump { self.cmd.arg(path.as_ref()); self } + + /// Disassemble all executable sections found in the input files. + pub fn disassemble(&mut self) -> &mut Self { + self.cmd.arg("-d"); + self + } } impl LlvmAr { diff --git a/tests/run-make/cross-lang-lto-clang/_Makefile b/tests/run-make/cross-lang-lto-clang/_Makefile deleted file mode 100644 index b039328b0f9e..000000000000 --- a/tests/run-make/cross-lang-lto-clang/_Makefile +++ /dev/null @@ -1,29 +0,0 @@ -# FIXME(Oneirical): This is already implemented as an rmake.rs file, but due to #126180, -# the rmake.rs is not ran on CI. Once the rmake test has been proven to work, remove this -# Makefile. - -# needs-force-clang-based-tests - -# This test makes sure that cross-language inlining actually works by checking -# the generated machine code. - -include ../tools.mk - -all: cpp-executable rust-executable - -cpp-executable: - $(RUSTC) -Clinker-plugin-lto=on -o $(TMPDIR)/librustlib-xlto.a -Copt-level=2 -Ccodegen-units=1 ./rustlib.rs - $(CLANG) -flto=thin -fuse-ld=lld -L $(TMPDIR) -lrustlib-xlto -o $(TMPDIR)/cmain ./cmain.c -O3 - # Make sure we don't find a call instruction to the function we expect to - # always be inlined. - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -v -e "call.*rust_always_inlined" - # As a sanity check, make sure we do find a call instruction to a - # non-inlined function - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -e "call.*rust_never_inlined" - -rust-executable: - $(CLANG) ./clib.c -flto=thin -c -o $(TMPDIR)/clib.o -O2 - (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) - $(RUSTC) -Clinker-plugin-lto=on -L$(TMPDIR) -Copt-level=2 -Clinker=$(CLANG) -Clink-arg=-fuse-ld=lld ./main.rs -o $(TMPDIR)/rsmain - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -e "call.*c_never_inlined" - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -v -e "call.*c_always_inlined" diff --git a/tests/run-make/cross-lang-lto-clang/rmake.rs b/tests/run-make/cross-lang-lto-clang/rmake.rs index 114b2d355793..1b15a54aacb0 100644 --- a/tests/run-make/cross-lang-lto-clang/rmake.rs +++ b/tests/run-make/cross-lang-lto-clang/rmake.rs @@ -3,8 +3,9 @@ // See https://github.com/rust-lang/rust/pull/57514 //@ needs-force-clang-based-tests -// FIXME(#126180): This test doesn't actually run anywhere, because the only -// CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. +// NOTE(#126180): This test only runs on `x86_64-gnu-debug`, because that CI job sets +// RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their +// name. use run_make_support::{clang, env_var, llvm_ar, llvm_objdump, rustc, static_lib_name}; @@ -27,14 +28,14 @@ fn main() { // Make sure we don't find a call instruction to the function we expect to // always be inlined. llvm_objdump() - .arg("-d") + .disassemble() .input("cmain") .run() .assert_stdout_not_contains_regex("call.*rust_always_inlined"); // As a sanity check, make sure we do find a call instruction to a // non-inlined function llvm_objdump() - .arg("-d") + .disassemble() .input("cmain") .run() .assert_stdout_contains_regex("call.*rust_never_inlined"); @@ -49,12 +50,12 @@ fn main() { .output("rsmain") .run(); llvm_objdump() - .arg("-d") + .disassemble() .input("rsmain") .run() .assert_stdout_not_contains_regex("call.*c_always_inlined"); llvm_objdump() - .arg("-d") + .disassemble() .input("rsmain") .run() .assert_stdout_contains_regex("call.*c_never_inlined"); diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/clib.c b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/clib.c similarity index 100% rename from tests/run-make/cross-lang-lto-pgo-smoketest/clib.c rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/clib.c diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/cmain.c b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/cmain.c similarity index 100% rename from tests/run-make/cross-lang-lto-pgo-smoketest/cmain.c rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/cmain.c diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/main.rs b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/main.rs similarity index 100% rename from tests/run-make/cross-lang-lto-pgo-smoketest/main.rs rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/main.rs diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs similarity index 85% rename from tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs index e4d8879607fd..03c9af4bb898 100644 --- a/tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs +++ b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs @@ -5,14 +5,23 @@ // See https://github.com/rust-lang/rust/pull/61036 //@ needs-force-clang-based-tests -// FIXME(#126180): This test doesn't actually run anywhere, because the only -// CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. +// NOTE(#126180): This test would only run on `x86_64-gnu-debug`, because that CI job sets +// RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their +// name. + +//@ needs-profiler-support +// FIXME(Oneirical): Except that due to the reliance on llvm-profdata, this test +// never runs, because `x86_64-gnu-debug` does not have the `profiler_builtins` crate. //FIXME(Oneirical): There was a strange workaround for MSVC on this test // which added -C panic=abort to every RUSTC call. It was justified as follows: -// LLVM doesn't support instrumenting binaries that use SEH: + +// "LLVM doesn't support instrumenting binaries that use SEH: // https://bugs.llvm.org/show_bug.cgi?id=41279 -// Things work fine with -Cpanic=abort though. +// Things work fine with -Cpanic=abort though." + +// This isn't very pertinent, however, as the test does not get run on any +// MSVC platforms. use run_make_support::{ clang, env_var, has_extension, has_prefix, llvm_ar, llvm_profdata, rfs, run, rustc, diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/rustlib.rs b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rustlib.rs similarity index 100% rename from tests/run-make/cross-lang-lto-pgo-smoketest/rustlib.rs rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/rustlib.rs diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile b/tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile deleted file mode 100644 index 737f066b4da0..000000000000 --- a/tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile +++ /dev/null @@ -1,94 +0,0 @@ -# FIXME(Oneirical): This is already implemented as an rmake.rs file, but due to #126180, -# the rmake.rs is not ran on CI. Once the rmake test has been proven to work, remove this -# Makefile. - -# needs-force-clang-based-tests - -# FIXME(#126180): This test doesn't actually run anywhere, because the only -# CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. - -# This test makes sure that cross-language inlining can be used in conjunction -# with profile-guided optimization. The test only tests that the whole workflow -# can be executed without anything crashing. It does not test whether PGO or -# xLTO have any specific effect on the generated code. - -include ../tools.mk - -COMMON_FLAGS=-Copt-level=3 -Ccodegen-units=1 - -# LLVM doesn't support instrumenting binaries that use SEH: -# https://bugs.llvm.org/show_bug.cgi?id=41279 -# -# Things work fine with -Cpanic=abort though. -ifdef IS_MSVC -COMMON_FLAGS+= -Cpanic=abort -endif - -all: cpp-executable rust-executable - -cpp-executable: - $(RUSTC) -Clinker-plugin-lto=on \ - -Cprofile-generate="$(TMPDIR)"/cpp-profdata \ - -o "$(TMPDIR)"/librustlib-xlto.a \ - $(COMMON_FLAGS) \ - ./rustlib.rs - $(CLANG) -flto=thin \ - -fprofile-generate="$(TMPDIR)"/cpp-profdata \ - -fuse-ld=lld \ - -L "$(TMPDIR)" \ - -lrustlib-xlto \ - -o "$(TMPDIR)"/cmain \ - -O3 \ - ./cmain.c - $(TMPDIR)/cmain - # Postprocess the profiling data so it can be used by the compiler - "$(LLVM_BIN_DIR)"/llvm-profdata merge \ - -o "$(TMPDIR)"/cpp-profdata/merged.profdata \ - "$(TMPDIR)"/cpp-profdata/default_*.profraw - $(RUSTC) -Clinker-plugin-lto=on \ - -Cprofile-use="$(TMPDIR)"/cpp-profdata/merged.profdata \ - -o "$(TMPDIR)"/librustlib-xlto.a \ - $(COMMON_FLAGS) \ - ./rustlib.rs - $(CLANG) -flto=thin \ - -fprofile-use="$(TMPDIR)"/cpp-profdata/merged.profdata \ - -fuse-ld=lld \ - -L "$(TMPDIR)" \ - -lrustlib-xlto \ - -o "$(TMPDIR)"/cmain \ - -O3 \ - ./cmain.c - -rust-executable: - exit - $(CLANG) ./clib.c -fprofile-generate="$(TMPDIR)"/rs-profdata -flto=thin -c -o $(TMPDIR)/clib.o -O3 - (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) - $(RUSTC) -Clinker-plugin-lto=on \ - -Cprofile-generate="$(TMPDIR)"/rs-profdata \ - -L$(TMPDIR) \ - $(COMMON_FLAGS) \ - -Clinker=$(CLANG) \ - -Clink-arg=-fuse-ld=lld \ - -o $(TMPDIR)/rsmain \ - ./main.rs - $(TMPDIR)/rsmain - # Postprocess the profiling data so it can be used by the compiler - "$(LLVM_BIN_DIR)"/llvm-profdata merge \ - -o "$(TMPDIR)"/rs-profdata/merged.profdata \ - "$(TMPDIR)"/rs-profdata/default_*.profraw - $(CLANG) ./clib.c \ - -fprofile-use="$(TMPDIR)"/rs-profdata/merged.profdata \ - -flto=thin \ - -c \ - -o $(TMPDIR)/clib.o \ - -O3 - rm "$(TMPDIR)"/libxyz.a - (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) - $(RUSTC) -Clinker-plugin-lto=on \ - -Cprofile-use="$(TMPDIR)"/rs-profdata/merged.profdata \ - -L$(TMPDIR) \ - $(COMMON_FLAGS) \ - -Clinker=$(CLANG) \ - -Clink-arg=-fuse-ld=lld \ - -o $(TMPDIR)/rsmain \ - ./main.rs diff --git a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs index 391759ec5f66..92573353a741 100644 --- a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs +++ b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs @@ -3,8 +3,11 @@ //@ needs-force-clang-based-tests //@ needs-llvm-components riscv -// FIXME(#126180): This test doesn't actually run anywhere, because the only -// CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. +//@ needs-force-clang-based-tests +// FIXME(#126180): This test can only run on `x86_64-gnu-debug`, because that CI job sets +// RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their +// name. +// However, this test does not run at all as its name does not contain "clang". use std::path::PathBuf; use std::process::{Command, Output}; diff --git a/tests/run-make/wasm-override-linker/rmake.rs b/tests/run-make/wasm-override-linker/rmake.rs index 01bc08e99015..b04edc18eef3 100644 --- a/tests/run-make/wasm-override-linker/rmake.rs +++ b/tests/run-make/wasm-override-linker/rmake.rs @@ -2,6 +2,10 @@ // $ RUSTBUILD_FORCE_CLANG_BASED_TESTS=1 ./x.py test tests/run-make/wasm-override-linker/ //@ needs-force-clang-based-tests +// FIXME(#126180): This test can only run on `x86_64-gnu-debug`, because that CI job sets +// RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their +// name. +// However, this test does not run at all as its name does not contain "clang". use run_make_support::{env_var, rustc, target}; From 84e261e5cb47f637b1d94f03fc65b80c8f45add4 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 2 Aug 2024 12:16:52 -0400 Subject: [PATCH 40/62] chore: use shorthand initializer --- compiler/rustc_builtin_macros/src/alloc_error_handler.rs | 2 +- compiler/rustc_query_system/src/query/job.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index 09d892768b46..1df2812e0c88 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -80,7 +80,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span let params = thin_vec![cx.param(span, size, ty_usize.clone()), cx.param(span, align, ty_usize)]; let decl = cx.fn_decl(params, never); let header = FnHeader { safety: Safety::Unsafe(span), ..FnHeader::default() }; - let sig = FnSig { decl, header, span: span }; + let sig = FnSig { decl, header, span }; let body = Some(cx.block_expr(call)); let kind = ItemKind::Fn(Box::new(Fn { diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 761d6acdbaeb..ca3efc11201e 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -588,7 +588,7 @@ pub fn report_cycle<'a>( cycle_stack, stack_bottom: stack[0].query.description.to_owned(), alias, - cycle_usage: cycle_usage, + cycle_usage, stack_count, note_span: (), }; From 05111c90beecb35f58d0e7e335b0994bc08e8534 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 2 Aug 2024 20:36:03 -0400 Subject: [PATCH 41/62] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 257b72b8adfb..fa646583675d 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 257b72b8adfb1f2aa9916cefca67285c21666276 +Subproject commit fa646583675d7c140482bd906145c71b7fb4fc2b From a798e0f4883997907e6a1ffa484071c0ceb2ba85 Mon Sep 17 00:00:00 2001 From: Konippi Date: Fri, 2 Aug 2024 23:58:05 +0900 Subject: [PATCH 42/62] chore: refactor backtrace style in panic --- library/std/src/panic.rs | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 2ca9256715cd..4c496ade81cd 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -463,11 +463,10 @@ static SHOULD_CAPTURE: AtomicU8 = AtomicU8::new(0); /// environment variable; see the details in [`get_backtrace_style`]. #[unstable(feature = "panic_backtrace_config", issue = "93346")] pub fn set_backtrace_style(style: BacktraceStyle) { - if !cfg!(feature = "backtrace") { - // If the `backtrace` feature of this crate isn't enabled, skip setting. - return; + if cfg!(feature = "backtrace") { + // If the `backtrace` feature of this crate is enabled, set the backtrace style. + SHOULD_CAPTURE.store(style.as_u8(), Ordering::Release); } - SHOULD_CAPTURE.store(style.as_u8(), Ordering::Release); } /// Checks whether the standard library's panic hook will capture and print a @@ -503,21 +502,13 @@ pub fn get_backtrace_style() -> Option { return Some(style); } - let format = crate::env::var_os("RUST_BACKTRACE") - .map(|x| { - if &x == "0" { - BacktraceStyle::Off - } else if &x == "full" { - BacktraceStyle::Full - } else { - BacktraceStyle::Short - } - }) - .unwrap_or(if crate::sys::FULL_BACKTRACE_DEFAULT { - BacktraceStyle::Full - } else { - BacktraceStyle::Off - }); + let format = match crate::env::var_os("RUST_BACKTRACE") { + Some(x) if &x == "0" => BacktraceStyle::Off, + Some(x) if &x == "full" => BacktraceStyle::Full, + Some(_) => BacktraceStyle::Short, + None if crate::sys::FULL_BACKTRACE_DEFAULT => BacktraceStyle::Full, + None => BacktraceStyle::Off, + }; set_backtrace_style(format); Some(format) } From ed010dd32c55c2add60dc4baff837b281cf81be8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 31 Jul 2024 15:56:09 +0000 Subject: [PATCH 43/62] Assert that all attributes are actually checked via `CheckAttrVisitor` and aren't accidentally usable on completely unrelated HIR nodes Co-authored-by: Jieyou Xu --- compiler/rustc_feature/src/builtin_attrs.rs | 8 +-- compiler/rustc_passes/messages.ftl | 4 ++ compiler/rustc_passes/src/check_attr.rs | 66 ++++++++++++++++++++- compiler/rustc_passes/src/errors.rs | 7 +++ 4 files changed, 79 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index ef03a25bc164..72ea55d5999a 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -703,21 +703,21 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::No, allocator_internals, experimental!(needs_allocator), ), gated!( - panic_runtime, Normal, template!(Word), WarnFollowing, + panic_runtime, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No, experimental!(panic_runtime) ), gated!( - needs_panic_runtime, Normal, template!(Word), WarnFollowing, + needs_panic_runtime, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No, experimental!(needs_panic_runtime) ), gated!( - compiler_builtins, Normal, template!(Word), WarnFollowing, + compiler_builtins, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No, "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ which contains compiler-rt intrinsics and will never be stable", ), gated!( - profiler_runtime, Normal, template!(Word), WarnFollowing, + profiler_runtime, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No, "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ which contains the profiler runtime and will never be stable", diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 1747307a1b2c..59c9d1e49f5b 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -100,6 +100,10 @@ passes_continue_labeled_block = .label = labeled blocks cannot be `continue`'d .block_label = labeled block the `continue` points to +passes_coroutine_on_non_closure = + attribute should be applied to closures + .label = not a closure + passes_coverage_not_fn_or_closure = attribute should be applied to a function definition or closure .label = not a function or closure diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 86b18570f376..755f67b3f4fe 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -20,13 +20,13 @@ use rustc_hir::{ TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID, }; use rustc_macros::LintDiagnostic; -use rustc_middle::bug; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS, UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, @@ -239,7 +239,59 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_generic_attr(hir_id, attr, target, Target::Fn); self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } - _ => {} + [sym::coroutine] => { + self.check_coroutine(attr, target); + } + [ + // ok + sym::allow + | sym::expect + | sym::warn + | sym::deny + | sym::forbid + | sym::cfg + // need to be fixed + | sym::cfi_encoding // FIXME(cfi_encoding) + | sym::may_dangle // FIXME(dropck_eyepatch) + | sym::pointee // FIXME(derive_smart_pointer) + | sym::linkage // FIXME(linkage) + | sym::no_sanitize // FIXME(no_sanitize) + | sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section) + | sym::used // handled elsewhere to restrict to static items + | sym::repr // handled elsewhere to restrict to type decls items + | sym::instruction_set // broken on stable!!! + | sym::windows_subsystem // broken on stable!!! + | sym::patchable_function_entry // FIXME(patchable_function_entry) + | sym::deprecated_safe // FIXME(deprecated_safe) + // internal + | sym::prelude_import + | sym::panic_handler + | sym::allow_internal_unsafe + | sym::fundamental + | sym::lang + | sym::needs_allocator + | sym::default_lib_allocator + | sym::start + | sym::custom_mir, + ] => {} + [name, ..] => { + match BUILTIN_ATTRIBUTE_MAP.get(name) { + // checked below + Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) => {} + Some(_) => { + // FIXME: differentiate between unstable and internal attributes just like we do with features instead + // of just accepting `rustc_` attributes by name. That should allow trimming the above list, too. + if !name.as_str().starts_with("rustc_") { + span_bug!( + attr.span, + "builtin attribute {name:?} not handled by `CheckAttrVisitor`" + ) + } + } + None => (), + } + } + [] => unreachable!(), } let builtin = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); @@ -376,6 +428,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Checks that `#[optimize(..)]` is applied to a function/closure/method, /// or to an impl block or module. + // FIXME(#128488): this should probably be elevated to an error? fn check_optimize(&self, hir_id: HirId, attr: &Attribute, target: Target) { match target { Target::Fn @@ -2279,6 +2332,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.abort.set(true); } } + + fn check_coroutine(&self, attr: &Attribute, target: Target) { + match target { + Target::Closure => return, + _ => { + self.dcx().emit_err(errors::CoroutineOnNonClosure { span: attr.span }); + } + } + } } impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index c4f3c8a0d6cf..36dfc40e7628 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -636,6 +636,13 @@ pub struct Confusables { pub attr_span: Span, } +#[derive(Diagnostic)] +#[diag(passes_coroutine_on_non_closure)] +pub struct CoroutineOnNonClosure { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(passes_empty_confusables)] pub(crate) struct EmptyConfusables { From 33cb33441de5086e5daa2d951619c279fc394681 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 1 Aug 2024 10:03:10 +0000 Subject: [PATCH 44/62] Add test for `coroutine` attribute --- tests/ui/coroutine/invalid_attr_usage.rs | 11 +++++++++++ tests/ui/coroutine/invalid_attr_usage.stderr | 14 ++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/ui/coroutine/invalid_attr_usage.rs create mode 100644 tests/ui/coroutine/invalid_attr_usage.stderr diff --git a/tests/ui/coroutine/invalid_attr_usage.rs b/tests/ui/coroutine/invalid_attr_usage.rs new file mode 100644 index 000000000000..995a3aa3100f --- /dev/null +++ b/tests/ui/coroutine/invalid_attr_usage.rs @@ -0,0 +1,11 @@ +//! The `coroutine` attribute is only allowed on closures. + +#![feature(coroutines)] + +#[coroutine] +//~^ ERROR: attribute should be applied to closures +struct Foo; + +#[coroutine] +//~^ ERROR: attribute should be applied to closures +fn main() {} diff --git a/tests/ui/coroutine/invalid_attr_usage.stderr b/tests/ui/coroutine/invalid_attr_usage.stderr new file mode 100644 index 000000000000..316a0117e5d4 --- /dev/null +++ b/tests/ui/coroutine/invalid_attr_usage.stderr @@ -0,0 +1,14 @@ +error: attribute should be applied to closures + --> $DIR/invalid_attr_usage.rs:5:1 + | +LL | #[coroutine] + | ^^^^^^^^^^^^ + +error: attribute should be applied to closures + --> $DIR/invalid_attr_usage.rs:9:1 + | +LL | #[coroutine] + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 8b9d7b1489ddd90a69820b6b4f146a79351e850d Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 4 Jul 2024 12:43:37 +0800 Subject: [PATCH 45/62] Simplify match based on the cast result of `IntToInt`. --- Cargo.lock | 1 + compiler/rustc_mir_transform/Cargo.toml | 1 + .../rustc_mir_transform/src/match_branches.rs | 141 ++-- ...h_i128_u128.MatchBranchSimplification.diff | 61 +- ...atch_i16_i8.MatchBranchSimplification.diff | 37 - ...atch_i8_i16.MatchBranchSimplification.diff | 37 - ..._i16_failed.MatchBranchSimplification.diff | 37 - ...sext_i8_i16.MatchBranchSimplification.diff | 52 ++ ..._i16_failed.MatchBranchSimplification.diff | 47 ++ ...sext_i8_u16.MatchBranchSimplification.diff | 52 ++ ..._u16_failed.MatchBranchSimplification.diff | 47 ++ ...runc_i16_i8.MatchBranchSimplification.diff | 77 ++ ...6_i8_failed.MatchBranchSimplification.diff | 72 ++ ...runc_i16_u8.MatchBranchSimplification.diff | 77 ++ ...6_u8_failed.MatchBranchSimplification.diff | 72 ++ ...runc_u16_i8.MatchBranchSimplification.diff | 67 ++ ...6_i8_failed.MatchBranchSimplification.diff | 62 ++ ...runc_u16_u8.MatchBranchSimplification.diff | 67 ++ ...6_u8_failed.MatchBranchSimplification.diff | 62 ++ ...atch_u8_i16.MatchBranchSimplification.diff | 32 - ...ch_u8_i16_2.MatchBranchSimplification.diff | 26 - ..._i16_failed.MatchBranchSimplification.diff | 32 - ...16_fallback.MatchBranchSimplification.diff | 31 - ...match_u8_i8.MatchBranchSimplification.diff | 47 ++ ...tch_u8_i8_2.MatchBranchSimplification.diff | 80 ++ ...i8_2_failed.MatchBranchSimplification.diff | 74 ++ ...8_i8_failed.MatchBranchSimplification.diff | 42 ++ ...ailed_len_1.MatchBranchSimplification.diff | 42 ++ ...ailed_len_2.MatchBranchSimplification.diff | 42 ++ ...i8_fallback.MatchBranchSimplification.diff | 38 + ...atch_u8_u16.MatchBranchSimplification.diff | 37 - ...ch_u8_u16_2.MatchBranchSimplification.diff | 37 - ...zext_u8_i16.MatchBranchSimplification.diff | 47 ++ ..._i16_failed.MatchBranchSimplification.diff | 42 ++ ...zext_u8_u16.MatchBranchSimplification.diff | 47 ++ ..._u16_failed.MatchBranchSimplification.diff | 42 ++ tests/mir-opt/matches_reduce_branches.rs | 693 ++++++++++++++---- ...stive_match.MatchBranchSimplification.diff | 41 +- ...ve_match_i8.MatchBranchSimplification.diff | 41 +- tests/mir-opt/matches_u8.rs | 1 + 40 files changed, 1994 insertions(+), 589 deletions(-) delete mode 100644 tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff diff --git a/Cargo.lock b/Cargo.lock index 316926e584e2..0b5aa7db3190 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4346,6 +4346,7 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", + "rustc_type_ir", "smallvec", "tracing", ] diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index f864a13a31bb..07ca51a67aef 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -25,6 +25,7 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } +rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index df4f3ccb9b5b..68000fe0ef88 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -3,8 +3,10 @@ use std::iter; use rustc_index::IndexSlice; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; +use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{ParamEnv, ScalarInt, Ty, TyCtxt}; -use rustc_target::abi::Size; +use rustc_target::abi::Integer; +use rustc_type_ir::TyKind::*; use super::simplify::simplify_cfg; @@ -264,33 +266,56 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { } } +/// Check if the cast constant using `IntToInt` is equal to the target constant. +fn can_cast( + tcx: TyCtxt<'_>, + src_val: impl Into, + src_layout: TyAndLayout<'_>, + cast_ty: Ty<'_>, + target_scalar: ScalarInt, +) -> bool { + let from_scalar = ScalarInt::try_from_uint(src_val.into(), src_layout.size).unwrap(); + let v = match src_layout.ty.kind() { + Uint(_) => from_scalar.to_uint(src_layout.size), + Int(_) => from_scalar.to_int(src_layout.size) as u128, + _ => unreachable!("invalid int"), + }; + let size = match *cast_ty.kind() { + Int(t) => Integer::from_int_ty(&tcx, t).size(), + Uint(t) => Integer::from_uint_ty(&tcx, t).size(), + _ => unreachable!("invalid int"), + }; + let v = size.truncate(v); + let cast_scalar = ScalarInt::try_from_uint(v, size).unwrap(); + cast_scalar == target_scalar +} + #[derive(Default)] struct SimplifyToExp { - transfrom_types: Vec, + transfrom_kinds: Vec, } #[derive(Clone, Copy)] -enum CompareType<'tcx, 'a> { +enum ExpectedTransformKind<'tcx, 'a> { /// Identical statements. Same(&'a StatementKind<'tcx>), /// Assignment statements have the same value. - Eq(&'a Place<'tcx>, Ty<'tcx>, ScalarInt), + SameByEq { place: &'a Place<'tcx>, ty: Ty<'tcx>, scalar: ScalarInt }, /// Enum variant comparison type. - Discr { place: &'a Place<'tcx>, ty: Ty<'tcx>, is_signed: bool }, + Cast { place: &'a Place<'tcx>, ty: Ty<'tcx> }, } -enum TransfromType { +enum TransfromKind { Same, - Eq, - Discr, + Cast, } -impl From> for TransfromType { - fn from(compare_type: CompareType<'_, '_>) -> Self { +impl From> for TransfromKind { + fn from(compare_type: ExpectedTransformKind<'_, '_>) -> Self { match compare_type { - CompareType::Same(_) => TransfromType::Same, - CompareType::Eq(_, _, _) => TransfromType::Eq, - CompareType::Discr { .. } => TransfromType::Discr, + ExpectedTransformKind::Same(_) => TransfromKind::Same, + ExpectedTransformKind::SameByEq { .. } => TransfromKind::Same, + ExpectedTransformKind::Cast { .. } => TransfromKind::Cast, } } } @@ -354,7 +379,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { return None; } let mut target_iter = targets.iter(); - let (first_val, first_target) = target_iter.next().unwrap(); + let (first_case_val, first_target) = target_iter.next().unwrap(); let first_terminator_kind = &bbs[first_target].terminator().kind; // Check that destinations are identical, and if not, then don't optimize this block if !targets @@ -364,24 +389,20 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { return None; } - let discr_size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size; + let discr_layout = tcx.layout_of(param_env.and(discr_ty)).unwrap(); let first_stmts = &bbs[first_target].statements; - let (second_val, second_target) = target_iter.next().unwrap(); + let (second_case_val, second_target) = target_iter.next().unwrap(); let second_stmts = &bbs[second_target].statements; if first_stmts.len() != second_stmts.len() { return None; } - fn int_equal(l: ScalarInt, r: impl Into, size: Size) -> bool { - l.to_bits_unchecked() == ScalarInt::try_from_uint(r, size).unwrap().to_bits_unchecked() - } - // We first compare the two branches, and then the other branches need to fulfill the same conditions. - let mut compare_types = Vec::new(); + let mut expected_transform_kinds = Vec::new(); for (f, s) in iter::zip(first_stmts, second_stmts) { let compare_type = match (&f.kind, &s.kind) { // If two statements are exactly the same, we can optimize. - (f_s, s_s) if f_s == s_s => CompareType::Same(f_s), + (f_s, s_s) if f_s == s_s => ExpectedTransformKind::Same(f_s), // If two statements are assignments with the match values to the same place, we can optimize. ( @@ -395,22 +416,29 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { f_c.const_.try_eval_scalar_int(tcx, param_env), s_c.const_.try_eval_scalar_int(tcx, param_env), ) { - (Some(f), Some(s)) if f == s => CompareType::Eq(lhs_f, f_c.const_.ty(), f), - // Enum variants can also be simplified to an assignment statement if their values are equal. - // We need to consider both unsigned and signed scenarios here. + (Some(f), Some(s)) if f == s => ExpectedTransformKind::SameByEq { + place: lhs_f, + ty: f_c.const_.ty(), + scalar: f, + }, + // Enum variants can also be simplified to an assignment statement, + // if we can use `IntToInt` cast to get an equal value. (Some(f), Some(s)) - if ((f_c.const_.ty().is_signed() || discr_ty.is_signed()) - && int_equal(f, first_val, discr_size) - && int_equal(s, second_val, discr_size)) - || (Some(f) == ScalarInt::try_from_uint(first_val, f.size()) - && Some(s) - == ScalarInt::try_from_uint(second_val, s.size())) => + if (can_cast( + tcx, + first_case_val, + discr_layout, + f_c.const_.ty(), + f, + ) && can_cast( + tcx, + second_case_val, + discr_layout, + f_c.const_.ty(), + s, + )) => { - CompareType::Discr { - place: lhs_f, - ty: f_c.const_.ty(), - is_signed: f_c.const_.ty().is_signed() || discr_ty.is_signed(), - } + ExpectedTransformKind::Cast { place: lhs_f, ty: f_c.const_.ty() } } _ => { return None; @@ -421,47 +449,36 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { // Otherwise we cannot optimize. Try another block. _ => return None, }; - compare_types.push(compare_type); + expected_transform_kinds.push(compare_type); } // All remaining BBs need to fulfill the same pattern as the two BBs from the previous step. for (other_val, other_target) in target_iter { let other_stmts = &bbs[other_target].statements; - if compare_types.len() != other_stmts.len() { + if expected_transform_kinds.len() != other_stmts.len() { return None; } - for (f, s) in iter::zip(&compare_types, other_stmts) { + for (f, s) in iter::zip(&expected_transform_kinds, other_stmts) { match (*f, &s.kind) { - (CompareType::Same(f_s), s_s) if f_s == s_s => {} + (ExpectedTransformKind::Same(f_s), s_s) if f_s == s_s => {} ( - CompareType::Eq(lhs_f, f_ty, val), + ExpectedTransformKind::SameByEq { place: lhs_f, ty: f_ty, scalar }, StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), ) if lhs_f == lhs_s && s_c.const_.ty() == f_ty - && s_c.const_.try_eval_scalar_int(tcx, param_env) == Some(val) => {} + && s_c.const_.try_eval_scalar_int(tcx, param_env) == Some(scalar) => {} ( - CompareType::Discr { place: lhs_f, ty: f_ty, is_signed }, + ExpectedTransformKind::Cast { place: lhs_f, ty: f_ty }, StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), - ) if lhs_f == lhs_s && s_c.const_.ty() == f_ty => { - let Some(f) = s_c.const_.try_eval_scalar_int(tcx, param_env) else { - return None; - }; - if is_signed - && s_c.const_.ty().is_signed() - && int_equal(f, other_val, discr_size) - { - continue; - } - if Some(f) == ScalarInt::try_from_uint(other_val, f.size()) { - continue; - } - return None; - } + ) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, param_env) + && lhs_f == lhs_s + && s_c.const_.ty() == f_ty + && can_cast(tcx, other_val, discr_layout, f_ty, f) => {} _ => return None, } } } - self.transfrom_types = compare_types.into_iter().map(|c| c.into()).collect(); + self.transfrom_kinds = expected_transform_kinds.into_iter().map(|c| c.into()).collect(); Some(()) } @@ -479,13 +496,13 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { let (_, first) = targets.iter().next().unwrap(); let first = &bbs[first]; - for (t, s) in iter::zip(&self.transfrom_types, &first.statements) { + for (t, s) in iter::zip(&self.transfrom_kinds, &first.statements) { match (t, &s.kind) { - (TransfromType::Same, _) | (TransfromType::Eq, _) => { + (TransfromKind::Same, _) => { patch.add_statement(parent_end, s.kind.clone()); } ( - TransfromType::Discr, + TransfromKind::Cast, StatementKind::Assign(box (lhs, Rvalue::Use(Operand::Constant(f_c)))), ) => { let operand = Operand::Copy(Place::from(discr_local)); diff --git a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff index dc50ae954725..fc34ce7125ec 100644 --- a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff @@ -5,37 +5,42 @@ debug i => _1; let mut _0: u128; let mut _2: i128; ++ let mut _3: i128; bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [1: bb5, 2: bb4, 3: bb3, 340282366920938463463374607431768211455: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const core::num::::MAX; - goto -> bb6; - } - - bb3: { - _0 = const 3_u128; - goto -> bb6; - } - - bb4: { - _0 = const 2_u128; - goto -> bb6; - } - - bb5: { - _0 = const 1_u128; - goto -> bb6; - } - - bb6: { +- switchInt(move _2) -> [1: bb5, 2: bb4, 3: bb3, 340282366920938463463374607431768211455: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const core::num::::MAX; +- goto -> bb6; +- } +- +- bb3: { +- _0 = const 3_u128; +- goto -> bb6; +- } +- +- bb4: { +- _0 = const 2_u128; +- goto -> bb6; +- } +- +- bb5: { +- _0 = const 1_u128; +- goto -> bb6; +- } +- +- bb6: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u128 (IntToInt); ++ StorageDead(_3); return; } } diff --git a/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff deleted file mode 100644 index 3514914b8ecb..000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff +++ /dev/null @@ -1,37 +0,0 @@ -- // MIR for `match_i16_i8` before MatchBranchSimplification -+ // MIR for `match_i16_i8` after MatchBranchSimplification - - fn match_i16_i8(_1: EnumAi16) -> i8 { - debug i => _1; - let mut _0: i8; - let mut _2: i16; - - bb0: { - _2 = discriminant(_1); - switchInt(move _2) -> [65535: bb4, 2: bb3, 65533: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const -3_i8; - goto -> bb5; - } - - bb3: { - _0 = const 2_i8; - goto -> bb5; - } - - bb4: { - _0 = const -1_i8; - goto -> bb5; - } - - bb5: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff deleted file mode 100644 index ff4255ec8cc9..000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff +++ /dev/null @@ -1,37 +0,0 @@ -- // MIR for `match_i8_i16` before MatchBranchSimplification -+ // MIR for `match_i8_i16` after MatchBranchSimplification - - fn match_i8_i16(_1: EnumAi8) -> i16 { - debug i => _1; - let mut _0: i16; - let mut _2: i8; - - bb0: { - _2 = discriminant(_1); - switchInt(move _2) -> [255: bb4, 2: bb3, 253: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const -3_i16; - goto -> bb5; - } - - bb3: { - _0 = const 2_i16; - goto -> bb5; - } - - bb4: { - _0 = const -1_i16; - goto -> bb5; - } - - bb5: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff deleted file mode 100644 index 022039ecee62..000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff +++ /dev/null @@ -1,37 +0,0 @@ -- // MIR for `match_i8_i16_failed` before MatchBranchSimplification -+ // MIR for `match_i8_i16_failed` after MatchBranchSimplification - - fn match_i8_i16_failed(_1: EnumAi8) -> i16 { - debug i => _1; - let mut _0: i16; - let mut _2: i8; - - bb0: { - _2 = discriminant(_1); - switchInt(move _2) -> [255: bb4, 2: bb3, 253: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 3_i16; - goto -> bb5; - } - - bb3: { - _0 = const 2_i16; - goto -> bb5; - } - - bb4: { - _0 = const -1_i16; - goto -> bb5; - } - - bb5: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff new file mode 100644 index 000000000000..7f8c2ab8d374 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff @@ -0,0 +1,52 @@ +- // MIR for `match_sext_i8_i16` before MatchBranchSimplification ++ // MIR for `match_sext_i8_i16` after MatchBranchSimplification + + fn match_sext_i8_i16(_1: EnumAi8) -> i16 { + debug i => _1; + let mut _0: i16; + let mut _2: i8; ++ let mut _3: i8; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [128: bb6, 255: bb5, 0: bb4, 1: bb3, 127: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 127_i16; +- goto -> bb7; +- } +- +- bb3: { +- _0 = const 1_i16; +- goto -> bb7; +- } +- +- bb4: { +- _0 = const 0_i16; +- goto -> bb7; +- } +- +- bb5: { +- _0 = const -1_i16; +- goto -> bb7; +- } +- +- bb6: { +- _0 = const -128_i16; +- goto -> bb7; +- } +- +- bb7: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i16 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff new file mode 100644 index 000000000000..94ec22932222 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff @@ -0,0 +1,47 @@ +- // MIR for `match_sext_i8_i16_failed` before MatchBranchSimplification ++ // MIR for `match_sext_i8_i16_failed` after MatchBranchSimplification + + fn match_sext_i8_i16_failed(_1: EnumAi8) -> i16 { + debug i => _1; + let mut _0: i16; + let mut _2: i8; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [128: bb6, 255: bb5, 0: bb4, 1: bb3, 127: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 127_i16; + goto -> bb7; + } + + bb3: { + _0 = const 1_i16; + goto -> bb7; + } + + bb4: { + _0 = const 0_i16; + goto -> bb7; + } + + bb5: { + _0 = const 255_i16; + goto -> bb7; + } + + bb6: { + _0 = const -128_i16; + goto -> bb7; + } + + bb7: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff new file mode 100644 index 000000000000..86d0d0ba6cf5 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff @@ -0,0 +1,52 @@ +- // MIR for `match_sext_i8_u16` before MatchBranchSimplification ++ // MIR for `match_sext_i8_u16` after MatchBranchSimplification + + fn match_sext_i8_u16(_1: EnumAi8) -> u16 { + debug i => _1; + let mut _0: u16; + let mut _2: i8; ++ let mut _3: i8; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [128: bb6, 255: bb5, 0: bb4, 1: bb3, 127: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 127_u16; +- goto -> bb7; +- } +- +- bb3: { +- _0 = const 1_u16; +- goto -> bb7; +- } +- +- bb4: { +- _0 = const 0_u16; +- goto -> bb7; +- } +- +- bb5: { +- _0 = const u16::MAX; +- goto -> bb7; +- } +- +- bb6: { +- _0 = const 65408_u16; +- goto -> bb7; +- } +- +- bb7: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u16 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff new file mode 100644 index 000000000000..281f373bf879 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff @@ -0,0 +1,47 @@ +- // MIR for `match_sext_i8_u16_failed` before MatchBranchSimplification ++ // MIR for `match_sext_i8_u16_failed` after MatchBranchSimplification + + fn match_sext_i8_u16_failed(_1: EnumAi8) -> u16 { + debug i => _1; + let mut _0: u16; + let mut _2: i8; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [128: bb6, 255: bb5, 0: bb4, 1: bb3, 127: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 127_u16; + goto -> bb7; + } + + bb3: { + _0 = const 1_u16; + goto -> bb7; + } + + bb4: { + _0 = const 0_u16; + goto -> bb7; + } + + bb5: { + _0 = const 255_u16; + goto -> bb7; + } + + bb6: { + _0 = const 65408_u16; + goto -> bb7; + } + + bb7: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff new file mode 100644 index 000000000000..d3d27be20701 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff @@ -0,0 +1,77 @@ +- // MIR for `match_trunc_i16_i8` before MatchBranchSimplification ++ // MIR for `match_trunc_i16_i8` after MatchBranchSimplification + + fn match_trunc_i16_i8(_1: EnumAi16) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: i16; ++ let mut _3: i16; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [128: bb11, 255: bb10, 0: bb9, 1: bb8, 127: bb7, 65408: bb6, 65535: bb5, 65280: bb4, 65281: bb3, 65407: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const i8::MAX; +- goto -> bb12; +- } +- +- bb3: { +- _0 = const 1_i8; +- goto -> bb12; +- } +- +- bb4: { +- _0 = const 0_i8; +- goto -> bb12; +- } +- +- bb5: { +- _0 = const -1_i8; +- goto -> bb12; +- } +- +- bb6: { +- _0 = const i8::MIN; +- goto -> bb12; +- } +- +- bb7: { +- _0 = const i8::MAX; +- goto -> bb12; +- } +- +- bb8: { +- _0 = const 1_i8; +- goto -> bb12; +- } +- +- bb9: { +- _0 = const 0_i8; +- goto -> bb12; +- } +- +- bb10: { +- _0 = const -1_i8; +- goto -> bb12; +- } +- +- bb11: { +- _0 = const i8::MIN; +- goto -> bb12; +- } +- +- bb12: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i8 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff new file mode 100644 index 000000000000..7f663baefba5 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff @@ -0,0 +1,72 @@ +- // MIR for `match_trunc_i16_i8_failed` before MatchBranchSimplification ++ // MIR for `match_trunc_i16_i8_failed` after MatchBranchSimplification + + fn match_trunc_i16_i8_failed(_1: EnumAi16) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: i16; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [128: bb11, 255: bb10, 0: bb9, 1: bb8, 127: bb7, 65408: bb6, 65535: bb5, 65280: bb4, 65281: bb3, 65407: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const -127_i8; + goto -> bb12; + } + + bb3: { + _0 = const 1_i8; + goto -> bb12; + } + + bb4: { + _0 = const 0_i8; + goto -> bb12; + } + + bb5: { + _0 = const -1_i8; + goto -> bb12; + } + + bb6: { + _0 = const i8::MIN; + goto -> bb12; + } + + bb7: { + _0 = const i8::MAX; + goto -> bb12; + } + + bb8: { + _0 = const 1_i8; + goto -> bb12; + } + + bb9: { + _0 = const 0_i8; + goto -> bb12; + } + + bb10: { + _0 = const -1_i8; + goto -> bb12; + } + + bb11: { + _0 = const i8::MIN; + goto -> bb12; + } + + bb12: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff new file mode 100644 index 000000000000..5fe899148ebc --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff @@ -0,0 +1,77 @@ +- // MIR for `match_trunc_i16_u8` before MatchBranchSimplification ++ // MIR for `match_trunc_i16_u8` after MatchBranchSimplification + + fn match_trunc_i16_u8(_1: EnumAi16) -> u8 { + debug i => _1; + let mut _0: u8; + let mut _2: i16; ++ let mut _3: i16; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [128: bb11, 255: bb10, 0: bb9, 1: bb8, 127: bb7, 65408: bb6, 65535: bb5, 65280: bb4, 65281: bb3, 65407: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 127_u8; +- goto -> bb12; +- } +- +- bb3: { +- _0 = const 1_u8; +- goto -> bb12; +- } +- +- bb4: { +- _0 = const 0_u8; +- goto -> bb12; +- } +- +- bb5: { +- _0 = const u8::MAX; +- goto -> bb12; +- } +- +- bb6: { +- _0 = const 128_u8; +- goto -> bb12; +- } +- +- bb7: { +- _0 = const 127_u8; +- goto -> bb12; +- } +- +- bb8: { +- _0 = const 1_u8; +- goto -> bb12; +- } +- +- bb9: { +- _0 = const 0_u8; +- goto -> bb12; +- } +- +- bb10: { +- _0 = const u8::MAX; +- goto -> bb12; +- } +- +- bb11: { +- _0 = const 128_u8; +- goto -> bb12; +- } +- +- bb12: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u8 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff new file mode 100644 index 000000000000..1c0ffb30c5b5 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff @@ -0,0 +1,72 @@ +- // MIR for `match_trunc_i16_u8_failed` before MatchBranchSimplification ++ // MIR for `match_trunc_i16_u8_failed` after MatchBranchSimplification + + fn match_trunc_i16_u8_failed(_1: EnumAi16) -> u8 { + debug i => _1; + let mut _0: u8; + let mut _2: i16; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [128: bb11, 255: bb10, 0: bb9, 1: bb8, 127: bb7, 65408: bb6, 65535: bb5, 65280: bb4, 65281: bb3, 65407: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const -127_i8 as u8 (IntToInt); + goto -> bb12; + } + + bb3: { + _0 = const 1_u8; + goto -> bb12; + } + + bb4: { + _0 = const 0_u8; + goto -> bb12; + } + + bb5: { + _0 = const u8::MAX; + goto -> bb12; + } + + bb6: { + _0 = const 128_u8; + goto -> bb12; + } + + bb7: { + _0 = const 127_u8; + goto -> bb12; + } + + bb8: { + _0 = const 1_u8; + goto -> bb12; + } + + bb9: { + _0 = const 0_u8; + goto -> bb12; + } + + bb10: { + _0 = const u8::MAX; + goto -> bb12; + } + + bb11: { + _0 = const 128_u8; + goto -> bb12; + } + + bb12: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff new file mode 100644 index 000000000000..85f97a13cac9 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff @@ -0,0 +1,67 @@ +- // MIR for `match_trunc_u16_i8` before MatchBranchSimplification ++ // MIR for `match_trunc_u16_i8` after MatchBranchSimplification + + fn match_trunc_u16_i8(_1: EnumAu16) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: u16; ++ let mut _3: u16; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [0: bb9, 127: bb8, 128: bb7, 255: bb6, 65280: bb5, 65407: bb4, 65408: bb3, 65535: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const -1_i8; +- goto -> bb10; +- } +- +- bb3: { +- _0 = const i8::MIN; +- goto -> bb10; +- } +- +- bb4: { +- _0 = const i8::MAX; +- goto -> bb10; +- } +- +- bb5: { +- _0 = const 0_i8; +- goto -> bb10; +- } +- +- bb6: { +- _0 = const -1_i8; +- goto -> bb10; +- } +- +- bb7: { +- _0 = const i8::MIN; +- goto -> bb10; +- } +- +- bb8: { +- _0 = const i8::MAX; +- goto -> bb10; +- } +- +- bb9: { +- _0 = const 0_i8; +- goto -> bb10; +- } +- +- bb10: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i8 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff new file mode 100644 index 000000000000..cf6c86a71ad9 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff @@ -0,0 +1,62 @@ +- // MIR for `match_trunc_u16_i8_failed` before MatchBranchSimplification ++ // MIR for `match_trunc_u16_i8_failed` after MatchBranchSimplification + + fn match_trunc_u16_i8_failed(_1: EnumAu16) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: u16; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [0: bb9, 127: bb8, 128: bb7, 255: bb6, 65280: bb5, 65407: bb4, 65408: bb3, 65535: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 1_i8; + goto -> bb10; + } + + bb3: { + _0 = const i8::MIN; + goto -> bb10; + } + + bb4: { + _0 = const i8::MAX; + goto -> bb10; + } + + bb5: { + _0 = const 0_i8; + goto -> bb10; + } + + bb6: { + _0 = const -1_i8; + goto -> bb10; + } + + bb7: { + _0 = const i8::MIN; + goto -> bb10; + } + + bb8: { + _0 = const i8::MAX; + goto -> bb10; + } + + bb9: { + _0 = const 0_i8; + goto -> bb10; + } + + bb10: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff new file mode 100644 index 000000000000..768d838eaa6f --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff @@ -0,0 +1,67 @@ +- // MIR for `match_trunc_u16_u8` before MatchBranchSimplification ++ // MIR for `match_trunc_u16_u8` after MatchBranchSimplification + + fn match_trunc_u16_u8(_1: EnumAu16) -> u8 { + debug i => _1; + let mut _0: u8; + let mut _2: u16; ++ let mut _3: u16; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [0: bb9, 127: bb8, 128: bb7, 255: bb6, 65280: bb5, 65407: bb4, 65408: bb3, 65535: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const u8::MAX; +- goto -> bb10; +- } +- +- bb3: { +- _0 = const 128_u8; +- goto -> bb10; +- } +- +- bb4: { +- _0 = const 127_u8; +- goto -> bb10; +- } +- +- bb5: { +- _0 = const 0_u8; +- goto -> bb10; +- } +- +- bb6: { +- _0 = const u8::MAX; +- goto -> bb10; +- } +- +- bb7: { +- _0 = const 128_u8; +- goto -> bb10; +- } +- +- bb8: { +- _0 = const 127_u8; +- goto -> bb10; +- } +- +- bb9: { +- _0 = const 0_u8; +- goto -> bb10; +- } +- +- bb10: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u8 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff new file mode 100644 index 000000000000..109e97bb578a --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff @@ -0,0 +1,62 @@ +- // MIR for `match_trunc_u16_u8_failed` before MatchBranchSimplification ++ // MIR for `match_trunc_u16_u8_failed` after MatchBranchSimplification + + fn match_trunc_u16_u8_failed(_1: EnumAu16) -> u8 { + debug i => _1; + let mut _0: u8; + let mut _2: u16; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [0: bb9, 127: bb8, 128: bb7, 255: bb6, 65280: bb5, 65407: bb4, 65408: bb3, 65535: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 127_u8; + goto -> bb10; + } + + bb3: { + _0 = const 128_u8; + goto -> bb10; + } + + bb4: { + _0 = const 127_u8; + goto -> bb10; + } + + bb5: { + _0 = const 0_u8; + goto -> bb10; + } + + bb6: { + _0 = const u8::MAX; + goto -> bb10; + } + + bb7: { + _0 = const 128_u8; + goto -> bb10; + } + + bb8: { + _0 = const 127_u8; + goto -> bb10; + } + + bb9: { + _0 = const 0_u8; + goto -> bb10; + } + + bb10: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff deleted file mode 100644 index 72ad60956ab7..000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff +++ /dev/null @@ -1,32 +0,0 @@ -- // MIR for `match_u8_i16` before MatchBranchSimplification -+ // MIR for `match_u8_i16` after MatchBranchSimplification - - fn match_u8_i16(_1: EnumAu8) -> i16 { - debug i => _1; - let mut _0: i16; - let mut _2: u8; - - bb0: { - _2 = discriminant(_1); - switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 2_i16; - goto -> bb4; - } - - bb3: { - _0 = const 1_i16; - goto -> bb4; - } - - bb4: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff deleted file mode 100644 index 3333cd765a89..000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff +++ /dev/null @@ -1,26 +0,0 @@ -- // MIR for `match_u8_i16_2` before MatchBranchSimplification -+ // MIR for `match_u8_i16_2` after MatchBranchSimplification - - fn match_u8_i16_2(_1: EnumAu8) -> i16 { - let mut _0: i16; - let mut _2: u8; - - bb0: { - _2 = discriminant(_1); - switchInt(_2) -> [1: bb3, 2: bb1, otherwise: bb2]; - } - - bb1: { - _0 = const 2_i16; - goto -> bb3; - } - - bb2: { - unreachable; - } - - bb3: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff deleted file mode 100644 index 6da19e46dab7..000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff +++ /dev/null @@ -1,32 +0,0 @@ -- // MIR for `match_u8_i16_failed` before MatchBranchSimplification -+ // MIR for `match_u8_i16_failed` after MatchBranchSimplification - - fn match_u8_i16_failed(_1: EnumAu8) -> i16 { - debug i => _1; - let mut _0: i16; - let mut _2: u8; - - bb0: { - _2 = discriminant(_1); - switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 3_i16; - goto -> bb4; - } - - bb3: { - _0 = const 1_i16; - goto -> bb4; - } - - bb4: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff deleted file mode 100644 index 5690f17f24f6..000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff +++ /dev/null @@ -1,31 +0,0 @@ -- // MIR for `match_u8_i16_fallback` before MatchBranchSimplification -+ // MIR for `match_u8_i16_fallback` after MatchBranchSimplification - - fn match_u8_i16_fallback(_1: u8) -> i16 { - debug i => _1; - let mut _0: i16; - - bb0: { - switchInt(_1) -> [1: bb3, 2: bb2, otherwise: bb1]; - } - - bb1: { - _0 = const 3_i16; - goto -> bb4; - } - - bb2: { - _0 = const 2_i16; - goto -> bb4; - } - - bb3: { - _0 = const 1_i16; - goto -> bb4; - } - - bb4: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff new file mode 100644 index 000000000000..d63eed7c019a --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff @@ -0,0 +1,47 @@ +- // MIR for `match_u8_i8` before MatchBranchSimplification ++ // MIR for `match_u8_i8` after MatchBranchSimplification + + fn match_u8_i8(_1: EnumAu8) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: u8; ++ let mut _3: u8; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const -1_i8; +- goto -> bb6; +- } +- +- bb3: { +- _0 = const i8::MIN; +- goto -> bb6; +- } +- +- bb4: { +- _0 = const i8::MAX; +- goto -> bb6; +- } +- +- bb5: { +- _0 = const 0_i8; +- goto -> bb6; +- } +- +- bb6: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i8 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff new file mode 100644 index 000000000000..98dee1835a82 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff @@ -0,0 +1,80 @@ +- // MIR for `match_u8_i8_2` before MatchBranchSimplification ++ // MIR for `match_u8_i8_2` after MatchBranchSimplification + + fn match_u8_i8_2(_1: EnumAu8) -> (i8, i8) { + debug i => _1; + let mut _0: (i8, i8); + let _2: i8; + let _4: (); + let mut _5: u8; + let mut _6: i8; + let mut _7: i8; ++ let mut _8: u8; + scope 1 { + debug a => _2; + let _3: i8; + scope 2 { + debug b => _3; + } + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _5 = discriminant(_1); +- switchInt(move _5) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _2 = const -1_i8; +- _3 = const -1_i8; ++ StorageLive(_8); ++ _8 = move _5; ++ _2 = _8 as i8 (IntToInt); ++ _3 = _8 as i8 (IntToInt); + _4 = (); +- goto -> bb6; +- } +- +- bb3: { +- _2 = const i8::MIN; +- _3 = const i8::MIN; +- _4 = (); +- goto -> bb6; +- } +- +- bb4: { +- _2 = const i8::MAX; +- _3 = const i8::MAX; +- _4 = (); +- goto -> bb6; +- } +- +- bb5: { +- _2 = const 0_i8; +- _3 = const 0_i8; +- _4 = (); +- goto -> bb6; +- } +- +- bb6: { ++ StorageDead(_8); + StorageDead(_4); + StorageLive(_6); + _6 = _2; + StorageLive(_7); + _7 = _3; + _0 = (move _6, move _7); + StorageDead(_7); + StorageDead(_6); + StorageDead(_3); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff new file mode 100644 index 000000000000..901dda586177 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff @@ -0,0 +1,74 @@ +- // MIR for `match_u8_i8_2_failed` before MatchBranchSimplification ++ // MIR for `match_u8_i8_2_failed` after MatchBranchSimplification + + fn match_u8_i8_2_failed(_1: EnumAu8) -> (i8, i8) { + debug i => _1; + let mut _0: (i8, i8); + let _2: i8; + let _4: (); + let mut _5: u8; + let mut _6: i8; + let mut _7: i8; + scope 1 { + debug a => _2; + let _3: i8; + scope 2 { + debug b => _3; + } + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _5 = discriminant(_1); + switchInt(move _5) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _2 = const -1_i8; + _3 = const 1_i8; + _4 = (); + goto -> bb6; + } + + bb3: { + _2 = const i8::MIN; + _3 = const i8::MIN; + _4 = (); + goto -> bb6; + } + + bb4: { + _2 = const i8::MAX; + _3 = const i8::MAX; + _4 = (); + goto -> bb6; + } + + bb5: { + _2 = const 0_i8; + _3 = const 0_i8; + _4 = (); + goto -> bb6; + } + + bb6: { + StorageDead(_4); + StorageLive(_6); + _6 = _2; + StorageLive(_7); + _7 = _3; + _0 = (move _6, move _7); + StorageDead(_7); + StorageDead(_6); + StorageDead(_3); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff new file mode 100644 index 000000000000..ac96be553127 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff @@ -0,0 +1,42 @@ +- // MIR for `match_u8_i8_failed` before MatchBranchSimplification ++ // MIR for `match_u8_i8_failed` after MatchBranchSimplification + + fn match_u8_i8_failed(_1: EnumAu8) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: u8; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 1_i8; + goto -> bb6; + } + + bb3: { + _0 = const i8::MIN; + goto -> bb6; + } + + bb4: { + _0 = const i8::MAX; + goto -> bb6; + } + + bb5: { + _0 = const 0_i8; + goto -> bb6; + } + + bb6: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff new file mode 100644 index 000000000000..9ebf2cf27cbf --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff @@ -0,0 +1,42 @@ +- // MIR for `match_u8_i8_failed_len_1` before MatchBranchSimplification ++ // MIR for `match_u8_i8_failed_len_1` after MatchBranchSimplification + + fn match_u8_i8_failed_len_1(_1: EnumAu8) -> i8 { + let mut _0: i8; + let mut _2: u8; + + bb0: { + _2 = discriminant(_1); + switchInt(_2) -> [0: bb1, 127: bb2, 128: bb3, 255: bb4, otherwise: bb5]; + } + + bb1: { + _0 = const 0_i8; + goto -> bb6; + } + + bb2: { + _0 = const i8::MAX; + _0 = const i8::MAX; + goto -> bb6; + } + + bb3: { + _0 = const i8::MIN; + goto -> bb6; + } + + bb4: { + _0 = const -1_i8; + goto -> bb6; + } + + bb5: { + unreachable; + } + + bb6: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff new file mode 100644 index 000000000000..554856777eb6 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff @@ -0,0 +1,42 @@ +- // MIR for `match_u8_i8_failed_len_2` before MatchBranchSimplification ++ // MIR for `match_u8_i8_failed_len_2` after MatchBranchSimplification + + fn match_u8_i8_failed_len_2(_1: EnumAu8) -> i8 { + let mut _0: i8; + let mut _2: u8; + + bb0: { + _2 = discriminant(_1); + switchInt(_2) -> [0: bb1, 127: bb2, 128: bb3, 255: bb4, otherwise: bb5]; + } + + bb1: { + _0 = const 0_i8; + goto -> bb6; + } + + bb2: { + _0 = const i8::MAX; + goto -> bb6; + } + + bb3: { + _0 = const i8::MIN; + goto -> bb6; + } + + bb4: { + _0 = const -1_i8; + _0 = const -1_i8; + goto -> bb6; + } + + bb5: { + unreachable; + } + + bb6: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff new file mode 100644 index 000000000000..356655021f7f --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff @@ -0,0 +1,38 @@ +- // MIR for `match_u8_i8_fallback` before MatchBranchSimplification ++ // MIR for `match_u8_i8_fallback` after MatchBranchSimplification + + fn match_u8_i8_fallback(_1: EnumAu8) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: u8; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [0: bb4, 127: bb3, 128: bb2, otherwise: bb1]; + } + + bb1: { + _0 = const -1_i8; + goto -> bb5; + } + + bb2: { + _0 = const i8::MIN; + goto -> bb5; + } + + bb3: { + _0 = const i8::MAX; + goto -> bb5; + } + + bb4: { + _0 = const 0_i8; + goto -> bb5; + } + + bb5: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff deleted file mode 100644 index dc9c1c2b97f1..000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff +++ /dev/null @@ -1,37 +0,0 @@ -- // MIR for `match_u8_u16` before MatchBranchSimplification -+ // MIR for `match_u8_u16` after MatchBranchSimplification - - fn match_u8_u16(_1: EnumBu8) -> u16 { - debug i => _1; - let mut _0: u16; - let mut _2: u8; - - bb0: { - _2 = discriminant(_1); - switchInt(move _2) -> [1: bb4, 2: bb3, 5: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 5_u16; - goto -> bb5; - } - - bb3: { - _0 = const 2_u16; - goto -> bb5; - } - - bb4: { - _0 = const 1_u16; - goto -> bb5; - } - - bb5: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff deleted file mode 100644 index b47de6a52b77..000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff +++ /dev/null @@ -1,37 +0,0 @@ -- // MIR for `match_u8_u16_2` before MatchBranchSimplification -+ // MIR for `match_u8_u16_2` after MatchBranchSimplification - - fn match_u8_u16_2(_1: EnumBu8) -> i16 { - let mut _0: i16; - let mut _2: u8; - - bb0: { - _2 = discriminant(_1); - switchInt(_2) -> [1: bb1, 2: bb2, 5: bb3, otherwise: bb4]; - } - - bb1: { - _0 = const 1_i16; - goto -> bb5; - } - - bb2: { - _0 = const 2_i16; - goto -> bb5; - } - - bb3: { - _0 = const 5_i16; - _0 = const 5_i16; - goto -> bb5; - } - - bb4: { - unreachable; - } - - bb5: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff new file mode 100644 index 000000000000..e00a604fe25d --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff @@ -0,0 +1,47 @@ +- // MIR for `match_zext_u8_i16` before MatchBranchSimplification ++ // MIR for `match_zext_u8_i16` after MatchBranchSimplification + + fn match_zext_u8_i16(_1: EnumAu8) -> i16 { + debug i => _1; + let mut _0: i16; + let mut _2: u8; ++ let mut _3: u8; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 255_i16; +- goto -> bb6; +- } +- +- bb3: { +- _0 = const 128_i16; +- goto -> bb6; +- } +- +- bb4: { +- _0 = const 127_i16; +- goto -> bb6; +- } +- +- bb5: { +- _0 = const 0_i16; +- goto -> bb6; +- } +- +- bb6: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i16 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff new file mode 100644 index 000000000000..a19cd796c275 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff @@ -0,0 +1,42 @@ +- // MIR for `match_zext_u8_i16_failed` before MatchBranchSimplification ++ // MIR for `match_zext_u8_i16_failed` after MatchBranchSimplification + + fn match_zext_u8_i16_failed(_1: EnumAu8) -> i16 { + debug i => _1; + let mut _0: i16; + let mut _2: u8; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 255_i16; + goto -> bb6; + } + + bb3: { + _0 = const 128_i16; + goto -> bb6; + } + + bb4: { + _0 = const -127_i16; + goto -> bb6; + } + + bb5: { + _0 = const 0_i16; + goto -> bb6; + } + + bb6: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff new file mode 100644 index 000000000000..befb9118907b --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff @@ -0,0 +1,47 @@ +- // MIR for `match_zext_u8_u16` before MatchBranchSimplification ++ // MIR for `match_zext_u8_u16` after MatchBranchSimplification + + fn match_zext_u8_u16(_1: EnumAu8) -> u16 { + debug i => _1; + let mut _0: u16; + let mut _2: u8; ++ let mut _3: u8; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 255_u16; +- goto -> bb6; +- } +- +- bb3: { +- _0 = const 128_u16; +- goto -> bb6; +- } +- +- bb4: { +- _0 = const 127_u16; +- goto -> bb6; +- } +- +- bb5: { +- _0 = const 0_u16; +- goto -> bb6; +- } +- +- bb6: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u16 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff new file mode 100644 index 000000000000..f781f88449d1 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff @@ -0,0 +1,42 @@ +- // MIR for `match_zext_u8_u16_failed` before MatchBranchSimplification ++ // MIR for `match_zext_u8_u16_failed` after MatchBranchSimplification + + fn match_zext_u8_u16_failed(_1: EnumAu8) -> u16 { + debug i => _1; + let mut _0: u16; + let mut _2: u8; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 255_u16; + goto -> bb6; + } + + bb3: { + _0 = const 128_u16; + goto -> bb6; + } + + bb4: { + _0 = const 65407_u16; + goto -> bb6; + } + + bb5: { + _0 = const 0_u16; + goto -> bb6; + } + + bb6: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.rs b/tests/mir-opt/matches_reduce_branches.rs index 176d68bcd401..9328c616127a 100644 --- a/tests/mir-opt/matches_reduce_branches.rs +++ b/tests/mir-opt/matches_reduce_branches.rs @@ -1,8 +1,10 @@ //@ test-mir-pass: MatchBranchSimplification +//@ compile-flags: -Zunsound-mir-opts #![feature(repr128)] #![feature(core_intrinsics)] #![feature(custom_mir)] +#![allow(non_camel_case_types)] use std::intrinsics::mir::*; @@ -12,6 +14,7 @@ fn foo(bar: Option<()>) { // CHECK: = Eq( // CHECK: switchInt // CHECK-NOT: switchInt + // CHECK: return if matches!(bar, None) { () } @@ -23,6 +26,7 @@ fn bar(i: i32) -> (bool, bool, bool, bool) { // CHECK: = Ne( // CHECK: = Eq( // CHECK-NOT: switchInt + // CHECK: return let a; let b; let c; @@ -52,6 +56,7 @@ fn bar(i: i32) -> (bool, bool, bool, bool) { fn match_nested_if() -> bool { // CHECK-LABEL: fn match_nested_if( // CHECK-NOT: switchInt + // CHECK: return let val = match () { () if if if if true { true } else { false } { true } else { false } { true @@ -66,174 +71,528 @@ fn match_nested_if() -> bool { val } +// # Fold switchInt into IntToInt. +// To simplify writing and checking these test cases, I use the first character of +// each case to distinguish the sign of the number: +// 'u' for unsigned, '_' for negative, and 'o' for non-negative. +// Followed by a decimal number, and add the corresponding radix representation. +// For example, o127_0x7f represents 127i8, and _1_0xff represents -1i8. + +// ## Cast but without numeric conversion. + #[repr(u8)] enum EnumAu8 { - A = 1, - B = 2, -} - -// EMIT_MIR matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff -fn match_u8_i16(i: EnumAu8) -> i16 { - // CHECK-LABEL: fn match_u8_i16( - // CHECK: switchInt - match i { - EnumAu8::A => 1, - EnumAu8::B => 2, - } -} - -// EMIT_MIR matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff -// Check for different instruction lengths -#[custom_mir(dialect = "built")] -fn match_u8_i16_2(i: EnumAu8) -> i16 { - // CHECK-LABEL: fn match_u8_i16_2( - // CHECK: switchInt - mir! { - { - let a = Discriminant(i); - match a { - 1 => bb1, - 2 => bb2, - _ => unreachable_bb, - } - } - bb1 = { - Goto(ret) - } - bb2 = { - RET = 2; - Goto(ret) - } - unreachable_bb = { - Unreachable() - } - ret = { - Return() - } - } -} - -// EMIT_MIR matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff -fn match_u8_i16_failed(i: EnumAu8) -> i16 { - // CHECK-LABEL: fn match_u8_i16_failed( - // CHECK: switchInt - match i { - EnumAu8::A => 1, - EnumAu8::B => 3, - } -} - -// EMIT_MIR matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff -fn match_u8_i16_fallback(i: u8) -> i16 { - // CHECK-LABEL: fn match_u8_i16_fallback( - // CHECK: switchInt - match i { - 1 => 1, - 2 => 2, - _ => 3, - } -} - -#[repr(u8)] -enum EnumBu8 { - A = 1, - B = 2, - C = 5, -} - -// EMIT_MIR matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff -fn match_u8_u16(i: EnumBu8) -> u16 { - // CHECK-LABEL: fn match_u8_u16( - // CHECK: switchInt - match i { - EnumBu8::A => 1, - EnumBu8::B => 2, - EnumBu8::C => 5, - } -} - -// EMIT_MIR matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff -// Check for different instruction lengths -#[custom_mir(dialect = "built")] -fn match_u8_u16_2(i: EnumBu8) -> i16 { - // CHECK-LABEL: fn match_u8_u16_2( - // CHECK: switchInt - mir! { - { - let a = Discriminant(i); - match a { - 1 => bb1, - 2 => bb2, - 5 => bb5, - _ => unreachable_bb, - } - } - bb1 = { - RET = 1; - Goto(ret) - } - bb2 = { - RET = 2; - Goto(ret) - } - bb5 = { - RET = 5; - RET = 5; - Goto(ret) - } - unreachable_bb = { - Unreachable() - } - ret = { - Return() - } - } + u0_0x00 = 0, + u127_0x7f = 127, + u128_0x80 = 128, + u255_0xff = 255, } #[repr(i8)] enum EnumAi8 { - A = -1, - B = 2, - C = -3, + _128_0x80 = -128, + _1_0xff = -1, + o0_0x00 = 0, + o1_0x01 = 1, + o127_0x7f = 127, } -// EMIT_MIR matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff -fn match_i8_i16(i: EnumAi8) -> i16 { - // CHECK-LABEL: fn match_i8_i16( - // CHECK: switchInt +// EMIT_MIR matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff +fn match_u8_i8(i: EnumAu8) -> i8 { + // CHECK-LABEL: fn match_u8_i8( + // CHECK-NOT: switchInt + // CHECK: return match i { - EnumAi8::A => -1, - EnumAi8::B => 2, - EnumAi8::C => -3, + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => 127, + EnumAu8::u128_0x80 => -128, + EnumAu8::u255_0xff => -1, } } -// EMIT_MIR matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff -fn match_i8_i16_failed(i: EnumAi8) -> i16 { - // CHECK-LABEL: fn match_i8_i16_failed( +// EMIT_MIR matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff +fn match_u8_i8_failed(i: EnumAu8) -> i8 { + // CHECK-LABEL: fn match_u8_i8_failed( // CHECK: switchInt + // CHECK: return match i { - EnumAi8::A => -1, - EnumAi8::B => 2, - EnumAi8::C => 3, + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => 127, + EnumAu8::u128_0x80 => -128, + EnumAu8::u255_0xff => 1, // failed } } +// EMIT_MIR matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff +fn match_u8_i8_2(i: EnumAu8) -> (i8, i8) { + // CHECK-LABEL: fn match_u8_i8_2( + // CHECK-NOT: switchInt + // CHECK: IntToInt + // CHECK: IntToInt + // CHECK: return + let a: i8; + let b: i8; + match i { + EnumAu8::u0_0x00 => { + a = 0; + b = 0; + () + } + EnumAu8::u127_0x7f => { + a = 127; + b = 127; + () + } + EnumAu8::u128_0x80 => { + a = -128; + b = -128; + () + } + EnumAu8::u255_0xff => { + a = -1; + b = -1; + () + } + }; + (a, b) +} + +// EMIT_MIR matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff +fn match_u8_i8_2_failed(i: EnumAu8) -> (i8, i8) { + // CHECK-LABEL: fn match_u8_i8_2_failed( + // CHECK: switchInt + // CHECK: return + let a: i8; + let b: i8; + match i { + EnumAu8::u0_0x00 => { + a = 0; + b = 0; + () + } + EnumAu8::u127_0x7f => { + a = 127; + b = 127; + () + } + EnumAu8::u128_0x80 => { + a = -128; + b = -128; + () + } + EnumAu8::u255_0xff => { + a = -1; + b = 1; // failed + () + } + }; + (a, b) +} + +// EMIT_MIR matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff +fn match_u8_i8_fallback(i: EnumAu8) -> i8 { + // CHECK-LABEL: fn match_u8_i8_fallback( + // CHECK: switchInt + // CHECK: return + match i { + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => 127, + EnumAu8::u128_0x80 => -128, + _ => -1, + } +} + +// EMIT_MIR matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff +// Check for different instruction lengths +#[custom_mir(dialect = "built")] +fn match_u8_i8_failed_len_1(i: EnumAu8) -> i8 { + // CHECK-LABEL: fn match_u8_i8_failed_len_1( + // CHECK: switchInt + // CHECK: return + mir! { + { + let a = Discriminant(i); + match a { + 0 => bb1, + 127 => bb2, + 128 => bb3, + 255 => bb4, + _ => unreachable_bb, + } + } + bb1 = { + RET = 0; + Goto(ret) + } + bb2 = { + RET = 127; + RET = 127; + Goto(ret) + } + bb3 = { + RET = -128; + Goto(ret) + } + bb4 = { + RET = -1; + Goto(ret) + } + unreachable_bb = { + Unreachable() + } + ret = { + Return() + } + } +} + +// EMIT_MIR matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff +// Check for different instruction lengths +#[custom_mir(dialect = "built")] +fn match_u8_i8_failed_len_2(i: EnumAu8) -> i8 { + // CHECK-LABEL: fn match_u8_i8_failed_len_2( + // CHECK: switchInt + // CHECK: return + mir! { + { + let a = Discriminant(i); + match a { + 0 => bb1, + 127 => bb2, + 128 => bb3, + 255 => bb4, + _ => unreachable_bb, + } + } + bb1 = { + RET = 0; + Goto(ret) + } + bb2 = { + RET = 127; + Goto(ret) + } + bb3 = { + RET = -128; + Goto(ret) + } + bb4 = { + RET = -1; + RET = -1; + Goto(ret) + } + unreachable_bb = { + Unreachable() + } + ret = { + Return() + } + } +} + +// ## Cast with sext. + +// EMIT_MIR matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff +fn match_sext_i8_i16(i: EnumAi8) -> i16 { + // CHECK-LABEL: fn match_sext_i8_i16( + // CHECK-NOT: switchInt + // CHECK: return + match i { + EnumAi8::_128_0x80 => -128, + EnumAi8::_1_0xff => -1, + EnumAi8::o0_0x00 => 0, + EnumAi8::o1_0x01 => 1, + EnumAi8::o127_0x7f => 127, + } +} + +// EMIT_MIR matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff +// Converting `-1i8` to `255i16` is zext. +fn match_sext_i8_i16_failed(i: EnumAi8) -> i16 { + // CHECK-LABEL: fn match_sext_i8_i16_failed( + // CHECK: switchInt + // CHECK: return + match i { + EnumAi8::_128_0x80 => -128, + EnumAi8::_1_0xff => 255, // failed + EnumAi8::o0_0x00 => 0, + EnumAi8::o1_0x01 => 1, + EnumAi8::o127_0x7f => 127, + } +} + +// EMIT_MIR matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff +fn match_sext_i8_u16(i: EnumAi8) -> u16 { + // CHECK-LABEL: fn match_sext_i8_u16( + // CHECK-NOT: switchInt + // CHECK: return + match i { + EnumAi8::_128_0x80 => 0xff80, + EnumAi8::_1_0xff => 0xffff, + EnumAi8::o0_0x00 => 0, + EnumAi8::o1_0x01 => 1, + EnumAi8::o127_0x7f => 127, + } +} + +// EMIT_MIR matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff +// Converting `-1i8` to `255u16` is zext. +fn match_sext_i8_u16_failed(i: EnumAi8) -> u16 { + // CHECK-LABEL: fn match_sext_i8_u16_failed( + // CHECK: switchInt + // CHECK: return + match i { + EnumAi8::_128_0x80 => 0xff80, + EnumAi8::_1_0xff => 0x00ff, // failed + EnumAi8::o0_0x00 => 0, + EnumAi8::o1_0x01 => 1, + EnumAi8::o127_0x7f => 127, + } +} + +// ## Cast with zext. + +// EMIT_MIR matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff +fn match_zext_u8_u16(i: EnumAu8) -> u16 { + // CHECK-LABEL: fn match_zext_u8_u16( + // CHECK-NOT: switchInt + // CHECK: return + match i { + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => 0x7f, + EnumAu8::u128_0x80 => 128, + EnumAu8::u255_0xff => 255, + } +} + +// EMIT_MIR matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff +fn match_zext_u8_u16_failed(i: EnumAu8) -> u16 { + // CHECK-LABEL: fn match_zext_u8_u16_failed( + // CHECK: switchInt + // CHECK: return + match i { + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => 0xff7f, // failed + EnumAu8::u128_0x80 => 128, + EnumAu8::u255_0xff => 255, + } +} + +// EMIT_MIR matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff +fn match_zext_u8_i16(i: EnumAu8) -> i16 { + // CHECK-LABEL: fn match_zext_u8_i16( + // CHECK-NOT: switchInt + // CHECK: return + match i { + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => 127, + EnumAu8::u128_0x80 => 128, + EnumAu8::u255_0xff => 255, + } +} + +// EMIT_MIR matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff +fn match_zext_u8_i16_failed(i: EnumAu8) -> i16 { + // CHECK-LABEL: fn match_zext_u8_i16_failed( + // CHECK: switchInt + // CHECK: return + match i { + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => -127, // failed + EnumAu8::u128_0x80 => 128, + EnumAu8::u255_0xff => 255, + } +} + +// ## Cast with trunc. + +#[repr(u16)] +enum EnumAu16 { + // 0x00nn + u0_0x0000 = 0, + u127_0x007f = 127, + u128_0x0080 = 128, + u255_0x00ff = 255, + // 0xffnn + u65280_0xff00 = 65280, + u65407_0xff7f = 65407, + u65408_0xff80 = 65408, + u65535_0xffff = 65535, +} + #[repr(i16)] enum EnumAi16 { - A = -1, - B = 2, - C = -3, + // 0x00nn + o128_0x0080 = 128, + o255_0x00ff = 255, + o0_0x0000 = 0, + o1_0x0001 = 1, + o127_0x007f = 127, + // 0xffnn + _128_0xff80 = -128, + _1_0xffff = -1, + o0_0xff00 = -256, + o1_0xff01 = -255, + o127_0xff7f = -129, } -// EMIT_MIR matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff -fn match_i16_i8(i: EnumAi16) -> i8 { - // CHECK-LABEL: fn match_i16_i8( - // CHECK: switchInt +// EMIT_MIR matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff +fn match_trunc_i16_i8(i: EnumAi16) -> i8 { + // CHECK-LABEL: fn match_trunc_i16_i8( + // CHECK-NOT: switchInt + // CHECK: return match i { - EnumAi16::A => -1, - EnumAi16::B => 2, - EnumAi16::C => -3, + // 0x00nn + EnumAi16::o128_0x0080 => -128, + EnumAi16::o255_0x00ff => -1, + EnumAi16::o0_0x0000 => 0, + EnumAi16::o1_0x0001 => 1, + EnumAi16::o127_0x007f => 127, + // 0xffnn + EnumAi16::_128_0xff80 => -128, + EnumAi16::_1_0xffff => -1, + EnumAi16::o0_0xff00 => 0, + EnumAi16::o1_0xff01 => 1, + EnumAi16::o127_0xff7f => 127, + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff +fn match_trunc_i16_i8_failed(i: EnumAi16) -> i8 { + // CHECK-LABEL: fn match_trunc_i16_i8_failed( + // CHECK: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAi16::o128_0x0080 => -128, + EnumAi16::o255_0x00ff => -1, + EnumAi16::o0_0x0000 => 0, + EnumAi16::o1_0x0001 => 1, + EnumAi16::o127_0x007f => 127, + // 0xffnn + EnumAi16::_128_0xff80 => -128, + EnumAi16::_1_0xffff => -1, + EnumAi16::o0_0xff00 => 0, + EnumAi16::o1_0xff01 => 1, + EnumAi16::o127_0xff7f => -127, // failed + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff +fn match_trunc_i16_u8(i: EnumAi16) -> u8 { + // CHECK-LABEL: fn match_trunc_i16_u8( + // CHECK-NOT: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAi16::o128_0x0080 => 128, + EnumAi16::o255_0x00ff => 255, + EnumAi16::o0_0x0000 => 0, + EnumAi16::o1_0x0001 => 1, + EnumAi16::o127_0x007f => 127, + // 0xffnn + EnumAi16::_128_0xff80 => 128, + EnumAi16::_1_0xffff => 255, + EnumAi16::o0_0xff00 => 0, + EnumAi16::o1_0xff01 => 1, + EnumAi16::o127_0xff7f => 127, + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff +fn match_trunc_i16_u8_failed(i: EnumAi16) -> u8 { + // CHECK-LABEL: fn match_trunc_i16_u8_failed( + // CHECK: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAi16::o128_0x0080 => 128, + EnumAi16::o255_0x00ff => 255, + EnumAi16::o0_0x0000 => 0, + EnumAi16::o1_0x0001 => 1, + EnumAi16::o127_0x007f => 127, + // 0xffnn + EnumAi16::_128_0xff80 => 128, + EnumAi16::_1_0xffff => 255, + EnumAi16::o0_0xff00 => 0, + EnumAi16::o1_0xff01 => 1, + EnumAi16::o127_0xff7f => -127i8 as u8, // failed + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff +fn match_trunc_u16_u8(i: EnumAu16) -> u8 { + // CHECK-LABEL: fn match_trunc_u16_u8( + // CHECK-NOT: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAu16::u0_0x0000 => 0, + EnumAu16::u127_0x007f => 127, + EnumAu16::u128_0x0080 => 128, + EnumAu16::u255_0x00ff => 255, + // 0xffnn + EnumAu16::u65280_0xff00 => 0, + EnumAu16::u65407_0xff7f => 127, + EnumAu16::u65408_0xff80 => 128, + EnumAu16::u65535_0xffff => 255, + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff +fn match_trunc_u16_u8_failed(i: EnumAu16) -> u8 { + // CHECK-LABEL: fn match_trunc_u16_u8_failed( + // CHECK: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAu16::u0_0x0000 => 0, + EnumAu16::u127_0x007f => 127, + EnumAu16::u128_0x0080 => 128, + EnumAu16::u255_0x00ff => 255, + // 0xffnn + EnumAu16::u65280_0xff00 => 0, + EnumAu16::u65407_0xff7f => 127, + EnumAu16::u65408_0xff80 => 128, + EnumAu16::u65535_0xffff => 127, // failed + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff +fn match_trunc_u16_i8(i: EnumAu16) -> i8 { + // CHECK-LABEL: fn match_trunc_u16_i8( + // CHECK-NOT: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAu16::u0_0x0000 => 0, + EnumAu16::u127_0x007f => 127, + EnumAu16::u128_0x0080 => -128, + EnumAu16::u255_0x00ff => -1, + // 0xffnn + EnumAu16::u65280_0xff00 => 0, + EnumAu16::u65407_0xff7f => 127, + EnumAu16::u65408_0xff80 => -128, + EnumAu16::u65535_0xffff => -1, + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff +fn match_trunc_u16_i8_failed(i: EnumAu16) -> i8 { + // CHECK-LABEL: fn match_trunc_u16_i8_failed( + // CHECK: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAu16::u0_0x0000 => 0, + EnumAu16::u127_0x007f => 127, + EnumAu16::u128_0x0080 => -128, + EnumAu16::u255_0x00ff => -1, + // 0xffnn + EnumAu16::u65280_0xff00 => 0, + EnumAu16::u65407_0xff7f => 127, + EnumAu16::u65408_0xff80 => -128, + EnumAu16::u65535_0xffff => 1, } } @@ -248,7 +607,8 @@ enum EnumAi128 { // EMIT_MIR matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff fn match_i128_u128(i: EnumAi128) -> u128 { // CHECK-LABEL: fn match_i128_u128( - // CHECK: switchInt + // CHECK-NOT: switchInt + // CHECK: return match i { EnumAi128::A => 1, EnumAi128::B => 2, @@ -262,15 +622,34 @@ fn main() { let _ = foo(Some(())); let _ = bar(0); let _ = match_nested_if(); - let _ = match_u8_i16(EnumAu8::A); - let _ = match_u8_i16_2(EnumAu8::A); - let _ = match_u8_i16_failed(EnumAu8::A); - let _ = match_u8_i16_fallback(1); - let _ = match_u8_u16(EnumBu8::A); - let _ = match_u8_u16_2(EnumBu8::A); - let _ = match_i8_i16(EnumAi8::A); - let _ = match_i8_i16_failed(EnumAi8::A); - let _ = match_i8_i16(EnumAi8::A); - let _ = match_i16_i8(EnumAi16::A); + + let _: i8 = match_u8_i8(EnumAu8::u0_0x00); + let _: i8 = match_u8_i8_failed(EnumAu8::u0_0x00); + let _: (i8, i8) = match_u8_i8_2(EnumAu8::u0_0x00); + let _: (i8, i8) = match_u8_i8_2_failed(EnumAu8::u0_0x00); + let _: i8 = match_u8_i8_fallback(EnumAu8::u0_0x00); + let _: i8 = match_u8_i8_failed_len_1(EnumAu8::u0_0x00); + let _: i8 = match_u8_i8_failed_len_2(EnumAu8::u0_0x00); + + let _: i16 = match_sext_i8_i16(EnumAi8::o0_0x00); + let _: i16 = match_sext_i8_i16_failed(EnumAi8::o0_0x00); + let _: u16 = match_sext_i8_u16(EnumAi8::o0_0x00); + let _: u16 = match_sext_i8_u16_failed(EnumAi8::o0_0x00); + + let _: u16 = match_zext_u8_u16(EnumAu8::u0_0x00); + let _: u16 = match_zext_u8_u16_failed(EnumAu8::u0_0x00); + let _: i16 = match_zext_u8_i16(EnumAu8::u0_0x00); + let _: i16 = match_zext_u8_i16_failed(EnumAu8::u0_0x00); + + let _: i8 = match_trunc_i16_i8(EnumAi16::o0_0x0000); + let _: i8 = match_trunc_i16_i8_failed(EnumAi16::o0_0x0000); + let _: u8 = match_trunc_i16_u8(EnumAi16::o0_0x0000); + let _: u8 = match_trunc_i16_u8_failed(EnumAi16::o0_0x0000); + + let _: i8 = match_trunc_u16_i8(EnumAu16::u0_0x0000); + let _: i8 = match_trunc_u16_i8_failed(EnumAu16::u0_0x0000); + let _: u8 = match_trunc_u16_u8(EnumAu16::u0_0x0000); + let _: u8 = match_trunc_u16_u8_failed(EnumAu16::u0_0x0000); + let _ = match_i128_u128(EnumAi128::A); } diff --git a/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff b/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff index 157f9c98353e..11a18f58e3a1 100644 --- a/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff @@ -5,27 +5,32 @@ debug e => _1; let mut _0: u8; let mut _2: isize; ++ let mut _3: isize; bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 1_u8; - goto -> bb4; - } - - bb3: { - _0 = const 0_u8; - goto -> bb4; - } - - bb4: { +- switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 1_u8; +- goto -> bb4; +- } +- +- bb3: { +- _0 = const 0_u8; +- goto -> bb4; +- } +- +- bb4: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u8 (IntToInt); ++ StorageDead(_3); return; } } diff --git a/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff index 19083771fd95..809badc41ba7 100644 --- a/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff @@ -5,27 +5,32 @@ debug e => _1; let mut _0: i8; let mut _2: isize; ++ let mut _3: isize; bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 1_i8; - goto -> bb4; - } - - bb3: { - _0 = const 0_i8; - goto -> bb4; - } - - bb4: { +- switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 1_i8; +- goto -> bb4; +- } +- +- bb3: { +- _0 = const 0_i8; +- goto -> bb4; +- } +- +- bb4: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i8 (IntToInt); ++ StorageDead(_3); return; } } diff --git a/tests/mir-opt/matches_u8.rs b/tests/mir-opt/matches_u8.rs index 86d646256742..89deead461ee 100644 --- a/tests/mir-opt/matches_u8.rs +++ b/tests/mir-opt/matches_u8.rs @@ -1,5 +1,6 @@ // skip-filecheck //@ test-mir-pass: MatchBranchSimplification +//@ compile-flags: -Zunsound-mir-opts // EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff // EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff From 1f9d9603c05a1fb56825b4fc54ea28aa04485024 Mon Sep 17 00:00:00 2001 From: DianQK Date: Wed, 31 Jul 2024 07:58:39 +0800 Subject: [PATCH 46/62] Re-enable SimplifyToExp in match_branches. --- compiler/rustc_mir_transform/src/match_branches.rs | 5 +---- tests/mir-opt/matches_reduce_branches.rs | 1 - tests/mir-opt/matches_u8.rs | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 68000fe0ef88..47758b56f8c9 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -44,10 +44,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { should_cleanup = true; continue; } - // unsound: https://github.com/rust-lang/rust/issues/124150 - if tcx.sess.opts.unstable_opts.unsound_mir_opts - && SimplifyToExp::default().simplify(tcx, body, bb_idx, param_env).is_some() - { + if SimplifyToExp::default().simplify(tcx, body, bb_idx, param_env).is_some() { should_cleanup = true; continue; } diff --git a/tests/mir-opt/matches_reduce_branches.rs b/tests/mir-opt/matches_reduce_branches.rs index 9328c616127a..6787e5816a30 100644 --- a/tests/mir-opt/matches_reduce_branches.rs +++ b/tests/mir-opt/matches_reduce_branches.rs @@ -1,5 +1,4 @@ //@ test-mir-pass: MatchBranchSimplification -//@ compile-flags: -Zunsound-mir-opts #![feature(repr128)] #![feature(core_intrinsics)] diff --git a/tests/mir-opt/matches_u8.rs b/tests/mir-opt/matches_u8.rs index 89deead461ee..86d646256742 100644 --- a/tests/mir-opt/matches_u8.rs +++ b/tests/mir-opt/matches_u8.rs @@ -1,6 +1,5 @@ // skip-filecheck //@ test-mir-pass: MatchBranchSimplification -//@ compile-flags: -Zunsound-mir-opts // EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff // EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff From 35977b47cc80e54af8e8559231945bada6fe1c01 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 29 Jul 2024 22:17:25 +0300 Subject: [PATCH 47/62] linker: Pass fewer search directories to the linker --- compiler/rustc_codegen_ssa/src/back/link.rs | 94 ++++++++++++--------- compiler/rustc_session/src/filesearch.rs | 5 ++ 2 files changed, 61 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7d457526380d..93ddd1ef0441 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2065,17 +2065,57 @@ fn add_local_crate_metadata_objects( } /// Add sysroot and other globally set directories to the directory search list. -fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained: bool) { - // The default library location, we need this to find the runtime. - // The location of crates will be determined as needed. - let lib_path = sess.target_filesearch(PathKind::All).get_lib_path(); - cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); +fn add_library_search_dirs( + cmd: &mut dyn Linker, + sess: &Session, + self_contained_components: LinkSelfContainedComponents, + apple_sdk_root: Option<&Path>, +) { + if !sess.opts.unstable_opts.link_native_libraries { + return; + } - // Special directory with libraries used only in self-contained linkage mode - if self_contained { - let lib_path = sess.target_filesearch(PathKind::All).get_self_contained_lib_path(); + // Library search paths explicitly supplied by user (`-L` on the command line). + for search_path in sess.target_filesearch(PathKind::Native).cli_search_paths() { + cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir)); + } + for search_path in sess.target_filesearch(PathKind::Framework).cli_search_paths() { + // Contrary to the `-L` docs only framework-specific paths are considered here. + if search_path.kind != PathKind::All { + cmd.framework_path(&search_path.dir); + } + } + + // The toolchain ships some native library components and self-contained linking was enabled. + // Add the self-contained library directory to search paths. + if self_contained_components.intersects( + LinkSelfContainedComponents::LIBC + | LinkSelfContainedComponents::UNWIND + | LinkSelfContainedComponents::MINGW, + ) { + let lib_path = sess.target_filesearch(PathKind::Native).get_self_contained_lib_path(); cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); } + + // Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot + // library directory instead of the self-contained directories. + // The targets here should be in sync with `copy_third_party_objects` in bootstrap. + // FIXME: implement `-Clink-self-contained=+/-unwind`, move the shipped libunwind + // to self-contained directory, and stop adding this search path. + if sess.target.vendor == "fortanix" || sess.target.os == "linux" || sess.target.os == "fuchsia" + { + let lib_path = sess.target_filesearch(PathKind::Native).get_lib_path(); + cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); + } + + // Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks + // we must have the support library stubs in the library search path (#121430). + if let Some(sdk_root) = apple_sdk_root + && sess.target.llvm_target.contains("macabi") + { + cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib")); + cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks")); + } } /// Add options making relocation sections in the produced ELF files read-only @@ -2367,7 +2407,7 @@ fn add_order_independent_options( // Take care of the flavors and CLI options requesting the `lld` linker. add_lld_args(cmd, sess, flavor, self_contained_components); - add_apple_sdk(cmd, sess, flavor); + let apple_sdk_root = add_apple_sdk(cmd, sess, flavor); add_link_script(cmd, sess, tmpdir, crate_type); @@ -2423,7 +2463,7 @@ fn add_order_independent_options( cmd.linker_plugin_lto(); - add_library_search_dirs(cmd, sess, self_contained_components.are_any_components_enabled()); + add_library_search_dirs(cmd, sess, self_contained_components, apple_sdk_root.as_deref()); cmd.output_filename(out_filename); @@ -2637,19 +2677,6 @@ fn add_local_native_libraries( tmpdir: &Path, link_output_kind: LinkOutputKind, ) { - if sess.opts.unstable_opts.link_native_libraries { - // User-supplied library search paths (-L on the command line). These are the same paths - // used to find Rust crates, so some of them may have been added already by the previous - // crate linking code. This only allows them to be found at compile time so it is still - // entirely up to outside forces to make sure that library can be found at runtime. - for search_path in sess.target_filesearch(PathKind::All).search_paths() { - match search_path.kind { - PathKind::Framework => cmd.framework_path(&search_path.dir), - _ => cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir)), - } - } - } - // All static and dynamic native library dependencies are linked to the local crate. let link_static = true; let link_dynamic = true; @@ -2944,7 +2971,7 @@ pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool } } -fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { +fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option { let arch = &sess.target.arch; let os = &sess.target.os; let llvm_target = &sess.target.llvm_target; @@ -2952,11 +2979,11 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { || !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "visionos" | "macos") || !matches!(flavor, LinkerFlavor::Darwin(..)) { - return; + return None; } if os == "macos" && !matches!(flavor, LinkerFlavor::Darwin(Cc::No, _)) { - return; + return None; } let sdk_name = match (arch.as_ref(), os.as_ref()) { @@ -2980,14 +3007,14 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { (_, "macos") => "macosx", _ => { sess.dcx().emit_err(errors::UnsupportedArch { arch, os }); - return; + return None; } }; let sdk_root = match get_apple_sdk_root(sdk_name) { Ok(s) => s, Err(e) => { sess.dcx().emit_err(e); - return; + return None; } }; @@ -3007,16 +3034,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { _ => unreachable!(), } - if llvm_target.contains("macabi") { - // Mac Catalyst uses the macOS SDK, but to link to iOS-specific - // frameworks, we must have the support library stubs in the library - // search path. - - // The flags are called `-L` and `-F` both in Clang, ld64 and ldd. - let sdk_root = Path::new(&sdk_root); - cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib")); - cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks")); - } + Some(sdk_root.into()) } fn get_apple_sdk_root(sdk_name: &str) -> Result> { diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 0c3ec36fed5a..63ca5fefd9fa 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -19,6 +19,11 @@ pub struct FileSearch<'a> { } impl<'a> FileSearch<'a> { + pub fn cli_search_paths(&self) -> impl Iterator { + let kind = self.kind; + self.cli_search_paths.iter().filter(move |sp| sp.kind.matches(kind)) + } + pub fn search_paths(&self) -> impl Iterator { let kind = self.kind; self.cli_search_paths From 1f873f9cf1e6307d1f0bee85f7a866f9531b8a98 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 3 Aug 2024 14:18:55 +0300 Subject: [PATCH 48/62] Fix linking to sanitizers on Apple targets --- compiler/rustc_codegen_ssa/src/back/link.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 93ddd1ef0441..653895380beb 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2099,10 +2099,14 @@ fn add_library_search_dirs( // Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot // library directory instead of the self-contained directories. + // Sanitizer libraries have the same issue and are also linked by name on Apple targets. // The targets here should be in sync with `copy_third_party_objects` in bootstrap. - // FIXME: implement `-Clink-self-contained=+/-unwind`, move the shipped libunwind - // to self-contained directory, and stop adding this search path. - if sess.target.vendor == "fortanix" || sess.target.os == "linux" || sess.target.os == "fuchsia" + // FIXME: implement `-Clink-self-contained=+/-unwind,+/-sanitizers`, move the shipped libunwind + // and sanitizers to self-contained directory, and stop adding this search path. + if sess.target.vendor == "fortanix" + || sess.target.os == "linux" + || sess.target.os == "fuchsia" + || sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty() { let lib_path = sess.target_filesearch(PathKind::Native).get_lib_path(); cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); From 361ab1af0c74820ff74cd48dd7817c308da62642 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:28:57 -0400 Subject: [PATCH 49/62] Revert "Rollup merge of #128104 - mu001999-contrib:fix/128053, r=petrochenkov" This reverts commit 91b18a058c4661f82e420b633dc0a3e1ccd14b88, reversing changes made to 9aedec9313dc8ecf9bdcb5f09c4eb0ad8b9a4875. --- compiler/rustc_passes/src/dead.rs | 36 +++++++++---------- ...lone-debug-dead-code-in-the-same-struct.rs | 4 +-- ...-debug-dead-code-in-the-same-struct.stderr | 16 ++------- .../dead-code/unconstructible-pub-struct.rs | 35 ------------------ .../unconstructible-pub-struct.stderr | 14 -------- 5 files changed, 22 insertions(+), 83 deletions(-) delete mode 100644 tests/ui/lint/dead-code/unconstructible-pub-struct.rs delete mode 100644 tests/ui/lint/dead-code/unconstructible-pub-struct.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 8a931fc4158e..3b1a796130c4 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -73,26 +73,24 @@ fn adt_of<'tcx>(ty: &hir::Ty<'tcx>) -> Option<(LocalDefId, DefKind)> { } fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: LocalDefId) -> bool { - let adt_def = tcx.adt_def(id); - - // skip types contain fields of unit and never type, - // it's usually intentional to make the type not constructible - let not_require_constructor = adt_def.all_fields().any(|field| { + // treat PhantomData and positional ZST as public, + // we don't want to lint types which only have them, + // cause it's a common way to use such types to check things like well-formedness + tcx.adt_def(id).all_fields().all(|field| { let field_type = tcx.type_of(field.did).instantiate_identity(); - field_type.is_unit() || field_type.is_never() - }); - - not_require_constructor - || adt_def.all_fields().all(|field| { - let field_type = tcx.type_of(field.did).instantiate_identity(); - // skip fields of PhantomData, - // cause it's a common way to check things like well-formedness - if field_type.is_phantom_data() { - return true; - } - - field.vis.is_public() - }) + if field_type.is_phantom_data() { + return true; + } + let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit()); + if is_positional + && tcx + .layout_of(tcx.param_env(field.did).and(field_type)) + .map_or(true, |layout| layout.is_zst()) + { + return true; + } + field.vis.is_public() + }) } /// check struct and its fields are public or not, diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs index 6ab1fb7b039b..885dacc727af 100644 --- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs +++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs @@ -1,9 +1,9 @@ #![forbid(dead_code)] #[derive(Debug)] -pub struct Whatever { +pub struct Whatever { //~ ERROR struct `Whatever` is never constructed pub field0: (), - field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read + field1: (), field2: (), field3: (), field4: (), diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr index e9b757b6bae7..e10d28ad03a4 100644 --- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr +++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr @@ -1,19 +1,9 @@ -error: fields `field1`, `field2`, `field3`, and `field4` are never read - --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:6:5 +error: struct `Whatever` is never constructed + --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:4:12 | LL | pub struct Whatever { - | -------- fields in this struct -LL | pub field0: (), -LL | field1: (), - | ^^^^^^ -LL | field2: (), - | ^^^^^^ -LL | field3: (), - | ^^^^^^ -LL | field4: (), - | ^^^^^^ + | ^^^^^^^^ | - = note: `Whatever` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis note: the lint level is defined here --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11 | diff --git a/tests/ui/lint/dead-code/unconstructible-pub-struct.rs b/tests/ui/lint/dead-code/unconstructible-pub-struct.rs deleted file mode 100644 index 2202cbb67309..000000000000 --- a/tests/ui/lint/dead-code/unconstructible-pub-struct.rs +++ /dev/null @@ -1,35 +0,0 @@ -#![feature(never_type)] -#![deny(dead_code)] - -pub struct T1(!); -pub struct T2(()); -pub struct T3(std::marker::PhantomData); - -pub struct T4 { - _x: !, -} - -pub struct T5 { - _x: !, - _y: X, -} - -pub struct T6 { - _x: (), -} - -pub struct T7 { - _x: (), - _y: X, -} - -pub struct T8 { - _x: std::marker::PhantomData, -} - -pub struct T9 { //~ ERROR struct `T9` is never constructed - _x: std::marker::PhantomData, - _y: i32, -} - -fn main() {} diff --git a/tests/ui/lint/dead-code/unconstructible-pub-struct.stderr b/tests/ui/lint/dead-code/unconstructible-pub-struct.stderr deleted file mode 100644 index a3dde042bbe1..000000000000 --- a/tests/ui/lint/dead-code/unconstructible-pub-struct.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: struct `T9` is never constructed - --> $DIR/unconstructible-pub-struct.rs:30:12 - | -LL | pub struct T9 { - | ^^ - | -note: the lint level is defined here - --> $DIR/unconstructible-pub-struct.rs:2:9 - | -LL | #![deny(dead_code)] - | ^^^^^^^^^ - -error: aborting due to 1 previous error - From c6b6c1270a25ee05c4e1f6a9daaf48ef60317f2c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:28:58 -0400 Subject: [PATCH 50/62] Revert "Rollup merge of #127017 - mu001999-contrib:dead/enhance, r=pnkfelix" This reverts commit a70dc297a899b76793a14c5705f6ec78fd7a57a7, reversing changes made to ceae37188b9f1be527bb16c9d657a161be7dbbe3. --- compiler/rustc_passes/src/dead.rs | 32 +++++-------- .../dead-code/unused-impl-for-non-adts.rs | 45 ------------------- .../dead-code/unused-impl-for-non-adts.stderr | 20 --------- 3 files changed, 10 insertions(+), 87 deletions(-) delete mode 100644 tests/ui/lint/dead-code/unused-impl-for-non-adts.rs delete mode 100644 tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 3b1a796130c4..9c475c9fbf46 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -55,24 +55,7 @@ impl Publicness { } } -fn adt_of<'tcx>(ty: &hir::Ty<'tcx>) -> Option<(LocalDefId, DefKind)> { - match ty.kind { - TyKind::Path(hir::QPath::Resolved(_, path)) => { - if let Res::Def(def_kind, def_id) = path.res - && let Some(local_def_id) = def_id.as_local() - { - Some((local_def_id, def_kind)) - } else { - None - } - } - TyKind::Slice(ty) | TyKind::Array(ty, _) => adt_of(ty), - TyKind::Ptr(ty) | TyKind::Ref(_, ty) => adt_of(ty.ty), - _ => None, - } -} - -fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: LocalDefId) -> bool { +fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool { // treat PhantomData and positional ZST as public, // we don't want to lint types which only have them, // cause it's a common way to use such types to check things like well-formedness @@ -97,7 +80,10 @@ fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: LocalDefId) -> bool { /// for enum and union, just check they are public, /// and doesn't solve types like &T for now, just skip them fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> Publicness { - if let Some((def_id, def_kind)) = adt_of(ty) { + if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind + && let Res::Def(def_kind, def_id) = path.res + && def_id.is_local() + { return match def_kind { DefKind::Enum | DefKind::Union => { let ty_is_public = tcx.visibility(def_id).is_public(); @@ -580,8 +566,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } fn impl_item_with_used_self(&mut self, impl_id: hir::ItemId, impl_item_id: LocalDefId) -> bool { - if let Some((local_def_id, def_kind)) = - adt_of(self.tcx.hir().item(impl_id).expect_impl().self_ty) + if let TyKind::Path(hir::QPath::Resolved(_, path)) = + self.tcx.hir().item(impl_id).expect_impl().self_ty.kind + && let Res::Def(def_kind, def_id) = path.res + && let Some(local_def_id) = def_id.as_local() && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union) { if let Some(trait_item_id) = self.tcx.associated_item(impl_item_id).trait_item_def_id @@ -928,7 +916,7 @@ fn create_and_seed_worklist( match tcx.def_kind(id) { DefKind::Impl { .. } => false, DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), - DefKind::Struct => struct_all_fields_are_public(tcx, id) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(), + DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(), _ => true }) .map(|id| (id, ComesFromAllowExpect::No)) diff --git a/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs b/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs deleted file mode 100644 index 46065dcee81e..000000000000 --- a/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs +++ /dev/null @@ -1,45 +0,0 @@ -#![deny(dead_code)] - -struct Foo; //~ ERROR struct `Foo` is never constructed - -trait Trait { //~ ERROR trait `Trait` is never used - fn foo(&self) {} -} - -impl Trait for Foo {} - -impl Trait for [Foo] {} -impl Trait for [Foo; N] {} - -impl Trait for *const Foo {} -impl Trait for *mut Foo {} - -impl Trait for &Foo {} -impl Trait for &&Foo {} -impl Trait for &mut Foo {} - -impl Trait for [&Foo] {} -impl Trait for &[Foo] {} -impl Trait for &*const Foo {} - -pub trait Trait2 { - fn foo(&self) {} -} - -impl Trait2 for Foo {} - -impl Trait2 for [Foo] {} -impl Trait2 for [Foo; N] {} - -impl Trait2 for *const Foo {} -impl Trait2 for *mut Foo {} - -impl Trait2 for &Foo {} -impl Trait2 for &&Foo {} -impl Trait2 for &mut Foo {} - -impl Trait2 for [&Foo] {} -impl Trait2 for &[Foo] {} -impl Trait2 for &*const Foo {} - -fn main() {} diff --git a/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr b/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr deleted file mode 100644 index e61fc403e810..000000000000 --- a/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: struct `Foo` is never constructed - --> $DIR/unused-impl-for-non-adts.rs:3:8 - | -LL | struct Foo; - | ^^^ - | -note: the lint level is defined here - --> $DIR/unused-impl-for-non-adts.rs:1:9 - | -LL | #![deny(dead_code)] - | ^^^^^^^^^ - -error: trait `Trait` is never used - --> $DIR/unused-impl-for-non-adts.rs:5:7 - | -LL | trait Trait { - | ^^^^^ - -error: aborting due to 2 previous errors - From 5f5b4ee12859e9ba54a862a07c02be272be27d50 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:28:59 -0400 Subject: [PATCH 51/62] Revert "Rollup merge of #127107 - mu001999-contrib:dead/enhance-2, r=pnkfelix" This reverts commit 31fe9628cf830a08e7194a446f66c668aaea86e9, reversing changes made to f20307851ead9fbbb9fa88bbffb3258a069230a6. --- compiler/rustc_passes/src/dead.rs | 40 +++++++++++++------ library/core/src/default.rs | 1 + tests/ui-fulldeps/deriving-global.rs | 3 -- tests/ui-fulldeps/deriving-hygiene.rs | 1 - .../ui/const-generics/issues/issue-86535-2.rs | 1 - tests/ui/const-generics/issues/issue-86535.rs | 1 - .../impl-trait/extra-impl-in-trait-impl.fixed | 2 - .../ui/impl-trait/extra-impl-in-trait-impl.rs | 2 - .../extra-impl-in-trait-impl.stderr | 8 ++-- tests/ui/lint/dead-code/issue-59003.rs | 2 +- .../lint-unused-adt-appeared-in-pattern.rs | 37 ----------------- ...lint-unused-adt-appeared-in-pattern.stderr | 20 ---------- .../not-lint-used-adt-appeared-in-pattern.rs | 32 --------------- ...sed-adt-impl-pub-trait-with-assoc-const.rs | 36 ++++++----------- ...adt-impl-pub-trait-with-assoc-const.stderr | 24 ++--------- .../dead-code/unused-struct-derive-default.rs | 1 - .../unused-struct-derive-default.stderr | 1 + tests/ui/parser/issues/issue-105366.fixed | 1 - tests/ui/parser/issues/issue-105366.rs | 1 - tests/ui/parser/issues/issue-105366.stderr | 2 +- 20 files changed, 52 insertions(+), 164 deletions(-) delete mode 100644 tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs delete mode 100644 tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr delete mode 100644 tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 9c475c9fbf46..78fbcc1f4062 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -278,10 +278,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { pats: &[hir::PatField<'_>], ) { let variant = match self.typeck_results().node_type(lhs.hir_id).kind() { - ty::Adt(adt, _) => { - self.check_def_id(adt.did()); - adt.variant_of_res(res) - } + ty::Adt(adt, _) => adt.variant_of_res(res), _ => span_bug!(lhs.span, "non-ADT in struct pattern"), }; for pat in pats { @@ -301,10 +298,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { dotdot: hir::DotDotPos, ) { let variant = match self.typeck_results().node_type(lhs.hir_id).kind() { - ty::Adt(adt, _) => { - self.check_def_id(adt.did()); - adt.variant_of_res(res) - } + ty::Adt(adt, _) => adt.variant_of_res(res), _ => { self.tcx.dcx().span_delayed_bug(lhs.span, "non-ADT in tuple struct pattern"); return; @@ -409,6 +403,31 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { return false; } + // don't ignore impls for Enums and pub Structs whose methods don't have self receiver, + // cause external crate may call such methods to construct values of these types + if let Some(local_impl_of) = impl_of.as_local() + && let Some(local_def_id) = def_id.as_local() + && let Some(fn_sig) = + self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id)) + && matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None) + && let TyKind::Path(hir::QPath::Resolved(_, path)) = + self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind + && let Res::Def(def_kind, did) = path.res + { + match def_kind { + // for example, #[derive(Default)] pub struct T(i32); + // external crate can call T::default() to construct T, + // so that don't ignore impl Default for pub Enum and Structs + DefKind::Struct | DefKind::Union if self.tcx.visibility(did).is_public() => { + return false; + } + // don't ignore impl Default for Enums, + // cause we don't know which variant is constructed + DefKind::Enum => return false, + _ => (), + }; + } + if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of) && self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads) { @@ -672,9 +691,6 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { self.handle_field_pattern_match(pat, res, fields); } PatKind::Path(ref qpath) => { - if let ty::Adt(adt, _) = self.typeck_results().node_type(pat.hir_id).kind() { - self.check_def_id(adt.did()); - } let res = self.typeck_results().qpath_res(qpath, pat.hir_id); self.handle_res(res); } @@ -830,7 +846,7 @@ fn check_item<'tcx>( // mark the method live if the self_ty is public, // or the method is public and may construct self if tcx.visibility(local_def_id).is_public() - && (ty_and_all_fields_are_public || (ty_is_public && may_construct_self)) + && (ty_and_all_fields_are_public || may_construct_self) { // if the impl item is public, // and the ty may be constructed or can be constructed in foreign crates, diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 4524b352ec81..5cacedcb241a 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -103,6 +103,7 @@ use crate::ascii::Char as AsciiChar; /// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "Default")] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)] pub trait Default: Sized { /// Returns the "default value" for a type. /// diff --git a/tests/ui-fulldeps/deriving-global.rs b/tests/ui-fulldeps/deriving-global.rs index 0ba149c9ad65..7783010be441 100644 --- a/tests/ui-fulldeps/deriving-global.rs +++ b/tests/ui-fulldeps/deriving-global.rs @@ -17,21 +17,18 @@ mod submod { // if any of these are implemented without global calls for any // function calls, then being in a submodule will (correctly) // cause errors about unrecognised module `std` (or `extra`) - #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] enum A { A1(usize), A2(isize), } - #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] struct B { x: usize, y: isize, } - #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] struct C(usize, isize); } diff --git a/tests/ui-fulldeps/deriving-hygiene.rs b/tests/ui-fulldeps/deriving-hygiene.rs index f948d6ac544e..a3a6f9e022eb 100644 --- a/tests/ui-fulldeps/deriving-hygiene.rs +++ b/tests/ui-fulldeps/deriving-hygiene.rs @@ -20,7 +20,6 @@ pub const s: u8 = 1; pub const state: u8 = 1; pub const cmp: u8 = 1; -#[allow(dead_code)] #[derive(Ord, Eq, PartialOrd, PartialEq, Debug, Decodable, Encodable, Hash)] struct Foo {} diff --git a/tests/ui/const-generics/issues/issue-86535-2.rs b/tests/ui/const-generics/issues/issue-86535-2.rs index ab68c6b78df3..8d064f3eeb1b 100644 --- a/tests/ui/const-generics/issues/issue-86535-2.rs +++ b/tests/ui/const-generics/issues/issue-86535-2.rs @@ -9,7 +9,6 @@ pub trait Foo { [(); Self::ASSOC_C]:; } -#[allow(dead_code)] struct Bar; impl Foo for Bar { const ASSOC_C: usize = 3; diff --git a/tests/ui/const-generics/issues/issue-86535.rs b/tests/ui/const-generics/issues/issue-86535.rs index 9aaf7ddc9e86..62454f4a388a 100644 --- a/tests/ui/const-generics/issues/issue-86535.rs +++ b/tests/ui/const-generics/issues/issue-86535.rs @@ -2,7 +2,6 @@ #![feature(adt_const_params, unsized_const_params, generic_const_exprs)] #![allow(incomplete_features, unused_variables)] -#[allow(dead_code)] struct F; impl X for F<{ S }> { const W: usize = 3; diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed index 3c4499f01733..886fc1d00580 100644 --- a/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed +++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed @@ -1,8 +1,6 @@ //@ run-rustfix -#[allow(dead_code)] struct S(T); -#[allow(dead_code)] struct S2; impl Default for S { diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.rs b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs index ac0783295242..f3271993867c 100644 --- a/tests/ui/impl-trait/extra-impl-in-trait-impl.rs +++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs @@ -1,8 +1,6 @@ //@ run-rustfix -#[allow(dead_code)] struct S(T); -#[allow(dead_code)] struct S2; impl impl Default for S { diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr index 91c7da5a04fb..5aafc8b64d4f 100644 --- a/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr +++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr @@ -1,23 +1,23 @@ error: unexpected `impl` keyword - --> $DIR/extra-impl-in-trait-impl.rs:8:18 + --> $DIR/extra-impl-in-trait-impl.rs:6:18 | LL | impl impl Default for S { | ^^^^^ help: remove the extra `impl` | note: this is parsed as an `impl Trait` type, but a trait is expected at this position - --> $DIR/extra-impl-in-trait-impl.rs:8:18 + --> $DIR/extra-impl-in-trait-impl.rs:6:18 | LL | impl impl Default for S { | ^^^^^^^^^^^^ error: unexpected `impl` keyword - --> $DIR/extra-impl-in-trait-impl.rs:14:6 + --> $DIR/extra-impl-in-trait-impl.rs:12:6 | LL | impl impl Default for S2 { | ^^^^^ help: remove the extra `impl` | note: this is parsed as an `impl Trait` type, but a trait is expected at this position - --> $DIR/extra-impl-in-trait-impl.rs:14:6 + --> $DIR/extra-impl-in-trait-impl.rs:12:6 | LL | impl impl Default for S2 { | ^^^^^^^^^^^^ diff --git a/tests/ui/lint/dead-code/issue-59003.rs b/tests/ui/lint/dead-code/issue-59003.rs index 319cf2db1495..e3dcaca57788 100644 --- a/tests/ui/lint/dead-code/issue-59003.rs +++ b/tests/ui/lint/dead-code/issue-59003.rs @@ -4,8 +4,8 @@ #![deny(dead_code)] -#[allow(dead_code)] struct Foo { + #[allow(dead_code)] inner: u32, } diff --git a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs deleted file mode 100644 index 25777438456b..000000000000 --- a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![deny(dead_code)] - -struct Foo(u8); //~ ERROR struct `Foo` is never constructed - -enum Bar { //~ ERROR enum `Bar` is never used - Var1(u8), - Var2(u8), -} - -pub trait Tr1 { - fn f1() -> Self; -} - -impl Tr1 for Foo { - fn f1() -> Foo { - let f = Foo(0); - let Foo(tag) = f; - Foo(tag) - } -} - -impl Tr1 for Bar { - fn f1() -> Bar { - let b = Bar::Var1(0); - let b = if let Bar::Var1(_) = b { - Bar::Var1(0) - } else { - Bar::Var2(0) - }; - match b { - Bar::Var1(_) => Bar::Var2(0), - Bar::Var2(_) => Bar::Var1(0), - } - } -} - -fn main() {} diff --git a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr deleted file mode 100644 index 7c1a4b459775..000000000000 --- a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: struct `Foo` is never constructed - --> $DIR/lint-unused-adt-appeared-in-pattern.rs:3:8 - | -LL | struct Foo(u8); - | ^^^ - | -note: the lint level is defined here - --> $DIR/lint-unused-adt-appeared-in-pattern.rs:1:9 - | -LL | #![deny(dead_code)] - | ^^^^^^^^^ - -error: enum `Bar` is never used - --> $DIR/lint-unused-adt-appeared-in-pattern.rs:5:6 - | -LL | enum Bar { - | ^^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs b/tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs deleted file mode 100644 index 43a2e4319043..000000000000 --- a/tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs +++ /dev/null @@ -1,32 +0,0 @@ -//@ check-pass - -#![deny(dead_code)] - -#[repr(u8)] -#[derive(Copy, Clone, Debug)] -pub enum RecordField { - Target = 1, - Level, - Module, - File, - Line, - NumArgs, -} - -unsafe trait Pod {} - -#[repr(transparent)] -struct RecordFieldWrapper(RecordField); - -unsafe impl Pod for RecordFieldWrapper {} - -fn try_read(buf: &[u8]) -> T { - unsafe { std::ptr::read_unaligned(buf.as_ptr() as *const T) } -} - -pub fn foo(buf: &[u8]) -> RecordField { - let RecordFieldWrapper(tag) = try_read(buf); - tag -} - -fn main() {} diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs index 658cc3d6c613..bf2fc243e819 100644 --- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs +++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs @@ -1,9 +1,8 @@ #![deny(dead_code)] struct T1; //~ ERROR struct `T1` is never constructed -struct T2; //~ ERROR struct `T2` is never constructed -pub struct T3(i32); //~ ERROR struct `T3` is never constructed -pub struct T4(i32); //~ ERROR field `0` is never read +pub struct T2(i32); //~ ERROR struct `T2` is never constructed +struct T3; trait Trait1 { //~ ERROR trait `Trait1` is never used const UNUSED: i32; @@ -12,13 +11,13 @@ trait Trait1 { //~ ERROR trait `Trait1` is never used } pub trait Trait2 { - const MAY_USED: i32; - fn may_used(&self) {} + const USED: i32; + fn used(&self) {} } pub trait Trait3 { - const MAY_USED: i32; - fn may_used() -> Self; + const USED: i32; + fn construct_self() -> Self; } impl Trait1 for T1 { @@ -31,34 +30,23 @@ impl Trait1 for T1 { impl Trait1 for T2 { const UNUSED: i32 = 0; fn construct_self() -> Self { - Self + T2(0) } } impl Trait2 for T1 { - const MAY_USED: i32 = 0; + const USED: i32 = 0; } impl Trait2 for T2 { - const MAY_USED: i32 = 0; + const USED: i32 = 0; } -impl Trait2 for T3 { - const MAY_USED: i32 = 0; -} - -impl Trait3 for T2 { - const MAY_USED: i32 = 0; - fn may_used() -> Self { +impl Trait3 for T3 { + const USED: i32 = 0; + fn construct_self() -> Self { Self } } -impl Trait3 for T4 { - const MAY_USED: i32 = 0; - fn may_used() -> Self { - T4(0) - } -} - fn main() {} diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr index 08c7a5cb4b06..174096d93988 100644 --- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr +++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr @@ -11,32 +11,16 @@ LL | #![deny(dead_code)] | ^^^^^^^^^ error: struct `T2` is never constructed - --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:8 + --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:12 | -LL | struct T2; - | ^^ - -error: struct `T3` is never constructed - --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:5:12 - | -LL | pub struct T3(i32); +LL | pub struct T2(i32); | ^^ -error: field `0` is never read - --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:6:15 - | -LL | pub struct T4(i32); - | -- ^^^ - | | - | field in this struct - | - = help: consider removing this field - error: trait `Trait1` is never used - --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:8:7 + --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:7:7 | LL | trait Trait1 { | ^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.rs b/tests/ui/lint/dead-code/unused-struct-derive-default.rs index f20b7cb66ee5..330ad32dd570 100644 --- a/tests/ui/lint/dead-code/unused-struct-derive-default.rs +++ b/tests/ui/lint/dead-code/unused-struct-derive-default.rs @@ -22,5 +22,4 @@ pub struct T2 { fn main() { let _x: Used = Default::default(); - let _e: E = Default::default(); } diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.stderr b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr index 7422f9a39f31..bbb0bd7be706 100644 --- a/tests/ui/lint/dead-code/unused-struct-derive-default.stderr +++ b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr @@ -4,6 +4,7 @@ error: struct `T` is never constructed LL | struct T; | ^ | + = note: `T` has a derived impl for the trait `Default`, but this is intentionally ignored during dead code analysis note: the lint level is defined here --> $DIR/unused-struct-derive-default.rs:1:9 | diff --git a/tests/ui/parser/issues/issue-105366.fixed b/tests/ui/parser/issues/issue-105366.fixed index 95419dc07f2c..7157b647524d 100644 --- a/tests/ui/parser/issues/issue-105366.fixed +++ b/tests/ui/parser/issues/issue-105366.fixed @@ -1,6 +1,5 @@ //@ run-rustfix -#[allow(dead_code)] struct Foo; impl From for Foo { diff --git a/tests/ui/parser/issues/issue-105366.rs b/tests/ui/parser/issues/issue-105366.rs index 3278b7379912..dc3cb8b343d3 100644 --- a/tests/ui/parser/issues/issue-105366.rs +++ b/tests/ui/parser/issues/issue-105366.rs @@ -1,6 +1,5 @@ //@ run-rustfix -#[allow(dead_code)] struct Foo; fn From for Foo { diff --git a/tests/ui/parser/issues/issue-105366.stderr b/tests/ui/parser/issues/issue-105366.stderr index 195305a2ec88..18c04dfaf208 100644 --- a/tests/ui/parser/issues/issue-105366.stderr +++ b/tests/ui/parser/issues/issue-105366.stderr @@ -1,5 +1,5 @@ error: you might have meant to write `impl` instead of `fn` - --> $DIR/issue-105366.rs:6:1 + --> $DIR/issue-105366.rs:5:1 | LL | fn From for Foo { | ^^ From 22da61624590a413c98df5087ff4454fcc618dbf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:29:01 -0400 Subject: [PATCH 52/62] Revert "Rollup merge of #126618 - mu001999-contrib:dead/enhance, r=pnkfelix" This reverts commit 2724aeaaeb127a8073e39461caacbe21a128ce7b, reversing changes made to d929a42a664c026167800801b26d734db925314f. --- compiler/rustc_passes/src/dead.rs | 41 ++++++++----------- .../ui/const-generics/cross_crate_complex.rs | 1 - .../missing-bounds.fixed | 4 -- .../missing-bounds.rs | 4 -- .../missing-bounds.stderr | 18 ++++---- .../dead-code/unused-trait-with-assoc-ty.rs | 11 ----- .../unused-trait-with-assoc-ty.stderr | 20 --------- tests/ui/pattern/issue-22546.rs | 2 +- tests/ui/pattern/issue-22546.stderr | 10 +++++ 9 files changed, 36 insertions(+), 75 deletions(-) delete mode 100644 tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs delete mode 100644 tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr create mode 100644 tests/ui/pattern/issue-22546.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 78fbcc1f4062..d4ce9b02473b 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -156,10 +156,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn handle_res(&mut self, res: Res) { match res { - Res::Def( - DefKind::Const | DefKind::AssocConst | DefKind::AssocTy | DefKind::TyAlias, - def_id, - ) => { + Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => { self.check_def_id(def_id); } _ if self.in_pat => {} @@ -470,7 +467,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_item(self, item) } hir::ItemKind::ForeignMod { .. } => {} - hir::ItemKind::Trait(_, _, _, _, trait_item_refs) => { + hir::ItemKind::Trait(..) => { for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) { if let Some(local_def_id) = impl_def_id.as_local() && let ItemKind::Impl(impl_ref) = @@ -483,12 +480,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_path(self, impl_ref.of_trait.unwrap().path); } } - // mark assoc ty live if the trait is live - for trait_item in trait_item_refs { - if let hir::AssocItemKind::Type = trait_item.kind { - self.check_def_id(trait_item.id.owner_id.to_def_id()); - } - } + intravisit::walk_item(self, item) } _ => intravisit::walk_item(self, item), @@ -505,8 +497,9 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { && let ItemKind::Impl(impl_ref) = self.tcx.hir().expect_item(local_impl_id).kind { - if !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty) - .ty_and_all_fields_are_public + if !matches!(trait_item.kind, hir::TraitItemKind::Type(..)) + && !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty) + .ty_and_all_fields_are_public { // skip impl-items of non pure pub ty, // cause we don't know the ty is constructed or not, @@ -845,8 +838,9 @@ fn check_item<'tcx>( // for trait impl blocks, // mark the method live if the self_ty is public, // or the method is public and may construct self - if tcx.visibility(local_def_id).is_public() - && (ty_and_all_fields_are_public || may_construct_self) + if of_trait && matches!(tcx.def_kind(local_def_id), DefKind::AssocTy) + || tcx.visibility(local_def_id).is_public() + && (ty_and_all_fields_are_public || may_construct_self) { // if the impl item is public, // and the ty may be constructed or can be constructed in foreign crates, @@ -883,13 +877,10 @@ fn check_trait_item( worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>, id: hir::TraitItemId, ) { - use hir::TraitItemKind::{Const, Fn, Type}; - if matches!( - tcx.def_kind(id.owner_id), - DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn - ) { + use hir::TraitItemKind::{Const, Fn}; + if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) { let trait_item = tcx.hir().trait_item(id); - if matches!(trait_item.kind, Const(_, Some(_)) | Type(_, Some(_)) | Fn(..)) + if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..)) && let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id) { @@ -931,7 +922,7 @@ fn create_and_seed_worklist( // checks impls, impl-items and pub structs with all public fields later match tcx.def_kind(id) { DefKind::Impl { .. } => false, - DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), + DefKind::AssocConst | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(), _ => true }) @@ -1218,7 +1209,6 @@ impl<'tcx> DeadVisitor<'tcx> { } match self.tcx.def_kind(def_id) { DefKind::AssocConst - | DefKind::AssocTy | DefKind::AssocFn | DefKind::Fn | DefKind::Static { .. } @@ -1260,14 +1250,15 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { || (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id)) { for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) { - // We have diagnosed unused assocs in traits + // We have diagnosed unused assoc consts and fns in traits if matches!(def_kind, DefKind::Impl { of_trait: true }) - && matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn) + && matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocFn) // skip unused public inherent methods, // cause we have diagnosed unconstructed struct || matches!(def_kind, DefKind::Impl { of_trait: false }) && tcx.visibility(def_id).is_public() && ty_ref_to_pub_struct(tcx, tcx.hir().item(item).expect_impl().self_ty).ty_is_public + || def_kind == DefKind::Trait && tcx.def_kind(def_id) == DefKind::AssocTy { continue; } diff --git a/tests/ui/const-generics/cross_crate_complex.rs b/tests/ui/const-generics/cross_crate_complex.rs index b44d889f5e99..d13b69aa0cfb 100644 --- a/tests/ui/const-generics/cross_crate_complex.rs +++ b/tests/ui/const-generics/cross_crate_complex.rs @@ -11,7 +11,6 @@ async fn foo() { async_in_foo(async_out_foo::<4>().await).await; } -#[allow(dead_code)] struct Faz; impl Foo for Faz {} diff --git a/tests/ui/generic-associated-types/missing-bounds.fixed b/tests/ui/generic-associated-types/missing-bounds.fixed index ff69016d8626..703d3c1e0fb1 100644 --- a/tests/ui/generic-associated-types/missing-bounds.fixed +++ b/tests/ui/generic-associated-types/missing-bounds.fixed @@ -2,7 +2,6 @@ use std::ops::Add; -#[allow(dead_code)] struct A(B); impl Add for A where B: Add { @@ -13,7 +12,6 @@ impl Add for A where B: Add { } } -#[allow(dead_code)] struct C(B); impl> Add for C { @@ -24,7 +22,6 @@ impl> Add for C { } } -#[allow(dead_code)] struct D(B); impl> Add for D { @@ -35,7 +32,6 @@ impl> Add for D { } } -#[allow(dead_code)] struct E(B); impl> Add for E where B: Add { diff --git a/tests/ui/generic-associated-types/missing-bounds.rs b/tests/ui/generic-associated-types/missing-bounds.rs index 1f83356c2fa6..f40b42288731 100644 --- a/tests/ui/generic-associated-types/missing-bounds.rs +++ b/tests/ui/generic-associated-types/missing-bounds.rs @@ -2,7 +2,6 @@ use std::ops::Add; -#[allow(dead_code)] struct A(B); impl Add for A where B: Add { @@ -13,7 +12,6 @@ impl Add for A where B: Add { } } -#[allow(dead_code)] struct C(B); impl Add for C { @@ -24,7 +22,6 @@ impl Add for C { } } -#[allow(dead_code)] struct D(B); impl Add for D { @@ -35,7 +32,6 @@ impl Add for D { } } -#[allow(dead_code)] struct E(B); impl Add for E where ::Output = B { diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr index 0f0dc24c06c0..1d7d80d1b076 100644 --- a/tests/ui/generic-associated-types/missing-bounds.stderr +++ b/tests/ui/generic-associated-types/missing-bounds.stderr @@ -1,5 +1,5 @@ error: equality constraints are not yet supported in `where` clauses - --> $DIR/missing-bounds.rs:41:33 + --> $DIR/missing-bounds.rs:37:33 | LL | impl Add for E where ::Output = B { | ^^^^^^^^^^^^^^^^^^^^^^ not supported @@ -11,7 +11,7 @@ LL | impl Add for E where B: Add { | ~~~~~~~~~~~~~~~~~~ error[E0308]: mismatched types - --> $DIR/missing-bounds.rs:12:11 + --> $DIR/missing-bounds.rs:11:11 | LL | impl Add for A where B: Add { | - expected this type parameter @@ -24,14 +24,14 @@ LL | A(self.0 + rhs.0) = note: expected type parameter `B` found associated type `::Output` help: the type constructed contains `::Output` due to the type of the argument passed - --> $DIR/missing-bounds.rs:12:9 + --> $DIR/missing-bounds.rs:11:9 | LL | A(self.0 + rhs.0) | ^^--------------^ | | | this argument influences the type of `A` note: tuple struct defined here - --> $DIR/missing-bounds.rs:6:8 + --> $DIR/missing-bounds.rs:5:8 | LL | struct A(B); | ^ @@ -41,7 +41,7 @@ LL | impl Add for A where B: Add { | ++++++++++++ error[E0308]: mismatched types - --> $DIR/missing-bounds.rs:23:14 + --> $DIR/missing-bounds.rs:21:14 | LL | impl Add for C { | - expected this type parameter @@ -54,7 +54,7 @@ LL | Self(self.0 + rhs.0) = note: expected type parameter `B` found associated type `::Output` note: tuple struct defined here - --> $DIR/missing-bounds.rs:17:8 + --> $DIR/missing-bounds.rs:15:8 | LL | struct C(B); | ^ @@ -64,7 +64,7 @@ LL | impl> Add for C { | ++++++++++++ error[E0369]: cannot add `B` to `B` - --> $DIR/missing-bounds.rs:34:21 + --> $DIR/missing-bounds.rs:31:21 | LL | Self(self.0 + rhs.0) | ------ ^ ----- B @@ -77,7 +77,7 @@ LL | impl> Add for D { | +++++++++++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/missing-bounds.rs:46:14 + --> $DIR/missing-bounds.rs:42:14 | LL | impl Add for E where ::Output = B { | - expected this type parameter @@ -90,7 +90,7 @@ LL | Self(self.0 + rhs.0) = note: expected type parameter `B` found associated type `::Output` note: tuple struct defined here - --> $DIR/missing-bounds.rs:39:8 + --> $DIR/missing-bounds.rs:35:8 | LL | struct E(B); | ^ diff --git a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs b/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs deleted file mode 100644 index e8116d83ebf1..000000000000 --- a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![deny(dead_code)] - -struct T1; //~ ERROR struct `T1` is never constructed - -trait Foo { type Unused; } //~ ERROR trait `Foo` is never used -impl Foo for T1 { type Unused = Self; } - -pub trait Bar { type Used; } -impl Bar for T1 { type Used = Self; } - -fn main() {} diff --git a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr b/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr deleted file mode 100644 index ab73c6406343..000000000000 --- a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: struct `T1` is never constructed - --> $DIR/unused-trait-with-assoc-ty.rs:3:8 - | -LL | struct T1; - | ^^ - | -note: the lint level is defined here - --> $DIR/unused-trait-with-assoc-ty.rs:1:9 - | -LL | #![deny(dead_code)] - | ^^^^^^^^^ - -error: trait `Foo` is never used - --> $DIR/unused-trait-with-assoc-ty.rs:5:7 - | -LL | trait Foo { type Unused; } - | ^^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/pattern/issue-22546.rs b/tests/ui/pattern/issue-22546.rs index d5c5b68be78d..fd1d5fb6c477 100644 --- a/tests/ui/pattern/issue-22546.rs +++ b/tests/ui/pattern/issue-22546.rs @@ -15,7 +15,7 @@ impl Foo { } } -trait Tr { +trait Tr { //~ WARN trait `Tr` is never used type U; } diff --git a/tests/ui/pattern/issue-22546.stderr b/tests/ui/pattern/issue-22546.stderr new file mode 100644 index 000000000000..e067a95e4226 --- /dev/null +++ b/tests/ui/pattern/issue-22546.stderr @@ -0,0 +1,10 @@ +warning: trait `Tr` is never used + --> $DIR/issue-22546.rs:18:7 + | +LL | trait Tr { + | ^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + From d29818c9f552d6941bc00770e7aa1e2768e02e07 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:29:02 -0400 Subject: [PATCH 53/62] Revert "Rollup merge of #126315 - mu001999-contrib:fix/126289, r=petrochenkov" This reverts commit 977c5fd419ade52467f7de79d5bfc25c0c893275, reversing changes made to 24c94f0e4f5aa333c665fbbba423172c30176624. --- compiler/rustc_passes/src/dead.rs | 2 +- .../allow-unconstructed-pub-struct.rs | 33 ------------------- 2 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index d4ce9b02473b..90f436a6fc1a 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -923,7 +923,7 @@ fn create_and_seed_worklist( match tcx.def_kind(id) { DefKind::Impl { .. } => false, DefKind::AssocConst | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), - DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(), + DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()), _ => true }) .map(|id| (id, ComesFromAllowExpect::No)) diff --git a/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs b/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs deleted file mode 100644 index 8cd1524045b1..000000000000 --- a/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs +++ /dev/null @@ -1,33 +0,0 @@ -//@ check-pass - -mod ffi { - use super::*; - - extern "C" { - pub fn DomPromise_AddRef(promise: *const Promise); - pub fn DomPromise_Release(promise: *const Promise); - } -} - -#[repr(C)] -#[allow(unused)] -pub struct Promise { - private: [u8; 0], - __nosync: ::std::marker::PhantomData<::std::rc::Rc>, -} - -pub unsafe trait RefCounted { - unsafe fn addref(&self); - unsafe fn release(&self); -} - -unsafe impl RefCounted for Promise { - unsafe fn addref(&self) { - ffi::DomPromise_AddRef(self) - } - unsafe fn release(&self) { - ffi::DomPromise_Release(self) - } -} - -fn main() {} From ac56007ea7ba6f5bdf9c018f6561617fc5626e3d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:29:20 -0400 Subject: [PATCH 54/62] Revert "Rollup merge of #125572 - mu001999-contrib:dead/enhance, r=pnkfelix" This reverts commit 13314df21b0bb0cdd02c6760581d1b9f1052fa7e, reversing changes made to 6e534c73c35f569492ed5fb5f349075d58ed8b7e. --- compiler/rustc_passes/src/dead.rs | 121 ++++-------------- .../item-collection/generic-impl.rs | 10 +- .../item-collection/overloaded-operators.rs | 24 ++-- tests/ui/coherence/re-rebalance-coherence.rs | 1 - .../defaults/repr-c-issue-82792.rs | 1 - .../generic_const_exprs/associated-consts.rs | 3 +- .../transparent-maybeunit-array-wrapper.rs | 1 - ...lone-debug-dead-code-in-the-same-struct.rs | 4 +- ...-debug-dead-code-in-the-same-struct.stderr | 16 ++- tests/ui/issues/issue-5708.rs | 1 - tests/ui/lint/dead-code/lint-dead-code-1.rs | 5 +- .../ui/lint/dead-code/lint-dead-code-1.stderr | 26 +--- tests/ui/lint/dead-code/unused-assoc-const.rs | 20 --- .../lint/dead-code/unused-assoc-const.stderr | 16 --- tests/ui/lint/dead-code/unused-pub-struct.rs | 48 ------- .../lint/dead-code/unused-pub-struct.stderr | 14 -- ...re-clause-before-tuple-struct-body-0.fixed | 3 +- ...where-clause-before-tuple-struct-body-0.rs | 3 +- ...e-clause-before-tuple-struct-body-0.stderr | 10 +- tests/ui/pub/pub-ident-struct-4.fixed | 3 +- tests/ui/pub/pub-ident-struct-4.rs | 3 +- tests/ui/pub/pub-ident-struct-4.stderr | 8 +- tests/ui/regions/regions-issue-21422.rs | 1 - .../structs-enums/newtype-struct-with-dtor.rs | 2 - .../ui/structs-enums/uninstantiable-struct.rs | 3 +- .../ui/suggestions/derive-clone-for-eq.fixed | 1 - tests/ui/suggestions/derive-clone-for-eq.rs | 1 - .../ui/suggestions/derive-clone-for-eq.stderr | 4 +- .../ui/suggestions/option-content-move.fixed | 2 - tests/ui/suggestions/option-content-move.rs | 2 - .../ui/suggestions/option-content-move.stderr | 4 +- tests/ui/traits/object/generics.rs | 1 - 32 files changed, 89 insertions(+), 273 deletions(-) delete mode 100644 tests/ui/lint/dead-code/unused-assoc-const.rs delete mode 100644 tests/ui/lint/dead-code/unused-assoc-const.stderr delete mode 100644 tests/ui/lint/dead-code/unused-pub-struct.rs delete mode 100644 tests/ui/lint/dead-code/unused-pub-struct.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 90f436a6fc1a..7ae5c9040042 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -17,7 +17,7 @@ use rustc_hir::{Node, PatKind, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, AssocItemContainer, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::lint; use rustc_session::lint::builtin::DEAD_CODE; @@ -44,63 +44,16 @@ fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { ) } -struct Publicness { - ty_is_public: bool, - ty_and_all_fields_are_public: bool, -} - -impl Publicness { - fn new(ty_is_public: bool, ty_and_all_fields_are_public: bool) -> Self { - Self { ty_is_public, ty_and_all_fields_are_public } - } -} - -fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool { - // treat PhantomData and positional ZST as public, - // we don't want to lint types which only have them, - // cause it's a common way to use such types to check things like well-formedness - tcx.adt_def(id).all_fields().all(|field| { - let field_type = tcx.type_of(field.did).instantiate_identity(); - if field_type.is_phantom_data() { - return true; - } - let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit()); - if is_positional - && tcx - .layout_of(tcx.param_env(field.did).and(field_type)) - .map_or(true, |layout| layout.is_zst()) - { - return true; - } - field.vis.is_public() - }) -} - -/// check struct and its fields are public or not, -/// for enum and union, just check they are public, -/// and doesn't solve types like &T for now, just skip them -fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> Publicness { +fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> bool { if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind && let Res::Def(def_kind, def_id) = path.res && def_id.is_local() + && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union) { - return match def_kind { - DefKind::Enum | DefKind::Union => { - let ty_is_public = tcx.visibility(def_id).is_public(); - Publicness::new(ty_is_public, ty_is_public) - } - DefKind::Struct => { - let ty_is_public = tcx.visibility(def_id).is_public(); - Publicness::new( - ty_is_public, - ty_is_public && struct_all_fields_are_public(tcx, def_id), - ) - } - _ => Publicness::new(true, true), - }; + tcx.visibility(def_id).is_public() + } else { + true } - - Publicness::new(true, true) } /// Determine if a work from the worklist is coming from a `#[allow]` @@ -499,11 +452,9 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { { if !matches!(trait_item.kind, hir::TraitItemKind::Type(..)) && !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty) - .ty_and_all_fields_are_public { - // skip impl-items of non pure pub ty, - // cause we don't know the ty is constructed or not, - // check these later in `solve_rest_impl_items` + // skip methods of private ty, + // they would be solved in `solve_rest_impl_items` continue; } @@ -584,21 +535,22 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { && let Some(local_def_id) = def_id.as_local() && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union) { + if self.tcx.visibility(impl_item_id).is_public() { + // for the public method, we don't know the trait item is used or not, + // so we mark the method live if the self is used + return self.live_symbols.contains(&local_def_id); + } + if let Some(trait_item_id) = self.tcx.associated_item(impl_item_id).trait_item_def_id && let Some(local_id) = trait_item_id.as_local() { - // for the local impl item, we can know the trait item is used or not, + // for the private method, we can know the trait item is used or not, // so we mark the method live if the self is used and the trait item is used - self.live_symbols.contains(&local_id) && self.live_symbols.contains(&local_def_id) - } else { - // for the foreign method and inherent pub method, - // we don't know the trait item or the method is used or not, - // so we mark the method live if the self is used - self.live_symbols.contains(&local_def_id) + return self.live_symbols.contains(&local_id) + && self.live_symbols.contains(&local_def_id); } - } else { - false } + false } } @@ -820,9 +772,7 @@ fn check_item<'tcx>( .iter() .filter_map(|def_id| def_id.as_local()); - let self_ty = tcx.hir().item(id).expect_impl().self_ty; - let Publicness { ty_is_public, ty_and_all_fields_are_public } = - ty_ref_to_pub_struct(tcx, self_ty); + let ty_is_pub = ty_ref_to_pub_struct(tcx, tcx.hir().item(id).expect_impl().self_ty); // And we access the Map here to get HirId from LocalDefId for local_def_id in local_def_ids { @@ -838,20 +788,18 @@ fn check_item<'tcx>( // for trait impl blocks, // mark the method live if the self_ty is public, // or the method is public and may construct self - if of_trait && matches!(tcx.def_kind(local_def_id), DefKind::AssocTy) - || tcx.visibility(local_def_id).is_public() - && (ty_and_all_fields_are_public || may_construct_self) + if of_trait + && (!matches!(tcx.def_kind(local_def_id), DefKind::AssocFn) + || tcx.visibility(local_def_id).is_public() + && (ty_is_pub || may_construct_self)) { - // if the impl item is public, - // and the ty may be constructed or can be constructed in foreign crates, - // mark the impl item live worklist.push((local_def_id, ComesFromAllowExpect::No)); } else if let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, local_def_id) { worklist.push((local_def_id, comes_from_allow)); - } else if of_trait || tcx.visibility(local_def_id).is_public() && ty_is_public { - // private impl items of traits || public impl items not constructs self + } else if of_trait { + // private method || public method not constructs self unsolved_impl_items.push((id, local_def_id)); } } @@ -918,14 +866,6 @@ fn create_and_seed_worklist( effective_vis .is_public_at_level(Level::Reachable) .then_some(id) - .filter(|&id| - // checks impls, impl-items and pub structs with all public fields later - match tcx.def_kind(id) { - DefKind::Impl { .. } => false, - DefKind::AssocConst | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), - DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()), - _ => true - }) .map(|id| (id, ComesFromAllowExpect::No)) }) // Seed entry point @@ -1250,15 +1190,10 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { || (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id)) { for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) { - // We have diagnosed unused assoc consts and fns in traits + // We have diagnosed unused methods in traits if matches!(def_kind, DefKind::Impl { of_trait: true }) - && matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocFn) - // skip unused public inherent methods, - // cause we have diagnosed unconstructed struct - || matches!(def_kind, DefKind::Impl { of_trait: false }) - && tcx.visibility(def_id).is_public() - && ty_ref_to_pub_struct(tcx, tcx.hir().item(item).expect_impl().self_ty).ty_is_public - || def_kind == DefKind::Trait && tcx.def_kind(def_id) == DefKind::AssocTy + && tcx.def_kind(def_id) == DefKind::AssocFn + || def_kind == DefKind::Trait && tcx.def_kind(def_id) != DefKind::AssocFn { continue; } diff --git a/tests/codegen-units/item-collection/generic-impl.rs b/tests/codegen-units/item-collection/generic-impl.rs index b4cd99272b15..23d09e0d8af3 100644 --- a/tests/codegen-units/item-collection/generic-impl.rs +++ b/tests/codegen-units/item-collection/generic-impl.rs @@ -22,16 +22,16 @@ impl Struct { } } -pub struct _LifeTimeOnly<'a> { +pub struct LifeTimeOnly<'a> { _a: &'a u32, } -impl<'a> _LifeTimeOnly<'a> { - //~ MONO_ITEM fn _LifeTimeOnly::<'_>::foo +impl<'a> LifeTimeOnly<'a> { + //~ MONO_ITEM fn LifeTimeOnly::<'_>::foo pub fn foo(&self) {} - //~ MONO_ITEM fn _LifeTimeOnly::<'_>::bar + //~ MONO_ITEM fn LifeTimeOnly::<'_>::bar pub fn bar(&'a self) {} - //~ MONO_ITEM fn _LifeTimeOnly::<'_>::baz + //~ MONO_ITEM fn LifeTimeOnly::<'_>::baz pub fn baz<'b>(&'b self) {} pub fn non_instantiated(&self) {} diff --git a/tests/codegen-units/item-collection/overloaded-operators.rs b/tests/codegen-units/item-collection/overloaded-operators.rs index e00e22dbab99..69b55695d3d3 100644 --- a/tests/codegen-units/item-collection/overloaded-operators.rs +++ b/tests/codegen-units/item-collection/overloaded-operators.rs @@ -5,44 +5,44 @@ use std::ops::{Add, Deref, Index, IndexMut}; -pub struct _Indexable { +pub struct Indexable { data: [u8; 3], } -impl Index for _Indexable { +impl Index for Indexable { type Output = u8; - //~ MONO_ITEM fn <_Indexable as std::ops::Index>::index + //~ MONO_ITEM fn >::index fn index(&self, index: usize) -> &Self::Output { if index >= 3 { &self.data[0] } else { &self.data[index] } } } -impl IndexMut for _Indexable { - //~ MONO_ITEM fn <_Indexable as std::ops::IndexMut>::index_mut +impl IndexMut for Indexable { + //~ MONO_ITEM fn >::index_mut fn index_mut(&mut self, index: usize) -> &mut Self::Output { if index >= 3 { &mut self.data[0] } else { &mut self.data[index] } } } -//~ MONO_ITEM fn <_Equatable as std::cmp::PartialEq>::eq -//~ MONO_ITEM fn <_Equatable as std::cmp::PartialEq>::ne +//~ MONO_ITEM fn ::eq +//~ MONO_ITEM fn ::ne #[derive(PartialEq)] -pub struct _Equatable(u32); +pub struct Equatable(u32); -impl Add for _Equatable { +impl Add for Equatable { type Output = u32; - //~ MONO_ITEM fn <_Equatable as std::ops::Add>::add + //~ MONO_ITEM fn >::add fn add(self, rhs: u32) -> u32 { self.0 + rhs } } -impl Deref for _Equatable { +impl Deref for Equatable { type Target = u32; - //~ MONO_ITEM fn <_Equatable as std::ops::Deref>::deref + //~ MONO_ITEM fn ::deref fn deref(&self) -> &Self::Target { &self.0 } diff --git a/tests/ui/coherence/re-rebalance-coherence.rs b/tests/ui/coherence/re-rebalance-coherence.rs index 5383a634617f..9c176d5b1b12 100644 --- a/tests/ui/coherence/re-rebalance-coherence.rs +++ b/tests/ui/coherence/re-rebalance-coherence.rs @@ -4,7 +4,6 @@ extern crate re_rebalance_coherence_lib as lib; use lib::*; -#[allow(dead_code)] struct Oracle; impl Backend for Oracle {} impl<'a, T:'a, Tab> QueryFragment for BatchInsert<'a, T, Tab> {} diff --git a/tests/ui/const-generics/defaults/repr-c-issue-82792.rs b/tests/ui/const-generics/defaults/repr-c-issue-82792.rs index 4bf2fa761eae..c23187598bce 100644 --- a/tests/ui/const-generics/defaults/repr-c-issue-82792.rs +++ b/tests/ui/const-generics/defaults/repr-c-issue-82792.rs @@ -2,7 +2,6 @@ //@ run-pass -#[allow(dead_code)] #[repr(C)] pub struct Loaf { head: [T; N], diff --git a/tests/ui/const-generics/generic_const_exprs/associated-consts.rs b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs index 50a6102c605a..5d2198f50ad9 100644 --- a/tests/ui/const-generics/generic_const_exprs/associated-consts.rs +++ b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs @@ -16,8 +16,7 @@ impl BlockCipher for BarCipher { const BLOCK_SIZE: usize = 32; } -#[allow(dead_code)] -pub struct Block(C); +pub struct Block(#[allow(dead_code)] C); pub fn test() where diff --git a/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs b/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs index 35c41ae46152..419d605d0c87 100644 --- a/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs +++ b/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs @@ -6,7 +6,6 @@ use std::mem::MaybeUninit; -#[allow(dead_code)] #[repr(transparent)] pub struct MaybeUninitWrapper(MaybeUninit<[u64; N]>); diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs index 885dacc727af..6ab1fb7b039b 100644 --- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs +++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs @@ -1,9 +1,9 @@ #![forbid(dead_code)] #[derive(Debug)] -pub struct Whatever { //~ ERROR struct `Whatever` is never constructed +pub struct Whatever { pub field0: (), - field1: (), + field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read field2: (), field3: (), field4: (), diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr index e10d28ad03a4..e9b757b6bae7 100644 --- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr +++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr @@ -1,9 +1,19 @@ -error: struct `Whatever` is never constructed - --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:4:12 +error: fields `field1`, `field2`, `field3`, and `field4` are never read + --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:6:5 | LL | pub struct Whatever { - | ^^^^^^^^ + | -------- fields in this struct +LL | pub field0: (), +LL | field1: (), + | ^^^^^^ +LL | field2: (), + | ^^^^^^ +LL | field3: (), + | ^^^^^^ +LL | field4: (), + | ^^^^^^ | + = note: `Whatever` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis note: the lint level is defined here --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11 | diff --git a/tests/ui/issues/issue-5708.rs b/tests/ui/issues/issue-5708.rs index 89ea9fbdcd8f..ce9ef78ffcd9 100644 --- a/tests/ui/issues/issue-5708.rs +++ b/tests/ui/issues/issue-5708.rs @@ -44,7 +44,6 @@ pub trait MyTrait { fn dummy(&self, t: T) -> T { panic!() } } -#[allow(dead_code)] pub struct MyContainer<'a, T:'a> { foos: Vec<&'a (dyn MyTrait+'a)> , } diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.rs b/tests/ui/lint/dead-code/lint-dead-code-1.rs index 3386dfa47470..ddcafedf7bc5 100644 --- a/tests/ui/lint/dead-code/lint-dead-code-1.rs +++ b/tests/ui/lint/dead-code/lint-dead-code-1.rs @@ -46,10 +46,11 @@ struct SemiUsedStruct; impl SemiUsedStruct { fn la_la_la() {} } -struct StructUsedAsField; //~ ERROR struct `StructUsedAsField` is never constructed +struct StructUsedAsField; pub struct StructUsedInEnum; struct StructUsedInGeneric; -pub struct PubStruct2 { //~ ERROR struct `PubStruct2` is never constructed +pub struct PubStruct2 { + #[allow(dead_code)] struct_used_as_field: *const StructUsedAsField } diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.stderr b/tests/ui/lint/dead-code/lint-dead-code-1.stderr index b0163df8855c..eb728b5b9305 100644 --- a/tests/ui/lint/dead-code/lint-dead-code-1.stderr +++ b/tests/ui/lint/dead-code/lint-dead-code-1.stderr @@ -22,26 +22,14 @@ error: struct `PrivStruct` is never constructed LL | struct PrivStruct; | ^^^^^^^^^^ -error: struct `StructUsedAsField` is never constructed - --> $DIR/lint-dead-code-1.rs:49:8 - | -LL | struct StructUsedAsField; - | ^^^^^^^^^^^^^^^^^ - -error: struct `PubStruct2` is never constructed - --> $DIR/lint-dead-code-1.rs:52:12 - | -LL | pub struct PubStruct2 { - | ^^^^^^^^^^ - error: enum `priv_enum` is never used - --> $DIR/lint-dead-code-1.rs:63:6 + --> $DIR/lint-dead-code-1.rs:64:6 | LL | enum priv_enum { foo2, bar2 } | ^^^^^^^^^ error: variant `bar3` is never constructed - --> $DIR/lint-dead-code-1.rs:66:5 + --> $DIR/lint-dead-code-1.rs:67:5 | LL | enum used_enum { | --------- variant in this enum @@ -50,25 +38,25 @@ LL | bar3 | ^^^^ error: function `priv_fn` is never used - --> $DIR/lint-dead-code-1.rs:87:4 + --> $DIR/lint-dead-code-1.rs:88:4 | LL | fn priv_fn() { | ^^^^^^^ error: function `foo` is never used - --> $DIR/lint-dead-code-1.rs:92:4 + --> $DIR/lint-dead-code-1.rs:93:4 | LL | fn foo() { | ^^^ error: function `bar` is never used - --> $DIR/lint-dead-code-1.rs:97:4 + --> $DIR/lint-dead-code-1.rs:98:4 | LL | fn bar() { | ^^^ error: function `baz` is never used - --> $DIR/lint-dead-code-1.rs:101:4 + --> $DIR/lint-dead-code-1.rs:102:4 | LL | fn baz() -> impl Copy { | ^^^ @@ -79,5 +67,5 @@ error: struct `Bar` is never constructed LL | pub struct Bar; | ^^^ -error: aborting due to 12 previous errors +error: aborting due to 10 previous errors diff --git a/tests/ui/lint/dead-code/unused-assoc-const.rs b/tests/ui/lint/dead-code/unused-assoc-const.rs deleted file mode 100644 index 36e8315ad360..000000000000 --- a/tests/ui/lint/dead-code/unused-assoc-const.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![deny(dead_code)] - -trait Trait { - const UNUSED_CONST: i32; //~ ERROR associated constant `UNUSED_CONST` is never used - const USED_CONST: i32; - - fn foo(&self) {} -} - -pub struct T(()); - -impl Trait for T { - const UNUSED_CONST: i32 = 0; - const USED_CONST: i32 = 1; -} - -fn main() { - T(()).foo(); - T::USED_CONST; -} diff --git a/tests/ui/lint/dead-code/unused-assoc-const.stderr b/tests/ui/lint/dead-code/unused-assoc-const.stderr deleted file mode 100644 index 78296d706638..000000000000 --- a/tests/ui/lint/dead-code/unused-assoc-const.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: associated constant `UNUSED_CONST` is never used - --> $DIR/unused-assoc-const.rs:4:11 - | -LL | trait Trait { - | ----- associated constant in this trait -LL | const UNUSED_CONST: i32; - | ^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/unused-assoc-const.rs:1:9 - | -LL | #![deny(dead_code)] - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/lint/dead-code/unused-pub-struct.rs b/tests/ui/lint/dead-code/unused-pub-struct.rs deleted file mode 100644 index aaf4dd612de4..000000000000 --- a/tests/ui/lint/dead-code/unused-pub-struct.rs +++ /dev/null @@ -1,48 +0,0 @@ -#![deny(dead_code)] - -pub struct NotLint1(()); -pub struct NotLint2(std::marker::PhantomData); - -pub struct NeverConstructed(i32); //~ ERROR struct `NeverConstructed` is never constructed - -impl NeverConstructed { - pub fn not_construct_self(&self) {} -} - -impl Clone for NeverConstructed { - fn clone(&self) -> NeverConstructed { - NeverConstructed(0) - } -} - -pub trait Trait { - fn not_construct_self(&self); -} - -impl Trait for NeverConstructed { - fn not_construct_self(&self) { - self.0; - } -} - -pub struct Constructed(i32); - -impl Constructed { - pub fn construct_self() -> Self { - Constructed(0) - } -} - -impl Clone for Constructed { - fn clone(&self) -> Constructed { - Constructed(0) - } -} - -impl Trait for Constructed { - fn not_construct_self(&self) { - self.0; - } -} - -fn main() {} diff --git a/tests/ui/lint/dead-code/unused-pub-struct.stderr b/tests/ui/lint/dead-code/unused-pub-struct.stderr deleted file mode 100644 index 3667ddb97bd3..000000000000 --- a/tests/ui/lint/dead-code/unused-pub-struct.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: struct `NeverConstructed` is never constructed - --> $DIR/unused-pub-struct.rs:6:12 - | -LL | pub struct NeverConstructed(i32); - | ^^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/unused-pub-struct.rs:1:9 - | -LL | #![deny(dead_code)] - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed index e9c89807fa56..a851300a9828 100644 --- a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed +++ b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed @@ -1,8 +1,7 @@ // Regression test for issues #100790 and #106439. //@ run-rustfix -#[allow(dead_code)] -pub struct Example(usize) +pub struct Example(#[allow(dead_code)] usize) where (): Sized; //~^^^ ERROR where clauses are not allowed before tuple struct bodies diff --git a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs index 3bd0f51ec2cb..10f435859f15 100644 --- a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs +++ b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs @@ -1,11 +1,10 @@ // Regression test for issues #100790 and #106439. //@ run-rustfix -#[allow(dead_code)] pub struct Example where (): Sized, -(usize); +(#[allow(dead_code)] usize); //~^^^ ERROR where clauses are not allowed before tuple struct bodies struct _Demo diff --git a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr index 77eafa6bea33..ddbf237e8662 100644 --- a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr +++ b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr @@ -1,23 +1,23 @@ error: where clauses are not allowed before tuple struct bodies - --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:6:1 + --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:5:1 | LL | pub struct Example | ------- while parsing this tuple struct LL | / where LL | | (): Sized, | |______________^ unexpected where clause -LL | (usize); - | ------- the struct body +LL | (#[allow(dead_code)] usize); + | --------------------------- the struct body | help: move the body before the where clause | -LL ~ pub struct Example(usize) +LL ~ pub struct Example(#[allow(dead_code)] usize) LL | where LL ~ (): Sized; | error: where clauses are not allowed before tuple struct bodies - --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:12:1 + --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:11:1 | LL | struct _Demo | ----- while parsing this tuple struct diff --git a/tests/ui/pub/pub-ident-struct-4.fixed b/tests/ui/pub/pub-ident-struct-4.fixed index a62ece43eced..5fedbb724374 100644 --- a/tests/ui/pub/pub-ident-struct-4.fixed +++ b/tests/ui/pub/pub-ident-struct-4.fixed @@ -1,7 +1,6 @@ //@ run-rustfix -#[allow(dead_code)] -pub struct T(String); +pub struct T(#[allow(dead_code)] String); //~^ ERROR missing `struct` for struct definition fn main() {} diff --git a/tests/ui/pub/pub-ident-struct-4.rs b/tests/ui/pub/pub-ident-struct-4.rs index 0d56a31beaf1..5c721c25a781 100644 --- a/tests/ui/pub/pub-ident-struct-4.rs +++ b/tests/ui/pub/pub-ident-struct-4.rs @@ -1,7 +1,6 @@ //@ run-rustfix -#[allow(dead_code)] -pub T(String); +pub T(#[allow(dead_code)] String); //~^ ERROR missing `struct` for struct definition fn main() {} diff --git a/tests/ui/pub/pub-ident-struct-4.stderr b/tests/ui/pub/pub-ident-struct-4.stderr index d3072464e05c..e04fff1ebf4a 100644 --- a/tests/ui/pub/pub-ident-struct-4.stderr +++ b/tests/ui/pub/pub-ident-struct-4.stderr @@ -1,12 +1,12 @@ error: missing `struct` for struct definition - --> $DIR/pub-ident-struct-4.rs:4:1 + --> $DIR/pub-ident-struct-4.rs:3:4 | -LL | pub T(String); - | ^^^^^ +LL | pub T(#[allow(dead_code)] String); + | ^ | help: add `struct` here to parse `T` as a struct | -LL | pub struct T(String); +LL | pub struct T(#[allow(dead_code)] String); | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-issue-21422.rs b/tests/ui/regions/regions-issue-21422.rs index 67852a6f5de0..54beed9b3ac2 100644 --- a/tests/ui/regions/regions-issue-21422.rs +++ b/tests/ui/regions/regions-issue-21422.rs @@ -5,7 +5,6 @@ //@ pretty-expanded FIXME #23616 -#[allow(dead_code)] pub struct P<'a> { _ptr: *const &'a u8, } diff --git a/tests/ui/structs-enums/newtype-struct-with-dtor.rs b/tests/ui/structs-enums/newtype-struct-with-dtor.rs index 16439a7fedd3..19672e41c9a3 100644 --- a/tests/ui/structs-enums/newtype-struct-with-dtor.rs +++ b/tests/ui/structs-enums/newtype-struct-with-dtor.rs @@ -3,10 +3,8 @@ #![allow(unused_variables)] //@ pretty-expanded FIXME #23616 -#[allow(dead_code)] pub struct Fd(u32); -#[allow(dead_code)] fn foo(a: u32) {} impl Drop for Fd { diff --git a/tests/ui/structs-enums/uninstantiable-struct.rs b/tests/ui/structs-enums/uninstantiable-struct.rs index 1074dbcd6e6b..97bc7d8414e7 100644 --- a/tests/ui/structs-enums/uninstantiable-struct.rs +++ b/tests/ui/structs-enums/uninstantiable-struct.rs @@ -1,5 +1,4 @@ //@ run-pass -#[allow(dead_code)] -pub struct Z(&'static Z); +pub struct Z(#[allow(dead_code)] &'static Z); pub fn main() {} diff --git a/tests/ui/suggestions/derive-clone-for-eq.fixed b/tests/ui/suggestions/derive-clone-for-eq.fixed index cf800c6e47d8..4dc362f94787 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.fixed +++ b/tests/ui/suggestions/derive-clone-for-eq.fixed @@ -1,7 +1,6 @@ //@ run-rustfix // https://github.com/rust-lang/rust/issues/79076 -#[allow(dead_code)] #[derive(Clone, Eq)] //~ ERROR [E0277] pub struct Struct(T); diff --git a/tests/ui/suggestions/derive-clone-for-eq.rs b/tests/ui/suggestions/derive-clone-for-eq.rs index 84736426bac0..b3635000f165 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.rs +++ b/tests/ui/suggestions/derive-clone-for-eq.rs @@ -1,7 +1,6 @@ //@ run-rustfix // https://github.com/rust-lang/rust/issues/79076 -#[allow(dead_code)] #[derive(Clone, Eq)] //~ ERROR [E0277] pub struct Struct(T); diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr index 54670fbffcfb..6fae6e1316df 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.stderr +++ b/tests/ui/suggestions/derive-clone-for-eq.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/derive-clone-for-eq.rs:5:17 + --> $DIR/derive-clone-for-eq.rs:4:17 | LL | #[derive(Clone, Eq)] | ^^ the trait `Clone` is not implemented for `T`, which is required by `Struct: PartialEq` | note: required for `Struct` to implement `PartialEq` - --> $DIR/derive-clone-for-eq.rs:8:19 + --> $DIR/derive-clone-for-eq.rs:7:19 | LL | impl PartialEq for Struct | ----- ^^^^^^^^^^^^ ^^^^^^^^^ diff --git a/tests/ui/suggestions/option-content-move.fixed b/tests/ui/suggestions/option-content-move.fixed index ef07d55871e7..4a5a9483c20c 100644 --- a/tests/ui/suggestions/option-content-move.fixed +++ b/tests/ui/suggestions/option-content-move.fixed @@ -1,5 +1,4 @@ //@ run-rustfix -#[allow(dead_code)] pub struct LipogramCorpora { selections: Vec<(char, Option)>, } @@ -18,7 +17,6 @@ impl LipogramCorpora { } } -#[allow(dead_code)] pub struct LipogramCorpora2 { selections: Vec<(char, Result)>, } diff --git a/tests/ui/suggestions/option-content-move.rs b/tests/ui/suggestions/option-content-move.rs index 5be6358fd6a5..90d05c743997 100644 --- a/tests/ui/suggestions/option-content-move.rs +++ b/tests/ui/suggestions/option-content-move.rs @@ -1,5 +1,4 @@ //@ run-rustfix -#[allow(dead_code)] pub struct LipogramCorpora { selections: Vec<(char, Option)>, } @@ -18,7 +17,6 @@ impl LipogramCorpora { } } -#[allow(dead_code)] pub struct LipogramCorpora2 { selections: Vec<(char, Result)>, } diff --git a/tests/ui/suggestions/option-content-move.stderr b/tests/ui/suggestions/option-content-move.stderr index b4ec5b180d21..a382a04344ae 100644 --- a/tests/ui/suggestions/option-content-move.stderr +++ b/tests/ui/suggestions/option-content-move.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `selection.1` which is behind a shared reference - --> $DIR/option-content-move.rs:11:20 + --> $DIR/option-content-move.rs:10:20 | LL | if selection.1.unwrap().contains(selection.0) { | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call @@ -19,7 +19,7 @@ LL | if selection.1.clone().unwrap().contains(selection.0) { | ++++++++ error[E0507]: cannot move out of `selection.1` which is behind a shared reference - --> $DIR/option-content-move.rs:30:20 + --> $DIR/option-content-move.rs:28:20 | LL | if selection.1.unwrap().contains(selection.0) { | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call diff --git a/tests/ui/traits/object/generics.rs b/tests/ui/traits/object/generics.rs index 0ae562c0d30a..462b0bc5bb77 100644 --- a/tests/ui/traits/object/generics.rs +++ b/tests/ui/traits/object/generics.rs @@ -7,7 +7,6 @@ pub trait Trait2 { fn doit(&self) -> A; } -#[allow(dead_code)] pub struct Impl { m1: marker::PhantomData<(A1,A2,A3)>, /* From cbd27db9a996661792bbbd1dde7ac476eded8340 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:16:33 -0400 Subject: [PATCH 55/62] Suppress new false-negatives that were masked by dead code analysis changes --- library/std/src/sys/pal/unix/pipe.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/std/src/sys/pal/unix/pipe.rs b/library/std/src/sys/pal/unix/pipe.rs index 8762af614f17..f0ebc767bada 100644 --- a/library/std/src/sys/pal/unix/pipe.rs +++ b/library/std/src/sys/pal/unix/pipe.rs @@ -47,6 +47,8 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { } impl AnonPipe { + #[allow(dead_code)] + // FIXME: This function seems legitimately unused. pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(Self) } @@ -85,6 +87,8 @@ impl AnonPipe { self.0.is_write_vectored() } + #[allow(dead_code)] + // FIXME: This function seems legitimately unused. pub fn as_file_desc(&self) -> &FileDesc { &self.0 } From a57b8b91dbcb1cc3768c0a2a2a0c4971ed01b2f0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:23:41 -0400 Subject: [PATCH 56/62] Bless test fallout --- tests/ui-fulldeps/deriving-global.rs | 3 +++ tests/ui-fulldeps/deriving-hygiene.rs | 1 + .../unused-adt-impl-pub-trait-with-assoc-const.rs | 2 +- .../unused-adt-impl-pub-trait-with-assoc-const.stderr | 10 +++++++--- tests/ui/pub/pub-ident-struct-4.stderr | 4 ++-- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/tests/ui-fulldeps/deriving-global.rs b/tests/ui-fulldeps/deriving-global.rs index 7783010be441..0ba149c9ad65 100644 --- a/tests/ui-fulldeps/deriving-global.rs +++ b/tests/ui-fulldeps/deriving-global.rs @@ -17,18 +17,21 @@ mod submod { // if any of these are implemented without global calls for any // function calls, then being in a submodule will (correctly) // cause errors about unrecognised module `std` (or `extra`) + #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] enum A { A1(usize), A2(isize), } + #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] struct B { x: usize, y: isize, } + #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] struct C(usize, isize); } diff --git a/tests/ui-fulldeps/deriving-hygiene.rs b/tests/ui-fulldeps/deriving-hygiene.rs index a3a6f9e022eb..f948d6ac544e 100644 --- a/tests/ui-fulldeps/deriving-hygiene.rs +++ b/tests/ui-fulldeps/deriving-hygiene.rs @@ -20,6 +20,7 @@ pub const s: u8 = 1; pub const state: u8 = 1; pub const cmp: u8 = 1; +#[allow(dead_code)] #[derive(Ord, Eq, PartialOrd, PartialEq, Debug, Decodable, Encodable, Hash)] struct Foo {} diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs index bf2fc243e819..5b755d62a059 100644 --- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs +++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs @@ -1,7 +1,7 @@ #![deny(dead_code)] struct T1; //~ ERROR struct `T1` is never constructed -pub struct T2(i32); //~ ERROR struct `T2` is never constructed +pub struct T2(i32); //~ ERROR field `0` is never read struct T3; trait Trait1 { //~ ERROR trait `Trait1` is never used diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr index 174096d93988..2441a3f868dc 100644 --- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr +++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr @@ -10,11 +10,15 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: struct `T2` is never constructed - --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:12 +error: field `0` is never read + --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:15 | LL | pub struct T2(i32); - | ^^ + | -- ^^^ + | | + | field in this struct + | + = help: consider removing this field error: trait `Trait1` is never used --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:7:7 diff --git a/tests/ui/pub/pub-ident-struct-4.stderr b/tests/ui/pub/pub-ident-struct-4.stderr index e04fff1ebf4a..04965a1a7372 100644 --- a/tests/ui/pub/pub-ident-struct-4.stderr +++ b/tests/ui/pub/pub-ident-struct-4.stderr @@ -1,8 +1,8 @@ error: missing `struct` for struct definition - --> $DIR/pub-ident-struct-4.rs:3:4 + --> $DIR/pub-ident-struct-4.rs:3:1 | LL | pub T(#[allow(dead_code)] String); - | ^ + | ^^^^^ | help: add `struct` here to parse `T` as a struct | From 106cf7bec2019aa92912e1df1f4d045f6435bc9a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 3 Aug 2024 07:57:23 -0400 Subject: [PATCH 57/62] Remove another false-negative hidden by dead code changes --- src/bootstrap/src/core/build_steps/check.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 8b71300cf85e..7f7faf077d04 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -31,10 +31,6 @@ pub struct Std { } impl Std { - pub fn new(target: TargetSelection) -> Self { - Self::new_with_build_kind(target, None) - } - pub fn new_with_build_kind(target: TargetSelection, kind: Option) -> Self { Self { target, crates: vec![], override_build_kind: kind } } From b564b70d1cb3678108f9045e8fcf2627270d544b Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 3 Aug 2024 12:26:50 +0000 Subject: [PATCH 58/62] Update run-make/used to use `any_symbol_contains` --- tests/run-make/used/rmake.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/run-make/used/rmake.rs b/tests/run-make/used/rmake.rs index 56ef5c6b9cc0..eb5d026feda1 100644 --- a/tests/run-make/used/rmake.rs +++ b/tests/run-make/used/rmake.rs @@ -4,12 +4,11 @@ // It comes from #39987 which implements this RFC for the #[used] attribute: // https://rust-lang.github.io/rfcs/2386-used.html -//@ ignore-msvc - -use run_make_support::{cmd, rustc}; +use run_make_support::rustc; +use run_make_support::symbols::any_symbol_contains; fn main() { rustc().opt_level("3").emit("obj").input("used.rs").run(); - - cmd("nm").arg("used.o").run().assert_stdout_contains("FOO"); + assert!(any_symbol_contains("used.o", &["FOO"])); + assert!(!any_symbol_contains("used.o", &["BAR"])); } From eb451464a7557f2d8115183a92e6a300d20d75e5 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 3 Aug 2024 13:01:34 +0000 Subject: [PATCH 59/62] Remove BAR for run-make/used.rs --- tests/run-make/used/rmake.rs | 1 - tests/run-make/used/used.rs | 2 -- 2 files changed, 3 deletions(-) diff --git a/tests/run-make/used/rmake.rs b/tests/run-make/used/rmake.rs index eb5d026feda1..39f36b2eea8f 100644 --- a/tests/run-make/used/rmake.rs +++ b/tests/run-make/used/rmake.rs @@ -10,5 +10,4 @@ use run_make_support::symbols::any_symbol_contains; fn main() { rustc().opt_level("3").emit("obj").input("used.rs").run(); assert!(any_symbol_contains("used.o", &["FOO"])); - assert!(!any_symbol_contains("used.o", &["BAR"])); } diff --git a/tests/run-make/used/used.rs b/tests/run-make/used/used.rs index dca0a5e1167a..133f8121a8e9 100644 --- a/tests/run-make/used/used.rs +++ b/tests/run-make/used/used.rs @@ -2,5 +2,3 @@ #[used] static FOO: u32 = 0; - -static BAR: u32 = 0; From a3a09b488fde8fbe66c2be44491cdb87201d32a2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 3 Aug 2024 00:14:45 +0200 Subject: [PATCH 60/62] Simplify `body` usage in rustdoc --- src/librustdoc/html/static/js/main.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index e0ea234f9e71..ee771a40595a 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1115,8 +1115,7 @@ function preLoadCss(cssUrl) { wrapper.style.left = 0; wrapper.style.right = "auto"; wrapper.style.visibility = "hidden"; - const body = document.getElementsByTagName("body")[0]; - body.appendChild(wrapper); + document.body.appendChild(wrapper); const wrapperPos = wrapper.getBoundingClientRect(); // offset so that the arrow points at the center of the "(i)" const finalPos = pos.left + window.scrollX - wrapperPos.width + 24; @@ -1235,8 +1234,7 @@ function preLoadCss(cssUrl) { } window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE = false; } - const body = document.getElementsByTagName("body")[0]; - body.removeChild(window.CURRENT_TOOLTIP_ELEMENT); + document.body.removeChild(window.CURRENT_TOOLTIP_ELEMENT); clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT); window.CURRENT_TOOLTIP_ELEMENT = null; } @@ -1833,7 +1831,7 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm let elem = event.target; while (!hasClass(elem, "example-wrap")) { elem = elem.parentElement; - if (elem.tagName === "body" || hasClass(elem, "docblock")) { + if (elem === document.body || hasClass(elem, "docblock")) { return null; } } From 9e5c9c14c7fb3bc6032fff6e9031e641ed2a104a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Sun, 4 Aug 2024 01:42:14 +0000 Subject: [PATCH 61/62] tests: add regression test for incorrect "builtin attribute is checked" assertion ICE See . --- tests/ui/attributes/check-builtin-attr-ice.rs | 58 +++++++++++++++++++ .../attributes/check-builtin-attr-ice.stderr | 21 +++++++ 2 files changed, 79 insertions(+) create mode 100644 tests/ui/attributes/check-builtin-attr-ice.rs create mode 100644 tests/ui/attributes/check-builtin-attr-ice.stderr diff --git a/tests/ui/attributes/check-builtin-attr-ice.rs b/tests/ui/attributes/check-builtin-attr-ice.rs new file mode 100644 index 000000000000..9ef5890601f6 --- /dev/null +++ b/tests/ui/attributes/check-builtin-attr-ice.rs @@ -0,0 +1,58 @@ +//! Regression test for #128622. +//! +//! PR #128581 introduced an assertion that all builtin attributes are actually checked via +//! `CheckAttrVisitor` and aren't accidentally usable on completely unrelated HIR nodes. +//! Unfortunately, the check had correctness problems. +//! +//! The match on attribute path segments looked like +//! +//! ```rs,ignore +//! [sym::should_panic] => /* check is implemented */ +//! match BUILTIN_ATTRIBUTE_MAP.get(name) { +//! // checked below +//! Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) => {} +//! Some(_) => { +//! if !name.as_str().starts_with("rustc_") { +//! span_bug!( +//! attr.span, +//! "builtin attribute {name:?} not handled by `CheckAttrVisitor`" +//! ) +//! } +//! } +//! None => (), +//! } +//! ``` +//! +//! However, it failed to account for edge cases such as an attribute whose: +//! +//! 1. path segments *starts* with a builtin attribute such as `should_panic` +//! 2. which does not start with `rustc_`, and +//! 3. is also an `AttributeType::Normal` attribute upon registration with the builtin attribute map +//! +//! These conditions when all satisfied cause the span bug to be issued for e.g. +//! `#[should_panic::skip]` because the `[sym::should_panic]` arm is not matched (since it's +//! `[sym::should_panic, sym::skip]`). +//! +//! This test checks that the span bug is not fired for such cases. +//! +//! issue: rust-lang/rust#128622 + +// Notably, `should_panic` is a `AttributeType::Normal` attribute that is checked separately. + +struct Foo { + #[should_panic::skip] + //~^ ERROR failed to resolve + pub field: u8, + + #[should_panic::a::b::c] + //~^ ERROR failed to resolve + pub field2: u8, +} + +fn foo() {} + +fn main() { + #[deny::skip] + //~^ ERROR failed to resolve + foo(); +} diff --git a/tests/ui/attributes/check-builtin-attr-ice.stderr b/tests/ui/attributes/check-builtin-attr-ice.stderr new file mode 100644 index 000000000000..5a27da565a85 --- /dev/null +++ b/tests/ui/attributes/check-builtin-attr-ice.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `should_panic` + --> $DIR/check-builtin-attr-ice.rs:43:7 + | +LL | #[should_panic::skip] + | ^^^^^^^^^^^^ use of undeclared crate or module `should_panic` + +error[E0433]: failed to resolve: use of undeclared crate or module `should_panic` + --> $DIR/check-builtin-attr-ice.rs:47:7 + | +LL | #[should_panic::a::b::c] + | ^^^^^^^^^^^^ use of undeclared crate or module `should_panic` + +error[E0433]: failed to resolve: use of undeclared crate or module `deny` + --> $DIR/check-builtin-attr-ice.rs:55:7 + | +LL | #[deny::skip] + | ^^^^ use of undeclared crate or module `deny` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0433`. From 9d0eaa2ad78ca2995d4f2c4edb61f762ba79846b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Sun, 4 Aug 2024 01:39:05 +0000 Subject: [PATCH 62/62] check_attr: cover multi-segment attributes on specific check arms PR #128581 introduced an assertion that all builtin attributes are actually checked via `CheckAttrVisitor` and aren't accidentally usable on completely unrelated HIR nodes. Unfortunately, the check had correctness problems. The match on attribute path segments looked like ```rust,ignore [sym::should_panic] => /* check is implemented */ match BUILTIN_ATTRIBUTE_MAP.get(name) { // checked below Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) => {} Some(_) => { if !name.as_str().starts_with("rustc_") { span_bug!( attr.span, "builtin attribute {name:?} not handled by `CheckAttrVisitor`" ) } } None => (), } ``` However, it failed to account for edge cases such as an attribute whose: 1. path segments *starts* with a builtin attribute such as `should_panic` 2. which does not start with `rustc_`, and 3. is also an `AttributeType::Normal` attribute upon registration with the builtin attribute map These conditions when all satisfied cause the span bug to be issued for e.g. `#[should_panic::skip]` because the `[sym::should_panic]` arm is not matched (since it's `[sym::should_panic, sym::skip]`). See . --- compiler/rustc_passes/src/check_attr.rs | 144 ++++++++++++------------ 1 file changed, 73 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 755f67b3f4fe..a0d0d80b9572 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -116,130 +116,130 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { match attr.path().as_slice() { - [sym::diagnostic, sym::do_not_recommend] => { + [sym::diagnostic, sym::do_not_recommend, ..] => { self.check_do_not_recommend(attr.span, hir_id, target) } - [sym::diagnostic, sym::on_unimplemented] => { + [sym::diagnostic, sym::on_unimplemented, ..] => { self.check_diagnostic_on_unimplemented(attr.span, hir_id, target) } - [sym::inline] => self.check_inline(hir_id, attr, span, target), - [sym::coverage] => self.check_coverage(attr, span, target), - [sym::optimize] => self.check_optimize(hir_id, attr, target), - [sym::non_exhaustive] => self.check_non_exhaustive(hir_id, attr, span, target), - [sym::marker] => self.check_marker(hir_id, attr, span, target), - [sym::target_feature] => { + [sym::inline, ..] => self.check_inline(hir_id, attr, span, target), + [sym::coverage, ..] => self.check_coverage(attr, span, target), + [sym::optimize, ..] => self.check_optimize(hir_id, attr, target), + [sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target), + [sym::marker, ..] => self.check_marker(hir_id, attr, span, target), + [sym::target_feature, ..] => { self.check_target_feature(hir_id, attr, span, target, attrs) } - [sym::thread_local] => self.check_thread_local(attr, span, target), - [sym::track_caller] => { + [sym::thread_local, ..] => self.check_thread_local(attr, span, target), + [sym::track_caller, ..] => { self.check_track_caller(hir_id, attr.span, attrs, span, target) } - [sym::doc] => self.check_doc_attrs( + [sym::doc, ..] => self.check_doc_attrs( attr, hir_id, target, &mut specified_inline, &mut doc_aliases, ), - [sym::no_link] => self.check_no_link(hir_id, attr, span, target), - [sym::export_name] => self.check_export_name(hir_id, attr, span, target), - [sym::rustc_layout_scalar_valid_range_start] - | [sym::rustc_layout_scalar_valid_range_end] => { + [sym::no_link, ..] => self.check_no_link(hir_id, attr, span, target), + [sym::export_name, ..] => self.check_export_name(hir_id, attr, span, target), + [sym::rustc_layout_scalar_valid_range_start, ..] + | [sym::rustc_layout_scalar_valid_range_end, ..] => { self.check_rustc_layout_scalar_valid_range(attr, span, target) } - [sym::allow_internal_unstable] => { + [sym::allow_internal_unstable, ..] => { self.check_allow_internal_unstable(hir_id, attr, span, target, attrs) } - [sym::debugger_visualizer] => self.check_debugger_visualizer(attr, target), - [sym::rustc_allow_const_fn_unstable] => { + [sym::debugger_visualizer, ..] => self.check_debugger_visualizer(attr, target), + [sym::rustc_allow_const_fn_unstable, ..] => { self.check_rustc_allow_const_fn_unstable(hir_id, attr, span, target) } - [sym::rustc_std_internal_symbol] => { + [sym::rustc_std_internal_symbol, ..] => { self.check_rustc_std_internal_symbol(attr, span, target) } - [sym::naked] => self.check_naked(hir_id, attr, span, target, attrs), - [sym::rustc_never_returns_null_ptr] => { + [sym::naked, ..] => self.check_naked(hir_id, attr, span, target, attrs), + [sym::rustc_never_returns_null_ptr, ..] => { self.check_applied_to_fn_or_method(hir_id, attr, span, target) } - [sym::rustc_legacy_const_generics] => { + [sym::rustc_legacy_const_generics, ..] => { self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item) } - [sym::rustc_lint_query_instability] => { + [sym::rustc_lint_query_instability, ..] => { self.check_rustc_lint_query_instability(hir_id, attr, span, target) } - [sym::rustc_lint_diagnostics] => { + [sym::rustc_lint_diagnostics, ..] => { self.check_rustc_lint_diagnostics(hir_id, attr, span, target) } - [sym::rustc_lint_opt_ty] => self.check_rustc_lint_opt_ty(attr, span, target), - [sym::rustc_lint_opt_deny_field_access] => { + [sym::rustc_lint_opt_ty, ..] => self.check_rustc_lint_opt_ty(attr, span, target), + [sym::rustc_lint_opt_deny_field_access, ..] => { self.check_rustc_lint_opt_deny_field_access(attr, span, target) } - [sym::rustc_clean] - | [sym::rustc_dirty] - | [sym::rustc_if_this_changed] - | [sym::rustc_then_this_would_need] => self.check_rustc_dirty_clean(attr), - [sym::rustc_coinductive] - | [sym::rustc_must_implement_one_of] - | [sym::rustc_deny_explicit_impl] - | [sym::const_trait] => self.check_must_be_applied_to_trait(attr, span, target), - [sym::cmse_nonsecure_entry] => { + [sym::rustc_clean, ..] + | [sym::rustc_dirty, ..] + | [sym::rustc_if_this_changed, ..] + | [sym::rustc_then_this_would_need, ..] => self.check_rustc_dirty_clean(attr), + [sym::rustc_coinductive, ..] + | [sym::rustc_must_implement_one_of, ..] + | [sym::rustc_deny_explicit_impl, ..] + | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target), + [sym::cmse_nonsecure_entry, ..] => { self.check_cmse_nonsecure_entry(hir_id, attr, span, target) } - [sym::collapse_debuginfo] => self.check_collapse_debuginfo(attr, span, target), - [sym::must_not_suspend] => self.check_must_not_suspend(attr, span, target), - [sym::must_use] => self.check_must_use(hir_id, attr, target), - [sym::rustc_pass_by_value] => self.check_pass_by_value(attr, span, target), - [sym::rustc_allow_incoherent_impl] => { + [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target), + [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target), + [sym::must_use, ..] => self.check_must_use(hir_id, attr, target), + [sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target), + [sym::rustc_allow_incoherent_impl, ..] => { self.check_allow_incoherent_impl(attr, span, target) } - [sym::rustc_has_incoherent_inherent_impls] => { + [sym::rustc_has_incoherent_inherent_impls, ..] => { self.check_has_incoherent_inherent_impls(attr, span, target) } - [sym::ffi_pure] => self.check_ffi_pure(attr.span, attrs, target), - [sym::ffi_const] => self.check_ffi_const(attr.span, target), - [sym::rustc_const_unstable] - | [sym::rustc_const_stable] - | [sym::unstable] - | [sym::stable] - | [sym::rustc_allowed_through_unstable_modules] - | [sym::rustc_promotable] => self.check_stability_promotable(attr, target), - [sym::link_ordinal] => self.check_link_ordinal(attr, span, target), - [sym::rustc_confusables] => self.check_confusables(attr, target), - [sym::rustc_safe_intrinsic] => { + [sym::ffi_pure, ..] => self.check_ffi_pure(attr.span, attrs, target), + [sym::ffi_const, ..] => self.check_ffi_const(attr.span, target), + [sym::rustc_const_unstable, ..] + | [sym::rustc_const_stable, ..] + | [sym::unstable, ..] + | [sym::stable, ..] + | [sym::rustc_allowed_through_unstable_modules, ..] + | [sym::rustc_promotable, ..] => self.check_stability_promotable(attr, target), + [sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target), + [sym::rustc_confusables, ..] => self.check_confusables(attr, target), + [sym::rustc_safe_intrinsic, ..] => { self.check_rustc_safe_intrinsic(hir_id, attr, span, target) } - [sym::cold] => self.check_cold(hir_id, attr, span, target), - [sym::link] => self.check_link(hir_id, attr, span, target), - [sym::link_name] => self.check_link_name(hir_id, attr, span, target), - [sym::link_section] => self.check_link_section(hir_id, attr, span, target), - [sym::no_mangle] => self.check_no_mangle(hir_id, attr, span, target), - [sym::deprecated] => self.check_deprecated(hir_id, attr, span, target), - [sym::macro_use] | [sym::macro_escape] => { + [sym::cold, ..] => self.check_cold(hir_id, attr, span, target), + [sym::link, ..] => self.check_link(hir_id, attr, span, target), + [sym::link_name, ..] => self.check_link_name(hir_id, attr, span, target), + [sym::link_section, ..] => self.check_link_section(hir_id, attr, span, target), + [sym::no_mangle, ..] => self.check_no_mangle(hir_id, attr, span, target), + [sym::deprecated, ..] => self.check_deprecated(hir_id, attr, span, target), + [sym::macro_use, ..] | [sym::macro_escape, ..] => { self.check_macro_use(hir_id, attr, target) } - [sym::path] => self.check_generic_attr(hir_id, attr, target, Target::Mod), - [sym::macro_export] => self.check_macro_export(hir_id, attr, target), - [sym::ignore] | [sym::should_panic] => { + [sym::path, ..] => self.check_generic_attr(hir_id, attr, target, Target::Mod), + [sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target), + [sym::ignore, ..] | [sym::should_panic, ..] => { self.check_generic_attr(hir_id, attr, target, Target::Fn) } - [sym::automatically_derived] => { + [sym::automatically_derived, ..] => { self.check_generic_attr(hir_id, attr, target, Target::Impl) } - [sym::no_implicit_prelude] => { + [sym::no_implicit_prelude, ..] => { self.check_generic_attr(hir_id, attr, target, Target::Mod) } - [sym::rustc_object_lifetime_default] => self.check_object_lifetime_default(hir_id), - [sym::proc_macro] => { + [sym::rustc_object_lifetime_default, ..] => self.check_object_lifetime_default(hir_id), + [sym::proc_macro, ..] => { self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike) } - [sym::proc_macro_attribute] => { + [sym::proc_macro_attribute, ..] => { self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute); } - [sym::proc_macro_derive] => { + [sym::proc_macro_derive, ..] => { self.check_generic_attr(hir_id, attr, target, Target::Fn); self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } - [sym::coroutine] => { + [sym::coroutine, ..] => { self.check_coroutine(attr, target); } [ @@ -273,14 +273,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::default_lib_allocator | sym::start | sym::custom_mir, + .. ] => {} [name, ..] => { match BUILTIN_ATTRIBUTE_MAP.get(name) { // checked below Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) => {} Some(_) => { - // FIXME: differentiate between unstable and internal attributes just like we do with features instead - // of just accepting `rustc_` attributes by name. That should allow trimming the above list, too. + // FIXME: differentiate between unstable and internal attributes just + // like we do with features instead of just accepting `rustc_` + // attributes by name. That should allow trimming the above list, too. if !name.as_str().starts_with("rustc_") { span_bug!( attr.span,