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