Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upRFC: Quick dbg!(expr) macro #2173
Conversation
Centril
added some commits
Oct 13, 2017
Centril
changed the title
Rfc/quick debug macro
RFC: Quick dbg!(expr) macro
Oct 13, 2017
sfackler
reviewed
Oct 13, 2017
|
|
||
| ## On release builds: | ||
|
|
||
| The same examples above will print nothing to `STDERR` and will instead simply |
This comment has been minimized.
This comment has been minimized.
sfackler
Oct 13, 2017
Member
Why? dbg!() calls don't seem like something that you'd want to keep around other than when you're looking into a specific bug.
This comment has been minimized.
This comment has been minimized.
Centril
Oct 13, 2017
Author
Contributor
I think looking into a specific bug is the most likely scenario. However...
There might be some fix you made, but you are not 100% sure, and you'd still like to include it into release builds. With the macro having no effect on release, this is possible.
Does this have any downsides?
This comment has been minimized.
This comment has been minimized.
sfackler
Oct 13, 2017
Member
Spewing a bunch of stuff to stderr when a downstream crate isn't building with --release is a downside.
Asserts are a more common way of handling those kinds of checks IME.
This comment has been minimized.
This comment has been minimized.
Centril
Oct 13, 2017
Author
Contributor
I buy the argument regarding assert for at least libraries. However, it might have some value for programs?
This comment has been minimized.
This comment has been minimized.
|
Does something like this exist in other languages? |
This comment has been minimized.
This comment has been minimized.
sdleffler
commented
Oct 13, 2017
|
@sfackler Haskell has |
This comment has been minimized.
This comment has been minimized.
|
@sfackler (You could argue that) It is similar to: |
This comment has been minimized.
This comment has been minimized.
|
Yes please. I think the lesser verbosity compared to |
This comment has been minimized.
This comment has been minimized.
sdleffler
commented
Oct 13, 2017
•
|
I want to restate the concern I had on IRC - I think that perhaps this macro should take a single format string argument, with a privileged "first" parameter: e.g. |
This comment has been minimized.
This comment has been minimized.
|
@sdleffler this seems more like traceShowId than trace, right? None of those examples wrap the output in |
This comment has been minimized.
This comment has been minimized.
sdleffler
commented
Oct 13, 2017
|
@sfackler no, because |
This comment has been minimized.
This comment has been minimized.
|
@sfackler The format, including |
This comment has been minimized.
This comment has been minimized.
sdleffler
commented
Oct 13, 2017
|
@sfackler see the "Reference-level Explanation": ideally I'd want to avoid that formatting and just let the user do it. It doesn't actually wrap the output in |
This comment has been minimized.
This comment has been minimized.
sdleffler
commented
Oct 13, 2017
|
And also thus avoid that bikeshedding :P |
sfackler
reviewed
Oct 13, 2017
| the identity function on the expression, but the call will be inlined away such | ||
| that the overhead is zero. | ||
|
|
||
| The file name, line number and column is included for increased utility when included in production quality code. The expression is also stringified, so that |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Centril
Oct 13, 2017
Author
Contributor
Things ready to be included in programs & libraries run in production... This is arguably vague and subjective. It could be interpreted as things ready for cargo publish, but probably not.
This comment has been minimized.
This comment has been minimized.
sfackler
Oct 13, 2017
Member
I would argue that things that should be included in programs & libraries run in production should never be writing something like
[DEBUGGING, foobar.rs]
some-expr => 15
to stderr. If you want people to use your library, let them decide if and how they want to consume the debugging information you produce.
This comment has been minimized.
This comment has been minimized.
Centril
Oct 13, 2017
Author
Contributor
This would probably only be included when developing/debugging a library, which the developer of the lib does.
This comment has been minimized.
This comment has been minimized.
sfackler
Oct 13, 2017
•
Member
The "when included in production quality code" bit seems out of place if this wouldn't be used in production quality code.
This comment has been minimized.
This comment has been minimized.
Centril
Oct 13, 2017
Author
Contributor
Should probably be reworded.
The intent is:
- In the case of a library: If the library is used in production and you are the developer/contributor to it, and you want to make some changes and debug those, the macro should be useful to you when doing debug builds.
- In the case of a program: The macro should be useful to you when doing debug builds and you shouldn't have to remove them in
--release.
This comment has been minimized.
This comment has been minimized.
sfackler
Oct 13, 2017
Member
But how is the production-ness of the library relevant in the first case?
This comment has been minimized.
This comment has been minimized.
Centril
Oct 13, 2017
Author
Contributor
Changed production quality to non-trivial per discussion here and on IRC.
scottmcm
added
the
T-libs
label
Oct 13, 2017
This comment has been minimized.
This comment has been minimized.
|
ping @bluss for non- |
scottmcm
reviewed
Oct 13, 2017
|
|
||
| By using `dbg!(expr);`, the burden of a common papercut: writing `println!("{:?}", expr);` every time you want to see the evaluted-to value of an expression, can be significantly reduced. The developer no longer has to remember the formatting args and has to type significantly less (12 characters to be exact). | ||
|
|
||
| The shortness is also beneficial when asking `playbot-mini` on #rust@irc.mozilla.org to evaluate and print an expression. |
This comment has been minimized.
This comment has been minimized.
scottmcm
Oct 13, 2017
Member
I think IRC bots would rather a very different output format from what's described currently:
- The
[DEBUGGING, src/main.rs:1:12]:is clearly of no value there - Most bots only keep one or two lines (to avoid spamming), so
{:#?}is worse than{:?} - The expression is one the line right above, so isn't really worth showing again
playbot (RIP) just used fn show<T:Debug>(x: T) -> T { print!("{:?}", x); x } which worked great for it.
This comment has been minimized.
This comment has been minimized.
Centril
added some commits
Oct 13, 2017
This comment has been minimized.
This comment has been minimized.
|
This comment has been minimized.
This comment has been minimized.
vi
commented
Oct 13, 2017
•
|
Maybe it should be sensitive to environment variables, like in the Can it be made enabled (by default) only from crate being actively developed (e.g current crate, it's examples, |
This comment has been minimized.
This comment has been minimized.
|
FWIW my use case for this is to sprinkle it during debugging and remove it before making a git commit. So any extra step required to get some visible output (setting an env variable, adding a crate dependency, typing a formatting string, …) is a hindrance. |
This comment has been minimized.
This comment has been minimized.
vi
commented
Oct 13, 2017
•
|
@SimonSapin , Then why bother removing it in release? What if debug and release take different code paths (due to timing, for example) and you are debugging it? |
This comment has been minimized.
This comment has been minimized.
|
@vi If timing matters, I think a considerably more rigorous approach to debugging & verification for the code under test is required. This makes this macro less interesting for those use cases, which is OK. |
This comment has been minimized.
This comment has been minimized.
dlight
commented
Oct 14, 2017
|
Hello, I wrote some time ago a crate called One interesting thing about Another thing is that you can prefix with a Another is that you can do And another thing is being able to print many lines, like
|
This comment has been minimized.
This comment has been minimized.
|
@vi If an environment variable is used to opt-in to printing the macro will also be quite useless for the Rust Playground as there is no way to specify environment variables there (AFAIK), and if there were, it wouldn't be ergonomic for newcomers to the language or experienced rustaceans. |
This comment has been minimized.
This comment has been minimized.
To that end, I counter-propose: pub struct WrapDebug<T>(pub T); // <-- This type goes into `std::fmt`.
impl<T: Debug> Debug for WrapDebug<T> {
fn fmt(&self, f: &mut Formatter) -> Result { self.0.fmt(f) }
}
impl<T> Debug for WrapDebug<T> {
default fn fmt(&self, f: &mut Formatter) -> Result {
use intrinsics::type_name;
write!(f, "[<unknown> of type {} is !Debug]",
unsafe { type_name::<T>() })
}
}
macro_rules! dbg { // <-- Goes into the prelude.
($val: expr) => {{
let tmp = ::std::fmt::WrapDebug($val);
eprintln!("[{}:{}] {} => {:?}\n",
file!(), line!(), stringify!($val), tmp);
tmp.0
}}
}This design is forward compatible with the fully featured macro in this RFC, which leaves us room to grow. |
This comment has been minimized.
This comment has been minimized.
|
I like the counter-proposal. It hits the things I think are essential:
(I'd suggest making stabilizing |
This comment has been minimized.
This comment has been minimized.
Does that work? If EDIT: Of course, one can also see this as a benefit... |
This comment has been minimized.
This comment has been minimized.
|
Standard library macros can bypass stability. I would argue that WrapDebug should be omitted entirely in an initial proposal.
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable]
macro_rules! print {
($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
}
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! println {
() => (print!("\n"));
($fmt:expr) => (print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
} |
This comment has been minimized.
This comment has been minimized.
Interesting... But what is the rationale for omitting WrapDebug initially? Also, if you expand
|
This comment has been minimized.
This comment has been minimized.
It can only be implemented through specialization which is not stable. There is currently nothing in the standard library API that exposes specialization.
It does not seem particularly reasonable to consider the complexity of an API by the transitive size of its dependencies. Are we going to include the |
This comment has been minimized.
This comment has been minimized.
Including If we don't include
Then simply consider the complexity of the |
This comment has been minimized.
This comment has been minimized.
|
I was specifically referring to macro_rules macros, but I think it's hopefully clear that format_args earns its complexity. It's one of the fundamental and most commonly used components of the standard library. |
This comment has been minimized.
This comment has been minimized.
Fair enough =) |
rfcbot
added
final-comment-period
and removed
proposed-final-comment-period
labels
Mar 13, 2018
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Mar 13, 2018
|
|
SimonSapin
added a commit
to SimonSapin/rfcs
that referenced
this pull request
Mar 13, 2018
This comment has been minimized.
This comment has been minimized.
|
I’ve expressed before that I’d prefer this macro to be kept very simple (and in particular configuration-less). I wrote up a full counter-proposal at #2361. |
This comment has been minimized.
This comment has been minimized.
vi
commented
Mar 13, 2018
|
Is it a good idea to restrict |
This comment has been minimized.
This comment has been minimized.
|
@vi That sounds like a fine lint for Clippy or other project-specific linter, but maybe doesn’t belong in rustc or cargo. |
This comment has been minimized.
This comment has been minimized.
Irrespective of this RFC, I want to note that I find this comment to be unhelpful and also wrong.
|
This comment has been minimized.
This comment has been minimized.
repax
commented
Mar 14, 2018
|
@Centril: Meh. you're overreacting. I'm not here to bicker. I'm simply pointing out that I think that what started as a good idea has grown too much in complexity. It's easy to see how the complexity of the proposal has grown if you read the commit history. I think this is a valid thing to point out. Did not mean to hurt your feelings. |
This comment has been minimized.
This comment has been minimized.
This formulation is much better.
Don't worry; they were not hurt - while I would have wanted a more feature complete macro, I am excited to see My comment was more general about RFCs in general and not specific to this RFC. I think these points are important to understand how the RFC process works so that people don't see a lot of upvotes or downvotes as indicative of what the responsible subteam will do; if people have this perception, and argue about popularity, they will become disappointed. Moreover, arguments about popularity do not advance discussion or bring clarity into trade-offs. |
This comment has been minimized.
This comment has been minimized.
repax
commented
Mar 14, 2018
|
@Centril: I should choose my words more carefully. Thank you for all the work you put into this. |
Centril
referenced this pull request
Mar 16, 2018
Closed
add BestEffortDebug<T>, an always-Debug wrapper over T irrespective of T: Debug / T: !Debug #49071
This comment has been minimized.
This comment has been minimized.
|
@Centril I just want to thank you for the huge amount of work and patience here, regardless of the outcome. The detail in "formerly unresolved questions" is super valuable, and I wish that all RFCs contained such great summarizations. Your comparison to Over time, we've come to be increasingly conservative in our approach to
On the flip side, our fantastic packaging story with Cargo, together with other ongoing work on improving discoverability and curation in the ecosystem, allow us to provide a very strong user experience despite a lean So to be clear: I think everyone acknowledges that debugging ergonomics are extremely important, and worth investing in. But I think folks are skeptical that, even with this lengthy discussion, we've arrived at the Best Way that will work for everyone (even taking into account the provided knobs). To me, this seems like the perfect kind of thing to provide in the crates.io ecosystem, joining the ranks of many other crates providing highly sophisticated, ergonomic -- and competing -- answers to important development questions. |
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Mar 23, 2018
|
The final comment period is now complete. |
This comment has been minimized.
This comment has been minimized.
|
As the FCP is now complete with a motion to close this RFC is now closed. The discussion on a more streamlined macro, roughly based on #2173 (comment) continues in RFC #2361. |
Centril commentedOct 13, 2017
•
edited
See RFC #2361 for the "second version" of this RFC
Adds a macro
dbg!(expr1 [, expr2, .., exprN])for quick and dirtyDebug:ing of expressions to the terminal. The macro evaluates expressions, prints it toSTDERR, and finally yields a flat tuple of(expr1 [, expr2, .. exprN]). On release builds, the macro is the identity function and has no side effects. The macro is added to the prelude of the standard library.Rendered.
Acknowledgements & ping
@scottmcm, @mbrubeck, @sdleffler, @setharnold