Disallow duplicated extern declarations

a561032
Opened by klutzy/defunct at 2024-01-22 20:52:51
mod a {
    extern {
        fn func();
    }
}

mod b {
    extern {
        fn func(i: i8); // different signature
    }
}

Currently rustc accepts this, but I think it should be disallowed to reduce potential mistakes.

  1. This would disallow duplicate functions with different signatures, but still allow duplicate with the same?

    Brian Anderson at 2014-03-05 08:37:56

  2. I thought identical duplicates are ok because make check-fast needs them. Some rpass tests use same extern fn then they are combined into one crate.

    klutzy/defunct at 2014-03-05 14:13:06

  3. Modified test case causing llvm assertion error on x64:

    mod a {
        extern {
            fn func(); // declare void @func() unnamed_addr
        }
    }
    
    mod b {
        struct S {
            a: u64,
            b: u64,
            c: u64,
        }
    
        extern {
            fn func(s: S); // declare void @func(%"struct.b::S"* byval) unnamed_addr
        }
    }
    
    rustc: /media/a/lime/src/rust/src/llvm/include/llvm/Support/Casting.h:240:typename llvm::cast_retty<X, Y*>::ret_type llvm::cast(Y*) [with X = llvm::Argument; Y = llvm::Value; typename llvm::cast_retty<X, Y*>::ret_type = llvm::Argument*]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
    

    In the case, argument has byval attribute.

    klutzy/defunct at 2014-03-10 01:05:52

  4. cc #12762: <del>it contains a patch to suppress llvm assertion error above.</del> Not really.

    klutzy/defunct at 2014-03-10 02:37:44

  5. klutzy's test case is causing a different error now on 64-bit Linux:

    Attribute after last parameter!
    void ()* @func
    LLVM ERROR: Broken module found, compilation aborted!
    

    Are duplicate declarations useful/necessary for calling functions like objc_msgSend? IIRC, that function isn't really varargs -- the prototype varies depending upon which ObjC method is invoked. (I discovered this GitHub issue because I did something similar to objc_msgSend.)

    Ryan Prichard at 2014-10-17 06:56:59

  6. Traige: Still getting the same failure as @rprichard , but I'm also on x86-64. Does this fail everywhere now?

    Steve Klabnik at 2015-12-31 18:04:19

  7. On x86-64 as well, does not reproduce with --crate-type lib and rustc 1.18.0-nightly (bbdaad0dc 2017-04-14). Going to presume the assertions are fixed, but the original issue (multiple externs with the same name) isn't, so leaving open.

    Mark Rousskov at 2017-04-15 17:51:37

  8. Triage: no change

    Steve Klabnik at 2018-09-24 17:18:18

  9. The rustc compiler does throw warnings when we use two conflicting function signatures in extern declarations. So, shall we change this to disallow it and instead throw an error?

    BurgundyWillow at 2020-12-09 08:44:11

  10. objc_msgSend is declared with multiple signatures in libstd. The signature of this function depends on the message sent. It forwards all arguments to the called method. Declaring it as a vararg function is not valid in AArch64 due to ABI differences.

    bjorn3 at 2023-05-31 18:44:01

  11. objc_msgSend is declared with multiple signatures in libstd. The signature of this function depends on the message sent. It forwards all arguments to the called method. Declaring it as a vararg function is not valid in AArch64 due to ABI differences.

    Since https://github.com/rust-lang/rust/pull/117910, this is no longer true, instead we explicitly cast the function pointer (which is arguably the more correct behaviour, at least it's what the C headers also declare and expect you to do).

    Mads Marquart at 2024-01-22 20:52:51