If Ada is already *very* safe, why Rust?


#1

Hello,
I’ve been playing around with Rust for the past 2 weeks or so - so far, it’s a quite nice language. However, the main selling points of Rust is:

  1. it’s a systems programming language
  2. it’s “blazingly fast”
  3. it’s safe
  4. it’s good with concurrency

Not to say that Rust is bad or unnecessary (as I said, it accomplishes it’s goals quite well, except for the fact that the tooling is intolerably slow), but doesn’t Ada have similar features? Ada is also very safe - it’s made for defense and safety critical systems, after all! Ada can also get low level, and has concurrency built in. It’s also quite fast. So what makes Rust better than Ada? Is it because Ada’s too verbose? Not fast enough? Syntax issues?


How does Rust compare with Ada (and Spark)?
#2

Rust has compile-time checked pointers.

Ada developers either use a garbage collector, or they avoid freeing memory entirely and design the whole application as a finite state machine (both of which are possible in Rust, too, but the point is you don’t have to).

Of course, Ada has range-checked arithmetic, which Rust doesn’t have (it needs const generics first before that can be done in a library), so if you’re more worried about arithmetic errors than dangling pointers, then you might prefer Ada.


#3

I probably wouldn’t think of in terms of language A is better/worse than language B, instead I’d look at the problems each language is trying to solve and see which is better suited to a particular application.

I know Rust is a more functional language, while Ada leans towards procedural/OO. Both paradigms are perfectly legitimate and the languages are flexible enough that you aren’t locked into doing things in just one way, although there will probably be use cases when it’s easier to express something in one language than the other. Ada also has a long history of use in critical places like the military and embedded space, while Rust is still pretty young and won’t have had as much time to gain confidence in it.

The library, tooling, and package management stories for Rust are second to none though. cargo and crates.io are awesome when you want to do something but don’t want to reinvent the wheel, and the community itself is thriving and quite helpful. Of course, if you’re wanting to make a safety-critical system you’d want to verify every line of code that goes into your program. I’m not sure if/how that would affect your language choice though.


#4

That would suggest to me that neither Ada nor Rust are acceptable and that you want to verify the program in a theorem prover / language such as Idris / Agda / Coq / F* / Lean where you can prove that execution will not diverge and where you can prove arbitrarily complex properties (unless what you need requires turing completeness…).


#5

if only Ada would have ever had Rust’s community! I come from a Pascal background originally and wouldn’t have minded that.

But the lack of popularity of Ada—at least in open source development—makes that bindings are usually badly maintained. Unless you’re working on something that is entirely built from scratch that’s going to give you a lot more work.


#6

In a recent post of mine I’ve shown that you probably can’t implement those well in library code even if you have good const generics.

I am in the Rust community because I like Rust much more than Ada language.


#7

Still need const generics to implement traits over range numeric types, for the same reason why fixed-size arrays aren’t very good in current Rust.


#8

… Ada developers either use a garbage collector, or they avoid freeing memory entirely …

  1. I have not seen a single project using a GC (Ada has no GC but can be augmented with one) : https://github.com/ohenley/awesome-ada
  2. You can free memory if you need to: https://en.wikibooks.org/wiki/Ada_Programming/Types/access#Deleting_objects_from_a_storage_pool

#9

Which safety-critical system is using Ada: https://www2.seas.gwu.edu/~mfeldman/ada-project-summary.html

… verify the program in a theorem prover … here we go

SPARK is a formally defined computer programming language based on the Ada programming language, intended for the development of high integrity software used in systems where predictable and highly reliable operation is essential. It facilitates the development of applications that demand safety, security, or business integrity.


#10

Two posts on Ada SPARK <–> Rust worth considering:

Safe Pointers in SPARK Ada, inspired by Rust’s borrowed references

Why Rust was the best thing that could have happened to Ada


#11

One of the first things I tried to find out about Ada is how it manages dynamic resources. What I found out is:

  1. Optional GC, on which no one can depend reliably due to its optionality
  2. Manual new/Unchecked_Deallocation
  3. RAII pointers either don’t exist or are buried deep in manuals
  4. Finally, pointers (“access types”) are nullable by default.

How can Ada be called safe language then??? Even dreaded C++ does the job better. Not to mention Haskell and friends which make as many invalid states as possible simply inexpressible.


#12

[mod note: Specific comparison of Rust/Ada trade-offs is fine, but general critique of Ada is off topic here.]


#14

if only Ada would have ever had Rust’s community! I come from a Pascal background originally and wouldn’t have minded that.

Well… Ada has a very active community, one of my preferred channels is a google group
https://groups.google.com/forum/#!forum/comp.lang.ada
Take a look if you are curious about it, and welcome.

One thing I would point out, is that, according to https://blog.rust-lang.org/2018/11/27/Rust-survey-2018.html, Rust has only 9.6% of users with experience longer than 3 years. In Ada community it’s quite common to find people with far 20 years, some even with 30 yeas of experiencie, still active. I might say my 12 Ada years would put me in a baby chair. A high number of new people is sure awesome, but a good number of more experienced people tells a lot about the maturity of the community and helps a lot in the more complex discussions.

