1 //! Values computed by queries that use MIR.
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;
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;
14 use rustc_target::abi::VariantIdx;
15 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 {
39 AssignToDroppingUnionField,
41 MutationOfLayoutConstrainedField,
42 BorrowOfLayoutConstrainedField,
46 impl UnsafetyViolationDetails {
47 pub fn description_and_note(&self) -> (&'static str, &'static str) {
48 use UnsafetyViolationDetails::*;
50 CallToUnsafeFunction => (
51 "call to unsafe function",
52 "consult the function's documentation for information on how to avoid undefined \
55 UseOfInlineAssembly => (
56 "use of inline assembly",
57 "inline assembly is entirely unchecked and can cause undefined behavior",
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",
64 CastOfPointerToInt => {
65 ("cast of pointer to int", "casting pointers to integers in constants")
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",
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",
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",
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",
87 AccessToUnionField => (
88 "access to union field",
89 "the field may not be properly initialized: using uninitialized data will cause \
92 MutationOfLayoutConstrainedField => (
93 "mutation of layout constrained field",
94 "mutating layout constrained fields cannot statically be checked for valid values",
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",
101 CallToFunctionWith => (
102 "call to function with `#[target_feature]`",
103 "can only be called if the required target features are available",
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,
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)]>,
126 rustc_index::newtype_index! {
127 pub struct GeneratorSavedLocal {
129 DEBUG_FORMAT = "_{}",
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>>,
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>>,
143 /// The source that led to each variant being created (usually, a yield or
145 pub variant_source_info: IndexVec<VariantIdx, SourceInfo>,
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
150 pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
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))))
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()
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)
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);
179 write!(fmt, "{:9}({:?})", variant_name, self.0)
181 write!(fmt, "{}", variant_name)
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)
194 fmt.debug_struct("GeneratorLayout")
195 .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated()))
201 .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))),
204 .field("storage_conflicts", &self.storage_conflicts)
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>,
220 /// The result of the `mir_const_qualif` query.
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
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,
231 pub tainted_by_errors: Option<ErrorReported>,
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.
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.
248 /// Example: If type check produces a closure with the closure substs:
251 /// ClosureSubsts = [
252 /// 'a, // From the parent.
254 /// i8, // the "closure kind"
255 /// for<'x> fn(&'<erased> &'x u32) -> &'x u32, // the "closure signature"
256 /// &'<erased> String, // some upvar
260 /// We would "renumber" each free region to a unique vid, as follows:
263 /// ClosureSubsts = [
264 /// '1, // From the parent.
266 /// i8, // the "closure kind"
267 /// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature"
268 /// &'4 String, // some upvar
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.
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
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
290 pub num_external_vids: usize,
292 /// Requirements between the various free regions defined in
294 pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
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>,
304 // ... must outlive this one.
305 pub outlived_free_region: ty::RegionVid,
307 // If not, report an error here ...
308 pub blame_span: Span,
310 // ... due to this reason.
311 pub category: ConstraintCategory,
314 // Make sure this enum doesn't unintentionally grow
315 rustc_data_structures::static_assert_size!(ConstraintCategory, 12);
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.
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),
332 /// A constraint that came from checking the body of a closure.
334 /// We try to get the category that the closure used when reporting this.
340 /// A constraint that came from a usage of a variable (e.g. in an ADT expression
341 /// like `Foo { field: my_val }`)
344 ClosureUpvar(hir::HirId),
346 /// A constraint from a user-written predicate
347 /// with the provided span, written on the item
348 /// with the given `DefId`
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.
355 // Boring and applicable everywhere.
358 /// A constraint that doesn't correspond to anything the user sees.
362 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
363 #[derive(TyEncodable, TyDecodable, HashStable)]
364 pub enum ReturnConstraint {
366 ClosureUpvar(hir::HirId),
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`.
377 /// The type here is guaranteed not to contain any free regions at
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),
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>],
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,
401 /// The total number of coverage region counter expressions added to the MIR `Body`.
402 pub num_expressions: u32,
405 /// Shims which make dealing with `WithOptConstParam` easier.
407 /// For more information on why this is needed, consider looking
408 /// at the docs for `WithOptConstParam` itself.
409 impl<'tcx> TyCtxt<'tcx> {
411 pub fn mir_const_qualif_opt_const_arg(
413 def: ty::WithOptConstParam<LocalDefId>,
415 if let Some(param_did) = def.const_param_did {
416 self.mir_const_qualif_const_arg((def.did, param_did))
418 self.mir_const_qualif(def.did)
423 pub fn promoted_mir_opt_const_arg(
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))
430 self.promoted_mir(def.did)
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))
439 self.mir_for_ctfe(def.did)