rustc_const_eval/util/
caller_location.rs1use rustc_abi::FieldIdx;
2use rustc_hir::LangItem;
3use rustc_middle::ty::{self, TyCtxt};
4use rustc_middle::{bug, mir};
5use rustc_span::Symbol;
6use tracing::trace;
7
8use crate::const_eval::{CanAccessMutGlobal, CompileTimeInterpCx, mk_eval_cx_to_read_const_val};
9use crate::interpret::*;
10
11fn alloc_caller_location<'tcx>(
13 ecx: &mut CompileTimeInterpCx<'tcx>,
14 filename: Symbol,
15 line: u32,
16 col: u32,
17) -> MPlaceTy<'tcx> {
18 assert!(!filename.as_str().as_bytes().contains(&0));
22
23 let loc_details = ecx.tcx.sess.opts.unstable_opts.location_detail;
24 let filename = {
25 let filename = if loc_details.file { filename.as_str() } else { "<redacted>" };
26 let filename_with_nul = filename.to_owned() + "\0";
27 let file_ptr = ecx.allocate_bytes_dedup(filename_with_nul.as_bytes()).unwrap();
30 let file_len = u64::try_from(filename.len()).unwrap();
31 Immediate::new_slice(file_ptr.into(), file_len, ecx)
32 };
33 let line = if loc_details.line { Scalar::from_u32(line) } else { Scalar::from_u32(0) };
34 let col = if loc_details.column { Scalar::from_u32(col) } else { Scalar::from_u32(0) };
35
36 let loc_ty = ecx
38 .tcx
39 .type_of(ecx.tcx.require_lang_item(LangItem::PanicLocation, ecx.tcx.span))
40 .instantiate(*ecx.tcx, ecx.tcx.mk_args(&[ecx.tcx.lifetimes.re_erased.into()]));
41 let loc_layout = ecx.layout_of(loc_ty).unwrap();
42 let location = ecx.allocate(loc_layout, MemoryKind::CallerLocation).unwrap();
43
44 ecx.write_immediate(filename, &ecx.project_field(&location, FieldIdx::from_u32(0)).unwrap())
46 .expect("writing to memory we just allocated cannot fail");
47 ecx.write_scalar(line, &ecx.project_field(&location, FieldIdx::from_u32(1)).unwrap())
48 .expect("writing to memory we just allocated cannot fail");
49 ecx.write_scalar(col, &ecx.project_field(&location, FieldIdx::from_u32(2)).unwrap())
50 .expect("writing to memory we just allocated cannot fail");
51
52 location
53}
54
55pub(crate) fn const_caller_location_provider(
56 tcx: TyCtxt<'_>,
57 file: Symbol,
58 line: u32,
59 col: u32,
60) -> mir::ConstValue<'_> {
61 trace!("const_caller_location: {}:{}:{}", file, line, col);
62 let mut ecx = mk_eval_cx_to_read_const_val(
63 tcx,
64 rustc_span::DUMMY_SP, ty::TypingEnv::fully_monomorphized(),
66 CanAccessMutGlobal::No,
67 );
68
69 let loc_place = alloc_caller_location(&mut ecx, file, line, col);
70 if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
71 bug!("intern_const_alloc_recursive should not error in this case")
72 }
73 mir::ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr(), &tcx))
74}