https://github.com/pstolarz/rust-playground
My Rust battlefield.
https://github.com/pstolarz/rust-playground
Last synced: 3 months ago
JSON representation
My Rust battlefield.
- Host: GitHub
- URL: https://github.com/pstolarz/rust-playground
- Owner: pstolarz
- Created: 2022-02-08T17:36:39.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2024-12-08T17:56:19.000Z (7 months ago)
- Last Synced: 2025-02-03T04:32:41.637Z (5 months ago)
- Language: Rust
- Homepage:
- Size: 76.2 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# My Rust battlefield
* Rust Operators and symbols
[[RPL]](https://doc.rust-lang.org/book/appendix-02-operators.html)
* _Type coercions_ - automatic type conversions in some specific cases.
[[REF]](https://doc.rust-lang.org/reference/type-coercions.html).
* _Deref coercions_ - automatic dereference and type conversion for `Deref` implementers.
[[RPL]](https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/deref-coercions.html).
* _Orphan rule_ (aka _Coherence_) - Implementation allowed in the same crate.
[[RPL]](https://doc.rust-lang.org/book/ch10-02-traits.html#implementing-a-trait-on-a-type).
* Rust undefined behaviour [[REF]](https://doc.rust-lang.org/reference/behavior-considered-undefined.html).* Unsized objects:
* slices (including `str`),
* Trait objects [[REF]](https://doc.rust-lang.org/reference/types/trait-object.html),
* `struct` with last object unsized.## Variable declaration
**let** [**ref**] [**mut**] _VAR_ [**:**_T_] [**=** _RHS_] **;**
where:
_T_ - specifies _RHS_ value type. If not specified _T_ is implied from _RHS_.
_T_: [**&mut**] [**&**] _T_
_T_: _non_ref_type_**ref**, **mut** defines _VAR_ as a reference and/or make it mutable.
```rust
// i type: i32
let i = 0;
// ri type: &i32
let ref ri = i;
// rri type: &&i32
let ref rri = ri;
// mi type: mutable i32
let mut mi = i;
// rmi type: &mut i32
let ref mut rmi = mi;
```Note, the most generic format of the variable(s) declaration is:
**let** _PATTERN_ = _RHS_ **;**
That means pattern matching may occur for the **let** statement, e.g.:
```rust
let mut mi = 0;
let ref mut rmi = mi;// pattern matching, i type: i32
let &mut i = rmi;
```## `Fn`, `FnMut`, `FnOnce`
* Function traits inheritance
`Fn`: possible to call multiple times for multiple copies,
`FnMut`: possible to call multiple times for a single copy,
`FnOnce`: possible to call once for a single copy.If an object may be called multiple times for multiple copies, it may be also
called multiple times for a single copy. Similarly, if an object may be called
multiple times for a single copy, it may be also called once for that copy.For that reason `Fn` is subtype of `FnMut` which is subtype of `FnOnce`.
* If function trait doesn't own accessed objects, it contains references to them
(mutable on non-mutable). The compiler elides the references lifetime. In some
cases it may be required to explicitly refer to the lifetime. Good example is
provided in `std::thread::scope`:```rust
pub fn scope<'env, F, T>(f: F) -> T
where
F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> T,
{
// We put the `ScopeData` into an `Arc` so that other threads can finish their
// `decrement_num_running_threads` even after this function returns.
let scope = Scope {
data: Arc::new(ScopeData {
num_running_threads: AtomicUsize::new(0),
main_thread: current(),
a_thread_panicked: AtomicBool::new(false),
}),
env: PhantomData,
scope: PhantomData,
};// Run `f`, but catch panics so we can make sure to wait for all the threads to join.
let result = catch_unwind(AssertUnwindSafe(|| f(&scope)));...
}
```Here `'env` denotes `f` environment lifetime (that is reference lifetime of
objects accessed by `f`).NOTES
* At first `scope` object is created without `'scope` and `'env` lifetimes
which are specified later on - once `f` is called and the actual lifetimes
are known (an object needs not to be fully specified until its first use,
that is, in this case, the `f` call).
* `F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> T` uses `'scope`
lifetime in _HRTB_ context, while `'env` is bound to `f` environment lifetime.## `Send`, `Sync`
* `Send`: unsafe auto trait marking a type `T` as safe to be sent between threads
(value move).
* `Sync`: unsafe auto trait marking a type `T` as safe to be shared between threads
(`&T` is therefore `Send`).See [[NOM]](https://doc.rust-lang.org/nomicon/send-and-sync.html) and
[[STD]](https://doc.rust-lang.org/std/marker/trait.Sync.html).```rust
#![feature(negative_impls)]struct S1;
struct S2;
struct S3;impl !Sync for S2{}
impl !Send for S3{}fn main() {
let s2: S2;std::thread::scope(|s| {
s.spawn(|| {
// OK: S1 is Send and may be safely sent between threads
return S1;
});
s.spawn(|| {
// OK: S2 is Send and may be safely sent between threads
return S2;
});
s.spawn(|| {
// ERROR: S2 is not Sync, therfore &S2 CAN'T be safely sent between threads
return &s2;
});
s.spawn(|| {
// ERROR: S3 is not Send, therfore CAN'T be safely sent between threads
return S3;
});
});
}
```## Lifetimes
* Notations
* `'b: 'a`: Lifetime `'b` must outlive lifetime `'a` (`'b` is a subtype
of `'a`). See _Lifetime bounds_ [[REF]](https://doc.rust-lang.org/reference/trait-bounds.html#lifetime-bounds).
* `T: 'a`: Generic type T must outlive lifetime `'a` (all references in T
must outlive `'a`). See _Implied bounds_ [[REF]](https://doc.rust-lang.org/reference/trait-bounds.html#implied-bounds).* _Lifetime elision_ - automatic lifetimes marking. [[REF]](https://doc.rust-lang.org/reference/lifetime-elision.html).
* `struct S` defined as: `struct S<'a, 'b, ...> { ... }` means: lifetimes `'a`,
`'b`, ..., associated with `struct S` must outlive `struct S` object lifetime:
`S: 'S_obj_lifetime````rust
struct S<'a>(Option<&'a S<'a>>);let s1 = S::<'_>(None);
{
// s2 references to s1 which outlives s2
let s2 = S::<'_>(Some(&s1));
}
```* While matching declared lifetimes with the actual object (for `struct`s or
function calls) they refer to, a compiler tries to find proper lifetimes
fulfilling the declaration, lifetime bounds etc.Some [example](src/lifetime.rs) illustrating lifetime bounds for legacy and
newer lifetime notation.The process of the substitution of actual lifetimes (e.g. in the process of
function call) with their identifiers is expressed by _Higher-ranked trait bounds_
(_HRTB_) [[NOM]](https://doc.rust-lang.org/nomicon/hrtb.html),
[[REF]](https://doc.rust-lang.org/reference/trait-bounds.html#higher-ranked-trait-bounds),
where "for all lifetimes" term is used to name the substitution.* _Subtyping and Variance_ [[NOM]](https://doc.rust-lang.org/nomicon/subtyping.html#subtyping), [[REF]](https://doc.rust-lang.org/reference/subtyping.html)
While passing reference to T in a function: `fn func<'a>(t: &'a mut T)`,
passing parameter must not outlive the function argument, which basically means
`T`, after the `func()` call, must not contain references with shorter lifetime that
object passed to the function to avoid dangling references.Good example illustrating the rule has been provided in [[NOM]](https://doc.rust-lang.org/nomicon/subtyping.html#variance).
```rust
fn assign(input: &mut T, val: T) {
*input = val;
}fn main() {
let mut hello: &'static str = "hello";
{
let world = String::from("world");
assign(&mut hello, &world);
}
println!("{hello}"); // use after free!
}
```Actual parameter to `assign()` has type `&'a mut &'static str`, while the
function argument type is `&'a mut &'a str`, where `'a` denotes `world`
lifetime. `'static` is a subtype of `'a` (longer lifetime), therefore after
returning from `assign()` `str` may be a dangling reference.NOTE: The above excerpt would compile fine in case mutability had been removed.
## Conversion diagrams
### `From`, `Into`
```
From
A ◄─────────────────────── B
Into (*)(*) Created automatically
```### `FromIterator`
```
FromIterator
A ◄─────────────────────── B
│ IntoIterator
│
│
│
│ Iterator
▼
I
```### `FromStr`
```
FromStr
A ◄──────────────────────── str
(Result)```