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}