88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
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+
1137use std:: fmt;
1238use std:: fmt:: Show ;
1339use std:: hash:: Hash ;
@@ -19,18 +45,21 @@ pub struct P<T> {
1945}
2046
2147#[ allow( non_snake_case) ]
22- /// Construct a P<T> from a T value.
48+ /// Construct a ` P<T>` from a `T` value.
2349pub fn P < T : ' static > ( value : T ) -> P < T > {
2450 P {
2551 ptr : box value
2652 }
2753}
2854
2955impl < T : ' static > P < T > {
56+ /// Move out of the pointer.
57+ /// Intended for chaining transformations not covered by `map`.
3058 pub fn and_then < U > ( self , f: |T | -> U ) -> U {
3159 f ( * self . ptr )
3260 }
3361
62+ /// Transform the inner value, consuming `self` and producing a new `P<T>`.
3463 pub fn map ( mut self , f: |T | -> T ) -> P < T > {
3564 use std:: { mem, ptr} ;
3665 unsafe {
0 commit comments