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