Rust allows function argument names to shadow unit structs imported in function body

9b36885
Opened by Sage Griffin at 2019-09-28 23:50:17

Assume that foo::bar is a unit struct in all these examples. This fails to compile:

use foo::bar;

fn foo(bar: i32) {}

As does this:

fn foo() {
    use foo::bar;
    let bar = 1;
}

However, this compiles successfully:

fn foo(bar: i32) {
    use foo::bar;
}

It probably shouldn't. The local variable bar can never be accessed for the same reason as the first two. This has led to some confusion by users of Diesel, when they tried to write code like the following:

fn find_by_email(conn: &PgConnection, email: &str) -> QueryResult<User> {
    use schema::users::dsl::*;
    use schema::users;

    users.filter(users::email.eq(email)).first(conn)

However, users::email and email are both that unit struct, so this code would return the first user in the database not the user with the given email as you'd expect. It does at least complain about the unused argument, but this should be a hard error.

  1. The problem is that the unit struct is shadowing the function argument, not the other way around.

    Ariel Ben-Yehuda at 2017-03-16 14:56:56

  2. @sgrif so the reproducer would be:

    mod foo {
        pub struct bar;
    }
    
    fn foo(bar: i32) {
        use foo::bar;
    }
    

    ?

    Mazdak Farrokhzad at 2019-09-28 23:07:09

  3. I believe so, yes

    Sage Griffin at 2019-09-28 23:50:17