from Hacker News

Carbon’s most exciting feature is its calling convention

by obl on 7/30/22, 6:43 PM with 217 comments

  • by Denvercoder9 on 7/30/22, 8:39 PM

    Maybe I'm missing something, but I don't see what's special about Carbon here. In C++ the compiler can also optimize pass-by-const-reference to pass-by-value, and they do. It just can't do it across an ABI boundary, but that should only be an issue with dynamic libraries, and Carbon has to follow the standard ABI there as well. Just make sure the compiler knows it doesn't have to follow the standard ABI for every symbol in your program, e.g. by enabling LTO and setting -fvisibility=hidden. See what happens `add` is made static: https://godbolt.org/z/KsqxP5Pxh (I also had to change foo() to avoid the compiler hardcoding the result of the single call in `add`).
  • by bbkane on 7/30/22, 7:58 PM

    I really think the most exciting feature of Carbon (indeed, it's justification for existence) is its backwards compatibility with C++, followed closely by it's more modern and flexible governance structure. Even the docs in the repo say you should avoid Carbon unless you have lots of C++ code you need to interact with.
  • by Animats on 7/30/22, 8:08 PM

    That's been done before. The original Modula 1 compiler had that. In a language where the default parameter mode is a read-only reference, it's an obvious optimization.

    The reverse is true. Anything passed by value can be treated as const reference by the compiler if the compiler knows enough about access and lifetime. The compiler must be able to determine that the parameter is neither deallocated nor modified while the function is using it. Rust compilers should be able to do that.

  • by oneplane on 7/30/22, 7:38 PM

    At first I thought this was about Mac OS around the 9 and 10 times... but I suppose not everyone is going to make that link with this name.
  • by fwsgonzo on 7/31/22, 7:18 AM

    I have to say, and pardon me for saying so, but Carbon seems to be utterly uninteresting to me. They are not solving any interesting problems that shows me that they are creating a modern language.

    As an example, look at this issue from the mold linker: https://github.com/rui314/mold/issues/584

    They are looking at creating an embeddable custom dynamic linker in order to greatly reduce loading times, by fixing locations as the file gets loaded in.

    The equivalent in Carbon would (for example) be to create a new type of exception handling that changes how we think about exceptions, performance and their cost. Perhaps something like the static exceptions that Herb Sutter has been working on. Instead, they are not adding exceptions at all.

    You will have to excuse my disappointment.

  • by tialaramex on 7/30/22, 9:19 PM

    C++ also pays a price for insisting not only that objects have addresses, but those addresses are distinct.

    If you've got a 1.6 billion empty tuples in variable A, 1.4 billion in variable B and 1.8 billion in variable C, C++ can't see a way to do that on a 32-bit operating system. It needs to give each empty tuple an address, so it must think of 4.8 billion integers between 0 and 2^32 and it can't do that, so your program won't work.

    Carbon is still far from finished, but if objects needn't have addresses it can do the same as Rust here, and cheerfully handle A, B and C as merely counters, counting 1.6 billion, 1.4 billion and 1.8 billion respectively is fine. Empty tuples are indistinguishable, so I needn't worry about giving you back the "wrong" empty tuple when you remove one, I can just give you a fresh one each time and decrement the counter.

  • by rgovostes on 7/30/22, 7:52 PM

    I was very confused by what the author is pointing out in the opening Point / Print example. ("[T]he compiler is allowed to convert that to a T" -> wait, why did the compiler change a struct to an int32?)

    I think this boils down to: Carbon defaults to passing parameters that fit in a single register by value, and all others by const reference. This affects a few things you might take for granted in C++, like whether you can take a reference to a parameter.

    The opening example is showing two samples of Carbon and the equivalent C++ code, noting that the "undecorated" parameter `p : Point` is equivalent to `const Point& p` (pass by const reference to a struct) and `x : i32` is equivalent to `std::int32_t x` (pass by value).

  • by titzer on 7/31/22, 1:27 PM

    Carbon is what happens when you have a ton of experience programming in C++ and nothing else whatsoever. It is absolutely littered with joyful declarations of "hooray, we fixed this thing in C++", when in reality it absolutely bathed in the utter fictions of C++ and has no perspective on the entire universe of other things that we could base languages on.

    I give it a -1 on innovation, it's so obviously stuck in a cul-de-sac in the design space that I see no hope for it. "We'll get around to memory safety eventually". Riiight.

    That said, I'm glad they at least made the leap to, "Hey, we could actually use something other than C++?"

  • by matrix_overload on 7/31/22, 3:08 AM

    Spent a terrible amount of time hunting down C++ bottlenecks. It has almost never been about unintended copying of structs or classes.

    It usually boils down to someone assuming that a particular collection or algorithm won't be on the critical path, and using a lazy O(N^2) solution. Then the codebase grows, use cases shift, someone puts another O(N^2) algorithm around an existing O(N^2) and the whole thing explodes.

    Adding proper caching and switching to N*log(N) algorithms usually brings a DRAMATIC improvement (like 100x faster), while trying to squeeze out every unnecessary copy will only squeeze out about 10% of complexity.

  • by nyanpasu64 on 7/31/22, 12:03 AM

    If you call a function with `f(large_struct, &large_struct)` and f() mutates through the second/pointer argument before reading the first/value argument, will its value change even though the function signature looks like a pass-by-value?
  • by IIsi50MHz on 7/31/22, 5:11 AM

    I really thought this was gonna be about carbon atoms and molecular interactions, in some kind of geeky, programmer-friendly analogy.
  • by fourthark on 7/30/22, 8:40 PM

    This is mostly a Google project?

    Unclear from the repo who is sponsoring it.

  • by funstuff007 on 7/30/22, 11:34 PM

    > It has the usual cool features you expect from a modern language: useful generics

    Are they trolling Go here?

  • by oxff on 7/31/22, 4:20 AM

    Rust seems to have failed to be a drop-in replacement for C++.
  • by DeathMetal3000 on 7/31/22, 8:19 PM

    I realize this is unrelated to the blog post but it is related to Carbon… If you are creating an off-ramp language from C++ wouldn’t you keep the syntax as close to C++ as possible? The syntax looks like it would be more familiar to a Rust developer than a C++ developer.
  • by t6jvcereio on 7/31/22, 12:50 PM

    > Passing things by const T& is always good, right? After all, you’re avoiding a copy!

    I find the tone strange. I understand that the author doesn't believe the statement. But I've never met anyone for whom performance matters and believes this. So, who's the audience here?

  • by girvo on 7/31/22, 8:10 AM

    My one annoyance with Carbon’s promise is the lack of ABI stability; I know why they are doing that, and I know that C++ has the same downside, but as someone who binds C libraries constantly in other languages and finds the pain of C++ and now likely Carbon frustrating, it makes me a little sad to see the same mistake repeated.

    A C++ replacement that is just as difficult to bind/link/work with in other languages as C++ itself just seems like a missed mark, despite the fact I know this is not on their priority list at all.

    I hope my read of this is wrong, and it will be easy to bind and link to from other languages after all.

  • by inoyau on 7/31/22, 2:24 AM

    If this is the most exciting feature - Carbon is not that much exciting at all!
  • by tmpz22 on 7/31/22, 5:30 AM

    Language ecosystems for general purpose programming languages takes a long time to grow. We all know this. And yet here we are making college plans in the birthing room.
  • by chubs on 7/31/22, 4:06 AM

    I searched on several sites to find out what their memory management strategy is but couldn’t figure it out. GC? ARC? Whatever Rust does? Would love to see where this fits. Exciting to see a neat new language though! Also my second favourite feature of rust and swift is Enums with associated values, I can’t see any info on this but I saw a blog mention they have it.
  • by pyjarrett on 7/30/22, 9:23 PM

    It's a bit early in its lifecycle to get too excited for features which already exist in other languages. Carbon is exciting because of C++ interoperability, but I already get this behavior today in Ada.

      type Point is record
         x, y, z : Interfaces.Integer_64;
      end record;
    
      procedure Print(p : Point); 
    
    Is `p` passed by reference or value? The compiler chooses what it thinks is best--all parameters are considered `const` unless they're `out` parameters. There's some rules for classes (tagged types), uncopyable (limited) objects, and `aliased` parameters which are always passed by reference.

    I can't get a pointer type (access) out of the parameter to the function, since the accessibility rules prevent it:

      -- "constant" since we don't know if it is writable
      type Point_Access is access constant Point;
    
      Last_Printed : Point_Access := null;
    
      procedure Print(P : Point) is
      begin
         -- P'Access is sort of like C++ std::addressof(P) to get a "pointer"
         -- There's also P'Address to get the actual address, but then requires conversion to a pointer-like "access" type to be used.
         --
         -- Compiler Error: "non-local pointer cannot point to local object" since Point_Access type is declared at a higher level
         Last_Printed := P'Access;
    
         -- If we really, really, want to do it, "I'm smarter than the compiler", you can force it...
         -- Think of "Unrestricted" and "Unchecked" as grep-able warnings signs of "this is potentially very dangerous"
         Last_Access := P'Unrestricted_Access;
    
         -- ...
      end Last_Printed;
    
    What about making and then trying to use a local pointer-like type? This doesn't work because you can only create pointer-like accesses to types which have been marked as `aliased`, since you don't know if there's a location you can point to which has the value.

      procedure Print (P : Point) is
         type Local_Access is access constant Point;
    
         -- Compiler Error: prefix of "Access" attribute must be aliased
         Ptr_Like : Local_Access := P'Access;
    
         -- Similar, "I am smarter than compiler" trick works here too...
         Ptr_Like : Local_Access := P'Unrestricted_Access;
    
    You can allow passing any arbitrary pointer into a function by providing `access`, but you're not allowed to store it, since you don't know which flavor of the pointer type it could be, e.g. if it points to something on the stack, or on the heap:

      type Point_Access is access constant Point;
      Last_Printed : Point_Access := null;
    
      -- Allow printing any pointer-like (access) to a point.
      procedure Print (P : access constant Point) is
      begin
         -- Compile Error: implicit conversion of anonymous access parameter not allowed
         Last_Printed := P;
    
         -- If we really, really want to do this, we can force it with a cast...
         Last_Printed := Point_Access (P);
         -- ... 
      end Print;
  • by JadeNB on 7/30/22, 11:58 PM

    I'm sure the name has been discussed endlessly already, but I was quite surprised to see a discussion of the exciting feature of a deprecated API! https://en.wikipedia.org/wiki/Carbon_(API)
  • by axegon_ on 7/30/22, 10:57 PM

    Dunno about the most exciting but the most irritating so far is seeing it up. Admittedly I didn't spent a lot of time trying(I didn't have all that much time today) but in the 40 minutes or so, I was unable to get it going. I'll go back to attempting tomorrow and make sense of the errors.
  • by mgaunard on 7/31/22, 5:20 AM

    Advantage #3 is false. C++ already does this.

    The standard explicitly states that a parameter taken by value and initialized from an prvalue of the same type may elide the move constructor (which all implementations do).

  • by lifeplusplus on 7/31/22, 12:51 AM

    It's fair to say carbon shouldn't be the starter language that people should be learning
  • by ArrayBoundCheck on 7/30/22, 9:11 PM

    Calling convention? That's the most exciting feature? It doesn't boost productivity, reduce compile times, offer a larger standard library or create a boost a reasonable language would provide?

    No thanks google. I've been saying that for years now. You jumped the shark

  • by booleandilemma on 7/30/22, 9:19 PM

    I get the impression this guy just wanted something to blog about.
  • by spullara on 7/30/22, 11:12 PM

    Just like Java?
  • by ISL on 7/30/22, 9:59 PM

    I'm sure the ship has sailed on Carbon's naming convention, but darn if that isn't a confusing article-title.

    It is interesting to contemplate the most-ambiguous and least-comprehensible/googleable name one might be able to give to a piece of software. "the"? "Biden"? "Russia"? "water"? "air"? "dog"? "person"? "!"? "?"? " "?

  • by glouwbug on 7/30/22, 10:31 PM

    Aren't we just reinventing the wheel over and over at this point? Sure could us another Go, C wasn't doing functions well at all /s
  • by NonNefarious on 7/30/22, 8:27 PM

    An old Apple UI kit has an "exciting" feature?