-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
Change the desugaring of assert! for better error output
#122661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
rust-analyzer is developed in its own repository. If possible, consider making this change to rust-lang/rust-analyzer instead. cc @rust-lang/rust-analyzer The Miri subtree was changed cc @rust-lang/miri |
This comment has been minimized.
This comment has been minimized.
ead1593 to
eb411c1
Compare
This comment has been minimized.
This comment has been minimized.
|
Sigh, clippy shows at least one test where a suggestion causes there to be a condition that isn't a |
This comment was marked as resolved.
This comment was marked as resolved.
This comment has been minimized.
This comment has been minimized.
|
Isn't this technically a breaking change for e.g. (playground): struct Booly(i32);
impl std::ops::Not for Booly {
type Output = bool;
fn not(self) -> Self::Output {
self.0 == 0
}
}
fn main() {
assert!(Booly(1), "booly booly!")
} |
|
At the very least, we might need to tie such a change to an edition. I am not certain whether this decision would be a T-lang matter or a T-libs-api one. I'll nominate for T-lang for now. (Namely: The question is whether we can start enforcing a rule that the first expression to @rustbot label +I-lang-nominated |
src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0035_weird_exprs.rs
Outdated
Show resolved
Hide resolved
|
@pnkfelix we can keep the current (undocumented) behavior by making the desugaring be {
let x: bool = !!condition;
x
}instead of what this PR does: {
let x: bool = condition;
x
}I believe that would still cause errors to complain about Edit: an option would be to have an internal marker trait: use std::ops::Not;
trait CanAssert {}
impl<T: Not<Output = bool>> CanAssert for T {}
fn main() {
let _ = Box::new(true) as Box<dyn CanAssert>;
let _ = Box::new(42) as Box<dyn CanAssert>;
} |
|
@estebank what about making the expansion edition-dependent? Is there precedent for that? Then, editions >= 2024 would expand to what you have proposed in the code of this PR, and editions < 2024 could expand to the |
(to answer my own question, |
c8185ea to
07a5b21
Compare
|
Some changes occurred in coverage tests. cc @Zalathar |
|
I tried the marker trait approach for <=2021, and it kind of worked, but the diagnostics were actually worse than just doing |
This comment has been minimized.
This comment has been minimized.
|
Since I don't think it's been acknowledged above, for the record, this breaks the following code: Because |
|
@compiler-errors that is indeed the case for 2024 onwards, not for previous editions. |
I think the critical point is whether an edition-dependent expansion is worth breaking that case (of Update: I don't know whether it is worth going through this exercise explicitly, but there is a design space here. E.g. one set of options is:
(And then there's variations thereof about how to handle editions < 2024, but that's a separate debate IMO.) |
|
(this is waiting for a decision from T-lang and/or T-libs regarding what interface we want to commit to for @rustbot label: +S-waiting-on-team -S-waiting-on-review |
|
Thank you to everyone who spent time reviewing this PR! |
|
Per #145423 (comment), it looks like this caused a meaningful regression to ripgrep builds... about 0.8% slower:
My guess is that ripgrep contains a particularly large amount of assertions compared to our other primary benchmarks and so it's most affected, but presumably the new expansion is harder on the compiler? It looks like the MIR produced is ~identical between the changed expressions if I correctly skimmed the desugaring godbolt, so it's probably the earlier stages of the compiler that are affected. The match does seem like it consumes more blocks etc. I'm guessing it's not worth digging too much deeper here, so probably can be marked as triaged. Runtime performance isn't likely to be affected given the equivalent MIR which matters more for this change IMO. |
|
We've discovered that https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=81a747b4884e11637c33beeb1de28465 compiles in stable, but not after this PR. Do you want a tracking bug for that? |
I believe this was discussed in #122661 (comment) and later comments. |
|
@durin42 could you point us to where that change in behavior affected you? We tried our best at doing our due diligence to avoid that behavior affecting the ecosystem, but if there was a failure in our methodology it is best to know about it so that we can revise our process in for future changes. |
|
We saw it in the bitvec crate. ferrilab/bitvec#298 was filed before we realized that backing out this PR let us build bitvec again. Sounds like we should locally-patch bitvec? |
|
I'm shocked this wasn't picked up by our crater runs :-/ We had an earlier proposed approach to restrict the new desugaring to the latest edition, which would have helped/masked this one case. I am concerned that there might have been more cases out there. |
|
This scenario was basically what my addition of the prepare-fail category was trying to prevent. |

In the desugaring of
assert!, we now expand to amatchexpression instead ofif !cond {..}.The span of incorrect conditions will point only at the expression, and not the whole
assert!invocation.We no longer mention the expression needing to implement the
Nottrait.Now
assert!(val)desugars to:Fix #122159.