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