Rust Log for December Adventure of reviewing and studying Rust concepts.

12.19

12.20

12.21

12.22

12.23

In Rust, a lifetime is always tied to a reference (&). Lifetimes are a way to specify how long a reference is valid, and they are not relevant for non-reference types like i32, String, or Vec.

static is stored in its own place in memory, that is not the heap or the stack, and has a lifetime for the entire duration of the program. Sometimes referred to as “leaked heap value”.

12.25

12.27

A variable’s lifetime is how long the data it points to can be statically verified by the compiler to be valid at its current memory address.

Well yes, but a type with a ‘static lifetime is different from a type bounded by a ‘static lifetime. The latter can be dynamically allocated at run-time, can be safely and freely mutated, can be dropped, and can live for arbitrary durations.

T: ‘static includes all &‘static T however it also includes all owned types, like String, Vec, etc. The owner of some data is guaranteed that data will never get invalidated as long as the owner holds onto it, therefore the owner can safely hold onto the data indefinitely long, including up until the end of the program

from https://github.com/pretzelhammer/rust-blog/blob/master/posts/learning-rust-in-2024.md

https://users.rust-lang.org/t/dining-philosophers-sync-vs-async/123152

also looked at this comparison of different async models https://users.rust-lang.org/t/all-concurrency-models-comparision-help/34886/3

The type F’s variance is how the subtyping of its inputs affects the subtyping of its outputs. There are three kinds of variance in Rust. Given two types Sub and Super, where Sub is a subtype of Super:

F is covariant if F<Sub> is a subtype of F<Super> (the subtype property is passed through)
F is contravariant if F<Super> is a subtype of F<Sub> (the subtype property is "inverted")
F is invariant otherwise (no subtyping relationship exists)

12.28

if ‘a contains ‘b then ‘a is a subtype of ‘b – the bigger scope is a subtype of the smaller scope

Variance is a property that type constructors have with respect to their arguments.

A type constructor in Rust is a generic type with unbound arguments

For instance Vec is a type constructor that takes a T and returns a Vec

& and &mut are type constructors that take two inputs: a lifetime, and a type to point to.

A type constructor’s variance is how the subtyping of its inputs affects the subtyping of its outputs.

‘static is a subtype of any ‘a

https://users.rust-lang.org/t/is-a-foo-a-a-footgun/122766/27?u=notplants

fn item for<'a> fn(&'a (dyn Animal + 'a)) {foo} https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3188a7dba84d1c185cbf3ba876d84c7b

12.29

1.1

  • Vec puts its contents on the heap, while &[T] may be on the stack. from https://users.rust-lang.org/t/why-do-some-people-confound-t-with-stack-memory/123336

  • more explanation of async and Future The compiler translates the async fn into a function returning impl Future<Output = T>, where T is the return type of the async block.

  • studied support for recursion in async fn https://blog.rust-lang.org/2024/03/21/Rust-1.77.0.html#support-for-recursion-in-async-fn

  • studied compiler parallelism strategies. e.g. being able to compile a caller in parallel with its callee. using creates as the codegen limit. and other nuances. like a function exporting its metadata, that can be used by compilation by callers, before the function itself has been compiled. but also apparently sometimes the compiler does need to “look-ahead” into a function to some degree to figure out the type returned (unlike C). to see which variant of Future state machine it returns … although my understanding here is still a bit vague cargo build --timings can help visualized the dependency graph of compilation … so beautiful !

  • functions are contravariant but not function pointers While the type system variance rules might suggest this should work (because fn(T) -> U is contravariant with respect to T), Rust’s function pointers are invariant. This is because:

A function pointer fn(&T) must match exactly; Rust does not allow substituting one with another even if variance rules are satisfied. broken example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=68ec583c9aa22a3790f00af7280f8761 working example is still neede