]>
Commit | Line | Data |
---|---|---|
532ac7d7 | 1 | use crate::ty::subst::SubstsRef; |
dfeec247 XL |
2 | use crate::ty::{self, Ty, TyCtxt}; |
3 | use rustc_hir as hir; | |
4 | use rustc_hir::def_id::DefId; | |
3dfed10e | 5 | use rustc_hir::lang_items::LangItem; |
532ac7d7 | 6 | use rustc_macros::HashStable; |
1b1a35ee | 7 | use rustc_span::Span; |
7cac9316 | 8 | |
6a06907d | 9 | #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] |
48663c56 XL |
10 | pub enum PointerCast { |
11 | /// Go from a fn-item type to a fn-pointer type. | |
12 | ReifyFnPointer, | |
13 | ||
14 | /// Go from a safe fn pointer to an unsafe fn pointer. | |
15 | UnsafeFnPointer, | |
16 | ||
17 | /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer. | |
18 | /// It cannot convert a closure that requires unsafe. | |
19 | ClosureFnPointer(hir::Unsafety), | |
20 | ||
21 | /// Go from a mut raw pointer to a const raw pointer. | |
22 | MutToConstPointer, | |
23 | ||
60c5eb7d XL |
24 | /// Go from `*const [T; N]` to `*const T` |
25 | ArrayToPointer, | |
26 | ||
48663c56 XL |
27 | /// Unsize a pointer/reference value, e.g., `&[T; n]` to |
28 | /// `&[T]`. Note that the source could be a thin or fat pointer. | |
29 | /// This will do things like convert thin pointers to fat | |
30 | /// pointers, or convert structs containing thin pointers to | |
31 | /// structs containing fat pointers, or convert between fat | |
32 | /// pointers. We don't store the details of how the transform is | |
33 | /// done (in fact, we don't know that, because it might depend on | |
34 | /// the precise type parameters). We just store the target | |
35 | /// type. Codegen backends and miri figure out what has to be done | |
36 | /// based on the precise source/target type at hand. | |
37 | Unsize, | |
38 | } | |
39 | ||
7cac9316 XL |
40 | /// Represents coercing a value to a different type of value. |
41 | /// | |
42 | /// We transform values by following a number of `Adjust` steps in order. | |
43 | /// See the documentation on variants of `Adjust` for more details. | |
44 | /// | |
45 | /// Here are some common scenarios: | |
46 | /// | |
47 | /// 1. The simplest cases are where a pointer is not adjusted fat vs thin. | |
ff7c6d11 XL |
48 | /// Here the pointer will be dereferenced N times (where a dereference can |
49 | /// happen to raw or borrowed pointers or any smart pointer which implements | |
17df50a5 | 50 | /// `Deref`, including `Box<_>`). The types of dereferences is given by |
9fa01778 | 51 | /// `autoderefs`. It can then be auto-referenced zero or one times, indicated |
ff7c6d11 XL |
52 | /// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is |
53 | /// `false`. | |
7cac9316 | 54 | /// |
3b2f2976 | 55 | /// 2. A thin-to-fat coercion involves unsizing the underlying data. We start |
ff7c6d11 XL |
56 | /// with a thin pointer, deref a number of times, unsize the underlying data, |
57 | /// then autoref. The 'unsize' phase may change a fixed length array to a | |
58 | /// dynamically sized one, a concrete object to a trait object, or statically | |
17df50a5 | 59 | /// sized struct to a dynamically sized one. E.g., `&[i32; 4]` -> `&[i32]` is |
ff7c6d11 | 60 | /// represented by: |
7cac9316 | 61 | /// |
ff7c6d11 XL |
62 | /// ``` |
63 | /// Deref(None) -> [i32; 4], | |
64 | /// Borrow(AutoBorrow::Ref) -> &[i32; 4], | |
65 | /// Unsize -> &[i32], | |
66 | /// ``` | |
7cac9316 | 67 | /// |
ff7c6d11 | 68 | /// Note that for a struct, the 'deep' unsizing of the struct is not recorded. |
17df50a5 | 69 | /// E.g., `struct Foo<T> { x: T }` we can coerce `&Foo<[i32; 4]>` to `&Foo<[i32]>` |
ff7c6d11 XL |
70 | /// The autoderef and -ref are the same as in the above example, but the type |
71 | /// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about | |
72 | /// the underlying conversions from `[i32; 4]` to `[i32]`. | |
7cac9316 | 73 | /// |
9fa01778 | 74 | /// 3. Coercing a `Box<T>` to `Box<dyn Trait>` is an interesting special case. In |
ff7c6d11 XL |
75 | /// that case, we have the pointer we need coming in, so there are no |
76 | /// autoderefs, and no autoref. Instead we just do the `Unsize` transformation. | |
77 | /// At some point, of course, `Box` should move out of the compiler, in which | |
17df50a5 XL |
78 | /// case this is analogous to transforming a struct. E.g., `Box<[i32; 4]>` -> |
79 | /// `Box<[i32]>` is an `Adjust::Unsize` with the target `Box<[i32]>`. | |
3dfed10e | 80 | #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)] |
c30ab7b3 SL |
81 | pub struct Adjustment<'tcx> { |
82 | pub kind: Adjust<'tcx>, | |
7cac9316 | 83 | pub target: Ty<'tcx>, |
e9174d1e SL |
84 | } |
85 | ||
dfeec247 XL |
86 | impl Adjustment<'tcx> { |
87 | pub fn is_region_borrow(&self) -> bool { | |
29967ef6 | 88 | matches!(self.kind, Adjust::Borrow(AutoBorrow::Ref(..))) |
dfeec247 XL |
89 | } |
90 | } | |
91 | ||
3dfed10e | 92 | #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] |
c30ab7b3 SL |
93 | pub enum Adjust<'tcx> { |
94 | /// Go from ! to any type. | |
95 | NeverToAny, | |
96 | ||
2c00a5a8 | 97 | /// Dereference once, producing a place. |
7cac9316 XL |
98 | Deref(Option<OverloadedDeref<'tcx>>), |
99 | ||
100 | /// Take the address and produce either a `&` or `*` pointer. | |
101 | Borrow(AutoBorrow<'tcx>), | |
102 | ||
48663c56 | 103 | Pointer(PointerCast), |
e9174d1e SL |
104 | } |
105 | ||
7cac9316 XL |
106 | /// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)` |
107 | /// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`. | |
108 | /// The target type is `U` in both cases, with the region and mutability | |
109 | /// being those shared by both the receiver and the returned reference. | |
3dfed10e | 110 | #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] |
7cac9316 XL |
111 | pub struct OverloadedDeref<'tcx> { |
112 | pub region: ty::Region<'tcx>, | |
113 | pub mutbl: hir::Mutability, | |
1b1a35ee XL |
114 | /// The `Span` associated with the field access or method call |
115 | /// that triggered this overloaded deref. | |
116 | pub span: Span, | |
7cac9316 | 117 | } |
c30ab7b3 | 118 | |
dc9dc135 XL |
119 | impl<'tcx> OverloadedDeref<'tcx> { |
120 | pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> (DefId, SubstsRef<'tcx>) { | |
7cac9316 | 121 | let trait_def_id = match self.mutbl { |
3dfed10e XL |
122 | hir::Mutability::Not => tcx.require_lang_item(LangItem::Deref, None), |
123 | hir::Mutability::Mut => tcx.require_lang_item(LangItem::DerefMut, None), | |
7cac9316 | 124 | }; |
dfeec247 | 125 | let method_def_id = tcx |
f9f354fc | 126 | .associated_items(trait_def_id) |
74b04a01 | 127 | .in_definition_order() |
ba9703b0 | 128 | .find(|m| m.kind == ty::AssocKind::Fn) |
dfeec247 XL |
129 | .unwrap() |
130 | .def_id; | |
7cac9316 | 131 | (method_def_id, tcx.mk_substs_trait(source, &[])) |
e9174d1e SL |
132 | } |
133 | } | |
e9174d1e | 134 | |
83c7162d | 135 | /// At least for initial deployment, we want to limit two-phase borrows to |
9fa01778 XL |
136 | /// only a few specific cases. Right now, those are mostly "things that desugar" |
137 | /// into method calls: | |
138 | /// - using `x.some_method()` syntax, where some_method takes `&mut self`, | |
139 | /// - using `Foo::some_method(&mut x, ...)` syntax, | |
140 | /// - binary assignment operators (`+=`, `-=`, `*=`, etc.). | |
141 | /// Anything else should be rejected until generalized two-phase borrow support | |
83c7162d XL |
142 | /// is implemented. Right now, dataflow can't handle the general case where there |
143 | /// is more than one use of a mutable borrow, and we don't want to accept too much | |
144 | /// new code via two-phase borrows, so we try to limit where we create two-phase | |
145 | /// capable mutable borrows. | |
146 | /// See #49434 for tracking. | |
3dfed10e | 147 | #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)] |
83c7162d XL |
148 | pub enum AllowTwoPhase { |
149 | Yes, | |
dfeec247 | 150 | No, |
83c7162d XL |
151 | } |
152 | ||
3dfed10e | 153 | #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)] |
2c00a5a8 | 154 | pub enum AutoBorrowMutability { |
dfeec247 XL |
155 | Mut { allow_two_phase_borrow: AllowTwoPhase }, |
156 | Not, | |
2c00a5a8 XL |
157 | } |
158 | ||
159 | impl From<AutoBorrowMutability> for hir::Mutability { | |
160 | fn from(m: AutoBorrowMutability) -> Self { | |
161 | match m { | |
dfeec247 XL |
162 | AutoBorrowMutability::Mut { .. } => hir::Mutability::Mut, |
163 | AutoBorrowMutability::Not => hir::Mutability::Not, | |
2c00a5a8 XL |
164 | } |
165 | } | |
166 | } | |
167 | ||
3dfed10e | 168 | #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] |
c30ab7b3 | 169 | pub enum AutoBorrow<'tcx> { |
9fa01778 | 170 | /// Converts from T to &T. |
2c00a5a8 | 171 | Ref(ty::Region<'tcx>, AutoBorrowMutability), |
e9174d1e | 172 | |
9fa01778 | 173 | /// Converts from T to *T. |
c30ab7b3 | 174 | RawPtr(hir::Mutability), |
e9174d1e SL |
175 | } |
176 | ||
cc61c64b XL |
177 | /// Information for `CoerceUnsized` impls, storing information we |
178 | /// have computed about the coercion. | |
179 | /// | |
180 | /// This struct can be obtained via the `coerce_impl_info` query. | |
181 | /// Demanding this struct also has the side-effect of reporting errors | |
182 | /// for inappropriate impls. | |
3dfed10e | 183 | #[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)] |
cc61c64b XL |
184 | pub struct CoerceUnsizedInfo { |
185 | /// If this is a "custom coerce" impl, then what kind of custom | |
186 | /// coercion is it? This applies to impls of `CoerceUnsized` for | |
187 | /// structs, primarily, where we store a bit of info about which | |
188 | /// fields need to be coerced. | |
dfeec247 | 189 | pub custom_kind: Option<CustomCoerceUnsized>, |
cc61c64b XL |
190 | } |
191 | ||
3dfed10e | 192 | #[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)] |
e9174d1e SL |
193 | pub enum CustomCoerceUnsized { |
194 | /// Records the index of the field being coerced. | |
dfeec247 | 195 | Struct(usize), |
e9174d1e | 196 | } |