2020-01-05 15:46:44 +00:00
|
|
|
//! Values computed by queries that use MIR.
|
|
|
|
|
2020-10-04 23:20:00 +02:00
|
|
|
use crate::mir::{abstract_const, Body, Promoted};
|
2020-07-08 01:03:19 +02:00
|
|
|
use crate::ty::{self, Ty, TyCtxt};
|
2019-12-25 09:50:07 +00:00
|
|
|
use rustc_data_structures::fx::FxHashMap;
|
2020-01-05 15:46:44 +00:00
|
|
|
use rustc_data_structures::sync::Lrc;
|
2020-10-04 23:20:00 +02:00
|
|
|
use rustc_errors::ErrorReported;
|
2020-01-05 15:46:44 +00:00
|
|
|
use rustc_hir as hir;
|
2020-07-08 01:03:19 +02:00
|
|
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
2020-01-05 15:46:44 +00:00
|
|
|
use rustc_index::bit_set::BitMatrix;
|
|
|
|
use rustc_index::vec::IndexVec;
|
2020-07-14 12:12:01 +10:00
|
|
|
use rustc_span::Span;
|
2020-01-05 15:46:44 +00:00
|
|
|
use rustc_target::abi::VariantIdx;
|
|
|
|
use smallvec::SmallVec;
|
2020-06-19 20:19:19 -07:00
|
|
|
use std::cell::Cell;
|
|
|
|
use std::fmt::{self, Debug};
|
2020-01-05 15:46:44 +00:00
|
|
|
|
|
|
|
use super::{Field, SourceInfo};
|
|
|
|
|
2021-01-03 09:19:16 -05:00
|
|
|
#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
|
2020-01-05 15:46:44 +00:00
|
|
|
pub enum UnsafetyViolationKind {
|
2021-04-25 18:41:14 +02:00
|
|
|
/// Unsafe operation outside `unsafe`.
|
2020-01-05 15:46:44 +00:00
|
|
|
General,
|
2020-05-03 23:11:34 +02:00
|
|
|
/// Unsafe operation in an `unsafe fn` but outside an `unsafe` block.
|
|
|
|
/// Has to be handled as a lint for backwards compatibility.
|
2020-05-13 23:43:21 +02:00
|
|
|
UnsafeFn,
|
2020-01-05 15:46:44 +00:00
|
|
|
}
|
|
|
|
|
2021-01-03 09:19:16 -05:00
|
|
|
#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
|
2020-07-14 12:12:01 +10:00
|
|
|
pub enum UnsafetyViolationDetails {
|
|
|
|
CallToUnsafeFunction,
|
|
|
|
UseOfInlineAssembly,
|
|
|
|
InitializingTypeWith,
|
|
|
|
CastOfPointerToInt,
|
|
|
|
UseOfMutableStatic,
|
|
|
|
UseOfExternStatic,
|
|
|
|
DerefOfRawPointer,
|
2020-10-18 13:53:54 +02:00
|
|
|
AssignToDroppingUnionField,
|
2020-07-14 12:12:01 +10:00
|
|
|
AccessToUnionField,
|
|
|
|
MutationOfLayoutConstrainedField,
|
|
|
|
BorrowOfLayoutConstrainedField,
|
|
|
|
CallToFunctionWith,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UnsafetyViolationDetails {
|
|
|
|
pub fn description_and_note(&self) -> (&'static str, &'static str) {
|
|
|
|
use UnsafetyViolationDetails::*;
|
|
|
|
match self {
|
|
|
|
CallToUnsafeFunction => (
|
|
|
|
"call to unsafe function",
|
|
|
|
"consult the function's documentation for information on how to avoid undefined \
|
|
|
|
behavior",
|
|
|
|
),
|
|
|
|
UseOfInlineAssembly => (
|
|
|
|
"use of inline assembly",
|
|
|
|
"inline assembly is entirely unchecked and can cause undefined behavior",
|
|
|
|
),
|
|
|
|
InitializingTypeWith => (
|
|
|
|
"initializing type with `rustc_layout_scalar_valid_range` attr",
|
|
|
|
"initializing a layout restricted type's field with a value outside the valid \
|
|
|
|
range is undefined behavior",
|
|
|
|
),
|
|
|
|
CastOfPointerToInt => {
|
|
|
|
("cast of pointer to int", "casting pointers to integers in constants")
|
|
|
|
}
|
|
|
|
UseOfMutableStatic => (
|
|
|
|
"use of mutable static",
|
|
|
|
"mutable statics can be mutated by multiple threads: aliasing violations or data \
|
|
|
|
races will cause undefined behavior",
|
|
|
|
),
|
|
|
|
UseOfExternStatic => (
|
|
|
|
"use of extern static",
|
|
|
|
"extern statics are not controlled by the Rust type system: invalid data, \
|
|
|
|
aliasing violations or data races will cause undefined behavior",
|
|
|
|
),
|
|
|
|
DerefOfRawPointer => (
|
|
|
|
"dereference of raw pointer",
|
2021-05-02 15:55:22 -06:00
|
|
|
"raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
|
2020-07-14 12:12:01 +10:00
|
|
|
and cause data races: all of these are undefined behavior",
|
|
|
|
),
|
2020-10-18 13:53:54 +02:00
|
|
|
AssignToDroppingUnionField => (
|
2020-10-28 08:57:57 +01:00
|
|
|
"assignment to union field that might need dropping",
|
2020-07-14 12:12:01 +10:00
|
|
|
"the previous content of the field will be dropped, which causes undefined \
|
|
|
|
behavior if the field was not properly initialized",
|
|
|
|
),
|
|
|
|
AccessToUnionField => (
|
|
|
|
"access to union field",
|
|
|
|
"the field may not be properly initialized: using uninitialized data will cause \
|
|
|
|
undefined behavior",
|
|
|
|
),
|
|
|
|
MutationOfLayoutConstrainedField => (
|
|
|
|
"mutation of layout constrained field",
|
|
|
|
"mutating layout constrained fields cannot statically be checked for valid values",
|
|
|
|
),
|
|
|
|
BorrowOfLayoutConstrainedField => (
|
|
|
|
"borrow of layout constrained field with interior mutability",
|
|
|
|
"references to fields of layout constrained fields lose the constraints. Coupled \
|
|
|
|
with interior mutability, the field can be changed to invalid values",
|
|
|
|
),
|
|
|
|
CallToFunctionWith => (
|
|
|
|
"call to function with `#[target_feature]`",
|
|
|
|
"can only be called if the required target features are available",
|
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-03 09:19:16 -05:00
|
|
|
#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
|
2020-01-05 15:46:44 +00:00
|
|
|
pub struct UnsafetyViolation {
|
|
|
|
pub source_info: SourceInfo,
|
2020-05-13 23:43:21 +02:00
|
|
|
pub lint_root: hir::HirId,
|
2020-01-05 15:46:44 +00:00
|
|
|
pub kind: UnsafetyViolationKind,
|
2020-07-14 12:12:01 +10:00
|
|
|
pub details: UnsafetyViolationDetails,
|
2020-01-05 15:46:44 +00:00
|
|
|
}
|
|
|
|
|
2021-01-03 09:19:16 -05:00
|
|
|
#[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
|
2020-01-05 15:46:44 +00:00
|
|
|
pub struct UnsafetyCheckResult {
|
|
|
|
/// Violations that are propagated *upwards* from this function.
|
|
|
|
pub violations: Lrc<[UnsafetyViolation]>,
|
|
|
|
/// `unsafe` blocks in this function, along with whether they are used. This is
|
|
|
|
/// used for the "unused_unsafe" lint.
|
|
|
|
pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>,
|
|
|
|
}
|
|
|
|
|
|
|
|
rustc_index::newtype_index! {
|
|
|
|
pub struct GeneratorSavedLocal {
|
|
|
|
derive [HashStable]
|
|
|
|
DEBUG_FORMAT = "_{}",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The layout of generator state.
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
|
2020-01-05 15:46:44 +00:00
|
|
|
pub struct GeneratorLayout<'tcx> {
|
|
|
|
/// The type of every local stored inside the generator.
|
|
|
|
pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
|
|
|
|
|
|
|
|
/// Which of the above fields are in each variant. Note that one field may
|
|
|
|
/// be stored in multiple variants.
|
|
|
|
pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
|
|
|
|
|
2020-06-17 16:04:25 -07:00
|
|
|
/// The source that led to each variant being created (usually, a yield or
|
|
|
|
/// await).
|
|
|
|
pub variant_source_info: IndexVec<VariantIdx, SourceInfo>,
|
|
|
|
|
2020-01-05 15:46:44 +00:00
|
|
|
/// Which saved locals are storage-live at the same time. Locals that do not
|
|
|
|
/// have conflicts with each other are allowed to overlap in the computed
|
|
|
|
/// layout.
|
|
|
|
pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
|
|
|
|
}
|
|
|
|
|
2020-06-19 20:19:19 -07:00
|
|
|
impl Debug for GeneratorLayout<'_> {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
/// Prints an iterator of (key, value) tuples as a map.
|
|
|
|
struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>);
|
|
|
|
impl<'a, K, V> MapPrinter<'a, K, V> {
|
|
|
|
fn new(iter: impl Iterator<Item = (K, V)> + 'a) -> Self {
|
|
|
|
Self(Cell::new(Some(Box::new(iter))))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
fmt.debug_map().entries(self.0.take().unwrap()).finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Prints the generator variant name.
|
|
|
|
struct GenVariantPrinter(VariantIdx);
|
|
|
|
impl From<VariantIdx> for GenVariantPrinter {
|
|
|
|
fn from(idx: VariantIdx) -> Self {
|
|
|
|
GenVariantPrinter(idx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl Debug for GenVariantPrinter {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
let variant_name = ty::GeneratorSubsts::variant_name(self.0);
|
|
|
|
if fmt.alternate() {
|
|
|
|
write!(fmt, "{:9}({:?})", variant_name, self.0)
|
|
|
|
} else {
|
|
|
|
write!(fmt, "{}", variant_name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Forces its contents to print in regular mode instead of alternate mode.
|
|
|
|
struct OneLinePrinter<T>(T);
|
|
|
|
impl<T: Debug> Debug for OneLinePrinter<T> {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
write!(fmt, "{:?}", self.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.debug_struct("GeneratorLayout")
|
|
|
|
.field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated()))
|
|
|
|
.field(
|
|
|
|
"variant_fields",
|
|
|
|
&MapPrinter::new(
|
|
|
|
self.variant_fields
|
|
|
|
.iter_enumerated()
|
|
|
|
.map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.field("storage_conflicts", &self.storage_conflicts)
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Debug, TyEncodable, TyDecodable, HashStable)]
|
2020-01-05 15:46:44 +00:00
|
|
|
pub struct BorrowCheckResult<'tcx> {
|
2019-12-25 09:50:07 +00:00
|
|
|
/// All the opaque types that are restricted to concrete types
|
2020-07-17 08:47:04 +00:00
|
|
|
/// by this function. Unlike the value in `TypeckResults`, this has
|
2019-12-25 09:50:07 +00:00
|
|
|
/// unerased regions.
|
|
|
|
pub concrete_opaque_types: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
|
2020-01-05 15:46:44 +00:00
|
|
|
pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
|
|
|
|
pub used_mut_upvars: SmallVec<[Field; 8]>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The result of the `mir_const_qualif` query.
|
|
|
|
///
|
2020-11-06 20:46:38 +05:30
|
|
|
/// Each field (except `error_occured`) corresponds to an implementer of the `Qualif` trait in
|
|
|
|
/// `rustc_mir/src/transform/check_consts/qualifs.rs`. See that file for more information on each
|
2020-01-05 15:46:44 +00:00
|
|
|
/// `Qualif`.
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)]
|
2020-01-05 15:46:44 +00:00
|
|
|
pub struct ConstQualifs {
|
|
|
|
pub has_mut_interior: bool,
|
|
|
|
pub needs_drop: bool,
|
2020-03-16 10:45:39 -07:00
|
|
|
pub custom_eq: bool,
|
2020-11-10 14:59:44 +05:30
|
|
|
pub error_occured: Option<ErrorReported>,
|
2020-01-05 15:46:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// After we borrow check a closure, we are left with various
|
|
|
|
/// requirements that we have inferred between the free regions that
|
|
|
|
/// appear in the closure's signature or on its field types. These
|
|
|
|
/// requirements are then verified and proved by the closure's
|
|
|
|
/// creating function. This struct encodes those requirements.
|
|
|
|
///
|
2020-03-11 22:24:20 +00:00
|
|
|
/// The requirements are listed as being between various `RegionVid`. The 0th
|
|
|
|
/// region refers to `'static`; subsequent region vids refer to the free
|
|
|
|
/// regions that appear in the closure (or generator's) type, in order of
|
|
|
|
/// appearance. (This numbering is actually defined by the `UniversalRegions`
|
|
|
|
/// struct in the NLL region checker. See for example
|
|
|
|
/// `UniversalRegions::closure_mapping`.) Note the free regions in the
|
|
|
|
/// closure's signature and captures are erased.
|
2020-01-05 15:46:44 +00:00
|
|
|
///
|
|
|
|
/// Example: If type check produces a closure with the closure substs:
|
|
|
|
///
|
|
|
|
/// ```text
|
|
|
|
/// ClosureSubsts = [
|
2020-03-11 22:24:20 +00:00
|
|
|
/// 'a, // From the parent.
|
|
|
|
/// 'b,
|
|
|
|
/// i8, // the "closure kind"
|
|
|
|
/// for<'x> fn(&'<erased> &'x u32) -> &'x u32, // the "closure signature"
|
|
|
|
/// &'<erased> String, // some upvar
|
2020-01-05 15:46:44 +00:00
|
|
|
/// ]
|
|
|
|
/// ```
|
|
|
|
///
|
2020-03-11 22:24:20 +00:00
|
|
|
/// We would "renumber" each free region to a unique vid, as follows:
|
2020-01-05 15:46:44 +00:00
|
|
|
///
|
|
|
|
/// ```text
|
|
|
|
/// ClosureSubsts = [
|
2020-03-11 22:24:20 +00:00
|
|
|
/// '1, // From the parent.
|
|
|
|
/// '2,
|
|
|
|
/// i8, // the "closure kind"
|
|
|
|
/// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature"
|
|
|
|
/// &'4 String, // some upvar
|
2020-01-05 15:46:44 +00:00
|
|
|
/// ]
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// Now the code might impose a requirement like `'1: '2`. When an
|
|
|
|
/// instance of the closure is created, the corresponding free regions
|
|
|
|
/// can be extracted from its type and constrained to have the given
|
|
|
|
/// outlives relationship.
|
|
|
|
///
|
2020-03-11 22:24:20 +00:00
|
|
|
/// In some cases, we have to record outlives requirements between types and
|
|
|
|
/// regions as well. In that case, if those types include any regions, those
|
|
|
|
/// regions are recorded using their external names (`ReStatic`,
|
|
|
|
/// `ReEarlyBound`, `ReFree`). We use these because in a query response we
|
|
|
|
/// cannot use `ReVar` (which is what we use internally within the rest of the
|
|
|
|
/// NLL code).
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
2020-01-05 15:46:44 +00:00
|
|
|
pub struct ClosureRegionRequirements<'tcx> {
|
|
|
|
/// The number of external regions defined on the closure. In our
|
|
|
|
/// example above, it would be 3 -- one for `'static`, then `'1`
|
|
|
|
/// and `'2`. This is just used for a sanity check later on, to
|
|
|
|
/// make sure that the number of regions we see at the callsite
|
|
|
|
/// matches.
|
|
|
|
pub num_external_vids: usize,
|
|
|
|
|
|
|
|
/// Requirements between the various free regions defined in
|
|
|
|
/// indices.
|
|
|
|
pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Indicates an outlives-constraint between a type or between two
|
|
|
|
/// free regions declared on the closure.
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
2020-01-05 15:46:44 +00:00
|
|
|
pub struct ClosureOutlivesRequirement<'tcx> {
|
|
|
|
// This region or type ...
|
|
|
|
pub subject: ClosureOutlivesSubject<'tcx>,
|
|
|
|
|
|
|
|
// ... must outlive this one.
|
|
|
|
pub outlived_free_region: ty::RegionVid,
|
|
|
|
|
|
|
|
// If not, report an error here ...
|
|
|
|
pub blame_span: Span,
|
|
|
|
|
|
|
|
// ... due to this reason.
|
|
|
|
pub category: ConstraintCategory,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Outlives-constraints can be categorized to determine whether and why they
|
|
|
|
/// are interesting (for error reporting). Order of variants indicates sort
|
|
|
|
/// order of the category, thereby influencing diagnostic output.
|
|
|
|
///
|
2020-05-01 22:28:15 +02:00
|
|
|
/// See also `rustc_mir::borrow_check::constraints`.
|
2020-01-05 15:46:44 +00:00
|
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(TyEncodable, TyDecodable, HashStable)]
|
2020-01-05 15:46:44 +00:00
|
|
|
pub enum ConstraintCategory {
|
2020-05-23 21:40:55 -04:00
|
|
|
Return(ReturnConstraint),
|
2020-01-05 15:46:44 +00:00
|
|
|
Yield,
|
|
|
|
UseAsConst,
|
|
|
|
UseAsStatic,
|
|
|
|
TypeAnnotation,
|
|
|
|
Cast,
|
|
|
|
|
|
|
|
/// A constraint that came from checking the body of a closure.
|
|
|
|
///
|
|
|
|
/// We try to get the category that the closure used when reporting this.
|
|
|
|
ClosureBounds,
|
|
|
|
CallArgument,
|
|
|
|
CopyBound,
|
|
|
|
SizedBound,
|
|
|
|
Assignment,
|
|
|
|
OpaqueType,
|
2020-05-23 21:40:55 -04:00
|
|
|
ClosureUpvar(hir::HirId),
|
2020-01-05 15:46:44 +00:00
|
|
|
|
|
|
|
/// A "boring" constraint (caused by the given location) is one that
|
|
|
|
/// the user probably doesn't want to see described in diagnostics,
|
|
|
|
/// because it is kind of an artifact of the type system setup.
|
|
|
|
/// Example: `x = Foo { field: y }` technically creates
|
|
|
|
/// intermediate regions representing the "type of `Foo { field: y
|
|
|
|
/// }`", and data flows from `y` into those variables, but they
|
|
|
|
/// are not very interesting. The assignment into `x` on the other
|
|
|
|
/// hand might be.
|
|
|
|
Boring,
|
|
|
|
// Boring and applicable everywhere.
|
|
|
|
BoringNoLocation,
|
|
|
|
|
|
|
|
/// A constraint that doesn't correspond to anything the user sees.
|
|
|
|
Internal,
|
|
|
|
}
|
|
|
|
|
2020-05-23 21:40:55 -04:00
|
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(TyEncodable, TyDecodable, HashStable)]
|
2020-05-23 21:40:55 -04:00
|
|
|
pub enum ReturnConstraint {
|
|
|
|
Normal,
|
|
|
|
ClosureUpvar(hir::HirId),
|
|
|
|
}
|
|
|
|
|
2020-01-05 15:46:44 +00:00
|
|
|
/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
|
|
|
|
/// that must outlive some region.
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
2020-01-05 15:46:44 +00:00
|
|
|
pub enum ClosureOutlivesSubject<'tcx> {
|
|
|
|
/// Subject is a type, typically a type parameter, but could also
|
|
|
|
/// be a projection. Indicates a requirement like `T: 'a` being
|
|
|
|
/// passed to the caller, where the type here is `T`.
|
|
|
|
///
|
|
|
|
/// The type here is guaranteed not to contain any free regions at
|
|
|
|
/// present.
|
|
|
|
Ty(Ty<'tcx>),
|
|
|
|
|
|
|
|
/// Subject is a free region from the closure. Indicates a requirement
|
|
|
|
/// like `'a: 'b` being passed to the caller; the region here is `'a`.
|
|
|
|
Region(ty::RegionVid),
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The constituent parts of an ADT or array.
|
|
|
|
#[derive(Copy, Clone, Debug, HashStable)]
|
|
|
|
pub struct DestructuredConst<'tcx> {
|
2020-06-18 10:37:59 +01:00
|
|
|
pub variant: Option<VariantIdx>,
|
2020-01-05 15:46:44 +00:00
|
|
|
pub fields: &'tcx [&'tcx ty::Const<'tcx>],
|
|
|
|
}
|
2020-06-21 23:29:08 -07:00
|
|
|
|
|
|
|
/// Coverage information summarized from a MIR if instrumented for source code coverage (see
|
|
|
|
/// compiler option `-Zinstrument-coverage`). This information is generated by the
|
|
|
|
/// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query.
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)]
|
2020-06-21 23:29:08 -07:00
|
|
|
pub struct CoverageInfo {
|
|
|
|
/// The total number of coverage region counters added to the MIR `Body`.
|
|
|
|
pub num_counters: u32,
|
2020-07-02 11:27:15 -07:00
|
|
|
|
|
|
|
/// The total number of coverage region counter expressions added to the MIR `Body`.
|
|
|
|
pub num_expressions: u32,
|
2020-06-21 23:29:08 -07:00
|
|
|
}
|
2020-07-08 01:03:19 +02:00
|
|
|
|
2020-10-04 23:20:00 +02:00
|
|
|
/// Shims which make dealing with `WithOptConstParam` easier.
|
|
|
|
///
|
|
|
|
/// For more information on why this is needed, consider looking
|
|
|
|
/// at the docs for `WithOptConstParam` itself.
|
2020-07-08 01:03:19 +02:00
|
|
|
impl<'tcx> TyCtxt<'tcx> {
|
2020-10-04 23:20:00 +02:00
|
|
|
#[inline]
|
2020-07-15 10:50:54 +02:00
|
|
|
pub fn mir_const_qualif_opt_const_arg(
|
|
|
|
self,
|
|
|
|
def: ty::WithOptConstParam<LocalDefId>,
|
|
|
|
) -> ConstQualifs {
|
|
|
|
if let Some(param_did) = def.const_param_did {
|
2020-07-08 01:03:19 +02:00
|
|
|
self.mir_const_qualif_const_arg((def.did, param_did))
|
|
|
|
} else {
|
|
|
|
self.mir_const_qualif(def.did)
|
|
|
|
}
|
|
|
|
}
|
2020-07-08 10:35:58 +02:00
|
|
|
|
2020-10-04 23:20:00 +02:00
|
|
|
#[inline]
|
2020-10-05 08:49:21 +02:00
|
|
|
pub fn promoted_mir_opt_const_arg(
|
2020-07-08 10:35:58 +02:00
|
|
|
self,
|
2020-07-15 10:50:54 +02:00
|
|
|
def: ty::WithOptConstParam<DefId>,
|
2020-07-08 10:35:58 +02:00
|
|
|
) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
|
|
|
|
if let Some((did, param_did)) = def.as_const_arg() {
|
|
|
|
self.promoted_mir_of_const_arg((did, param_did))
|
|
|
|
} else {
|
|
|
|
self.promoted_mir(def.did)
|
|
|
|
}
|
|
|
|
}
|
2020-10-04 23:20:00 +02:00
|
|
|
|
2020-10-26 19:00:40 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam<DefId>) -> &'tcx Body<'tcx> {
|
|
|
|
if let Some((did, param_did)) = def.as_const_arg() {
|
|
|
|
self.mir_for_ctfe_of_const_arg((did, param_did))
|
|
|
|
} else {
|
|
|
|
self.mir_for_ctfe(def.did)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-04 23:20:00 +02:00
|
|
|
#[inline]
|
2020-10-05 08:49:21 +02:00
|
|
|
pub fn mir_abstract_const_opt_const_arg(
|
2020-10-04 23:20:00 +02:00
|
|
|
self,
|
|
|
|
def: ty::WithOptConstParam<DefId>,
|
|
|
|
) -> Result<Option<&'tcx [abstract_const::Node<'tcx>]>, ErrorReported> {
|
|
|
|
if let Some((did, param_did)) = def.as_const_arg() {
|
|
|
|
self.mir_abstract_const_of_const_arg((did, param_did))
|
|
|
|
} else {
|
|
|
|
self.mir_abstract_const(def.did)
|
|
|
|
}
|
|
|
|
}
|
2020-07-08 01:03:19 +02:00
|
|
|
}
|