Rust Trivia
What are the 3 types used to represent a sequence of values, and what are their generic type annotations?
- Array
[T; N]- Vector
Vec<T>- Slice
&[T]
How do you check the current size and capacity of any sequential-type value?
.len()and.capacity()
What makes a
Stringand a&strunique? What are their effective underlying types?
- A
Stringis just aVec<u8>with the guarantee that the data is well-formed UTF-8.- A
&stris just a slice&[u8]of aString.
Given
let x = y;, under what condition would it be true thatydid not become uninitialized?
If the type of
yimplements theCopytrait.
Given
let s = "hello!";, what is the type ofs?
sis a&strwhose pointer refers to preallocated, read-only memory on the stack.
How do you get the size of any data type?
std::mem::size_of::<T>();
What's a fat pointer?
A fat pointer is a pointer to a slice (a region of an array or vector). It's a two-word value on the stack comprised of:
- A pointer to the slice's first element
- The number of elements in the slice
What's the difference between
ArcandRctypes?
Arc(atomic reference count) is safe to share between threads directly, whereas aRcuses faster non-thread-safe code to update its reference count.
When defining a type (
struct), when is it required that a field's lifetime be specified?
Lifetimes must be specified when a field is a reference type. e.g.
struct RefPoint<'a, 'b> { x: &'a f64, y: &'b f64, }
What risk is sometimes posed by using reference count types?
If two
Rctypes point to each other, they will keep each other's ref count above zero and neither will be freed. This is called a reference cycle.
Given two reference variables
xandy, how do I check to see if they point to the same value in memory?
std::ptr::eq(x, y)
What are the two ways for closures to get data from enclosing scopes?
- Moves
- Borrowing
What are the three variants of
IntoIteratorimplementations?
- Shared reference
- Mutable reference
- By value
When should you use either
PathorOsStr?
For absolute and relative paths, use
Path. For an individual component of a path, useOsStr.
How are
boolvalues stored in memory, and why?
boolvalues are stored as a whole byte so that pointers to them may be created.
What mechanism should you reach for to allow for shared ownership of a value?
Rc<T>orArc<T>(if sharing across multiple threads)
What mechanism allows us to mutate the value inside of an
Rc<T>? What about anArc<T>?
For an
Rc<T>, interior mutability can be facilitated by aRefCell<T>. For anArc<T>, you'd reach for aMutex<T>.
What special ability does a
Pin'd object have?
Pinned (i.e. immovable) objects can have pointers to their own fields. e.g.
#![allow(unused)] fn main() { struct MyFuture { a: i32, ptr_to_a: *const i32, // I point to my own `a` } }
When would you use
ArcWake(from thefuturescrate) trait?
Use
ArcWakewhen you need an easy way to construct aWaker.
What is the actual return type of this function?
#![allow(unused)] fn main() { async fn get_five() -> u8 { 5 } }
Returns value of type
impl Future<Output = u8>.
How is an
asyncfunction in terms of lifetimes if one of its arguments is a > reference or non-'staticvalue?
Unlike regular functions,
asyncfunctions whose parameters are references or non-'static return aFuturewhich is bounded by the lifetime of the arguments. Meaning, the future returned from anasync fnmust be.awaited while its non-'static arguments are still valid.
What's the workaround for
asyncfunctions' non-static lifetime rules?
An
asyncfunction'sFuturereturn value can be make'staticby moving the non-static (or reference) values into anasyncblock:#![allow(unused)] fn main() { fn work_around() -> impl Future<Output = u8> { async { let x = 5; borrow_x(&x).await } } }
What's the formal fancy term to describe Rust's form of polymorphism?
What's the pattern used as a way to get around the orphan rule?
The newtype pattern, which involves creating a new type in a tuple struct.
I've implemented a newtype,
Wrapper, that wraps aVec<T>, but now I can't use theVec<T>'s built-in methods! What can I do?
Implement the
Dereftrait forWrapper, which would allow us to treatWrapperexactly like a Vec.
Something about how passing by value cedes all ownership of a value. Use
dropas point of reference.
How do I write an
impl Tfunction that consumesT(it will no longer be usable by others) and converts it toU?
In the function's signature, you'd have
selfbased by value, which will consume it. (usually, impl functions receive&self)
How do I get the address of a value (say, a
String)?
#![allow(unused)] fn main() { let txt = String::from("hello world"); let txt_stack = &txt as *const _; // Address of pointer on the stack let txt_heap = &txt.as_bytes()[0] as *const _; // Address of first charcacter in heap dbg!((txt_stack, txt_heap)); }
TODO: Go here and add stuff about the use of phantom/types/data