25 ms·
Well, you get what you pay for. Rust can call and expose C-style ABI functions natively so you can always do what C does. If you want a safer Rust API you can a
by simias 9y ago
Well, you get what you pay for. Rust can call and expose C-style ABI functions natively so you can always do what C does. If you want a safer Rust API you can also have that but it makes interfacing with 3rd party code more difficult.
I disagree somewhat with your assertion that:
> C embeds a remarkable amount of cross-object-file information about a function just with 'int f();'. We know the range of valid values, we know how big the object is, etc.".
First of all this is not embedded in the object file but rather in the header, Rust doesn't need that. The object only tells you the name of the symbol and that's about it. In particular that means that the C linker can't detect ABI mismatch if the prototype of a function or the layout of a struct changed, as long as the symbol is found it'll link just fine.
Furthermore even with the header available a lot of the time C prototypes are not sufficient to know how to use a method. Take for instance:
sometype_t *some_function(someothertype_t *param, int flag);
Is param an input or output parameter? Do I own the return value or is it allocated by the function? Or maybe it's just a member of param so it has the same lifetime? I know that flag is an int but that doesn't really tell me which are the valid values I can put in there. In Rust function signatures tell you all of that and it's enforced by the compiler.
So yeah, there's a significant overhead in Rust here, but it's for a good reason IMO. It does make it harder to make quick hacks with the linker though.
> There's a reason C++ names look like CintFuncf!!!@34$902, Rust doesn't have or plan to have anything like this yet, and it'd need to be 20x more complicated.
Are you talking about name mangling? Rust does that too but that's not really the same issue, it's just about generating unique "flat" names for objects that include namespacing and generic info. Like if you have a "fn foo<T>(t: &T)" and you instanciate it with T = i32 and T = String you need to generate two symbols. C doesn't need that because it doesn't have namespaces, generics or overloading.
- kibwen 9y ago> C doesn't need that because it doesn't have namespaces, generics or overloading. Overloading as in operator overloading? Because I don't see how that would affect symbols. Though along with namespaces and generics, there is one thing that Rust also bakes into symbols: versioning information. This is how, in the case of deep dependency graphs, it's possible for a finished binary to include multiple copies of the same library in the event that multiple versions are transitively depended upon. But that doesn't add any complexity to symbol mangling on its own, because if you already have namespaces then you can just treat it as a namespace that only the compiler can see.
- zid 9y agoIt would need it if it had it. How do I find your code that adds bananas together using a banana adding operator via a text name?
- kibwen 9y agoIf you're referring to the ability to define entirely new symbolic operators like you can do in Haskell and Scala, then you'll be happy to hear that Rust doesn't support such a thing. (Frankly, I'm happy about it too. :P ) Rust only allows you to overload a fixed set of operators, and that overloading is all done via traits with well-known names (e.g. overloading the plus symbol "+" is done via implementing std::ops::Add for a type), and traits too can be effectively treated like namespaces as far as symbols are concerned.
- simias 9y agoNo I meant parameter-based function overloading like C++ has (or is it not the wrong term? I forget). So like: int do_something(int param); int do_something(double param, char *param2); I don't see how you can avoid some form of name mangling since obviously you can't just define two duplicate "do_something" symbols.
- steveklabnik 9y agoRust does not currently support parameter-based function overloading, and there are no plans to in the near-term, if ever. (This isn't the only way to end up with duplicate symbols, just trying to make it clear that this specifically won't be a problem with Rust.)
- Someone 9y agoNitpick: C11 introduced support for some form of that kind of overloading, using _Generic macros. See http://en.cppreference.com/w/c/language/generic http://en.cppreference.com/w/c/language/generic, https://stackoverflow.com/questions/9804371/syntax-and-sample-usage-of-generic-in-c11 https://stackoverflow.com/questions/9804371/syntax-and-sampl..., https://stackoverflow.com/questions/40096584/c11-generic-usage https://stackoverflow.com/questions/40096584/c11-generic-usa.... Ugly? Yes, IMO, but it also is useful.
- zid 9y ago>First of all this is not embedded in the object file but rather in the header, Rust doesn't need that. Granted, pointed about the header, I was talking more about the 'int' part but failed to describe myself well at all. I mean more that you can map it onto the ABI properly and easily. Try shuffling internal Rustisms over the usual SysV ABI. What Rust means by anything is still entirely up in the air, and last I checked their bug tracker, the issue had been open for years and was basically commented as "probably won't ever resolve due to rust changing too often". >Furthermore even with the header available a lot of the time C prototypes are not sufficient to know how to use a method. A keyword could be added for that, you wouldn't be able to enforce it on the ABI level but you could make the compiler check the same as Rust. I'm not here to argue about which is better though, I think I accidentally led you up this path though. >Are you talking about name mangling? Rust does that too but that's not really the same issue I need to know how to generate those 'flat names', is the point, I can't call it if I can't name it, and it all plays in from the same systemic issue in that Rust has no idea what it is doing from week to week. EDIT: I'll use this space to re-iterate, if you get rid of all the Rustisms and shuffle everything over the existing SysV ABI, you're left with C. Keeping the Rustisms will need megs of data sending over the ABI somehow to allow Rust to elide bounds checks, etc that Rust is useful for to begin with.
- kibwen 9y ago> What Rust means by anything is still entirely up in the air, and last I checked their bug tracker, the issue had been open for years and was basically commented as "probably won't ever resolve due to rust changing too often". Do you have a link? There's a good chance that issue was opened and that comment made before 1.0, when things really were changing too often. Change is less common these days, though I'm sure the compiler developers do still enjoy not being restrained by the need to maintain ABI backwards-compatibility (which isn't to say they couldn't be convinced, only that it would take cajoling). > it all plays in from the same systemic issue in that Rust has no idea what it is doing from week to week. What do you mean by this? > Keeping the Rustisms will need megs of data sending over the ABI somehow to allow Rust to elide bounds checks, etc that Rust is useful for to begin with. I'm confused here. I don't see how the ABI has anything at all to do with bounds checking; bounds checking, where it exists, is all done at runtime by regular code in the standard library. And by "etc" I presume you're referring to type inference (which you mentioned in an earlier comment), but Rust doesn't do inter-procedural type inference; it's not like Haskell or ML. There's simply nothing to infer, and no need that I can see for an ABI to care about that. Can you be more concrete?