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}