1 //! Values computed by queries that use MIR.
3 use crate::mir::{abstract_const, Body, Promoted};
4 use crate::ty::{self, Ty, TyCtxt};
5 use rustc_data_structures::fx::FxHashMap;
6 use rustc_data_structures::sync::Lrc;
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;
13 use rustc_target::abi::VariantIdx;
14 use smallvec::SmallVec;
16 use std::fmt::{self, Debug};
18 use super::{Field, SourceInfo};
20 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
21 pub enum UnsafetyViolationKind {
22 /// Only permitted in regular `fn`s, prohibited in `const fn`s.
24 /// Permitted both in `const fn`s and regular `fn`s.
26 /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block.
27 /// Has to be handled as a lint for backwards compatibility.
31 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
32 pub enum UnsafetyViolationDetails {
41 AssignToDroppingUnionField,
43 MutationOfLayoutConstrainedField,
44 BorrowOfLayoutConstrainedField,
48 impl UnsafetyViolationDetails {
49 pub fn description_and_note(&self) -> (&'static str, &'static str) {
50 use UnsafetyViolationDetails::*;
52 CallToUnsafeFunction => (
53 "call to unsafe function",
54 "consult the function's documentation for information on how to avoid undefined \
57 UseOfInlineAssembly => (
58 "use of inline assembly",
59 "inline assembly is entirely unchecked and can cause undefined behavior",
61 InitializingTypeWith => (
62 "initializing type with `rustc_layout_scalar_valid_range` attr",
63 "initializing a layout restricted type's field with a value outside the valid \
64 range is undefined behavior",
66 CastOfPointerToInt => {
67 ("cast of pointer to int", "casting pointers to integers in constants")
69 BorrowOfPackedField => (
70 "borrow of packed field",
71 "fields of packed structs might be misaligned: dereferencing a misaligned pointer \
72 or even just creating a misaligned reference is undefined behavior",
74 UseOfMutableStatic => (
75 "use of mutable static",
76 "mutable statics can be mutated by multiple threads: aliasing violations or data \
77 races will cause undefined behavior",
79 UseOfExternStatic => (
80 "use of extern static",
81 "extern statics are not controlled by the Rust type system: invalid data, \
82 aliasing violations or data races will cause undefined behavior",
84 DerefOfRawPointer => (
85 "dereference of raw pointer",
86 "raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules \
87 and cause data races: all of these are undefined behavior",
89 AssignToDroppingUnionField => (
90 "assignment to union field that might need dropping",
91 "the previous content of the field will be dropped, which causes undefined \
92 behavior if the field was not properly initialized",
94 AccessToUnionField => (
95 "access to union field",
96 "the field may not be properly initialized: using uninitialized data will cause \
99 MutationOfLayoutConstrainedField => (
100 "mutation of layout constrained field",
101 "mutating layout constrained fields cannot statically be checked for valid values",
103 BorrowOfLayoutConstrainedField => (
104 "borrow of layout constrained field with interior mutability",
105 "references to fields of layout constrained fields lose the constraints. Coupled \
106 with interior mutability, the field can be changed to invalid values",
108 CallToFunctionWith => (
109 "call to function with `#[target_feature]`",
110 "can only be called if the required target features are available",
116 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
117 pub struct UnsafetyViolation {
118 pub source_info: SourceInfo,
119 pub lint_root: hir::HirId,
120 pub kind: UnsafetyViolationKind,
121 pub details: UnsafetyViolationDetails,
124 #[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
125 pub struct UnsafetyCheckResult {
126 /// Violations that are propagated *upwards* from this function.
127 pub violations: Lrc<[UnsafetyViolation]>,
128 /// `unsafe` blocks in this function, along with whether they are used. This is
129 /// used for the "unused_unsafe" lint.
130 pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>,
133 rustc_index::newtype_index! {
134 pub struct GeneratorSavedLocal {
136 DEBUG_FORMAT = "_{}",
140 /// The layout of generator state.
141 #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
142 pub struct GeneratorLayout<'tcx> {
143 /// The type of every local stored inside the generator.
144 pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
146 /// Which of the above fields are in each variant. Note that one field may
147 /// be stored in multiple variants.
148 pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
150 /// The source that led to each variant being created (usually, a yield or
152 pub variant_source_info: IndexVec<VariantIdx, SourceInfo>,
154 /// Which saved locals are storage-live at the same time. Locals that do not
155 /// have conflicts with each other are allowed to overlap in the computed
157 pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
160 impl Debug for GeneratorLayout<'_> {
161 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
162 /// Prints an iterator of (key, value) tuples as a map.
163 struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>);
164 impl<'a, K, V> MapPrinter<'a, K, V> {
165 fn new(iter: impl Iterator<Item = (K, V)> + 'a) -> Self {
166 Self(Cell::new(Some(Box::new(iter))))
169 impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> {
170 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
171 fmt.debug_map().entries(self.0.take().unwrap()).finish()
175 /// Prints the generator variant name.
176 struct GenVariantPrinter(VariantIdx);
177 impl From<VariantIdx> for GenVariantPrinter {
178 fn from(idx: VariantIdx) -> Self {
179 GenVariantPrinter(idx)
182 impl Debug for GenVariantPrinter {
183 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
184 let variant_name = ty::GeneratorSubsts::variant_name(self.0);
186 write!(fmt, "{:9}({:?})", variant_name, self.0)
188 write!(fmt, "{}", variant_name)
193 /// Forces its contents to print in regular mode instead of alternate mode.
194 struct OneLinePrinter<T>(T);
195 impl<T: Debug> Debug for OneLinePrinter<T> {
196 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
197 write!(fmt, "{:?}", self.0)
201 fmt.debug_struct("GeneratorLayout")
202 .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated()))
208 .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))),
211 .field("storage_conflicts", &self.storage_conflicts)
216 #[derive(Debug, TyEncodable, TyDecodable, HashStable)]
217 pub struct BorrowCheckResult<'tcx> {
218 /// All the opaque types that are restricted to concrete types
219 /// by this function. Unlike the value in `TypeckResults`, this has
220 /// unerased regions.
221 pub concrete_opaque_types: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
222 pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
223 pub used_mut_upvars: SmallVec<[Field; 8]>,
226 /// The result of the `mir_const_qualif` query.
228 /// Each field (except `error_occured`) corresponds to an implementer of the `Qualif` trait in
229 /// `rustc_mir/src/transform/check_consts/qualifs.rs`. See that file for more information on each
231 #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)]
232 pub struct ConstQualifs {
233 pub has_mut_interior: bool,
234 pub needs_drop: bool,
236 pub error_occured: Option<ErrorReported>,
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.
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.
253 /// Example: If type check produces a closure with the closure substs:
256 /// ClosureSubsts = [
257 /// 'a, // From the parent.
259 /// i8, // the "closure kind"
260 /// for<'x> fn(&'<erased> &'x u32) -> &'x u32, // the "closure signature"
261 /// &'<erased> String, // some upvar
265 /// We would "renumber" each free region to a unique vid, as follows:
268 /// ClosureSubsts = [
269 /// '1, // From the parent.
271 /// i8, // the "closure kind"
272 /// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature"
273 /// &'4 String, // some upvar
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.
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
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
295 pub num_external_vids: usize,
297 /// Requirements between the various free regions defined in
299 pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
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>,
309 // ... must outlive this one.
310 pub outlived_free_region: ty::RegionVid,
312 // If not, report an error here ...
313 pub blame_span: Span,
315 // ... due to this reason.
316 pub category: ConstraintCategory,
319 /// Outlives-constraints can be categorized to determine whether and why they
320 /// are interesting (for error reporting). Order of variants indicates sort
321 /// order of the category, thereby influencing diagnostic output.
323 /// See also `rustc_mir::borrow_check::constraints`.
324 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
325 #[derive(TyEncodable, TyDecodable, HashStable)]
326 pub enum ConstraintCategory {
327 Return(ReturnConstraint),
334 /// A constraint that came from checking the body of a closure.
336 /// We try to get the category that the closure used when reporting this.
343 ClosureUpvar(hir::HirId),
345 /// A "boring" constraint (caused by the given location) is one that
346 /// the user probably doesn't want to see described in diagnostics,
347 /// because it is kind of an artifact of the type system setup.
348 /// Example: `x = Foo { field: y }` technically creates
349 /// intermediate regions representing the "type of `Foo { field: y
350 /// }`", and data flows from `y` into those variables, but they
351 /// are not very interesting. The assignment into `x` on the other
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)
443 pub fn mir_abstract_const_opt_const_arg(
445 def: ty::WithOptConstParam<DefId>,
446 ) -> Result<Option<&'tcx [abstract_const::Node<'tcx>]>, ErrorReported> {
447 if let Some((did, param_did)) = def.as_const_arg() {
448 self.mir_abstract_const_of_const_arg((did, param_did))
450 self.mir_abstract_const(def.did)