]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_middle/src/mir/query.rs
New upstream version 1.68.2+dfsg1
[rustc.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 /// The layout of generator state.
139 #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
140 pub struct GeneratorLayout<'tcx> {
141 /// The type of every local stored inside the generator.
142 pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
143
144 /// Which of the above fields are in each variant. Note that one field may
145 /// be stored in multiple variants.
146 pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
147
148 /// The source that led to each variant being created (usually, a yield or
149 /// await).
150 pub variant_source_info: IndexVec<VariantIdx, SourceInfo>,
151
152 /// Which saved locals are storage-live at the same time. Locals that do not
153 /// have conflicts with each other are allowed to overlap in the computed
154 /// layout.
155 pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
156 }
157
158 impl Debug for GeneratorLayout<'_> {
159 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
160 /// Prints an iterator of (key, value) tuples as a map.
161 struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>);
162 impl<'a, K, V> MapPrinter<'a, K, V> {
163 fn new(iter: impl Iterator<Item = (K, V)> + 'a) -> Self {
164 Self(Cell::new(Some(Box::new(iter))))
165 }
166 }
167 impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> {
168 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
169 fmt.debug_map().entries(self.0.take().unwrap()).finish()
170 }
171 }
172
173 /// Prints the generator variant name.
174 struct GenVariantPrinter(VariantIdx);
175 impl From<VariantIdx> for GenVariantPrinter {
176 fn from(idx: VariantIdx) -> Self {
177 GenVariantPrinter(idx)
178 }
179 }
180 impl Debug for GenVariantPrinter {
181 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
182 let variant_name = ty::GeneratorSubsts::variant_name(self.0);
183 if fmt.alternate() {
184 write!(fmt, "{:9}({:?})", variant_name, self.0)
185 } else {
186 write!(fmt, "{}", variant_name)
187 }
188 }
189 }
190
191 /// Forces its contents to print in regular mode instead of alternate mode.
192 struct OneLinePrinter<T>(T);
193 impl<T: Debug> Debug for OneLinePrinter<T> {
194 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
195 write!(fmt, "{:?}", self.0)
196 }
197 }
198
199 fmt.debug_struct("GeneratorLayout")
200 .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated()))
201 .field(
202 "variant_fields",
203 &MapPrinter::new(
204 self.variant_fields
205 .iter_enumerated()
206 .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))),
207 ),
208 )
209 .field("storage_conflicts", &self.storage_conflicts)
210 .finish()
211 }
212 }
213
214 #[derive(Debug, TyEncodable, TyDecodable, HashStable)]
215 pub struct BorrowCheckResult<'tcx> {
216 /// All the opaque types that are restricted to concrete types
217 /// by this function. Unlike the value in `TypeckResults`, this has
218 /// unerased regions.
219 pub concrete_opaque_types: VecMap<LocalDefId, OpaqueHiddenType<'tcx>>,
220 pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
221 pub used_mut_upvars: SmallVec<[Field; 8]>,
222 pub tainted_by_errors: Option<ErrorGuaranteed>,
223 }
224
225 /// The result of the `mir_const_qualif` query.
226 ///
227 /// Each field (except `error_occurred`) corresponds to an implementer of the `Qualif` trait in
228 /// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each
229 /// `Qualif`.
230 #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)]
231 pub struct ConstQualifs {
232 pub has_mut_interior: bool,
233 pub needs_drop: bool,
234 pub needs_non_const_drop: bool,
235 pub custom_eq: bool,
236 pub tainted_by_errors: Option<ErrorGuaranteed>,
237 }
238
239 /// After we borrow check a closure, we are left with various
240 /// requirements that we have inferred between the free regions that
241 /// appear in the closure's signature or on its field types. These
242 /// requirements are then verified and proved by the closure's
243 /// creating function. This struct encodes those requirements.
244 ///
245 /// The requirements are listed as being between various `RegionVid`. The 0th
246 /// region refers to `'static`; subsequent region vids refer to the free
247 /// regions that appear in the closure (or generator's) type, in order of
248 /// appearance. (This numbering is actually defined by the `UniversalRegions`
249 /// struct in the NLL region checker. See for example
250 /// `UniversalRegions::closure_mapping`.) Note the free regions in the
251 /// closure's signature and captures are erased.
252 ///
253 /// Example: If type check produces a closure with the closure substs:
254 ///
255 /// ```text
256 /// ClosureSubsts = [
257 /// 'a, // From the parent.
258 /// 'b,
259 /// i8, // the "closure kind"
260 /// for<'x> fn(&'<erased> &'x u32) -> &'x u32, // the "closure signature"
261 /// &'<erased> String, // some upvar
262 /// ]
263 /// ```
264 ///
265 /// We would "renumber" each free region to a unique vid, as follows:
266 ///
267 /// ```text
268 /// ClosureSubsts = [
269 /// '1, // From the parent.
270 /// '2,
271 /// i8, // the "closure kind"
272 /// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature"
273 /// &'4 String, // some upvar
274 /// ]
275 /// ```
276 ///
277 /// Now the code might impose a requirement like `'1: '2`. When an
278 /// instance of the closure is created, the corresponding free regions
279 /// can be extracted from its type and constrained to have the given
280 /// outlives relationship.
281 ///
282 /// In some cases, we have to record outlives requirements between types and
283 /// regions as well. In that case, if those types include any regions, those
284 /// regions are recorded using their external names (`ReStatic`,
285 /// `ReEarlyBound`, `ReFree`). We use these because in a query response we
286 /// cannot use `ReVar` (which is what we use internally within the rest of the
287 /// NLL code).
288 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
289 pub struct ClosureRegionRequirements<'tcx> {
290 /// The number of external regions defined on the closure. In our
291 /// example above, it would be 3 -- one for `'static`, then `'1`
292 /// and `'2`. This is just used for a sanity check later on, to
293 /// make sure that the number of regions we see at the callsite
294 /// matches.
295 pub num_external_vids: usize,
296
297 /// Requirements between the various free regions defined in
298 /// indices.
299 pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
300 }
301
302 /// Indicates an outlives-constraint between a type or between two
303 /// free regions declared on the closure.
304 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
305 pub struct ClosureOutlivesRequirement<'tcx> {
306 // This region or type ...
307 pub subject: ClosureOutlivesSubject<'tcx>,
308
309 // ... must outlive this one.
310 pub outlived_free_region: ty::RegionVid,
311
312 // If not, report an error here ...
313 pub blame_span: Span,
314
315 // ... due to this reason.
316 pub category: ConstraintCategory<'tcx>,
317 }
318
319 // Make sure this enum doesn't unintentionally grow
320 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
321 rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
322
323 /// Outlives-constraints can be categorized to determine whether and why they
324 /// are interesting (for error reporting). Order of variants indicates sort
325 /// order of the category, thereby influencing diagnostic output.
326 ///
327 /// See also `rustc_const_eval::borrow_check::constraints`.
328 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
329 #[derive(TyEncodable, TyDecodable, HashStable, Lift, TypeVisitable, TypeFoldable)]
330 pub enum ConstraintCategory<'tcx> {
331 Return(ReturnConstraint),
332 Yield,
333 UseAsConst,
334 UseAsStatic,
335 TypeAnnotation,
336 Cast,
337
338 /// A constraint that came from checking the body of a closure.
339 ///
340 /// We try to get the category that the closure used when reporting this.
341 ClosureBounds,
342
343 /// Contains the function type if available.
344 CallArgument(Option<Ty<'tcx>>),
345 CopyBound,
346 SizedBound,
347 Assignment,
348 /// A constraint that came from a usage of a variable (e.g. in an ADT expression
349 /// like `Foo { field: my_val }`)
350 Usage,
351 OpaqueType,
352 ClosureUpvar(Field),
353
354 /// A constraint from a user-written predicate
355 /// with the provided span, written on the item
356 /// with the given `DefId`
357 Predicate(Span),
358
359 /// A "boring" constraint (caused by the given location) is one that
360 /// the user probably doesn't want to see described in diagnostics,
361 /// because it is kind of an artifact of the type system setup.
362 Boring,
363 // Boring and applicable everywhere.
364 BoringNoLocation,
365
366 /// A constraint that doesn't correspond to anything the user sees.
367 Internal,
368 }
369
370 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
371 #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
372 pub enum ReturnConstraint {
373 Normal,
374 ClosureUpvar(Field),
375 }
376
377 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
378 /// that must outlive some region.
379 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
380 pub enum ClosureOutlivesSubject<'tcx> {
381 /// Subject is a type, typically a type parameter, but could also
382 /// be a projection. Indicates a requirement like `T: 'a` being
383 /// passed to the caller, where the type here is `T`.
384 ///
385 /// The type here is guaranteed not to contain any free regions at
386 /// present.
387 Ty(Ty<'tcx>),
388
389 /// Subject is a free region from the closure. Indicates a requirement
390 /// like `'a: 'b` being passed to the caller; the region here is `'a`.
391 Region(ty::RegionVid),
392 }
393
394 /// The constituent parts of a mir constant of kind ADT or array.
395 #[derive(Copy, Clone, Debug, HashStable)]
396 pub struct DestructuredConstant<'tcx> {
397 pub variant: Option<VariantIdx>,
398 pub fields: &'tcx [ConstantKind<'tcx>],
399 }
400
401 /// Coverage information summarized from a MIR if instrumented for source code coverage (see
402 /// compiler option `-Cinstrument-coverage`). This information is generated by the
403 /// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query.
404 #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)]
405 pub struct CoverageInfo {
406 /// The total number of coverage region counters added to the MIR `Body`.
407 pub num_counters: u32,
408
409 /// The total number of coverage region counter expressions added to the MIR `Body`.
410 pub num_expressions: u32,
411 }
412
413 /// Shims which make dealing with `WithOptConstParam` easier.
414 ///
415 /// For more information on why this is needed, consider looking
416 /// at the docs for `WithOptConstParam` itself.
417 impl<'tcx> TyCtxt<'tcx> {
418 #[inline]
419 pub fn mir_const_qualif_opt_const_arg(
420 self,
421 def: ty::WithOptConstParam<LocalDefId>,
422 ) -> ConstQualifs {
423 if let Some(param_did) = def.const_param_did {
424 self.mir_const_qualif_const_arg((def.did, param_did))
425 } else {
426 self.mir_const_qualif(def.did)
427 }
428 }
429
430 #[inline]
431 pub fn promoted_mir_opt_const_arg(
432 self,
433 def: ty::WithOptConstParam<DefId>,
434 ) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
435 if let Some((did, param_did)) = def.as_const_arg() {
436 self.promoted_mir_of_const_arg((did, param_did))
437 } else {
438 self.promoted_mir(def.did)
439 }
440 }
441
442 #[inline]
443 pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam<DefId>) -> &'tcx Body<'tcx> {
444 if let Some((did, param_did)) = def.as_const_arg() {
445 self.mir_for_ctfe_of_const_arg((did, param_did))
446 } else {
447 self.mir_for_ctfe(def.did)
448 }
449 }
450 }