mv compiler to compiler/
This commit is contained in:
parent
db534b3ac2
commit
9e5f7d5631
1686 changed files with 941 additions and 1051 deletions
63
compiler/rustc_data_structures/src/frozen.rs
Normal file
63
compiler/rustc_data_structures/src/frozen.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
//! An immutable, owned value (except for interior mutability).
|
||||
//!
|
||||
//! The purpose of `Frozen` is to make a value immutable for the sake of defensive programming. For example,
|
||||
//! suppose we have the following:
|
||||
//!
|
||||
//! ```rust
|
||||
//! struct Bar { /* some data */ }
|
||||
//!
|
||||
//! struct Foo {
|
||||
//! /// Some computed data that should never change after construction.
|
||||
//! pub computed: Bar,
|
||||
//!
|
||||
//! /* some other fields */
|
||||
//! }
|
||||
//!
|
||||
//! impl Bar {
|
||||
//! /// Mutate the `Bar`.
|
||||
//! pub fn mutate(&mut self) { }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Now suppose we want to pass around a mutable `Foo` instance but, we want to make sure that
|
||||
//! `computed` does not change accidentally (e.g. somebody might accidentally call
|
||||
//! `foo.computed.mutate()`). This is what `Frozen` is for. We can do the following:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use rustc_data_structures::frozen::Frozen;
|
||||
//!
|
||||
//! struct Foo {
|
||||
//! /// Some computed data that should never change after construction.
|
||||
//! pub computed: Frozen<Bar>,
|
||||
//!
|
||||
//! /* some other fields */
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! `Frozen` impls `Deref`, so we can ergonomically call methods on `Bar`, but it doesn't `impl
|
||||
//! DerefMut`. Now calling `foo.compute.mutate()` will result in a compile-time error stating that
|
||||
//! `mutate` requires a mutable reference but we don't have one.
|
||||
//!
|
||||
//! # Caveats
|
||||
//!
|
||||
//! - `Frozen` doesn't try to defend against interior mutability (e.g. `Frozen<RefCell<Bar>>`).
|
||||
//! - `Frozen` doesn't pin it's contents (e.g. one could still do `foo.computed =
|
||||
//! Frozen::freeze(new_bar)`).
|
||||
|
||||
/// An owned immutable value.
|
||||
#[derive(Debug)]
|
||||
pub struct Frozen<T>(T);
|
||||
|
||||
impl<T> Frozen<T> {
|
||||
pub fn freeze(val: T) -> Self {
|
||||
Frozen(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::Deref for Frozen<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue