In Rule 3: struct Ship { int fuel; }; void print(Ship* ship) { cout Should that be "ship->fuel" instead?
Making C++ safe without borrow checking, reference counting, or tracing GC
151–160 of 226 posts
Re: Making C++ safe without borrow checking, reference counting, or tracing GC
#152Interesting pigeon reference.
Re: Making C++ safe without borrow checking, reference counting, or tracing GC
#153Earlier quoted context omitted.
I don't write Rust. But here is what you said and what the author said don't conflict with each other, and it has been on my mind for a while. People who write similar code, or work on things for decades usually don't really think through what "sketch out some code" looks like. They spend most of their time on refactoring things that has clear use-cases, but not well-defined API boundaries within the component, or be…
I really love parts of rust and kinda hate other parts. but this is what really ruins it for me. I want to play. I want to knock something together and work with it and see what kind of shape it is. rust demands that I cross every last t before I can run it at all. which is great if you already have a crystal notion of what you are building
As a Rust beginner, I find the principle that "if it compiles, it works" quite helpful for catching technical oversights.
Re: Making C++ safe without borrow checking, reference counting, or tracing GC
#154Methods such as these for C and C++ are interesting, and needed, but only solve a part of the problem. As others have noted before, they do little good because they're opt-in. I think there's a bit of nuance to that which needs to be explored though, as I think it's less a problem that the extra checks are opt in, and more a problem of how we use and categorize libraries. As long as we encourage dynamic and static li…
If the choice is a C library with 95% of the code in inline assembly, ... C is not providing any benefits in that situation, is it?
Re: Making C++ safe without borrow checking, reference counting, or tracing GC
#155> Borrow checking is incompatible with some useful patterns and optimizations (described later on), and its infectious constraints can have trouble coexisting with non-borrow-checked code. Not that this isn't true, but the rest of the article introduces a system with a superset of those limitations, gradually decreasing over time but never becoming a subset. In fact the pattern described in the article is a common pa…
> In fact the pattern described in the article is a common pattern in Rust and I make use of it all the time; the library for making use of it is `slotmap`. Slotmap uses unsafe everywhere, it's a memory usage pattern not supported by the borrow checker. It's basically hand-implementing use-after-free and double-free checks, which is what the borrow checker is supposed to do. Is that really a common pattern in Rust?
There is nothing inherent to the slotmap that requires unsafe code! It's only used for optimizations purposes.
Mine works in a similar way to the "standard" slotmap. It's a vec of slots, slot is an enum that can be occupied or vacant, the occupied variant is a two tuple containing the value and generation, vacant holds just a generation. Inserting into the slotmap simply switches the variant of the slot from vacant to occupied, and popping does the reverse. If there is no currently vacant slots, we just use the underlying push method on the vec of slots which will handle resizing for us! I also store a stack of indexes to vacant slots to make insertion fast.
When you insert into the slotmap, it provides a opaque key, but the data inside is an index and a generation. When you attempt to retrieve a value with a key, the slotmap checks if the slot is occupied and if the generation matches, and if so returns the value, otherwise returns none.
There is also a indirect slotmap, that adds an extra layer of indirection, so rather than the key being an index directly into the underlying vec of slots, its an index into a vec of indexes, this allows moving the slots around without invaliding currently living keys.
The indirect slotmap has the advantage of faster iteration, since it doesn't have to skip over empty "holes" of vacant slots in the vec of slots. The tradeoff is that insertion is slightly slower!
Anyways, no unsafe is required to implement a performant slotmap data structure! I have not uploaded my slotmap to crates.io because I didn't think anyone would find it useful, but maybe I should reconsider this!
Re: Making C++ safe without borrow checking, reference counting, or tracing GC
#156Earlier quoted context omitted.
> everything further out is playing with fire. That's the point. C and C++ don't prevent you from playing with that for. Memory-safe language do.
Rust only requires you to wrap it in unsafe. And I think C# allows you to do some pretty crazy stuff too.
[0] https://github.com/dotnet/aspnetcore/tree/1a56bdb671700ae698...
[1] https://github.com/dotnet/aspnetcore/blob/1a56bdb671700ae698...
Re: Making C++ safe without borrow checking, reference counting, or tracing GC
#157Earlier quoted context omitted.
> Slotmap uses unsafe everywhere, it's a memory usage pattern not supported by the borrow checker. Is disabling the borrow checker really a common pattern in Rust? Wrapping "unsafe" code in a safe interface is a common pattern in Rust, yes. There is absolutely nothing wrong with using "unsafe" so long as you are diligent about checking invariants, and keep it contained as much as possible. Obviously the standard libr…
> Obviously the standard library uses some "unsafe" as well, for instance. Most beautifully, MaybeUninit ::assume_init() -> T This unsafe Rust method says "I promise that I actually did initialize this MaybeUninit , so give me the T". In terms of the resulting program the machine is not going to do any work whatsoever, a MaybeUninit and a T are the same size, they're in the same place, your CPU doesn't care that this…
Re: Making C++ safe without borrow checking, reference counting, or tracing GC
#158Methods such as these for C and C++ are interesting, and needed, but only solve a part of the problem. As others have noted before, they do little good because they're opt-in. I think there's a bit of nuance to that which needs to be explored though, as I think it's less a problem that the extra checks are opt in, and more a problem of how we use and categorize libraries. As long as we encourage dynamic and static li…
> If the choice is a Rust library with 95% of the code in unsafe blocks, ... Rust is not providing any real safety benefits in that situation, is it? If the choice is a C library with 95% of the code in inline assembly, ... C is not providing any benefits in that situation, is it?
That's the whole point, it's less about the language, and more about the specifics of the code itself in a testable way. Saying something is written in C without accounting for a bunch of inline assembly is analogous to saying something is written in Rust and not accounting for a bunch of unsafe blocks. Not in that they are equivalently safe or unsafe, but that that high level assumptions because of the language fail because of the practices done within.
If I had to choose between two libraries written in C and one was pure C and one was 50% inlined assembly, and I viewed security and safety as more important for my use case, I know which one I would choose if that information was surfaced to me easily.
Re: Making C++ safe without borrow checking, reference counting, or tracing GC
#159Re: Making C++ safe without borrow checking, reference counting, or tracing GC
#160Earlier quoted context omitted.
> If the choice is a Rust library with 95% of the code in unsafe blocks, ... Rust is not providing any real safety benefits in that situation, is it? If the choice is a C library with 95% of the code in inline assembly, ... C is not providing any benefits in that situation, is it?
Exactly. Presumably there are some opt-in tools that are very strict about the inline assembly uses you have in C. I don't have any experience with them, but I'm sure they exist. That's the whole point, it's less about the language, and more about the specifics of the code itself in a testable way. Saying something is written in C without accounting for a bunch of inline assembly is analogous to saying something is w…