Skip to content

Commit

Permalink
Merge question 28: underscore prefixed variables
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Jan 6, 2019
2 parents 14cfccf + 3eff6e3 commit c937f9d
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/28/index.html
7 changes: 7 additions & 0 deletions docs/questions.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions questions/028-underscore-prefix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
Answer: 3121
Difficulty: 1

# Hint

A value is dropped when it no longer has an owner.

# Explanation

The program prints `3121`. That is, the `Drop` impl for `let _guard = Guard`
runs at the end of main but the `Drop` impl for `let _ = Guard` runs right away.

In general, a value is dropped when it no longer has an owner. The variable
`_guard` owns the first value of type `Guard` and remains in scope until the end
of main. The `_` is not a variable but a wildcard pattern that binds nothing;
since no variables are bound on this line, there is no variable to be the owner
of the second value of type `Guard` and that value is dropped on the same line.

This distinction between the underscore pattern vs variables with a leading
underscore is incredibly important to remember when working with lock guards in
unsafe code.

use lazy_static::lazy_static;
use std::sync::Mutex;

lazy_static! {
static ref MUTEX: Mutex<()> = Mutex::new(());
}

/// MUTEX must be held when accessing this value.
static mut VALUE: usize = 0;

fn main() {
let _guard = MUTEX.lock().unwrap();
unsafe {
VALUE += 1;
}
}

If this code were to use `let _ = MUTEX.lock().unwrap()` then the mutex guard
would be dropped immediately, releasing the mutex and failing to guard the
access of `VALUE`.
14 changes: 14 additions & 0 deletions questions/028-underscore-prefix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
struct Guard;

impl Drop for Guard {
fn drop(&mut self) {
print!("1");
}
}

fn main() {
let _guard = Guard;
print!("3");
let _ = Guard;
print!("2");
}

0 comments on commit c937f9d

Please sign in to comment.