Skip to content

Potential Pitfalls #29

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Veykril opened this issue Apr 8, 2025 · 0 comments
Open

Potential Pitfalls #29

Veykril opened this issue Apr 8, 2025 · 0 comments
Labels
coding-guideline An issue related to a suggestion for a coding guideline enhancement New feature or request

Comments

@Veykril
Copy link

Veykril commented Apr 8, 2025

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 usable
    let _ = { 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-op
    unsafe { 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.
@PLeVasseur PLeVasseur added enhancement New feature or request coding-guideline An issue related to a suggestion for a coding guideline labels Apr 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
coding-guideline An issue related to a suggestion for a coding guideline enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants