1 //! Values computed by queries that use MIR.
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
;
9 use rustc_hir
::def_id
::{DefId, LocalDefId}
;
10 use rustc_index
::bit_set
::BitMatrix
;
11 use rustc_index
::vec
::{Idx, 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 /// Unsafe operation outside `unsafe`.
24 /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block.
25 /// Has to be handled as a lint for backwards compatibility.
29 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
30 pub enum UnsafetyViolationDetails
{
39 MutationOfLayoutConstrainedField
,
40 BorrowOfLayoutConstrainedField
,
44 impl UnsafetyViolationDetails
{
45 pub fn description_and_note(&self) -> (&'
static str, &'
static str) {
46 use UnsafetyViolationDetails
::*;
48 CallToUnsafeFunction
=> (
49 "call to unsafe function",
50 "consult the function's documentation for information on how to avoid undefined \
53 UseOfInlineAssembly
=> (
54 "use of inline assembly",
55 "inline assembly is entirely unchecked and can cause undefined behavior",
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",
62 CastOfPointerToInt
=> {
63 ("cast of pointer to int", "casting pointers to integers in constants")
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",
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",
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",
80 AccessToUnionField
=> (
81 "access to union field",
82 "the field may not be properly initialized: using uninitialized data will cause \
85 MutationOfLayoutConstrainedField
=> (
86 "mutation of layout constrained field",
87 "mutating layout constrained fields cannot statically be checked for valid values",
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",
94 CallToFunctionWith
=> (
95 "call to function with `#[target_feature]`",
96 "can only be called if the required target features are available",
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
,
110 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
111 pub enum UnusedUnsafe
{
112 /// `unsafe` block contains no unsafe operations
113 /// > ``unnecessary `unsafe` block``
115 /// `unsafe` block nested under another (used) `unsafe` block
116 /// > ``… because it's nested under this `unsafe` block``
117 InUnsafeBlock(hir
::HirId
),
120 #[derive(TyEncodable, TyDecodable, HashStable, Debug)]
121 pub struct UnsafetyCheckResult
{
122 /// Violations that are propagated *upwards* from this function.
123 pub violations
: Vec
<UnsafetyViolation
>,
125 /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint.
126 pub used_unsafe_blocks
: FxHashSet
<hir
::HirId
>,
128 /// This is `Some` iff the item is not a closure.
129 pub unused_unsafes
: Option
<Vec
<(hir
::HirId
, UnusedUnsafe
)>>,
132 rustc_index
::newtype_index
! {
133 #[derive(HashStable)]
134 #[debug_format = "_{}"]
135 pub struct GeneratorSavedLocal {}
138 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
139 pub struct GeneratorSavedTy
<'tcx
> {
141 /// Source info corresponding to the local in the original MIR body.
142 pub source_info
: SourceInfo
,
143 /// Whether the local should be ignored for trait bound computations.
144 pub ignore_for_traits
: bool
,
147 /// The layout of generator state.
148 #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
149 pub struct GeneratorLayout
<'tcx
> {
150 /// The type of every local stored inside the generator.
151 pub field_tys
: IndexVec
<GeneratorSavedLocal
, GeneratorSavedTy
<'tcx
>>,
153 /// Which of the above fields are in each variant. Note that one field may
154 /// be stored in multiple variants.
155 pub variant_fields
: IndexVec
<VariantIdx
, IndexVec
<Field
, GeneratorSavedLocal
>>,
157 /// The source that led to each variant being created (usually, a yield or
159 pub variant_source_info
: IndexVec
<VariantIdx
, SourceInfo
>,
161 /// Which saved locals are storage-live at the same time. Locals that do not
162 /// have conflicts with each other are allowed to overlap in the computed
164 #[type_foldable(identity)]
165 #[type_visitable(ignore)]
166 pub storage_conflicts
: BitMatrix
<GeneratorSavedLocal
, GeneratorSavedLocal
>,
169 impl Debug
for GeneratorLayout
<'_
> {
170 fn fmt(&self, fmt
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
171 /// Prints an iterator of (key, value) tuples as a map.
172 struct MapPrinter
<'a
, K
, V
>(Cell
<Option
<Box
<dyn Iterator
<Item
= (K
, V
)> + 'a
>>>);
173 impl<'a
, K
, V
> MapPrinter
<'a
, K
, V
> {
174 fn new(iter
: impl Iterator
<Item
= (K
, V
)> + 'a
) -> Self {
175 Self(Cell
::new(Some(Box
::new(iter
))))
178 impl<'a
, K
: Debug
, V
: Debug
> Debug
for MapPrinter
<'a
, K
, V
> {
179 fn fmt(&self, fmt
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
180 fmt
.debug_map().entries(self.0.take().unwrap()).finish()
184 /// Prints the generator variant name.
185 struct GenVariantPrinter(VariantIdx
);
186 impl From
<VariantIdx
> for GenVariantPrinter
{
187 fn from(idx
: VariantIdx
) -> Self {
188 GenVariantPrinter(idx
)
191 impl Debug
for GenVariantPrinter
{
192 fn fmt(&self, fmt
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
193 let variant_name
= ty
::GeneratorSubsts
::variant_name(self.0);
195 write
!(fmt
, "{:9}({:?})", variant_name
, self.0)
197 write
!(fmt
, "{}", variant_name
)
202 /// Forces its contents to print in regular mode instead of alternate mode.
203 struct OneLinePrinter
<T
>(T
);
204 impl<T
: Debug
> Debug
for OneLinePrinter
<T
> {
205 fn fmt(&self, fmt
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
206 write
!(fmt
, "{:?}", self.0)
210 fmt
.debug_struct("GeneratorLayout")
211 .field("field_tys", &MapPrinter
::new(self.field_tys
.iter_enumerated()))
217 .map(|(k
, v
)| (GenVariantPrinter(k
), OneLinePrinter(v
))),
220 .field("storage_conflicts", &self.storage_conflicts
)
225 #[derive(Debug, TyEncodable, TyDecodable, HashStable)]
226 pub struct BorrowCheckResult
<'tcx
> {
227 /// All the opaque types that are restricted to concrete types
228 /// by this function. Unlike the value in `TypeckResults`, this has
229 /// unerased regions.
230 pub concrete_opaque_types
: VecMap
<LocalDefId
, OpaqueHiddenType
<'tcx
>>,
231 pub closure_requirements
: Option
<ClosureRegionRequirements
<'tcx
>>,
232 pub used_mut_upvars
: SmallVec
<[Field
; 8]>,
233 pub tainted_by_errors
: Option
<ErrorGuaranteed
>,
236 /// The result of the `mir_const_qualif` query.
238 /// Each field (except `error_occurred`) corresponds to an implementer of the `Qualif` trait in
239 /// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each
241 #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)]
242 pub struct ConstQualifs
{
243 pub has_mut_interior
: bool
,
244 pub needs_drop
: bool
,
245 pub needs_non_const_drop
: bool
,
247 pub tainted_by_errors
: Option
<ErrorGuaranteed
>,
250 /// After we borrow check a closure, we are left with various
251 /// requirements that we have inferred between the free regions that
252 /// appear in the closure's signature or on its field types. These
253 /// requirements are then verified and proved by the closure's
254 /// creating function. This struct encodes those requirements.
256 /// The requirements are listed as being between various `RegionVid`. The 0th
257 /// region refers to `'static`; subsequent region vids refer to the free
258 /// regions that appear in the closure (or generator's) type, in order of
259 /// appearance. (This numbering is actually defined by the `UniversalRegions`
260 /// struct in the NLL region checker. See for example
261 /// `UniversalRegions::closure_mapping`.) Note the free regions in the
262 /// closure's signature and captures are erased.
264 /// Example: If type check produces a closure with the closure substs:
267 /// ClosureSubsts = [
268 /// 'a, // From the parent.
270 /// i8, // the "closure kind"
271 /// for<'x> fn(&'<erased> &'x u32) -> &'x u32, // the "closure signature"
272 /// &'<erased> String, // some upvar
276 /// We would "renumber" each free region to a unique vid, as follows:
279 /// ClosureSubsts = [
280 /// '1, // From the parent.
282 /// i8, // the "closure kind"
283 /// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature"
284 /// &'4 String, // some upvar
288 /// Now the code might impose a requirement like `'1: '2`. When an
289 /// instance of the closure is created, the corresponding free regions
290 /// can be extracted from its type and constrained to have the given
291 /// outlives relationship.
292 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
293 pub struct ClosureRegionRequirements
<'tcx
> {
294 /// The number of external regions defined on the closure. In our
295 /// example above, it would be 3 -- one for `'static`, then `'1`
296 /// and `'2`. This is just used for a sanity check later on, to
297 /// make sure that the number of regions we see at the callsite
299 pub num_external_vids
: usize,
301 /// Requirements between the various free regions defined in
303 pub outlives_requirements
: Vec
<ClosureOutlivesRequirement
<'tcx
>>,
306 /// Indicates an outlives-constraint between a type or between two
307 /// free regions declared on the closure.
308 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
309 pub struct ClosureOutlivesRequirement
<'tcx
> {
310 // This region or type ...
311 pub subject
: ClosureOutlivesSubject
<'tcx
>,
313 // ... must outlive this one.
314 pub outlived_free_region
: ty
::RegionVid
,
316 // If not, report an error here ...
317 pub blame_span
: Span
,
319 // ... due to this reason.
320 pub category
: ConstraintCategory
<'tcx
>,
323 // Make sure this enum doesn't unintentionally grow
324 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
325 rustc_data_structures
::static_assert_size
!(ConstraintCategory
<'_
>, 16);
327 /// Outlives-constraints can be categorized to determine whether and why they
328 /// are interesting (for error reporting). Order of variants indicates sort
329 /// order of the category, thereby influencing diagnostic output.
331 /// See also `rustc_const_eval::borrow_check::constraints`.
332 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
333 #[derive(TyEncodable, TyDecodable, HashStable, Lift, TypeVisitable, TypeFoldable)]
334 pub enum ConstraintCategory
<'tcx
> {
335 Return(ReturnConstraint
),
342 /// A constraint that came from checking the body of a closure.
344 /// We try to get the category that the closure used when reporting this.
347 /// Contains the function type if available.
348 CallArgument(Option
<Ty
<'tcx
>>),
352 /// A constraint that came from a usage of a variable (e.g. in an ADT expression
353 /// like `Foo { field: my_val }`)
358 /// A constraint from a user-written predicate
359 /// with the provided span, written on the item
360 /// with the given `DefId`
363 /// A "boring" constraint (caused by the given location) is one that
364 /// the user probably doesn't want to see described in diagnostics,
365 /// because it is kind of an artifact of the type system setup.
367 // Boring and applicable everywhere.
370 /// A constraint that doesn't correspond to anything the user sees.
374 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
375 #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
376 pub enum ReturnConstraint
{
381 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
382 /// that must outlive some region.
383 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
384 pub enum ClosureOutlivesSubject
<'tcx
> {
385 /// Subject is a type, typically a type parameter, but could also
386 /// be a projection. Indicates a requirement like `T: 'a` being
387 /// passed to the caller, where the type here is `T`.
388 Ty(ClosureOutlivesSubjectTy
<'tcx
>),
390 /// Subject is a free region from the closure. Indicates a requirement
391 /// like `'a: 'b` being passed to the caller; the region here is `'a`.
392 Region(ty
::RegionVid
),
395 /// Represents a `ty::Ty` for use in [`ClosureOutlivesSubject`].
397 /// This abstraction is necessary because the type may include `ReVar` regions,
398 /// which is what we use internally within NLL code, and they can't be used in
399 /// a query response.
401 /// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this
402 /// type is not recognized as a binder for late-bound region.
403 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
404 pub struct ClosureOutlivesSubjectTy
<'tcx
> {
408 impl<'tcx
> ClosureOutlivesSubjectTy
<'tcx
> {
409 /// All regions of `ty` must be of kind `ReVar` and must represent
410 /// universal regions *external* to the closure.
411 pub fn bind(tcx
: TyCtxt
<'tcx
>, ty
: Ty
<'tcx
>) -> Self {
412 let inner
= tcx
.fold_regions(ty
, |r
, depth
| match r
.kind() {
414 let br
= ty
::BoundRegion
{
415 var
: ty
::BoundVar
::new(vid
.index()),
416 kind
: ty
::BrAnon(vid
.as_u32(), None
),
418 tcx
.mk_re_late_bound(depth
, br
)
420 _
=> bug
!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
429 mut map
: impl FnMut(ty
::RegionVid
) -> ty
::Region
<'tcx
>,
431 tcx
.fold_regions(self.inner
, |r
, depth
| match r
.kind() {
432 ty
::ReLateBound(debruijn
, br
) => {
433 debug_assert_eq
!(debruijn
, depth
);
434 map(ty
::RegionVid
::new(br
.var
.index()))
436 _
=> bug
!("unexpected region {r:?}"),
441 /// The constituent parts of a mir constant of kind ADT or array.
442 #[derive(Copy, Clone, Debug, HashStable)]
443 pub struct DestructuredConstant
<'tcx
> {
444 pub variant
: Option
<VariantIdx
>,
445 pub fields
: &'tcx
[ConstantKind
<'tcx
>],
448 /// Coverage information summarized from a MIR if instrumented for source code coverage (see
449 /// compiler option `-Cinstrument-coverage`). This information is generated by the
450 /// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query.
451 #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)]
452 pub struct CoverageInfo
{
453 /// The total number of coverage region counters added to the MIR `Body`.
454 pub num_counters
: u32,
456 /// The total number of coverage region counter expressions added to the MIR `Body`.
457 pub num_expressions
: u32,
460 /// Shims which make dealing with `WithOptConstParam` easier.
462 /// For more information on why this is needed, consider looking
463 /// at the docs for `WithOptConstParam` itself.
464 impl<'tcx
> TyCtxt
<'tcx
> {
466 pub fn mir_const_qualif_opt_const_arg(
468 def
: ty
::WithOptConstParam
<LocalDefId
>,
470 if let Some(param_did
) = def
.const_param_did
{
471 self.mir_const_qualif_const_arg((def
.did
, param_did
))
473 self.mir_const_qualif(def
.did
)
478 pub fn promoted_mir_opt_const_arg(
480 def
: ty
::WithOptConstParam
<DefId
>,
481 ) -> &'tcx IndexVec
<Promoted
, Body
<'tcx
>> {
482 if let Some((did
, param_did
)) = def
.as_const_arg() {
483 self.promoted_mir_of_const_arg((did
, param_did
))
485 self.promoted_mir(def
.did
)
490 pub fn mir_for_ctfe_opt_const_arg(self, def
: ty
::WithOptConstParam
<DefId
>) -> &'tcx Body
<'tcx
> {
491 if let Some((did
, param_did
)) = def
.as_const_arg() {
492 self.mir_for_ctfe_of_const_arg((did
, param_did
))
494 self.mir_for_ctfe(def
.did
)