rustc_middle/mir/
query.rs

1//! Values computed by queries that use MIR.
2
3use std::fmt::{self, Debug};
4
5use rustc_abi::{FieldIdx, VariantIdx};
6use rustc_data_structures::fx::FxIndexMap;
7use rustc_errors::ErrorGuaranteed;
8use rustc_hir::def_id::LocalDefId;
9use rustc_index::bit_set::BitMatrix;
10use rustc_index::{Idx, IndexVec};
11use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
12use rustc_span::{Span, Symbol};
13use smallvec::SmallVec;
14
15use super::{ConstValue, SourceInfo};
16use crate::ty::fold::fold_regions;
17use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt};
18
19rustc_index::newtype_index! {
20    #[derive(HashStable)]
21    #[encodable]
22    #[debug_format = "_{}"]
23    pub struct CoroutineSavedLocal {}
24}
25
26#[derive(Clone, Debug, PartialEq, Eq)]
27#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
28pub struct CoroutineSavedTy<'tcx> {
29    pub ty: Ty<'tcx>,
30    /// Source info corresponding to the local in the original MIR body.
31    pub source_info: SourceInfo,
32    /// Whether the local should be ignored for trait bound computations.
33    pub ignore_for_traits: bool,
34}
35
36/// The layout of coroutine state.
37#[derive(Clone, PartialEq, Eq)]
38#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
39pub struct CoroutineLayout<'tcx> {
40    /// The type of every local stored inside the coroutine.
41    pub field_tys: IndexVec<CoroutineSavedLocal, CoroutineSavedTy<'tcx>>,
42
43    /// The name for debuginfo.
44    pub field_names: IndexVec<CoroutineSavedLocal, Option<Symbol>>,
45
46    /// Which of the above fields are in each variant. Note that one field may
47    /// be stored in multiple variants.
48    pub variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, CoroutineSavedLocal>>,
49
50    /// The source that led to each variant being created (usually, a yield or
51    /// await).
52    pub variant_source_info: IndexVec<VariantIdx, SourceInfo>,
53
54    /// Which saved locals are storage-live at the same time. Locals that do not
55    /// have conflicts with each other are allowed to overlap in the computed
56    /// layout.
57    #[type_foldable(identity)]
58    #[type_visitable(ignore)]
59    pub storage_conflicts: BitMatrix<CoroutineSavedLocal, CoroutineSavedLocal>,
60}
61
62impl Debug for CoroutineLayout<'_> {
63    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
64        fmt.debug_struct("CoroutineLayout")
65            .field_with("field_tys", |fmt| {
66                fmt.debug_map().entries(self.field_tys.iter_enumerated()).finish()
67            })
68            .field_with("variant_fields", |fmt| {
69                let mut map = fmt.debug_map();
70                for (idx, fields) in self.variant_fields.iter_enumerated() {
71                    map.key_with(|fmt| {
72                        let variant_name = ty::CoroutineArgs::variant_name(idx);
73                        if fmt.alternate() {
74                            write!(fmt, "{variant_name:9}({idx:?})")
75                        } else {
76                            write!(fmt, "{variant_name}")
77                        }
78                    });
79                    // Force variant fields to print in regular mode instead of alternate mode.
80                    map.value_with(|fmt| write!(fmt, "{fields:?}"));
81                }
82                map.finish()
83            })
84            .field("storage_conflicts", &self.storage_conflicts)
85            .finish()
86    }
87}
88
89#[derive(Debug, TyEncodable, TyDecodable, HashStable)]
90pub struct BorrowCheckResult<'tcx> {
91    /// All the opaque types that are restricted to concrete types
92    /// by this function. Unlike the value in `TypeckResults`, this has
93    /// unerased regions.
94    pub concrete_opaque_types: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
95    pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
96    pub used_mut_upvars: SmallVec<[FieldIdx; 8]>,
97    pub tainted_by_errors: Option<ErrorGuaranteed>,
98}
99
100/// The result of the `mir_const_qualif` query.
101///
102/// Each field (except `tainted_by_errors`) corresponds to an implementer of the `Qualif` trait in
103/// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each
104/// `Qualif`.
105#[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)]
106pub struct ConstQualifs {
107    pub has_mut_interior: bool,
108    pub needs_drop: bool,
109    pub needs_non_const_drop: bool,
110    pub tainted_by_errors: Option<ErrorGuaranteed>,
111}
112
113/// After we borrow check a closure, we are left with various
114/// requirements that we have inferred between the free regions that
115/// appear in the closure's signature or on its field types. These
116/// requirements are then verified and proved by the closure's
117/// creating function. This struct encodes those requirements.
118///
119/// The requirements are listed as being between various `RegionVid`. The 0th
120/// region refers to `'static`; subsequent region vids refer to the free
121/// regions that appear in the closure (or coroutine's) type, in order of
122/// appearance. (This numbering is actually defined by the `UniversalRegions`
123/// struct in the NLL region checker. See for example
124/// `UniversalRegions::closure_mapping`.) Note the free regions in the
125/// closure's signature and captures are erased.
126///
127/// Example: If type check produces a closure with the closure args:
128///
129/// ```text
130/// ClosureArgs = [
131///     'a,                                         // From the parent.
132///     'b,
133///     i8,                                         // the "closure kind"
134///     for<'x> fn(&'<erased> &'x u32) -> &'x u32,  // the "closure signature"
135///     &'<erased> String,                          // some upvar
136/// ]
137/// ```
138///
139/// We would "renumber" each free region to a unique vid, as follows:
140///
141/// ```text
142/// ClosureArgs = [
143///     '1,                                         // From the parent.
144///     '2,
145///     i8,                                         // the "closure kind"
146///     for<'x> fn(&'3 &'x u32) -> &'x u32,         // the "closure signature"
147///     &'4 String,                                 // some upvar
148/// ]
149/// ```
150///
151/// Now the code might impose a requirement like `'1: '2`. When an
152/// instance of the closure is created, the corresponding free regions
153/// can be extracted from its type and constrained to have the given
154/// outlives relationship.
155#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
156pub struct ClosureRegionRequirements<'tcx> {
157    /// The number of external regions defined on the closure. In our
158    /// example above, it would be 3 -- one for `'static`, then `'1`
159    /// and `'2`. This is just used for a sanity check later on, to
160    /// make sure that the number of regions we see at the callsite
161    /// matches.
162    pub num_external_vids: usize,
163
164    /// Requirements between the various free regions defined in
165    /// indices.
166    pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
167}
168
169/// Indicates an outlives-constraint between a type or between two
170/// free regions declared on the closure.
171#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
172pub struct ClosureOutlivesRequirement<'tcx> {
173    // This region or type ...
174    pub subject: ClosureOutlivesSubject<'tcx>,
175
176    // ... must outlive this one.
177    pub outlived_free_region: ty::RegionVid,
178
179    // If not, report an error here ...
180    pub blame_span: Span,
181
182    // ... due to this reason.
183    pub category: ConstraintCategory<'tcx>,
184}
185
186// Make sure this enum doesn't unintentionally grow
187#[cfg(target_pointer_width = "64")]
188rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
189
190/// Outlives-constraints can be categorized to determine whether and why they
191/// are interesting (for error reporting). Order of variants indicates sort
192/// order of the category, thereby influencing diagnostic output.
193///
194/// See also `rustc_const_eval::borrow_check::constraints`.
195#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
196#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
197pub enum ConstraintCategory<'tcx> {
198    Return(ReturnConstraint),
199    Yield,
200    UseAsConst,
201    UseAsStatic,
202    TypeAnnotation(AnnotationSource),
203    Cast {
204        /// Whether this cast is a coercion that was automatically inserted by the compiler.
205        is_implicit_coercion: bool,
206        /// Whether this is an unsizing coercion and if yes, this contains the target type.
207        /// Region variables are erased to ReErased.
208        unsize_to: Option<Ty<'tcx>>,
209    },
210
211    /// Contains the function type if available.
212    CallArgument(Option<Ty<'tcx>>),
213    CopyBound,
214    SizedBound,
215    Assignment,
216    /// A constraint that came from a usage of a variable (e.g. in an ADT expression
217    /// like `Foo { field: my_val }`)
218    Usage,
219    OpaqueType,
220    ClosureUpvar(FieldIdx),
221
222    /// A constraint from a user-written predicate
223    /// with the provided span, written on the item
224    /// with the given `DefId`
225    Predicate(Span),
226
227    /// A "boring" constraint (caused by the given location) is one that
228    /// the user probably doesn't want to see described in diagnostics,
229    /// because it is kind of an artifact of the type system setup.
230    Boring,
231    // Boring and applicable everywhere.
232    BoringNoLocation,
233
234    /// A constraint that doesn't correspond to anything the user sees.
235    Internal,
236
237    /// An internal constraint derived from an illegal universe relation.
238    IllegalUniverse,
239}
240
241#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
242#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
243pub enum ReturnConstraint {
244    Normal,
245    ClosureUpvar(FieldIdx),
246}
247
248#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
249#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
250pub enum AnnotationSource {
251    Ascription,
252    Declaration,
253    OpaqueCast,
254    GenericArg,
255}
256
257/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
258/// that must outlive some region.
259#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
260pub enum ClosureOutlivesSubject<'tcx> {
261    /// Subject is a type, typically a type parameter, but could also
262    /// be a projection. Indicates a requirement like `T: 'a` being
263    /// passed to the caller, where the type here is `T`.
264    Ty(ClosureOutlivesSubjectTy<'tcx>),
265
266    /// Subject is a free region from the closure. Indicates a requirement
267    /// like `'a: 'b` being passed to the caller; the region here is `'a`.
268    Region(ty::RegionVid),
269}
270
271/// Represents a `ty::Ty` for use in [`ClosureOutlivesSubject`].
272///
273/// This abstraction is necessary because the type may include `ReVar` regions,
274/// which is what we use internally within NLL code, and they can't be used in
275/// a query response.
276///
277/// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this
278/// type is not recognized as a binder for late-bound region.
279#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
280pub struct ClosureOutlivesSubjectTy<'tcx> {
281    inner: Ty<'tcx>,
282}
283
284impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
285    /// All regions of `ty` must be of kind `ReVar` and must represent
286    /// universal regions *external* to the closure.
287    pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
288        let inner = fold_regions(tcx, ty, |r, depth| match r.kind() {
289            ty::ReVar(vid) => {
290                let br = ty::BoundRegion {
291                    var: ty::BoundVar::new(vid.index()),
292                    kind: ty::BoundRegionKind::Anon,
293                };
294                ty::Region::new_bound(tcx, depth, br)
295            }
296            _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
297        });
298
299        Self { inner }
300    }
301
302    pub fn instantiate(
303        self,
304        tcx: TyCtxt<'tcx>,
305        mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>,
306    ) -> Ty<'tcx> {
307        fold_regions(tcx, self.inner, |r, depth| match r.kind() {
308            ty::ReBound(debruijn, br) => {
309                debug_assert_eq!(debruijn, depth);
310                map(ty::RegionVid::new(br.var.index()))
311            }
312            _ => bug!("unexpected region {r:?}"),
313        })
314    }
315}
316
317/// The constituent parts of a mir constant of kind ADT or array.
318#[derive(Copy, Clone, Debug, HashStable)]
319pub struct DestructuredConstant<'tcx> {
320    pub variant: Option<VariantIdx>,
321    pub fields: &'tcx [(ConstValue<'tcx>, Ty<'tcx>)],
322}