title options:
- A Memory Safety Enigma in the Mojo Standard Library
- Mojo's Dependent Types and Memory Safety
I was doing my normal thing in Mojo, implementing struct extensions, when I came across this function in the standard library:
| import Foundation | |
| class Engine { | |
| var fuel = 100 | |
| } | |
| class Spaceship { | |
| var engine = Engine() | |
| } | |
| func accelerate(_ ship: Spaceship) { | |
| let engine = ship.engine // Race: read | |
| // literally no field access |
| #include <memory> | |
| #include <thread> | |
| struct Engine { | |
| int fuel = 100; | |
| }; | |
| struct Spaceship { | |
| std::shared_ptr<Engine> engine = std::make_shared<Engine>(); | |
| }; | |
| void accelerate(std::shared_ptr<Spaceship> ship) { | |
| std::shared_ptr<Engine> engine = ship->engine; |
| struct Navigation: ~Copyable { | |
| var antenna: Bool | |
| } | |
| struct Engine: ~Copyable { | |
| var fuel: Int | |
| } | |
| enum Variant: ~Copyable { | |
| case navigation(Navigation) |
| # Article Skeleton | |
| title options: | |
| - A Memory Safety Enigma in the Mojo Standard Library | |
| - Mojo's Dependent Types and Memory Safety | |
| -------- | |
| I was doing my normal thing in Mojo, implementing struct extensions, when I came across this function in the standard library: |
| #!DeriveStructConstructor extern struct Vec<T> { | |
| extern func new() -> Vec<T>; | |
| extern func with_capacity(capacity: usize) -> Vec<T>; | |
| // Skipping (self) method try_with_capacity: Didn't contain whitelisted type | |
| // Skipping (self) method from_raw_parts: Encountered raw pointer type | |
| // Skipping (self) method new_in: Encountered defaulted rune | |
| // Skipping (self) method with_capacity_in: Encountered defaulted rune | |
| // Skipping (self) method try_with_capacity_in: Encountered defaulted rune | |
| // Skipping (self) method from_raw_parts_in: Encountered raw pointer type | |
| // Skipping (self) method into_raw_parts: Encountered raw pointer type |
| // Seamless C->Rust example: reversing a string | |
| // Import types. More advanced compilers with generics wouldn't need | |
| // to specify these generic args in theory, it would basically be a | |
| // vanilla java import. | |
| #pragma rsuse Str = &str | |
| #pragma rsuse String = std::string::String | |
| #pragma rsuse Chars = core::str::Chars<'static> | |
| #pragma rsuse RevChars = core::iter::Rev<Chars> | |
| // Import methods. More advanced compilers with generics won't need |
| // Seamless C->Rust example: reversing a string | |
| // Import types. More advanced compilers with generics wouldn't need | |
| // to specify these generic args in theory, it would basically be a | |
| // vanilla java import. | |
| #pragma rsuse Str = &str | |
| #pragma rsuse String = std::string::String | |
| #pragma rsuse Chars = core::str::Chars<'static> | |
| #pragma rsuse RevChars = core::iter::Rev<Chars> | |
| // Import methods. More advanced compilers with generics won't need |
| // Seamless C->Rust example: reversing a string | |
| // Import types. More advanced compilers with generics wouldn't need | |
| // to specify these generic args in theory, it would basically be a | |
| // vanilla java import. | |
| #pragma rsuse Str = &str | |
| #pragma rsuse String = std::string::String | |
| #pragma rsuse Chars = core::str::Chars<'static> | |
| #pragma rsuse RevChars = core::iter::Rev<Chars> | |
| // Import methods. More advanced compilers with generics won't need |