1 use crate::ty
::subst
::SubstsRef
;
2 use crate::ty
::{self, Ty, TyCtxt}
;
4 use rustc_hir
::def_id
::DefId
;
5 use rustc_hir
::lang_items
::LangItem
;
6 use rustc_macros
::HashStable
;
9 #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
10 pub enum PointerCast
{
11 /// Go from a fn-item type to a fn-pointer type.
14 /// Go from a safe fn pointer to an unsafe fn pointer.
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
),
21 /// Go from a mut raw pointer to a const raw pointer.
24 /// Go from `*const [T; N]` to `*const T`
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.
40 /// Represents coercing a value to a different type of value.
42 /// We transform values by following a number of `Adjust` steps in order.
43 /// See the documentation on variants of `Adjust` for more details.
45 /// Here are some common scenarios:
47 /// 1. The simplest cases are where a pointer is not adjusted fat vs thin.
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
50 /// `Deref`, including `Box<_>`). The types of dereferences is given by
51 /// `autoderefs`. It can then be auto-referenced zero or one times, indicated
52 /// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
55 /// 2. A thin-to-fat coercion involves unsizing the underlying data. We start
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
59 /// sized struct to a dynamically sized one. E.g., `&[i32; 4]` -> `&[i32]` is
62 /// ```ignore (illustrative)
63 /// Deref(None) -> [i32; 4],
64 /// Borrow(AutoBorrow::Ref) -> &[i32; 4],
68 /// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
69 /// E.g., `struct Foo<T> { x: T }` we can coerce `&Foo<[i32; 4]>` to `&Foo<[i32]>`
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]`.
74 /// 3. Coercing a `Box<T>` to `Box<dyn Trait>` is an interesting special case. In
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
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]>`.
80 #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
81 pub struct Adjustment
<'tcx
> {
82 pub kind
: Adjust
<'tcx
>,
86 impl<'tcx
> Adjustment
<'tcx
> {
87 pub fn is_region_borrow(&self) -> bool
{
88 matches
!(self.kind
, Adjust
::Borrow(AutoBorrow
::Ref(..)))
92 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
93 pub enum Adjust
<'tcx
> {
94 /// Go from ! to any type.
97 /// Dereference once, producing a place.
98 Deref(Option
<OverloadedDeref
<'tcx
>>),
100 /// Take the address and produce either a `&` or `*` pointer.
101 Borrow(AutoBorrow
<'tcx
>),
103 Pointer(PointerCast
),
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.
110 #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
111 #[derive(TypeFoldable, TypeVisitable, Lift)]
112 pub struct OverloadedDeref
<'tcx
> {
113 pub region
: ty
::Region
<'tcx
>,
114 pub mutbl
: hir
::Mutability
,
115 /// The `Span` associated with the field access or method call
116 /// that triggered this overloaded deref.
120 impl<'tcx
> OverloadedDeref
<'tcx
> {
121 pub fn method_call(&self, tcx
: TyCtxt
<'tcx
>, source
: Ty
<'tcx
>) -> (DefId
, SubstsRef
<'tcx
>) {
122 let trait_def_id
= match self.mutbl
{
123 hir
::Mutability
::Not
=> tcx
.require_lang_item(LangItem
::Deref
, None
),
124 hir
::Mutability
::Mut
=> tcx
.require_lang_item(LangItem
::DerefMut
, None
),
126 let method_def_id
= tcx
127 .associated_items(trait_def_id
)
128 .in_definition_order()
129 .find(|m
| m
.kind
== ty
::AssocKind
::Fn
)
132 (method_def_id
, tcx
.mk_substs_trait(source
, &[]))
136 /// At least for initial deployment, we want to limit two-phase borrows to
137 /// only a few specific cases. Right now, those are mostly "things that desugar"
138 /// into method calls:
139 /// - using `x.some_method()` syntax, where some_method takes `&mut self`,
140 /// - using `Foo::some_method(&mut x, ...)` syntax,
141 /// - binary assignment operators (`+=`, `-=`, `*=`, etc.).
142 /// Anything else should be rejected until generalized two-phase borrow support
143 /// is implemented. Right now, dataflow can't handle the general case where there
144 /// is more than one use of a mutable borrow, and we don't want to accept too much
145 /// new code via two-phase borrows, so we try to limit where we create two-phase
146 /// capable mutable borrows.
147 /// See #49434 for tracking.
148 #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
149 pub enum AllowTwoPhase
{
154 #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
155 pub enum AutoBorrowMutability
{
156 Mut { allow_two_phase_borrow: AllowTwoPhase }
,
160 impl From
<AutoBorrowMutability
> for hir
::Mutability
{
161 fn from(m
: AutoBorrowMutability
) -> Self {
163 AutoBorrowMutability
::Mut { .. }
=> hir
::Mutability
::Mut
,
164 AutoBorrowMutability
::Not
=> hir
::Mutability
::Not
,
169 #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
170 #[derive(TypeFoldable, TypeVisitable, Lift)]
171 pub enum AutoBorrow
<'tcx
> {
172 /// Converts from T to &T.
173 Ref(ty
::Region
<'tcx
>, AutoBorrowMutability
),
175 /// Converts from T to *T.
176 RawPtr(hir
::Mutability
),
179 /// Information for `CoerceUnsized` impls, storing information we
180 /// have computed about the coercion.
182 /// This struct can be obtained via the `coerce_impl_info` query.
183 /// Demanding this struct also has the side-effect of reporting errors
184 /// for inappropriate impls.
185 #[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)]
186 pub struct CoerceUnsizedInfo
{
187 /// If this is a "custom coerce" impl, then what kind of custom
188 /// coercion is it? This applies to impls of `CoerceUnsized` for
189 /// structs, primarily, where we store a bit of info about which
190 /// fields need to be coerced.
191 pub custom_kind
: Option
<CustomCoerceUnsized
>,
194 #[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)]
195 pub enum CustomCoerceUnsized
{
196 /// Records the index of the field being coerced.