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