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

Change extern "ABI" to extern<ABI> or extern ABI or extern(ABI) #156

Closed
wants to merge 2 commits into from

Conversation

glaebhoerl
Copy link
Contributor

@lilyball
Copy link
Contributor

lilyball commented Jul 5, 2014

I don't see the benefit to this. The supported ABIs for a function type are determined by the compiler, not by the library, and so having to use an enumeration (which would presumably be defined in the library using lang items to identify it to the compiler) for ABI just strikes me as odd.

The only proposed benefit is the ability to abstract over the ABI of a function, but we could support this today merely by having the compiler provide automatic generation of function shims that expose a function from one ABI as if it were another. In fact, we basically already have this through closures; if you accept a closure value, function values will be implicitly wrapped in closures. I haven't tested to see how that handles ABI but I assume the compiler does that regardless of the function ABI.

An unlisted drawback is that providing an enumeration like this is polluting the prelude with yet more stuff. We try to avoid putting values in the prelude (for the most part it's just traits), but for extern<ABI> to be useful, we'd have to put the enumeration variants in the prelude as well. Not doing so makes it even more confusing how to specify a function of a different ABI and makes it harder to teach people how it's supposed to work.

@glaebhoerl
Copy link
Contributor Author

Just to be clear, this proposal is only about changing the syntax we currently use, not any kind of semantic change (exposing an enum, adding it to the prelude, etc.). It only creates the opportunity for later adding that kind of thing, if we want to.

Even if we never actually end up doing that, conceptually the ABI specifier is still much more like an enumeration member than a string. There is a limited list of options and you choose one of them; it's not free-form. Of course, making a breaking change just for this kind of conceptual consistency may not be worthwhile.

I'm not particularly attached to this idea, and I have no idea whether it might have any practical benefit myself. I just figured I would write it up because it's interesting, and one of those rare RFCs which is small.

The supported ABIs for a function type are determined by the compiler, not by the library, and so having to use an enumeration (which would presumably be defined in the library using lang items to identify it to the compiler) for ABI just strikes me as odd.

The list-of-variants would probably have to come from the compiler in some fashion.

@huonw
Copy link
Member

huonw commented Jul 7, 2014

I definitely prefer using identifiers (rather than strings) for closed classes this; as you say, strings feel free-form.

@o11c
Copy link
Contributor

o11c commented Jul 8, 2014

I prefer strings, because who's to say that one day someone won't write a compiler plugin that does extern "Nimrod" or extern "Clay"?

@huonw
Copy link
Member

huonw commented Jul 8, 2014

@o11c being an identifier doesn't prohibit other names, i.e. the parser etc. could handle extern<Foo> and just have some later pass check the Foo.

@pcwalton
Copy link
Contributor

pcwalton commented Jul 9, 2014

How does this interact with macro hygiene?

@bstrie
Copy link
Contributor

bstrie commented Jul 11, 2014

I missed that this was not proposing an enum for all possible ABIs. Even if we could create such an enum sometime in the future, I highly doubt that we ever would, as adding names to the prelude is both gross and backwards-incompatible.

So really this is just strictly a syntactic change. extern "C" is definitely gunky, but has precedent from C++. Maybe it's so minor that it doesn't matter breaking with precedent. I don't like extern<C>, as pretending there's some sort of real parameterization going on is just as misleading as having it being a string. extern C looks okay, I suppose. Mostly I'm ambivalent.

@Ericson2314
Copy link
Contributor

+1 identifiers seem much more appropriate than string literals.

@blaenk
Copy link
Contributor

blaenk commented Jul 20, 2014

I'm in favor of this change, since like @huonw says, strings feel free-form when they're clearly not. +1

EDIT: I think I prefer the extern<ABI> notation as it makes it clearer that the ABI identifier is part of the extern declaration.

// what's system?
let fptr: extern system fn() -> int = new_int;

// clearer IMO
let fptr: extern<system> fn() -> int = new_int;

@glaebhoerl
Copy link
Contributor Author

I think extern<ABI> would be a good idea if and only if the idea of ABI as a type argument is actually a good intuition. (I'm not completely sure whether it is; I just think it might be.)

If it's not, then there'd be no point in changing from one misleading intuition to another misleading intuition. Either extern ABI, or perhaps extern(ABI) as another possibility (to make it clearer that they belong together), would be a better option in that case.

@pczarn
Copy link

pczarn commented Jul 20, 2014

I consider the association with type arguments to be good intuition. A close analogy within the type system seems to be fn foo<T: Integer>(bar: T) where T could be passed as for example i16 or i64, but that's a low level detail. Moreover, parameterization over the ABI is intriguing.

Still, extern "C" is common in C++. And the extern Rust syntax is lightweight. So each alternative has a merit.

@liigo
Copy link
Contributor

liigo commented Jul 20, 2014

-1. Looks weird syntax, where ABI is neither keywords nor library defined names.

extern "C" is the syntax that C++ uses. It's OK, especially for FFI.

@alexchandel
Copy link

How does

extern rust-call fn call(...);

compare to

extern "rust-call" fn call(...);

?

Requiring ABI names to be identifiers may limit what compiler plugins one could provide. Also, it may create the illusion of collision with or shadowing of other identifiers in scope.

@glaebhoerl
Copy link
Contributor Author

FWIW I'm leaning toward

extern(rust-call) fn call(...);

syntax iff the extern<> analogy is considered to not be sensible.

@huonw
Copy link
Member

huonw commented Jul 28, 2014

Why not RustCall, rustcall or rust_call (etc.)?

@glaebhoerl glaebhoerl changed the title Change extern "ABI" to extern<ABI> or extern ABI Change extern "ABI" to extern<ABI> or extern ABI or extern(ABI) Jul 28, 2014
@alexchandel
Copy link

So the choices are:

#[link(name = "c")]
extern "C"
{
    fn printf(arg: *const u8, ...) -> i32;
}

#[link(name = "c")]
extern C
{
    fn printf(arg: *const u8, ...) -> i32;
}

#[link(name = "c")]
extern(C)
{
    fn printf(arg: *const u8, ...) -> i32;
}

#[link(name = "c")]
extern<C>
{
    fn printf(arg: *const u8, ...) -> i32;
}

Unless the types C, fastcall, Rust, etc, or something like enum ABI {C, Rust, RustCall, cdecl, fastcall, ...} were actually provided somewhere, the syntax looks misfitting. But since arbitrary string literals aren't valid calling conventions, a change is appropriate.

It's similar to what's already provided in syntax::abi, enum Abi { C, Rust, RustCall, Cdecl, Fastcall, ...}, except syntax::abi::Abi changes the names to fit Rust's CamelCase. This may or may not be appropriate for all, e.g. extern(Fastcall).

@brendanzab
Copy link
Member

I like extern<RustCall> fn ....

A counter to the argument against extensibility could be that type parameter is an uninhabited enum, ie. enum RustCall {}. Therefore using the parametrization syntax makes sense.

@brson
Copy link
Contributor

brson commented Sep 3, 2014

Although the syntax is not attractive, it's not 'common', there's existing precedent, and the string syntax makes it clear these are implementation- and platform-specific and not keywords or 'normal' identifiers. We'll keep this as-is. Thank you.

Meeting discussion

@brson brson closed this Sep 3, 2014
withoutboats pushed a commit to withoutboats/rfcs that referenced this pull request Jan 15, 2017
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

Successfully merging this pull request may close these issues.