You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Pete asked me to think about some common pitfalls/traps in the language, so here is a small list of things I was able to think of so far that we likely want to talk about in some capacity.
Offsetting raw pointer to zero sized type. It is common to do raw pointer type erasure in Rust by erasing to *const/mut () (mimicking C's void ptr pattern), but what people tend to then run into is that the offset function will become useless as it then increments in size of () which is 0.
Temporaries, drop order and destructors. Knowing when Rust allocates temporaries and in what order values (and temporaries) are being dropped can be overwhelming. This coupled with destructors running code implicitly can quickly turn into unexpected behavior.
as _ pointer casts. It is possible to use as _ (as well as using ptr::cast without supplying an explicit type argument) to cast between different raw pointer types. This should be considered an anti-pattern as these casts will happily accept surrounding types changing even if the cast itself becomes invalid in a sense. (transmute without supplying the two type arguments suffers a similar problem)
_ patterns do not constitute a read. This pattern is a frequent source of confusion for Rust devs as it is a complete no-op.
let s = String::new();let _ = s;// this does not do anything, it does not move the string and so it also does not drop the string here.let s2 = s;// this does move the string, but it does not drop it yet. `s` is now now longer usablelet _ = { s2 };// this does move the string, it also immediately drops it after as the return value of the block is not bound to a local// Notably that also means the following here is not undefined behavior, we dereference the null pointer to a place, but we do not end up reading from it and as such, this entire statement is a no-opunsafe{let _ = *std::ptr::null::<String>();};
Panicking while panicking leads to an abort. This is only really relevant for targets where unwinding occurs, given abort is otherwise the default. This is relevant only for two things, destructors and the panic hook. The only way to run into a double panic is by either panicking in a Drop implementation while the stack is currently unwinding from another panic or by panicking within the panic handler. Care must be taken to avoid this if aborting the program is of a significiant problem.
The text was updated successfully, but these errors were encountered:
Pete asked me to think about some common pitfalls/traps in the language, so here is a small list of things I was able to think of so far that we likely want to talk about in some capacity.
*const/mut ()
(mimicking C's void ptr pattern), but what people tend to then run into is that theoffset
function will become useless as it then increments in size of()
which is 0.as _
pointer casts. It is possible to useas _
(as well as usingptr::cast
without supplying an explicit type argument) to cast between different raw pointer types. This should be considered an anti-pattern as these casts will happily accept surrounding types changing even if the cast itself becomes invalid in a sense. (transmute
without supplying the two type arguments suffers a similar problem)_
patterns do not constitute a read. This pattern is a frequent source of confusion for Rust devs as it is a complete no-op.Drop
implementation while the stack is currently unwinding from another panic or by panicking within the panic handler. Care must be taken to avoid this if aborting the program is of a significiant problem.The text was updated successfully, but these errors were encountered: