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