don't drop arguments' temporaries in dbg!#154074
don't drop arguments' temporaries in dbg!#154074rust-bors[bot] merged 2 commits intorust-lang:mainfrom
dbg!#154074Conversation
|
Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
There was a problem hiding this comment.
I'm not totally sure where this should go. Conceptually, it makes the most sense for it to be a std test, but I can't find where dbg! is actually tested. It also only needs to pass borrowck, not be built and executed, so we could maybe save CI time by making it a //@ check-pass ui test or such.
There was a problem hiding this comment.
I think this is OK. It probably doesn't need to be an integration test though? i.e., you could add it to macros/test.rs or so?
There was a problem hiding this comment.
Oh, I wasn't aware there was a difference! Done.
There was a problem hiding this comment.
Unit tests get compiled as part of the general crate whereas integ tests (in tests/ at the top level) each get compiled separately, so they're generally slower to compile (on a per-test amortized basis).
| *dbg!(&temp()); | ||
| *dbg!(&temp(), 1).0; | ||
| *dbg!(0, &temp()).1; | ||
| *dbg!(0, &temp(), 2).1; |
There was a problem hiding this comment.
Only the last couple of these actually regressed, but I figure we may as well be resilient to changes in dbg!.
Also, the dereferences of the temporary aren't necessary to reproduce this and weren't present in the reproducer found by crater, but I feel like being explicit makes the intent of the test clearer.
| $crate::stringify!($processed), | ||
| // The `&T: Debug` check happens here (not in the format literal desugaring) | ||
| // to avoid format literal related messages and suggestions. | ||
| &&$bound as &dyn $crate::fmt::Debug |
There was a problem hiding this comment.
Why do we need a double reference here? Is it to support some crazy code doing impl Debug for &Thing ?
There was a problem hiding this comment.
I'm not sure! The double reference just coerces away as part of the cast, right? But it's been that way since #142594, so I figured I'd leave it be.
There was a problem hiding this comment.
.. though on second thought, just removing the & would be a very small PR on its own, so maybe it could be bundled in here, especially if the decision is to backport a revert of #149869 instead of this.
There was a problem hiding this comment.
Huh. This code has compiled ever since the stabilization of dbg!() in 1.32.0.
use std::fmt::{self, Debug, Formatter};
struct Thing;
impl Debug for &Thing {
fn fmt(&self, _: &mut Formatter) -> fmt::Result {
Ok(())
}
}
fn main() {
dbg!(Thing);
}Removing the double reference would break this code.
There was a problem hiding this comment.
That feels probably accidental ^^ but it definitely shouldn't be changed as part of this, then.
There was a problem hiding this comment.
The dbg! macro has always done the equivalent of println!("{:?}", &x). The double reference is necessary to keep those semantics.
You can do something like
#![feature(impl_trait_in_bindings)]
fn main() {
let x = 4_u8;
let y: impl std::fmt::Debug = &x;
}if you really want to get rid of the double reference/cast, though.
This comment has been minimized.
This comment has been minimized.
|
The Miri subtree was changed cc @rust-lang/miri |
There was a problem hiding this comment.
Generally this looks fine to me. I'm also not sure where (or whether they exist) there's more tests, but I think as long as you confirmed the one you added fails CI if the changes are reverted it feels OK to me.
r=me, I think it would probably make sense to revert #149869 as the beta backport but I'll leave that up to T-libs backport decision making.
There was a problem hiding this comment.
I think this is OK. It probably doesn't need to be an integration test though? i.e., you could add it to macros/test.rs or so?
| | ^ value used here after move | ||
| | | ||
| help: consider borrowing instead of transferring ownership | ||
| help: consider cloning the value if the performance cost is acceptable |
There was a problem hiding this comment.
This feels like an unfortunate regression (fine for this PR but maybe file an issue for it)? It seems highly likely that borrowing is better here.
There was a problem hiding this comment.
Apparently that suggestion was actually specifically meant for dbg!; I'd assumed it was generic. Maybe it's worth handling it in this PR to keep its expectation of what dbg! looks like in sync with reality—same as the clippy lint change? That test is specifically for the diagnostic too; if I'd taken care to read the linked issue (or if the test was documented or tested for the suggestion message) I'd have updated the diagnostic from the start ^^
I've added a fix, but I can move it to its own PR if that'd be better.
There was a problem hiding this comment.
This already only worked for expansions, so I'd like to keep its scope narrow for now. If a more general "borrow here" suggestion would be helpful, I think it should be designed intentionally.
There was a problem hiding this comment.
Here's why it only worked for expansions: self.expr_span was the move_span, which previously pointed to the match's pattern (specifically a by-move binding), which is normally separate from the match scrutinee (where dbg!'s args expand).
| path @ Path { segments: [seg], .. }, | ||
| )) = &arg.kind | ||
| && seg.ident.name == self.arg_name | ||
| && self.move_span.source_equal(arg.span) |
There was a problem hiding this comment.
This incidentally fixes a minor bug: if given dbg!(a, a); a;, it would produce two suggestions to borrow the second argument rather than one for each. Now that the move_span points to the user-provided argument, we can check the scrutinee for it to find the correct argument for each suggestion.
| && e.span.macro_backtrace().any(|expn| { | ||
| expn.macro_def_id.is_some_and(|macro_def_id| { | ||
| self.tcx.is_diagnostic_item(sym::dbg_macro, macro_def_id) | ||
| }) |
There was a problem hiding this comment.
This could avoid iterating by making dbg_internal! a diagnostic item. I figured it'd be cleaner to reuse the dbg_macro diagnostic item instead since efficiency isn't a priority, but I'm not sure.
There was a problem hiding this comment.
I think as-is this will also apply to e.g. dbg!(some_other_macro!(a)), right? Not sure that's desirable. But I think it's probably fairly rare that someone does that, so we can go with this for now.
There was a problem hiding this comment.
I don't think so? I could be wrong, but I don't think the argument to dbg! would have the dbg! expansion in its macro backtrace, since it's not part of dbg!. I tested the spans of the moved-from arguments to dbg! in dbg-issue-120327.rs; they all have empty macro backtraces.
| } | ||
|
|
||
| fn get_expr(_s: String) {} | ||
|
|
||
| // The suggestion is purely syntactic; applying it here will result in a type error. |
There was a problem hiding this comment.
This was a pre-existing issue; I consider fixing it out-of-scope. I think other suggestions to borrow often produce incorrect code, but if we want to be extra-safe, it could only fire when the dbg! invocation is on a statement of its own.
|
Re-adding the T-compiler label since I've added in a diagnostic fix. I'll re-remove it if it'd be better as its own PR; I can add a FIXME to the diagnostic and its test in that case. Also, it looks like my self-review notes didn't all end up rendering properly? Oops. Hopefully they still make sense. |
There was a problem hiding this comment.
@bors r+
I think my sense is that especially with compiler changes also involved we should land the revert on beta rather than trying to backport this.
This comment has been minimized.
This comment has been minimized.
|
Forgot to re-test clippy 😔 @bors r- |
|
@bors r=Mark-Simulacrum |
…uwer Rollup of 11 pull requests Successful merges: - #154074 (don't drop arguments' temporaries in `dbg!`) - #154328 (rustdoc: add missing {os,target,target_env} values for cfg pretty printer) - #154540 (Fix invalid type suggestion for item nested in function) - #154549 (Add regression test for recursive lazy type alias normalization ICE) - #153373 (Fix LegacyKeyValueFormat report from docker build: powerpc) - #154322 (feat: reimplement `hash_map!` macro) - #154416 (Add `IoSplit` diagnostic item for `std::io::Split`) - #154486 (std_detect on AArch64 Darwin: Detect FEAT_SVE_B16B16) - #154508 (Fix ambiguous parsing in bootstrap.py) - #154518 (Panic in Hermit clock_gettime) - #154530 (update zulip link in `std` documentation)
Rollup merge of #154074 - dianne:dbg-temp-scopes, r=Mark-Simulacrum don't drop arguments' temporaries in `dbg!` Fixes #153850 Credit to @theemathas for help with macro engineering ^^ r? libs
…uwer Rollup of 11 pull requests Successful merges: - rust-lang/rust#154074 (don't drop arguments' temporaries in `dbg!`) - rust-lang/rust#154328 (rustdoc: add missing {os,target,target_env} values for cfg pretty printer) - rust-lang/rust#154540 (Fix invalid type suggestion for item nested in function) - rust-lang/rust#154549 (Add regression test for recursive lazy type alias normalization ICE) - rust-lang/rust#153373 (Fix LegacyKeyValueFormat report from docker build: powerpc) - rust-lang/rust#154322 (feat: reimplement `hash_map!` macro) - rust-lang/rust#154416 (Add `IoSplit` diagnostic item for `std::io::Split`) - rust-lang/rust#154486 (std_detect on AArch64 Darwin: Detect FEAT_SVE_B16B16) - rust-lang/rust#154508 (Fix ambiguous parsing in bootstrap.py) - rust-lang/rust#154518 (Panic in Hermit clock_gettime) - rust-lang/rust#154530 (update zulip link in `std` documentation)
View all comments
Fixes #153850
Credit to @theemathas for help with macro engineering ^^
r? libs