Live data from Hacker News

Ask HN: A retrofitted C dialect?

news.ycombinator.com

21–30 of 81 posts

Re: Ask HN: A retrofitted C dialect?

#21

The problem with "safe pockets in ambient unsafety" is that C and C++ intentionally disallow this model. It doesn't matter what you do to enforce safety within the safe block, the definition of Undefined Behavior means that code elsewhere in your program can violate any guarantees you attempt to enforce. The only ways around this are with a language that doesn't transpile to C and doesn't have undefined behavior like…

Safe pockets in ambient unsafety does have benefits though. For example, some code has a higher likelihood of containing undefined behavior (code that manipulates pointers and offsets directly, parsing code, code that deals with complex lifetimes and interconnected graphs, etc), so converting just that code to safe code would have a high ROI.

And once you get to the point where a large chunk of code is in safe pockets, any bugs that smell of undefined behavior only require you to look at the code outside of the safe pockets, which hopefully decreases over time.

There are also studies that show that newly written code tends to have more undefined behavior due to its age, so writing new code in safe pockets has a lot of benefit there too.

Re: Ask HN: A retrofitted C dialect?

#22
post #8

There are approaches with at least partly the same goals as you mentioned, e.g. Zig. Personally I have been working on my own C replacement for some time which meets many of your points (see https://github.com/micron-language/specification ); but the syntax is derived from my Oberon+ language, not from C (even if I use C and C++ for decades, I don't think it's a good syntax); it has compile-time execution, inlines an…

> There are approaches e.g. Zig. Yes! Zig has done a great job on many C-related stuff, e.g. they've already made it possible to cross-compile C/C++ projects with Zig toolchain years ago. But I'm still quite stupidly obsessed with source-level compatibility with C, don't know if it's good, but things like "Zig uses `0xAA` on debugging undefined memory, not C's traditional `0xCC` byte" make me feel Zig is not "bare-bo…

> source-level compatibility with C

not sure if this is exactly what you meant, but in Zig you can #include a C header and then "just" invoke the function. no special FFI syntax or typecasting (except rich enums and strings). it can produce compatible ASTs for C and Zig.

Re: Ask HN: A retrofitted C dialect?

#23
In 2014 John Regehr and colleagues suggested what he called Friendly C[0], in an attempt to salvage C from UB. About bit more than a year later, he concluded that the project wasn't really feasible because people couldn't agree on the details of what Friendly C should be.[1]

In the second post, there's an interesting comment towards the end:

> Luckily there’s an easy away forward, which is to skip the step where we try to get consensus. Rather, an influential group such as the Android team could create a friendly C dialect and use it to build the C code (or at least the security-sensitive C code) in their project. My guess is that if they did a good job choosing the dialect, others would start to use it, and at some point it becomes important enough that the broader compiler community can start to help figure out how to better optimize Friendly C without breaking its guarantees, and maybe eventually the thing even gets standardized. There’s precedent for organizations providing friendly semantics; Microsoft, for example, provides stronger-than-specified semantics for volatile variables by default on platforms other than ARM.

I would argue that this has happened, but not quite in the way he expected. Google (and others) has chosen a way forward, but rather than somehow fixing C they have chosen Rust. And from what I see happening in the tech space, I think that trend is going to continue: love it or hate it, the future is most likely going to be Rust encroaching on C, with C increasinly being relegated to the "legacy" status like COBOL and Fortran. In the words of Ambassador Kosh: "The avalanche has already started. It is too late for the pebbles to vote."

0: https://blog.regehr.org/archives/1180 1: https://blog.regehr.org/archives/1287

Re: Ask HN: A retrofitted C dialect?

#26

I think you don't need any rants but here it goes anyway. Ditching headers does not solve anything at least if your language targets include performance or my beloved example Gamedev =) . You will have to consume headers until operating systems will not stop using them. It is a people problem not language problem. Big elephants in the room I do not see in your list: 1) "threading" was bolted onto languages like C and…

> Just want you to think that threading has to be natural in any language targeting multicore hardware.

parallel execution and thus parallel programming will never be natural to any human being. We don't do it, we can't think it except by using various cognitive props (diagrams, objects) to help us. You cannot make it natural no matter how strongly you desire it.

Now, there is a different sort of "natural" which might mean something more like "idiomatic to other language forms and patterns", and that's certainly a goal that can widely missed or closely approximated.

Re: Ask HN: A retrofitted C dialect?

#27
There are plenty of attempts at "safe C-like" languages that you can learn from:

C++ has smart pointers. I personally haven't worked with them, but you can probably get very close to "safe C" by mostly working in C++ with smart pointers. Perhaps there is a way to annotate the code (with a .editorconfig) to warn/error when using a straight pointer, except within a #pragma?

> Just talk to the platform, almost all the platforms speak C. Nothing like Rust's PAL (platform-agnostic layer) is needed. 2) Just talk to other languages, C is the lingua franca

C# / .Net tried to do that. Unfortunately, the memory model needed to enable garbage collection makes it far too opinionated to work in cases where straight C shines. (IE, it's not practical to write a kernel in C# / .Net.) The memory model is also so opinionated about how garbage collection should work that C# in WASM can't use the proposed generalized garbage collector for WASM.

Vala is a language that's inspired by C#, but transpiles to C. It uses the gobject system under the hood. (I guess gobjects are used in some linux GUIs, but I have little experience with it.) Gobjects, and thus Vala, are also opinionated about how automatic memory management should work, (In this case, they use reference counting.), but from what I remember it might be easier to drop into C in a Vala project.

Objective C is a decent object-oriented language, and IMO, nicer than C++. It allows you to call C directly without needing to write bindings; and you can even write straight C functions mixed in with Objective C. But, like C# and Vala, Objective C's memory model is also opinionated about how memory management should work. You might even be able to mix Swift and Objective C, and merely use Objective C as a way to turn C code into objects.

---

The thing is, if you were to try to retrofit a "safe C" inside of C, you have to be opinionated about how memory management should work. The value of C is that it has no opinions about how your memory management should work; this allows C to interoperate with other languages that allow access to pointers.

Re: Ask HN: A retrofitted C dialect?

#28

In 2014 John Regehr and colleagues suggested what he called Friendly C[0], in an attempt to salvage C from UB. About bit more than a year later, he concluded that the project wasn't really feasible because people couldn't agree on the details of what Friendly C should be.[1] In the second post, there's an interesting comment towards the end: > Luckily there’s an easy away forward, which is to skip the step where we t…

I think the problem with "friendly C", "safe C++" proposals is they come from a place of "I want to continue using what I know in C/C++ but get some of the safety benefits. I'm willing to trade some of the safety benefits for familiarity". The problem is the friendly C/safe C++ that people picture from that is on a spectrum. On one end you have people that really just want to keep writing C++98 or C99 and see this as basically a way to keep the network effects of C/C++ by having other people write C who wouldn't. The other extreme are people who are willingly to significantly rework their codebases to this hypothetical safe C.

The people on one end of this spectrum actually wouldn't accept any of the changes to meaningfully move the needle, while the people on the other end have already moved or are moving to Rust.

Then in the middle you have a large group of people but not one that agrees on which points of compatibility they will give up for which points of safety. If someone just said "Ok, here's the standard variant, deal with it", they might adopt it... but they wouldn't be the ones invested enough to make it and the people who would make it have already moved to other languages.

Re: Ask HN: A retrofitted C dialect?

#29
I'm a lot less experienced than you, but since you're collecting ideas, I'll give my opinion.

For me personally, the biggest improvements that could be made to C aren't about advanced type system stuff. They're things that are technically simple but backwards compatibility makes them difficult in practice. In order of importance:

1) Get rid of null-terminated strings; introduce native slice and buffer types. A slice would be basically struct { T *ptr, size_t count } and a buffer would be struct { T *ptr, size_t count, size_t capacity }, though with dedicated syntax to make them ergonomic - perhaps T ^slice and T @buffer. We'd also want buffer -> slice -> pointer decay, beginof/endof/countof/capacityof operators, and of course good handling of type qualifiers.

