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