vscode-rust icon indicating copy to clipboard operation
vscode-rust copied to clipboard

Rust extension reporting problems which don't(?) exist

Open ayesaac opened this issue 5 years ago • 3 comments

I'm new to Rust, so it's entirely possible I'm missing something obvious here, but I've run into a weird scenario where the VS Code extension (I've disabled every other extension) is reporting problems which don't exist.

I've written a macro that allows me to annotate types with an identifier, and build an enum containing variants for each of those types, as well as a 'type enumeration' enum which is identical, but without any associated data on the variants. It builds A-OK with no complaints—cargo build works.

However, the Rust extension in VS Code reports four errors (E0428):

the name `Message1` is defined multiple times
`Message1` redefined here
note: `Message1` must be defined only once in the type namespace of this enum

the name `Message1` is defined multiple times
previous definition of the type `Message1` here
note: `Message1` must be defined only once in the type namespace of this enum

the name `Message2` is defined multiple times
`Message2` redefined here
note: `Message2` must be defined only once in the type namespace of this enum

the name `Message2` is defined multiple times
previous definition of the type `Message2` here
note: `Message2` must be defined only once in the type namespace of this enum

The actual code in question is:

    #[message(Test)]
    pub struct Message1 {
        pub val: i32,
    }

    #[message(Test)]
    pub struct Message2;

    #[write_message_type(Test)] // Red squiggly
    pub enum Test {
    }

cargo expand outputs:

    pub struct Message1 {
        pub val: i32,
    }
    pub struct Message2;
    pub enum TestTypes {
        Message1,
        Message2,
    }
    pub enum Test {
        Message1(Message1),
        Message2(Message2),
    }

Given the expansion is correct (and the crate builds and produces the expected outputs when wrapping & unwrapping messages), I'm not sure whether the macro code has much relevance, but just incase, here it is. Be forewarned, it's quick, dirty, unfinished, and my first attempt at writing a macro (without having done enough reading beforehand, frankly).

lazy_static! {
    static ref MESSAGE_MAP: Mutex<HashMap<String, Vec<String>>> = Mutex::new(HashMap::new());
}

#[proc_macro_attribute]
pub fn message(attr: TokenStream, item: TokenStream) -> TokenStream {
    match MESSAGE_MAP.lock() {
        Ok(mut map) => map.entry(attr.to_string()).or_insert(Vec::new()).push(
            syn::parse::<syn::DeriveInput>(item.clone())
                .expect("Invalid target for message attr")
                .ident
                .to_string(),
        ),
        Err(e) => panic!("Message map lock poisoned: '{}'.", e.to_string()),
    }

    item
}

#[proc_macro_attribute]
pub fn write_message_type(attr: TokenStream, _: TokenStream) -> TokenStream {
    let name = attr.to_string();
    match MESSAGE_MAP.lock() {
        Ok(map) => match map.get(&name) {
            Some(entries) => {
                let message_type_enumeration_name = syn::parse_str::<syn::Ident>(&(name.clone() + "Types")).expect("Invalid message wrapper name.");
                let type_entries: Vec<_>= entries.iter().map(|e| syn::parse_str::<syn::Ident>(e).expect("Something went horribly wrong enumerating the wrapped message types")).collect();

                let message_wrapper_name = syn::parse_str::<syn::Variant>(&name).expect("Invalid message wrapper name.");
                let wrapper_entries: Vec<_>= entries.iter().map(|e|{
                    let mut variant = e.clone();
                    variant += "(";
                    variant += e;
                    variant += ")";
                    syn::parse_str::<syn::Variant>(&variant).expect("Something went horribly wrong enumerating the wrapped message types")}).collect();
                
                     (quote! {
                    pub enum #message_type_enumeration_name {
                        #(#type_entries),*
                    }

                    pub enum #message_wrapper_name {
                        #(#wrapper_entries),*
                    }
                })
                .into()
            }
            None => panic!("Tried to expand message type wrappers '{}', but no message types were recorded for it!", name)
        },
        Err(e) => panic!("Message map lock poisoned: '{}'.", e.to_string()),
    }
}

VS Code is up to date, the Rust extension is up to date, and my Win 10 installation is up to date. As I can build, it's not the end of the world, but it would be nice to not have those errors in the problem panel; if it's a problem with my code, and not the extension, my apologies.

ayesaac avatar Sep 17 '20 19:09 ayesaac