Skip to content

Tracking issue for RFC 2011: Generic assert #44838

Open

Description

@alexcrichton

View all comments

This is a tracking issue for rust-lang/rfcs#2011.
The feature gate for the issue is #![feature(generic_assert)].

Sub tracking-issue: #96949.

About tracking issues

Tracking issues are used to record the overall progress of implementation.
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.

Steps

  • Implementation (see section Implementation history)
  • Final comment period (FCP)1
  • Stabilization PR

Blockers

Implementation history

Footnotes

  1. https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html ↩

Activity

  1. added
    B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.
    T-libs-api[DEPRECATED; DO NOT USE]
    on Sep 25, 2017
  2. added
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Sep 27, 2017
  3. bstrie commented on Sep 27, 2017

    @bstrie
  4. durka commented on Sep 27, 2017

    @durka
  5. bstrie commented on Sep 27, 2017

    @bstrie
  6. emilio commented on Feb 7, 2018

    @emilio
    Contributor

    Quick question, is it expected for this to have some sort of switch to less-nice error messages? Sometimes people care about code size, and including a bunch of debug formatters on release builds may not be acceptable.

  7. ishitatsuyuki commented on Feb 7, 2018

    @ishitatsuyuki
    Contributor

    This was one of the concerns in the RFC, and following are some points:

    • The performance impact may be minimal, as the first step is just making assert having assert_eq's functionality.
    • If notable regression was found, we may decide to disable some of the rules for release builds.
    • For certain critical path, debug assertions or custom formatters may be used to minimize (control) the performance impact, just as before.
  8. sinkuu commented on Mar 8, 2018

    @sinkuu
    Contributor

    I am trying to implement this, but have not been successful so far. The problem is that we don't know if a operand is Copy during macro expansion.

    Status quo(sinkuu@ba00a0e):

    assert!(a == b && c)

    expands to

    let mut __capture0 = None;
    let mut __capture1 = None;
    let mut __capture2 = None;
    // `try_copy` copies it if it implements `Copy`
    if !({ let __tmp = a; __capture0 = __tmp.try_copy(); __tmp }
       == { let __tmp = b; __capture1 = __tmp.try_copy(); __tmp }
       && { let __tmp = c; __capture2 = __tmp.try_copy(); __tmp }) {
        panic!("assertion failed: a == b && c\nwith expansion: {:?} == {:?} && {:?}", ...);
    }

    But this moves non-Copy operands into assert, and causes use-after-move afterward.

    @ishitatsuyuki Do you have concrete implementation strategies in mind?

  9. ishitatsuyuki commented on Mar 8, 2018

    @ishitatsuyuki
    Contributor

    @sinkuu Nice work! However, PartialEq takes self by reference, which means you don't have to copy/clone it. In this case, we may have to call the trait methods directly instead of the operators.

    In the case of moving Ops like Add, your approach is good and should just work.

    Another thing is that we should use our own enum instead of Option here, as we need to handle the case of non-Copy type and the case of short-circuit differently.

  10. shepmaster commented on Mar 8, 2018

    @shepmaster
    Member

    You might be able to use the tricks that assert_eq! uses to take references to the arguments as well.

  11. gilescope commented on Mar 21, 2018

    @gilescope
    Contributor

    I’m probably not meant to comment now given the RFC has been merged, but spare a thought for if it’s possible to line up both sides of an == vertically above and below one another as that can make things much easier to spot the difference. Really love this rfc btw, looking forward to it.

  12. ishitatsuyuki commented on Mar 21, 2018

    @ishitatsuyuki
    Contributor

    @gilescope You're welcome to comment on how we should form the message. The RFC is just meant to be a brief proposal, and there are libraries in other languages that has much more helpful expansion outputs. (Example: https://github.com/power-assert-js/power-assert)

  13. 35 remaining items

  14. added a commit that references this issue on May 27, 2023
  15. changed the title [-]Tracking issue for RFC 2011: nicer assert messages[/-] [+]Tracking issue for RFC 2011: Generic assert[/+] on Oct 16, 2024
  16. added 2 commits that reference this issue on Dec 10, 2024
  17. added 2 commits that reference this issue on Jan 7, 2025
  18. added a commit that references this issue on Jan 7, 2025
  19. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Jan 19, 2025
  20. Sky9x commented on Feb 23, 2025

    @Sky9x
    Contributor

    The only thing blocking progress is the lack of formatting in constant environments, i.e., things like const _: () = { panic!("{}", 1i32); }; don't work. This current limitation is something that I will try to figure out after enabling the capture of variables in matches! declarations.

    @c410-f3r IIUC the most straightforward implementation (where you write const and ~const in a few places and rustc does the rest) requires dynamic dispatch in CTFE, which in turn requires const fn() function pointers. This is because Formatter internally holds and writes to a dyn fmt::Write.

    Here's a little const formatting demo i threw together a couple months ago: https://gist.github.com/Sky9x/e11cb7ba0772289c05172ebda7dcaeda
    the code is pretty crap but it all leads to this line:

    const MEOW: &str = const_format!("meow", " :3 ", -59999, ' ', true, ' ', 'x', '3');

    where MEOW is a &'static str and after const evaluation it has the content "meow :3 -59999 true x3".

    I couldn't be bothered to implement template parsing so instead it just formats and concatenates everything into one big buffer, then returns it as a &'static str. The macro will also panic if called at runtime.

    However, that API is not suitable for use in std because it makes Formatter and Display::fmt generic over the writer type, which is a breaking change.

  21. c410-f3r commented on Feb 24, 2025

    @c410-f3r
    Contributor

    The intention is to "constify" all methods and related traits of https://github.com/rust-lang/rust/blob/master/library/core/src/asserting.rs, which is on the library side.

    If additional support is necessary on the compiler side beyond the ongoing #[const_trait] effort, then it is probably wise to just skip generic_assert in constant environments.

  22. added a commit that references this issue on Mar 11, 2025
  23. added
    T-libsRelevant to the library team, which will review and decide on the PR/issue.
    and removed
    T-libs-api[DEPRECATED; DO NOT USE]
    on Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-error-handlingArea: Error handlingA-fmtArea: `core::fmt`B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCF-generic_assert`#![feature(generic_assert)]`I-libs-radarLibs issues that are tracked on the team's radar.PG-error-handlingProject group: Error handling (https://github.com/rust-lang/project-error-handling)S-tracking-impl-incompleteStatus: The implementation is incomplete.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions