Erm it is perfectly possible to perform dynamic allocation in Ada. You have the 'new' keyword to allocate a new object of a type. You have the 'unchecked deallocation' mechanism. You have controlled types that deallocate when an object is out of scope. You have all sorts of weak references schemes in some libraries. You have storage pools to handle allocation specifics for a type. You have the secondary stack that handles returning objects of unknown-size-at-call-site.
Most of those can be disabled though through the 'restriction' mechanism (look up Pragma Restriction which is very interesting in itself).
SPARK itself can handle and prove some ownership properties but to the best of my knowledge isn't at the level of rust in memory safety on dynamically allocated memory.
> SPARK itself can handle and prove some ownership properties but to the best of my knowledge isn't at the level of rust in memory safety on dynamically allocated memory.
And using https://www.adacore.com/sparkpro as a reference (ignore the 'Pro' bit as it's also available in the GPL edition) - anything certified to SPARK Silver level is far safer than any Rust code out there.