1

I'm looking at the Condvar example and am curious how the tuples pair and pair2 are destructured:

let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = pair.clone();
// ...

thread::spawn(move|| {
    let &(ref lock, ref cvar) = &*pair2;
    // ...
}

Doesn't Arc's Deref implementation return a reference to the inner data? But removing the & from pair2:

let &(ref lock, ref cvar) = *pair2;

gives a compiler error:

11 |     let &(ref lock, ref cvar) = *pair2;
   |         ^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
   |
   = note: expected type `(std::sync::Mutex<bool>, std::sync::Condvar)`
              found type `&_`

This seems to imply that *pair2 returns a tuple and not a reference.

Kevin W Matthews
  • 722
  • 6
  • 19
  • 1
    It looks like your question might be answered by the answers of [Why is the return type of Deref::deref itself a reference?](https://stackoverflow.com/q/31624743/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Jul 09 '19 at 17:34
  • It's hard to answer multiple questions made in one post. Please separate them into multiple questions so that we can help you better and so that your questions will help others in the future that have one of the same questions as you! – Shepmaster Jul 09 '19 at 17:35
  • 1
    It looks like your second question ("why do these variants work") might be answered by the answers of [How does Rust pattern matching determine if the bound variable will be a reference or a value?](https://stackoverflow.com/q/56511328/155423); [Is there any difference between matching on a reference to a pattern or a dereferenced value?](https://stackoverflow.com/q/43370054/155423); [How can the ref keyword be avoided when pattern matching in a function taking &self or &mut self?](https://stackoverflow.com/q/55130932/155423). – Shepmaster Jul 09 '19 at 17:36
  • 1
    You can go one step further: `let (lock, cvar) = &*pair;` – Shepmaster Jul 09 '19 at 17:38
  • 1
    Hi @Shepmaster, thanks for the quick response! Let me take some time to digest the links that you gave. – Kevin W Matthews Jul 09 '19 at 17:42
  • Hi again @Shepmaster, I've taken a stab at splitting, editing, and answering this question. The other half is [here](https://stackoverflow.com/q/57128842/8807809). – Kevin W Matthews Jul 20 '19 at 22:05

1 Answers1

0

The short answer is yes, Deref returns a reference but this reference is still dereferenced by *.

Before deciphering &*pair, first look at *pair in detail.

Arc implements the Deref trait, so the Rust compiler essentially transforms:

*pair

into

*(pair.deref())

Arc::deref() does return a reference but this will be dereferenced by *, resulting in a tuple.

The Condvar example adds a leading & because it only needs to borrow the tuple that *pair yields.

Also see:

Kevin W Matthews
  • 722
  • 6
  • 19