Skip to content

Commit

Permalink
debug-fmt-detail option
Browse files Browse the repository at this point in the history
Allows disabling `fmt::Debug` derive and debug formatting.
  • Loading branch information
kornelski committed Apr 20, 2024
1 parent 8cf135e commit 92cac91
Show file tree
Hide file tree
Showing 32 changed files with 265 additions and 56 deletions.
6 changes: 5 additions & 1 deletion compiler/rustc_ast_lowering/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use rustc_ast::visit::Visitor;
use rustc_ast::*;
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
use rustc_session::config::DebugFmtDetail;
use rustc_span::{
sym,
symbol::{kw, Ident},
Expand Down Expand Up @@ -245,7 +246,10 @@ fn make_argument<'hir>(
hir::LangItem::FormatArgument,
match ty {
Format(Display) => sym::new_display,
Format(Debug) => sym::new_debug,
Format(Debug) => match ctx.tcx.sess.opts.unstable_opts.debug_fmt_detail {
DebugFmtDetail::Full | DebugFmtDetail::Shallow => sym::new_debug,
DebugFmtDetail::None => sym::new_debug_noop,
},
Format(LowerExp) => sym::new_lower_exp,
Format(UpperExp) => sym::new_upper_exp,
Format(Octal) => sym::new_octal,
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_builtin_macros/src/deriving/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::deriving::path_std;

use rustc_ast::{self as ast, EnumDef, MetaItem};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_session::config::DebugFmtDetail;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
use thin_vec::{thin_vec, ThinVec};
Expand Down Expand Up @@ -49,6 +50,11 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) ->
// We want to make sure we have the ctxt set so that we can use unstable methods
let span = cx.with_def_site_ctxt(span);

let fmt_detail = cx.sess.opts.unstable_opts.debug_fmt_detail;
if fmt_detail == DebugFmtDetail::None {
return BlockOrExpr::new_expr(cx.expr_ok(span, cx.expr_tuple(span, ThinVec::new())));
}

let (ident, vdata, fields) = match substr.fields {
Struct(vdata, fields) => (substr.type_ident, *vdata, fields),
EnumMatching(_, v, fields) => (v.ident, &v.data, fields),
Expand All @@ -61,6 +67,13 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) ->
let name = cx.expr_str(span, ident.name);
let fmt = substr.nonselflike_args[0].clone();

// Fieldless enums have been special-cased earlier
if fmt_detail == DebugFmtDetail::Shallow {
let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
let expr = cx.expr_call_global(span, fn_path_write_str, thin_vec![fmt, name]);
return BlockOrExpr::new_expr(expr);
}

// Struct and tuples are similar enough that we use the same code for both,
// with some extra pieces for structs due to the field names.
let (is_struct, args_per_field) = match vdata {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ const GATED_CFGS: &[GatedCfg] = &[
(sym::relocation_model, sym::cfg_relocation_model, cfg_fn!(cfg_relocation_model)),
(sym::sanitizer_cfi_generalize_pointers, sym::cfg_sanitizer_cfi, cfg_fn!(cfg_sanitizer_cfi)),
(sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, cfg_fn!(cfg_sanitizer_cfi)),
// this is consistent with naming of the compiler flag it's for
(sym::debug_fmt_detail, sym::debug_fmt_detail, cfg_fn!(debug_fmt_detail)),
];

/// Find a gated cfg determined by the `pred`icate which is given the cfg's name.
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,8 @@ declare_features! (
(unstable, custom_inner_attributes, "1.30.0", Some(54726)),
/// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`.
(unstable, custom_test_frameworks, "1.30.0", Some(50297)),
/// Disabling fmt::Debug
(unstable, debug_fmt_detail, "CURRENT_RUSTC_VERSION", Some(123940)),
/// Allows declarative macros 2.0 (`macro`).
(unstable, decl_macro, "1.17.0", Some(39412)),
/// Allows default type parameters to influence type inference.
Expand Down
13 changes: 7 additions & 6 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ use rustc_data_structures::profiling::TimePassesFormat;
use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
use rustc_session::config::{
build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg,
CollapseMacroDebuginfo, CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType,
ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold, Input,
InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli,
NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet,
Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion,
WasiExecModel,
CollapseMacroDebuginfo, CoverageOptions, DebugFmtDetail, DebugInfo, DumpMonoStatsFormat,
ErrorOutputType, ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold,
Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail,
LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey,
PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath,
SymbolManglingVersion, WasiExecModel,
};
use rustc_session::lint::Level;
use rustc_session::search_paths::SearchPath;
Expand Down Expand Up @@ -763,6 +763,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(coverage_options, CoverageOptions { branch: true, mcdc: true });
tracked!(crate_attr, vec!["abc".to_string()]);
tracked!(cross_crate_inline_threshold, InliningThreshold::Always);
tracked!(debug_fmt_detail, DebugFmtDetail::Shallow);
tracked!(debug_info_for_profiling, true);
tracked!(debug_macros, true);
tracked!(default_hidden_visibility, Some(true));
Expand Down
30 changes: 25 additions & 5 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ use rustc_errors::{ColorConfig, DiagArgValue, DiagCtxtFlags, IntoDiagArg};
use rustc_feature::UnstableFeatures;
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
use rustc_span::source_map::FilePathMapping;
use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm};
use rustc_span::{
sym, FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm, Symbol,
};
use rustc_target::spec::{LinkSelfContainedComponents, LinkerFeatures};
use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple};
use std::collections::btree_map::{
Expand Down Expand Up @@ -362,6 +364,23 @@ impl LocationDetail {
}
}

/// Values for the `-Z debug-fmt-detail` flag.
#[derive(Copy, Clone, PartialEq, Hash, Debug)]
pub enum DebugFmtDetail {
/// Derive fully-featured implementation
Full,
/// Print only type name, without fields
Shallow,
/// `#[derive(Debug)]` and `{:?}` are no-ops
None,
}

impl DebugFmtDetail {
pub(crate) fn all() -> [Symbol; 3] {
[sym::full, sym::none, sym::shallow]
}
}

#[derive(Clone, PartialEq, Hash, Debug)]
pub enum SwitchWithOptPath {
Enabled(Option<PathBuf>),
Expand Down Expand Up @@ -2868,10 +2887,10 @@ pub enum WasiExecModel {
pub(crate) mod dep_tracking {
use super::{
BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions,
CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn,
InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
CrateType, DebugFmtDetail, DebugInfo, DebugInfoCompression, ErrorOutputType,
FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto,
LocationDetail, LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType,
OutputTypes, Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
};
use crate::lint;
Expand Down Expand Up @@ -2973,6 +2992,7 @@ pub(crate) mod dep_tracking {
OutputType,
RealFileName,
LocationDetail,
DebugFmtDetail,
BranchProtection,
OomStrategy,
LanguageIdentifier,
Expand Down
16 changes: 15 additions & 1 deletion compiler/rustc_session/src/config/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use rustc_target::abi::Align;
use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet};
use rustc_target::spec::{Target, TargetTriple, TARGETS};

use crate::config::CrateType;
use crate::config::{CrateType, DebugFmtDetail};
use crate::Session;

use std::hash::Hash;
Expand Down Expand Up @@ -115,6 +115,18 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg {
ins_none!(sym::debug_assertions);
}

match sess.opts.unstable_opts.debug_fmt_detail {
DebugFmtDetail::Full => {
ins_sym!(sym::debug_fmt_detail, sym::full);
}
DebugFmtDetail::Shallow => {
ins_sym!(sym::debug_fmt_detail, sym::shallow);
}
DebugFmtDetail::None => {
ins_sym!(sym::debug_fmt_detail, sym::none);
}
}

if sess.overflow_checks() {
ins_none!(sym::overflow_checks);
}
Expand Down Expand Up @@ -262,6 +274,8 @@ impl CheckCfg {

ins!(sym::debug_assertions, no_values);

ins!(sym::debug_fmt_detail, empty_values).extend(DebugFmtDetail::all());

// These four are never set by rustc, but we set them anyway: they
// should not trigger a lint because `cargo clippy`, `cargo doc`,
// `cargo test` and `cargo miri run` (respectively) can set them.
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ mod desc {
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 = "either `none`, or a comma separated list of location details to track: `file`, `line`, or `column`";
pub const parse_debug_fmt_detail: &str = "either `full`, `shallow`, or `none`";
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`";
Expand Down Expand Up @@ -588,6 +589,16 @@ mod parse {
}
}

pub(crate) fn parse_debug_fmt_detail(opt: &mut DebugFmtDetail, v: Option<&str>) -> bool {
*opt = match v {
Some("full") => DebugFmtDetail::Full,
Some("shallow") => DebugFmtDetail::Shallow,
Some("none") => DebugFmtDetail::None,
_ => return false,
};
true
}

pub(crate) fn parse_location_detail(ld: &mut LocationDetail, v: Option<&str>) -> bool {
if let Some(v) = v {
ld.line = false;
Expand Down Expand Up @@ -1622,6 +1633,9 @@ options! {
"inject the given attribute in the crate"),
cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED],
"threshold to allow cross crate inlining of functions"),
debug_fmt_detail: DebugFmtDetail = (DebugFmtDetail::Full, parse_debug_fmt_detail, [TRACKED],
"how detailed `#[derive(Debug)]` should be. `full` prints types recursively, \
`shallow` prints only type names, `none` prints nothing and disables `{:?}`. (default: `full`)"),
debug_info_for_profiling: bool = (false, parse_bool, [TRACKED],
"emit discriminators and other data necessary for AutoFDO"),
debug_macros: bool = (false, parse_bool, [TRACKED],
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ symbols! {
cfg_accessible,
cfg_attr,
cfg_attr_multi,
cfg_debug_fmt_detail,
cfg_doctest,
cfg_eval,
cfg_hide,
Expand Down Expand Up @@ -658,6 +659,7 @@ symbols! {
debug_assert_macro,
debug_assert_ne_macro,
debug_assertions,
debug_fmt_detail,
debug_struct,
debug_struct_fields_finish,
debug_tuple,
Expand Down Expand Up @@ -892,6 +894,7 @@ symbols! {
fs_create_dir,
fsub_algebraic,
fsub_fast,
full,
fundamental,
fused_iterator,
future,
Expand Down Expand Up @@ -1228,6 +1231,7 @@ symbols! {
new_binary,
new_const,
new_debug,
new_debug_noop,
new_display,
new_lower_exp,
new_lower_hex,
Expand Down Expand Up @@ -1645,6 +1649,7 @@ symbols! {
self_struct_ctor,
semitransparent,
shadow_call_stack,
shallow,
shl,
shl_assign,
should_panic,
Expand Down
4 changes: 4 additions & 0 deletions library/core/src/fmt/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ impl<'a> Argument<'a> {
Self::new(x, Debug::fmt)
}
#[inline(always)]
pub fn new_debug_noop<'b, T: Debug>(x: &'b T) -> Argument<'_> {
Self::new(x, |_, _| Ok(()))
}
#[inline(always)]
pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'_> {
Self::new(x, Octal::fmt)
}
Expand Down
15 changes: 15 additions & 0 deletions src/doc/unstable-book/src/compiler-flags/debug-fmt-detail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# `debug-fmt-detail`

The tracking issue for this feature is: [#123940](https://github.com/rust-lang/rust/issues/123940).

------------------------

Option `-Z debug-fmt-detail=val` controls verbosity of derived `Debug` implementations
and debug formatting in format strings (`{:?}`).

* `full``#[derive(Debug)]` prints types recursively. This is the default behavior.

* `shallow``#[derive(Debug)]` prints only the type name, or name of a variant of a fieldless enums. Details of the `Debug` implementation are not stable and may change in the future. Behavior of custom `fmt::Debug` implementations is not affected.

* `none``#[derive(Debug)]` does not print anything at all. `{:?}` in formatting strings has no effect.
This option may reduce size of binaries, and remove occurrences of type names in the binary that are not removed by striping symbols. However, it may also cause `panic!` and `assert!` messages to be incomplete.
2 changes: 1 addition & 1 deletion tests/ui/check-cfg/allow-same-level.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `FALSE`
LL | #[cfg(FALSE)]
| ^^^^^
|
= help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
= help: expected names are: `clippy`, `debug_assertions`, `debug_fmt_detail`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
= help: to expect this configuration use `--check-cfg=cfg(FALSE)`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/check-cfg/cargo-feature.none.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable`
LL | #[cfg(tokio_unstable)]
| ^^^^^^^^^^^^^^
|
= help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
= help: expected names are: `clippy`, `debug_assertions`, `debug_fmt_detail`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
= help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(tokio_unstable)");` to the top of a `build.rs`
= note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/check-cfg/cargo-feature.some.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable`
LL | #[cfg(tokio_unstable)]
| ^^^^^^^^^^^^^^
|
= help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
= help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `debug_fmt_detail`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
= help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(tokio_unstable)");` to the top of a `build.rs`
= note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `value`
LL | #[cfg(value)]
| ^^^^^
|
= help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
= help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `debug_fmt_detail`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
= help: to expect this configuration use `--check-cfg=cfg(value)`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default
Expand Down
Loading

0 comments on commit 92cac91

Please sign in to comment.