]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
b7449926 | 11 | // run-pass |
c34b1796 | 12 | |
1a4d82fc JJ |
13 | use std::cell::Cell; |
14 | use std::ops::{Deref, DerefMut}; | |
15 | use std::vec::Vec; | |
16 | ||
17 | struct DerefCounter<T> { | |
c34b1796 AL |
18 | count_imm: Cell<usize>, |
19 | count_mut: usize, | |
1a4d82fc JJ |
20 | value: T |
21 | } | |
22 | ||
23 | impl<T> DerefCounter<T> { | |
24 | fn new(value: T) -> DerefCounter<T> { | |
25 | DerefCounter { | |
26 | count_imm: Cell::new(0), | |
27 | count_mut: 0, | |
28 | value: value | |
29 | } | |
30 | } | |
31 | ||
c34b1796 | 32 | fn counts(&self) -> (usize, usize) { |
1a4d82fc JJ |
33 | (self.count_imm.get(), self.count_mut) |
34 | } | |
35 | } | |
36 | ||
37 | impl<T> Deref for DerefCounter<T> { | |
38 | type Target = T; | |
39 | ||
40 | fn deref(&self) -> &T { | |
41 | self.count_imm.set(self.count_imm.get() + 1); | |
42 | &self.value | |
43 | } | |
44 | } | |
45 | ||
46 | impl<T> DerefMut for DerefCounter<T> { | |
47 | fn deref_mut(&mut self) -> &mut T { | |
48 | self.count_mut += 1; | |
49 | &mut self.value | |
50 | } | |
51 | } | |
52 | ||
53 | pub fn main() { | |
85aaf69f | 54 | let mut n = DerefCounter::new(0); |
1a4d82fc JJ |
55 | let mut v = DerefCounter::new(Vec::new()); |
56 | ||
57 | let _ = *n; // Immutable deref + copy a POD. | |
58 | assert_eq!(n.counts(), (1, 0)); | |
59 | ||
60 | let _ = (&*n, &*v); // Immutable deref + borrow. | |
61 | assert_eq!(n.counts(), (2, 0)); assert_eq!(v.counts(), (1, 0)); | |
62 | ||
63 | let _ = (&mut *n, &mut *v); // Mutable deref + mutable borrow. | |
64 | assert_eq!(n.counts(), (2, 1)); assert_eq!(v.counts(), (1, 1)); | |
65 | ||
66 | let mut v2 = Vec::new(); | |
85aaf69f | 67 | v2.push(1); |
1a4d82fc JJ |
68 | |
69 | *n = 5; *v = v2; // Mutable deref + assignment. | |
70 | assert_eq!(n.counts(), (2, 2)); assert_eq!(v.counts(), (1, 2)); | |
71 | ||
72 | *n -= 3; // Mutable deref + assignment with binary operation. | |
73 | assert_eq!(n.counts(), (2, 3)); | |
74 | ||
75 | // Immutable deref used for calling a method taking &self. (The | |
76 | // typechecker is smarter now about doing this.) | |
77 | (*n).to_string(); | |
78 | assert_eq!(n.counts(), (3, 3)); | |
79 | ||
80 | // Mutable deref used for calling a method taking &mut self. | |
81 | (*v).push(2); | |
82 | assert_eq!(v.counts(), (1, 3)); | |
83 | ||
84 | // Check the final states. | |
85 | assert_eq!(*n, 2); | |
86 | let expected: &[_] = &[1, 2]; | |
85aaf69f | 87 | assert_eq!((*v), expected); |
1a4d82fc | 88 | } |