]> git.lizzy.rs Git - rust.git/blob - src/librustc_middle/mir/query.rs
6ce5d61fbed1b82dcd710540511f874d32e38dc0
[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;
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, prohibited 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 enum UnsafetyViolationDetails {
40     CallToUnsafeFunction,
41     UseOfInlineAssembly,
42     InitializingTypeWith,
43     CastOfPointerToInt,
44     BorrowOfPackedField,
45     UseOfMutableStatic,
46     UseOfExternStatic,
47     DerefOfRawPointer,
48     AssignToNonCopyUnionField,
49     AccessToUnionField,
50     MutationOfLayoutConstrainedField,
51     BorrowOfLayoutConstrainedField,
52     CallToFunctionWith,
53 }
54
55 impl UnsafetyViolationDetails {
56     pub fn description_and_note(&self) -> (&'static str, &'static str) {
57         use UnsafetyViolationDetails::*;
58         match self {
59             CallToUnsafeFunction => (
60                 "call to unsafe function",
61                 "consult the function's documentation for information on how to avoid undefined \
62                  behavior",
63             ),
64             UseOfInlineAssembly => (
65                 "use of inline assembly",
66                 "inline assembly is entirely unchecked and can cause undefined behavior",
67             ),
68             InitializingTypeWith => (
69                 "initializing type with `rustc_layout_scalar_valid_range` attr",
70                 "initializing a layout restricted type's field with a value outside the valid \
71                  range is undefined behavior",
72             ),
73             CastOfPointerToInt => {
74                 ("cast of pointer to int", "casting pointers to integers in constants")
75             }
76             BorrowOfPackedField => (
77                 "borrow of packed field",
78                 "fields of packed structs might be misaligned: dereferencing a misaligned pointer \
79                  or even just creating a misaligned reference is undefined behavior",
80             ),
81             UseOfMutableStatic => (
82                 "use of mutable static",
83                 "mutable statics can be mutated by multiple threads: aliasing violations or data \
84                  races will cause undefined behavior",
85             ),
86             UseOfExternStatic => (
87                 "use of extern static",
88                 "extern statics are not controlled by the Rust type system: invalid data, \
89                  aliasing violations or data races will cause undefined behavior",
90             ),
91             DerefOfRawPointer => (
92                 "dereference of raw pointer",
93                 "raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules \
94                  and cause data races: all of these are undefined behavior",
95             ),
96             AssignToNonCopyUnionField => (
97                 "assignment to non-`Copy` union field",
98                 "the previous content of the field will be dropped, which causes undefined \
99                  behavior if the field was not properly initialized",
100             ),
101             AccessToUnionField => (
102                 "access to union field",
103                 "the field may not be properly initialized: using uninitialized data will cause \
104                  undefined behavior",
105             ),
106             MutationOfLayoutConstrainedField => (
107                 "mutation of layout constrained field",
108                 "mutating layout constrained fields cannot statically be checked for valid values",
109             ),
110             BorrowOfLayoutConstrainedField => (
111                 "borrow of layout constrained field with interior mutability",
112                 "references to fields of layout constrained fields lose the constraints. Coupled \
113                  with interior mutability, the field can be changed to invalid values",
114             ),
115             CallToFunctionWith => (
116                 "call to function with `#[target_feature]`",
117                 "can only be called if the required target features are available",
118             ),
119         }
120     }
121 }
122
123 #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
124 pub struct UnsafetyViolation {
125     pub source_info: SourceInfo,
126     pub lint_root: hir::HirId,
127     pub kind: UnsafetyViolationKind,
128     pub details: UnsafetyViolationDetails,
129 }
130
131 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
132 pub struct UnsafetyCheckResult {
133     /// Violations that are propagated *upwards* from this function.
134     pub violations: Lrc<[UnsafetyViolation]>,
135     /// `unsafe` blocks in this function, along with whether they are used. This is
136     /// used for the "unused_unsafe" lint.
137     pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>,
138 }
139
140 rustc_index::newtype_index! {
141     pub struct GeneratorSavedLocal {
142         derive [HashStable]
143         DEBUG_FORMAT = "_{}",
144     }
145 }
146
147 /// The layout of generator state.
148 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
149 pub struct GeneratorLayout<'tcx> {
150     /// The type of every local stored inside the generator.
151     pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
152
153     /// Which of the above fields are in each variant. Note that one field may
154     /// be stored in multiple variants.
155     pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
156
157     /// The source that led to each variant being created (usually, a yield or
158     /// await).
159     pub variant_source_info: IndexVec<VariantIdx, SourceInfo>,
160
161     /// Which saved locals are storage-live at the same time. Locals that do not
162     /// have conflicts with each other are allowed to overlap in the computed
163     /// layout.
164     pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
165 }
166
167 impl Debug for GeneratorLayout<'_> {
168     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
169         /// Prints an iterator of (key, value) tuples as a map.
170         struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>);
171         impl<'a, K, V> MapPrinter<'a, K, V> {
172             fn new(iter: impl Iterator<Item = (K, V)> + 'a) -> Self {
173                 Self(Cell::new(Some(Box::new(iter))))
174             }
175         }
176         impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> {
177             fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
178                 fmt.debug_map().entries(self.0.take().unwrap()).finish()
179             }
180         }
181
182         /// Prints the generator variant name.
183         struct GenVariantPrinter(VariantIdx);
184         impl From<VariantIdx> for GenVariantPrinter {
185             fn from(idx: VariantIdx) -> Self {
186                 GenVariantPrinter(idx)
187             }
188         }
189         impl Debug for GenVariantPrinter {
190             fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
191                 let variant_name = ty::GeneratorSubsts::variant_name(self.0);
192                 if fmt.alternate() {
193                     write!(fmt, "{:9}({:?})", variant_name, self.0)
194                 } else {
195                     write!(fmt, "{}", variant_name)
196                 }
197             }
198         }
199
200         /// Forces its contents to print in regular mode instead of alternate mode.
201         struct OneLinePrinter<T>(T);
202         impl<T: Debug> Debug for OneLinePrinter<T> {
203             fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
204                 write!(fmt, "{:?}", self.0)
205             }
206         }
207
208         fmt.debug_struct("GeneratorLayout")
209             .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated()))
210             .field(
211                 "variant_fields",
212                 &MapPrinter::new(
213                     self.variant_fields
214                         .iter_enumerated()
215                         .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))),
216                 ),
217             )
218             .field("storage_conflicts", &self.storage_conflicts)
219             .finish()
220     }
221 }
222
223 #[derive(Debug, RustcEncodable, RustcDecodable, HashStable)]
224 pub struct BorrowCheckResult<'tcx> {
225     /// All the opaque types that are restricted to concrete types
226     /// by this function. Unlike the value in `TypeckResults`, this has
227     /// unerased regions.
228     pub concrete_opaque_types: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
229     pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
230     pub used_mut_upvars: SmallVec<[Field; 8]>,
231 }
232
233 /// The result of the `mir_const_qualif` query.
234 ///
235 /// Each field corresponds to an implementer of the `Qualif` trait in
236 /// `librustc_mir/transform/check_consts/qualifs.rs`. See that file for more information on each
237 /// `Qualif`.
238 #[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)]
239 pub struct ConstQualifs {
240     pub has_mut_interior: bool,
241     pub needs_drop: bool,
242     pub custom_eq: bool,
243 }
244
245 /// After we borrow check a closure, we are left with various
246 /// requirements that we have inferred between the free regions that
247 /// appear in the closure's signature or on its field types. These
248 /// requirements are then verified and proved by the closure's
249 /// creating function. This struct encodes those requirements.
250 ///
251 /// The requirements are listed as being between various `RegionVid`. The 0th
252 /// region refers to `'static`; subsequent region vids refer to the free
253 /// regions that appear in the closure (or generator's) type, in order of
254 /// appearance. (This numbering is actually defined by the `UniversalRegions`
255 /// struct in the NLL region checker. See for example
256 /// `UniversalRegions::closure_mapping`.) Note the free regions in the
257 /// closure's signature and captures are erased.
258 ///
259 /// Example: If type check produces a closure with the closure substs:
260 ///
261 /// ```text
262 /// ClosureSubsts = [
263 ///     'a,                                         // From the parent.
264 ///     'b,
265 ///     i8,                                         // the "closure kind"
266 ///     for<'x> fn(&'<erased> &'x u32) -> &'x u32,  // the "closure signature"
267 ///     &'<erased> String,                          // some upvar
268 /// ]
269 /// ```
270 ///
271 /// We would "renumber" each free region to a unique vid, as follows:
272 ///
273 /// ```text
274 /// ClosureSubsts = [
275 ///     '1,                                         // From the parent.
276 ///     '2,
277 ///     i8,                                         // the "closure kind"
278 ///     for<'x> fn(&'3 &'x u32) -> &'x u32,         // the "closure signature"
279 ///     &'4 String,                                 // some upvar
280 /// ]
281 /// ```
282 ///
283 /// Now the code might impose a requirement like `'1: '2`. When an
284 /// instance of the closure is created, the corresponding free regions
285 /// can be extracted from its type and constrained to have the given
286 /// outlives relationship.
287 ///
288 /// In some cases, we have to record outlives requirements between types and
289 /// regions as well. In that case, if those types include any regions, those
290 /// regions are recorded using their external names (`ReStatic`,
291 /// `ReEarlyBound`, `ReFree`). We use these because in a query response we
292 /// cannot use `ReVar` (which is what we use internally within the rest of the
293 /// NLL code).
294 #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
295 pub struct ClosureRegionRequirements<'tcx> {
296     /// The number of external regions defined on the closure. In our
297     /// example above, it would be 3 -- one for `'static`, then `'1`
298     /// and `'2`. This is just used for a sanity check later on, to
299     /// make sure that the number of regions we see at the callsite
300     /// matches.
301     pub num_external_vids: usize,
302
303     /// Requirements between the various free regions defined in
304     /// indices.
305     pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
306 }
307
308 /// Indicates an outlives-constraint between a type or between two
309 /// free regions declared on the closure.
310 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
311 pub struct ClosureOutlivesRequirement<'tcx> {
312     // This region or type ...
313     pub subject: ClosureOutlivesSubject<'tcx>,
314
315     // ... must outlive this one.
316     pub outlived_free_region: ty::RegionVid,
317
318     // If not, report an error here ...
319     pub blame_span: Span,
320
321     // ... due to this reason.
322     pub category: ConstraintCategory,
323 }
324
325 /// Outlives-constraints can be categorized to determine whether and why they
326 /// are interesting (for error reporting). Order of variants indicates sort
327 /// order of the category, thereby influencing diagnostic output.
328 ///
329 /// See also `rustc_mir::borrow_check::constraints`.
330 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
331 #[derive(RustcEncodable, RustcDecodable, HashStable)]
332 pub enum ConstraintCategory {
333     Return(ReturnConstraint),
334     Yield,
335     UseAsConst,
336     UseAsStatic,
337     TypeAnnotation,
338     Cast,
339
340     /// A constraint that came from checking the body of a closure.
341     ///
342     /// We try to get the category that the closure used when reporting this.
343     ClosureBounds,
344     CallArgument,
345     CopyBound,
346     SizedBound,
347     Assignment,
348     OpaqueType,
349     ClosureUpvar(hir::HirId),
350
351     /// A "boring" constraint (caused by the given location) is one that
352     /// the user probably doesn't want to see described in diagnostics,
353     /// because it is kind of an artifact of the type system setup.
354     /// Example: `x = Foo { field: y }` technically creates
355     /// intermediate regions representing the "type of `Foo { field: y
356     /// }`", and data flows from `y` into those variables, but they
357     /// are not very interesting. The assignment into `x` on the other
358     /// hand might be.
359     Boring,
360     // Boring and applicable everywhere.
361     BoringNoLocation,
362
363     /// A constraint that doesn't correspond to anything the user sees.
364     Internal,
365 }
366
367 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
368 #[derive(RustcEncodable, RustcDecodable, HashStable)]
369 pub enum ReturnConstraint {
370     Normal,
371     ClosureUpvar(hir::HirId),
372 }
373
374 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
375 /// that must outlive some region.
376 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
377 pub enum ClosureOutlivesSubject<'tcx> {
378     /// Subject is a type, typically a type parameter, but could also
379     /// be a projection. Indicates a requirement like `T: 'a` being
380     /// passed to the caller, where the type here is `T`.
381     ///
382     /// The type here is guaranteed not to contain any free regions at
383     /// present.
384     Ty(Ty<'tcx>),
385
386     /// Subject is a free region from the closure. Indicates a requirement
387     /// like `'a: 'b` being passed to the caller; the region here is `'a`.
388     Region(ty::RegionVid),
389 }
390
391 /// The constituent parts of an ADT or array.
392 #[derive(Copy, Clone, Debug, HashStable)]
393 pub struct DestructuredConst<'tcx> {
394     pub variant: Option<VariantIdx>,
395     pub fields: &'tcx [&'tcx ty::Const<'tcx>],
396 }
397
398 /// Coverage information summarized from a MIR if instrumented for source code coverage (see
399 /// compiler option `-Zinstrument-coverage`). This information is generated by the
400 /// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query.
401 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
402 pub struct CoverageInfo {
403     /// The total number of coverage region counters added to the MIR `Body`.
404     pub num_counters: u32,
405
406     /// The total number of coverage region counter expressions added to the MIR `Body`.
407     pub num_expressions: u32,
408 }
409
410 impl<'tcx> TyCtxt<'tcx> {
411     pub fn mir_borrowck_opt_const_arg(
412         self,
413         def: ty::WithOptConstParam<LocalDefId>,
414     ) -> &'tcx BorrowCheckResult<'tcx> {
415         if let Some(param_did) = def.const_param_did {
416             self.mir_borrowck_const_arg((def.did, param_did))
417         } else {
418             self.mir_borrowck(def.did)
419         }
420     }
421
422     pub fn mir_const_qualif_opt_const_arg(
423         self,
424         def: ty::WithOptConstParam<LocalDefId>,
425     ) -> ConstQualifs {
426         if let Some(param_did) = def.const_param_did {
427             self.mir_const_qualif_const_arg((def.did, param_did))
428         } else {
429             self.mir_const_qualif(def.did)
430         }
431     }
432
433     pub fn promoted_mir_of_opt_const_arg(
434         self,
435         def: ty::WithOptConstParam<DefId>,
436     ) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
437         if let Some((did, param_did)) = def.as_const_arg() {
438             self.promoted_mir_of_const_arg((did, param_did))
439         } else {
440             self.promoted_mir(def.did)
441         }
442     }
443 }