1 //! Values computed by queries that use MIR.
3 use crate::mir::{Body, Promoted};
4 use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
5 use rustc_data_structures::stable_map::FxHashMap;
6 use rustc_data_structures::vec_map::VecMap;
7 use rustc_errors::ErrorGuaranteed;
9 use rustc_hir::def_id::{DefId, LocalDefId};
10 use rustc_index::bit_set::BitMatrix;
11 use rustc_index::vec::IndexVec;
13 use rustc_target::abi::VariantIdx;
14 use smallvec::SmallVec;
17 use std::fmt::{self, Debug};
19 use super::{Field, SourceInfo};
21 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
22 pub enum UnsafetyViolationKind {
23 /// Unsafe operation outside `unsafe`.
25 /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block.
26 /// Has to be handled as a lint for backwards compatibility.
30 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
31 pub enum UnsafetyViolationDetails {
32 CallToUnsafeFunction(Option<DefId>),
39 AssignToDroppingUnionField,
41 MutationOfLayoutConstrainedField,
42 BorrowOfLayoutConstrainedField,
43 CallToFunctionWith(DefId),
46 impl UnsafetyViolationDetails {
47 pub fn simple_description(&self) -> &'static str {
48 use UnsafetyViolationDetails::*;
51 CallToUnsafeFunction(..) => "call to unsafe function",
52 UseOfInlineAssembly => "use of inline assembly",
53 InitializingTypeWith => "initializing type with `rustc_layout_scalar_valid_range` attr",
54 CastOfPointerToInt => "cast of pointer to int",
55 UseOfMutableStatic => "use of mutable static",
56 UseOfExternStatic => "use of extern static",
57 DerefOfRawPointer => "dereference of raw pointer",
58 AssignToDroppingUnionField => "assignment to union field that might need dropping",
59 AccessToUnionField => "access to union field",
60 MutationOfLayoutConstrainedField => "mutation of layout constrained field",
61 BorrowOfLayoutConstrainedField => {
62 "borrow of layout constrained field with interior mutability"
64 CallToFunctionWith(..) => "call to function with `#[target_feature]`",
68 pub fn description_and_note(&self, tcx: TyCtxt<'_>) -> (Cow<'static, str>, &'static str) {
69 use UnsafetyViolationDetails::*;
71 CallToUnsafeFunction(did) => (
72 if let Some(did) = did {
73 Cow::from(format!("call to unsafe function `{}`", tcx.def_path_str(*did)))
75 Cow::Borrowed(self.simple_description())
77 "consult the function's documentation for information on how to avoid undefined \
80 UseOfInlineAssembly => (
81 Cow::Borrowed(self.simple_description()),
82 "inline assembly is entirely unchecked and can cause undefined behavior",
84 InitializingTypeWith => (
85 Cow::Borrowed(self.simple_description()),
86 "initializing a layout restricted type's field with a value outside the valid \
87 range is undefined behavior",
89 CastOfPointerToInt => (
90 Cow::Borrowed(self.simple_description()),
91 "casting pointers to integers in constants",
93 UseOfMutableStatic => (
94 Cow::Borrowed(self.simple_description()),
95 "mutable statics can be mutated by multiple threads: aliasing violations or data \
96 races will cause undefined behavior",
98 UseOfExternStatic => (
99 Cow::Borrowed(self.simple_description()),
100 "extern statics are not controlled by the Rust type system: invalid data, \
101 aliasing violations or data races will cause undefined behavior",
103 DerefOfRawPointer => (
104 Cow::Borrowed(self.simple_description()),
105 "raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
106 and cause data races: all of these are undefined behavior",
108 AssignToDroppingUnionField => (
109 Cow::Borrowed(self.simple_description()),
110 "the previous content of the field will be dropped, which causes undefined \
111 behavior if the field was not properly initialized",
113 AccessToUnionField => (
114 Cow::Borrowed(self.simple_description()),
115 "the field may not be properly initialized: using uninitialized data will cause \
118 MutationOfLayoutConstrainedField => (
119 Cow::Borrowed(self.simple_description()),
120 "mutating layout constrained fields cannot statically be checked for valid values",
122 BorrowOfLayoutConstrainedField => (
123 Cow::Borrowed(self.simple_description()),
124 "references to fields of layout constrained fields lose the constraints. Coupled \
125 with interior mutability, the field can be changed to invalid values",
127 CallToFunctionWith(did) => (
129 "call to function `{}` with `#[target_feature]`",
130 tcx.def_path_str(*did)
132 "can only be called if the required target features are available",
138 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
139 pub struct UnsafetyViolation {
140 pub source_info: SourceInfo,
141 pub lint_root: hir::HirId,
142 pub kind: UnsafetyViolationKind,
143 pub details: UnsafetyViolationDetails,
146 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
147 pub enum UnusedUnsafe {
148 /// `unsafe` block contains no unsafe operations
149 /// > ``unnecessary `unsafe` block``
151 /// `unsafe` block nested under another (used) `unsafe` block
152 /// > ``… because it's nested under this `unsafe` block``
153 InUnsafeBlock(hir::HirId),
154 /// `unsafe` block nested under `unsafe fn`
155 /// > ``… because it's nested under this `unsafe fn` ``
157 /// the second HirId here indicates the first usage of the `unsafe` block,
158 /// which allows retrieval of the LintLevelSource for why that operation would
159 /// have been permitted without the block
160 InUnsafeFn(hir::HirId, hir::HirId),
163 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
164 pub enum UsedUnsafeBlockData {
165 SomeDisallowedInUnsafeFn,
166 // the HirId here indicates the first usage of the `unsafe` block
167 // (i.e. the one that's first encountered in the MIR traversal of the unsafety check)
168 AllAllowedInUnsafeFn(hir::HirId),
171 #[derive(TyEncodable, TyDecodable, HashStable, Debug)]
172 pub struct UnsafetyCheckResult {
173 /// Violations that are propagated *upwards* from this function.
174 pub violations: Vec<UnsafetyViolation>,
176 /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint.
178 /// The keys are the used `unsafe` blocks, the UnusedUnsafeKind indicates whether
179 /// or not any of the usages happen at a place that doesn't allow `unsafe_op_in_unsafe_fn`.
180 pub used_unsafe_blocks: FxHashMap<hir::HirId, UsedUnsafeBlockData>,
182 /// This is `Some` iff the item is not a closure.
183 pub unused_unsafes: Option<Vec<(hir::HirId, UnusedUnsafe)>>,
186 rustc_index::newtype_index! {
187 pub struct GeneratorSavedLocal {
189 DEBUG_FORMAT = "_{}",
193 /// The layout of generator state.
194 #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
195 pub struct GeneratorLayout<'tcx> {
196 /// The type of every local stored inside the generator.
197 pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
199 /// Which of the above fields are in each variant. Note that one field may
200 /// be stored in multiple variants.
201 pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
203 /// The source that led to each variant being created (usually, a yield or
205 pub variant_source_info: IndexVec<VariantIdx, SourceInfo>,
207 /// Which saved locals are storage-live at the same time. Locals that do not
208 /// have conflicts with each other are allowed to overlap in the computed
210 pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
213 impl Debug for GeneratorLayout<'_> {
214 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
215 /// Prints an iterator of (key, value) tuples as a map.
216 struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>);
217 impl<'a, K, V> MapPrinter<'a, K, V> {
218 fn new(iter: impl Iterator<Item = (K, V)> + 'a) -> Self {
219 Self(Cell::new(Some(Box::new(iter))))
222 impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> {
223 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
224 fmt.debug_map().entries(self.0.take().unwrap()).finish()
228 /// Prints the generator variant name.
229 struct GenVariantPrinter(VariantIdx);
230 impl From<VariantIdx> for GenVariantPrinter {
231 fn from(idx: VariantIdx) -> Self {
232 GenVariantPrinter(idx)
235 impl Debug for GenVariantPrinter {
236 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
237 let variant_name = ty::GeneratorSubsts::variant_name(self.0);
239 write!(fmt, "{:9}({:?})", variant_name, self.0)
241 write!(fmt, "{}", variant_name)
246 /// Forces its contents to print in regular mode instead of alternate mode.
247 struct OneLinePrinter<T>(T);
248 impl<T: Debug> Debug for OneLinePrinter<T> {
249 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
250 write!(fmt, "{:?}", self.0)
254 fmt.debug_struct("GeneratorLayout")
255 .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated()))
261 .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))),
264 .field("storage_conflicts", &self.storage_conflicts)
269 #[derive(Debug, TyEncodable, TyDecodable, HashStable)]
270 pub struct BorrowCheckResult<'tcx> {
271 /// All the opaque types that are restricted to concrete types
272 /// by this function. Unlike the value in `TypeckResults`, this has
273 /// unerased regions.
274 pub concrete_opaque_types: VecMap<DefId, OpaqueHiddenType<'tcx>>,
275 pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
276 pub used_mut_upvars: SmallVec<[Field; 8]>,
277 pub tainted_by_errors: Option<ErrorGuaranteed>,
280 /// The result of the `mir_const_qualif` query.
282 /// Each field (except `error_occurred`) corresponds to an implementer of the `Qualif` trait in
283 /// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each
285 #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)]
286 pub struct ConstQualifs {
287 pub has_mut_interior: bool,
288 pub needs_drop: bool,
289 pub needs_non_const_drop: bool,
291 pub tainted_by_errors: Option<ErrorGuaranteed>,
294 /// After we borrow check a closure, we are left with various
295 /// requirements that we have inferred between the free regions that
296 /// appear in the closure's signature or on its field types. These
297 /// requirements are then verified and proved by the closure's
298 /// creating function. This struct encodes those requirements.
300 /// The requirements are listed as being between various `RegionVid`. The 0th
301 /// region refers to `'static`; subsequent region vids refer to the free
302 /// regions that appear in the closure (or generator's) type, in order of
303 /// appearance. (This numbering is actually defined by the `UniversalRegions`
304 /// struct in the NLL region checker. See for example
305 /// `UniversalRegions::closure_mapping`.) Note the free regions in the
306 /// closure's signature and captures are erased.
308 /// Example: If type check produces a closure with the closure substs:
311 /// ClosureSubsts = [
312 /// 'a, // From the parent.
314 /// i8, // the "closure kind"
315 /// for<'x> fn(&'<erased> &'x u32) -> &'x u32, // the "closure signature"
316 /// &'<erased> String, // some upvar
320 /// We would "renumber" each free region to a unique vid, as follows:
323 /// ClosureSubsts = [
324 /// '1, // From the parent.
326 /// i8, // the "closure kind"
327 /// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature"
328 /// &'4 String, // some upvar
332 /// Now the code might impose a requirement like `'1: '2`. When an
333 /// instance of the closure is created, the corresponding free regions
334 /// can be extracted from its type and constrained to have the given
335 /// outlives relationship.
337 /// In some cases, we have to record outlives requirements between types and
338 /// regions as well. In that case, if those types include any regions, those
339 /// regions are recorded using their external names (`ReStatic`,
340 /// `ReEarlyBound`, `ReFree`). We use these because in a query response we
341 /// cannot use `ReVar` (which is what we use internally within the rest of the
343 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
344 pub struct ClosureRegionRequirements<'tcx> {
345 /// The number of external regions defined on the closure. In our
346 /// example above, it would be 3 -- one for `'static`, then `'1`
347 /// and `'2`. This is just used for a sanity check later on, to
348 /// make sure that the number of regions we see at the callsite
350 pub num_external_vids: usize,
352 /// Requirements between the various free regions defined in
354 pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
357 /// Indicates an outlives-constraint between a type or between two
358 /// free regions declared on the closure.
359 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
360 pub struct ClosureOutlivesRequirement<'tcx> {
361 // This region or type ...
362 pub subject: ClosureOutlivesSubject<'tcx>,
364 // ... must outlive this one.
365 pub outlived_free_region: ty::RegionVid,
367 // If not, report an error here ...
368 pub blame_span: Span,
370 // ... due to this reason.
371 pub category: ConstraintCategory,
374 // Make sure this enum doesn't unintentionally grow
375 rustc_data_structures::static_assert_size!(ConstraintCategory, 12);
377 /// Outlives-constraints can be categorized to determine whether and why they
378 /// are interesting (for error reporting). Order of variants indicates sort
379 /// order of the category, thereby influencing diagnostic output.
381 /// See also `rustc_const_eval::borrow_check::constraints`.
382 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
383 #[derive(TyEncodable, TyDecodable, HashStable)]
384 pub enum ConstraintCategory {
385 Return(ReturnConstraint),
392 /// A constraint that came from checking the body of a closure.
394 /// We try to get the category that the closure used when reporting this.
400 /// A constraint that came from a usage of a variable (e.g. in an ADT expression
401 /// like `Foo { field: my_val }`)
406 /// A constraint from a user-written predicate
407 /// with the provided span, written on the item
408 /// with the given `DefId`
411 /// A "boring" constraint (caused by the given location) is one that
412 /// the user probably doesn't want to see described in diagnostics,
413 /// because it is kind of an artifact of the type system setup.
415 // Boring and applicable everywhere.
418 /// A constraint that doesn't correspond to anything the user sees.
422 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
423 #[derive(TyEncodable, TyDecodable, HashStable)]
424 pub enum ReturnConstraint {
429 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
430 /// that must outlive some region.
431 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
432 pub enum ClosureOutlivesSubject<'tcx> {
433 /// Subject is a type, typically a type parameter, but could also
434 /// be a projection. Indicates a requirement like `T: 'a` being
435 /// passed to the caller, where the type here is `T`.
437 /// The type here is guaranteed not to contain any free regions at
441 /// Subject is a free region from the closure. Indicates a requirement
442 /// like `'a: 'b` being passed to the caller; the region here is `'a`.
443 Region(ty::RegionVid),
446 /// The constituent parts of an ADT or array.
447 #[derive(Copy, Clone, Debug, HashStable)]
448 pub struct DestructuredConst<'tcx> {
449 pub variant: Option<VariantIdx>,
450 pub fields: &'tcx [ty::Const<'tcx>],
453 /// Coverage information summarized from a MIR if instrumented for source code coverage (see
454 /// compiler option `-Cinstrument-coverage`). This information is generated by the
455 /// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query.
456 #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)]
457 pub struct CoverageInfo {
458 /// The total number of coverage region counters added to the MIR `Body`.
459 pub num_counters: u32,
461 /// The total number of coverage region counter expressions added to the MIR `Body`.
462 pub num_expressions: u32,
465 /// Shims which make dealing with `WithOptConstParam` easier.
467 /// For more information on why this is needed, consider looking
468 /// at the docs for `WithOptConstParam` itself.
469 impl<'tcx> TyCtxt<'tcx> {
471 pub fn mir_const_qualif_opt_const_arg(
473 def: ty::WithOptConstParam<LocalDefId>,
475 if let Some(param_did) = def.const_param_did {
476 self.mir_const_qualif_const_arg((def.did, param_did))
478 self.mir_const_qualif(def.did)
483 pub fn promoted_mir_opt_const_arg(
485 def: ty::WithOptConstParam<DefId>,
486 ) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
487 if let Some((did, param_did)) = def.as_const_arg() {
488 self.promoted_mir_of_const_arg((did, param_did))
490 self.promoted_mir(def.did)
495 pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam<DefId>) -> &'tcx Body<'tcx> {
496 if let Some((did, param_did)) = def.as_const_arg() {
497 self.mir_for_ctfe_of_const_arg((did, param_did))
499 self.mir_for_ctfe(def.did)