1 //! Values computed by queries that use MIR. 2 3 use crate::mir::interpret::ConstValue; 4 use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; 5 use rustc_data_structures::fx::FxIndexMap; 6 use rustc_data_structures::unord::UnordSet; 7 use rustc_errors::ErrorGuaranteed; 8 use rustc_hir as hir; 9 use rustc_hir::def_id::LocalDefId; 10 use rustc_index::bit_set::BitMatrix; 11 use rustc_index::{Idx, IndexVec}; 12 use rustc_span::symbol::Symbol; 13 use rustc_span::Span; 14 use rustc_target::abi::{FieldIdx, VariantIdx}; 15 use smallvec::SmallVec; 16 use std::cell::Cell; 17 use std::fmt::{self, Debug}; 18 19 use super::SourceInfo; 20 21 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] 22 pub enum UnsafetyViolationKind { 23 /// Unsafe operation outside `unsafe`. 24 General, 25 /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block. 26 /// Has to be handled as a lint for backwards compatibility. 27 UnsafeFn, 28 } 29 30 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] 31 pub enum UnsafetyViolationDetails { 32 CallToUnsafeFunction, 33 UseOfInlineAssembly, 34 InitializingTypeWith, 35 CastOfPointerToInt, 36 UseOfMutableStatic, 37 UseOfExternStatic, 38 DerefOfRawPointer, 39 AccessToUnionField, 40 MutationOfLayoutConstrainedField, 41 BorrowOfLayoutConstrainedField, 42 CallToFunctionWith, 43 } 44 45 impl UnsafetyViolationDetails { description_and_note(&self) -> (&'static str, &'static str)46 pub fn description_and_note(&self) -> (&'static str, &'static str) { 47 use UnsafetyViolationDetails::*; 48 match self { 49 CallToUnsafeFunction => ( 50 "call to unsafe function", 51 "consult the function's documentation for information on how to avoid undefined \ 52 behavior", 53 ), 54 UseOfInlineAssembly => ( 55 "use of inline assembly", 56 "inline assembly is entirely unchecked and can cause undefined behavior", 57 ), 58 InitializingTypeWith => ( 59 "initializing type with `rustc_layout_scalar_valid_range` attr", 60 "initializing a layout restricted type's field with a value outside the valid \ 61 range is undefined behavior", 62 ), 63 CastOfPointerToInt => { 64 ("cast of pointer to int", "casting pointers to integers in constants") 65 } 66 UseOfMutableStatic => ( 67 "use of mutable static", 68 "mutable statics can be mutated by multiple threads: aliasing violations or data \ 69 races will cause undefined behavior", 70 ), 71 UseOfExternStatic => ( 72 "use of extern static", 73 "extern statics are not controlled by the Rust type system: invalid data, \ 74 aliasing violations or data races will cause undefined behavior", 75 ), 76 DerefOfRawPointer => ( 77 "dereference of raw pointer", 78 "raw pointers may be null, dangling or unaligned; they can violate aliasing rules \ 79 and cause data races: all of these are undefined behavior", 80 ), 81 AccessToUnionField => ( 82 "access to union field", 83 "the field may not be properly initialized: using uninitialized data will cause \ 84 undefined behavior", 85 ), 86 MutationOfLayoutConstrainedField => ( 87 "mutation of layout constrained field", 88 "mutating layout constrained fields cannot statically be checked for valid values", 89 ), 90 BorrowOfLayoutConstrainedField => ( 91 "borrow of layout constrained field with interior mutability", 92 "references to fields of layout constrained fields lose the constraints. Coupled \ 93 with interior mutability, the field can be changed to invalid values", 94 ), 95 CallToFunctionWith => ( 96 "call to function with `#[target_feature]`", 97 "can only be called if the required target features are available", 98 ), 99 } 100 } 101 } 102 103 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] 104 pub struct UnsafetyViolation { 105 pub source_info: SourceInfo, 106 pub lint_root: hir::HirId, 107 pub kind: UnsafetyViolationKind, 108 pub details: UnsafetyViolationDetails, 109 } 110 111 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] 112 pub enum UnusedUnsafe { 113 /// `unsafe` block contains no unsafe operations 114 /// > ``unnecessary `unsafe` block`` 115 Unused, 116 /// `unsafe` block nested under another (used) `unsafe` block 117 /// > ``… because it's nested under this `unsafe` block`` 118 InUnsafeBlock(hir::HirId), 119 } 120 121 #[derive(TyEncodable, TyDecodable, HashStable, Debug)] 122 pub struct UnsafetyCheckResult { 123 /// Violations that are propagated *upwards* from this function. 124 pub violations: Vec<UnsafetyViolation>, 125 126 /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint. 127 pub used_unsafe_blocks: UnordSet<hir::HirId>, 128 129 /// This is `Some` iff the item is not a closure. 130 pub unused_unsafes: Option<Vec<(hir::HirId, UnusedUnsafe)>>, 131 } 132 133 rustc_index::newtype_index! { 134 #[derive(HashStable)] 135 #[debug_format = "_{}"] 136 pub struct GeneratorSavedLocal {} 137 } 138 139 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] 140 pub struct GeneratorSavedTy<'tcx> { 141 pub ty: Ty<'tcx>, 142 /// Source info corresponding to the local in the original MIR body. 143 pub source_info: SourceInfo, 144 /// Whether the local should be ignored for trait bound computations. 145 pub ignore_for_traits: bool, 146 } 147 148 /// The layout of generator state. 149 #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] 150 pub struct GeneratorLayout<'tcx> { 151 /// The type of every local stored inside the generator. 152 pub field_tys: IndexVec<GeneratorSavedLocal, GeneratorSavedTy<'tcx>>, 153 154 /// The name for debuginfo. 155 pub field_names: IndexVec<GeneratorSavedLocal, Option<Symbol>>, 156 157 /// Which of the above fields are in each variant. Note that one field may 158 /// be stored in multiple variants. 159 pub variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, GeneratorSavedLocal>>, 160 161 /// The source that led to each variant being created (usually, a yield or 162 /// await). 163 pub variant_source_info: IndexVec<VariantIdx, SourceInfo>, 164 165 /// Which saved locals are storage-live at the same time. Locals that do not 166 /// have conflicts with each other are allowed to overlap in the computed 167 /// layout. 168 #[type_foldable(identity)] 169 #[type_visitable(ignore)] 170 pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>, 171 } 172 173 impl Debug for GeneratorLayout<'_> { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result174 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 175 /// Prints an iterator of (key, value) tuples as a map. 176 struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>); 177 impl<'a, K, V> MapPrinter<'a, K, V> { 178 fn new(iter: impl Iterator<Item = (K, V)> + 'a) -> Self { 179 Self(Cell::new(Some(Box::new(iter)))) 180 } 181 } 182 impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> { 183 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 184 fmt.debug_map().entries(self.0.take().unwrap()).finish() 185 } 186 } 187 188 /// Prints the generator variant name. 189 struct GenVariantPrinter(VariantIdx); 190 impl From<VariantIdx> for GenVariantPrinter { 191 fn from(idx: VariantIdx) -> Self { 192 GenVariantPrinter(idx) 193 } 194 } 195 impl Debug for GenVariantPrinter { 196 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 197 let variant_name = ty::GeneratorSubsts::variant_name(self.0); 198 if fmt.alternate() { 199 write!(fmt, "{:9}({:?})", variant_name, self.0) 200 } else { 201 write!(fmt, "{}", variant_name) 202 } 203 } 204 } 205 206 /// Forces its contents to print in regular mode instead of alternate mode. 207 struct OneLinePrinter<T>(T); 208 impl<T: Debug> Debug for OneLinePrinter<T> { 209 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 210 write!(fmt, "{:?}", self.0) 211 } 212 } 213 214 fmt.debug_struct("GeneratorLayout") 215 .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated())) 216 .field( 217 "variant_fields", 218 &MapPrinter::new( 219 self.variant_fields 220 .iter_enumerated() 221 .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))), 222 ), 223 ) 224 .field("storage_conflicts", &self.storage_conflicts) 225 .finish() 226 } 227 } 228 229 #[derive(Debug, TyEncodable, TyDecodable, HashStable)] 230 pub struct BorrowCheckResult<'tcx> { 231 /// All the opaque types that are restricted to concrete types 232 /// by this function. Unlike the value in `TypeckResults`, this has 233 /// unerased regions. 234 pub concrete_opaque_types: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>, 235 pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>, 236 pub used_mut_upvars: SmallVec<[FieldIdx; 8]>, 237 pub tainted_by_errors: Option<ErrorGuaranteed>, 238 } 239 240 /// The result of the `mir_const_qualif` query. 241 /// 242 /// Each field (except `error_occurred`) corresponds to an implementer of the `Qualif` trait in 243 /// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each 244 /// `Qualif`. 245 #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)] 246 pub struct ConstQualifs { 247 pub has_mut_interior: bool, 248 pub needs_drop: bool, 249 pub needs_non_const_drop: bool, 250 pub custom_eq: bool, 251 pub tainted_by_errors: Option<ErrorGuaranteed>, 252 } 253 254 /// After we borrow check a closure, we are left with various 255 /// requirements that we have inferred between the free regions that 256 /// appear in the closure's signature or on its field types. These 257 /// requirements are then verified and proved by the closure's 258 /// creating function. This struct encodes those requirements. 259 /// 260 /// The requirements are listed as being between various `RegionVid`. The 0th 261 /// region refers to `'static`; subsequent region vids refer to the free 262 /// regions that appear in the closure (or generator's) type, in order of 263 /// appearance. (This numbering is actually defined by the `UniversalRegions` 264 /// struct in the NLL region checker. See for example 265 /// `UniversalRegions::closure_mapping`.) Note the free regions in the 266 /// closure's signature and captures are erased. 267 /// 268 /// Example: If type check produces a closure with the closure substs: 269 /// 270 /// ```text 271 /// ClosureSubsts = [ 272 /// 'a, // From the parent. 273 /// 'b, 274 /// i8, // the "closure kind" 275 /// for<'x> fn(&'<erased> &'x u32) -> &'x u32, // the "closure signature" 276 /// &'<erased> String, // some upvar 277 /// ] 278 /// ``` 279 /// 280 /// We would "renumber" each free region to a unique vid, as follows: 281 /// 282 /// ```text 283 /// ClosureSubsts = [ 284 /// '1, // From the parent. 285 /// '2, 286 /// i8, // the "closure kind" 287 /// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature" 288 /// &'4 String, // some upvar 289 /// ] 290 /// ``` 291 /// 292 /// Now the code might impose a requirement like `'1: '2`. When an 293 /// instance of the closure is created, the corresponding free regions 294 /// can be extracted from its type and constrained to have the given 295 /// outlives relationship. 296 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] 297 pub struct ClosureRegionRequirements<'tcx> { 298 /// The number of external regions defined on the closure. In our 299 /// example above, it would be 3 -- one for `'static`, then `'1` 300 /// and `'2`. This is just used for a sanity check later on, to 301 /// make sure that the number of regions we see at the callsite 302 /// matches. 303 pub num_external_vids: usize, 304 305 /// Requirements between the various free regions defined in 306 /// indices. 307 pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>, 308 } 309 310 /// Indicates an outlives-constraint between a type or between two 311 /// free regions declared on the closure. 312 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] 313 pub struct ClosureOutlivesRequirement<'tcx> { 314 // This region or type ... 315 pub subject: ClosureOutlivesSubject<'tcx>, 316 317 // ... must outlive this one. 318 pub outlived_free_region: ty::RegionVid, 319 320 // If not, report an error here ... 321 pub blame_span: Span, 322 323 // ... due to this reason. 324 pub category: ConstraintCategory<'tcx>, 325 } 326 327 // Make sure this enum doesn't unintentionally grow 328 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] 329 rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16); 330 331 /// Outlives-constraints can be categorized to determine whether and why they 332 /// are interesting (for error reporting). Order of variants indicates sort 333 /// order of the category, thereby influencing diagnostic output. 334 /// 335 /// See also `rustc_const_eval::borrow_check::constraints`. 336 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] 337 #[derive(TyEncodable, TyDecodable, HashStable, Lift, TypeVisitable, TypeFoldable)] 338 pub enum ConstraintCategory<'tcx> { 339 Return(ReturnConstraint), 340 Yield, 341 UseAsConst, 342 UseAsStatic, 343 TypeAnnotation, 344 Cast, 345 346 /// A constraint that came from checking the body of a closure. 347 /// 348 /// We try to get the category that the closure used when reporting this. 349 ClosureBounds, 350 351 /// Contains the function type if available. 352 CallArgument(Option<Ty<'tcx>>), 353 CopyBound, 354 SizedBound, 355 Assignment, 356 /// A constraint that came from a usage of a variable (e.g. in an ADT expression 357 /// like `Foo { field: my_val }`) 358 Usage, 359 OpaqueType, 360 ClosureUpvar(FieldIdx), 361 362 /// A constraint from a user-written predicate 363 /// with the provided span, written on the item 364 /// with the given `DefId` 365 Predicate(Span), 366 367 /// A "boring" constraint (caused by the given location) is one that 368 /// the user probably doesn't want to see described in diagnostics, 369 /// because it is kind of an artifact of the type system setup. 370 Boring, 371 // Boring and applicable everywhere. 372 BoringNoLocation, 373 374 /// A constraint that doesn't correspond to anything the user sees. 375 Internal, 376 } 377 378 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] 379 #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] 380 pub enum ReturnConstraint { 381 Normal, 382 ClosureUpvar(FieldIdx), 383 } 384 385 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing 386 /// that must outlive some region. 387 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] 388 pub enum ClosureOutlivesSubject<'tcx> { 389 /// Subject is a type, typically a type parameter, but could also 390 /// be a projection. Indicates a requirement like `T: 'a` being 391 /// passed to the caller, where the type here is `T`. 392 Ty(ClosureOutlivesSubjectTy<'tcx>), 393 394 /// Subject is a free region from the closure. Indicates a requirement 395 /// like `'a: 'b` being passed to the caller; the region here is `'a`. 396 Region(ty::RegionVid), 397 } 398 399 /// Represents a `ty::Ty` for use in [`ClosureOutlivesSubject`]. 400 /// 401 /// This abstraction is necessary because the type may include `ReVar` regions, 402 /// which is what we use internally within NLL code, and they can't be used in 403 /// a query response. 404 /// 405 /// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this 406 /// type is not recognized as a binder for late-bound region. 407 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] 408 pub struct ClosureOutlivesSubjectTy<'tcx> { 409 inner: Ty<'tcx>, 410 } 411 412 impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { 413 /// All regions of `ty` must be of kind `ReVar` and must represent 414 /// universal regions *external* to the closure. bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self415 pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { 416 let inner = tcx.fold_regions(ty, |r, depth| match r.kind() { 417 ty::ReVar(vid) => { 418 let br = 419 ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon(None) }; 420 ty::Region::new_late_bound(tcx, depth, br) 421 } 422 _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"), 423 }); 424 425 Self { inner } 426 } 427 instantiate( self, tcx: TyCtxt<'tcx>, mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>, ) -> Ty<'tcx>428 pub fn instantiate( 429 self, 430 tcx: TyCtxt<'tcx>, 431 mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>, 432 ) -> Ty<'tcx> { 433 tcx.fold_regions(self.inner, |r, depth| match r.kind() { 434 ty::ReLateBound(debruijn, br) => { 435 debug_assert_eq!(debruijn, depth); 436 map(ty::RegionVid::new(br.var.index())) 437 } 438 _ => bug!("unexpected region {r:?}"), 439 }) 440 } 441 } 442 443 /// The constituent parts of a mir constant of kind ADT or array. 444 #[derive(Copy, Clone, Debug, HashStable)] 445 pub struct DestructuredConstant<'tcx> { 446 pub variant: Option<VariantIdx>, 447 pub fields: &'tcx [(ConstValue<'tcx>, Ty<'tcx>)], 448 } 449 450 /// Coverage information summarized from a MIR if instrumented for source code coverage (see 451 /// compiler option `-Cinstrument-coverage`). This information is generated by the 452 /// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query. 453 #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)] 454 pub struct CoverageInfo { 455 /// The total number of coverage region counters added to the MIR `Body`. 456 pub num_counters: u32, 457 458 /// The total number of coverage region counter expressions added to the MIR `Body`. 459 pub num_expressions: u32, 460 } 461