rust-lang / rust-lang/rust-analyzer

Type checker uses different macro definitions for different parts of a single invocation of a macro. (or something like that)

Open
#21,713 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug
Dominant language
Rust
Stars
16.9k
Forks
2.2k
Avg merge
1d 12h
Merged PRs (30d)
72

Description

rust-analyzer version: 0.3.2803-standalone (0c746f6990 2026-02-22) [c:\Users\[Expunged]\.vscode\extensions\rust-lang.rust-analyzer-0.3.2803-win32-x64\server\rust-analyzer.exe]
rustc version: Tested on both 1.93.0 and 1.93.1 (this reminded me to update)

editor or extension: Visual Studio Code. Extension versions:
0.3.2803 (also tested on the pre-release version and probably whatever version came right before that because it updated while I was making the reproducible example)

relevant settings: Defaults, except for cargo check which was tested set to both clippy and check, same result.

code snippet to reproduce:

pub trait Trait {
    fn func(self);
}

macro_rules! impl_trait {
    ($($t:ty),+) => {$(
        macro_rules! bar {
            ($x:ident) => {{
                const CONST: $t = 1 << (<$t>::BITS - 1);
                
                let vec = vec![$x];
                // doesn't work
                let _ = vec.contains(&CONST);

                let vec = vec![CONST];
                // doesn't work
                let _ = vec.contains(&$x);

                // none of these work
                let _ = $x >= CONST;
                let _ = $x > CONST;
                let _ = $x < CONST;
                let _ = $x <= CONST;
                let _ = CONST >= $x;
                let _ = CONST > $x;
                let _ = CONST < $x;
                let _ = CONST <= $x;


                // only issue is with u128 for these
                // order doesn't matter as long as u128 isn't last
                let _ = $x == CONST;
                let _ = core::cmp::PartialEq::eq(&$x, &CONST);
                let _ = $x != CONST;
                let _ = core::cmp::PartialEq::ne(&$x, &CONST);

                // all of these ops are fine though
                let _ = $x - CONST;
                let _ = $x + CONST;
                let _ = $x / CONST;
                let _ = $x * CONST;
                let _ = $x % CONST;
                let _ = $x & CONST;
                let _ = $x ^ CONST;
                let _ = $x | CONST;
                let _ = CONST - $x;
                let _ = CONST + $x;
                let _ = CONST / $x;
                let _ = CONST * $x;
                let _ = CONST % $x;
                let _ = CONST & $x;
                let _ = CONST ^ $x;
                let _ = CONST | $x;
                let _ = core::ops::Add::add($x, CONST);
                let _ = core::ops::Add::add(CONST, $x);
                
                // these don't work
                let _ = $x.checked_add(CONST);
                let _ = CONST.checked_add($x);
            }};
        }
        impl Trait for $t {
            #[inline(always)]
            fn func(self) {
                bar!(self)
            }
        }
    )+};
}
/*
 *  Expanding any of these doesn't fix the issue,
 *  even after fixing the issue where comparator 
 *  ops are not expanded properly.
 */
impl_trait!(u8, u16, u32, u64, u128, usize);
// impl_trait!(u8, u16, u32, u64, u128);
// impl_trait!(u32, u128, usize);
// impl_trait!(u128, u32, usize);
// impl_trait!(u128, usize, u32);
// impl_trait!(u32, usize, u128);

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the provided macro_rules! reproduction and compare rust-analyzer's type-checking results as the generic type order changes. Trace the macro expansion and type inference paths involved in the inconsistent diagnostics; done means the same invocation is checked consistently regardless of the order of types.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.