From c56f49dc34f43568122f057d72f3472b3fcd4d8e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 28 Jul 2025 17:24:28 +0300 Subject: [PATCH 01/10] expand: Micro-optimize prelude injection Use `splice` to avoid shifting the other items twice. Put `extern crate std;` first so it's already resolved when we resolve `::std::prelude::rust_20XX`. --- compiler/rustc_builtin_macros/src/standard_library_imports.rs | 4 +--- tests/pretty/asm.pp | 4 ++-- tests/pretty/cast-lt.pp | 4 ++-- tests/pretty/dollar-crate.pp | 4 ++-- tests/pretty/expanded-and-path-remap-80832.pp | 4 ++-- tests/pretty/format-args-str-escape.pp | 4 ++-- tests/pretty/hir-delegation.pp | 4 ++-- tests/pretty/hir-fn-params.pp | 4 ++-- tests/pretty/hir-fn-variadic.pp | 4 ++-- tests/pretty/hir-if-else.pp | 4 ++-- tests/pretty/hir-lifetimes.pp | 4 ++-- tests/pretty/hir-pretty-attr.pp | 4 ++-- tests/pretty/hir-pretty-loop.pp | 4 ++-- tests/pretty/hir-struct-expr.pp | 4 ++-- tests/pretty/if-else.pp | 4 ++-- tests/pretty/issue-12590-c.pp | 4 ++-- tests/pretty/issue-4264.pp | 4 ++-- tests/pretty/issue-85089.pp | 4 ++-- tests/pretty/never-pattern.pp | 4 ++-- tests/pretty/pin-ergonomics-hir.pp | 4 ++-- tests/pretty/postfix-match/precedence.pp | 4 ++-- tests/pretty/shebang-at-top.pp | 4 ++-- tests/pretty/tests-are-sorted.pp | 4 ++-- tests/ui/asm/unpretty-expanded.stdout | 4 ++-- .../return-type-notation/unpretty-parenthesized.stdout | 4 ++-- tests/ui/codemap_tests/unicode.expanded.stdout | 4 ++-- tests/ui/const-generics/defaults/pretty-printing-ast.stdout | 4 ++-- tests/ui/deriving/built-in-proc-macro-scope.stdout | 4 ++-- tests/ui/deriving/deriving-all-codegen.stdout | 4 ++-- tests/ui/deriving/deriving-coerce-pointee-expanded.stdout | 4 ++-- tests/ui/deriving/proc-macro-attribute-mixing.stdout | 4 ++-- .../no_ice_for_partial_compiler_runs.stdout | 4 ++-- tests/ui/macros/genercs-in-path-with-prettry-hir.stdout | 4 ++-- .../non-consuming-methods-have-optimized-codegen.stdout | 4 ++-- tests/ui/match/issue-82392.stdout | 4 ++-- tests/ui/proc-macro/meta-macro-hygiene.stdout | 4 ++-- tests/ui/proc-macro/nonterminal-token-hygiene.stdout | 4 ++-- tests/ui/proc-macro/quote/debug.stdout | 4 ++-- tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout | 4 ++-- tests/ui/type-alias-impl-trait/issue-60662.stdout | 4 ++-- tests/ui/unpretty/bad-literal.stdout | 4 ++-- tests/ui/unpretty/debug-fmt-hir.stdout | 4 ++-- tests/ui/unpretty/deprecated-attr.stdout | 4 ++-- tests/ui/unpretty/diagnostic-attr.stdout | 4 ++-- tests/ui/unpretty/exhaustive-asm.expanded.stdout | 4 ++-- tests/ui/unpretty/exhaustive-asm.hir.stdout | 4 ++-- tests/ui/unpretty/exhaustive.expanded.stdout | 4 ++-- tests/ui/unpretty/exhaustive.hir.stdout | 4 ++-- tests/ui/unpretty/flattened-format-args.stdout | 4 ++-- tests/ui/unpretty/interpolation-expanded.stdout | 4 ++-- tests/ui/unpretty/let-else-hir.stdout | 4 ++-- tests/ui/unpretty/self-hir.stdout | 4 ++-- tests/ui/unpretty/unpretty-expr-fn-arg.stdout | 4 ++-- 53 files changed, 105 insertions(+), 107 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index 682e7c9b17ae8..2068b5ca54dd0 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -47,8 +47,6 @@ pub fn inject( ast::ItemKind::ExternCrate(None, Ident::new(name, ident_span)), ); - krate.items.insert(0, item); - let root = (edition == Edition2015).then_some(kw::PathRoot); let import_path = root @@ -75,6 +73,6 @@ pub fn inject( }), ); - krate.items.insert(0, use_item); + krate.items.splice(0..0, [item, use_item]); krate.items.len() - orig_num_items } diff --git a/tests/pretty/asm.pp b/tests/pretty/asm.pp index e6c9545f51ee4..dca28f99a37d5 100644 --- a/tests/pretty/asm.pp +++ b/tests/pretty/asm.pp @@ -1,9 +1,9 @@ #![feature(prelude_import)] #![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ pretty-mode:expanded //@ pp-exact:asm.pp //@ only-x86_64 diff --git a/tests/pretty/cast-lt.pp b/tests/pretty/cast-lt.pp index f6155c9d827b4..e82636edca7e5 100644 --- a/tests/pretty/cast-lt.pp +++ b/tests/pretty/cast-lt.pp @@ -1,9 +1,9 @@ #![feature(prelude_import)] #![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ pretty-compare-only //@ pretty-mode:expanded //@ pp-exact:cast-lt.pp diff --git a/tests/pretty/dollar-crate.pp b/tests/pretty/dollar-crate.pp index 561a9500aaaa0..31a55ec2bdaa8 100644 --- a/tests/pretty/dollar-crate.pp +++ b/tests/pretty/dollar-crate.pp @@ -1,9 +1,9 @@ #![feature(prelude_import)] #![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ pretty-compare-only //@ pretty-mode:expanded //@ pp-exact:dollar-crate.pp diff --git a/tests/pretty/expanded-and-path-remap-80832.pp b/tests/pretty/expanded-and-path-remap-80832.pp index 5b3922bb32946..6206498e4a2be 100644 --- a/tests/pretty/expanded-and-path-remap-80832.pp +++ b/tests/pretty/expanded-and-path-remap-80832.pp @@ -1,9 +1,9 @@ #![feature(prelude_import)] #![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; // Test for issue 80832 // //@ pretty-mode:expanded diff --git a/tests/pretty/format-args-str-escape.pp b/tests/pretty/format-args-str-escape.pp index 277b608475cfd..d0bd7cf0c72a3 100644 --- a/tests/pretty/format-args-str-escape.pp +++ b/tests/pretty/format-args-str-escape.pp @@ -1,9 +1,9 @@ #![feature(prelude_import)] #![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ pretty-compare-only //@ pretty-mode:expanded //@ pp-exact:format-args-str-escape.pp diff --git a/tests/pretty/hir-delegation.pp b/tests/pretty/hir-delegation.pp index c0d724cccb51e..f8ad02f2fccce 100644 --- a/tests/pretty/hir-delegation.pp +++ b/tests/pretty/hir-delegation.pp @@ -4,10 +4,10 @@ #![allow(incomplete_features)] #![feature(fn_delegation)] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; fn b(e: C) { } diff --git a/tests/pretty/hir-fn-params.pp b/tests/pretty/hir-fn-params.pp index cfb33cc93ebad..fb4ea0304e5a9 100644 --- a/tests/pretty/hir-fn-params.pp +++ b/tests/pretty/hir-fn-params.pp @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ pretty-compare-only //@ pretty-mode:hir //@ pp-exact:hir-fn-params.pp diff --git a/tests/pretty/hir-fn-variadic.pp b/tests/pretty/hir-fn-variadic.pp index 99919e7fc6b2d..c0f5b7069a2d7 100644 --- a/tests/pretty/hir-fn-variadic.pp +++ b/tests/pretty/hir-fn-variadic.pp @@ -3,10 +3,10 @@ //@ pp-exact:hir-fn-variadic.pp #![feature(c_variadic)] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; extern "C" { unsafe fn foo(x: i32, va1: ...); diff --git a/tests/pretty/hir-if-else.pp b/tests/pretty/hir-if-else.pp index 4bccde663eb53..af5d31b07cb18 100644 --- a/tests/pretty/hir-if-else.pp +++ b/tests/pretty/hir-if-else.pp @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ pretty-compare-only //@ pretty-mode:hir //@ pp-exact:hir-if-else.pp diff --git a/tests/pretty/hir-lifetimes.pp b/tests/pretty/hir-lifetimes.pp index 1bb2f17cdfb4a..00c052d3f7986 100644 --- a/tests/pretty/hir-lifetimes.pp +++ b/tests/pretty/hir-lifetimes.pp @@ -5,10 +5,10 @@ // This tests the pretty-printing of lifetimes in lots of ways. #![allow(unused)] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; struct Foo<'a> { x: &'a u32, diff --git a/tests/pretty/hir-pretty-attr.pp b/tests/pretty/hir-pretty-attr.pp index c780f8e3639fe..01bfe2c095476 100644 --- a/tests/pretty/hir-pretty-attr.pp +++ b/tests/pretty/hir-pretty-attr.pp @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ pretty-compare-only //@ pretty-mode:hir //@ pp-exact:hir-pretty-attr.pp diff --git a/tests/pretty/hir-pretty-loop.pp b/tests/pretty/hir-pretty-loop.pp index c07120273c909..a0830c5188ada 100644 --- a/tests/pretty/hir-pretty-loop.pp +++ b/tests/pretty/hir-pretty-loop.pp @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ pretty-compare-only //@ pretty-mode:hir //@ pp-exact:hir-pretty-loop.pp diff --git a/tests/pretty/hir-struct-expr.pp b/tests/pretty/hir-struct-expr.pp index 177eb5e8631fa..bb222dc2e5f10 100644 --- a/tests/pretty/hir-struct-expr.pp +++ b/tests/pretty/hir-struct-expr.pp @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ pretty-compare-only //@ pretty-mode:hir //@ pp-exact:hir-struct-expr.pp diff --git a/tests/pretty/if-else.pp b/tests/pretty/if-else.pp index d4ff02c544159..f29b693e571eb 100644 --- a/tests/pretty/if-else.pp +++ b/tests/pretty/if-else.pp @@ -1,9 +1,9 @@ #![feature(prelude_import)] #![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ pretty-compare-only //@ pretty-mode:expanded //@ pp-exact:if-else.pp diff --git a/tests/pretty/issue-12590-c.pp b/tests/pretty/issue-12590-c.pp index 691738a89ed86..0df095b0ee554 100644 --- a/tests/pretty/issue-12590-c.pp +++ b/tests/pretty/issue-12590-c.pp @@ -1,9 +1,9 @@ #![feature(prelude_import)] #![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ pretty-compare-only //@ pretty-mode:expanded //@ pp-exact:issue-12590-c.pp diff --git a/tests/pretty/issue-4264.pp b/tests/pretty/issue-4264.pp index f4b641335d1db..1344923f4c47c 100644 --- a/tests/pretty/issue-4264.pp +++ b/tests/pretty/issue-4264.pp @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ pretty-compare-only //@ pretty-mode:hir,typed //@ pp-exact:issue-4264.pp diff --git a/tests/pretty/issue-85089.pp b/tests/pretty/issue-85089.pp index 31c0f90bf27ee..28a85bdf4ad8b 100644 --- a/tests/pretty/issue-85089.pp +++ b/tests/pretty/issue-85089.pp @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; // Test to print lifetimes on HIR pretty-printing. //@ pretty-compare-only diff --git a/tests/pretty/never-pattern.pp b/tests/pretty/never-pattern.pp index 923ad9b82c7a7..1ce332ea50643 100644 --- a/tests/pretty/never-pattern.pp +++ b/tests/pretty/never-pattern.pp @@ -7,10 +7,10 @@ #![allow(incomplete_features)] #![feature(never_patterns)] #![feature(never_type)] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; fn f(x: Result) { _ = match x { Ok(x) => x, Err(!) , }; } diff --git a/tests/pretty/pin-ergonomics-hir.pp b/tests/pretty/pin-ergonomics-hir.pp index 58a1c62f712c3..beca5988017dc 100644 --- a/tests/pretty/pin-ergonomics-hir.pp +++ b/tests/pretty/pin-ergonomics-hir.pp @@ -4,10 +4,10 @@ #![feature(pin_ergonomics)] #![allow(dead_code, incomplete_features)] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; use std::pin::Pin; diff --git a/tests/pretty/postfix-match/precedence.pp b/tests/pretty/postfix-match/precedence.pp index 2052b445a2b30..b6ff45daea120 100644 --- a/tests/pretty/postfix-match/precedence.pp +++ b/tests/pretty/postfix-match/precedence.pp @@ -1,10 +1,10 @@ #![feature(prelude_import)] #![no_std] #![feature(postfix_match)] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; use std::ops::Add; diff --git a/tests/pretty/shebang-at-top.pp b/tests/pretty/shebang-at-top.pp index a279725263640..197def4a154b1 100644 --- a/tests/pretty/shebang-at-top.pp +++ b/tests/pretty/shebang-at-top.pp @@ -1,10 +1,10 @@ #!/usr/bin/env rust #![feature(prelude_import)] #![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ pretty-mode:expanded //@ pp-exact:shebang-at-top.pp //@ pretty-compare-only diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp index d6a2c0ff9796b..9e1566b2eff3b 100644 --- a/tests/pretty/tests-are-sorted.pp +++ b/tests/pretty/tests-are-sorted.pp @@ -1,9 +1,9 @@ #![feature(prelude_import)] #![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ compile-flags: --crate-type=lib --test --remap-path-prefix={{src-base}}/=/the/src/ --remap-path-prefix={{src-base}}\=/the/src/ //@ pretty-compare-only //@ pretty-mode:expanded diff --git a/tests/ui/asm/unpretty-expanded.stdout b/tests/ui/asm/unpretty-expanded.stdout index 7ba1702dfed8e..7678f6bc3450c 100644 --- a/tests/ui/asm/unpretty-expanded.stdout +++ b/tests/ui/asm/unpretty-expanded.stdout @@ -1,9 +1,9 @@ #![feature(prelude_import)] #![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ needs-asm-support //@ check-pass //@ compile-flags: -Zunpretty=expanded diff --git a/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stdout b/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stdout index 87667553837f5..7499df5be5da1 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stdout +++ b/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stdout @@ -1,8 +1,8 @@ #![feature(prelude_import)] -#[prelude_import] -use std::prelude::rust_2021::*; #[macro_use] extern crate std; +#[prelude_import] +use std::prelude::rust_2021::*; //@ edition: 2021 //@ compile-flags: -Zunpretty=expanded //@ check-pass diff --git a/tests/ui/codemap_tests/unicode.expanded.stdout b/tests/ui/codemap_tests/unicode.expanded.stdout index c88035de0449f..af375108b4780 100644 --- a/tests/ui/codemap_tests/unicode.expanded.stdout +++ b/tests/ui/codemap_tests/unicode.expanded.stdout @@ -1,9 +1,9 @@ #![feature(prelude_import)] #![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ revisions: normal expanded //@[expanded] check-pass //@[expanded]compile-flags: -Zunpretty=expanded diff --git a/tests/ui/const-generics/defaults/pretty-printing-ast.stdout b/tests/ui/const-generics/defaults/pretty-printing-ast.stdout index b6cb7fa09c880..030fcec9cf2a7 100644 --- a/tests/ui/const-generics/defaults/pretty-printing-ast.stdout +++ b/tests/ui/const-generics/defaults/pretty-printing-ast.stdout @@ -6,10 +6,10 @@ //@ edition: 2015 #![crate_type = "lib"] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; trait Foo {} diff --git a/tests/ui/deriving/built-in-proc-macro-scope.stdout b/tests/ui/deriving/built-in-proc-macro-scope.stdout index 2697618ab0035..4fbce5edb8194 100644 --- a/tests/ui/deriving/built-in-proc-macro-scope.stdout +++ b/tests/ui/deriving/built-in-proc-macro-scope.stdout @@ -6,10 +6,10 @@ //@ edition:2015 #![feature(derive_coerce_pointee)] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; #[macro_use] extern crate another_proc_macro; diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout index fa8f249373d30..0e4bfa30257df 100644 --- a/tests/ui/deriving/deriving-all-codegen.stdout +++ b/tests/ui/deriving/deriving-all-codegen.stdout @@ -17,10 +17,10 @@ #![crate_type = "lib"] #![allow(dead_code)] #![allow(deprecated)] -#[prelude_import] -use std::prelude::rust_2021::*; #[macro_use] extern crate std; +#[prelude_import] +use std::prelude::rust_2021::*; // Empty struct. struct Empty; diff --git a/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout b/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout index 84f8e9a3195a7..89300a5c6d0ca 100644 --- a/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout +++ b/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout @@ -4,10 +4,10 @@ //@ compile-flags: -Zunpretty=expanded //@ edition: 2015 #![feature(derive_coerce_pointee)] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; use std::marker::CoercePointee; pub trait MyTrait {} diff --git a/tests/ui/deriving/proc-macro-attribute-mixing.stdout b/tests/ui/deriving/proc-macro-attribute-mixing.stdout index faa9c0218a33c..b81110682d68f 100644 --- a/tests/ui/deriving/proc-macro-attribute-mixing.stdout +++ b/tests/ui/deriving/proc-macro-attribute-mixing.stdout @@ -12,10 +12,10 @@ //@ edition: 2015 #![feature(derive_coerce_pointee)] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; #[macro_use] extern crate another_proc_macro; diff --git a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout index d63abea92302a..80abac44ca84c 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout +++ b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout @@ -1,9 +1,9 @@ #![feature(prelude_import)] #![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; // This ensures that ICEs like rust#94953 don't happen //@ check-pass //@ compile-flags: -Z unpretty=expanded diff --git a/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout b/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout index 6b0300132b5f6..ba93384644d59 100644 --- a/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout +++ b/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ compile-flags: -Zunpretty=hir //@ edition: 2015 diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout index 33193c78334c9..e29655faabe58 100644 --- a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout @@ -5,10 +5,10 @@ //@ edition: 2015 #![feature(core_intrinsics, generic_assert)] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; fn arbitrary_consuming_method_for_demonstration_purposes() { let elem = 1i32; diff --git a/tests/ui/match/issue-82392.stdout b/tests/ui/match/issue-82392.stdout index 3efc964e053bc..d7eef0497392b 100644 --- a/tests/ui/match/issue-82392.stdout +++ b/tests/ui/match/issue-82392.stdout @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; // https://github.com/rust-lang/rust/issues/82329 //@ compile-flags: -Zunpretty=hir,typed //@ check-pass diff --git a/tests/ui/proc-macro/meta-macro-hygiene.stdout b/tests/ui/proc-macro/meta-macro-hygiene.stdout index 91d16eca1b0ad..452598c372c17 100644 --- a/tests/ui/proc-macro/meta-macro-hygiene.stdout +++ b/tests/ui/proc-macro/meta-macro-hygiene.stdout @@ -16,10 +16,10 @@ Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro // in the stdout #![no_std /* 0#0 */] -#[prelude_import /* 0#1 */] -use core /* 0#1 */::prelude /* 0#1 */::rust_2018 /* 0#1 */::*; #[macro_use /* 0#1 */] extern crate core /* 0#1 */; +#[prelude_import /* 0#1 */] +use core /* 0#1 */::prelude /* 0#1 */::rust_2018 /* 0#1 */::*; // Don't load unnecessary hygiene information from std extern crate std /* 0#0 */; diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index 63741326e3413..e10a5199f1793 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -36,10 +36,10 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ #![feature /* 0#0 */(decl_macro)] #![no_std /* 0#0 */] -#[prelude_import /* 0#1 */] -use ::core /* 0#1 */::prelude /* 0#1 */::rust_2015 /* 0#1 */::*; #[macro_use /* 0#1 */] extern crate core /* 0#2 */; +#[prelude_import /* 0#1 */] +use ::core /* 0#1 */::prelude /* 0#1 */::rust_2015 /* 0#1 */::*; // Don't load unnecessary hygiene information from std extern crate std /* 0#0 */; diff --git a/tests/ui/proc-macro/quote/debug.stdout b/tests/ui/proc-macro/quote/debug.stdout index 3acb472d9c0fb..77c52f02a33c1 100644 --- a/tests/ui/proc-macro/quote/debug.stdout +++ b/tests/ui/proc-macro/quote/debug.stdout @@ -12,10 +12,10 @@ #![feature(proc_macro_quote)] #![crate_type = "proc-macro"] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; extern crate proc_macro; diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout index e2e45ae94ea6e..66ba726fb9a49 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout @@ -1,9 +1,9 @@ #![feature(prelude_import)] #![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ check-pass //@ compile-flags: -Z unpretty=expanded //@ edition: 2015 diff --git a/tests/ui/type-alias-impl-trait/issue-60662.stdout b/tests/ui/type-alias-impl-trait/issue-60662.stdout index 52152a73affe8..7ad29c88bcfe5 100644 --- a/tests/ui/type-alias-impl-trait/issue-60662.stdout +++ b/tests/ui/type-alias-impl-trait/issue-60662.stdout @@ -3,10 +3,10 @@ //@ edition: 2015 #![feature(type_alias_impl_trait)] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; trait Animal { } diff --git a/tests/ui/unpretty/bad-literal.stdout b/tests/ui/unpretty/bad-literal.stdout index ba8467359cd6d..1f697aff27c9b 100644 --- a/tests/ui/unpretty/bad-literal.stdout +++ b/tests/ui/unpretty/bad-literal.stdout @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ compile-flags: -Zunpretty=hir //@ check-fail //@ edition: 2015 diff --git a/tests/ui/unpretty/debug-fmt-hir.stdout b/tests/ui/unpretty/debug-fmt-hir.stdout index 1d224c9e91ffe..9c79421e32aba 100644 --- a/tests/ui/unpretty/debug-fmt-hir.stdout +++ b/tests/ui/unpretty/debug-fmt-hir.stdout @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ compile-flags: -Zunpretty=hir //@ check-pass //@ edition: 2015 diff --git a/tests/ui/unpretty/deprecated-attr.stdout b/tests/ui/unpretty/deprecated-attr.stdout index 0abeef6f61e00..26cc74c11604d 100644 --- a/tests/ui/unpretty/deprecated-attr.stdout +++ b/tests/ui/unpretty/deprecated-attr.stdout @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ compile-flags: -Zunpretty=hir //@ check-pass //@ edition: 2015 diff --git a/tests/ui/unpretty/diagnostic-attr.stdout b/tests/ui/unpretty/diagnostic-attr.stdout index a1325c61ca730..4822cf4700b94 100644 --- a/tests/ui/unpretty/diagnostic-attr.stdout +++ b/tests/ui/unpretty/diagnostic-attr.stdout @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ compile-flags: -Zunpretty=hir //@ check-pass //@ edition: 2015 diff --git a/tests/ui/unpretty/exhaustive-asm.expanded.stdout b/tests/ui/unpretty/exhaustive-asm.expanded.stdout index 92829b0ab15bd..9a58e4c2877b1 100644 --- a/tests/ui/unpretty/exhaustive-asm.expanded.stdout +++ b/tests/ui/unpretty/exhaustive-asm.expanded.stdout @@ -1,8 +1,8 @@ #![feature(prelude_import)] -#[prelude_import] -use std::prelude::rust_2024::*; #[macro_use] extern crate std; +#[prelude_import] +use std::prelude::rust_2024::*; //@ revisions: expanded hir //@[expanded]compile-flags: -Zunpretty=expanded //@[expanded]check-pass diff --git a/tests/ui/unpretty/exhaustive-asm.hir.stdout b/tests/ui/unpretty/exhaustive-asm.hir.stdout index bbd846a884549..b33b38c2caba4 100644 --- a/tests/ui/unpretty/exhaustive-asm.hir.stdout +++ b/tests/ui/unpretty/exhaustive-asm.hir.stdout @@ -1,7 +1,7 @@ -#[prelude_import] -use std::prelude::rust_2024::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use std::prelude::rust_2024::*; //@ revisions: expanded hir //@[expanded]compile-flags: -Zunpretty=expanded //@[expanded]check-pass diff --git a/tests/ui/unpretty/exhaustive.expanded.stdout b/tests/ui/unpretty/exhaustive.expanded.stdout index 53ca3c8e39156..6b08f3e1cd76d 100644 --- a/tests/ui/unpretty/exhaustive.expanded.stdout +++ b/tests/ui/unpretty/exhaustive.expanded.stdout @@ -29,10 +29,10 @@ #![feature(try_blocks)] #![feature(yeet_expr)] #![allow(incomplete_features)] -#[prelude_import] -use std::prelude::rust_2024::*; #[macro_use] extern crate std; +#[prelude_import] +use std::prelude::rust_2024::*; #[prelude_import] use self::prelude::*; diff --git a/tests/ui/unpretty/exhaustive.hir.stdout b/tests/ui/unpretty/exhaustive.hir.stdout index 77807728c9d3e..9cfa65f580126 100644 --- a/tests/ui/unpretty/exhaustive.hir.stdout +++ b/tests/ui/unpretty/exhaustive.hir.stdout @@ -28,10 +28,10 @@ #![feature(try_blocks)] #![feature(yeet_expr)] #![allow(incomplete_features)] -#[prelude_import] -use std::prelude::rust_2024::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use std::prelude::rust_2024::*; #[prelude_import] use self::prelude::*; diff --git a/tests/ui/unpretty/flattened-format-args.stdout b/tests/ui/unpretty/flattened-format-args.stdout index 3cd0273466551..0792dc10e946b 100644 --- a/tests/ui/unpretty/flattened-format-args.stdout +++ b/tests/ui/unpretty/flattened-format-args.stdout @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ compile-flags: -Zunpretty=hir -Zflatten-format-args=yes //@ check-pass //@ edition: 2015 diff --git a/tests/ui/unpretty/interpolation-expanded.stdout b/tests/ui/unpretty/interpolation-expanded.stdout index d46b46b67f41f..7284a89e7a9b0 100644 --- a/tests/ui/unpretty/interpolation-expanded.stdout +++ b/tests/ui/unpretty/interpolation-expanded.stdout @@ -10,10 +10,10 @@ // synthesizing parentheses indiscriminately; only where necessary. #![feature(if_let_guard)] -#[prelude_import] -use std::prelude::rust_2024::*; #[macro_use] extern crate std; +#[prelude_import] +use std::prelude::rust_2024::*; macro_rules! expr { ($expr:expr) => { $expr }; } diff --git a/tests/ui/unpretty/let-else-hir.stdout b/tests/ui/unpretty/let-else-hir.stdout index a83790d8bee59..14270a5720274 100644 --- a/tests/ui/unpretty/let-else-hir.stdout +++ b/tests/ui/unpretty/let-else-hir.stdout @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ compile-flags: -Zunpretty=hir //@ check-pass //@ edition: 2015 diff --git a/tests/ui/unpretty/self-hir.stdout b/tests/ui/unpretty/self-hir.stdout index 1eafc3c8b46b6..b190565dcc472 100644 --- a/tests/ui/unpretty/self-hir.stdout +++ b/tests/ui/unpretty/self-hir.stdout @@ -1,7 +1,7 @@ -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; //@ compile-flags: -Zunpretty=hir //@ check-pass //@ edition: 2015 diff --git a/tests/ui/unpretty/unpretty-expr-fn-arg.stdout b/tests/ui/unpretty/unpretty-expr-fn-arg.stdout index e9fd2222a8d26..c04909a736136 100644 --- a/tests/ui/unpretty/unpretty-expr-fn-arg.stdout +++ b/tests/ui/unpretty/unpretty-expr-fn-arg.stdout @@ -8,10 +8,10 @@ //@ compile-flags: -Zunpretty=hir,typed //@ edition: 2015 #![allow(dead_code)] -#[prelude_import] -use ::std::prelude::rust_2015::*; #[attr = MacroUse {arguments: UseAll}] extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; fn main() ({ } as ()) From 2db97b2f7d877e5db2c892b42ed4deb8d829af14 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 28 Jul 2025 16:09:47 +0000 Subject: [PATCH 02/10] Account for .yield in illegal postfix operator message --- compiler/rustc_parse/src/parser/expr.rs | 6 +++++- tests/ui/coroutine/postfix-yield-after-cast.rs | 10 ++++++++++ tests/ui/coroutine/postfix-yield-after-cast.stderr | 13 +++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/ui/coroutine/postfix-yield-after-cast.rs create mode 100644 tests/ui/coroutine/postfix-yield-after-cast.stderr diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 3d89530f91435..54d8a79102580 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -785,9 +785,13 @@ impl<'a> Parser<'a> { ExprKind::Call(_, _) => "a function call", ExprKind::Await(_, _) => "`.await`", ExprKind::Use(_, _) => "`.use`", + ExprKind::Yield(YieldKind::Postfix(_)) => "`.yield`", ExprKind::Match(_, _, MatchKind::Postfix) => "a postfix match", ExprKind::Err(_) => return Ok(with_postfix), - _ => unreachable!("parse_dot_or_call_expr_with_ shouldn't produce this"), + _ => unreachable!( + "did not expect {:?} as an illegal postfix operator following cast", + with_postfix.kind + ), } ); let mut err = self.dcx().struct_span_err(span, msg); diff --git a/tests/ui/coroutine/postfix-yield-after-cast.rs b/tests/ui/coroutine/postfix-yield-after-cast.rs new file mode 100644 index 0000000000000..472efb9f5138b --- /dev/null +++ b/tests/ui/coroutine/postfix-yield-after-cast.rs @@ -0,0 +1,10 @@ +// Regression test for . + +#![feature(yield_expr, coroutines)] + +fn main() { + #[coroutine] || { + 0 as u8.yield + //~^ ERROR cast cannot be followed by `.yield` + }; +} diff --git a/tests/ui/coroutine/postfix-yield-after-cast.stderr b/tests/ui/coroutine/postfix-yield-after-cast.stderr new file mode 100644 index 0000000000000..a4de064fdf879 --- /dev/null +++ b/tests/ui/coroutine/postfix-yield-after-cast.stderr @@ -0,0 +1,13 @@ +error: cast cannot be followed by `.yield` + --> $DIR/postfix-yield-after-cast.rs:7:9 + | +LL | 0 as u8.yield + | ^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (0 as u8).yield + | + + + +error: aborting due to 1 previous error + From be9d3bcfed2df9926f620af84bde1d687a9f6962 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 4 Jul 2025 19:13:24 +0000 Subject: [PATCH 03/10] Make resolve_fn_signature responsible for its own rib. --- compiler/rustc_resolve/src/late.rs | 129 ++++++++++++----------------- 1 file changed, 54 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index ed9622a0d81cc..261d099abdc09 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -910,22 +910,15 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc span, |this| { this.visit_generic_params(&fn_ptr.generic_params, false); - this.with_lifetime_rib( - LifetimeRibKind::AnonymousCreateParameter { - binder: ty.id, - report_in_path: false, - }, - |this| { - this.resolve_fn_signature( - ty.id, - false, - // We don't need to deal with patterns in parameters, because - // they are not possible for foreign or bodiless functions. - fn_ptr.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)), - &fn_ptr.decl.output, - ) - }, - ); + this.resolve_fn_signature( + ty.id, + false, + // We don't need to deal with patterns in parameters, because + // they are not possible for foreign or bodiless functions. + fn_ptr.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)), + &fn_ptr.decl.output, + false, + ) }, ) } @@ -1042,19 +1035,12 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc self.visit_fn_header(&sig.header); self.visit_ident(ident); self.visit_generics(generics); - self.with_lifetime_rib( - LifetimeRibKind::AnonymousCreateParameter { - binder: fn_id, - report_in_path: false, - }, - |this| { - this.resolve_fn_signature( - fn_id, - sig.decl.has_self(), - sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)), - &sig.decl.output, - ); - }, + self.resolve_fn_signature( + fn_id, + sig.decl.has_self(), + sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)), + &sig.decl.output, + false, ); return; } @@ -1080,22 +1066,15 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc .coroutine_kind .map(|coroutine_kind| coroutine_kind.return_id()); - this.with_lifetime_rib( - LifetimeRibKind::AnonymousCreateParameter { - binder: fn_id, - report_in_path: coro_node_id.is_some(), - }, - |this| { - this.resolve_fn_signature( - fn_id, - declaration.has_self(), - declaration - .inputs - .iter() - .map(|Param { pat, ty, .. }| (Some(&**pat), &**ty)), - &declaration.output, - ); - }, + this.resolve_fn_signature( + fn_id, + declaration.has_self(), + declaration + .inputs + .iter() + .map(|Param { pat, ty, .. }| (Some(&**pat), &**ty)), + &declaration.output, + coro_node_id.is_some(), ); if let Some(contract) = contract { @@ -1307,19 +1286,12 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc kind: LifetimeBinderKind::PolyTrait, .. } => { - self.with_lifetime_rib( - LifetimeRibKind::AnonymousCreateParameter { - binder, - report_in_path: false, - }, - |this| { - this.resolve_fn_signature( - binder, - false, - p_args.inputs.iter().map(|ty| (None, &**ty)), - &p_args.output, - ) - }, + self.resolve_fn_signature( + binder, + false, + p_args.inputs.iter().map(|ty| (None, &**ty)), + &p_args.output, + false, ); break; } @@ -2236,25 +2208,32 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { has_self: bool, inputs: impl Iterator, &'ast Ty)> + Clone, output_ty: &'ast FnRetTy, + report_elided_lifetimes_in_path: bool, ) { - // Add each argument to the rib. - let elision_lifetime = self.resolve_fn_params(has_self, inputs); - debug!(?elision_lifetime); - - let outer_failures = take(&mut self.diag_metadata.current_elision_failures); - let output_rib = if let Ok(res) = elision_lifetime.as_ref() { - self.r.lifetime_elision_allowed.insert(fn_id); - LifetimeRibKind::Elided(*res) - } else { - LifetimeRibKind::ElisionFailure + let rib = LifetimeRibKind::AnonymousCreateParameter { + binder: fn_id, + report_in_path: report_elided_lifetimes_in_path, }; - self.with_lifetime_rib(output_rib, |this| visit::walk_fn_ret_ty(this, output_ty)); - let elision_failures = - replace(&mut self.diag_metadata.current_elision_failures, outer_failures); - if !elision_failures.is_empty() { - let Err(failure_info) = elision_lifetime else { bug!() }; - self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info)); - } + self.with_lifetime_rib(rib, |this| { + // Add each argument to the rib. + let elision_lifetime = this.resolve_fn_params(has_self, inputs); + debug!(?elision_lifetime); + + let outer_failures = take(&mut this.diag_metadata.current_elision_failures); + let output_rib = if let Ok(res) = elision_lifetime.as_ref() { + this.r.lifetime_elision_allowed.insert(fn_id); + LifetimeRibKind::Elided(*res) + } else { + LifetimeRibKind::ElisionFailure + }; + this.with_lifetime_rib(output_rib, |this| visit::walk_fn_ret_ty(this, output_ty)); + let elision_failures = + replace(&mut this.diag_metadata.current_elision_failures, outer_failures); + if !elision_failures.is_empty() { + let Err(failure_info) = elision_lifetime else { bug!() }; + this.report_missing_lifetime_specifiers(elision_failures, Some(failure_info)); + } + }); } /// Resolve inside function parameters and parameter types. From 950a3b34ea25631749708029594f892df4399c7d Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Mon, 28 Jul 2025 01:12:05 -0700 Subject: [PATCH 04/10] Add a mir-opt pre-codegen test for dropping a `Box<[impl Copy]>` --- ...ace.PreCodegen.after.32bit.panic-abort.mir | 111 ++++++++++++++++++ ...ce.PreCodegen.after.32bit.panic-unwind.mir | 111 ++++++++++++++++++ ...ace.PreCodegen.after.64bit.panic-abort.mir | 111 ++++++++++++++++++ ...ce.PreCodegen.after.64bit.panic-unwind.mir | 111 ++++++++++++++++++ tests/mir-opt/pre-codegen/drop_boxed_slice.rs | 19 +++ 5 files changed, 463 insertions(+) create mode 100644 tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir create mode 100644 tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir create mode 100644 tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir create mode 100644 tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir create mode 100644 tests/mir-opt/pre-codegen/drop_boxed_slice.rs diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir new file mode 100644 index 0000000000000..587e69154ea1c --- /dev/null +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir @@ -0,0 +1,111 @@ +// MIR for `generic_in_place` after PreCodegen + +fn generic_in_place(_1: *mut Box<[T]>) -> () { + debug ptr => _1; + let mut _0: (); + scope 1 (inlined drop_in_place::> - shim(Some(Box<[T]>))) { + scope 2 (inlined as Drop>::drop) { + let _2: std::ptr::NonNull<[T]>; + let mut _3: *mut [T]; + let mut _4: *const [T]; + let _12: (); + scope 3 { + let _8: std::ptr::alignment::AlignmentEnum; + scope 4 { + scope 12 (inlined Layout::size) { + } + scope 13 (inlined Unique::<[T]>::cast::) { + scope 14 (inlined NonNull::<[T]>::cast::) { + scope 15 (inlined NonNull::<[T]>::as_ptr) { + } + } + } + scope 16 (inlined as From>>::from) { + scope 17 (inlined Unique::::as_non_null_ptr) { + } + } + scope 18 (inlined ::deallocate) { + let mut _9: *mut u8; + scope 19 (inlined Layout::size) { + } + scope 20 (inlined NonNull::::as_ptr) { + } + scope 21 (inlined std::alloc::dealloc) { + let mut _11: usize; + scope 22 (inlined Layout::size) { + } + scope 23 (inlined Layout::align) { + scope 24 (inlined std::ptr::Alignment::as_usize) { + let mut _10: u32; + } + } + } + } + } + scope 5 (inlined Unique::<[T]>::as_ptr) { + scope 6 (inlined NonNull::<[T]>::as_ptr) { + } + } + scope 7 (inlined Layout::for_value_raw::<[T]>) { + let mut _5: usize; + let mut _6: usize; + scope 8 { + scope 11 (inlined #[track_caller] Layout::from_size_align_unchecked) { + let mut _7: std::ptr::Alignment; + } + } + scope 9 (inlined size_of_val_raw::<[T]>) { + } + scope 10 (inlined align_of_val_raw::<[T]>) { + } + } + } + } + } + + bb0: { + StorageLive(_2); + _2 = copy (((*_1).0: std::ptr::Unique<[T]>).0: std::ptr::NonNull<[T]>); + StorageLive(_4); + _3 = copy _2 as *mut [T] (Transmute); + _4 = copy _2 as *const [T] (Transmute); + StorageLive(_6); + _5 = std::intrinsics::size_of_val::<[T]>(copy _4) -> [return: bb1, unwind unreachable]; + } + + bb1: { + _6 = std::intrinsics::align_of_val::<[T]>(move _4) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageLive(_7); + _7 = copy _6 as std::ptr::Alignment (Transmute); + _8 = move (_7.0: std::ptr::alignment::AlignmentEnum); + StorageDead(_7); + StorageDead(_6); + StorageDead(_4); + switchInt(copy _5) -> [0: bb5, otherwise: bb3]; + } + + bb3: { + StorageLive(_9); + _9 = copy _3 as *mut u8 (PtrToPtr); + StorageLive(_11); + StorageLive(_10); + _10 = discriminant(_8); + _11 = move _10 as usize (IntToInt); + StorageDead(_10); + _12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_11); + StorageDead(_9); + goto -> bb5; + } + + bb5: { + StorageDead(_2); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir new file mode 100644 index 0000000000000..587e69154ea1c --- /dev/null +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir @@ -0,0 +1,111 @@ +// MIR for `generic_in_place` after PreCodegen + +fn generic_in_place(_1: *mut Box<[T]>) -> () { + debug ptr => _1; + let mut _0: (); + scope 1 (inlined drop_in_place::> - shim(Some(Box<[T]>))) { + scope 2 (inlined as Drop>::drop) { + let _2: std::ptr::NonNull<[T]>; + let mut _3: *mut [T]; + let mut _4: *const [T]; + let _12: (); + scope 3 { + let _8: std::ptr::alignment::AlignmentEnum; + scope 4 { + scope 12 (inlined Layout::size) { + } + scope 13 (inlined Unique::<[T]>::cast::) { + scope 14 (inlined NonNull::<[T]>::cast::) { + scope 15 (inlined NonNull::<[T]>::as_ptr) { + } + } + } + scope 16 (inlined as From>>::from) { + scope 17 (inlined Unique::::as_non_null_ptr) { + } + } + scope 18 (inlined ::deallocate) { + let mut _9: *mut u8; + scope 19 (inlined Layout::size) { + } + scope 20 (inlined NonNull::::as_ptr) { + } + scope 21 (inlined std::alloc::dealloc) { + let mut _11: usize; + scope 22 (inlined Layout::size) { + } + scope 23 (inlined Layout::align) { + scope 24 (inlined std::ptr::Alignment::as_usize) { + let mut _10: u32; + } + } + } + } + } + scope 5 (inlined Unique::<[T]>::as_ptr) { + scope 6 (inlined NonNull::<[T]>::as_ptr) { + } + } + scope 7 (inlined Layout::for_value_raw::<[T]>) { + let mut _5: usize; + let mut _6: usize; + scope 8 { + scope 11 (inlined #[track_caller] Layout::from_size_align_unchecked) { + let mut _7: std::ptr::Alignment; + } + } + scope 9 (inlined size_of_val_raw::<[T]>) { + } + scope 10 (inlined align_of_val_raw::<[T]>) { + } + } + } + } + } + + bb0: { + StorageLive(_2); + _2 = copy (((*_1).0: std::ptr::Unique<[T]>).0: std::ptr::NonNull<[T]>); + StorageLive(_4); + _3 = copy _2 as *mut [T] (Transmute); + _4 = copy _2 as *const [T] (Transmute); + StorageLive(_6); + _5 = std::intrinsics::size_of_val::<[T]>(copy _4) -> [return: bb1, unwind unreachable]; + } + + bb1: { + _6 = std::intrinsics::align_of_val::<[T]>(move _4) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageLive(_7); + _7 = copy _6 as std::ptr::Alignment (Transmute); + _8 = move (_7.0: std::ptr::alignment::AlignmentEnum); + StorageDead(_7); + StorageDead(_6); + StorageDead(_4); + switchInt(copy _5) -> [0: bb5, otherwise: bb3]; + } + + bb3: { + StorageLive(_9); + _9 = copy _3 as *mut u8 (PtrToPtr); + StorageLive(_11); + StorageLive(_10); + _10 = discriminant(_8); + _11 = move _10 as usize (IntToInt); + StorageDead(_10); + _12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_11); + StorageDead(_9); + goto -> bb5; + } + + bb5: { + StorageDead(_2); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir new file mode 100644 index 0000000000000..e88f6b394fa79 --- /dev/null +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir @@ -0,0 +1,111 @@ +// MIR for `generic_in_place` after PreCodegen + +fn generic_in_place(_1: *mut Box<[T]>) -> () { + debug ptr => _1; + let mut _0: (); + scope 1 (inlined drop_in_place::> - shim(Some(Box<[T]>))) { + scope 2 (inlined as Drop>::drop) { + let _2: std::ptr::NonNull<[T]>; + let mut _3: *mut [T]; + let mut _4: *const [T]; + let _12: (); + scope 3 { + let _8: std::ptr::alignment::AlignmentEnum; + scope 4 { + scope 12 (inlined Layout::size) { + } + scope 13 (inlined Unique::<[T]>::cast::) { + scope 14 (inlined NonNull::<[T]>::cast::) { + scope 15 (inlined NonNull::<[T]>::as_ptr) { + } + } + } + scope 16 (inlined as From>>::from) { + scope 17 (inlined Unique::::as_non_null_ptr) { + } + } + scope 18 (inlined ::deallocate) { + let mut _9: *mut u8; + scope 19 (inlined Layout::size) { + } + scope 20 (inlined NonNull::::as_ptr) { + } + scope 21 (inlined std::alloc::dealloc) { + let mut _11: usize; + scope 22 (inlined Layout::size) { + } + scope 23 (inlined Layout::align) { + scope 24 (inlined std::ptr::Alignment::as_usize) { + let mut _10: u64; + } + } + } + } + } + scope 5 (inlined Unique::<[T]>::as_ptr) { + scope 6 (inlined NonNull::<[T]>::as_ptr) { + } + } + scope 7 (inlined Layout::for_value_raw::<[T]>) { + let mut _5: usize; + let mut _6: usize; + scope 8 { + scope 11 (inlined #[track_caller] Layout::from_size_align_unchecked) { + let mut _7: std::ptr::Alignment; + } + } + scope 9 (inlined size_of_val_raw::<[T]>) { + } + scope 10 (inlined align_of_val_raw::<[T]>) { + } + } + } + } + } + + bb0: { + StorageLive(_2); + _2 = copy (((*_1).0: std::ptr::Unique<[T]>).0: std::ptr::NonNull<[T]>); + StorageLive(_4); + _3 = copy _2 as *mut [T] (Transmute); + _4 = copy _2 as *const [T] (Transmute); + StorageLive(_6); + _5 = std::intrinsics::size_of_val::<[T]>(copy _4) -> [return: bb1, unwind unreachable]; + } + + bb1: { + _6 = std::intrinsics::align_of_val::<[T]>(move _4) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageLive(_7); + _7 = copy _6 as std::ptr::Alignment (Transmute); + _8 = move (_7.0: std::ptr::alignment::AlignmentEnum); + StorageDead(_7); + StorageDead(_6); + StorageDead(_4); + switchInt(copy _5) -> [0: bb5, otherwise: bb3]; + } + + bb3: { + StorageLive(_9); + _9 = copy _3 as *mut u8 (PtrToPtr); + StorageLive(_11); + StorageLive(_10); + _10 = discriminant(_8); + _11 = move _10 as usize (IntToInt); + StorageDead(_10); + _12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_11); + StorageDead(_9); + goto -> bb5; + } + + bb5: { + StorageDead(_2); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir new file mode 100644 index 0000000000000..e88f6b394fa79 --- /dev/null +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir @@ -0,0 +1,111 @@ +// MIR for `generic_in_place` after PreCodegen + +fn generic_in_place(_1: *mut Box<[T]>) -> () { + debug ptr => _1; + let mut _0: (); + scope 1 (inlined drop_in_place::> - shim(Some(Box<[T]>))) { + scope 2 (inlined as Drop>::drop) { + let _2: std::ptr::NonNull<[T]>; + let mut _3: *mut [T]; + let mut _4: *const [T]; + let _12: (); + scope 3 { + let _8: std::ptr::alignment::AlignmentEnum; + scope 4 { + scope 12 (inlined Layout::size) { + } + scope 13 (inlined Unique::<[T]>::cast::) { + scope 14 (inlined NonNull::<[T]>::cast::) { + scope 15 (inlined NonNull::<[T]>::as_ptr) { + } + } + } + scope 16 (inlined as From>>::from) { + scope 17 (inlined Unique::::as_non_null_ptr) { + } + } + scope 18 (inlined ::deallocate) { + let mut _9: *mut u8; + scope 19 (inlined Layout::size) { + } + scope 20 (inlined NonNull::::as_ptr) { + } + scope 21 (inlined std::alloc::dealloc) { + let mut _11: usize; + scope 22 (inlined Layout::size) { + } + scope 23 (inlined Layout::align) { + scope 24 (inlined std::ptr::Alignment::as_usize) { + let mut _10: u64; + } + } + } + } + } + scope 5 (inlined Unique::<[T]>::as_ptr) { + scope 6 (inlined NonNull::<[T]>::as_ptr) { + } + } + scope 7 (inlined Layout::for_value_raw::<[T]>) { + let mut _5: usize; + let mut _6: usize; + scope 8 { + scope 11 (inlined #[track_caller] Layout::from_size_align_unchecked) { + let mut _7: std::ptr::Alignment; + } + } + scope 9 (inlined size_of_val_raw::<[T]>) { + } + scope 10 (inlined align_of_val_raw::<[T]>) { + } + } + } + } + } + + bb0: { + StorageLive(_2); + _2 = copy (((*_1).0: std::ptr::Unique<[T]>).0: std::ptr::NonNull<[T]>); + StorageLive(_4); + _3 = copy _2 as *mut [T] (Transmute); + _4 = copy _2 as *const [T] (Transmute); + StorageLive(_6); + _5 = std::intrinsics::size_of_val::<[T]>(copy _4) -> [return: bb1, unwind unreachable]; + } + + bb1: { + _6 = std::intrinsics::align_of_val::<[T]>(move _4) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageLive(_7); + _7 = copy _6 as std::ptr::Alignment (Transmute); + _8 = move (_7.0: std::ptr::alignment::AlignmentEnum); + StorageDead(_7); + StorageDead(_6); + StorageDead(_4); + switchInt(copy _5) -> [0: bb5, otherwise: bb3]; + } + + bb3: { + StorageLive(_9); + _9 = copy _3 as *mut u8 (PtrToPtr); + StorageLive(_11); + StorageLive(_10); + _10 = discriminant(_8); + _11 = move _10 as usize (IntToInt); + StorageDead(_10); + _12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_11); + StorageDead(_9); + goto -> bb5; + } + + bb5: { + StorageDead(_2); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.rs b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs new file mode 100644 index 0000000000000..e625a440d2003 --- /dev/null +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs @@ -0,0 +1,19 @@ +//@ compile-flags: -O -Zmir-opt-level=2 +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// EMIT_MIR_FOR_EACH_BIT_WIDTH + +#![crate_type = "lib"] + +// EMIT_MIR drop_boxed_slice.generic_in_place.PreCodegen.after.mir +pub unsafe fn generic_in_place(ptr: *mut Box<[T]>) { + // CHECK-LABEL: fn generic_in_place(_1: *mut Box<[T]>) + // CHECK: (inlined as Drop>::drop) + // CHECK: [[SIZE:_.+]] = std::intrinsics::size_of_val::<[T]> + // CHECK: [[ALIGN:_.+]] = std::intrinsics::align_of_val::<[T]> + // CHECK: [[B:_.+]] = copy [[ALIGN]] as std::ptr::Alignment (Transmute); + // CHECK: [[C:_.+]] = move ([[B]].0: std::ptr::alignment::AlignmentEnum); + // CHECK: [[D:_.+]] = discriminant([[C]]); + // CHECK: [[E:_.+]] = move [[D]] as usize (IntToInt); + // CHECK: = alloc::alloc::__rust_dealloc({{.+}}, move [[SIZE]], move [[E]]) -> + std::ptr::drop_in_place(ptr) +} From 185b0745180e6f6f3a4c9c7a41ec8725749cf5bd Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 27 Jul 2025 23:23:22 -0700 Subject: [PATCH 05/10] Add a MIR test for `align_of_val` on a slice --- ..._slice.InstSimplify-after-simplifycfg.diff | 20 +++++++++++++++++++ tests/mir-opt/instsimplify/align_of_slice.rs | 13 ++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 tests/mir-opt/instsimplify/align_of_slice.of_val_slice.InstSimplify-after-simplifycfg.diff create mode 100644 tests/mir-opt/instsimplify/align_of_slice.rs diff --git a/tests/mir-opt/instsimplify/align_of_slice.of_val_slice.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/align_of_slice.of_val_slice.InstSimplify-after-simplifycfg.diff new file mode 100644 index 0000000000000..21ba2e2505604 --- /dev/null +++ b/tests/mir-opt/instsimplify/align_of_slice.of_val_slice.InstSimplify-after-simplifycfg.diff @@ -0,0 +1,20 @@ +- // MIR for `of_val_slice` before InstSimplify-after-simplifycfg ++ // MIR for `of_val_slice` after InstSimplify-after-simplifycfg + + fn of_val_slice(_1: &[T]) -> usize { + debug slice => _1; + let mut _0: usize; + let mut _2: *const [T]; + + bb0: { + StorageLive(_2); + _2 = &raw const (*_1); + _0 = std::intrinsics::align_of_val::<[T]>(move _2) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/instsimplify/align_of_slice.rs b/tests/mir-opt/instsimplify/align_of_slice.rs new file mode 100644 index 0000000000000..900a05c2a8b3d --- /dev/null +++ b/tests/mir-opt/instsimplify/align_of_slice.rs @@ -0,0 +1,13 @@ +//@ test-mir-pass: InstSimplify-after-simplifycfg +//@ needs-unwind + +#![crate_type = "lib"] +#![feature(core_intrinsics)] + +// EMIT_MIR align_of_slice.of_val_slice.InstSimplify-after-simplifycfg.diff +pub fn of_val_slice(slice: &[T]) -> usize { + // CHECK-LABEL: fn of_val_slice(_1: &[T]) + // CHECK: _2 = &raw const (*_1); + // CHECK: _0 = std::intrinsics::align_of_val::<[T]>(move _2) + unsafe { core::intrinsics::align_of_val(slice) } +} From 8ef9233339c09d80e12b31c523082b94d9e09b44 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 27 Jul 2025 23:39:06 -0700 Subject: [PATCH 06/10] =?UTF-8?q?Simplify=20`align=5Fof=5Fval::<[T]>(?= =?UTF-8?q?=E2=80=A6)`=20=E2=86=92=20`align=5Fof::()`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rustc_mir_transform/src/instsimplify.rs | 31 +++++++++++++++++++ ..._slice.InstSimplify-after-simplifycfg.diff | 4 ++- tests/mir-opt/instsimplify/align_of_slice.rs | 3 +- ...ace.PreCodegen.after.32bit.panic-abort.mir | 19 +++++------- ...ce.PreCodegen.after.32bit.panic-unwind.mir | 19 +++++------- ...ace.PreCodegen.after.64bit.panic-abort.mir | 19 +++++------- ...ce.PreCodegen.after.64bit.panic-unwind.mir | 19 +++++------- tests/mir-opt/pre-codegen/drop_boxed_slice.rs | 2 +- 8 files changed, 68 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index dbcaed2095383..c83bd25c6636b 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -55,6 +55,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { let terminator = block.terminator.as_mut().unwrap(); ctx.simplify_primitive_clone(terminator, &mut block.statements); + ctx.simplify_align_of_slice_val(terminator, &mut block.statements); ctx.simplify_intrinsic_assert(terminator); ctx.simplify_nounwind_call(terminator); simplify_duplicate_switch_targets(terminator); @@ -252,6 +253,36 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { terminator.kind = TerminatorKind::Goto { target: *destination_block }; } + // Convert `align_of_val::<[T]>(ptr)` to `align_of::()`, since the + // alignment of a slice doesn't actually depend on metadata at all + // and the element type is always `Sized`. + // + // This is here so it can run after inlining, where it's more useful. + // (LowerIntrinsics is done in cleanup, before the optimization passes.) + fn simplify_align_of_slice_val( + &self, + terminator: &mut Terminator<'tcx>, + statements: &mut Vec>, + ) { + if let TerminatorKind::Call { + func, args, destination, target: Some(destination_block), .. + } = &terminator.kind + && args.len() == 1 + && let Some((fn_def_id, generics)) = func.const_fn_def() + && self.tcx.is_intrinsic(fn_def_id, sym::align_of_val) + && let ty::Slice(elem_ty) = *generics.type_at(0).kind() + { + statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( + *destination, + Rvalue::NullaryOp(NullOp::AlignOf, elem_ty), + ))), + )); + terminator.kind = TerminatorKind::Goto { target: *destination_block }; + } + } + fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) { let TerminatorKind::Call { ref func, ref mut unwind, .. } = terminator.kind else { return; diff --git a/tests/mir-opt/instsimplify/align_of_slice.of_val_slice.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/align_of_slice.of_val_slice.InstSimplify-after-simplifycfg.diff index 21ba2e2505604..042e19bf2aa18 100644 --- a/tests/mir-opt/instsimplify/align_of_slice.of_val_slice.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/align_of_slice.of_val_slice.InstSimplify-after-simplifycfg.diff @@ -9,7 +9,9 @@ bb0: { StorageLive(_2); _2 = &raw const (*_1); - _0 = std::intrinsics::align_of_val::<[T]>(move _2) -> [return: bb1, unwind unreachable]; +- _0 = std::intrinsics::align_of_val::<[T]>(move _2) -> [return: bb1, unwind unreachable]; ++ _0 = AlignOf(T); ++ goto -> bb1; } bb1: { diff --git a/tests/mir-opt/instsimplify/align_of_slice.rs b/tests/mir-opt/instsimplify/align_of_slice.rs index 900a05c2a8b3d..0af05cb6b0b02 100644 --- a/tests/mir-opt/instsimplify/align_of_slice.rs +++ b/tests/mir-opt/instsimplify/align_of_slice.rs @@ -7,7 +7,6 @@ // EMIT_MIR align_of_slice.of_val_slice.InstSimplify-after-simplifycfg.diff pub fn of_val_slice(slice: &[T]) -> usize { // CHECK-LABEL: fn of_val_slice(_1: &[T]) - // CHECK: _2 = &raw const (*_1); - // CHECK: _0 = std::intrinsics::align_of_val::<[T]>(move _2) + // CHECK: _0 = AlignOf(T); unsafe { core::intrinsics::align_of_val(slice) } } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir index 587e69154ea1c..2777bba893bbc 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir @@ -70,24 +70,21 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _3 = copy _2 as *mut [T] (Transmute); _4 = copy _2 as *const [T] (Transmute); StorageLive(_6); - _5 = std::intrinsics::size_of_val::<[T]>(copy _4) -> [return: bb1, unwind unreachable]; + _5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; } bb1: { - _6 = std::intrinsics::align_of_val::<[T]>(move _4) -> [return: bb2, unwind unreachable]; - } - - bb2: { + _6 = AlignOf(T); StorageLive(_7); _7 = copy _6 as std::ptr::Alignment (Transmute); _8 = move (_7.0: std::ptr::alignment::AlignmentEnum); StorageDead(_7); StorageDead(_6); StorageDead(_4); - switchInt(copy _5) -> [0: bb5, otherwise: bb3]; + switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } - bb3: { + bb2: { StorageLive(_9); _9 = copy _3 as *mut u8 (PtrToPtr); StorageLive(_11); @@ -95,16 +92,16 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _10 = discriminant(_8); _11 = move _10 as usize (IntToInt); StorageDead(_10); - _12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb4, unwind unreachable]; + _12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb3, unwind unreachable]; } - bb4: { + bb3: { StorageDead(_11); StorageDead(_9); - goto -> bb5; + goto -> bb4; } - bb5: { + bb4: { StorageDead(_2); return; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir index 587e69154ea1c..2777bba893bbc 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir @@ -70,24 +70,21 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _3 = copy _2 as *mut [T] (Transmute); _4 = copy _2 as *const [T] (Transmute); StorageLive(_6); - _5 = std::intrinsics::size_of_val::<[T]>(copy _4) -> [return: bb1, unwind unreachable]; + _5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; } bb1: { - _6 = std::intrinsics::align_of_val::<[T]>(move _4) -> [return: bb2, unwind unreachable]; - } - - bb2: { + _6 = AlignOf(T); StorageLive(_7); _7 = copy _6 as std::ptr::Alignment (Transmute); _8 = move (_7.0: std::ptr::alignment::AlignmentEnum); StorageDead(_7); StorageDead(_6); StorageDead(_4); - switchInt(copy _5) -> [0: bb5, otherwise: bb3]; + switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } - bb3: { + bb2: { StorageLive(_9); _9 = copy _3 as *mut u8 (PtrToPtr); StorageLive(_11); @@ -95,16 +92,16 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _10 = discriminant(_8); _11 = move _10 as usize (IntToInt); StorageDead(_10); - _12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb4, unwind unreachable]; + _12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb3, unwind unreachable]; } - bb4: { + bb3: { StorageDead(_11); StorageDead(_9); - goto -> bb5; + goto -> bb4; } - bb5: { + bb4: { StorageDead(_2); return; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir index e88f6b394fa79..2be0a478c852c 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir @@ -70,24 +70,21 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _3 = copy _2 as *mut [T] (Transmute); _4 = copy _2 as *const [T] (Transmute); StorageLive(_6); - _5 = std::intrinsics::size_of_val::<[T]>(copy _4) -> [return: bb1, unwind unreachable]; + _5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; } bb1: { - _6 = std::intrinsics::align_of_val::<[T]>(move _4) -> [return: bb2, unwind unreachable]; - } - - bb2: { + _6 = AlignOf(T); StorageLive(_7); _7 = copy _6 as std::ptr::Alignment (Transmute); _8 = move (_7.0: std::ptr::alignment::AlignmentEnum); StorageDead(_7); StorageDead(_6); StorageDead(_4); - switchInt(copy _5) -> [0: bb5, otherwise: bb3]; + switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } - bb3: { + bb2: { StorageLive(_9); _9 = copy _3 as *mut u8 (PtrToPtr); StorageLive(_11); @@ -95,16 +92,16 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _10 = discriminant(_8); _11 = move _10 as usize (IntToInt); StorageDead(_10); - _12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb4, unwind unreachable]; + _12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb3, unwind unreachable]; } - bb4: { + bb3: { StorageDead(_11); StorageDead(_9); - goto -> bb5; + goto -> bb4; } - bb5: { + bb4: { StorageDead(_2); return; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir index e88f6b394fa79..2be0a478c852c 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir @@ -70,24 +70,21 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _3 = copy _2 as *mut [T] (Transmute); _4 = copy _2 as *const [T] (Transmute); StorageLive(_6); - _5 = std::intrinsics::size_of_val::<[T]>(copy _4) -> [return: bb1, unwind unreachable]; + _5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; } bb1: { - _6 = std::intrinsics::align_of_val::<[T]>(move _4) -> [return: bb2, unwind unreachable]; - } - - bb2: { + _6 = AlignOf(T); StorageLive(_7); _7 = copy _6 as std::ptr::Alignment (Transmute); _8 = move (_7.0: std::ptr::alignment::AlignmentEnum); StorageDead(_7); StorageDead(_6); StorageDead(_4); - switchInt(copy _5) -> [0: bb5, otherwise: bb3]; + switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } - bb3: { + bb2: { StorageLive(_9); _9 = copy _3 as *mut u8 (PtrToPtr); StorageLive(_11); @@ -95,16 +92,16 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _10 = discriminant(_8); _11 = move _10 as usize (IntToInt); StorageDead(_10); - _12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb4, unwind unreachable]; + _12 = alloc::alloc::__rust_dealloc(move _9, move _5, move _11) -> [return: bb3, unwind unreachable]; } - bb4: { + bb3: { StorageDead(_11); StorageDead(_9); - goto -> bb5; + goto -> bb4; } - bb5: { + bb4: { StorageDead(_2); return; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.rs b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs index e625a440d2003..11fb7afef0fb1 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.rs +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs @@ -9,7 +9,7 @@ pub unsafe fn generic_in_place(ptr: *mut Box<[T]>) { // CHECK-LABEL: fn generic_in_place(_1: *mut Box<[T]>) // CHECK: (inlined as Drop>::drop) // CHECK: [[SIZE:_.+]] = std::intrinsics::size_of_val::<[T]> - // CHECK: [[ALIGN:_.+]] = std::intrinsics::align_of_val::<[T]> + // CHECK: [[ALIGN:_.+]] = AlignOf(T); // CHECK: [[B:_.+]] = copy [[ALIGN]] as std::ptr::Alignment (Transmute); // CHECK: [[C:_.+]] = move ([[B]].0: std::ptr::alignment::AlignmentEnum); // CHECK: [[D:_.+]] = discriminant([[C]]); From 27610341768951b2d46071683bcb87ea7c690e98 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 28 Jul 2025 12:05:17 +1000 Subject: [PATCH 07/10] coverage: Test how `#[automatically_derived]` affects instrumentation --- tests/coverage/auto-derived.auto.cov-map | 47 +++++++++++++++++ tests/coverage/auto-derived.auto.coverage | 54 ++++++++++++++++++++ tests/coverage/auto-derived.base.cov-map | 61 +++++++++++++++++++++++ tests/coverage/auto-derived.base.coverage | 54 ++++++++++++++++++++ tests/coverage/auto-derived.on.cov-map | 47 +++++++++++++++++ tests/coverage/auto-derived.on.coverage | 54 ++++++++++++++++++++ tests/coverage/auto-derived.rs | 53 ++++++++++++++++++++ 7 files changed, 370 insertions(+) create mode 100644 tests/coverage/auto-derived.auto.cov-map create mode 100644 tests/coverage/auto-derived.auto.coverage create mode 100644 tests/coverage/auto-derived.base.cov-map create mode 100644 tests/coverage/auto-derived.base.coverage create mode 100644 tests/coverage/auto-derived.on.cov-map create mode 100644 tests/coverage/auto-derived.on.coverage create mode 100644 tests/coverage/auto-derived.rs diff --git a/tests/coverage/auto-derived.auto.cov-map b/tests/coverage/auto-derived.auto.cov-map new file mode 100644 index 0000000000000..a0aa1206de429 --- /dev/null +++ b/tests/coverage/auto-derived.auto.cov-map @@ -0,0 +1,47 @@ +Function name: ::my_assoc_fn::inner_fn +Raw bytes (24): 0x[01, 01, 00, 04, 01, 1a, 09, 00, 16, 01, 01, 0d, 00, 10, 01, 00, 11, 00, 1e, 01, 01, 09, 00, 0a] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 26, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +Highest counter ID seen: c0 + +Function name: ::my_assoc_fn::inner_fn_on +Raw bytes (24): 0x[01, 01, 00, 04, 01, 1f, 09, 00, 19, 01, 01, 0d, 00, 10, 01, 00, 11, 00, 23, 01, 01, 09, 00, 0a] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 31, 9) to (start + 0, 25) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 35) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +Highest counter ID seen: c0 + +Function name: ::my_assoc_fn::{closure#0} +Raw bytes (24): 0x[01, 01, 00, 04, 01, 23, 1a, 00, 1b, 01, 01, 0d, 00, 10, 01, 00, 11, 00, 1d, 01, 01, 09, 00, 0a] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 35, 26) to (start + 0, 27) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +Highest counter ID seen: c0 + +Function name: auto_derived::main +Raw bytes (19): 0x[01, 01, 00, 03, 01, 33, 01, 00, 0a, 01, 01, 05, 00, 1a, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 51, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c0 + diff --git a/tests/coverage/auto-derived.auto.coverage b/tests/coverage/auto-derived.auto.coverage new file mode 100644 index 0000000000000..960bd11ec3a19 --- /dev/null +++ b/tests/coverage/auto-derived.auto.coverage @@ -0,0 +1,54 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: base auto on + LL| | + LL| |// Tests for how `#[automatically_derived]` affects coverage instrumentation. + LL| |// + LL| |// The actual behaviour is an implementation detail, so this test mostly exists + LL| |// to show when that behaviour has been accidentally or deliberately changed. + LL| |// + LL| |// Revision guide: + LL| |// - base: Test baseline instrumentation behaviour without `#[automatically_derived]` + LL| |// - auto: Test how `#[automatically_derived]` affects instrumentation + LL| |// - on: Test interaction between auto-derived and `#[coverage(on)]` + LL| | + LL| |struct MyStruct; + LL| | + LL| |trait MyTrait { + LL| | fn my_assoc_fn(); + LL| |} + LL| | + LL| |#[cfg_attr(auto, automatically_derived)] + LL| |#[cfg_attr(on, automatically_derived)] + LL| |#[cfg_attr(on, coverage(on))] + LL| |impl MyTrait for MyStruct { + LL| | fn my_assoc_fn() { + LL| 1| fn inner_fn() { + LL| 1| say("in inner fn"); + LL| 1| } + LL| | + LL| | #[coverage(on)] + LL| 1| fn inner_fn_on() { + LL| 1| say("in inner fn (on)"); + LL| 1| } + LL| | + LL| 1| let closure = || { + LL| 1| say("in closure"); + LL| 1| }; + LL| | + LL| | closure(); + LL| | inner_fn(); + LL| | inner_fn_on(); + LL| | } + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |#[inline(never)] + LL| |fn say(s: &str) { + LL| | println!("{s}"); + LL| |} + LL| | + LL| 1|fn main() { + LL| 1| MyStruct::my_assoc_fn(); + LL| 1|} + diff --git a/tests/coverage/auto-derived.base.cov-map b/tests/coverage/auto-derived.base.cov-map new file mode 100644 index 0000000000000..2dcd616300d9d --- /dev/null +++ b/tests/coverage/auto-derived.base.cov-map @@ -0,0 +1,61 @@ +Function name: ::my_assoc_fn +Raw bytes (34): 0x[01, 01, 00, 06, 01, 19, 05, 00, 15, 01, 0a, 0d, 00, 14, 01, 04, 09, 00, 12, 01, 01, 09, 00, 11, 01, 01, 09, 00, 14, 01, 01, 05, 00, 06] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 25, 5) to (start + 0, 21) +- Code(Counter(0)) at (prev + 10, 13) to (start + 0, 20) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 20) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) +Highest counter ID seen: c0 + +Function name: ::my_assoc_fn::inner_fn +Raw bytes (24): 0x[01, 01, 00, 04, 01, 1a, 09, 00, 16, 01, 01, 0d, 00, 10, 01, 00, 11, 00, 1e, 01, 01, 09, 00, 0a] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 26, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +Highest counter ID seen: c0 + +Function name: ::my_assoc_fn::inner_fn_on +Raw bytes (24): 0x[01, 01, 00, 04, 01, 1f, 09, 00, 19, 01, 01, 0d, 00, 10, 01, 00, 11, 00, 23, 01, 01, 09, 00, 0a] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 31, 9) to (start + 0, 25) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 35) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +Highest counter ID seen: c0 + +Function name: ::my_assoc_fn::{closure#0} +Raw bytes (24): 0x[01, 01, 00, 04, 01, 23, 1a, 00, 1b, 01, 01, 0d, 00, 10, 01, 00, 11, 00, 1d, 01, 01, 09, 00, 0a] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 35, 26) to (start + 0, 27) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +Highest counter ID seen: c0 + +Function name: auto_derived::main +Raw bytes (19): 0x[01, 01, 00, 03, 01, 33, 01, 00, 0a, 01, 01, 05, 00, 1a, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 51, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c0 + diff --git a/tests/coverage/auto-derived.base.coverage b/tests/coverage/auto-derived.base.coverage new file mode 100644 index 0000000000000..6ab6aa5c4dfc4 --- /dev/null +++ b/tests/coverage/auto-derived.base.coverage @@ -0,0 +1,54 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: base auto on + LL| | + LL| |// Tests for how `#[automatically_derived]` affects coverage instrumentation. + LL| |// + LL| |// The actual behaviour is an implementation detail, so this test mostly exists + LL| |// to show when that behaviour has been accidentally or deliberately changed. + LL| |// + LL| |// Revision guide: + LL| |// - base: Test baseline instrumentation behaviour without `#[automatically_derived]` + LL| |// - auto: Test how `#[automatically_derived]` affects instrumentation + LL| |// - on: Test interaction between auto-derived and `#[coverage(on)]` + LL| | + LL| |struct MyStruct; + LL| | + LL| |trait MyTrait { + LL| | fn my_assoc_fn(); + LL| |} + LL| | + LL| |#[cfg_attr(auto, automatically_derived)] + LL| |#[cfg_attr(on, automatically_derived)] + LL| |#[cfg_attr(on, coverage(on))] + LL| |impl MyTrait for MyStruct { + LL| 1| fn my_assoc_fn() { + LL| 1| fn inner_fn() { + LL| 1| say("in inner fn"); + LL| 1| } + LL| | + LL| | #[coverage(on)] + LL| 1| fn inner_fn_on() { + LL| 1| say("in inner fn (on)"); + LL| 1| } + LL| | + LL| 1| let closure = || { + LL| 1| say("in closure"); + LL| 1| }; + LL| | + LL| 1| closure(); + LL| 1| inner_fn(); + LL| 1| inner_fn_on(); + LL| 1| } + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |#[inline(never)] + LL| |fn say(s: &str) { + LL| | println!("{s}"); + LL| |} + LL| | + LL| 1|fn main() { + LL| 1| MyStruct::my_assoc_fn(); + LL| 1|} + diff --git a/tests/coverage/auto-derived.on.cov-map b/tests/coverage/auto-derived.on.cov-map new file mode 100644 index 0000000000000..a0aa1206de429 --- /dev/null +++ b/tests/coverage/auto-derived.on.cov-map @@ -0,0 +1,47 @@ +Function name: ::my_assoc_fn::inner_fn +Raw bytes (24): 0x[01, 01, 00, 04, 01, 1a, 09, 00, 16, 01, 01, 0d, 00, 10, 01, 00, 11, 00, 1e, 01, 01, 09, 00, 0a] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 26, 9) to (start + 0, 22) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +Highest counter ID seen: c0 + +Function name: ::my_assoc_fn::inner_fn_on +Raw bytes (24): 0x[01, 01, 00, 04, 01, 1f, 09, 00, 19, 01, 01, 0d, 00, 10, 01, 00, 11, 00, 23, 01, 01, 09, 00, 0a] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 31, 9) to (start + 0, 25) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 35) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +Highest counter ID seen: c0 + +Function name: ::my_assoc_fn::{closure#0} +Raw bytes (24): 0x[01, 01, 00, 04, 01, 23, 1a, 00, 1b, 01, 01, 0d, 00, 10, 01, 00, 11, 00, 1d, 01, 01, 09, 00, 0a] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 35, 26) to (start + 0, 27) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 16) +- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 29) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) +Highest counter ID seen: c0 + +Function name: auto_derived::main +Raw bytes (19): 0x[01, 01, 00, 03, 01, 33, 01, 00, 0a, 01, 01, 05, 00, 1a, 01, 01, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 51, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 26) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c0 + diff --git a/tests/coverage/auto-derived.on.coverage b/tests/coverage/auto-derived.on.coverage new file mode 100644 index 0000000000000..960bd11ec3a19 --- /dev/null +++ b/tests/coverage/auto-derived.on.coverage @@ -0,0 +1,54 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2024 + LL| |//@ revisions: base auto on + LL| | + LL| |// Tests for how `#[automatically_derived]` affects coverage instrumentation. + LL| |// + LL| |// The actual behaviour is an implementation detail, so this test mostly exists + LL| |// to show when that behaviour has been accidentally or deliberately changed. + LL| |// + LL| |// Revision guide: + LL| |// - base: Test baseline instrumentation behaviour without `#[automatically_derived]` + LL| |// - auto: Test how `#[automatically_derived]` affects instrumentation + LL| |// - on: Test interaction between auto-derived and `#[coverage(on)]` + LL| | + LL| |struct MyStruct; + LL| | + LL| |trait MyTrait { + LL| | fn my_assoc_fn(); + LL| |} + LL| | + LL| |#[cfg_attr(auto, automatically_derived)] + LL| |#[cfg_attr(on, automatically_derived)] + LL| |#[cfg_attr(on, coverage(on))] + LL| |impl MyTrait for MyStruct { + LL| | fn my_assoc_fn() { + LL| 1| fn inner_fn() { + LL| 1| say("in inner fn"); + LL| 1| } + LL| | + LL| | #[coverage(on)] + LL| 1| fn inner_fn_on() { + LL| 1| say("in inner fn (on)"); + LL| 1| } + LL| | + LL| 1| let closure = || { + LL| 1| say("in closure"); + LL| 1| }; + LL| | + LL| | closure(); + LL| | inner_fn(); + LL| | inner_fn_on(); + LL| | } + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |#[inline(never)] + LL| |fn say(s: &str) { + LL| | println!("{s}"); + LL| |} + LL| | + LL| 1|fn main() { + LL| 1| MyStruct::my_assoc_fn(); + LL| 1|} + diff --git a/tests/coverage/auto-derived.rs b/tests/coverage/auto-derived.rs new file mode 100644 index 0000000000000..cbf8279918a21 --- /dev/null +++ b/tests/coverage/auto-derived.rs @@ -0,0 +1,53 @@ +#![feature(coverage_attribute)] +//@ edition: 2024 +//@ revisions: base auto on + +// Tests for how `#[automatically_derived]` affects coverage instrumentation. +// +// The actual behaviour is an implementation detail, so this test mostly exists +// to show when that behaviour has been accidentally or deliberately changed. +// +// Revision guide: +// - base: Test baseline instrumentation behaviour without `#[automatically_derived]` +// - auto: Test how `#[automatically_derived]` affects instrumentation +// - on: Test interaction between auto-derived and `#[coverage(on)]` + +struct MyStruct; + +trait MyTrait { + fn my_assoc_fn(); +} + +#[cfg_attr(auto, automatically_derived)] +#[cfg_attr(on, automatically_derived)] +#[cfg_attr(on, coverage(on))] +impl MyTrait for MyStruct { + fn my_assoc_fn() { + fn inner_fn() { + say("in inner fn"); + } + + #[coverage(on)] + fn inner_fn_on() { + say("in inner fn (on)"); + } + + let closure = || { + say("in closure"); + }; + + closure(); + inner_fn(); + inner_fn_on(); + } +} + +#[coverage(off)] +#[inline(never)] +fn say(s: &str) { + println!("{s}"); +} + +fn main() { + MyStruct::my_assoc_fn(); +} From b4d0c91635e87be830282cb86d23882b6b6f9dad Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 28 Jul 2025 12:29:40 +1000 Subject: [PATCH 08/10] coverage: Rename `CoverageStatus` to `CoverageAttrKind` This patch also prepares the affected code in `coverage_attr_on` for some subsequent changes. --- .../src/attributes.rs | 20 ++++--------- .../src/attributes/codegen_attrs.rs | 10 +++---- .../rustc_mir_transform/src/coverage/query.rs | 29 ++++++++++--------- 3 files changed, 27 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index 610c93a253ceb..55019cd57a71d 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -110,18 +110,10 @@ pub enum DeprecatedSince { Err, } -#[derive( - Copy, - Debug, - Eq, - PartialEq, - Encodable, - Decodable, - Clone, - HashStable_Generic, - PrintAttribute -)] -pub enum CoverageStatus { +/// Successfully-parsed value of a `#[coverage(..)]` attribute. +#[derive(Copy, Debug, Eq, PartialEq, Encodable, Decodable, Clone)] +#[derive(HashStable_Generic, PrintAttribute)] +pub enum CoverageAttrKind { On, Off, } @@ -304,8 +296,8 @@ pub enum AttributeKind { /// Represents `#[const_trait]`. ConstTrait(Span), - /// Represents `#[coverage]`. - Coverage(Span, CoverageStatus), + /// Represents `#[coverage(..)]`. + Coverage(Span, CoverageAttrKind), ///Represents `#[rustc_deny_explicit_impl]`. DenyExplicitImpl(Span), diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index bb28121c2c5d0..afa9abed0bb59 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -1,4 +1,4 @@ -use rustc_attr_data_structures::{AttributeKind, CoverageStatus, OptimizeAttr, UsedBy}; +use rustc_attr_data_structures::{AttributeKind, CoverageAttrKind, OptimizeAttr, UsedBy}; use rustc_feature::{AttributeTemplate, template}; use rustc_session::parse::feature_err; use rustc_span::{Span, Symbol, sym}; @@ -78,16 +78,16 @@ impl SingleAttributeParser for CoverageParser { return None; }; - let status = match arg.path().word_sym() { - Some(sym::off) => CoverageStatus::Off, - Some(sym::on) => CoverageStatus::On, + let kind = match arg.path().word_sym() { + Some(sym::off) => CoverageAttrKind::Off, + Some(sym::on) => CoverageAttrKind::On, None | Some(_) => { fail_incorrect_argument(arg.span()); return None; } }; - Some(AttributeKind::Coverage(cx.attr_span, status)) + Some(AttributeKind::Coverage(cx.attr_span, kind)) } } diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 551f720c869e8..02e433e53c929 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -1,4 +1,4 @@ -use rustc_attr_data_structures::{AttributeKind, CoverageStatus, find_attr}; +use rustc_attr_data_structures::{AttributeKind, CoverageAttrKind, find_attr}; use rustc_index::bit_set::DenseBitSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::{BasicCoverageBlock, CoverageIdsInfo, CoverageKind, MappingKind}; @@ -57,20 +57,23 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { /// Query implementation for `coverage_attr_on`. fn coverage_attr_on(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { - // Check for annotations directly on this def. - if let Some(coverage_status) = - find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Coverage(_, status) => status) + // Check for a `#[coverage(..)]` attribute on this def. + if let Some(kind) = + find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Coverage(_sp, kind) => kind) { - *coverage_status == CoverageStatus::On - } else { - match tcx.opt_local_parent(def_id) { - // Check the parent def (and so on recursively) until we find an - // enclosing attribute or reach the crate root. - Some(parent) => tcx.coverage_attr_on(parent), - // We reached the crate root without seeing a coverage attribute, so - // allow coverage instrumentation by default. - None => true, + match kind { + CoverageAttrKind::On => return true, + CoverageAttrKind::Off => return false, } + }; + + // Check the parent def (and so on recursively) until we find an + // enclosing attribute or reach the crate root. + match tcx.opt_local_parent(def_id) { + Some(parent) => tcx.coverage_attr_on(parent), + // We reached the crate root without seeing a coverage attribute, so + // allow coverage instrumentation by default. + None => true, } } From 682f744f89e1c014e91b2fd7058c75f2056ac870 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 28 Jul 2025 12:25:05 +1000 Subject: [PATCH 09/10] coverage: Treat `#[automatically_derived]` as `#[coverage(off)]` --- .../rustc_mir_transform/src/coverage/query.rs | 19 +++++++-------- tests/coverage/auto-derived.auto.cov-map | 24 ------------------- tests/coverage/auto-derived.auto.coverage | 12 +++++----- tests/coverage/auto-derived.on.cov-map | 14 +++++++++++ tests/coverage/auto-derived.on.coverage | 10 ++++---- 5 files changed, 34 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 02e433e53c929..73795e47d2e9d 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -32,16 +32,6 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { return false; } - // Don't instrument functions with `#[automatically_derived]` on their - // enclosing impl block, on the assumption that most users won't care about - // coverage for derived impls. - if let Some(impl_of) = tcx.impl_of_assoc(def_id.to_def_id()) - && tcx.is_automatically_derived(impl_of) - { - trace!("InstrumentCoverage skipped for {def_id:?} (automatically derived)"); - return false; - } - if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NAKED) { trace!("InstrumentCoverage skipped for {def_id:?} (`#[naked]`)"); return false; @@ -67,6 +57,15 @@ fn coverage_attr_on(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { } }; + // Treat `#[automatically_derived]` as an implied `#[coverage(off)]`, on + // the assumption that most users won't want coverage for derived impls. + // + // This affects not just the associated items of an impl block, but also + // any closures and other nested functions within those associated items. + if tcx.is_automatically_derived(def_id.to_def_id()) { + return false; + } + // Check the parent def (and so on recursively) until we find an // enclosing attribute or reach the crate root. match tcx.opt_local_parent(def_id) { diff --git a/tests/coverage/auto-derived.auto.cov-map b/tests/coverage/auto-derived.auto.cov-map index a0aa1206de429..e3d411d895aaa 100644 --- a/tests/coverage/auto-derived.auto.cov-map +++ b/tests/coverage/auto-derived.auto.cov-map @@ -1,15 +1,3 @@ -Function name: ::my_assoc_fn::inner_fn -Raw bytes (24): 0x[01, 01, 00, 04, 01, 1a, 09, 00, 16, 01, 01, 0d, 00, 10, 01, 00, 11, 00, 1e, 01, 01, 09, 00, 0a] -Number of files: 1 -- file 0 => $DIR/auto-derived.rs -Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 26, 9) to (start + 0, 22) -- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 16) -- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 30) -- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) -Highest counter ID seen: c0 - Function name: ::my_assoc_fn::inner_fn_on Raw bytes (24): 0x[01, 01, 00, 04, 01, 1f, 09, 00, 19, 01, 01, 0d, 00, 10, 01, 00, 11, 00, 23, 01, 01, 09, 00, 0a] Number of files: 1 @@ -22,18 +10,6 @@ Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) Highest counter ID seen: c0 -Function name: ::my_assoc_fn::{closure#0} -Raw bytes (24): 0x[01, 01, 00, 04, 01, 23, 1a, 00, 1b, 01, 01, 0d, 00, 10, 01, 00, 11, 00, 1d, 01, 01, 09, 00, 0a] -Number of files: 1 -- file 0 => $DIR/auto-derived.rs -Number of expressions: 0 -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 35, 26) to (start + 0, 27) -- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 16) -- Code(Counter(0)) at (prev + 0, 17) to (start + 0, 29) -- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 10) -Highest counter ID seen: c0 - Function name: auto_derived::main Raw bytes (19): 0x[01, 01, 00, 03, 01, 33, 01, 00, 0a, 01, 01, 05, 00, 1a, 01, 01, 01, 00, 02] Number of files: 1 diff --git a/tests/coverage/auto-derived.auto.coverage b/tests/coverage/auto-derived.auto.coverage index 960bd11ec3a19..242abbf803183 100644 --- a/tests/coverage/auto-derived.auto.coverage +++ b/tests/coverage/auto-derived.auto.coverage @@ -23,18 +23,18 @@ LL| |#[cfg_attr(on, coverage(on))] LL| |impl MyTrait for MyStruct { LL| | fn my_assoc_fn() { - LL| 1| fn inner_fn() { - LL| 1| say("in inner fn"); - LL| 1| } + LL| | fn inner_fn() { + LL| | say("in inner fn"); + LL| | } LL| | LL| | #[coverage(on)] LL| 1| fn inner_fn_on() { LL| 1| say("in inner fn (on)"); LL| 1| } LL| | - LL| 1| let closure = || { - LL| 1| say("in closure"); - LL| 1| }; + LL| | let closure = || { + LL| | say("in closure"); + LL| | }; LL| | LL| | closure(); LL| | inner_fn(); diff --git a/tests/coverage/auto-derived.on.cov-map b/tests/coverage/auto-derived.on.cov-map index a0aa1206de429..2dcd616300d9d 100644 --- a/tests/coverage/auto-derived.on.cov-map +++ b/tests/coverage/auto-derived.on.cov-map @@ -1,3 +1,17 @@ +Function name: ::my_assoc_fn +Raw bytes (34): 0x[01, 01, 00, 06, 01, 19, 05, 00, 15, 01, 0a, 0d, 00, 14, 01, 04, 09, 00, 12, 01, 01, 09, 00, 11, 01, 01, 09, 00, 14, 01, 01, 05, 00, 06] +Number of files: 1 +- file 0 => $DIR/auto-derived.rs +Number of expressions: 0 +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 25, 5) to (start + 0, 21) +- Code(Counter(0)) at (prev + 10, 13) to (start + 0, 20) +- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 20) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) +Highest counter ID seen: c0 + Function name: ::my_assoc_fn::inner_fn Raw bytes (24): 0x[01, 01, 00, 04, 01, 1a, 09, 00, 16, 01, 01, 0d, 00, 10, 01, 00, 11, 00, 1e, 01, 01, 09, 00, 0a] Number of files: 1 diff --git a/tests/coverage/auto-derived.on.coverage b/tests/coverage/auto-derived.on.coverage index 960bd11ec3a19..6ab6aa5c4dfc4 100644 --- a/tests/coverage/auto-derived.on.coverage +++ b/tests/coverage/auto-derived.on.coverage @@ -22,7 +22,7 @@ LL| |#[cfg_attr(on, automatically_derived)] LL| |#[cfg_attr(on, coverage(on))] LL| |impl MyTrait for MyStruct { - LL| | fn my_assoc_fn() { + LL| 1| fn my_assoc_fn() { LL| 1| fn inner_fn() { LL| 1| say("in inner fn"); LL| 1| } @@ -36,10 +36,10 @@ LL| 1| say("in closure"); LL| 1| }; LL| | - LL| | closure(); - LL| | inner_fn(); - LL| | inner_fn_on(); - LL| | } + LL| 1| closure(); + LL| 1| inner_fn(); + LL| 1| inner_fn_on(); + LL| 1| } LL| |} LL| | LL| |#[coverage(off)] From de02a32cf1203a9c9efb97a66dac44b7c646bb24 Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Tue, 29 Jul 2025 13:24:41 +0200 Subject: [PATCH 10/10] Fix typo in `DropGuard` doc --- library/core/src/mem/drop_guard.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/mem/drop_guard.rs b/library/core/src/mem/drop_guard.rs index 47ccb69acc806..fecc94b815e97 100644 --- a/library/core/src/mem/drop_guard.rs +++ b/library/core/src/mem/drop_guard.rs @@ -4,7 +4,7 @@ use crate::ops::{Deref, DerefMut}; /// Wrap a value and run a closure when dropped. /// -/// This is useful for quickly creating desructors inline. +/// This is useful for quickly creating destructors inline. /// /// # Examples ///