@@ -13,10 +13,83 @@ use hir::def_id::DefId;
1313use ty:: { self , Ty , TyCtxt , TypeAndMut } ;
1414use ty:: subst:: Substs ;
1515
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+ /// ```
1680#[ derive( Clone , RustcEncodable , RustcDecodable ) ]
1781pub struct Adjustment < ' tcx > {
82+ /// Step 1.
1883 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 > ,
2093}
2194
2295#[ derive( Clone , Debug , RustcEncodable , RustcDecodable ) ]
@@ -36,103 +109,25 @@ pub enum Adjust<'tcx> {
36109 /// Go from a mut raw pointer to a const raw pointer.
37110 MutToConstPointer ,
38111
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 > > > ) ,
118115}
119116
120117impl < ' tcx > Adjustment < ' tcx > {
121118 pub fn is_identity ( & self ) -> bool {
119+ if self . autoref . is_some ( ) || self . unsize {
120+ return false ;
121+ }
122122 match self . kind {
123123 Adjust :: NeverToAny => self . target . is_never ( ) ,
124124
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 ( ) ,
130126
131127 Adjust :: ReifyFnPointer |
132128 Adjust :: UnsafeFnPointer |
133129 Adjust :: ClosureFnPointer |
134- Adjust :: MutToConstPointer |
135- Adjust :: DerefRef { ..} => false ,
130+ Adjust :: MutToConstPointer => false ,
136131 }
137132 }
138133}
0 commit comments