pre-RFC: cfg()s for debug-profile-related uses


cfg(debug_assertions) is super useful for adding custom checks to code, but it in practice it is also used to detect builds in debug mode in general, and abused enable/disable other features that are vaguely related to debugging, but aren’t assertions at all.

This makes the debug_assertions check inaccurate and problematic for non-assertions uses, because assertions could be enabled in release mode (implicitly enabling other unwanted debug info), and also other features that are used in debug mode by default (e.g. verbose logging) are sometimes desired in release mode even when assertions aren’t.

So I’m proposing to identify other debug-related use-cases that cfg(debug_assertions) is unsuitable for, and adding new, specific cfg() for them.

Things I’ve seen so far:

  • Verbose logging. In the dbg!() RFC opinions are divided whether logging should be left enabled in release mode. There are good uses for it to be either way, so the dilemma could be solved by a separate cfg(debug_log) specifically for this. There are also 3rd party libraries that use cfg(debug_assertions) to control log verbosity.

  • Skipping unoptimized tests. While debug assertions are an overhead, most often the main cause is lack of optimizations by default in debug mode. cfg(opt_level = 0) would allow making more specific decision about it.

  • Debug symbols/backtraces. For applications that have automated crash reporting it is useful to ship debug symbols even in release mode (and even when runtime overflow checking is not desirable). Cargo already has a separate switch for debug symbols, and libraries related to backtraces could use it.

  • Dev environment/work-in-progress. I want to conditionally disable warnings that are noisy on unfinished code while I’m writing it, e.g. allow(dead_code), but of course I don’t want to disable them forever. Currently I gate these on #[cfg_attr(debug_assertions, allow(dead_code)].

I think there’s a strong case to add at least a cfg() for verbose logging, which is already needed by 3rd party libraries and would be useful for std’s own dbg!().

Idea: Mark code as "known dead" to silence dead-code lint