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