1 //! Values computed by queries that use MIR.
3 use crate::ty::{self, Ty};
4 use rustc_data_structures::fx::FxHashMap;
5 use rustc_data_structures::sync::Lrc;
7 use rustc_hir::def_id::DefId;
8 use rustc_index::bit_set::BitMatrix;
9 use rustc_index::vec::IndexVec;
10 use rustc_span::{Span, Symbol};
11 use rustc_target::abi::VariantIdx;
12 use smallvec::SmallVec;
14 use std::fmt::{self, Debug};
16 use super::{Field, SourceInfo};
18 #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
19 pub enum UnsafetyViolationKind {
20 /// Only permitted in regular `fn`s, prohibitted in `const fn`s.
22 /// Permitted both in `const fn`s and regular `fn`s.
24 /// Borrow of packed field.
25 /// Has to be handled as a lint for backwards compatibility.
27 /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block.
28 /// Has to be handled as a lint for backwards compatibility.
29 /// Should stay gated under `#![feature(unsafe_block_in_unsafe_fn)]`.
31 /// Borrow of packed field in an `unsafe fn` but outside an `unsafe` block.
32 /// Has to be handled as a lint for backwards compatibility.
33 /// Should stay gated under `#![feature(unsafe_block_in_unsafe_fn)]`.
37 #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
38 pub struct UnsafetyViolation {
39 pub source_info: SourceInfo,
40 pub lint_root: hir::HirId,
41 pub description: Symbol,
43 pub kind: UnsafetyViolationKind,
46 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
47 pub struct UnsafetyCheckResult {
48 /// Violations that are propagated *upwards* from this function.
49 pub violations: Lrc<[UnsafetyViolation]>,
50 /// `unsafe` blocks in this function, along with whether they are used. This is
51 /// used for the "unused_unsafe" lint.
52 pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>,
55 rustc_index::newtype_index! {
56 pub struct GeneratorSavedLocal {
62 /// The layout of generator state.
63 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
64 pub struct GeneratorLayout<'tcx> {
65 /// The type of every local stored inside the generator.
66 pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
68 /// Which of the above fields are in each variant. Note that one field may
69 /// be stored in multiple variants.
70 pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
72 /// The source that led to each variant being created (usually, a yield or
74 pub variant_source_info: IndexVec<VariantIdx, SourceInfo>,
76 /// Which saved locals are storage-live at the same time. Locals that do not
77 /// have conflicts with each other are allowed to overlap in the computed
79 pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
82 impl Debug for GeneratorLayout<'_> {
83 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
84 /// Prints an iterator of (key, value) tuples as a map.
85 struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>);
86 impl<'a, K, V> MapPrinter<'a, K, V> {
87 fn new(iter: impl Iterator<Item = (K, V)> + 'a) -> Self {
88 Self(Cell::new(Some(Box::new(iter))))
91 impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> {
92 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
93 fmt.debug_map().entries(self.0.take().unwrap()).finish()
97 /// Prints the generator variant name.
98 struct GenVariantPrinter(VariantIdx);
99 impl From<VariantIdx> for GenVariantPrinter {
100 fn from(idx: VariantIdx) -> Self {
101 GenVariantPrinter(idx)
104 impl Debug for GenVariantPrinter {
105 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
106 let variant_name = ty::GeneratorSubsts::variant_name(self.0);
108 write!(fmt, "{:9}({:?})", variant_name, self.0)
110 write!(fmt, "{}", variant_name)
115 /// Forces its contents to print in regular mode instead of alternate mode.
116 struct OneLinePrinter<T>(T);
117 impl<T: Debug> Debug for OneLinePrinter<T> {
118 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
119 write!(fmt, "{:?}", self.0)
123 fmt.debug_struct("GeneratorLayout")
124 .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated()))
130 .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))),
133 .field("storage_conflicts", &self.storage_conflicts)
138 #[derive(Debug, RustcEncodable, RustcDecodable, HashStable)]
139 pub struct BorrowCheckResult<'tcx> {
140 /// All the opaque types that are restricted to concrete types
141 /// by this function. Unlike the value in `TypeckTables`, this has
142 /// unerased regions.
143 pub concrete_opaque_types: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
144 pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
145 pub used_mut_upvars: SmallVec<[Field; 8]>,
148 /// The result of the `mir_const_qualif` query.
150 /// Each field corresponds to an implementer of the `Qualif` trait in
151 /// `librustc_mir/transform/check_consts/qualifs.rs`. See that file for more information on each
153 #[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)]
154 pub struct ConstQualifs {
155 pub has_mut_interior: bool,
156 pub needs_drop: bool,
160 /// After we borrow check a closure, we are left with various
161 /// requirements that we have inferred between the free regions that
162 /// appear in the closure's signature or on its field types. These
163 /// requirements are then verified and proved by the closure's
164 /// creating function. This struct encodes those requirements.
166 /// The requirements are listed as being between various `RegionVid`. The 0th
167 /// region refers to `'static`; subsequent region vids refer to the free
168 /// regions that appear in the closure (or generator's) type, in order of
169 /// appearance. (This numbering is actually defined by the `UniversalRegions`
170 /// struct in the NLL region checker. See for example
171 /// `UniversalRegions::closure_mapping`.) Note the free regions in the
172 /// closure's signature and captures are erased.
174 /// Example: If type check produces a closure with the closure substs:
177 /// ClosureSubsts = [
178 /// 'a, // From the parent.
180 /// i8, // the "closure kind"
181 /// for<'x> fn(&'<erased> &'x u32) -> &'x u32, // the "closure signature"
182 /// &'<erased> String, // some upvar
186 /// We would "renumber" each free region to a unique vid, as follows:
189 /// ClosureSubsts = [
190 /// '1, // From the parent.
192 /// i8, // the "closure kind"
193 /// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature"
194 /// &'4 String, // some upvar
198 /// Now the code might impose a requirement like `'1: '2`. When an
199 /// instance of the closure is created, the corresponding free regions
200 /// can be extracted from its type and constrained to have the given
201 /// outlives relationship.
203 /// In some cases, we have to record outlives requirements between types and
204 /// regions as well. In that case, if those types include any regions, those
205 /// regions are recorded using their external names (`ReStatic`,
206 /// `ReEarlyBound`, `ReFree`). We use these because in a query response we
207 /// cannot use `ReVar` (which is what we use internally within the rest of the
209 #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
210 pub struct ClosureRegionRequirements<'tcx> {
211 /// The number of external regions defined on the closure. In our
212 /// example above, it would be 3 -- one for `'static`, then `'1`
213 /// and `'2`. This is just used for a sanity check later on, to
214 /// make sure that the number of regions we see at the callsite
216 pub num_external_vids: usize,
218 /// Requirements between the various free regions defined in
220 pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
223 /// Indicates an outlives-constraint between a type or between two
224 /// free regions declared on the closure.
225 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
226 pub struct ClosureOutlivesRequirement<'tcx> {
227 // This region or type ...
228 pub subject: ClosureOutlivesSubject<'tcx>,
230 // ... must outlive this one.
231 pub outlived_free_region: ty::RegionVid,
233 // If not, report an error here ...
234 pub blame_span: Span,
236 // ... due to this reason.
237 pub category: ConstraintCategory,
240 /// Outlives-constraints can be categorized to determine whether and why they
241 /// are interesting (for error reporting). Order of variants indicates sort
242 /// order of the category, thereby influencing diagnostic output.
244 /// See also `rustc_mir::borrow_check::constraints`.
245 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
246 #[derive(RustcEncodable, RustcDecodable, HashStable)]
247 pub enum ConstraintCategory {
248 Return(ReturnConstraint),
255 /// A constraint that came from checking the body of a closure.
257 /// We try to get the category that the closure used when reporting this.
264 ClosureUpvar(hir::HirId),
266 /// A "boring" constraint (caused by the given location) is one that
267 /// the user probably doesn't want to see described in diagnostics,
268 /// because it is kind of an artifact of the type system setup.
269 /// Example: `x = Foo { field: y }` technically creates
270 /// intermediate regions representing the "type of `Foo { field: y
271 /// }`", and data flows from `y` into those variables, but they
272 /// are not very interesting. The assignment into `x` on the other
275 // Boring and applicable everywhere.
278 /// A constraint that doesn't correspond to anything the user sees.
282 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
283 #[derive(RustcEncodable, RustcDecodable, HashStable)]
284 pub enum ReturnConstraint {
286 ClosureUpvar(hir::HirId),
289 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
290 /// that must outlive some region.
291 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
292 pub enum ClosureOutlivesSubject<'tcx> {
293 /// Subject is a type, typically a type parameter, but could also
294 /// be a projection. Indicates a requirement like `T: 'a` being
295 /// passed to the caller, where the type here is `T`.
297 /// The type here is guaranteed not to contain any free regions at
301 /// Subject is a free region from the closure. Indicates a requirement
302 /// like `'a: 'b` being passed to the caller; the region here is `'a`.
303 Region(ty::RegionVid),
306 /// The constituent parts of an ADT or array.
307 #[derive(Copy, Clone, Debug, HashStable)]
308 pub struct DestructuredConst<'tcx> {
309 pub variant: Option<VariantIdx>,
310 pub fields: &'tcx [&'tcx ty::Const<'tcx>],