Skip to content

Commit bceb534

Browse files
committed
debug-fmt-detail option
Allows disabling `fmt::Debug` derive and debug formatting.
1 parent 0d8b334 commit bceb534

File tree

17 files changed

+230
-41
lines changed

17 files changed

+230
-41
lines changed

compiler/rustc_ast_lowering/src/format.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_ast::visit::Visitor;
55
use rustc_ast::*;
66
use rustc_data_structures::fx::FxIndexMap;
77
use rustc_hir as hir;
8+
use rustc_session::config::DebugFmtDetail;
89
use rustc_span::{
910
sym,
1011
symbol::{kw, Ident},
@@ -205,7 +206,10 @@ fn make_argument<'hir>(
205206
hir::LangItem::FormatArgument,
206207
match ty {
207208
Format(Display) => sym::new_display,
208-
Format(Debug) => sym::new_debug,
209+
Format(Debug) => match ctx.tcx.sess.opts.unstable_opts.debug_fmt_detail {
210+
DebugFmtDetail::Full | DebugFmtDetail::Shallow => sym::new_debug,
211+
DebugFmtDetail::None => sym::new_debug_noop,
212+
},
209213
Format(LowerExp) => sym::new_lower_exp,
210214
Format(UpperExp) => sym::new_upper_exp,
211215
Format(Octal) => sym::new_octal,

compiler/rustc_builtin_macros/src/deriving/debug.rs

+13
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::deriving::path_std;
44

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

53+
let fmt_detail = cx.sess.opts.unstable_opts.debug_fmt_detail;
54+
if fmt_detail == DebugFmtDetail::None {
55+
return BlockOrExpr::new_expr(cx.expr_ok(span, cx.expr_tuple(span, ThinVec::new())));
56+
}
57+
5258
let (ident, vdata, fields) = match substr.fields {
5359
Struct(vdata, fields) => (substr.type_ident, *vdata, fields),
5460
EnumMatching(_, v, fields) => (v.ident, &v.data, fields),
@@ -61,6 +67,13 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) ->
6167
let name = cx.expr_str(span, ident.name);
6268
let fmt = substr.nonselflike_args[0].clone();
6369

70+
// Fieldless enums have been special-cased earlier
71+
if fmt_detail == DebugFmtDetail::Shallow {
72+
let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
73+
let expr = cx.expr_call_global(span, fn_path_write_str, thin_vec![fmt, name]);
74+
return BlockOrExpr::new_expr(expr);
75+
}
76+
6477
// Struct and tuples are similar enough that we use the same code for both,
6578
// with some extra pieces for structs due to the field names.
6679
let (is_struct, args_per_field) = match vdata {

compiler/rustc_feature/src/builtin_attrs.rs

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const GATED_CFGS: &[GatedCfg] = &[
3838
(sym::relocation_model, sym::cfg_relocation_model, cfg_fn!(cfg_relocation_model)),
3939
(sym::sanitizer_cfi_generalize_pointers, sym::cfg_sanitizer_cfi, cfg_fn!(cfg_sanitizer_cfi)),
4040
(sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, cfg_fn!(cfg_sanitizer_cfi)),
41+
(sym::debug_fmt_detail, sym::debug_fmt_detail, cfg_fn!(debug_fmt_detail)),
4142
];
4243

4344
/// Find a gated cfg determined by the `pred`icate which is given the cfg's name.

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,8 @@ declare_features! (
432432
(unstable, custom_inner_attributes, "1.30.0", Some(54726)),
433433
/// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`.
434434
(unstable, custom_test_frameworks, "1.30.0", Some(50297)),
435+
/// Disabling fmt::Debug
436+
(unstable, debug_fmt_detail, "CURRENT_RUSTC_VERSION", Some(123940)),
435437
/// Allows declarative macros 2.0 (`macro`).
436438
(unstable, decl_macro, "1.17.0", Some(39412)),
437439
/// Allows default type parameters to influence type inference.

compiler/rustc_interface/src/tests.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use rustc_data_structures::profiling::TimePassesFormat;
44
use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
55
use rustc_session::config::{
66
build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg,
7-
CollapseMacroDebuginfo, CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType,
8-
ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold, Input,
9-
InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli,
10-
NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet,
11-
Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion,
12-
WasiExecModel,
7+
CollapseMacroDebuginfo, CoverageOptions, DebugFmtDetail, DebugInfo, DumpMonoStatsFormat,
8+
ErrorOutputType, ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold,
9+
Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail,
10+
LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey,
11+
PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath,
12+
SymbolManglingVersion, WasiExecModel,
1313
};
1414
use rustc_session::lint::Level;
1515
use rustc_session::search_paths::SearchPath;
@@ -762,6 +762,7 @@ fn test_unstable_options_tracking_hash() {
762762
tracked!(coverage_options, CoverageOptions { branch: true });
763763
tracked!(crate_attr, vec!["abc".to_string()]);
764764
tracked!(cross_crate_inline_threshold, InliningThreshold::Always);
765+
tracked!(debug_fmt_detail, DebugFmtDetail::Full);
765766
tracked!(debug_info_for_profiling, true);
766767
tracked!(debug_macros, true);
767768
tracked!(default_hidden_visibility, Some(true));

compiler/rustc_session/src/config.rs

+22-4
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,23 @@ impl LocationDetail {
360360
}
361361
}
362362

363+
/// Values for the `-Z debug-fmt-detail` flag.
364+
#[derive(Copy, Clone, PartialEq, Hash, Debug)]
365+
pub enum DebugFmtDetail {
366+
/// Derive fully-featured implementation
367+
Full,
368+
/// Print only type name, without fields
369+
Shallow,
370+
/// `#[derive(Debug)]` and `{:?}` are no-ops
371+
None,
372+
}
373+
374+
impl DebugFmtDetail {
375+
pub(crate) fn all() -> [&'static str; 3] {
376+
["full", "none", "shallow"]
377+
}
378+
}
379+
363380
#[derive(Clone, PartialEq, Hash, Debug)]
364381
pub enum SwitchWithOptPath {
365382
Enabled(Option<PathBuf>),
@@ -2863,10 +2880,10 @@ pub enum WasiExecModel {
28632880
pub(crate) mod dep_tracking {
28642881
use super::{
28652882
BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions,
2866-
CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn,
2867-
InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
2868-
LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
2869-
Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
2883+
CrateType, DebugFmtDetail, DebugInfo, DebugInfoCompression, ErrorOutputType,
2884+
FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto,
2885+
LocationDetail, LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType,
2886+
OutputTypes, Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
28702887
SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
28712888
};
28722889
use crate::lint;
@@ -2968,6 +2985,7 @@ pub(crate) mod dep_tracking {
29682985
OutputType,
29692986
RealFileName,
29702987
LocationDetail,
2988+
DebugFmtDetail,
29712989
BranchProtection,
29722990
OomStrategy,
29732991
LanguageIdentifier,

compiler/rustc_session/src/config/cfg.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_target::abi::Align;
2525
use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet};
2626
use rustc_target::spec::{Target, TargetTriple, TARGETS};
2727

28-
use crate::config::CrateType;
28+
use crate::config::{CrateType, DebugFmtDetail};
2929
use crate::Session;
3030

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

118+
match sess.opts.unstable_opts.debug_fmt_detail {
119+
DebugFmtDetail::Full => {
120+
ins_str!(sym::debug_fmt_detail, "full");
121+
}
122+
DebugFmtDetail::Shallow => {
123+
ins_str!(sym::debug_fmt_detail, "shallow");
124+
}
125+
DebugFmtDetail::None => {
126+
ins_str!(sym::debug_fmt_detail, "none");
127+
}
128+
}
129+
118130
if sess.overflow_checks() {
119131
ins_none!(sym::overflow_checks);
120132
}
@@ -262,6 +274,9 @@ impl CheckCfg {
262274

263275
ins!(sym::debug_assertions, no_values);
264276

277+
ins!(sym::debug_fmt_detail, empty_values)
278+
.extend(DebugFmtDetail::all().into_iter().map(Symbol::intern));
279+
265280
// These four are never set by rustc, but we set them anyway: they
266281
// should not trigger a lint because `cargo clippy`, `cargo doc`,
267282
// `cargo test` and `cargo miri run` (respectively) can set them.

compiler/rustc_session/src/options.rs

+14
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ mod desc {
406406
pub const parse_linker_plugin_lto: &str =
407407
"either a boolean (`yes`, `no`, `on`, `off`, etc), or the path to the linker plugin";
408408
pub const parse_location_detail: &str = "either `none`, or a comma separated list of location details to track: `file`, `line`, or `column`";
409+
pub const parse_debug_fmt_detail: &str = "either `full`, `shallow`, or `none`";
409410
pub const parse_switch_with_opt_path: &str =
410411
"an optional path to the profiling data output directory";
411412
pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`";
@@ -585,6 +586,16 @@ mod parse {
585586
}
586587
}
587588

589+
pub(crate) fn parse_debug_fmt_detail(opt: &mut DebugFmtDetail, v: Option<&str>) -> bool {
590+
*opt = match v {
591+
Some("full") => DebugFmtDetail::Full,
592+
Some("shallow") => DebugFmtDetail::Shallow,
593+
Some("none") => DebugFmtDetail::None,
594+
_ => return false,
595+
};
596+
true
597+
}
598+
588599
pub(crate) fn parse_location_detail(ld: &mut LocationDetail, v: Option<&str>) -> bool {
589600
if let Some(v) = v {
590601
ld.line = false;
@@ -1606,6 +1617,9 @@ options! {
16061617
"inject the given attribute in the crate"),
16071618
cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED],
16081619
"threshold to allow cross crate inlining of functions"),
1620+
debug_fmt_detail: DebugFmtDetail = (DebugFmtDetail::Full, parse_debug_fmt_detail, [TRACKED],
1621+
"how detailed `#[derive(Debug)]` should be. `full` prints types recursively, \
1622+
`shallow` prints only type names, `none` prints nothing and disables `{:?}`. (default: `full`)"),
16091623
debug_info_for_profiling: bool = (false, parse_bool, [TRACKED],
16101624
"emit discriminators and other data necessary for AutoFDO"),
16111625
debug_macros: bool = (false, parse_bool, [TRACKED],

compiler/rustc_span/src/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,7 @@ symbols! {
658658
debug_assert_macro,
659659
debug_assert_ne_macro,
660660
debug_assertions,
661+
debug_fmt_detail,
661662
debug_struct,
662663
debug_struct_fields_finish,
663664
debug_tuple,
@@ -1227,6 +1228,7 @@ symbols! {
12271228
new_binary,
12281229
new_const,
12291230
new_debug,
1231+
new_debug_noop,
12301232
new_display,
12311233
new_lower_exp,
12321234
new_lower_hex,

library/core/src/fmt/rt.rs

+4
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ impl<'a> Argument<'a> {
117117
Self::new(x, Debug::fmt)
118118
}
119119
#[inline(always)]
120+
pub fn new_debug_noop<'b, T: Debug>(x: &'b T) -> Argument<'_> {
121+
Self::new(x, |_, _| Ok(()))
122+
}
123+
#[inline(always)]
120124
pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'_> {
121125
Self::new(x, Octal::fmt)
122126
}

tests/ui/check-cfg/well-known-values.rs

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#![feature(cfg_target_has_atomic_equal_alignment)]
1616
#![feature(cfg_target_thread_local)]
1717
#![feature(cfg_ub_checks)]
18+
#![feature(debug_fmt_detail)]
1819

1920
// This part makes sure that none of the well known names are
2021
// unexpected.
@@ -28,6 +29,8 @@
2829
//~^ WARN unexpected `cfg` condition value
2930
debug_assertions = "_UNEXPECTED_VALUE",
3031
//~^ WARN unexpected `cfg` condition value
32+
debug_fmt_detail = "_UNEXPECTED_VALUE",
33+
//~^ WARN unexpected `cfg` condition value
3134
doc = "_UNEXPECTED_VALUE",
3235
//~^ WARN unexpected `cfg` condition value
3336
doctest = "_UNEXPECTED_VALUE",

0 commit comments

Comments
 (0)