]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/mir/query.rs
Auto merge of #91403 - cjgillot:inherit-async, r=oli-obk
[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     pub tainted_by_errors: Option<ErrorReported>,
218 }
219
220 /// The result of the `mir_const_qualif` query.
221 ///
222 /// Each field (except `error_occured`) corresponds to an implementer of the `Qualif` trait in
223 /// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each
224 /// `Qualif`.
225 #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)]
226 pub struct ConstQualifs {
227     pub has_mut_interior: bool,
228     pub needs_drop: bool,
229     pub needs_non_const_drop: bool,
230     pub custom_eq: bool,
231     pub tainted_by_errors: Option<ErrorReported>,
232 }
233
234 /// After we borrow check a closure, we are left with various
235 /// requirements that we have inferred between the free regions that
236 /// appear in the closure's signature or on its field types. These
237 /// requirements are then verified and proved by the closure's
238 /// creating function. This struct encodes those requirements.
239 ///
240 /// The requirements are listed as being between various `RegionVid`. The 0th
241 /// region refers to `'static`; subsequent region vids refer to the free
242 /// regions that appear in the closure (or generator's) type, in order of
243 /// appearance. (This numbering is actually defined by the `UniversalRegions`
244 /// struct in the NLL region checker. See for example
245 /// `UniversalRegions::closure_mapping`.) Note the free regions in the
246 /// closure's signature and captures are erased.
247 ///
248 /// Example: If type check produces a closure with the closure substs:
249 ///
250 /// ```text
251 /// ClosureSubsts = [
252 ///     'a,                                         // From the parent.
253 ///     'b,
254 ///     i8,                                         // the "closure kind"
255 ///     for<'x> fn(&'<erased> &'x u32) -> &'x u32,  // the "closure signature"
256 ///     &'<erased> String,                          // some upvar
257 /// ]
258 /// ```
259 ///
260 /// We would "renumber" each free region to a unique vid, as follows:
261 ///
262 /// ```text
263 /// ClosureSubsts = [
264 ///     '1,                                         // From the parent.
265 ///     '2,
266 ///     i8,                                         // the "closure kind"
267 ///     for<'x> fn(&'3 &'x u32) -> &'x u32,         // the "closure signature"
268 ///     &'4 String,                                 // some upvar
269 /// ]
270 /// ```
271 ///
272 /// Now the code might impose a requirement like `'1: '2`. When an
273 /// instance of the closure is created, the corresponding free regions
274 /// can be extracted from its type and constrained to have the given
275 /// outlives relationship.
276 ///
277 /// In some cases, we have to record outlives requirements between types and
278 /// regions as well. In that case, if those types include any regions, those
279 /// regions are recorded using their external names (`ReStatic`,
280 /// `ReEarlyBound`, `ReFree`). We use these because in a query response we
281 /// cannot use `ReVar` (which is what we use internally within the rest of the
282 /// NLL code).
283 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
284 pub struct ClosureRegionRequirements<'tcx> {
285     /// The number of external regions defined on the closure. In our
286     /// example above, it would be 3 -- one for `'static`, then `'1`
287     /// and `'2`. This is just used for a sanity check later on, to
288     /// make sure that the number of regions we see at the callsite
289     /// matches.
290     pub num_external_vids: usize,
291
292     /// Requirements between the various free regions defined in
293     /// indices.
294     pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
295 }
296
297 /// Indicates an outlives-constraint between a type or between two
298 /// free regions declared on the closure.
299 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
300 pub struct ClosureOutlivesRequirement<'tcx> {
301     // This region or type ...
302     pub subject: ClosureOutlivesSubject<'tcx>,
303
304     // ... must outlive this one.
305     pub outlived_free_region: ty::RegionVid,
306
307     // If not, report an error here ...
308     pub blame_span: Span,
309
310     // ... due to this reason.
311     pub category: ConstraintCategory,
312 }
313
314 // Make sure this enum doesn't unintentionally grow
315 rustc_data_structures::static_assert_size!(ConstraintCategory, 12);
316
317 /// Outlives-constraints can be categorized to determine whether and why they
318 /// are interesting (for error reporting). Order of variants indicates sort
319 /// order of the category, thereby influencing diagnostic output.
320 ///
321 /// See also `rustc_const_eval::borrow_check::constraints`.
322 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
323 #[derive(TyEncodable, TyDecodable, HashStable)]
324 pub enum ConstraintCategory {
325     Return(ReturnConstraint),
326     Yield,
327     UseAsConst,
328     UseAsStatic,
329     TypeAnnotation,
330     Cast,
331
332     /// A constraint that came from checking the body of a closure.
333     ///
334     /// We try to get the category that the closure used when reporting this.
335     ClosureBounds,
336     CallArgument,
337     CopyBound,
338     SizedBound,
339     Assignment,
340     /// A constraint that came from a usage of a variable (e.g. in an ADT expression
341     /// like `Foo { field: my_val }`)
342     Usage,
343     OpaqueType,
344     ClosureUpvar(hir::HirId),
345
346     /// A constraint from a user-written predicate
347     /// with the provided span, written on the item
348     /// with the given `DefId`
349     Predicate(Span),
350
351     /// A "boring" constraint (caused by the given location) is one that
352     /// the user probably doesn't want to see described in diagnostics,
353     /// because it is kind of an artifact of the type system setup.
354     Boring,
355     // Boring and applicable everywhere.
356     BoringNoLocation,
357
358     /// A constraint that doesn't correspond to anything the user sees.
359     Internal,
360 }
361
362 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
363 #[derive(TyEncodable, TyDecodable, HashStable)]
364 pub enum ReturnConstraint {
365     Normal,
366     ClosureUpvar(hir::HirId),
367 }
368
369 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
370 /// that must outlive some region.
371 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
372 pub enum ClosureOutlivesSubject<'tcx> {
373     /// Subject is a type, typically a type parameter, but could also
374     /// be a projection. Indicates a requirement like `T: 'a` being
375     /// passed to the caller, where the type here is `T`.
376     ///
377     /// The type here is guaranteed not to contain any free regions at
378     /// present.
379     Ty(Ty<'tcx>),
380
381     /// Subject is a free region from the closure. Indicates a requirement
382     /// like `'a: 'b` being passed to the caller; the region here is `'a`.
383     Region(ty::RegionVid),
384 }
385
386 /// The constituent parts of an ADT or array.
387 #[derive(Copy, Clone, Debug, HashStable)]
388 pub struct DestructuredConst<'tcx> {
389     pub variant: Option<VariantIdx>,
390     pub fields: &'tcx [&'tcx ty::Const<'tcx>],
391 }
392
393 /// Coverage information summarized from a MIR if instrumented for source code coverage (see
394 /// compiler option `-Cinstrument-coverage`). This information is generated by the
395 /// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query.
396 #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)]
397 pub struct CoverageInfo {
398     /// The total number of coverage region counters added to the MIR `Body`.
399     pub num_counters: u32,
400
401     /// The total number of coverage region counter expressions added to the MIR `Body`.
402     pub num_expressions: u32,
403 }
404
405 /// Shims which make dealing with `WithOptConstParam` easier.
406 ///
407 /// For more information on why this is needed, consider looking
408 /// at the docs for `WithOptConstParam` itself.
409 impl<'tcx> TyCtxt<'tcx> {
410     #[inline]
411     pub fn mir_const_qualif_opt_const_arg(
412         self,
413         def: ty::WithOptConstParam<LocalDefId>,
414     ) -> ConstQualifs {
415         if let Some(param_did) = def.const_param_did {
416             self.mir_const_qualif_const_arg((def.did, param_did))
417         } else {
418             self.mir_const_qualif(def.did)
419         }
420     }
421
422     #[inline]
423     pub fn promoted_mir_opt_const_arg(
424         self,
425         def: ty::WithOptConstParam<DefId>,
426     ) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
427         if let Some((did, param_did)) = def.as_const_arg() {
428             self.promoted_mir_of_const_arg((did, param_did))
429         } else {
430             self.promoted_mir(def.did)
431         }
432     }
433
434     #[inline]
435     pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam<DefId>) -> &'tcx Body<'tcx> {
436         if let Some((did, param_did)) = def.as_const_arg() {
437             self.mir_for_ctfe_of_const_arg((did, param_did))
438         } else {
439             self.mir_for_ctfe(def.did)
440         }
441     }
442 }