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