| > For example, you can specify a particular allocator for individual types rather than relying on each allocation to use the custom allocator. Having a 1-to-1 correspondence between types and allocators screams of lack of separation of concerns. In any case... > If you're outside the realm of the Rust borrow checker and want to use an arena to keep the memory side of things simple and safe, it's much easier to do properly in Ada. Arenas can be given safe interfaces in Rust just fine: https://crates.io/search?q=arena > memory safety facilities The article literally says: “Tasks are awesome, but sometimes they're not quite what you want --- particularly as there's no protection against two tasks modifying the same variable at the same time.” So much for memory safety. > bounds checking Implementable as a library feature. For example, in Standard ML: signature BOUNDS =
sig
val minBound : int
val maxBound : int
end
(* INTEGER and Overflow are in the Basis Library *)
functor BoundsChecked (include BOUNDS) :> INTEGER =
struct
type int = int
fun toInt x = x
fun fromInt x =
if x < minBound orelse x > maxBound
then raise Overflow else x
val op+ = fromInt o op+
val op- = fromInt o op-
val op* = fromInt o op*
(* rest of implementation... *)
end
There is no need to bloat the core language.> non-nullable pointer types In an unusable way. > generics Parametric polymorphism buys you non-repetition, not safety. > contracts Contracts don't buy you safety. Your code will just crash at more predictable places when a contract assertion fails. But it will still crash. Hard. Static analysis buys you safety. |
It's a 1-to-1 correspondence between an access type (aka pointer) and an allocator. There isn't an issue with separation of concerns.
> Arenas can be given safe interfaces in Rust just fine
I never said they couldn't. I said, they require the arena allocator to be used explicitly for each and every allocation. So if you screw that up, it's a problem.
> The article literally says: “Tasks are awesome, but sometimes they're not quite what you want --- particularly as there's no protection against two tasks modifying the same variable at the same time.”
And if you bothered to read another few sentences, you would see the article mention controlled types. These are types that exist to be task-safe. It's entirely safe.
> <bounds checking> Implementable as a library feature.
Which makes it more difficult or impossible (depending on other language features) to detect such errors at compile time. It's also much harder or impossible to optimize away the checks when possible. And finally being a separate library means it's not part of the core language. You might call that bloat, I call it good design that not only requires safety but fosters an environment that encourages safety. You can have all the best most safe features in the world, but if they are hidden off in a library then programmers must explicitly reach for them and by default start off playing around in unsafe ways. It becomes a cultural thing.
> (non-nullable pointer types)In an unusable way.
What? Care to expand? I've used them before, so they are usable in some sense at least...
> Parametric polymorphism buys you non-repetition, not safety.
Non-repetition buys you a single place to screw up, rather than many.
> Contracts don't buy you safety. Your code will just crash at more predictable places when a contract assertion fails. But it will still crash. Hard. Static analysis buys you safety.
Where possible Ada contracts are checked statically. Contracts that are checked at run-time do buy you safety too, though. Not in a given build, but unless you are in the habit of shipping as soon as you get a successful compile, having crashes occur as soon as there is a problem is a wonderful way of being able to quickly identify not only that a problem exists, but what the problem is. In terms of actual software development, it very much helps with producing correct software.