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]>,
219 /// The result of the `mir_const_qualif` query.
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
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,
230 pub error_occured: Option<ErrorReported>,
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.
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.
247 /// Example: If type check produces a closure with the closure substs:
250 /// ClosureSubsts = [
251 /// 'a, // From the parent.
253 /// i8, // the "closure kind"
254 /// for<'x> fn(&'<erased> &'x u32) -> &'x u32, // the "closure signature"
255 /// &'<erased> String, // some upvar
259 /// We would "renumber" each free region to a unique vid, as follows:
262 /// ClosureSubsts = [
263 /// '1, // From the parent.
265 /// i8, // the "closure kind"
266 /// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature"
267 /// &'4 String, // some upvar
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.
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
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
289 pub num_external_vids: usize,
291 /// Requirements between the various free regions defined in
293 pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
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>,
303 // ... must outlive this one.
304 pub outlived_free_region: ty::RegionVid,
306 // If not, report an error here ...
307 pub blame_span: Span,
309 // ... due to this reason.
310 pub category: ConstraintCategory,
313 // Make sure this enum doesn't unintentionally grow
314 rustc_data_structures::static_assert_size!(ConstraintCategory, 12);
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.
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),
331 /// A constraint that came from checking the body of a closure.
333 /// We try to get the category that the closure used when reporting this.
339 /// A constraint that came from a usage of a variable (e.g. in an ADT expression
340 /// like `Foo { field: my_val }`)
343 ClosureUpvar(hir::HirId),
345 /// A constraint from a user-written predicate
346 /// with the provided span, written on the item
347 /// with the given `DefId`
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.
354 // Boring and applicable everywhere.
357 /// A constraint that doesn't correspond to anything the user sees.
361 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
362 #[derive(TyEncodable, TyDecodable, HashStable)]
363 pub enum ReturnConstraint {
365 ClosureUpvar(hir::HirId),
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`.
376 /// The type here is guaranteed not to contain any free regions at
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),
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>],
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,
400 /// The total number of coverage region counter expressions added to the MIR `Body`.
401 pub num_expressions: u32,
404 /// Shims which make dealing with `WithOptConstParam` easier.
406 /// For more information on why this is needed, consider looking
407 /// at the docs for `WithOptConstParam` itself.
408 impl<'tcx> TyCtxt<'tcx> {
410 pub fn mir_const_qualif_opt_const_arg(
412 def: ty::WithOptConstParam<LocalDefId>,
414 if let Some(param_did) = def.const_param_did {
415 self.mir_const_qualif_const_arg((def.did, param_did))
417 self.mir_const_qualif(def.did)
422 pub fn promoted_mir_opt_const_arg(
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))
429 self.promoted_mir(def.did)
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))
438 self.mir_for_ctfe(def.did)