From 99049b3aa80a9aa75fed0acf29956508778df371 Mon Sep 17 00:00:00 2001 From: Jacob Greenfield Date: Tue, 15 Jul 2025 21:52:43 -0400 Subject: [PATCH 1/4] Add `DefId::parent()` accessor in `rustc_public` --- compiler/rustc_public/src/compiler_interface.rs | 8 ++++++++ compiler/rustc_public/src/crate_def.rs | 6 ++++++ compiler/rustc_public_bridge/src/context/impls.rs | 5 +++++ 3 files changed, 19 insertions(+) diff --git a/compiler/rustc_public/src/compiler_interface.rs b/compiler/rustc_public/src/compiler_interface.rs index b17d31f2b91ab..2cb1157a5c255 100644 --- a/compiler/rustc_public/src/compiler_interface.rs +++ b/compiler/rustc_public/src/compiler_interface.rs @@ -249,6 +249,14 @@ impl<'tcx> CompilerInterface<'tcx> { cx.def_name(did, trimmed) } + /// Returns the parent of the given `DefId`. + pub(crate) fn def_parent(&self, def_id: DefId) -> Option { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[def_id]; + cx.def_parent(did).map(|did| tables.create_def_id(did)) + } + /// Return registered tool attributes with the given attribute name. /// /// FIXME(jdonszelmann): may panic on non-tool attributes. After more attribute work, non-tool diff --git a/compiler/rustc_public/src/crate_def.rs b/compiler/rustc_public/src/crate_def.rs index 75228135e4cb3..7ab123544e3b6 100644 --- a/compiler/rustc_public/src/crate_def.rs +++ b/compiler/rustc_public/src/crate_def.rs @@ -29,6 +29,12 @@ impl DefId { pub fn trimmed_name(&self) -> Symbol { with(|cx| cx.def_name(*self, true)) } + + /// Return the parent of this definition, or `None` if this is the root of a + /// crate. + pub fn parent(&self) -> Option { + with(|cx| cx.def_parent(*self)) + } } /// A trait for retrieving information about a particular definition. diff --git a/compiler/rustc_public_bridge/src/context/impls.rs b/compiler/rustc_public_bridge/src/context/impls.rs index 25be9e7b30415..cbb00d64e0969 100644 --- a/compiler/rustc_public_bridge/src/context/impls.rs +++ b/compiler/rustc_public_bridge/src/context/impls.rs @@ -268,6 +268,11 @@ impl<'tcx, B: Bridge> CompilerCtxt<'tcx, B> { } } + /// Returns the parent of the given `DefId`. + pub fn def_parent(&self, def_id: DefId) -> Option { + self.tcx.opt_parent(def_id) + } + /// Return registered tool attributes with the given attribute name. /// /// FIXME(jdonszelmann): may panic on non-tool attributes. After more attribute work, non-tool From e9d68a5e757a269a8e59cc6c735fcd9c34e53221 Mon Sep 17 00:00:00 2001 From: Jacob Greenfield Date: Fri, 14 Nov 2025 20:09:56 -0500 Subject: [PATCH 2/4] Add UI test for `DefId::parent()` --- .../rustc_public/check_def_parent.rs | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 tests/ui-fulldeps/rustc_public/check_def_parent.rs diff --git a/tests/ui-fulldeps/rustc_public/check_def_parent.rs b/tests/ui-fulldeps/rustc_public/check_def_parent.rs new file mode 100644 index 0000000000000..192ad471de331 --- /dev/null +++ b/tests/ui-fulldeps/rustc_public/check_def_parent.rs @@ -0,0 +1,190 @@ +//@ run-pass +//! Test that users are able to use public MIR APIs to retrieve information about parent +//! definitions. + +//@ ignore-stage1 +//@ ignore-cross-compile +//@ ignore-remote +//@ edition: 2024 +// ignore-tidy-linelength + +#![feature(rustc_private)] + +extern crate rustc_middle; + +extern crate rustc_driver; +extern crate rustc_interface; +extern crate rustc_public; + +use rustc_public::ty::{RigidTy, TyKind}; +use rustc_public::*; +use std::fmt::Debug; +use std::io::Write; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "input"; + +/// Verify that each def has the correct parent +fn test_stable_mir() -> ControlFlow<()> { + fn set_once(slot: &mut Option, val: T) { + assert_eq!(slot.replace(val), None); + } + + let mut const_item = None; + let mut static_item = None; + let mut trait_method = None; + let mut trait_method_helper = None; + let mut inherent_method = None; + let mut inherent_method_helper = None; + let mut main = None; + let mut mystruct_ctor = None; + let mut trait_decl = None; + let mut trait_impl = None; + + let mut mystruct_ctor_ty = None; + + // Extract def-ids of various items + let krate = rustc_public::local_crate(); + for it in rustc_public::all_local_items() { + match &*it.0.name() { + "wrapper_mod::CONST_ITEM" => { + set_once(&mut const_item, it.0); + } + "wrapper_mod::STATIC_ITEM" => { + set_once(&mut static_item, it.0); + } + "::trait_method" => { + set_once(&mut trait_method, it.0); + } + "::trait_method::trait_method_helper" => { + set_once(&mut trait_method_helper, it.0); + } + "wrapper_mod::MyStruct::inherent_method" => { + set_once(&mut inherent_method, it.0); + } + "wrapper_mod::MyStruct::inherent_method::inherent_method_helper" => { + set_once(&mut inherent_method_helper, it.0); + } + "main" => { + set_once(&mut main, it.0); + } + "wrapper_mod::MyStruct" => { + set_once(&mut mystruct_ctor, it.0); + mystruct_ctor_ty = Some(it.ty()); + } + _ => (), + } + } + for it in krate.trait_decls() { + match &*it.0.name() { + "wrapper_mod::MyTrait" => set_once(&mut trait_decl, it.0), + _ => (), + } + } + for it in krate.trait_impls() { + match &*it.0.name() { + "" => set_once(&mut trait_impl, it.0), + _ => (), + } + } + + let const_item = const_item.unwrap(); + let static_item = static_item.unwrap(); + let trait_method = trait_method.unwrap(); + let trait_method_helper = trait_method_helper.unwrap(); + let inherent_method = inherent_method.unwrap(); + let inherent_method_helper = inherent_method_helper.unwrap(); + let main = main.unwrap(); + let mystruct_ctor = mystruct_ctor.unwrap(); + let trait_decl = trait_decl.unwrap(); + let trait_impl = trait_impl.unwrap(); + + let mystruct_ctor_ty = mystruct_ctor_ty.unwrap(); + let mystruct_ty = mystruct_ctor_ty.kind().fn_def().unwrap().0.fn_sig().skip_binder().output(); + let TyKind::RigidTy(RigidTy::Adt(mystruct_adt_def, _)) = mystruct_ty.kind() else { panic!() }; + + let inherent_impl = inherent_method.parent().unwrap(); + let wrapper_mod = const_item.parent().unwrap(); + let crate_root = wrapper_mod.parent().unwrap(); + assert_eq!(&*wrapper_mod.name(), "wrapper_mod"); + + // Check that each def-id has the correct parent + assert_eq!(crate_root.parent(), None); + assert_eq!(inherent_impl.parent(), Some(wrapper_mod)); + assert_eq!(const_item.parent(), Some(wrapper_mod)); + assert_eq!(static_item.parent(), Some(wrapper_mod)); + assert_eq!(trait_method.parent(), Some(trait_impl)); + assert_eq!(trait_method_helper.parent(), Some(trait_method)); + assert_eq!(inherent_method_helper.parent(), Some(inherent_method)); + assert_eq!(main.parent(), Some(crate_root)); + assert_eq!(trait_decl.parent(), Some(wrapper_mod)); + assert_eq!(trait_impl.parent(), Some(wrapper_mod)); + assert_eq!(mystruct_ctor.parent(), Some(mystruct_adt_def.0)); + assert_eq!(mystruct_adt_def.0.parent(), Some(wrapper_mod)); + + ControlFlow::Continue(()) +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `RustcPublic` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "def_parent_input.rs"; + generate_input(&path).unwrap(); + let args = &[ + "rustc".to_string(), + "-Cpanic=abort".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, test_stable_mir).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + mod wrapper_mod {{ + pub const CONST_ITEM: u32 = 100; + pub static STATIC_ITEM: u32 = 150; + + pub struct MyStruct(pub u32); + + pub trait MyTrait {{ + fn trait_method(&self); + }} + + impl MyTrait for MyStruct {{ + fn trait_method(&self) {{ + fn trait_method_helper() {{}} + + trait_method_helper() + }} + }} + + impl MyStruct {{ + pub fn inherent_method(&self) {{ + println!("{{}}", self.0); + + fn inherent_method_helper() {{}} + + inherent_method_helper() + }} + }} + }} + use wrapper_mod::{{MyStruct, MyTrait, CONST_ITEM, STATIC_ITEM}}; + + fn main() {{ + let mystruct = MyStruct(200); + mystruct.trait_method(); + mystruct.inherent_method(); + let _const = CONST_ITEM; + let _static = STATIC_ITEM; + }} + "# + )?; + Ok(()) +} From 7c24c9a9089f90a7acf1ad120a1e6c6e3b1b84f1 Mon Sep 17 00:00:00 2001 From: cezarbbb Date: Sat, 29 Nov 2025 14:17:58 +0800 Subject: [PATCH 3/4] Test the coexistence of 'stack-protector' and 'safe-stack' --- .../stack-protector-safe-stack.rs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/assembly-llvm/stack-protector/stack-protector-safe-stack.rs diff --git a/tests/assembly-llvm/stack-protector/stack-protector-safe-stack.rs b/tests/assembly-llvm/stack-protector/stack-protector-safe-stack.rs new file mode 100644 index 0000000000000..24a1276adc4ac --- /dev/null +++ b/tests/assembly-llvm/stack-protector/stack-protector-safe-stack.rs @@ -0,0 +1,54 @@ +//@ add-minicore +//@ revisions: all strong none safestack safestack_strong safestack_all +//@ assembly-output: emit-asm +//@ only-x86_64-unknown-linux-gnu +//@ [all] compile-flags: -Z stack-protector=all +//@ [strong] compile-flags: -Z stack-protector=strong +//@ [none] compile-flags: -Z stack-protector=none +//@ [safestack] compile-flags: -Z stack-protector=none -Z sanitizer=safestack +//@ [safestack_strong] compile-flags: -Z stack-protector=strong -Z sanitizer=safestack +//@ [safestack_all] compile-flags: -Z stack-protector=all -Z sanitizer=safestack +//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled --target x86_64-unknown-linux-gnu +//@ needs-llvm-components: x86 + +#![feature(unsized_fn_params)] +#![crate_type = "lib"] +#![feature(no_core)] +#![no_core] +#![no_std] + +extern crate minicore; +use minicore::*; + +extern "C" { + fn test4spss(p: *mut u8); +} + +// CHECK-LABEL: test1{{:|\[}} +#[no_mangle] +pub unsafe fn test1(x: *mut u8) -> u8 { + let mut buf: [u8; 64] = [0; 64]; + + let p = &mut buf as *mut [u8; 64] as *mut u8; + + *p = 42; + + test4spss(p); + + *x = *p; + + *p + + // none-NOT: __stack_chk_fail + // strong: __stack_chk_fail + // all: __stack_chk_fail + + // safestack: __safestack_unsafe_stack_ptr + // safestack-NOT: __stack_chk_fail + + // safestack_strong: __safestack_unsafe_stack_ptr + // safestack_strong: __stack_chk_fail + + // safestack_all: __safestack_unsafe_stack_ptr + // safestack_all: __stack_chk_fail +} From d3653e9f59b333c5c0f398b4364ea10e0f9fe8a5 Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Sat, 29 Nov 2025 10:19:56 +0100 Subject: [PATCH 4/4] Remove an unnecessary `unwrap` in `rustc_codegen_gcc` --- compiler/rustc_codegen_gcc/src/builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index c0519f7a68e28..1787415b72e6d 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -503,9 +503,9 @@ fn set_rvalue_location<'a, 'gcc, 'tcx>( bx: &mut Builder<'a, 'gcc, 'tcx>, rvalue: RValue<'gcc>, ) -> RValue<'gcc> { - if bx.location.is_some() { + if let Some(location) = bx.location { #[cfg(feature = "master")] - rvalue.set_location(bx.location.unwrap()); + rvalue.set_location(location); } rvalue }