Skip to content
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

extern fn type declarations and extern fn bindings should both default to the same ABI. #9309

Closed
brson opened this issue Sep 19, 2013 · 20 comments
Milestone

Comments

@brson
Copy link
Contributor

brson commented Sep 19, 2013

This has confused me several times:

fn main() {
    extern {
        // extern "C"
        fn foo();
    }

    // extern "Rust"
    let f: extern fn() = foo; // error
}
@brson
Copy link
Contributor Author

brson commented Sep 19, 2013

Nominating back compat.

@catamorphism
Copy link
Contributor

accepted backwards-compatible

@nikomatsakis
Copy link
Contributor

Relates to #2202.

@huonw
Copy link
Member

huonw commented Nov 3, 2013

extern fn foo() {
    // do Rust things
}

seems to have the C ABI by default too.

@brson
Copy link
Contributor Author

brson commented Jan 28, 2014

Is there still even an extern "Rust" type? What is the default for locals now?

@nikomatsakis
Copy link
Contributor

Yes, I believe fn(T) -> U is shorthand for extern "Rust" fn(T) -> U. It occurs to me that extern fn(T) -> U could (reasonably) be shorthand for extern "C" fn(T) -> U.

@nrc
Copy link
Member

nrc commented Feb 14, 2014

looking at this

@nrc
Copy link
Member

nrc commented Feb 14, 2014

The question is, if they should both default to the same ABI - which ABI? C or Rust?

@nrc
Copy link
Member

nrc commented Feb 14, 2014

Niko explained via irc that his comment implies that all uses of (unadorned) extern should mean extern "C"

@brendanzab
Copy link
Member

As I commented on #12328, why is this? Wouldn't it make more sense to have extern fn mean extern "Rust" fn? This is looking to the future here. We are our own language.

@huonw
Copy link
Member

huonw commented Feb 24, 2014

@bjz fn is the short name for a Rust function; shouldn't extern fn be the most common type used for FFI/extern-stuff (i.e. C ABI)?

@brendanzab
Copy link
Member

Doesn't extern "Rust" fn in function parameters mean that the function has to be free-standing?

@brendanzab
Copy link
Member

I just don't see that promoting "C" as all-powerful makes sense. Maybe I'm being idealistic here.

@huonw
Copy link
Member

huonw commented Feb 24, 2014

fn() now works for that, and with that change, extern can be regarded as just an FFI thing.

@brendanzab
Copy link
Member

Can't we just say that all externs must be followed by an ABI? Declaring extern fns is very rare outside of extern blocks, so I doubt the added verbosity would be an issue.

@brendanzab
Copy link
Member

I think this is definitely a thing that links into our 'design philosophy'. Do we privilege C as the default for all ffi stuff? If so, we need to be consistent everywhere.

@brendanzab
Copy link
Member

Another option would be to remove extern "ABI" fn, and instead have fn "ABI".

@nrc
Copy link
Member

nrc commented Feb 24, 2014

@bjz Rust tries to have identifiers always follow keywords. That makes things much easier to parse both by tools and humans, so I would be against fn "ABI" name.

We could always require an ABI for consistency, but given the target for Rust is systems programming I expect C to be the target lang for ffi in a large majority of cases. Therefore, I see nothing wrong with privileging it. It doesn't make calling any other language any harder.

@bors bors closed this as completed in 317a253 Feb 24, 2014
@huonw
Copy link
Member

huonw commented Feb 24, 2014

@bjz, there's some empirical evidence that C is the default:

$ git grep 'extern *\("C"\)\? *{' | wc -l # extern { ... }, or extern "C" { ... }
221
$ git grep 'extern *".*" *{' | grep -v "C" | wc -l # extern "non-C abi" { ... }
34

(running in the rust root dir.)

@nikomatsakis
Copy link
Contributor

On Sun, Feb 23, 2014 at 05:22:08PM -0800, Brendan Zabarauskas wrote:

As I commented on #12328, why is this? Wouldn't it make more sense to have extern fn mean extern "Rust" fn? This is looking to the future here. We are our own language.

extern "Rust" fn(S) -> T already has a short version: fn(S) -> T.

As for why one ought to use "C" by default, I think C does occupy a
privileged position, both in general and with respect to Rust. It's
the "lingua franca" for FFIs, and Rust has been specifically designed
to make C interop easy. Other ABIs (stdcall, etc) are simply far less
common, and I don't anticipate we'll ever be able to call into other
languages directly unless they offer some sort of C-compatible
public-facing interface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants