> It makes it a lot less performant and there is no avoiding or mitigating that downside.
You can’t possibly know that.
> C++ is often selected as a language instead of safer options for its unusual performance characteristics even among systems languages in practice.
Is that why sudo, bash, coreutils, and ssh are written in C?
Of course not.
C and C++ are often chosen because they make systems programming possible at all due to their direct access to syscall ABI.
> Fil-C is not a replacement for C++ generally, that oversells it.
I have made no such claim.
Fil-C means you cannot claim - as TFA claims - that it’s impossible to make C and C++ safe. You have to now hedge that claim with additional caveats about performance. And even then you’re on thin ice since the top perf problems in Fil-C are due to immaturity of its implementation (like the fact that linking is hella cheesy and the ABI is even cheesier).
> It might be a replacement for some C++ software without stringent performance requirements or a rigorously performance-engineered architecture. There is a lot of this software, often legacy.
It’s the opposite in my experience. For example, xzutils and simdutf have super lower overhead in Fil-C. In the case of SIMD code it’s because using SIMD amortizes Fil-C’s overheads.
> C and C++ are often chosen because they make systems programming possible at all due to their direct access to syscall ABI.
Surely Fil-C cannot provide direct access to syscalls without violating the safety guarantee. There must be something ensuring that what the kernel interprets as a pointer is actually a valid pointer.
> Fil-C means you cannot claim - as TFA claims - that it’s impossible to make C and C++ safe. You have to now hedge that claim with additional caveats about performance. And even then you’re on thin ice since the top perf problems in Fil-C are due to immaturity of its implementation (like the fact that linking is hella cheesy and the ABI is even cheesier).
The world of compilers is littered with corpses of projects that spent years claiming faster performance was right around the corner.
I believe you can make it faster, but how much faster? We'll see.
I think these types of compatibility layers will be a great option moving forward for legacy software. But I have a hard time seeing the case for using Fil-C for new code: all the known disadvantages of C and C++, now combined with performance closer to Java than Rust (if not worse), and high difficulty interoperating with other native code (normally C and C++'s strength!), in exchange for marginal safety improvements over Rust (minus Rust's more general safety culture).
edit: I feel bad writing such a dismissive comment, but it's hard to avoid reacting that way when I see unrealistically rosy portrayals of projects.
> Surely Fil-C cannot provide direct access to syscalls without violating the safety guarantee. There must be something ensuring that what the kernel interprets as a pointer is actually a valid pointer.
This is exactly what Fil-C does.
> all the known disadvantages of C and C++
The main disadvantage of C and C++ is unsafety and fil-C comprehensively fixes that.
> edit: I feel bad writing such a dismissive comment, but it's hard to avoid reacting that way when I see unrealistically rosy portrayals of projects.
How is my portrayal unrealistically rosy?
Even the fact that you know what the current perf costs are is the result of me being brutally honest about its perf.
Okay, I just checked. It does not. I wrote: "There must be something ensuring that what the kernel interprets as a pointer is actually a valid pointer." And sure enough, your runtime manually wraps each Linux syscall to do exactly that:
ioctl is even harder because some ioctls take pointers to structs that themselves contain pointers; on Linux that includes v4l2 and mmc. It looks like you don't handle that properly, judging by:
My point is: having to go through wrapper functions is not what I'd call "direct" access to "ABI". (Also, the wrappers don’t even wrap the syscall ABI directly; they wrap the libc ABI that in turn wraps syscalls.)
You might object that the wrappers are thin enough that they still count as direct. While that's a matter of definitions, I think my previous comment made it clear what _I_ meant when I questioned "direct", given my followup sentence about "actually a valid pointer".
But beyond quibbles about who meant what, this lack of directness matters because it implicates the portability of your approach.
At least as currently implemented, you rely on compiling almost everything (even libc) inside the sandbox, while having a ‘narrow waist’ of syscall wrappers mediating access between the sandbox and the outside world. That should work for most use cases on Linux, where there's already an assumption that different processes can have completely different library stacks, and static linking is common. Even if you want to do a GUI application you should be able to recompile the entire GTK or Qt stack inside the sandbox, and it doesn’t matter if other apps are using different versions or GTK or Qt.
But what about other operating systems? For server and CLI software you can probably still get away with exposing a small syscall/libc API, similar to Cosmopolitan (though that will still require significant effort for each OS). But for GUIs and platform integration more broadly, you’re expected to use the platform-provided libraries that live in your address space. They are usually proprietary, and even when they’re not, the system isn’t designed for multiple versions of the libraries to coexist.
I know I’m not telling you anything you don’t already know. But it’s an important point, because aside from performance, the _other_ big reason that Rust relies on user-written unsafe code is for FFI. If anyone can write their own FFI bindings, as opposed to making all FFI bindings live in a centralized runtime, then it becomes more feasible to scale the mammoth task of writing safe wrappers for all those ABIs. Your approach explicitly rejects user-written unsafe code, so I don’t know how you can possibly end up with reasonable OS library coverage.
Now sure, you didn’t claim anything about GUIs or portability. Perhaps this is more on topic for my previous comment’s point about “high difficulty interoperating with other native code” which you didn’t rebut. But it’s also relevant to “direct access to syscall ABI”, because if there _were_ some way to provide direct access to syscall ABI while remaining memory-safe, then the same approach would probably extend to other system ABIs. For example, a fully CHERI-aware system actually would allow for that. It’s an unfair comparison, because CHERI assumes cooperation from both the hardware and the OS, while you’re trying to run on existing hardware and OSes. I have no idea if we’ll ever see CHERI in general purpose systems. But in exchange, CHERI achieves something that’s otherwise impossible: combining direct system access and memory safety. And I originally read your comment as claiming to do the impossible.
It’s true that the Fil-C approach focuses on having a memory safe userland with no exceptions, which means no FFI to unsafe code (aside from the Fil-C runtime itself, which is just syscalls wrappers and a small handful of other things).
I have considered what FFI to native could look like, and have so far rejected it because it hurts the “no unsafe code” purism.
You’re right that this limits me to those OSes where the syscalls themselves are an adequate ABI. Linux isn’t the only such OS. It just happens to be the only OS Fil-C supports right now.
You can’t possibly know that.
> C++ is often selected as a language instead of safer options for its unusual performance characteristics even among systems languages in practice.
Is that why sudo, bash, coreutils, and ssh are written in C?
Of course not.
C and C++ are often chosen because they make systems programming possible at all due to their direct access to syscall ABI.
> Fil-C is not a replacement for C++ generally, that oversells it.
I have made no such claim.
Fil-C means you cannot claim - as TFA claims - that it’s impossible to make C and C++ safe. You have to now hedge that claim with additional caveats about performance. And even then you’re on thin ice since the top perf problems in Fil-C are due to immaturity of its implementation (like the fact that linking is hella cheesy and the ABI is even cheesier).
> It might be a replacement for some C++ software without stringent performance requirements or a rigorously performance-engineered architecture. There is a lot of this software, often legacy.
It’s the opposite in my experience. For example, xzutils and simdutf have super lower overhead in Fil-C. In the case of SIMD code it’s because using SIMD amortizes Fil-C’s overheads.