8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
+ //! The AST pointer
12
+ //!
13
+ //! Provides `P<T>`, a frozen owned smart pointer, as a replacement for `@T` in the AST.
14
+ //!
15
+ //! # Motivations and benefits
16
+ //!
17
+ //! * **Identity**: sharing AST nodes is problematic for the various analysis passes
18
+ //! (e.g. one may be able to bypass the borrow checker with a shared `ExprAddrOf`
19
+ //! node taking a mutable borrow). The only reason `@T` in the AST hasn't caused
20
+ //! issues is because of inefficient folding passes which would always deduplicate
21
+ //! any such shared nodes. Even if the AST were to switch to an arena, this would
22
+ //! still hold, i.e. it couldn't use `&'a T`, but rather a wrapper like `P<'a, T>`.
23
+ //!
24
+ //! * **Immutability**: `P<T>` disallows mutating its inner `T`, unlike `Box<T>`
25
+ //! (unless it contains an `Unsafe` interior, but that may be denied later).
26
+ //! This mainly prevents mistakes, but can also enforces a kind of "purity".
27
+ //!
28
+ //! * **Efficiency**: folding can reuse allocation space for `P<T>` and `Vec<T>`,
29
+ //! the latter even when the input and output types differ (as it would be the
30
+ //! case with arenas or a GADT AST using type parameters to toggle features).
31
+ //!
32
+ //! * **Maintainability**: `P<T>` provides a fixed interface - `Deref`,
33
+ //! `and_then` and `map` - which can remain fully functional even if the
34
+ //! implementation changes (using a special thread-local heap, for example).
35
+ //! Moreover, a switch to, e.g. `P<'a, T>` would be easy and mostly automated.
36
+
11
37
use std:: fmt;
12
38
use std:: fmt:: Show ;
13
39
use std:: hash:: Hash ;
@@ -19,18 +45,21 @@ pub struct P<T> {
19
45
}
20
46
21
47
#[ allow( non_snake_case) ]
22
- /// Construct a P<T> from a T value.
48
+ /// Construct a ` P<T>` from a `T` value.
23
49
pub fn P < T : ' static > ( value : T ) -> P < T > {
24
50
P {
25
51
ptr : box value
26
52
}
27
53
}
28
54
29
55
impl < T : ' static > P < T > {
56
+ /// Move out of the pointer.
57
+ /// Intended for chaining transformations not covered by `map`.
30
58
pub fn and_then < U > ( self , f: |T | -> U ) -> U {
31
59
f ( * self . ptr )
32
60
}
33
61
62
+ /// Transform the inner value, consuming `self` and producing a new `P<T>`.
34
63
pub fn map ( mut self , f: |T | -> T ) -> P < T > {
35
64
use std:: { mem, ptr} ;
36
65
unsafe {
0 commit comments