# The state of Rust trying to catch up with Ada ---- ## whoami oli-obk a maintainer of the Rust compiler ---- ## what is this talk not about Rust evangelism Note: I'm sure Ada has places where it could learn from Rust you get enough of that from me whenever you talk to me. --- ## what it is about * unsafe/unchecked * generic packages/modules * safety certification * contracts * subtypes Note: on everything else I think there's little difference in *capabilites*, even if there are in various important aspects of the usability and error avoidance. ---- ### unchecked vs unsafe ```rust #[no_mangle] extern "C" fn malloc(_n: usize) -> *const u8 { std::ptr::dangling() } ``` Note: extern + no_mangle not needing unsafe until very recently allowed you to do unsound things without mentioning unsafe ---- ### generic packages/modules ``` error: expected one of `;` or `{`, found `<` --> src/lib.rs:1:8 | 1 | mod foo<T> {} | ^ expected one of `;` or `{` ``` Note: We have negative support for it, not even diagnostics know what you meant. ---- ### safety certification Ferrocene (https://ferrocene.dev) > [It’s official: Ferrocene is ISO 26262 and IEC 61508 qualified!](https://ferrous-systems.com/blog/officially-qualified-ferrocene/) Note: adacore internal drama upper leadership severed coop with ferrous core Ada folk quit (not just over this I think, but timings are curious) ---- ## contracts ```rust use core::contracts::*; #[requires(x.bar > 50)] #[ensures(|ret| *ret > 100)] fn foo(x: Bar) -> i32 { x.bar + 50 } ``` https://github.com/rust-lang/rust/pull/128045 Note: very recent impl, not stable, may get dedicated (non-attribute) syntax. SPARK contracts-in-comments became core lang feature a few years back --- ## pattern types/subtypes Note: finally we're getting to the real thing of this talk ---- ### state on stable Rust ```ada subtype Non_Zero is Integer range 1..Integer'Last; subtype Non_Null_Foo is not null Foo; ``` ```rust use std::num::NonZeroU32; type NonNullFoo = std::ptr::NonNull<Foo>; ``` Note: hardcoded types using compiler-internal magic ---- ### Tangent: strong vs weak type aliases | `type Foo = u32;` | `type Bar = u32;` | | ----------------- | ----------------- | | `let x: Foo = 1;` | `let x: Bar = 1;` | ![same_pic](https://hackmd.io/_uploads/H1UjkVqu1x.jpg) Note: There's not implicit type conversion or anything, they *are* the same type Rust uses the "newtype" pattern instead, giving you more control but less convenience ---- ### Patterns ```rust match foo { 1..100 => {} _ => {} } ``` ```ada case Foo is when 1 .. 100 => null; when others => null; end case; ``` ---- ```rust match bar { Dog | Cat | Bat => {} _ => {} } ``` ```ada case Bar is when Dog | Cat | Bat => null; when others => null; end case; ``` ---- ### Matching on two things simultaneously ```rust match (foo, bar) { (1..10, Dog | Cat) => {} (10..20, Dog | Cat | Bat) => {} (_, Bat) => {} _ => {} } ``` ---- ```ada subtype Non_Zero is Integer range 1..Integer'Last; subtype Non_Null is not null SomePointer; ``` ```rust type NonZeroU32 = u32 is 1..; // non-null is WIP type NonNull = *const Thing is !null; ``` ---- ### So what's the difference? * pattern types need explicit creation * instead of just being part of type conversion * pattern types do not do strong typing * `u32 is 1..` is always the same as any other `u32 is 1..` * pattern types only coerce, they don't relate ---- ### Creation ```rust let x: u32 is 1.. = 42; ``` ```ada subtype Non_Zero is Integer range 1..Integer'Last; X: Non_Zero := 42; ``` Note: not on nightly yet, but PRs are open ---- ```rust let a: u32 = 42; let x: u32 is 1.. = transmute(a); ``` ```ada subtype Non_Zero is Integer range 1..Integer'Last; A: Integer := 42; X: Non_Zero := A; ``` Note: we don't even allow you to go from `u8` to `u16` silently. so.. not happening ---- ### Future creation Without specifying the pattern again: ```rust type Grade = u32 is 1..=6; type Passing = u32 is 1..=5; let grade: Grade = read_from_somewhere(); if let Some(passing) = Passing::try_from(grade) { // yay } ``` Note: via automatically implemented traits ---- ### Patterns can be combined ```rust type SomePercent = Option<u32> is Some(0..=100); type Disjunctive = u32 is 0..=100 | 500..=1000; type Tuple = (u32, &str) is (0..=100, "cake" | "fruit"); ``` Note: not implemented yet "obvious" extension due to patterns allowing this in general --- ## Summary --- * TODO * generic modules * WIP * contracts * pattern types * idiomatic conversion from/to * caught up * safety certification * sound-by-default: `unsafe` opt-out Note: strong type aliases are probably not happening.
{"title":"The state of Rust trying to catch up with Ada","description":"extern/no_mangle not needing jnsafe","contributors":"[{\"id\":\"ce357653-6779-4c50-b873-5c2ef0815935\",\"add\":6158,\"del\":1290}]"}
    541 views