rust-lang / rust-analyzer

A Rust compiler front-end for IDEs
https://rust-analyzer.github.io/
Apache License 2.0
14.36k stars 1.62k forks source link

Weird mismatched-arg-count lint on gtx_pipeline! macro. #9887

Open haihala opened 3 years ago

haihala commented 3 years ago

I'm new-ish to rust and don't know if the error is in the code or in the analyzer.

Opening https://github.com/PistonDevelopers/piston-examples/blob/master/examples/cube.rs in vscode makes rust-analyzer complain about mismatched-arg-count on lines 25-32. The exact message is a bit stranger still:

{
    "resource": "<redacted>",
    "owner": "rustc",
    "code": {
        "value": "mismatched-arg-count",
        "target": {
            "$mid": 1,
            "external": "https://rust-analyzer.github.io/manual.html#mismatched-arg-count",
            "path": "/manual.html",
            "scheme": "https",
            "authority": "rust-analyzer.github.io",
            "fragment": "mismatched-arg-count"
        }
    },
    "severity": 8,
    "message": "expected 7 arguments, found 4",
    "source": "rust-analyzer",
    "startLineNumber": 25,
    "startColumn": 1,
    "endLineNumber": 32,
    "endColumn": 4
}

The message says it expects 7 arguments, but found 4. Neither of these numbers make sense in any way I can think of.

Code of the macro:

/// Defines a set of pipeline-associated structures, and also
/// adds `new` constuctor for the `Init` structure.
#[macro_export]
macro_rules! gfx_pipeline {
    ($module:ident {
        $( $field:ident: $ty:ty = $value:expr, )*
    }) => {
        #[allow(missing_docs)]
        pub mod $module {
            #[allow(unused_imports)]
            use super::*;
            #[allow(unused_imports)]
            use super::gfx;
            gfx_pipeline_inner!{ $(
                $field: $ty,
            )*}
            pub fn new() -> Init<'static> {
                Init {
                    $( $field: $value, )*
                }
            }
        }
    }
}

Application of the macro:

gfx_pipeline!( pipe {
    vbuf: gfx::VertexBuffer<Vertex> = (),
    u_model_view_proj: gfx::Global<[[f32; 4]; 4]> = "u_model_view_proj",
    t_color: gfx::TextureSampler<[f32; 4]> = "t_color",
    out_color: gfx::RenderTarget<::gfx::format::Srgba8> = "o_Color",
    out_depth: gfx::DepthTarget<::gfx::format::DepthStencil> =
        gfx::preset::depth::LESS_EQUAL_WRITE,
});
lnicola commented 3 years ago

It happens when for some reason (wrong type inference/trait solving, wrong macro expansion, unsupported features like const generics) we pick up the wrong function.

It would really help if you can extract a reduced test case, but it's all right if you can't or don't have the time.

flodiebold commented 2 years ago

This is still happening, and really confusing. Here's a small reproduction:

fn foo(s: gfx::TextureSampler<[f32; 4]>) {
    let (a, b, c, d);
    s.bind_to(a, b, c, d);
}

Hovering over bind_to shows

gfx::pso::DataBind

pub fn bind_to(&self, RawDataSet: {error}, _: {error}, _: {error}, _: {error}, _: {error}, AccessInfo: {error}, _: {error})

---

Dump the given data into the raw data set.

but going to the definition shows the following code:

/// The "bind" logic portion of the PSO component.
/// Defines how the user data translates into the raw data set.
pub trait DataBind<R: c::Resources> {
    /// The associated "data" type - a member of the PSO "data" struct.
    type Data;
    /// Dump the given data into the raw data set.
    fn bind_to(&self,
               &mut RawDataSet<R>,
               &Self::Data,
               &mut c::handle::Manager<R>,
               &mut AccessInfo<R>);
}

which clearly takes 4 parameters. I don't understand how we can have two different definitions here.

Veykril commented 2 years ago

The reason for that is that we fail to parse the param list properly here. Because of that error recovery kicks in which parses each path segment as a new parameter, so Self::Data becomes two, and c::handle::Manager<R> becomes 3 parameters totalling 8 parameters.

Veykril commented 2 years ago

Given anonymous parameters are a hard error since the 2018 edition we could consider this a wontfix if it turns out to be too much work to fix in the parser

lnicola commented 2 years ago

If we do end up with a shared parser, we might have to fix this anyway.

flodiebold commented 2 years ago

Well, it might be a wontfix-until-shared-parser then ;)

flodiebold commented 2 years ago

gfx is also kind of deprecated; there are probably few maintained crates that use anonymous parameters.