Skip to content

unreachable!("{}") works on Rust 2021 #92137

Closed

Description

@m-ou-se

The behavior of unreachable does not depend the edition of the crate that invoked the macro. That's fine for todo!() and unimplemented!() due to the way they are implemented, but in #92068, it was discovered that unreachable!() behaves subtly different, due to the way it has a special one-argument case. Looks like missed this when working on the 2021 panic macros. :(

Activity

  1. added
    A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)
    C-bugCategory: This is a bug.
    on Dec 20, 2021
  2. self-assigned this
    on Dec 20, 2021
  3. changed the title [-]unimplemented!("{}") works on Rust 2021[/-] [+]unreachable!("{}") works on Rust 2021[/+] on Dec 20, 2021
  4. m-ou-se commented on Dec 20, 2021

    @m-ou-se
    MemberAuthor

    todo!() and unimplemented!() are implemented like this:

    macro_rules! todo {
    () => ($crate::panic!("not yet implemented"));
    ($($arg:tt)+) => ($crate::panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
    }

    They never accepted todo!("{}") or todo!(123) since their arguments are always directly passed to format_args!(). So, they didn't have to change for Rust 2021.

    unreachable!() however, is implemented differently:

    macro_rules! unreachable {
    () => ({
    $crate::panic!("internal error: entered unreachable code")
    });
    ($msg:expr $(,)?) => ({
    $crate::unreachable!("{}", $msg)
    });
    ($fmt:expr, $($arg:tt)*) => ({
    $crate::panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
    });
    }

    It doesn't just forward to panic!() or format_args!(), but instead it does its own concat shenanigans, and has special handling of the single argument case.

  5. m-ou-se commented on Dec 20, 2021

    @m-ou-se
    MemberAuthor

    So then the question is: Do we consider this a bug in Rust 2021 and fix it in Rust 1.59 for that edition? Or leave this in and only fix it in a later edition (or never)?

    There's quite a few cases on crates.io of Rust 2015/2018 code depending on this behavior, but Rust 2021 is very new at this point. Adding this change/fix to Rust 2021 probably doesn't break anyone, yet.

  6. m-ou-se commented on Dec 20, 2021

    @m-ou-se
    MemberAuthor

    Behavior:

    unreachable!();          // panic message: "internal error: entered unreachable code"
    unreachable!(123);       // panic message: "internal error: entered unreachable code: 123"
    unreachable!("{}");      // panic message: "internal error: entered unreachable code: {}"
    unreachable!("{}", 123); // panic message: "internal error: entered unreachable code: 123"
    
  7. m-ou-se commented on Dec 20, 2021

    @m-ou-se
    MemberAuthor

    We can't fix unreachable without making it a builtin macro, like panic!(). That's because (unlike e.g. debug_assert), this macro doesn't just forward to assert/panic, but has its own problematic implementation with a special case that shouldn't exist.

  8. jyn514 commented on Dec 20, 2021

    @jyn514
    Member

    We can't fix unreachable without making it a builtin macro, like panic!(). That's because (unlike e.g. debug_assert), this macro doesn't just forward to assert/panic, but has its own problematic implementation with a special case that shouldn't exist.

    I'm not sure I follow - can't we remove the concat special case and forward directly to panic, like todo does?

  9. m-ou-se commented on Dec 20, 2021

    @m-ou-se
    MemberAuthor

    I'm not sure I follow - can't we remove the concat special case and forward directly to panic, like todo does?

    @jyn514 Then unreachable!(123) would stop working on Rust 2015/2018.

  10. m-ou-se commented on Dec 20, 2021

    @m-ou-se
    MemberAuthor

    From a quick grep through crates.io, it looks like there's about 15 crates on crates.io depending on the current behavior that would break if we made it work like todo!(). Here's a few examples from the grep results:

    unreachable!(message);
    unreachable!(&error)
    unreachable!(format!("Cannot compute gcd of {:?} and {:?}", x, y))
    Err(err) => unreachable!(err),
    _ => unreachable!(format!("Unsupported socket family {}!", raw.family)),
    l => unreachable!(format!("got unexpected length {0:?}", l)),
    x => unreachable!(x),
    Error { message } => unreachable!(message),
    unreachable!(false);
    unreachable!(msg)
    unreachable!(&format!("n = {:?}", n)),
    _ => unreachable!(ERROR_MSG),
    _ => unreachable!(format!("{} is invalid month!", month)),
    hash => { unreachable!(hash); }
    
  11. joshtriplett commented on Dec 20, 2021

    @joshtriplett
    Member

    Making unreachable built-in to fix this on Rust 2021 seems reasonable to me.

  12. jhpratt commented on Dec 21, 2021

    @jhpratt
    Member

    IMO as long as there's a crater run fixing this is reasonable. It's certainly a bug.

  13. added
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Jan 5, 2022
  14. 48 remaining items

  15. added a commit that references this issue on Feb 11, 2022
  16. Arnavion commented on Feb 22, 2022

    @Arnavion
    Contributor

    @m-ou-se @Urgau Will this be in 1.59.0? I don't see it in the release notes, but I do see the fix in the beta git branch. If it's going to be in 1.59.0, could the release notes be updated to mention it?

  17. jhpratt commented on Feb 22, 2022

    @jhpratt
    Member

    This is in fact on beta: playground

  18. Arnavion commented on Feb 22, 2022

    @Arnavion
    Contributor

    Yes, as I said it's in the beta branch but not mentioned in the release notes for the upcoming 1.59.0. So if it's confirmed that it will be in 1.59.0, then it would be great if the release notes could be updated to mention it.

  19. Urgau commented on Feb 22, 2022

    @Urgau
    Member

    Yes it will be 1.59.0. cc @Mark-Simulacrum about the change not being in the release notes.

  20. added
    relnotesMarks issues that should be documented in the release notes of the next release.
    on Feb 22, 2022
  21. Mark-Simulacrum commented on Feb 22, 2022

    @Mark-Simulacrum
    Member

    #94265 includes a note about this into the 1.59 release notes.

  22. jqnatividad commented on Feb 24, 2022

    @jqnatividad
    Contributor

    Folks, reading the 1.59 release notes, it's odd that the markdown link to this issue is not rendering.

    https://github.com/rust-lang/rust/blob/stable/RELEASES.md#compatibility-notes

  23. Urgau commented on Feb 24, 2022

    @Urgau
    Member

    @jqnatividad Already reported here with a response here, but basically fixing this rendering issue would required a complete rebuild of all the artifacts of 1.59.0 which don't seems worth while.

  24. jyn514 commented on Mar 3, 2022

    @jyn514
    Member

    Why was there no future-incompat warning for this? The first time I saw it was when a stable compiler upgrade broke my code.

  25. Urgau commented on Mar 3, 2022

    @Urgau
    Member

    Why was there no future-incompat warning for this? The first time I saw it was when a stable compiler upgrade broke my code.

    See #92137 (comment), in particular:

    There's probably not many problematic invocations of this macro in general, and much less in Rust 2021 code, considering how recently that edition has been available.

    And

    I just see this as a bug that needs fixing, as the decision to make the panic macros consistent in 2021 has already been made. But since this is technically breakage, let's quickly check some boxes or raise some concerns:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-edition-2021Area: The 2021 editionA-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)C-bugCategory: This is a bug.P-highHigh priorityT-libs-api[DEPRECATED; DO NOT USE]disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.finished-final-comment-periodThe final comment period is finished for this PR / Issue.relnotesMarks issues that should be documented in the release notes of the next release.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions