summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_const_eval/src/util
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_const_eval/src/util
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_const_eval/src/util')
-rw-r--r--compiler/rustc_const_eval/src/util/alignment.rs10
-rw-r--r--compiler/rustc_const_eval/src/util/caller_location.rs66
-rw-r--r--compiler/rustc_const_eval/src/util/mod.rs1
-rw-r--r--compiler/rustc_const_eval/src/util/type_name.rs92
4 files changed, 119 insertions, 50 deletions
diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs
index 2e0643afb..8642dfccd 100644
--- a/compiler/rustc_const_eval/src/util/alignment.rs
+++ b/compiler/rustc_const_eval/src/util/alignment.rs
@@ -21,10 +21,18 @@ where
};
let ty = place.ty(local_decls, tcx).ty;
+ let unsized_tail = || tcx.struct_tail_with_normalize(ty, |ty| ty, || {});
match tcx.layout_of(param_env.and(ty)) {
- Ok(layout) if layout.align.abi <= pack => {
+ Ok(layout)
+ if layout.align.abi <= pack
+ && (layout.is_sized()
+ || matches!(unsized_tail().kind(), ty::Slice(..) | ty::Str)) =>
+ {
// If the packed alignment is greater or equal to the field alignment, the type won't be
// further disaligned.
+ // However we need to ensure the field is sized; for unsized fields, `layout.align` is
+ // just an approximation -- except when the unsized tail is a slice, where the alignment
+ // is fully determined by the type.
debug!(
"is_disaligned({:?}) - align = {}, packed = {}; not disaligned",
place,
diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs
new file mode 100644
index 000000000..4a3cfd50b
--- /dev/null
+++ b/compiler/rustc_const_eval/src/util/caller_location.rs
@@ -0,0 +1,66 @@
+use rustc_hir::LangItem;
+use rustc_middle::mir;
+use rustc_middle::query::TyCtxtAt;
+use rustc_middle::ty;
+use rustc_middle::ty::layout::LayoutOf;
+use rustc_span::symbol::Symbol;
+use rustc_type_ir::Mutability;
+
+use crate::const_eval::{mk_eval_cx, CanAccessStatics, CompileTimeEvalContext};
+use crate::interpret::*;
+
+/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
+fn alloc_caller_location<'mir, 'tcx>(
+ ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
+ filename: Symbol,
+ line: u32,
+ col: u32,
+) -> MPlaceTy<'tcx> {
+ let loc_details = ecx.tcx.sess.opts.unstable_opts.location_detail;
+ // This can fail if rustc runs out of memory right here. Trying to emit an error would be
+ // pointless, since that would require allocating more memory than these short strings.
+ let file = if loc_details.file {
+ ecx.allocate_str(filename.as_str(), MemoryKind::CallerLocation, Mutability::Not).unwrap()
+ } else {
+ // FIXME: This creates a new allocation each time. It might be preferable to
+ // perform this allocation only once, and re-use the `MPlaceTy`.
+ // See https://github.com/rust-lang/rust/pull/89920#discussion_r730012398
+ ecx.allocate_str("<redacted>", MemoryKind::CallerLocation, Mutability::Not).unwrap()
+ };
+ let line = if loc_details.line { Scalar::from_u32(line) } else { Scalar::from_u32(0) };
+ let col = if loc_details.column { Scalar::from_u32(col) } else { Scalar::from_u32(0) };
+
+ // Allocate memory for `CallerLocation` struct.
+ let loc_ty = ecx
+ .tcx
+ .type_of(ecx.tcx.require_lang_item(LangItem::PanicLocation, None))
+ .instantiate(*ecx.tcx, ecx.tcx.mk_args(&[ecx.tcx.lifetimes.re_erased.into()]));
+ let loc_layout = ecx.layout_of(loc_ty).unwrap();
+ let location = ecx.allocate(loc_layout, MemoryKind::CallerLocation).unwrap();
+
+ // Initialize fields.
+ ecx.write_immediate(file.to_ref(ecx), &ecx.project_field(&location, 0).unwrap())
+ .expect("writing to memory we just allocated cannot fail");
+ ecx.write_scalar(line, &ecx.project_field(&location, 1).unwrap())
+ .expect("writing to memory we just allocated cannot fail");
+ ecx.write_scalar(col, &ecx.project_field(&location, 2).unwrap())
+ .expect("writing to memory we just allocated cannot fail");
+
+ location
+}
+
+pub(crate) fn const_caller_location_provider(
+ tcx: TyCtxtAt<'_>,
+ file: Symbol,
+ line: u32,
+ col: u32,
+) -> mir::ConstValue<'_> {
+ trace!("const_caller_location: {}:{}:{}", file, line, col);
+ let mut ecx = mk_eval_cx(tcx.tcx, tcx.span, ty::ParamEnv::reveal_all(), CanAccessStatics::No);
+
+ let loc_place = alloc_caller_location(&mut ecx, file, line, col);
+ if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
+ bug!("intern_const_alloc_recursive should not error in this case")
+ }
+ mir::ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr(), &tcx))
+}
diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs
index 040b3071e..1e58bd645 100644
--- a/compiler/rustc_const_eval/src/util/mod.rs
+++ b/compiler/rustc_const_eval/src/util/mod.rs
@@ -1,6 +1,7 @@
use rustc_middle::mir;
mod alignment;
+pub(crate) mod caller_location;
mod check_validity_requirement;
mod compare_types;
mod type_name;
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index a924afda6..a82b65b19 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -3,7 +3,7 @@ use rustc_hir::def_id::CrateNum;
use rustc_hir::definitions::DisambiguatedDefPathData;
use rustc_middle::ty::{
self,
- print::{PrettyPrinter, Print, Printer},
+ print::{PrettyPrinter, Print, PrintError, Printer},
GenericArg, GenericArgKind, Ty, TyCtxt,
};
use std::fmt::Write;
@@ -14,23 +14,15 @@ struct AbsolutePathPrinter<'tcx> {
}
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<Self::Region, Self::Error> {
- Ok(self)
+ fn print_region(&mut self, _region: ty::Region<'_>) -> Result<(), PrintError> {
+ Ok(())
}
- fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
+ fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
match *ty.kind() {
// Types without identity.
ty::Bool
@@ -51,7 +43,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
// Placeholders (all printed as `_` to uniformize them).
ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => {
write!(self, "_")?;
- Ok(self)
+ Ok(())
}
// Types with identity (print the module path).
@@ -59,53 +51,53 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
| ty::FnDef(def_id, args)
| ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
| ty::Closure(def_id, args)
- | ty::Generator(def_id, args, _) => self.print_def_path(def_id, args),
+ | ty::Coroutine(def_id, args, _) => self.print_def_path(def_id, args),
ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
ty::Alias(ty::Weak, _) => bug!("type_name: unexpected weak projection"),
ty::Alias(ty::Inherent, _) => bug!("type_name: unexpected inherent projection"),
- ty::GeneratorWitness(..) => bug!("type_name: unexpected `GeneratorWitness`"),
+ ty::CoroutineWitness(..) => bug!("type_name: unexpected `CoroutineWitness`"),
}
}
- fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
+ fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
self.pretty_print_const(ct, false)
}
fn print_dyn_existential(
- self,
+ &mut self,
predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
- ) -> Result<Self::DynExistential, Self::Error> {
+ ) -> Result<(), PrintError> {
self.pretty_print_dyn_existential(predicates)
}
- fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
+ fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
self.path.push_str(self.tcx.crate_name(cnum).as_str());
- Ok(self)
+ Ok(())
}
fn path_qualified(
- self,
+ &mut self,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
- ) -> Result<Self::Path, Self::Error> {
+ ) -> Result<(), PrintError> {
self.pretty_path_qualified(self_ty, trait_ref)
}
fn path_append_impl(
- self,
- print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+ &mut self,
+ print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
_disambiguated_data: &DisambiguatedDefPathData,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
- ) -> Result<Self::Path, Self::Error> {
+ ) -> Result<(), PrintError> {
self.pretty_path_append_impl(
- |mut cx| {
- cx = print_prefix(cx)?;
+ |cx| {
+ print_prefix(cx)?;
cx.path.push_str("::");
- Ok(cx)
+ Ok(())
},
self_ty,
trait_ref,
@@ -113,29 +105,29 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
}
fn path_append(
- mut self,
- print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+ &mut self,
+ print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
disambiguated_data: &DisambiguatedDefPathData,
- ) -> Result<Self::Path, Self::Error> {
- self = print_prefix(self)?;
+ ) -> Result<(), PrintError> {
+ print_prefix(self)?;
write!(self.path, "::{}", disambiguated_data.data).unwrap();
- Ok(self)
+ Ok(())
}
fn path_generic_args(
- mut self,
- print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+ &mut self,
+ print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
args: &[GenericArg<'tcx>],
- ) -> Result<Self::Path, Self::Error> {
- self = print_prefix(self)?;
+ ) -> Result<(), PrintError> {
+ 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)
+ Ok(())
}
}
}
@@ -144,31 +136,31 @@ impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> {
fn should_print_region(&self, _region: ty::Region<'_>) -> bool {
false
}
- fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Self::Error>
+ fn comma_sep<T>(&mut self, mut elems: impl Iterator<Item = T>) -> Result<(), PrintError>
where
- T: Print<'tcx, Self, Output = Self, Error = Self::Error>,
+ T: Print<'tcx, Self>,
{
if let Some(first) = elems.next() {
- self = first.print(self)?;
+ first.print(self)?;
for elem in elems {
self.path.push_str(", ");
- self = elem.print(self)?;
+ elem.print(self)?;
}
}
- Ok(self)
+ Ok(())
}
fn generic_delimiters(
- mut self,
- f: impl FnOnce(Self) -> Result<Self, Self::Error>,
- ) -> Result<Self, Self::Error> {
+ &mut self,
+ f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
+ ) -> Result<(), PrintError> {
write!(self, "<")?;
- self = f(self)?;
+ f(self)?;
write!(self, ">")?;
- Ok(self)
+ Ok(())
}
fn should_print_verbose(&self) -> bool {
@@ -185,5 +177,7 @@ impl Write for AbsolutePathPrinter<'_> {
}
pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> String {
- AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path
+ let mut printer = AbsolutePathPrinter { tcx, path: String::new() };
+ printer.print_type(ty).unwrap();
+ printer.path
}