2) Get rid of errno in favor of consistent out-of-band error handling that would be used in the standard library and recommended for user code too. That would probably involve using the return value for a status code and writing the actual result via a pointer: int do_stuff(T *result, ...).

3) Get rid of the strict aliasing rule.

4) Get rid of various tiny sources of UB. For example, standardize realloc to be equivalent to free when called with a length of 0.

Metaprogramming-wise, my biggest wish would be for a way to enrich programs and libraries with custom compile-time checks, written in plain procedural code rather than some convoluted meta-language. These checks would be very useful for libraries that accept custom (non-printf) format strings, for example. An opt-in linear type system would be nice too.

Tool-wise, I wish there was something that could tell me definitively whether a particular run of my program executed any UB or not. The simpler types of UB, like null pointer dereferences and integer overflows, can be detected now, but I'd also like to know about any violations of aliasing and pointer provenance rules.

Re: Ask HN: A retrofitted C dialect?

#30
post #27

There are plenty of attempts at "safe C-like" languages that you can learn from: C++ has smart pointers. I personally haven't worked with them, but you can probably get very close to "safe C" by mostly working in C++ with smart pointers. Perhaps there is a way to annotate the code (with a .editorconfig) to warn/error when using a straight pointer, except within a #pragma? > Just talk to the platform, almost all the p…

It's less so opinionated and more so that WASM GC spec is just bad and too rudimentary to be anywhere near enough for more sophisticated GC implementations found in JVM and .NET.
Post reply on HN