X-Git-Url: https://git.ralfj.de/web.git/blobdiff_plain/6a09e54876b302feb4f66e055c39fa4007755a5c..09a57fbd0d9a22cda06212810a5b12f017619955:/personal/_posts/2024-08-14-places.md diff --git a/personal/_posts/2024-08-14-places.md b/personal/_posts/2024-08-14-places.md index 813bfc9..4b93ee5 100644 --- a/personal/_posts/2024-08-14-places.md +++ b/personal/_posts/2024-08-14-places.md @@ -151,6 +151,17 @@ match *ptr { _val => "not happy" } // This is UB. The scrutinee of a `match` expression is a place expression, and if the pattern is `_` then a value is never constructed. However, when an actual binder is present, this introduces a local variable and a place-to-value coercion is inserted to compute the value that will be stored in that local variable. +**Note on `unsafe` blocks.** +Note that wrapping an expression in a block forces it to be a value expression. +This means that `unsafe { *ptr }` always loads from the pointer! +In other words: +```rust +let ptr = std::ptr::null::(); +let _ = *ptr; // This is fine! +let _ = unsafe { *ptr }; // This is UB. +``` +The fact that braces force a value expression can occasionally be useful, but the fact that `unsafe` blocks do that is definitely quite unfortunate. + ### Are there also value-to-place coercions? So far, we have discussed what happens when a place expression is encountered in a spot where a value expression was expected.