]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/mir/query.rs
Rollup merge of #106798 - scottmcm:signum-via-cmp, 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::{Body, ConstantKind, Promoted};
4 use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
5 use rustc_data_structures::fx::FxHashSet;
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     AccessToUnionField,
39     MutationOfLayoutConstrainedField,
40     BorrowOfLayoutConstrainedField,
41     CallToFunctionWith,
42 }
43
44 impl UnsafetyViolationDetails {
45     pub fn description_and_note(&self) -> (&'static str, &'static str) {
46         use UnsafetyViolationDetails::*;
47         match self {
48             CallToUnsafeFunction => (
49                 "call to unsafe function",
50                 "consult the function's documentation for information on how to avoid undefined \
51                  behavior",
52             ),
53             UseOfInlineAssembly => (
54                 "use of inline assembly",
55                 "inline assembly is entirely unchecked and can cause undefined behavior",
56             ),
57             InitializingTypeWith => (
58                 "initializing type with `rustc_layout_scalar_valid_range` attr",
59                 "initializing a layout restricted type's field with a value outside the valid \
60                  range is undefined behavior",
61             ),
62             CastOfPointerToInt => {
63                 ("cast of pointer to int", "casting pointers to integers in constants")
64             }
65             UseOfMutableStatic => (
66                 "use of mutable static",
67                 "mutable statics can be mutated by multiple threads: aliasing violations or data \
68                  races will cause undefined behavior",
69             ),
70             UseOfExternStatic => (
71                 "use of extern static",
72                 "extern statics are not controlled by the Rust type system: invalid data, \
73                  aliasing violations or data races will cause undefined behavior",
74             ),
75             DerefOfRawPointer => (
76                 "dereference of raw pointer",
77                 "raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
78                  and cause data races: all of these are undefined behavior",
79             ),
80             AccessToUnionField => (
81                 "access to union field",
82                 "the field may not be properly initialized: using uninitialized data will cause \
83                  undefined behavior",
84             ),
85             MutationOfLayoutConstrainedField => (
86                 "mutation of layout constrained field",
87                 "mutating layout constrained fields cannot statically be checked for valid values",
88             ),
89             BorrowOfLayoutConstrainedField => (
90                 "borrow of layout constrained field with interior mutability",
91                 "references to fields of layout constrained fields lose the constraints. Coupled \
92                  with interior mutability, the field can be changed to invalid values",
93             ),
94             CallToFunctionWith => (
95                 "call to function with `#[target_feature]`",
96                 "can only be called if the required target features are available",
97             ),
98         }
99     }
100 }
101
102 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
103 pub struct UnsafetyViolation {
104     pub source_info: SourceInfo,
105     pub lint_root: hir::HirId,
106     pub kind: UnsafetyViolationKind,
107     pub details: UnsafetyViolationDetails,
108 }
109
110 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
111 pub enum UnusedUnsafe {
112     /// `unsafe` block contains no unsafe operations
113     /// > ``unnecessary `unsafe` block``
114     Unused,
115     /// `unsafe` block nested under another (used) `unsafe` block
116     /// > ``… because it's nested under this `unsafe` block``
117     InUnsafeBlock(hir::HirId),
118 }
119
120 #[derive(TyEncodable, TyDecodable, HashStable, Debug)]
121 pub struct UnsafetyCheckResult {
122     /// Violations that are propagated *upwards* from this function.
123     pub violations: Vec<UnsafetyViolation>,
124
125     /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint.
126     pub used_unsafe_blocks: FxHashSet<hir::HirId>,
127
128     /// This is `Some` iff the item is not a closure.
129     pub unused_unsafes: Option<Vec<(hir::HirId, UnusedUnsafe)>>,
130 }
131
132 rustc_index::newtype_index! {
133     #[derive(HashStable)]
134     #[debug_format = "_{}"]
135     pub struct GeneratorSavedLocal {}
136 }
137
138 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
139 pub struct GeneratorSavedTy<'tcx> {
140     pub ty: Ty<'tcx>,
141     /// Source info corresponding to the local in the original MIR body.
142     pub source_info: SourceInfo,
143     /// Whether the local should be ignored for trait bound computations.
144     pub ignore_for_traits: bool,
145 }
146
147 /// The layout of generator state.
148 #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
149 pub struct GeneratorLayout<'tcx> {
150     /// The type of every local stored inside the generator.
151     pub field_tys: IndexVec<GeneratorSavedLocal, GeneratorSavedTy<'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, TyEncodable, TyDecodable, 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: VecMap<LocalDefId, OpaqueHiddenType<'tcx>>,
229     pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
230     pub used_mut_upvars: SmallVec<[Field; 8]>,
231     pub tainted_by_errors: Option<ErrorGuaranteed>,
232 }
233
234 /// The result of the `mir_const_qualif` query.
235 ///
236 /// Each field (except `error_occurred`) corresponds to an implementer of the `Qualif` trait in
237 /// `rustc_const_eval/src/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 needs_non_const_drop: bool,
244     pub custom_eq: bool,
245     pub tainted_by_errors: Option<ErrorGuaranteed>,
246 }
247
248 /// After we borrow check a closure, we are left with various
249 /// requirements that we have inferred between the free regions that
250 /// appear in the closure's signature or on its field types. These
251 /// requirements are then verified and proved by the closure's
252 /// creating function. This struct encodes those requirements.
253 ///
254 /// The requirements are listed as being between various `RegionVid`. The 0th
255 /// region refers to `'static`; subsequent region vids refer to the free
256 /// regions that appear in the closure (or generator's) type, in order of
257 /// appearance. (This numbering is actually defined by the `UniversalRegions`
258 /// struct in the NLL region checker. See for example
259 /// `UniversalRegions::closure_mapping`.) Note the free regions in the
260 /// closure's signature and captures are erased.
261 ///
262 /// Example: If type check produces a closure with the closure substs:
263 ///
264 /// ```text
265 /// ClosureSubsts = [
266 ///     'a,                                         // From the parent.
267 ///     'b,
268 ///     i8,                                         // the "closure kind"
269 ///     for<'x> fn(&'<erased> &'x u32) -> &'x u32,  // the "closure signature"
270 ///     &'<erased> String,                          // some upvar
271 /// ]
272 /// ```
273 ///
274 /// We would "renumber" each free region to a unique vid, as follows:
275 ///
276 /// ```text
277 /// ClosureSubsts = [
278 ///     '1,                                         // From the parent.
279 ///     '2,
280 ///     i8,                                         // the "closure kind"
281 ///     for<'x> fn(&'3 &'x u32) -> &'x u32,         // the "closure signature"
282 ///     &'4 String,                                 // some upvar
283 /// ]
284 /// ```
285 ///
286 /// Now the code might impose a requirement like `'1: '2`. When an
287 /// instance of the closure is created, the corresponding free regions
288 /// can be extracted from its type and constrained to have the given
289 /// outlives relationship.
290 ///
291 /// In some cases, we have to record outlives requirements between types and
292 /// regions as well. In that case, if those types include any regions, those
293 /// regions are recorded using their external names (`ReStatic`,
294 /// `ReEarlyBound`, `ReFree`). We use these because in a query response we
295 /// cannot use `ReVar` (which is what we use internally within the rest of the
296 /// NLL code).
297 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
298 pub struct ClosureRegionRequirements<'tcx> {
299     /// The number of external regions defined on the closure. In our
300     /// example above, it would be 3 -- one for `'static`, then `'1`
301     /// and `'2`. This is just used for a sanity check later on, to
302     /// make sure that the number of regions we see at the callsite
303     /// matches.
304     pub num_external_vids: usize,
305
306     /// Requirements between the various free regions defined in
307     /// indices.
308     pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
309 }
310
311 /// Indicates an outlives-constraint between a type or between two
312 /// free regions declared on the closure.
313 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
314 pub struct ClosureOutlivesRequirement<'tcx> {
315     // This region or type ...
316     pub subject: ClosureOutlivesSubject<'tcx>,
317
318     // ... must outlive this one.
319     pub outlived_free_region: ty::RegionVid,
320
321     // If not, report an error here ...
322     pub blame_span: Span,
323
324     // ... due to this reason.
325     pub category: ConstraintCategory<'tcx>,
326 }
327
328 // Make sure this enum doesn't unintentionally grow
329 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
330 rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
331
332 /// Outlives-constraints can be categorized to determine whether and why they
333 /// are interesting (for error reporting). Order of variants indicates sort
334 /// order of the category, thereby influencing diagnostic output.
335 ///
336 /// See also `rustc_const_eval::borrow_check::constraints`.
337 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
338 #[derive(TyEncodable, TyDecodable, HashStable, Lift, TypeVisitable, TypeFoldable)]
339 pub enum ConstraintCategory<'tcx> {
340     Return(ReturnConstraint),
341     Yield,
342     UseAsConst,
343     UseAsStatic,
344     TypeAnnotation,
345     Cast,
346
347     /// A constraint that came from checking the body of a closure.
348     ///
349     /// We try to get the category that the closure used when reporting this.
350     ClosureBounds,
351
352     /// Contains the function type if available.
353     CallArgument(Option<Ty<'tcx>>),
354     CopyBound,
355     SizedBound,
356     Assignment,
357     /// A constraint that came from a usage of a variable (e.g. in an ADT expression
358     /// like `Foo { field: my_val }`)
359     Usage,
360     OpaqueType,
361     ClosureUpvar(Field),
362
363     /// A constraint from a user-written predicate
364     /// with the provided span, written on the item
365     /// with the given `DefId`
366     Predicate(Span),
367
368     /// A "boring" constraint (caused by the given location) is one that
369     /// the user probably doesn't want to see described in diagnostics,
370     /// because it is kind of an artifact of the type system setup.
371     Boring,
372     // Boring and applicable everywhere.
373     BoringNoLocation,
374
375     /// A constraint that doesn't correspond to anything the user sees.
376     Internal,
377 }
378
379 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
380 #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
381 pub enum ReturnConstraint {
382     Normal,
383     ClosureUpvar(Field),
384 }
385
386 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
387 /// that must outlive some region.
388 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
389 pub enum ClosureOutlivesSubject<'tcx> {
390     /// Subject is a type, typically a type parameter, but could also
391     /// be a projection. Indicates a requirement like `T: 'a` being
392     /// passed to the caller, where the type here is `T`.
393     ///
394     /// The type here is guaranteed not to contain any free regions at
395     /// present.
396     Ty(Ty<'tcx>),
397
398     /// Subject is a free region from the closure. Indicates a requirement
399     /// like `'a: 'b` being passed to the caller; the region here is `'a`.
400     Region(ty::RegionVid),
401 }
402
403 /// The constituent parts of a mir constant of kind ADT or array.
404 #[derive(Copy, Clone, Debug, HashStable)]
405 pub struct DestructuredConstant<'tcx> {
406     pub variant: Option<VariantIdx>,
407     pub fields: &'tcx [ConstantKind<'tcx>],
408 }
409
410 /// Coverage information summarized from a MIR if instrumented for source code coverage (see
411 /// compiler option `-Cinstrument-coverage`). This information is generated by the
412 /// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query.
413 #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)]
414 pub struct CoverageInfo {
415     /// The total number of coverage region counters added to the MIR `Body`.
416     pub num_counters: u32,
417
418     /// The total number of coverage region counter expressions added to the MIR `Body`.
419     pub num_expressions: u32,
420 }
421
422 /// Shims which make dealing with `WithOptConstParam` easier.
423 ///
424 /// For more information on why this is needed, consider looking
425 /// at the docs for `WithOptConstParam` itself.
426 impl<'tcx> TyCtxt<'tcx> {
427     #[inline]
428     pub fn mir_const_qualif_opt_const_arg(
429         self,
430         def: ty::WithOptConstParam<LocalDefId>,
431     ) -> ConstQualifs {
432         if let Some(param_did) = def.const_param_did {
433             self.mir_const_qualif_const_arg((def.did, param_did))
434         } else {
435             self.mir_const_qualif(def.did)
436         }
437     }
438
439     #[inline]
440     pub fn promoted_mir_opt_const_arg(
441         self,
442         def: ty::WithOptConstParam<DefId>,
443     ) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
444         if let Some((did, param_did)) = def.as_const_arg() {
445             self.promoted_mir_of_const_arg((did, param_did))
446         } else {
447             self.promoted_mir(def.did)
448         }
449     }
450
451     #[inline]
452     pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam<DefId>) -> &'tcx Body<'tcx> {
453         if let Some((did, param_did)) = def.as_const_arg() {
454             self.mir_for_ctfe_of_const_arg((did, param_did))
455         } else {
456             self.mir_for_ctfe(def.did)
457         }
458     }
459 }