From fa2aa1cedbe258fe13e8cb0933da95810a8f34ed Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 31 Oct 2022 11:04:03 +0100 Subject: interpret: move type_name implementation to an interpreter-independent helper file --- .../rustc_const_eval/src/interpret/intrinsics.rs | 14 +- .../src/interpret/intrinsics/type_name.rs | 201 --------------------- compiler/rustc_const_eval/src/util/mod.rs | 2 + compiler/rustc_const_eval/src/util/type_name.rs | 197 ++++++++++++++++++++ 4 files changed, 210 insertions(+), 204 deletions(-) delete mode 100644 compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs create mode 100644 compiler/rustc_const_eval/src/util/type_name.rs (limited to 'compiler/rustc_const_eval/src') diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 8637d6a7767..b92a6878847 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -7,7 +7,9 @@ use std::convert::TryFrom; use rustc_hir::def_id::DefId; use rustc_middle::mir::{ self, - interpret::{ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar}, + interpret::{ + Allocation, ConstAllocation, ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar, + }, BinOp, NonDivergingIntrinsic, }; use rustc_middle::ty; @@ -23,7 +25,6 @@ use super::{ }; mod caller_location; -mod type_name; fn numeric_intrinsic(name: Symbol, bits: u128, kind: Primitive) -> Scalar { let size = match kind { @@ -42,6 +43,13 @@ fn numeric_intrinsic(name: Symbol, bits: u128, kind: Primitive) -> Scalar< Scalar::from_uint(bits_out, size) } +/// Directly returns an `Allocation` containing an absolute path representation of the given type. +pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> { + let path = crate::util::type_name(tcx, ty); + let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes()); + tcx.intern_const_alloc(alloc) +} + /// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated /// inside an `InterpCx` and instead have their value computed directly from rustc internal info. pub(crate) fn eval_nullary_intrinsic<'tcx>( @@ -55,7 +63,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( Ok(match name { sym::type_name => { ensure_monomorphic_enough(tcx, tp_ty)?; - let alloc = type_name::alloc_type_name(tcx, tp_ty); + let alloc = alloc_type_name(tcx, tp_ty); ConstValue::Slice { data: alloc, start: 0, end: alloc.inner().len() } } sym::needs_drop => { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs deleted file mode 100644 index b15606baee5..00000000000 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs +++ /dev/null @@ -1,201 +0,0 @@ -use rustc_data_structures::intern::Interned; -use rustc_hir::def_id::CrateNum; -use rustc_hir::definitions::DisambiguatedDefPathData; -use rustc_middle::mir::interpret::{Allocation, ConstAllocation}; -use rustc_middle::ty::{ - self, - print::{PrettyPrinter, Print, Printer}, - subst::{GenericArg, GenericArgKind}, - Ty, TyCtxt, -}; -use std::fmt::Write; - -struct AbsolutePathPrinter<'tcx> { - tcx: TyCtxt<'tcx>, - path: String, -} - -impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { - type Error = std::fmt::Error; - - type Path = Self; - type Region = Self; - type Type = Self; - type DynExistential = Self; - type Const = Self; - - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn print_region(self, _region: ty::Region<'_>) -> Result { - Ok(self) - } - - fn print_type(mut self, ty: Ty<'tcx>) -> Result { - match *ty.kind() { - // Types without identity. - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Str - | ty::Array(_, _) - | ty::Slice(_) - | ty::RawPtr(_) - | ty::Ref(_, _, _) - | ty::FnPtr(_) - | ty::Never - | ty::Tuple(_) - | ty::Dynamic(_, _, _) => self.pretty_print_type(ty), - - // Placeholders (all printed as `_` to uniformize them). - ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => { - write!(self, "_")?; - Ok(self) - } - - // Types with identity (print the module path). - ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs) - | ty::FnDef(def_id, substs) - | ty::Opaque(def_id, substs) - | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) - | ty::Closure(def_id, substs) - | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs), - ty::Foreign(def_id) => self.print_def_path(def_id, &[]), - - ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"), - } - } - - fn print_const(self, ct: ty::Const<'tcx>) -> Result { - self.pretty_print_const(ct, false) - } - - fn print_dyn_existential( - mut self, - predicates: &'tcx ty::List>>, - ) -> Result { - let mut first = true; - for p in predicates { - if !first { - write!(self, "+")?; - } - first = false; - self = p.print(self)?; - } - Ok(self) - } - - fn path_crate(mut self, cnum: CrateNum) -> Result { - self.path.push_str(self.tcx.crate_name(cnum).as_str()); - Ok(self) - } - - fn path_qualified( - self, - self_ty: Ty<'tcx>, - trait_ref: Option>, - ) -> Result { - self.pretty_path_qualified(self_ty, trait_ref) - } - - fn path_append_impl( - self, - print_prefix: impl FnOnce(Self) -> Result, - _disambiguated_data: &DisambiguatedDefPathData, - self_ty: Ty<'tcx>, - trait_ref: Option>, - ) -> Result { - self.pretty_path_append_impl( - |mut cx| { - cx = print_prefix(cx)?; - - cx.path.push_str("::"); - - Ok(cx) - }, - self_ty, - trait_ref, - ) - } - - fn path_append( - mut self, - print_prefix: impl FnOnce(Self) -> Result, - disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { - self = print_prefix(self)?; - - write!(self.path, "::{}", disambiguated_data.data).unwrap(); - - Ok(self) - } - - fn path_generic_args( - mut self, - print_prefix: impl FnOnce(Self) -> Result, - args: &[GenericArg<'tcx>], - ) -> Result { - self = print_prefix(self)?; - let args = - args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_))); - if args.clone().next().is_some() { - self.generic_delimiters(|cx| cx.comma_sep(args)) - } else { - Ok(self) - } - } -} - -impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { - fn should_print_region(&self, _region: ty::Region<'_>) -> bool { - false - } - fn comma_sep(mut self, mut elems: impl Iterator) -> Result - where - T: Print<'tcx, Self, Output = Self, Error = Self::Error>, - { - if let Some(first) = elems.next() { - self = first.print(self)?; - for elem in elems { - self.path.push_str(", "); - self = elem.print(self)?; - } - } - Ok(self) - } - - fn generic_delimiters( - mut self, - f: impl FnOnce(Self) -> Result, - ) -> Result { - write!(self, "<")?; - - self = f(self)?; - - write!(self, ">")?; - - Ok(self) - } - - fn should_print_verbose(&self) -> bool { - // `std::any::type_name` should never print verbose type names - false - } -} - -impl Write for AbsolutePathPrinter<'_> { - fn write_str(&mut self, s: &str) -> std::fmt::Result { - self.path.push_str(s); - Ok(()) - } -} - -/// Directly returns an `Allocation` containing an absolute path representation of the given type. -pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> { - let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path; - let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes()); - tcx.intern_const_alloc(alloc) -} diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs index 7a05cfd235f..4d0f81a4060 100644 --- a/compiler/rustc_const_eval/src/util/mod.rs +++ b/compiler/rustc_const_eval/src/util/mod.rs @@ -4,9 +4,11 @@ mod call_kind; pub mod collect_writes; mod find_self_call; mod might_permit_raw_init; +mod type_name; pub use self::aggregate::expand_aggregate; pub use self::alignment::is_disaligned; pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind}; pub use self::find_self_call::find_self_call; pub use self::might_permit_raw_init::might_permit_raw_init; +pub use self::type_name::type_name; diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs new file mode 100644 index 00000000000..221efc6f981 --- /dev/null +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -0,0 +1,197 @@ +use rustc_data_structures::intern::Interned; +use rustc_hir::def_id::CrateNum; +use rustc_hir::definitions::DisambiguatedDefPathData; +use rustc_middle::ty::{ + self, + print::{PrettyPrinter, Print, Printer}, + subst::{GenericArg, GenericArgKind}, + Ty, TyCtxt, +}; +use std::fmt::Write; + +struct AbsolutePathPrinter<'tcx> { + tcx: TyCtxt<'tcx>, + path: String, +} + +impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { + type Error = std::fmt::Error; + + type Path = Self; + type Region = Self; + type Type = Self; + type DynExistential = Self; + type Const = Self; + + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn print_region(self, _region: ty::Region<'_>) -> Result { + Ok(self) + } + + fn print_type(mut self, ty: Ty<'tcx>) -> Result { + match *ty.kind() { + // Types without identity. + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Str + | ty::Array(_, _) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::Ref(_, _, _) + | ty::FnPtr(_) + | ty::Never + | ty::Tuple(_) + | ty::Dynamic(_, _, _) => self.pretty_print_type(ty), + + // Placeholders (all printed as `_` to uniformize them). + ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => { + write!(self, "_")?; + Ok(self) + } + + // Types with identity (print the module path). + ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs) + | ty::FnDef(def_id, substs) + | ty::Opaque(def_id, substs) + | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) + | ty::Closure(def_id, substs) + | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs), + ty::Foreign(def_id) => self.print_def_path(def_id, &[]), + + ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"), + } + } + + fn print_const(self, ct: ty::Const<'tcx>) -> Result { + self.pretty_print_const(ct, false) + } + + fn print_dyn_existential( + mut self, + predicates: &'tcx ty::List>>, + ) -> Result { + let mut first = true; + for p in predicates { + if !first { + write!(self, "+")?; + } + first = false; + self = p.print(self)?; + } + Ok(self) + } + + fn path_crate(mut self, cnum: CrateNum) -> Result { + self.path.push_str(self.tcx.crate_name(cnum).as_str()); + Ok(self) + } + + fn path_qualified( + self, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + self.pretty_path_qualified(self_ty, trait_ref) + } + + fn path_append_impl( + self, + print_prefix: impl FnOnce(Self) -> Result, + _disambiguated_data: &DisambiguatedDefPathData, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + self.pretty_path_append_impl( + |mut cx| { + cx = print_prefix(cx)?; + + cx.path.push_str("::"); + + Ok(cx) + }, + self_ty, + trait_ref, + ) + } + + fn path_append( + mut self, + print_prefix: impl FnOnce(Self) -> Result, + disambiguated_data: &DisambiguatedDefPathData, + ) -> Result { + self = print_prefix(self)?; + + write!(self.path, "::{}", disambiguated_data.data).unwrap(); + + Ok(self) + } + + fn path_generic_args( + mut self, + print_prefix: impl FnOnce(Self) -> Result, + args: &[GenericArg<'tcx>], + ) -> Result { + self = print_prefix(self)?; + let args = + args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_))); + if args.clone().next().is_some() { + self.generic_delimiters(|cx| cx.comma_sep(args)) + } else { + Ok(self) + } + } +} + +impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { + fn should_print_region(&self, _region: ty::Region<'_>) -> bool { + false + } + fn comma_sep(mut self, mut elems: impl Iterator) -> Result + where + T: Print<'tcx, Self, Output = Self, Error = Self::Error>, + { + if let Some(first) = elems.next() { + self = first.print(self)?; + for elem in elems { + self.path.push_str(", "); + self = elem.print(self)?; + } + } + Ok(self) + } + + fn generic_delimiters( + mut self, + f: impl FnOnce(Self) -> Result, + ) -> Result { + write!(self, "<")?; + + self = f(self)?; + + write!(self, ">")?; + + Ok(self) + } + + fn should_print_verbose(&self) -> bool { + // `std::any::type_name` should never print verbose type names + false + } +} + +impl Write for AbsolutePathPrinter<'_> { + fn write_str(&mut self, s: &str) -> std::fmt::Result { + self.path.push_str(s); + Ok(()) + } +} + +pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> String { + AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path +} -- cgit 1.4.1-3-g733a5