Skip to content

Removal of NtTy resulted in regression #138975

Closed
@raoulstrackx

Description

@raoulstrackx
Contributor

We encountered an issue that starting with nightly-2025-02-23, the async-usercalls crate fails to compile. We managed to come up with a minimal working run-make test, and found that the issue was introduced by commit 76b04437be91069260c72a6d59d130a4e127a9a8 as part of #133436.

Code

See this branch for a run-make test. Starting from nightly-2025-02-23 this fails with:

error: no rules expected `ty` metavariable
 --> two/src/main.rs:9:13
  |
4 | macro_rules! type_matcher {
  | ------------------------- when calling this macro
...
9 |     let _x: call_with_type!(type_matcher) = 42;
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no rules expected this token in macro call
  |
note: while trying to match `u64`
 --> two/src/main.rs:5:6
  |
5 |     (u64) => { u64 };
  |      ^^^
  = note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens
  = note: see <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment> for more information
  = help: try using `:tt` instead in the macro definition
  = note: this error originates in the macro `call_with_type` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
 --> two/src/main.rs:9:45
  |
9 |     let _x: call_with_type!(type_matcher) = 42;
  |             -----------------------------   ^^ expected `()`, found integer
  |             |
  |             expected due to this

For more information about this error, try `rustc --explain E0308`.
error: could not compile `two` (bin "two") due to 2 previous errors

Activity

added
I-prioritizeIssue: Indicates that prioritization has been requested for this issue.
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Mar 26, 2025
petrochenkov

petrochenkov commented on Mar 26, 2025

@petrochenkov
Contributor
self-assigned this
on Mar 26, 2025
added
A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
and removed
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Mar 26, 2025
nnethercote

nnethercote commented on Mar 26, 2025

@nnethercote
Contributor

It's late here, so I'll look at this closely tomorrow. But I will note an interesting thing from the crater run for #124141: there were several failures in the following form:

In every case, there is a declarative macro with some kind of complexity: a cfg attribute, or a cross-crate boundary, or a nested macro, or some combination. In every case, the old compiler accepts the complex declarative macro while rejecting a simpler form of the same macro, e.g. with the cfg removed, or in an intra-crate case. In every case the new compiler rejects both the more complex and simpler forms, for improved consistency. I believe that the old compiler is buggy in its current behaviour, and that the inconsistencies arise because of the complexity of the internal handling of Interpolated.

And the example involves a cross-crate boundary and a nested declarative macro, so it very much fits this pattern. In other words, it's possible that the code shouldn't have been compiling in its current form.

nnethercote

nnethercote commented on Mar 26, 2025

@nnethercote
Contributor

My hunch from yesterday was correct: this is invalid code that the old compiler (pre-#133436) should not have accepted, and the new compiler (post-#133436) is now correctly rejecting it. Details below.


I reproduced the behaviour. I didn't use the run-make test, I just created two crates one and two, where two depends on one, and built two. Thank you for minimizing, that was very helpful.

If I combine one and two into a single crate like this:

macro_rules! define_call_with_type {
    // if you replace `ty` with `tt` here, it compiles with the latest nightly
    ($ty: ty) => {
        macro_rules! call_with_type {
            ($m:ident) => { $m! { $ty } }
        }
    };
}

define_call_with_type!(u64);

macro_rules! type_matcher {
    (u64) => { u64 };
}

fn main() {
    let _x: call_with_type!(type_matcher) = 42;
}

then both the old compiler and the new compiler give the same error (modulo some very slight wording changes in the error message). I believe this is the correct behaviour here, and likewise giving an error when the code is split across two crates is also the correct behaviour. In other words, this code is invalid, the old compiler was incorrectly accepting it when it was split across two crates due to a bug in the handling of declarative macros across crate boundaries, and #133436 fixed the bug. This matches the handful of other failures seen in the crater run. (I don't know why async-usercalls didn't show up as a failure in that crater run.)

So I think there is nothing to be done on the compiler side, and the appropriate course of action is to fix the problem in async-usercalls. As the error message explains, changing the ty fragment specifier to tt is enough to fix the reduced test case, and hopefully the fix in the full crate is equally simple. Apologies for the inconvenience!

removed
I-prioritizeIssue: Indicates that prioritization has been requested for this issue.
regression-untriagedUntriaged performance or correctness regression.
on Mar 27, 2025
jethrogb

jethrogb commented on May 22, 2025

@jethrogb
Contributor

Why wasn't https://rustc-dev-guide.rust-lang.org/bug-fix-procedure.html followed to ensure a smooth transition for code that depended on the broken behavior? This is causing issues downstream of us.

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

Metadata

Metadata

Assignees

Labels

A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)C-bugCategory: This is a bug.T-compilerRelevant to the compiler 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

      Participants

      @jethrogb@nnethercote@petrochenkov@apiraino@jieyouxu

      Issue actions

        Removal of `NtTy` resulted in regression · Issue #138975 · rust-lang/rust