• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Values computed by queries that use MIR.
2 
3 use crate::mir::interpret::ConstValue;
4 use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
5 use rustc_data_structures::fx::FxIndexMap;
6 use rustc_data_structures::unord::UnordSet;
7 use rustc_errors::ErrorGuaranteed;
8 use rustc_hir as hir;
9 use rustc_hir::def_id::LocalDefId;
10 use rustc_index::bit_set::BitMatrix;
11 use rustc_index::{Idx, IndexVec};
12 use rustc_span::symbol::Symbol;
13 use rustc_span::Span;
14 use rustc_target::abi::{FieldIdx, VariantIdx};
15 use smallvec::SmallVec;
16 use std::cell::Cell;
17 use std::fmt::{self, Debug};
18 
19 use super::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,
33     UseOfInlineAssembly,
34     InitializingTypeWith,
35     CastOfPointerToInt,
36     UseOfMutableStatic,
37     UseOfExternStatic,
38     DerefOfRawPointer,
39     AccessToUnionField,
40     MutationOfLayoutConstrainedField,
41     BorrowOfLayoutConstrainedField,
42     CallToFunctionWith,
43 }
44 
45 impl UnsafetyViolationDetails {
description_and_note(&self) -> (&'static str, &'static str)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             AccessToUnionField => (
82                 "access to union field",
83                 "the field may not be properly initialized: using uninitialized data will cause \
84                  undefined behavior",
85             ),
86             MutationOfLayoutConstrainedField => (
87                 "mutation of layout constrained field",
88                 "mutating layout constrained fields cannot statically be checked for valid values",
89             ),
90             BorrowOfLayoutConstrainedField => (
91                 "borrow of layout constrained field with interior mutability",
92                 "references to fields of layout constrained fields lose the constraints. Coupled \
93                  with interior mutability, the field can be changed to invalid values",
94             ),
95             CallToFunctionWith => (
96                 "call to function with `#[target_feature]`",
97                 "can only be called if the required target features are available",
98             ),
99         }
100     }
101 }
102 
103 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
104 pub struct UnsafetyViolation {
105     pub source_info: SourceInfo,
106     pub lint_root: hir::HirId,
107     pub kind: UnsafetyViolationKind,
108     pub details: UnsafetyViolationDetails,
109 }
110 
111 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
112 pub enum UnusedUnsafe {
113     /// `unsafe` block contains no unsafe operations
114     /// > ``unnecessary `unsafe` block``
115     Unused,
116     /// `unsafe` block nested under another (used) `unsafe` block
117     /// > ``… because it's nested under this `unsafe` block``
118     InUnsafeBlock(hir::HirId),
119 }
120 
121 #[derive(TyEncodable, TyDecodable, HashStable, Debug)]
122 pub struct UnsafetyCheckResult {
123     /// Violations that are propagated *upwards* from this function.
124     pub violations: Vec<UnsafetyViolation>,
125 
126     /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint.
127     pub used_unsafe_blocks: UnordSet<hir::HirId>,
128 
129     /// This is `Some` iff the item is not a closure.
130     pub unused_unsafes: Option<Vec<(hir::HirId, UnusedUnsafe)>>,
131 }
132 
133 rustc_index::newtype_index! {
134     #[derive(HashStable)]
135     #[debug_format = "_{}"]
136     pub struct GeneratorSavedLocal {}
137 }
138 
139 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
140 pub struct GeneratorSavedTy<'tcx> {
141     pub ty: Ty<'tcx>,
142     /// Source info corresponding to the local in the original MIR body.
143     pub source_info: SourceInfo,
144     /// Whether the local should be ignored for trait bound computations.
145     pub ignore_for_traits: bool,
146 }
147 
148 /// The layout of generator state.
149 #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
150 pub struct GeneratorLayout<'tcx> {
151     /// The type of every local stored inside the generator.
152     pub field_tys: IndexVec<GeneratorSavedLocal, GeneratorSavedTy<'tcx>>,
153 
154     /// The name for debuginfo.
155     pub field_names: IndexVec<GeneratorSavedLocal, Option<Symbol>>,
156 
157     /// Which of the above fields are in each variant. Note that one field may
158     /// be stored in multiple variants.
159     pub variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, GeneratorSavedLocal>>,
160 
161     /// The source that led to each variant being created (usually, a yield or
162     /// await).
163     pub variant_source_info: IndexVec<VariantIdx, SourceInfo>,
164 
165     /// Which saved locals are storage-live at the same time. Locals that do not
166     /// have conflicts with each other are allowed to overlap in the computed
167     /// layout.
168     #[type_foldable(identity)]
169     #[type_visitable(ignore)]
170     pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
171 }
172 
173 impl Debug for GeneratorLayout<'_> {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result174     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
175         /// Prints an iterator of (key, value) tuples as a map.
176         struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>);
177         impl<'a, K, V> MapPrinter<'a, K, V> {
178             fn new(iter: impl Iterator<Item = (K, V)> + 'a) -> Self {
179                 Self(Cell::new(Some(Box::new(iter))))
180             }
181         }
182         impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> {
183             fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
184                 fmt.debug_map().entries(self.0.take().unwrap()).finish()
185             }
186         }
187 
188         /// Prints the generator variant name.
189         struct GenVariantPrinter(VariantIdx);
190         impl From<VariantIdx> for GenVariantPrinter {
191             fn from(idx: VariantIdx) -> Self {
192                 GenVariantPrinter(idx)
193             }
194         }
195         impl Debug for GenVariantPrinter {
196             fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
197                 let variant_name = ty::GeneratorSubsts::variant_name(self.0);
198                 if fmt.alternate() {
199                     write!(fmt, "{:9}({:?})", variant_name, self.0)
200                 } else {
201                     write!(fmt, "{}", variant_name)
202                 }
203             }
204         }
205 
206         /// Forces its contents to print in regular mode instead of alternate mode.
207         struct OneLinePrinter<T>(T);
208         impl<T: Debug> Debug for OneLinePrinter<T> {
209             fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
210                 write!(fmt, "{:?}", self.0)
211             }
212         }
213 
214         fmt.debug_struct("GeneratorLayout")
215             .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated()))
216             .field(
217                 "variant_fields",
218                 &MapPrinter::new(
219                     self.variant_fields
220                         .iter_enumerated()
221                         .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))),
222                 ),
223             )
224             .field("storage_conflicts", &self.storage_conflicts)
225             .finish()
226     }
227 }
228 
229 #[derive(Debug, TyEncodable, TyDecodable, HashStable)]
230 pub struct BorrowCheckResult<'tcx> {
231     /// All the opaque types that are restricted to concrete types
232     /// by this function. Unlike the value in `TypeckResults`, this has
233     /// unerased regions.
234     pub concrete_opaque_types: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
235     pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
236     pub used_mut_upvars: SmallVec<[FieldIdx; 8]>,
237     pub tainted_by_errors: Option<ErrorGuaranteed>,
238 }
239 
240 /// The result of the `mir_const_qualif` query.
241 ///
242 /// Each field (except `error_occurred`) corresponds to an implementer of the `Qualif` trait in
243 /// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each
244 /// `Qualif`.
245 #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)]
246 pub struct ConstQualifs {
247     pub has_mut_interior: bool,
248     pub needs_drop: bool,
249     pub needs_non_const_drop: bool,
250     pub custom_eq: bool,
251     pub tainted_by_errors: Option<ErrorGuaranteed>,
252 }
253 
254 /// After we borrow check a closure, we are left with various
255 /// requirements that we have inferred between the free regions that
256 /// appear in the closure's signature or on its field types. These
257 /// requirements are then verified and proved by the closure's
258 /// creating function. This struct encodes those requirements.
259 ///
260 /// The requirements are listed as being between various `RegionVid`. The 0th
261 /// region refers to `'static`; subsequent region vids refer to the free
262 /// regions that appear in the closure (or generator's) type, in order of
263 /// appearance. (This numbering is actually defined by the `UniversalRegions`
264 /// struct in the NLL region checker. See for example
265 /// `UniversalRegions::closure_mapping`.) Note the free regions in the
266 /// closure's signature and captures are erased.
267 ///
268 /// Example: If type check produces a closure with the closure substs:
269 ///
270 /// ```text
271 /// ClosureSubsts = [
272 ///     'a,                                         // From the parent.
273 ///     'b,
274 ///     i8,                                         // the "closure kind"
275 ///     for<'x> fn(&'<erased> &'x u32) -> &'x u32,  // the "closure signature"
276 ///     &'<erased> String,                          // some upvar
277 /// ]
278 /// ```
279 ///
280 /// We would "renumber" each free region to a unique vid, as follows:
281 ///
282 /// ```text
283 /// ClosureSubsts = [
284 ///     '1,                                         // From the parent.
285 ///     '2,
286 ///     i8,                                         // the "closure kind"
287 ///     for<'x> fn(&'3 &'x u32) -> &'x u32,         // the "closure signature"
288 ///     &'4 String,                                 // some upvar
289 /// ]
290 /// ```
291 ///
292 /// Now the code might impose a requirement like `'1: '2`. When an
293 /// instance of the closure is created, the corresponding free regions
294 /// can be extracted from its type and constrained to have the given
295 /// outlives relationship.
296 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
297 pub struct ClosureRegionRequirements<'tcx> {
298     /// The number of external regions defined on the closure. In our
299     /// example above, it would be 3 -- one for `'static`, then `'1`
300     /// and `'2`. This is just used for a sanity check later on, to
301     /// make sure that the number of regions we see at the callsite
302     /// matches.
303     pub num_external_vids: usize,
304 
305     /// Requirements between the various free regions defined in
306     /// indices.
307     pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
308 }
309 
310 /// Indicates an outlives-constraint between a type or between two
311 /// free regions declared on the closure.
312 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
313 pub struct ClosureOutlivesRequirement<'tcx> {
314     // This region or type ...
315     pub subject: ClosureOutlivesSubject<'tcx>,
316 
317     // ... must outlive this one.
318     pub outlived_free_region: ty::RegionVid,
319 
320     // If not, report an error here ...
321     pub blame_span: Span,
322 
323     // ... due to this reason.
324     pub category: ConstraintCategory<'tcx>,
325 }
326 
327 // Make sure this enum doesn't unintentionally grow
328 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
329 rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
330 
331 /// Outlives-constraints can be categorized to determine whether and why they
332 /// are interesting (for error reporting). Order of variants indicates sort
333 /// order of the category, thereby influencing diagnostic output.
334 ///
335 /// See also `rustc_const_eval::borrow_check::constraints`.
336 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
337 #[derive(TyEncodable, TyDecodable, HashStable, Lift, TypeVisitable, TypeFoldable)]
338 pub enum ConstraintCategory<'tcx> {
339     Return(ReturnConstraint),
340     Yield,
341     UseAsConst,
342     UseAsStatic,
343     TypeAnnotation,
344     Cast,
345 
346     /// A constraint that came from checking the body of a closure.
347     ///
348     /// We try to get the category that the closure used when reporting this.
349     ClosureBounds,
350 
351     /// Contains the function type if available.
352     CallArgument(Option<Ty<'tcx>>),
353     CopyBound,
354     SizedBound,
355     Assignment,
356     /// A constraint that came from a usage of a variable (e.g. in an ADT expression
357     /// like `Foo { field: my_val }`)
358     Usage,
359     OpaqueType,
360     ClosureUpvar(FieldIdx),
361 
362     /// A constraint from a user-written predicate
363     /// with the provided span, written on the item
364     /// with the given `DefId`
365     Predicate(Span),
366 
367     /// A "boring" constraint (caused by the given location) is one that
368     /// the user probably doesn't want to see described in diagnostics,
369     /// because it is kind of an artifact of the type system setup.
370     Boring,
371     // Boring and applicable everywhere.
372     BoringNoLocation,
373 
374     /// A constraint that doesn't correspond to anything the user sees.
375     Internal,
376 }
377 
378 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
379 #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
380 pub enum ReturnConstraint {
381     Normal,
382     ClosureUpvar(FieldIdx),
383 }
384 
385 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
386 /// that must outlive some region.
387 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
388 pub enum ClosureOutlivesSubject<'tcx> {
389     /// Subject is a type, typically a type parameter, but could also
390     /// be a projection. Indicates a requirement like `T: 'a` being
391     /// passed to the caller, where the type here is `T`.
392     Ty(ClosureOutlivesSubjectTy<'tcx>),
393 
394     /// Subject is a free region from the closure. Indicates a requirement
395     /// like `'a: 'b` being passed to the caller; the region here is `'a`.
396     Region(ty::RegionVid),
397 }
398 
399 /// Represents a `ty::Ty` for use in [`ClosureOutlivesSubject`].
400 ///
401 /// This abstraction is necessary because the type may include `ReVar` regions,
402 /// which is what we use internally within NLL code, and they can't be used in
403 /// a query response.
404 ///
405 /// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this
406 /// type is not recognized as a binder for late-bound region.
407 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
408 pub struct ClosureOutlivesSubjectTy<'tcx> {
409     inner: Ty<'tcx>,
410 }
411 
412 impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
413     /// All regions of `ty` must be of kind `ReVar` and must represent
414     /// universal regions *external* to the closure.
bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self415     pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
416         let inner = tcx.fold_regions(ty, |r, depth| match r.kind() {
417             ty::ReVar(vid) => {
418                 let br =
419                     ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon(None) };
420                 ty::Region::new_late_bound(tcx, depth, br)
421             }
422             _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
423         });
424 
425         Self { inner }
426     }
427 
instantiate( self, tcx: TyCtxt<'tcx>, mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>, ) -> Ty<'tcx>428     pub fn instantiate(
429         self,
430         tcx: TyCtxt<'tcx>,
431         mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>,
432     ) -> Ty<'tcx> {
433         tcx.fold_regions(self.inner, |r, depth| match r.kind() {
434             ty::ReLateBound(debruijn, br) => {
435                 debug_assert_eq!(debruijn, depth);
436                 map(ty::RegionVid::new(br.var.index()))
437             }
438             _ => bug!("unexpected region {r:?}"),
439         })
440     }
441 }
442 
443 /// The constituent parts of a mir constant of kind ADT or array.
444 #[derive(Copy, Clone, Debug, HashStable)]
445 pub struct DestructuredConstant<'tcx> {
446     pub variant: Option<VariantIdx>,
447     pub fields: &'tcx [(ConstValue<'tcx>, Ty<'tcx>)],
448 }
449 
450 /// Coverage information summarized from a MIR if instrumented for source code coverage (see
451 /// compiler option `-Cinstrument-coverage`). This information is generated by the
452 /// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query.
453 #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)]
454 pub struct CoverageInfo {
455     /// The total number of coverage region counters added to the MIR `Body`.
456     pub num_counters: u32,
457 
458     /// The total number of coverage region counter expressions added to the MIR `Body`.
459     pub num_expressions: u32,
460 }
461