From 66a554b04539a1319c68b3d52c7c3e027208dfec Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Fri, 20 Oct 2023 23:05:38 -0700 Subject: [PATCH 1/4] Add method to convert internal to stable constructs --- Cargo.lock | 1 + compiler/rustc_smir/Cargo.toml | 1 + compiler/rustc_smir/src/rustc_internal/mod.rs | 58 ++++- compiler/rustc_smir/src/rustc_smir/mod.rs | 206 +++++++++++------- compiler/stable_mir/src/lib.rs | 52 ++--- 5 files changed, 197 insertions(+), 121 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f8d566c2d156..d0422340c5258 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4524,6 +4524,7 @@ dependencies = [ "rustc_middle", "rustc_span", "rustc_target", + "scoped-tls", "stable_mir", "tracing", ] diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index 41c7d3a859437..47dd7372f3d18 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -9,6 +9,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } +scoped-tls = "1.0" stable_mir = {path = "../stable_mir" } tracing = "0.1" diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index f7e519570fa56..7bec946788b31 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -3,7 +3,7 @@ //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs //! until stable MIR is complete. -use crate::rustc_smir::Tables; +use crate::rustc_smir::{Stable, Tables, TablesWrapper}; use rustc_data_structures::fx; use rustc_data_structures::fx::FxIndexMap; use rustc_middle::mir::interpret::AllocId; @@ -11,13 +11,21 @@ use rustc_middle::ty; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::Span; +use scoped_tls::scoped_thread_local; use stable_mir::ty::IndexedVal; +use std::cell::Cell; +use std::cell::RefCell; use std::fmt::Debug; use std::hash::Hash; use std::ops::Index; +use std::rc::Rc; mod internal; +pub unsafe fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T { + with_tables(|tables| item.stable(tables)) +} + impl<'tcx> Index for Tables<'tcx> { type Output = DefId; @@ -125,18 +133,44 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { item.id.into() } +// A thread local variable that stores a pointer to the tables mapping between TyCtxt +// datastructures and stable MIR datastructures +scoped_thread_local! (static TLV: Cell<*const ()>); + +pub(crate) fn init<'tcx>(tables: TablesWrapper<'tcx>, f: impl FnOnce()) { + assert!(!TLV.is_set()); + fn g<'a, 'tcx>(context: &'a TablesWrapper<'tcx>, f: impl FnOnce()) { + let ptr: *const () = &context as *const &_ as _; + TLV.set(&Cell::new(ptr), || { + f(); + }); + } + g(&tables, f); +} + +/// Loads the current context and calls a function with it. +/// Do not nest these, as that will ICE. +pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R { + assert!(TLV.is_set()); + TLV.with(|tlv| { + let ptr = tlv.get(); + assert!(!ptr.is_null()); + let wrapper = unsafe { *(ptr as *const &TablesWrapper<'tcx>) }; + let mut tables = wrapper.0.borrow_mut(); + f(&mut *tables) + }) +} + pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { - stable_mir::run( - Tables { - tcx, - def_ids: IndexMap::default(), - alloc_ids: IndexMap::default(), - spans: IndexMap::default(), - types: vec![], - instances: IndexMap::default(), - }, - f, - ); + let tables = Rc::new(RefCell::new(Tables { + tcx, + def_ids: IndexMap::default(), + alloc_ids: IndexMap::default(), + spans: IndexMap::default(), + types: vec![], + instances: IndexMap::default(), + })); + stable_mir::run(TablesWrapper(Rc::clone(&tables)), || init(TablesWrapper(tables), f)); } #[macro_export] diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index d5379797f1c6b..19ad9898db168 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -23,27 +23,31 @@ use stable_mir::ty::{ FloatTy, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span, TyKind, UintTy, }; use stable_mir::{self, opaque, Context, Filename}; +use std::cell::RefCell; use tracing::debug; mod alloc; mod builder; -impl<'tcx> Context for Tables<'tcx> { +impl<'tcx> Context for TablesWrapper<'tcx> { fn local_crate(&self) -> stable_mir::Crate { - smir_crate(self.tcx, LOCAL_CRATE) + let tables = self.0.borrow(); + smir_crate(tables.tcx, LOCAL_CRATE) } fn external_crates(&self) -> Vec { - self.tcx.crates(()).iter().map(|crate_num| smir_crate(self.tcx, *crate_num)).collect() + let tables = self.0.borrow(); + tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect() } fn find_crates(&self, name: &str) -> Vec { + let tables = self.0.borrow(); let crates: Vec = [LOCAL_CRATE] .iter() - .chain(self.tcx.crates(()).iter()) + .chain(tables.tcx.crates(()).iter()) .map(|crate_num| { - let crate_name = self.tcx.crate_name(*crate_num).to_string(); - (name == crate_name).then(|| smir_crate(self.tcx, *crate_num)) + let crate_name = tables.tcx.crate_name(*crate_num).to_string(); + (name == crate_name).then(|| smir_crate(tables.tcx, *crate_num)) }) .into_iter() .filter_map(|c| c) @@ -52,163 +56,197 @@ impl<'tcx> Context for Tables<'tcx> { } fn name_of_def_id(&self, def_id: stable_mir::DefId) -> String { - self.tcx.def_path_str(self[def_id]) + let tables = self.0.borrow(); + tables.tcx.def_path_str(tables[def_id]) } fn span_to_string(&self, span: stable_mir::ty::Span) -> String { - self.tcx.sess.source_map().span_to_diagnostic_string(self[span]) + let tables = self.0.borrow(); + tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span]) } fn get_filename(&self, span: &Span) -> Filename { + let tables = self.0.borrow(); opaque( - &self + &tables .tcx .sess .source_map() - .span_to_filename(self[*span]) + .span_to_filename(tables[*span]) .display(rustc_span::FileNameDisplayPreference::Local) .to_string(), ) } fn get_lines(&self, span: &Span) -> LineInfo { - let lines = &self.tcx.sess.source_map().span_to_location_info(self[*span]); + let tables = self.0.borrow(); + let lines = &tables.tcx.sess.source_map().span_to_location_info(tables[*span]); LineInfo { start_line: lines.1, start_col: lines.2, end_line: lines.3, end_col: lines.4 } } - fn def_kind(&mut self, def_id: stable_mir::DefId) -> stable_mir::DefKind { - self.tcx.def_kind(self[def_id]).stable(self) + fn def_kind(&self, def_id: stable_mir::DefId) -> stable_mir::DefKind { + let mut tables = self.0.borrow_mut(); + tables.tcx.def_kind(tables[def_id]).stable(&mut *tables) } - fn span_of_an_item(&mut self, def_id: stable_mir::DefId) -> Span { - self.tcx.def_span(self[def_id]).stable(self) + fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span { + let mut tables = self.0.borrow_mut(); + tables.tcx.def_span(tables[def_id]).stable(&mut *tables) } - fn all_local_items(&mut self) -> stable_mir::CrateItems { - self.tcx.mir_keys(()).iter().map(|item| self.crate_item(item.to_def_id())).collect() + fn all_local_items(&self) -> stable_mir::CrateItems { + let mut tables = self.0.borrow_mut(); + tables.tcx.mir_keys(()).iter().map(|item| tables.crate_item(item.to_def_id())).collect() } - fn entry_fn(&mut self) -> Option { - Some(self.crate_item(self.tcx.entry_fn(())?.0)) + fn entry_fn(&self) -> Option { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + Some(tables.crate_item(tcx.entry_fn(())?.0)) } - fn all_trait_decls(&mut self) -> stable_mir::TraitDecls { - self.tcx + fn all_trait_decls(&self) -> stable_mir::TraitDecls { + let mut tables = self.0.borrow_mut(); + tables + .tcx .traits(LOCAL_CRATE) .iter() - .map(|trait_def_id| self.trait_def(*trait_def_id)) + .map(|trait_def_id| tables.trait_def(*trait_def_id)) .collect() } - fn trait_decl(&mut self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl { - let def_id = self[trait_def.0]; - let trait_def = self.tcx.trait_def(def_id); - trait_def.stable(self) + fn trait_decl(&self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl { + let mut tables = self.0.borrow_mut(); + let def_id = tables[trait_def.0]; + let trait_def = tables.tcx.trait_def(def_id); + trait_def.stable(&mut *tables) } - fn all_trait_impls(&mut self) -> stable_mir::ImplTraitDecls { - self.tcx + fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls { + let mut tables = self.0.borrow_mut(); + tables + .tcx .trait_impls_in_crate(LOCAL_CRATE) .iter() - .map(|impl_def_id| self.impl_def(*impl_def_id)) + .map(|impl_def_id| tables.impl_def(*impl_def_id)) .collect() } - fn trait_impl(&mut self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait { - let def_id = self[impl_def.0]; - let impl_trait = self.tcx.impl_trait_ref(def_id).unwrap(); - impl_trait.stable(self) + fn trait_impl(&self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait { + let mut tables = self.0.borrow_mut(); + let def_id = tables[impl_def.0]; + let impl_trait = tables.tcx.impl_trait_ref(def_id).unwrap(); + impl_trait.stable(&mut *tables) } - fn mir_body(&mut self, item: stable_mir::DefId) -> stable_mir::mir::Body { - let def_id = self[item]; - self.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(self) + fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body { + let mut tables = self.0.borrow_mut(); + let def_id = tables[item]; + tables.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(&mut tables) } - fn ty_kind(&mut self, ty: stable_mir::ty::Ty) -> TyKind { - self.types[ty.0].clone().stable(self) + fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind { + let mut tables = self.0.borrow_mut(); + tables.types[ty.0].clone().stable(&mut *tables) } - fn mk_ty(&mut self, kind: TyKind) -> stable_mir::ty::Ty { - let n = self.types.len(); - self.types.push(MaybeStable::Stable(kind)); + fn mk_ty(&self, kind: TyKind) -> stable_mir::ty::Ty { + let mut tables = self.0.borrow_mut(); + let n = tables.types.len(); + tables.types.push(MaybeStable::Stable(kind)); stable_mir::ty::Ty(n) } - fn generics_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics { - let def_id = self[def_id]; - let generics = self.tcx.generics_of(def_id); - generics.stable(self) + fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics { + let mut tables = self.0.borrow_mut(); + let def_id = tables[def_id]; + let generics = tables.tcx.generics_of(def_id); + generics.stable(&mut *tables) } - fn predicates_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates { - let def_id = self[def_id]; - let ty::GenericPredicates { parent, predicates } = self.tcx.predicates_of(def_id); + fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates { + let mut tables = self.0.borrow_mut(); + let def_id = tables[def_id]; + let ty::GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id); stable_mir::ty::GenericPredicates { - parent: parent.map(|did| self.trait_def(did)), + parent: parent.map(|did| tables.trait_def(did)), predicates: predicates .iter() .map(|(clause, span)| { - (clause.as_predicate().kind().skip_binder().stable(self), span.stable(self)) + ( + clause.as_predicate().kind().skip_binder().stable(&mut *tables), + span.stable(&mut *tables), + ) }) .collect(), } } fn explicit_predicates_of( - &mut self, + &self, def_id: stable_mir::DefId, ) -> stable_mir::ty::GenericPredicates { - let def_id = self[def_id]; - let ty::GenericPredicates { parent, predicates } = self.tcx.explicit_predicates_of(def_id); + let mut tables = self.0.borrow_mut(); + let def_id = tables[def_id]; + let ty::GenericPredicates { parent, predicates } = + tables.tcx.explicit_predicates_of(def_id); stable_mir::ty::GenericPredicates { - parent: parent.map(|did| self.trait_def(did)), + parent: parent.map(|did| tables.trait_def(did)), predicates: predicates .iter() .map(|(clause, span)| { - (clause.as_predicate().kind().skip_binder().stable(self), span.stable(self)) + ( + clause.as_predicate().kind().skip_binder().stable(&mut *tables), + span.stable(&mut *tables), + ) }) .collect(), } } - fn instance_body(&mut self, def: InstanceDef) -> Body { - let instance = self.instances[def]; - builder::BodyBuilder::new(self.tcx, instance).build(self) + fn instance_body(&self, def: InstanceDef) -> Body { + let mut tables = self.0.borrow_mut(); + let instance = tables.instances[def]; + builder::BodyBuilder::new(tables.tcx, instance).build(&mut *tables) } - fn instance_ty(&mut self, def: InstanceDef) -> stable_mir::ty::Ty { - let instance = self.instances[def]; - let ty = instance.ty(self.tcx, ParamEnv::empty()); - self.intern_ty(ty) + fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty { + let mut tables = self.0.borrow_mut(); + let instance = tables.instances[def]; + let ty = instance.ty(tables.tcx, ParamEnv::empty()); + tables.intern_ty(ty) } - fn instance_def_id(&mut self, def: InstanceDef) -> stable_mir::DefId { - let def_id = self.instances[def].def_id(); - self.create_def_id(def_id) + fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId { + let mut tables = self.0.borrow_mut(); + let def_id = tables.instances[def].def_id(); + tables.create_def_id(def_id) } - fn mono_instance(&mut self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance { - let def_id = self[item.0]; - Instance::mono(self.tcx, def_id).stable(self) + fn mono_instance(&self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance { + let mut tables = self.0.borrow_mut(); + let def_id = tables[item.0]; + Instance::mono(tables.tcx, def_id).stable(&mut *tables) } fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool { - let def_id = self[def_id]; - let generics = self.tcx.generics_of(def_id); - let result = generics.requires_monomorphization(self.tcx); + let tables = self.0.borrow(); + let def_id = tables[def_id]; + let generics = tables.tcx.generics_of(def_id); + let result = generics.requires_monomorphization(tables.tcx); result } fn resolve_instance( - &mut self, + &self, def: stable_mir::ty::FnDef, args: &stable_mir::ty::GenericArgs, ) -> Option { - let def_id = def.0.internal(self); - let args_ref = args.internal(self); - match Instance::resolve(self.tcx, ParamEnv::reveal_all(), def_id, args_ref) { - Ok(Some(instance)) => Some(instance.stable(self)), + let mut tables = self.0.borrow_mut(); + let def_id = def.0.internal(&mut *tables); + let args_ref = args.internal(&mut *tables); + match Instance::resolve(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) { + Ok(Some(instance)) => Some(instance.stable(&mut *tables)), Ok(None) | Err(_) => None, } } @@ -241,13 +279,15 @@ impl PartialEq for MaybeStable { } } +pub(crate) struct TablesWrapper<'tcx>(pub(crate) std::rc::Rc>>); + pub struct Tables<'tcx> { - pub tcx: TyCtxt<'tcx>, - pub def_ids: IndexMap, - pub alloc_ids: IndexMap, - pub spans: IndexMap, - pub types: Vec>>, - pub instances: IndexMap, InstanceDef>, + pub(crate) tcx: TyCtxt<'tcx>, + pub(crate) def_ids: IndexMap, + pub(crate) alloc_ids: IndexMap, + pub(crate) spans: IndexMap, + pub(crate) types: Vec>>, + pub(crate) instances: IndexMap, InstanceDef>, } impl<'tcx> Tables<'tcx> { @@ -270,7 +310,7 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate { } /// Trait used to convert between an internal MIR type to a Stable MIR type. -pub(crate) trait Stable<'tcx> { +pub trait Stable<'tcx> { /// The stable representation of the type implementing Stable. type T; /// Converts an object to the equivalent Stable MIR representation. diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index be5ccac78c7c6..512c3fc629645 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -175,17 +175,17 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait { } pub trait Context { - fn entry_fn(&mut self) -> Option; + fn entry_fn(&self) -> Option; /// Retrieve all items of the local crate that have a MIR associated with them. - fn all_local_items(&mut self) -> CrateItems; - fn mir_body(&mut self, item: DefId) -> mir::Body; - fn all_trait_decls(&mut self) -> TraitDecls; - fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl; - fn all_trait_impls(&mut self) -> ImplTraitDecls; - fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait; - fn generics_of(&mut self, def_id: DefId) -> Generics; - fn predicates_of(&mut self, def_id: DefId) -> GenericPredicates; - fn explicit_predicates_of(&mut self, def_id: DefId) -> GenericPredicates; + fn all_local_items(&self) -> CrateItems; + fn mir_body(&self, item: DefId) -> mir::Body; + fn all_trait_decls(&self) -> TraitDecls; + fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl; + fn all_trait_impls(&self) -> ImplTraitDecls; + fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait; + fn generics_of(&self, def_id: DefId) -> Generics; + fn predicates_of(&self, def_id: DefId) -> GenericPredicates; + fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates; /// Get information about the local crate. fn local_crate(&self) -> Crate; /// Retrieve a list of all external crates. @@ -207,61 +207,61 @@ pub trait Context { fn get_lines(&self, span: &Span) -> LineInfo; /// Returns the `kind` of given `DefId` - fn def_kind(&mut self, def_id: DefId) -> DefKind; + fn def_kind(&self, def_id: DefId) -> DefKind; /// `Span` of an item - fn span_of_an_item(&mut self, def_id: DefId) -> Span; + fn span_of_an_item(&self, def_id: DefId) -> Span; /// Obtain the representation of a type. - fn ty_kind(&mut self, ty: Ty) -> TyKind; + fn ty_kind(&self, ty: Ty) -> TyKind; /// Create a new `Ty` from scratch without information from rustc. - fn mk_ty(&mut self, kind: TyKind) -> Ty; + fn mk_ty(&self, kind: TyKind) -> Ty; /// Get the body of an Instance. /// FIXME: Monomorphize the body. - fn instance_body(&mut self, instance: InstanceDef) -> Body; + fn instance_body(&self, instance: InstanceDef) -> Body; /// Get the instance type with generic substitutions applied and lifetimes erased. - fn instance_ty(&mut self, instance: InstanceDef) -> Ty; + fn instance_ty(&self, instance: InstanceDef) -> Ty; /// Get the instance. - fn instance_def_id(&mut self, instance: InstanceDef) -> DefId; + fn instance_def_id(&self, instance: InstanceDef) -> DefId; /// Convert a non-generic crate item into an instance. /// This function will panic if the item is generic. - fn mono_instance(&mut self, item: CrateItem) -> Instance; + fn mono_instance(&self, item: CrateItem) -> Instance; /// Item requires monomorphization. fn requires_monomorphization(&self, def_id: DefId) -> bool; /// Resolve an instance from the given function definition and generic arguments. - fn resolve_instance(&mut self, def: FnDef, args: &GenericArgs) -> Option; + fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option; } // A thread local variable that stores a pointer to the tables mapping between TyCtxt // datastructures and stable MIR datastructures -scoped_thread_local! (static TLV: Cell<*mut ()>); +scoped_thread_local! (static TLV: Cell<*const ()>); -pub fn run(mut context: impl Context, f: impl FnOnce()) { +pub fn run(context: impl Context, f: impl FnOnce()) { assert!(!TLV.is_set()); - fn g<'a>(mut context: &mut (dyn Context + 'a), f: impl FnOnce()) { - let ptr: *mut () = &mut context as *mut &mut _ as _; + fn g<'a>(context: &(dyn Context + 'a), f: impl FnOnce()) { + let ptr: *const () = &context as *const &_ as _; TLV.set(&Cell::new(ptr), || { f(); }); } - g(&mut context, f); + g(&context, f); } /// Loads the current context and calls a function with it. /// Do not nest these, as that will ICE. -pub fn with(f: impl FnOnce(&mut dyn Context) -> R) -> R { +pub fn with(f: impl FnOnce(&dyn Context) -> R) -> R { assert!(TLV.is_set()); TLV.with(|tlv| { let ptr = tlv.get(); assert!(!ptr.is_null()); - f(unsafe { *(ptr as *mut &mut dyn Context) }) + f(unsafe { *(ptr as *const &dyn Context) }) }) } From f613b26cfbfea5d7b1afbbad57be8e5774669775 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Mon, 23 Oct 2023 12:02:17 -0700 Subject: [PATCH 2/4] Add `internal()` method counterpart to `stable()` Note: We do not expect to provide internalizing methods for all StableMIR constructs. They exist only to help migrating efforts to allow users to mix StableMIR and internal constructs. --- compiler/rustc_smir/src/rustc_internal/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 7bec946788b31..58cdcd49087e5 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -26,6 +26,10 @@ pub unsafe fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T { with_tables(|tables| item.stable(tables)) } +pub unsafe fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T { + with_tables(|tables| item.internal(tables)) +} + impl<'tcx> Index for Tables<'tcx> { type Output = DefId; @@ -285,7 +289,7 @@ impl Index { +pub trait RustcInternal<'tcx> { type T; fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T; } From 421631a3a1fb4fe5f12d3212c070f95ea501471e Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Mon, 23 Oct 2023 14:21:24 -0700 Subject: [PATCH 3/4] Remove unsafe and `Rc` --- compiler/rustc_smir/src/rustc_internal/mod.rs | 22 ++++++++----------- compiler/rustc_smir/src/rustc_smir/mod.rs | 2 +- compiler/stable_mir/src/lib.rs | 13 +++++------ 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 58cdcd49087e5..efbf9eba04c34 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -18,15 +18,14 @@ use std::cell::RefCell; use std::fmt::Debug; use std::hash::Hash; use std::ops::Index; -use std::rc::Rc; mod internal; -pub unsafe fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T { +pub fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T { with_tables(|tables| item.stable(tables)) } -pub unsafe fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T { +pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T { with_tables(|tables| item.internal(tables)) } @@ -141,15 +140,12 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { // datastructures and stable MIR datastructures scoped_thread_local! (static TLV: Cell<*const ()>); -pub(crate) fn init<'tcx>(tables: TablesWrapper<'tcx>, f: impl FnOnce()) { +pub(crate) fn init<'tcx>(tables: &TablesWrapper<'tcx>, f: impl FnOnce()) { assert!(!TLV.is_set()); - fn g<'a, 'tcx>(context: &'a TablesWrapper<'tcx>, f: impl FnOnce()) { - let ptr: *const () = &context as *const &_ as _; - TLV.set(&Cell::new(ptr), || { - f(); - }); - } - g(&tables, f); + let ptr: *const () = &tables as *const &_ as _; + TLV.set(&Cell::new(ptr), || { + f(); + }); } /// Loads the current context and calls a function with it. @@ -166,7 +162,7 @@ pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R } pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { - let tables = Rc::new(RefCell::new(Tables { + let tables = TablesWrapper(RefCell::new(Tables { tcx, def_ids: IndexMap::default(), alloc_ids: IndexMap::default(), @@ -174,7 +170,7 @@ pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { types: vec![], instances: IndexMap::default(), })); - stable_mir::run(TablesWrapper(Rc::clone(&tables)), || init(TablesWrapper(tables), f)); + stable_mir::run(&tables, || init(&tables, f)); } #[macro_export] diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 19ad9898db168..d5a5f800a40c0 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -279,7 +279,7 @@ impl PartialEq for MaybeStable { } } -pub(crate) struct TablesWrapper<'tcx>(pub(crate) std::rc::Rc>>); +pub(crate) struct TablesWrapper<'tcx>(pub(crate) RefCell>); pub struct Tables<'tcx> { pub(crate) tcx: TyCtxt<'tcx>, diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 512c3fc629645..8cacbdbda487f 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -243,15 +243,12 @@ pub trait Context { // datastructures and stable MIR datastructures scoped_thread_local! (static TLV: Cell<*const ()>); -pub fn run(context: impl Context, f: impl FnOnce()) { +pub fn run(context: &dyn Context, f: impl FnOnce()) { assert!(!TLV.is_set()); - fn g<'a>(context: &(dyn Context + 'a), f: impl FnOnce()) { - let ptr: *const () = &context as *const &_ as _; - TLV.set(&Cell::new(ptr), || { - f(); - }); - } - g(&context, f); + let ptr: *const () = &context as *const &_ as _; + TLV.set(&Cell::new(ptr), || { + f(); + }); } /// Loads the current context and calls a function with it. From ae86f59cc9dd7d4be3c47d9ecbc3b98ca1f514a8 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Mon, 23 Oct 2023 21:35:30 -0700 Subject: [PATCH 4/4] Add test and remove double ref --- compiler/rustc_smir/src/rustc_internal/mod.rs | 6 +- .../ui-fulldeps/stable-mir/check_instance.rs | 33 +++++----- tests/ui-fulldeps/stable-mir/smir_internal.rs | 64 +++++++++++++++++++ 3 files changed, 85 insertions(+), 18 deletions(-) create mode 100644 tests/ui-fulldeps/stable-mir/smir_internal.rs diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index efbf9eba04c34..d3ea8cdc699a0 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -142,7 +142,7 @@ scoped_thread_local! (static TLV: Cell<*const ()>); pub(crate) fn init<'tcx>(tables: &TablesWrapper<'tcx>, f: impl FnOnce()) { assert!(!TLV.is_set()); - let ptr: *const () = &tables as *const &_ as _; + let ptr = tables as *const _ as *const (); TLV.set(&Cell::new(ptr), || { f(); }); @@ -155,8 +155,8 @@ pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R TLV.with(|tlv| { let ptr = tlv.get(); assert!(!ptr.is_null()); - let wrapper = unsafe { *(ptr as *const &TablesWrapper<'tcx>) }; - let mut tables = wrapper.0.borrow_mut(); + let wrapper = ptr as *const TablesWrapper<'tcx>; + let mut tables = unsafe { (*wrapper).0.borrow_mut() }; f(&mut *tables) }) } diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index c6a9e08ed0260..ee82bc77aedae 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -1,5 +1,5 @@ // run-pass -// Test that users are able to use stable mir APIs to retrieve monomorphized instances +//! Test that users are able to use stable mir APIs to retrieve monomorphized instances // ignore-stage1 // ignore-cross-compile @@ -14,15 +14,15 @@ extern crate rustc_middle; #[macro_use] extern crate rustc_smir; -extern crate stable_mir; extern crate rustc_driver; extern crate rustc_interface; +extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use mir::{mono::Instance, TerminatorKind::*}; -use stable_mir::ty::{TyKind, RigidTy}; -use stable_mir::*; +use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; +use stable_mir::ty::{RigidTy, TyKind}; +use stable_mir::*; use std::io::Write; use std::ops::ControlFlow; @@ -33,16 +33,16 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { let items = stable_mir::all_local_items(); // Get all items and split generic vs monomorphic items. - let (generic, mono) : (Vec<_>, Vec<_>) = items.into_iter().partition(|item| { - item.requires_monomorphization() - }); + let (generic, mono): (Vec<_>, Vec<_>) = + items.into_iter().partition(|item| item.requires_monomorphization()); assert_eq!(mono.len(), 3, "Expected 2 mono functions and one constant"); assert_eq!(generic.len(), 2, "Expected 2 generic functions"); // For all monomorphic items, get the correspondent instances. - let instances = mono.iter().filter_map(|item| { - mir::mono::Instance::try_from(*item).ok() - }).collect::>(); + let instances = mono + .iter() + .filter_map(|item| mir::mono::Instance::try_from(*item).ok()) + .collect::>(); assert_eq!(instances.len(), mono.len()); // For all generic items, try_from should fail. @@ -58,19 +58,22 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { fn test_body(body: mir::Body) { for term in body.blocks.iter().map(|bb| &bb.terminator) { match &term.kind { - Call{ func, .. } => { + Call { func, .. } => { let TyKind::RigidTy(ty) = func.ty(&body.locals).kind() else { unreachable!() }; let RigidTy::FnDef(def, args) = ty else { unreachable!() }; let result = Instance::resolve(def, &args); assert!(result.is_ok()); } - Goto {..} | Assert{..} | SwitchInt{..} | Return | Drop {..} => { /* Do nothing */} - _ => { unreachable!("Unexpected terminator {term:?}") } + Goto { .. } | Assert { .. } | SwitchInt { .. } | Return | Drop { .. } => { + /* Do nothing */ + } + _ => { + unreachable!("Unexpected terminator {term:?}") + } } } } - /// 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 `StableMir` using custom arguments and then diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs new file mode 100644 index 0000000000000..5ad05559cb4bb --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs @@ -0,0 +1,64 @@ +// run-pass +//! Test that users are able to use retrieve internal constructs from stable ones to help with +//! the migration. + +// ignore-stage1 +// ignore-cross-compile +// ignore-remote +// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 +// edition: 2021 + +#![feature(rustc_private)] +#![feature(assert_matches)] +#![feature(control_flow_enum)] + +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate rustc_middle; +extern crate stable_mir; + +use rustc_middle::ty::TyCtxt; +use rustc_smir::rustc_internal; +use std::io::Write; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "input"; + +fn test_translation(_tcx: TyCtxt<'_>) -> ControlFlow<()> { + let main_fn = stable_mir::entry_fn().unwrap(); + let body = main_fn.body(); + let orig_ty = body.locals[0].ty; + let rustc_ty = rustc_internal::internal(&orig_ty); + assert!(rustc_ty.is_unit()); + 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 `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "internal_input.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, tcx, test_translation(tcx)).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + pub fn main() {{ + }} + "# + )?; + Ok(()) +}