Skip to content

Hygienic macros lead to incorrect resolved types of internal variables #17573

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
DeltaEpsilon7787 opened this issue Jul 10, 2024 · 1 comment
Closed
Labels
A-hygiene C-bug Category: bug

Comments

@DeltaEpsilon7787
Copy link

DeltaEpsilon7787 commented Jul 10, 2024

rust-analyzer version: 0.3.2029 & 0.4.2031
rustc version: rustc 1.76.0
editor or extension: VSCode, also Sublime Text, though irrelevant, this is a general LSP issue

code snippet to reproduce:
Refer to this issue for the first discovery: rust-itertools/itertools#970

Equivalent itertools reproducing code

fn main() {
    macro_rules! izip {
        // @closure creates a tuple-flattening closure for .map() call. usage:
        // @closure partial_pattern => partial_tuple , rest , of , iterators
        // eg. izip!( @closure ((a, b), c) => (a, b, c) , dd , ee )
        ( @closure $p:pat => $tup:expr ) => {
            |$p| $tup
        };
    
        // The "b" identifier is a different identifier on each recursion level thanks to hygiene.
        ( @closure $p:pat => ( $($tup:tt)* ) , $_iter:expr $( , $tail:expr )* ) => {
            izip!(@closure ($p, b) => ( $($tup)*, b ) $( , $tail )*)
        };
    
        // unary
        ($first:expr $(,)*) => {
            std::iter::IntoIterator::into_iter($first)
        };
    
        // binary
        ($first:expr, $second:expr $(,)*) => {
            std::iter::Iterator::zip(
                std::iter::IntoIterator::into_iter($first),
                $second,
            )
        };
    
        // n-ary where n > 2
        ( $first:expr $( , $rest:expr )* $(,)* ) => {
            {
                let iter = std::iter::IntoIterator::into_iter($first);
                $(
                    let iter = std::iter::Iterator::zip(iter, $rest);
                )*
                std::iter::Iterator::map(
                    iter,
                    izip!(@closure a => (a) $( , $rest )*)
                )
            }
        };
    }

    let alpha = vec![1, 2, 3, 4];
    let beta = vec!["One", "Two", "Three", "Four"];
    let gamma = vec![1.0, 4.0, 9.0, 16.0];

    let it = izip!(alpha, beta, gamma);
    
    // b here is resolved to be f64, but it's actually &str
    for (a, b, c) in it {
        println!("{} {} {}", a, b, c);
    }
}

image
but it does compile (if acos line is removed) and outputs as expected
image
thus the LSP is wrong

@DeltaEpsilon7787 DeltaEpsilon7787 added the C-bug Category: bug label Jul 10, 2024
@Veykril
Copy link
Member

Veykril commented Jul 10, 2024

Duplicate of #11681

@Veykril Veykril marked this as a duplicate of #11681 Jul 10, 2024
@Veykril Veykril closed this as completed Jul 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-hygiene C-bug Category: bug
Projects
None yet
Development

No branches or pull requests

2 participants