@@ -13,10 +13,83 @@ use hir::def_id::DefId;
13
13
use ty:: { self , Ty , TyCtxt , TypeAndMut } ;
14
14
use ty:: subst:: Substs ;
15
15
16
+
17
+ /// Represents coercing a value to a different type of value.
18
+ ///
19
+ /// We transform values by following the following steps in order:
20
+ /// 1. Apply a step of `Adjust` (see its variants for details).
21
+ /// 2. If `autoref` is `Some(_)`, then take the address and produce either a
22
+ /// `&` or `*` pointer.
23
+ /// 3. If `unsize` is `true`, then apply the unsize transformation,
24
+ /// which will do things like convert thin pointers to fat
25
+ /// pointers, or convert structs containing thin pointers to
26
+ /// structs containing fat pointers, or convert between fat
27
+ /// pointers. We don't store the details of how the transform is
28
+ /// done (in fact, we don't know that, because it might depend on
29
+ /// the precise type parameters). We just store the target
30
+ /// type. Trans figures out what has to be done at monomorphization
31
+ /// time based on the precise source/target type at hand.
32
+ ///
33
+ /// To make that more concrete, here are some common scenarios:
34
+ ///
35
+ /// 1. The simplest cases are where the pointer is not adjusted fat vs thin.
36
+ /// Here the pointer will be dereferenced N times (where a dereference can
37
+ /// happen to raw or borrowed pointers or any smart pointer which implements
38
+ /// Deref, including Box<_>). The types of dereferences is given by
39
+ /// `autoderefs`. It can then be auto-referenced zero or one times, indicated
40
+ /// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
41
+ /// `false`.
42
+ ///
43
+ /// 2. A thin-to-fat coercon involves unsizing the underlying data. We start
44
+ /// with a thin pointer, deref a number of times, unsize the underlying data,
45
+ /// then autoref. The 'unsize' phase may change a fixed length array to a
46
+ /// dynamically sized one, a concrete object to a trait object, or statically
47
+ /// sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is
48
+ /// represented by:
49
+ ///
50
+ /// ```
51
+ /// Adjustment {
52
+ /// kind: Adjust::Deref(vec![None]),// &[i32; 4] -> [i32; 4]
53
+ /// autoref: Some(AutoBorrow::Ref), // [i32; 4] -> &[i32; 4]
54
+ /// unsize: true, // &[i32; 4] -> &[i32]
55
+ /// target: `[i32]`,
56
+ /// }
57
+ /// ```
58
+ ///
59
+ /// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
60
+ /// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
61
+ /// The autoderef and -ref are the same as in the above example, but the type
62
+ /// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
63
+ /// the underlying conversions from `[i32; 4]` to `[i32]`.
64
+ ///
65
+ /// 3. Coercing a `Box<T>` to `Box<Trait>` is an interesting special case. In
66
+ /// that case, we have the pointer we need coming in, so there are no
67
+ /// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
68
+ /// At some point, of course, `Box` should move out of the compiler, in which
69
+ /// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> ->
70
+ /// Box<[i32]> is represented by:
71
+ ///
72
+ /// ```
73
+ /// Adjustment {
74
+ /// kind: Adjust::Deref(vec![]),
75
+ /// autoref: None,
76
+ /// unsize: true,
77
+ /// target: `Box<[i32]>`,
78
+ /// }
79
+ /// ```
16
80
#[ derive( Clone , RustcEncodable , RustcDecodable ) ]
17
81
pub struct Adjustment < ' tcx > {
82
+ /// Step 1.
18
83
pub kind : Adjust < ' tcx > ,
19
- pub target : Ty < ' tcx >
84
+
85
+ /// Step 2. Optionally produce a pointer/reference from the value.
86
+ pub autoref : Option < AutoBorrow < ' tcx > > ,
87
+
88
+ /// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to
89
+ /// `&[T]`. Note that the source could be a thin or fat pointer.
90
+ pub unsize : bool ,
91
+
92
+ pub target : Ty < ' tcx > ,
20
93
}
21
94
22
95
#[ derive( Clone , Debug , RustcEncodable , RustcDecodable ) ]
@@ -36,103 +109,25 @@ pub enum Adjust<'tcx> {
36
109
/// Go from a mut raw pointer to a const raw pointer.
37
110
MutToConstPointer ,
38
111
39
- /// Represents coercing a pointer to a different kind of pointer - where 'kind'
40
- /// here means either or both of raw vs borrowed vs unique and fat vs thin.
41
- ///
42
- /// We transform pointers by following the following steps in order:
43
- /// 1. Deref the pointer through `self.autoderefs` steps (may be no steps).
44
- /// 2. If `autoref` is `Some(_)`, then take the address and produce either a
45
- /// `&` or `*` pointer.
46
- /// 3. If `unsize` is `true`, then apply the unsize transformation,
47
- /// which will do things like convert thin pointers to fat
48
- /// pointers, or convert structs containing thin pointers to
49
- /// structs containing fat pointers, or convert between fat
50
- /// pointers. We don't store the details of how the transform is
51
- /// done (in fact, we don't know that, because it might depend on
52
- /// the precise type parameters). We just store the target
53
- /// type. Trans figures out what has to be done at monomorphization
54
- /// time based on the precise source/target type at hand.
55
- ///
56
- /// To make that more concrete, here are some common scenarios:
57
- ///
58
- /// 1. The simplest cases are where the pointer is not adjusted fat vs thin.
59
- /// Here the pointer will be dereferenced N times (where a dereference can
60
- /// happen to raw or borrowed pointers or any smart pointer which implements
61
- /// Deref, including Box<_>). The types of dereferences is given by
62
- /// `autoderefs`. It can then be auto-referenced zero or one times, indicated
63
- /// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
64
- /// `false`.
65
- ///
66
- /// 2. A thin-to-fat coercon involves unsizing the underlying data. We start
67
- /// with a thin pointer, deref a number of times, unsize the underlying data,
68
- /// then autoref. The 'unsize' phase may change a fixed length array to a
69
- /// dynamically sized one, a concrete object to a trait object, or statically
70
- /// sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is
71
- /// represented by:
72
- ///
73
- /// ```
74
- /// Adjustment {
75
- /// kind: Adjust::DerefRef {
76
- /// autoderefs: vec![None], // &[i32; 4] -> [i32; 4]
77
- /// autoref: Some(AutoBorrow::Ref), // [i32; 4] -> &[i32; 4]
78
- /// unsize: true, // &[i32; 4] -> &[i32]
79
- /// },
80
- /// target: `[i32]`,
81
- /// }
82
- /// ```
83
- ///
84
- /// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
85
- /// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
86
- /// The autoderef and -ref are the same as in the above example, but the type
87
- /// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
88
- /// the underlying conversions from `[i32; 4]` to `[i32]`.
89
- ///
90
- /// 3. Coercing a `Box<T>` to `Box<Trait>` is an interesting special case. In
91
- /// that case, we have the pointer we need coming in, so there are no
92
- /// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
93
- /// At some point, of course, `Box` should move out of the compiler, in which
94
- /// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> ->
95
- /// Box<[i32]> is represented by:
96
- ///
97
- /// ```
98
- /// Adjustment {
99
- /// Adjust::DerefRef {
100
- /// autoderefs: vec![],
101
- /// autoref: None,
102
- /// unsize: true,
103
- /// },
104
- /// target: `Box<[i32]>`,
105
- /// }
106
- /// ```
107
- DerefRef {
108
- /// Step 1. Apply a number of dereferences, producing an lvalue.
109
- autoderefs : Vec < Option < OverloadedDeref < ' tcx > > > ,
110
-
111
- /// Step 2. Optionally produce a pointer/reference from the value.
112
- autoref : Option < AutoBorrow < ' tcx > > ,
113
-
114
- /// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to
115
- /// `&[T]`. Note that the source could be a thin or fat pointer.
116
- unsize : bool ,
117
- }
112
+ /// Apply a number of dereferences, producing an lvalue,
113
+ /// if there are more than 0 dereferences.
114
+ Deref ( Vec < Option < OverloadedDeref < ' tcx > > > ) ,
118
115
}
119
116
120
117
impl < ' tcx > Adjustment < ' tcx > {
121
118
pub fn is_identity ( & self ) -> bool {
119
+ if self . autoref . is_some ( ) || self . unsize {
120
+ return false ;
121
+ }
122
122
match self . kind {
123
123
Adjust :: NeverToAny => self . target . is_never ( ) ,
124
124
125
- Adjust :: DerefRef {
126
- ref autoderefs,
127
- autoref : None ,
128
- unsize : false
129
- } if autoderefs. is_empty ( ) => true ,
125
+ Adjust :: Deref ( ref autoderefs) => autoderefs. is_empty ( ) ,
130
126
131
127
Adjust :: ReifyFnPointer |
132
128
Adjust :: UnsafeFnPointer |
133
129
Adjust :: ClosureFnPointer |
134
- Adjust :: MutToConstPointer |
135
- Adjust :: DerefRef { ..} => false ,
130
+ Adjust :: MutToConstPointer => false ,
136
131
}
137
132
}
138
133
}
0 commit comments