line: u32,
col: u32,
) -> MPlaceTy<'tcx, M::PointerTag> {
- let file =
- self.allocate_str(&filename.as_str(), MemoryKind::CallerLocation, Mutability::Not);
- let line = Scalar::from_u32(line);
- let col = Scalar::from_u32(col);
+ let loc_details = &self.tcx.sess.opts.debugging_opts.location_detail;
+ let file = if loc_details.file {
+ self.allocate_str(&filename.as_str(), MemoryKind::CallerLocation, Mutability::Not)
+ } 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
+ self.allocate_str("<redacted>", MemoryKind::CallerLocation, Mutability::Not)
+ };
+ 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 = self
use rustc_session::config::InstrumentCoverage;
use rustc_session::config::Strip;
use rustc_session::config::{build_configuration, build_session_options, to_crate_config};
-use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
+use rustc_session::config::{
+ rustc_optgroups, ErrorOutputType, ExternLocation, LocationDetail, Options, Passes,
+};
use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
use rustc_session::config::{
Externs, OutputType, OutputTypes, SymbolManglingVersion, WasiExecModel,
tracked!(instrument_mcount, true);
tracked!(link_only, true);
tracked!(llvm_plugins, vec![String::from("plugin_name")]);
+ tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
tracked!(merge_functions, Some(MergeFunctions::Disabled));
tracked!(mir_emit_retag, true);
tracked!(mir_opt_level, Some(4));
}
}
+/// The different settings that can be enabled via the `-Z location-detail` flag.
+#[derive(Clone, PartialEq, Hash, Debug)]
+pub struct LocationDetail {
+ pub file: bool,
+ pub line: bool,
+ pub column: bool,
+}
+
+impl LocationDetail {
+ pub fn all() -> Self {
+ Self { file: true, line: true, column: true }
+ }
+}
+
#[derive(Clone, PartialEq, Hash, Debug)]
pub enum SwitchWithOptPath {
Enabled(Option<PathBuf>),
use super::LdImpl;
use super::{
CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto,
- LtoCli, OptLevel, OutputType, OutputTypes, Passes, SourceFileHashAlgorithm,
+ LocationDetail, LtoCli, OptLevel, OutputType, OutputTypes, Passes, SourceFileHashAlgorithm,
SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths,
};
use crate::lint;
Option<LdImpl>,
OutputType,
RealFileName,
+ LocationDetail,
);
impl<T1, T2> DepTrackingHash for (T1, T2)
"either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted";
pub const parse_linker_plugin_lto: &str =
"either a boolean (`yes`, `no`, `on`, `off`, etc), or the path to the linker plugin";
+ pub const parse_location_detail: &str =
+ "comma seperated list of location details to track: `file`, `line`, or `column`";
pub const parse_switch_with_opt_path: &str =
"an optional path to the profiling data output directory";
pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`";
}
}
+ crate fn parse_location_detail(ld: &mut LocationDetail, v: Option<&str>) -> bool {
+ if let Some(v) = v {
+ ld.line = false;
+ ld.file = false;
+ ld.column = false;
+ for s in v.split(',') {
+ match s {
+ "file" => ld.file = true,
+ "line" => ld.line = true,
+ "column" => ld.column = true,
+ _ => return false,
+ }
+ }
+ true
+ } else {
+ false
+ }
+ }
+
crate fn parse_opt_comma_list(slot: &mut Option<Vec<String>>, v: Option<&str>) -> bool {
match v {
Some(s) => {
"a list LLVM plugins to enable (space separated)"),
llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],
"generate JSON tracing data file from LLVM data (default: no)"),
+ location_detail: LocationDetail = (LocationDetail::all(), parse_location_detail, [TRACKED],
+ "comma seperated list of location details to be tracked when using caller_location \
+ valid options are `file`, `line`, and `column` (default: all)"),
ls: bool = (false, parse_bool, [UNTRACKED],
"list the symbols defined by a library crate (default: no)"),
macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
--- /dev/null
+# `location-detail`
+
+The tracking issue for this feature is: [#70580](https://github.com/rust-lang/rust/issues/70580).
+
+------------------------
+
+Option `-Z location-detail=val` controls what location details are tracked when
+using `caller_location`. This allows users to control what location details
+are printed as part of panic messages, by allowing them to exclude any combination
+of filenames, line numbers, and column numbers. This option is intended to provide
+users with a way to mitigate the size impact of `#[track_caller]`.
+
+This option supports a comma separated list of location details to be included. Valid options
+within this list are:
+
+- `file` - the filename of the panic will be included in the panic output
+- `line` - the source line of the panic will be included in the panic output
+- `column` - the source column of the panic will be included in the panic output
+
+Any combination of these three options are supported. If this option is not specified,
+all three are included by default.
+
+An example of a panic output when using `-Z location-detail=line`:
+```text
+panicked at 'Process blink had a fault', <redacted>:323:0
+```
+
+The code size savings from this option are two-fold. First, the `&'static str` values
+for each path to a file containing a panic are removed from the binary. For projects
+with deep directory structures and many files with panics, this can add up. This category
+of savings can only be realized by excluding filenames from the panic output. Second,
+savings can be realized by allowing multiple panics to be fused into a single panicking
+branch. It is often the case that within a single file, multiple panics with the same
+panic message exist -- e.g. two calls to `Option::unwrap()` in a single line, or
+two calls to `Result::expect()` on adjacent lines. If column and line information
+are included in the `Location` struct passed to the panic handler, these branches cannot
+be fused, as the output is different depending on which panic occurs. However if line
+and column information is identical for all panics, these branches can be fused, which
+can lead to substantial code size savings, especially for small embedded binaries with
+many panics.
+
+The savings from this option are amplified when combined with the use of `-Zbuild-std`, as
+otherwise paths for panics within the standard library are still included in your binary.
--- /dev/null
+// run-fail
+// check-run-results
+// compile-flags: -Zlocation-detail=line,file
+
+fn main() {
+ panic!("column-redacted");
+}
--- /dev/null
+thread 'main' panicked at 'column-redacted', $DIR/location-detail-panic-no-column.rs:6:0
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
--- /dev/null
+// run-fail
+// check-run-results
+// compile-flags: -Zlocation-detail=line,column
+
+fn main() {
+ panic!("file-redacted");
+}
--- /dev/null
+thread 'main' panicked at 'file-redacted', <redacted>:6:5
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
--- /dev/null
+// run-fail
+// check-run-results
+// compile-flags: -Zlocation-detail=file,column
+
+fn main() {
+ panic!("line-redacted");
+}
--- /dev/null
+thread 'main' panicked at 'line-redacted', $DIR/location-detail-panic-no-line.rs:0:5
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
--- /dev/null
+// run-fail
+// check-run-results
+// compile-flags: -Zlocation-detail=line,column
+
+fn main() {
+ let opt: Option<u32> = None;
+ opt.unwrap();
+}
--- /dev/null
+thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', <redacted>:7:9
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace