]> git.lizzy.rs Git - rust.git/blob - src/librustc_middle/mir/query.rs
improve naming
[rust.git] / src / librustc_middle / mir / query.rs
1 //! Values computed by queries that use MIR.
2
3 use crate::mir::{Body, Promoted};
4 use crate::ty::{self, Ty, TyCtxt};
5 use rustc_data_structures::fx::FxHashMap;
6 use rustc_data_structures::sync::Lrc;
7 use rustc_hir as hir;
8 use rustc_hir::def_id::{DefId, LocalDefId};
9 use rustc_index::bit_set::BitMatrix;
10 use rustc_index::vec::IndexVec;
11 use rustc_span::{Span, Symbol};
12 use rustc_target::abi::VariantIdx;
13 use smallvec::SmallVec;
14 use std::cell::Cell;
15 use std::fmt::{self, Debug};
16
17 use super::{Field, SourceInfo};
18
19 #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
20 pub enum UnsafetyViolationKind {
21     /// Only permitted in regular `fn`s, prohibitted in `const fn`s.
22     General,
23     /// Permitted both in `const fn`s and regular `fn`s.
24     GeneralAndConstFn,
25     /// Borrow of packed field.
26     /// Has to be handled as a lint for backwards compatibility.
27     BorrowPacked,
28     /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block.
29     /// Has to be handled as a lint for backwards compatibility.
30     /// Should stay gated under `#![feature(unsafe_block_in_unsafe_fn)]`.
31     UnsafeFn,
32     /// Borrow of packed field in an `unsafe fn` but outside an `unsafe` block.
33     /// Has to be handled as a lint for backwards compatibility.
34     /// Should stay gated under `#![feature(unsafe_block_in_unsafe_fn)]`.
35     UnsafeFnBorrowPacked,
36 }
37
38 #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
39 pub struct UnsafetyViolation {
40     pub source_info: SourceInfo,
41     pub lint_root: hir::HirId,
42     pub description: Symbol,
43     pub details: Symbol,
44     pub kind: UnsafetyViolationKind,
45 }
46
47 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
48 pub struct UnsafetyCheckResult {
49     /// Violations that are propagated *upwards* from this function.
50     pub violations: Lrc<[UnsafetyViolation]>,
51     /// `unsafe` blocks in this function, along with whether they are used. This is
52     /// used for the "unused_unsafe" lint.
53     pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>,
54 }
55
56 rustc_index::newtype_index! {
57     pub struct GeneratorSavedLocal {
58         derive [HashStable]
59         DEBUG_FORMAT = "_{}",
60     }
61 }
62
63 /// The layout of generator state.
64 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
65 pub struct GeneratorLayout<'tcx> {
66     /// The type of every local stored inside the generator.
67     pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
68
69     /// Which of the above fields are in each variant. Note that one field may
70     /// be stored in multiple variants.
71     pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
72
73     /// The source that led to each variant being created (usually, a yield or
74     /// await).
75     pub variant_source_info: IndexVec<VariantIdx, SourceInfo>,
76
77     /// Which saved locals are storage-live at the same time. Locals that do not
78     /// have conflicts with each other are allowed to overlap in the computed
79     /// layout.
80     pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
81 }
82
83 impl Debug for GeneratorLayout<'_> {
84     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
85         /// Prints an iterator of (key, value) tuples as a map.
86         struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>);
87         impl<'a, K, V> MapPrinter<'a, K, V> {
88             fn new(iter: impl Iterator<Item = (K, V)> + 'a) -> Self {
89                 Self(Cell::new(Some(Box::new(iter))))
90             }
91         }
92         impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> {
93             fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
94                 fmt.debug_map().entries(self.0.take().unwrap()).finish()
95             }
96         }
97
98         /// Prints the generator variant name.
99         struct GenVariantPrinter(VariantIdx);
100         impl From<VariantIdx> for GenVariantPrinter {
101             fn from(idx: VariantIdx) -> Self {
102                 GenVariantPrinter(idx)
103             }
104         }
105         impl Debug for GenVariantPrinter {
106             fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
107                 let variant_name = ty::GeneratorSubsts::variant_name(self.0);
108                 if fmt.alternate() {
109                     write!(fmt, "{:9}({:?})", variant_name, self.0)
110                 } else {
111                     write!(fmt, "{}", variant_name)
112                 }
113             }
114         }
115
116         /// Forces its contents to print in regular mode instead of alternate mode.
117         struct OneLinePrinter<T>(T);
118         impl<T: Debug> Debug for OneLinePrinter<T> {
119             fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
120                 write!(fmt, "{:?}", self.0)
121             }
122         }
123
124         fmt.debug_struct("GeneratorLayout")
125             .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated()))
126             .field(
127                 "variant_fields",
128                 &MapPrinter::new(
129                     self.variant_fields
130                         .iter_enumerated()
131                         .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))),
132                 ),
133             )
134             .field("storage_conflicts", &self.storage_conflicts)
135             .finish()
136     }
137 }
138
139 #[derive(Debug, RustcEncodable, RustcDecodable, HashStable)]
140 pub struct BorrowCheckResult<'tcx> {
141     /// All the opaque types that are restricted to concrete types
142     /// by this function. Unlike the value in `TypeckTables`, this has
143     /// unerased regions.
144     pub concrete_opaque_types: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
145     pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
146     pub used_mut_upvars: SmallVec<[Field; 8]>,
147 }
148
149 /// The result of the `mir_const_qualif` query.
150 ///
151 /// Each field corresponds to an implementer of the `Qualif` trait in
152 /// `librustc_mir/transform/check_consts/qualifs.rs`. See that file for more information on each
153 /// `Qualif`.
154 #[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)]
155 pub struct ConstQualifs {
156     pub has_mut_interior: bool,
157     pub needs_drop: bool,
158     pub custom_eq: bool,
159 }
160
161 /// After we borrow check a closure, we are left with various
162 /// requirements that we have inferred between the free regions that
163 /// appear in the closure's signature or on its field types. These
164 /// requirements are then verified and proved by the closure's
165 /// creating function. This struct encodes those requirements.
166 ///
167 /// The requirements are listed as being between various `RegionVid`. The 0th
168 /// region refers to `'static`; subsequent region vids refer to the free
169 /// regions that appear in the closure (or generator's) type, in order of
170 /// appearance. (This numbering is actually defined by the `UniversalRegions`
171 /// struct in the NLL region checker. See for example
172 /// `UniversalRegions::closure_mapping`.) Note the free regions in the
173 /// closure's signature and captures are erased.
174 ///
175 /// Example: If type check produces a closure with the closure substs:
176 ///
177 /// ```text
178 /// ClosureSubsts = [
179 ///     'a,                                         // From the parent.
180 ///     'b,
181 ///     i8,                                         // the "closure kind"
182 ///     for<'x> fn(&'<erased> &'x u32) -> &'x u32,  // the "closure signature"
183 ///     &'<erased> String,                          // some upvar
184 /// ]
185 /// ```
186 ///
187 /// We would "renumber" each free region to a unique vid, as follows:
188 ///
189 /// ```text
190 /// ClosureSubsts = [
191 ///     '1,                                         // From the parent.
192 ///     '2,
193 ///     i8,                                         // the "closure kind"
194 ///     for<'x> fn(&'3 &'x u32) -> &'x u32,         // the "closure signature"
195 ///     &'4 String,                                 // some upvar
196 /// ]
197 /// ```
198 ///
199 /// Now the code might impose a requirement like `'1: '2`. When an
200 /// instance of the closure is created, the corresponding free regions
201 /// can be extracted from its type and constrained to have the given
202 /// outlives relationship.
203 ///
204 /// In some cases, we have to record outlives requirements between types and
205 /// regions as well. In that case, if those types include any regions, those
206 /// regions are recorded using their external names (`ReStatic`,
207 /// `ReEarlyBound`, `ReFree`). We use these because in a query response we
208 /// cannot use `ReVar` (which is what we use internally within the rest of the
209 /// NLL code).
210 #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
211 pub struct ClosureRegionRequirements<'tcx> {
212     /// The number of external regions defined on the closure. In our
213     /// example above, it would be 3 -- one for `'static`, then `'1`
214     /// and `'2`. This is just used for a sanity check later on, to
215     /// make sure that the number of regions we see at the callsite
216     /// matches.
217     pub num_external_vids: usize,
218
219     /// Requirements between the various free regions defined in
220     /// indices.
221     pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
222 }
223
224 /// Indicates an outlives-constraint between a type or between two
225 /// free regions declared on the closure.
226 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
227 pub struct ClosureOutlivesRequirement<'tcx> {
228     // This region or type ...
229     pub subject: ClosureOutlivesSubject<'tcx>,
230
231     // ... must outlive this one.
232     pub outlived_free_region: ty::RegionVid,
233
234     // If not, report an error here ...
235     pub blame_span: Span,
236
237     // ... due to this reason.
238     pub category: ConstraintCategory,
239 }
240
241 /// Outlives-constraints can be categorized to determine whether and why they
242 /// are interesting (for error reporting). Order of variants indicates sort
243 /// order of the category, thereby influencing diagnostic output.
244 ///
245 /// See also `rustc_mir::borrow_check::constraints`.
246 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
247 #[derive(RustcEncodable, RustcDecodable, HashStable)]
248 pub enum ConstraintCategory {
249     Return(ReturnConstraint),
250     Yield,
251     UseAsConst,
252     UseAsStatic,
253     TypeAnnotation,
254     Cast,
255
256     /// A constraint that came from checking the body of a closure.
257     ///
258     /// We try to get the category that the closure used when reporting this.
259     ClosureBounds,
260     CallArgument,
261     CopyBound,
262     SizedBound,
263     Assignment,
264     OpaqueType,
265     ClosureUpvar(hir::HirId),
266
267     /// A "boring" constraint (caused by the given location) is one that
268     /// the user probably doesn't want to see described in diagnostics,
269     /// because it is kind of an artifact of the type system setup.
270     /// Example: `x = Foo { field: y }` technically creates
271     /// intermediate regions representing the "type of `Foo { field: y
272     /// }`", and data flows from `y` into those variables, but they
273     /// are not very interesting. The assignment into `x` on the other
274     /// hand might be.
275     Boring,
276     // Boring and applicable everywhere.
277     BoringNoLocation,
278
279     /// A constraint that doesn't correspond to anything the user sees.
280     Internal,
281 }
282
283 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
284 #[derive(RustcEncodable, RustcDecodable, HashStable)]
285 pub enum ReturnConstraint {
286     Normal,
287     ClosureUpvar(hir::HirId),
288 }
289
290 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
291 /// that must outlive some region.
292 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
293 pub enum ClosureOutlivesSubject<'tcx> {
294     /// Subject is a type, typically a type parameter, but could also
295     /// be a projection. Indicates a requirement like `T: 'a` being
296     /// passed to the caller, where the type here is `T`.
297     ///
298     /// The type here is guaranteed not to contain any free regions at
299     /// present.
300     Ty(Ty<'tcx>),
301
302     /// Subject is a free region from the closure. Indicates a requirement
303     /// like `'a: 'b` being passed to the caller; the region here is `'a`.
304     Region(ty::RegionVid),
305 }
306
307 /// The constituent parts of an ADT or array.
308 #[derive(Copy, Clone, Debug, HashStable)]
309 pub struct DestructuredConst<'tcx> {
310     pub variant: Option<VariantIdx>,
311     pub fields: &'tcx [&'tcx ty::Const<'tcx>],
312 }
313
314 /// Coverage information summarized from a MIR if instrumented for source code coverage (see
315 /// compiler option `-Zinstrument-coverage`). This information is generated by the
316 /// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query.
317 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
318 pub struct CoverageInfo {
319     /// A hash value that can be used by the consumer of the coverage profile data to detect
320     /// changes to the instrumented source of the associated MIR body (typically, for an
321     /// individual function).
322     pub hash: u64,
323
324     /// The total number of coverage region counters added to the MIR `Body`.
325     pub num_counters: u32,
326 }
327
328 impl<'tcx> TyCtxt<'tcx> {
329     pub fn mir_borrowck_opt_const_arg(
330         self,
331         def: ty::WithOptConstParam<LocalDefId>,
332     ) -> &'tcx BorrowCheckResult<'tcx> {
333         if let Some(param_did) = def.const_param_did {
334             self.mir_borrowck_const_arg((def.did, param_did))
335         } else {
336             self.mir_borrowck(def.did)
337         }
338     }
339
340     pub fn mir_const_qualif_opt_const_arg(
341         self,
342         def: ty::WithOptConstParam<LocalDefId>,
343     ) -> ConstQualifs {
344         if let Some(param_did) = def.const_param_did {
345             self.mir_const_qualif_const_arg((def.did, param_did))
346         } else {
347             self.mir_const_qualif(def.did)
348         }
349     }
350
351     pub fn promoted_mir_of_opt_const_arg(
352         self,
353         def: ty::WithOptConstParam<DefId>,
354     ) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
355         if let Some((did, param_did)) = def.as_const_arg() {
356             self.promoted_mir_of_const_arg((did, param_did))
357         } else {
358             self.promoted_mir(def.did)
359         }
360     }
361 }