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)
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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