rustc_ast/
ptr.rs

1//! The AST pointer.
2//!
3//! Provides [`P<T>`][struct@P], an owned smart pointer.
4//!
5//! # Motivations and benefits
6//!
7//! * **Identity**: sharing AST nodes is problematic for the various analysis
8//!   passes (e.g., one may be able to bypass the borrow checker with a shared
9//!   `ExprKind::AddrOf` node taking a mutable borrow).
10//!
11//! * **Efficiency**: folding can reuse allocation space for `P<T>` and `Vec<T>`,
12//!   the latter even when the input and output types differ (as it would be the
13//!   case with arenas or a GADT AST using type parameters to toggle features).
14//!
15//! * **Maintainability**: `P<T>` provides an interface, which can remain fully
16//!   functional even if the implementation changes (using a special thread-local
17//!   heap, for example). Moreover, a switch to, e.g., `P<'a, T>` would be easy
18//!   and mostly automated.
19
20use std::fmt::{self, Debug, Display};
21use std::ops::{Deref, DerefMut};
22use std::{slice, vec};
23
24use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
25use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
26/// An owned smart pointer.
27///
28/// See the [module level documentation][crate::ptr] for details.
29pub struct P<T: ?Sized> {
30    ptr: Box<T>,
31}
32
33/// Construct a `P<T>` from a `T` value.
34#[allow(non_snake_case)]
35pub fn P<T: 'static>(value: T) -> P<T> {
36    P { ptr: Box::new(value) }
37}
38
39impl<T: 'static> P<T> {
40    /// Move out of the pointer.
41    /// Intended for chaining transformations not covered by `map`.
42    pub fn and_then<U, F>(self, f: F) -> U
43    where
44        F: FnOnce(T) -> U,
45    {
46        f(*self.ptr)
47    }
48
49    /// Equivalent to `and_then(|x| x)`.
50    pub fn into_inner(self) -> T {
51        *self.ptr
52    }
53
54    /// Produce a new `P<T>` from `self` without reallocating.
55    pub fn map<F>(mut self, f: F) -> P<T>
56    where
57        F: FnOnce(T) -> T,
58    {
59        let x = f(*self.ptr);
60        *self.ptr = x;
61
62        self
63    }
64
65    /// Optionally produce a new `P<T>` from `self` without reallocating.
66    pub fn filter_map<F>(mut self, f: F) -> Option<P<T>>
67    where
68        F: FnOnce(T) -> Option<T>,
69    {
70        *self.ptr = f(*self.ptr)?;
71        Some(self)
72    }
73}
74
75impl<T: ?Sized> Deref for P<T> {
76    type Target = T;
77
78    fn deref(&self) -> &T {
79        &self.ptr
80    }
81}
82
83impl<T: ?Sized> DerefMut for P<T> {
84    fn deref_mut(&mut self) -> &mut T {
85        &mut self.ptr
86    }
87}
88
89impl<T: 'static + Clone> Clone for P<T> {
90    fn clone(&self) -> P<T> {
91        P((**self).clone())
92    }
93}
94
95impl<T: ?Sized + Debug> Debug for P<T> {
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        Debug::fmt(&self.ptr, f)
98    }
99}
100
101impl<T: Display> Display for P<T> {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        Display::fmt(&**self, f)
104    }
105}
106
107impl<T> fmt::Pointer for P<T> {
108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109        fmt::Pointer::fmt(&self.ptr, f)
110    }
111}
112
113impl<D: Decoder, T: 'static + Decodable<D>> Decodable<D> for P<T> {
114    fn decode(d: &mut D) -> P<T> {
115        P(Decodable::decode(d))
116    }
117}
118
119impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<T> {
120    fn encode(&self, s: &mut S) {
121        (**self).encode(s);
122    }
123}
124
125impl<T> P<[T]> {
126    // FIXME(const-hack) make this const again
127    pub fn new() -> P<[T]> {
128        P { ptr: Box::default() }
129    }
130
131    #[inline(never)]
132    pub fn from_vec(v: Vec<T>) -> P<[T]> {
133        P { ptr: v.into_boxed_slice() }
134    }
135
136    #[inline(never)]
137    pub fn into_vec(self) -> Vec<T> {
138        self.ptr.into_vec()
139    }
140}
141
142impl<T> Default for P<[T]> {
143    /// Creates an empty `P<[T]>`.
144    fn default() -> P<[T]> {
145        P::new()
146    }
147}
148
149impl<T: Clone> Clone for P<[T]> {
150    fn clone(&self) -> P<[T]> {
151        P::from_vec(self.to_vec())
152    }
153}
154
155impl<T> From<Vec<T>> for P<[T]> {
156    fn from(v: Vec<T>) -> Self {
157        P::from_vec(v)
158    }
159}
160
161impl<T> From<P<[T]>> for Vec<T> {
162    fn from(val: P<[T]>) -> Self {
163        val.into_vec()
164    }
165}
166
167impl<T> FromIterator<T> for P<[T]> {
168    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> P<[T]> {
169        P::from_vec(iter.into_iter().collect())
170    }
171}
172
173impl<T> IntoIterator for P<[T]> {
174    type Item = T;
175    type IntoIter = vec::IntoIter<T>;
176
177    fn into_iter(self) -> Self::IntoIter {
178        self.into_vec().into_iter()
179    }
180}
181
182impl<'a, T> IntoIterator for &'a P<[T]> {
183    type Item = &'a T;
184    type IntoIter = slice::Iter<'a, T>;
185    fn into_iter(self) -> Self::IntoIter {
186        self.ptr.iter()
187    }
188}
189
190impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<[T]> {
191    fn encode(&self, s: &mut S) {
192        Encodable::encode(&**self, s);
193    }
194}
195
196impl<D: Decoder, T: Decodable<D>> Decodable<D> for P<[T]> {
197    fn decode(d: &mut D) -> P<[T]> {
198        P::from_vec(Decodable::decode(d))
199    }
200}
201
202impl<CTX, T> HashStable<CTX> for P<T>
203where
204    T: ?Sized + HashStable<CTX>,
205{
206    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
207        (**self).hash_stable(hcx, hasher);
208    }
209}