But the lack of popularity of Ada—at least in open source development—makes that bindings are usually badly maintained. Unless you’re working on something that is entirely built from scratch that’s going to give you a lot more work.

I would not say so. Ada is very popular among military systems, and it’s been widely used in tons of critical systems. For open source projects you could say it is not as popular as Rust, but it is changing. Still there are some initiatives to turn more popular for these projects, eg, the hackster Make with Ada contest

Also, according to TIOBE index, Ada is almost as popular in use as Rust, in the 36th position where Rust is in 35th, with the same score.
https://www.tiobe.com/tiobe-index/

Besides formal work, I personally have also used Ada even for my private and public projects. No problem with other languages, but Ada’s way for me is very intuitive (for the type of project I like to do for myself), so I just have to think in the system as the language flows. Bindings are also quite easy, when I don’t want to implement from scratch, no problem in using a C/C++ code.


#15

Link?


#16

It doesn’t have to be better or worse. For safety critical applications Ada is much mature language and I’m not sure Rust will support Ada Spark’s code contract and verifying software with specs features (although I do like to see it in Rust too).

For me personally I can say:

  1. Syntax. I prefered if Ada/Spark was based on C syntax.

    Rust is closer to C syntax and much less verbose.

  2. Ada/Spark does not have ownership rules and borrow checker build into the compiler like Rust (already mentioned earlier). I think they are adding this to Ada/Spark 2020.

  3. It is GPL license for community edition. If you want to keep your code closed, you have to buy commercial license which is very expensive for small developer.

    Rust is free but I don’t mind paying in the range of Visual Studio Professional for Rust and pro tools if it had.

Not true.

Not Ada/Spark limitation. It is guideline/requirement for developing avionics software. Developers using C language have to follow this for avionics software too.

In my opinion, choices between languages are complicated for each developer and even with very similar features a developer might use one language over the other.


#17

Ada and Rust had different, but overlapping, goals. They are each a product of the best computer language knowledge and compiler technology of their times. Both languages continue to evolve, to some extent even cross-fertilizing each other.

I was a minor participant in the original design of Honeywell’s Green submission, which became Ada, so I have some knowledge whereof I speak.

Edit: To cause the link to navigate to the appropriate credits paragraph.


#18

Just a minor correction here. There is a free commercial friendly Ada compiler as well. The FSF version of GNAT provides an exception to the standard GPL allowing you to link to any of the runtime files without having that make your code or binary fall under the GPL. Alternately if you feel froggy (and are more experienced), you can also create your own runtime under your own license and still use the community edition. It’s the runtime that makes a difference. The FSF version, however, is free and pretty easy to get for the majority of the platforms that support GCC (Windows, Linux, Mac, etc.).


#19

They have GNAT Pro Developer license for 3 or less developers which some articles say is reasonable for small developers but it doesn’t publish the price. They should advertise the price, it may get more people interested.


#20

You’ve got to love it when people who nothing about Ada like to tell other people, who know nothing about Ada, things about Ada that they probably heard from someone else, who knew nothing about Ada.

Ada has a new and it has a “free” but free is considered unsafe and is a generic function called Unchecked_Deallocation, because it’s unchecked by the compiler.

You would generally wrap your memory allocations within a package inside the private parts either in functions to call from outside the package or using a controlled type, which is a tagged type (or class in other languages) which have Initialize, Adjust and Finalize functions defined which you need to override. Handle your free within Finalize and you essentially have RAII (in other languages). Object goes out of scope and Finalize is called.

Also, there are provisions within the RM which states that when an access type (pointer type) goes out of scope, i.e. from a block, the block master can automatically delete that memory for you. This thread goes into more detail (I cannot put the link in):

Specify the 'Storage_Size associated with the access-type.
The implementation is required to reclaim the storage for the
access type when exiting its scope if a 'Storage_Size is specified
(see RM95 13.11(18)).

One of Ada’s best features are ranges, along with array indices:

type Celcius is range -100 .. 100;

type Celcius_Arrays is array (Ceclius'Range) of Integer; -- Example.
...
C : Celcius_Arrays := <some_initialiser>;
...
for C in C'Range loop - Yes, an array from -100 -> 100
  -- Do something
end loop;

[As I cannot post another reply…]

There are no compilers ever written for Ada which implemented the provision for GC.

Not quite true, see my previous post.

type A is access T; – Can point to local types.
type B is access all T; – Can point to types on the heap and locally.
type C is not null access T; – Exclude nulls.
type D is access constant T; – Can only point to constants.
type D is not null access constant T; – Can only point to constants and not null.

Then there are access to (protected) functions/procedures, etc.

It’s a hell of a lot safer than a lot of other languages out there including C++, which doesn’t do the job better.


#21

Remember, Ada was created to replace the thousands of languages already in use at the DoD, so was intended as a general purpose programming language.

[As I cannot post another reply]

Ada 202x has parallel blocks for fine grained concurrency:

parallel for I in A'Range loop
end loop;

-- and

parallel begin
   -- Statrements ex execute in parallel with
and 
   -- These statements
and 
   -- These statements
and 
   -- These statements
ane
   -- etc.
end;