]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_data_structures/src/frozen.rs
Auto merge of #85053 - camsteffen:duplicate-lint, r=davidtwco
[rust.git] / compiler / rustc_data_structures / src / frozen.rs
1 //! An immutable, owned value (except for interior mutability).
2 //!
3 //! The purpose of `Frozen` is to make a value immutable for the sake of defensive programming. For example,
4 //! suppose we have the following:
5 //!
6 //! ```rust
7 //! struct Bar { /* some data */ }
8 //!
9 //! struct Foo {
10 //!     /// Some computed data that should never change after construction.
11 //!     pub computed: Bar,
12 //!
13 //!     /* some other fields */
14 //! }
15 //!
16 //! impl Bar {
17 //!     /// Mutate the `Bar`.
18 //!     pub fn mutate(&mut self) { }
19 //! }
20 //! ```
21 //!
22 //! Now suppose we want to pass around a mutable `Foo` instance but, we want to make sure that
23 //! `computed` does not change accidentally (e.g. somebody might accidentally call
24 //! `foo.computed.mutate()`). This is what `Frozen` is for. We can do the following:
25 //!
26 //! ```rust
27 //! use rustc_data_structures::frozen::Frozen;
28 //!
29 //! struct Foo {
30 //!     /// Some computed data that should never change after construction.
31 //!     pub computed: Frozen<Bar>,
32 //!
33 //!     /* some other fields */
34 //! }
35 //! ```
36 //!
37 //! `Frozen` impls `Deref`, so we can ergonomically call methods on `Bar`, but it doesn't `impl
38 //! DerefMut`.  Now calling `foo.compute.mutate()` will result in a compile-time error stating that
39 //! `mutate` requires a mutable reference but we don't have one.
40 //!
41 //! # Caveats
42 //!
43 //! - `Frozen` doesn't try to defend against interior mutability (e.g. `Frozen<RefCell<Bar>>`).
44 //! - `Frozen` doesn't pin it's contents (e.g. one could still do `foo.computed =
45 //!    Frozen::freeze(new_bar)`).
46
47 /// An owned immutable value.
48 #[derive(Debug)]
49 pub struct Frozen<T>(T);
50
51 impl<T> Frozen<T> {
52     pub fn freeze(val: T) -> Self {
53         Frozen(val)
54     }
55 }
56
57 impl<T> std::ops::Deref for Frozen<T> {
58     type Target = T;
59
60     fn deref(&self) -> &T {
61         &self.0
62     }
63 }