Skip to content
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

Implement RFC 2011 (nicer assert messages) #48973

Closed
wants to merge 7 commits into from

Conversation

sinkuu
Copy link
Contributor

@sinkuu sinkuu commented Mar 13, 2018

#44838

assert!(x + y == z && w);
thread 'main' panicked at 'assertion failed: x + y == z && w
with expansion: 3 + 5 == 7 && (unevaluated)', test.rs:6:5

Detailed designs

🚲 🏠 What should be captured? (Current implementation captures operands of unary and binary operators.) How should the panic message look like?

Performance

Now assert expands to some amount of code, and this may slow down compilation and execution. We need to test performance difference and see if it have to fall back to the original behavior when not(debug_assertions).

@sinkuu sinkuu force-pushed the nicer_assert branch 2 times, most recently from 92bf267 to 1a2577d Compare March 13, 2018 09:36
@oli-obk
Copy link
Contributor

oli-obk commented Mar 13, 2018

Current implementation captures operands of unary and binary operators.

I think function call arguments could be captured, too. There's no difference between Add::add(&a, &b) and a + b in my book.

@pietroalbini pietroalbini added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 13, 2018
@pietroalbini
Copy link
Member

Highfive failed to assign a reviewer, assigning one randomly from the libs team.

r? @dtolnay

@bors
Copy link
Contributor

bors commented Mar 14, 2018

☔ The latest upstream changes (presumably #48684) made this pull request unmergeable. Please resolve the merge conflicts.

@sinkuu
Copy link
Contributor Author

sinkuu commented Mar 18, 2018

I think function call arguments could be captured, too. There's no difference between Add::add(&a, &b) and a + b in my book.

I thought so too, but realized that they are different after trying to implement.

let x = &mut Foo;
let y = &mut Foo;

let _ = bar(x); // x is reborrowed
println!("{:?}", x);

let _ = x + y; // x is consumed
// println!("{:?}", x); // "use of moved value: `x`"

This is problematic because my strategy to capture an intermediate value by-value is to replace a expression with

{ let tmp = {expression}; try_copy(&tmp, &mut __capture); tmp }

which always consumes the expression.
I tried applying another transformation like { try_copy(&{path}, &mut __capture); func({path}) } for ExprKind::Path (where reborrow works?) to preserve reborrow. This seemed to work at first, but bumped into func(None) (None is a Path on AST) causing type inference error. 😑

@sinkuu sinkuu force-pushed the nicer_assert branch 3 times, most recently from b386e12 to 63b84e8 Compare March 19, 2018 02:34
@shepmaster
Copy link
Member

Ping from triage, @dtolnay ! Will you have time to review this in the near future?

@bors
Copy link
Contributor

bors commented Mar 23, 2018

☔ The latest upstream changes (presumably #49308) made this pull request unmergeable. Please resolve the merge conflicts.

Copy link
Member

@dtolnay dtolnay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still need to look at the implementation of Context::generate but here are some comments regarding the rest.

#[unstable(feature = "generic_assert_internals", issue = "44838")]
impl<T> Debug for DebugFallback<T> {
default fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_str(self.alt)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for self.value to be Unevaluated here? If so, I would expect this to print "(unevaluated)" even for non-Debug types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, this needs to be

match self.value {
    Value | NotCopy => alt,
    Unevaluated => "(unevaluated)",
}

@@ -86,7 +761,7 @@ fn escape_format_string(s: &str) -> String {

#[test]
fn test_escape_format_string() {
assert!(escape_format_string(r"foo{}\") == r"foo{{}}\\");
assert!(escape_format_string("foo{}") == "foo{{}}");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change necessary? The implementation of escape_format_string has not changed.

/// True if `||` or `&&` are contained in this tree.
contains_lazy: bool,
/// True if by-value captures are contained in this tree.
contains_by_ref: bool,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field name contradicts the doc comment (by-ref vs by-value).

@dtolnay
Copy link
Member

dtolnay commented Mar 25, 2018

To help review, would you be able to share what src/libsyntax_ext/assert_tests.rs looks like after macro expansion? rustc -Z unstable-options --pretty=expanded

@sinkuu
Copy link
Contributor Author

sinkuu commented Mar 25, 2018

https://gist.github.com/sinkuu/ba6abd95cb55e839ae33cb022410bb36
(I added dummy macro_rules! panic { ($($t:tt)*) => {panic($($t)*)}; } to prevent explosion with format! expansion)

@ishitatsuyuki
Copy link
Contributor

@dtolnay I guess that your review comments are addressed. Mind doing another review?

@@ -208,3 +208,87 @@ pub use coresimd::simd;
#[unstable(feature = "stdsimd", issue = "48556")]
#[cfg(not(stage0))]
pub use coresimd::arch;

// FIXME: move to appropriate location
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this to libcore/asserting.rs (by analogy with runtime support for panicking in libcore/panicking.rs).

@dtolnay
Copy link
Member

dtolnay commented Mar 29, 2018

Thanks! I would be comfortable accepting this if for now we make it expand exactly the old way in release mode. Later we can debate what changes it makes sense to apply in release mode.

@ishitatsuyuki
Copy link
Contributor

Is this insta-stable? I have no strong opinion but maybe it's good to have a feature flag to switch between new and old behaviour.

Regarding the performance concern, does it make sense to have a perf run (while we have this enabled as default)?

@sinkuu
Copy link
Contributor Author

sinkuu commented Mar 30, 2018

#49071 (comment) applies to this PR, too:( I believe "plain text fallback" described in RFC2011 cannot be implmented without this specialization (T -> T: Debug).

@ishitatsuyuki
Copy link
Contributor

This RFC can be backward compatible only if the broader specialization is used; do you think we can use that here? Is there a soundness issue? cc @nikomatsakis

Back to the implementation itself, can we track the evaluated status by using a counter? Short circuits has a defined ordering, and presumably computing that at codegen time allows better optimization.

@sinkuu
Copy link
Contributor Author

sinkuu commented Apr 5, 2018

I'm not sure whether if I get what you mean. Maybe listing all evaluation states and have branches of panic call for each of them? I'd avoid that as it would make explosion of the amount of the generated code much more worse. I think optimization for the case of assertion falure is not important and should not regress other factors.

@ishitatsuyuki
Copy link
Contributor

Sounds like you're right. Never mind then.

@bors
Copy link
Contributor

bors commented Apr 6, 2018

☔ The latest upstream changes (presumably #49154) made this pull request unmergeable. Please resolve the merge conflicts.

@nikomatsakis
Copy link
Contributor

@ishitatsuyuki

Is there a soundness issue? ... Sounds like you're right. Never mind then.

I'm not sure if my input is still needed, can you clarify? =)

@ishitatsuyuki
Copy link
Contributor

@nikomatsakis As we are using a variant of specialization that isn't going to be stabilized, we need your input on whether it's acceptable to use such specialization or not. Also see #49071 which tries to achieve a similar specialization.

@sinkuu
Copy link
Contributor Author

sinkuu commented Apr 15, 2018

I will reopen once the discussion about sound specialization settles.

@sinkuu sinkuu closed this Apr 15, 2018
@fmease fmease added the F-generic_assert `#![feature(generic_assert)]` label Apr 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-generic_assert `#![feature(generic_assert)]` S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants