Skip to content

Commit

Permalink
Split rustc_mir::{build, hair, lints} into their own crate
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewjasper committed Jan 12, 2020
1 parent 1389494 commit b358929
Show file tree
Hide file tree
Showing 45 changed files with 621 additions and 525 deletions.
24 changes: 23 additions & 1 deletion Cargo.lock
Expand Up @@ -3633,6 +3633,7 @@ dependencies = [
"rustc_lint",
"rustc_metadata",
"rustc_mir",
"rustc_mir_build",
"rustc_parse",
"rustc_passes",
"rustc_plugin_impl",
Expand Down Expand Up @@ -3721,7 +3722,6 @@ dependencies = [
name = "rustc_mir"
version = "0.0.0"
dependencies = [
"arena",
"either",
"graphviz",
"itertools 0.8.0",
Expand All @@ -3744,6 +3744,28 @@ dependencies = [
"syntax",
]

[[package]]
name = "rustc_mir_build"
version = "0.0.0"
dependencies = [
"arena",
"itertools 0.8.0",
"log",
"rustc",
"rustc_apfloat",
"rustc_data_structures",
"rustc_error_codes",
"rustc_errors",
"rustc_hir",
"rustc_index",
"rustc_macros",
"rustc_span",
"rustc_target",
"serialize",
"smallvec 1.0.0",
"syntax",
]

[[package]]
name = "rustc_parse"
version = "0.0.0"
Expand Down
225 changes: 4 additions & 221 deletions src/librustc/mir/mod.rs
@@ -1,5 +1,3 @@
// ignore-tidy-filelength

//! MIR datatypes and passes. See the [rustc guide] for more info.
//!
//! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html
Expand All @@ -23,14 +21,12 @@ use polonius_engine::Atom;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::graph::dominators::Dominators;
use rustc_data_structures::graph::{self, GraphSuccessors};
use rustc_data_structures::sync::Lrc;
use rustc_index::bit_set::BitMatrix;
use rustc_index::vec::{Idx, IndexVec};
use rustc_macros::HashStable;
use rustc_serialize::{Decodable, Encodable};
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use smallvec::SmallVec;
use std::borrow::Cow;
use std::fmt::{self, Debug, Display, Formatter, Write};
use std::ops::Index;
Expand All @@ -39,13 +35,15 @@ use std::{iter, mem, option, u32};
pub use syntax::ast::Mutability;
use syntax::ast::Name;

pub use crate::mir::cache::{BodyAndCache, ReadOnlyBodyAndCache};
pub use crate::mir::interpret::AssertMessage;
pub use self::cache::{BodyAndCache, ReadOnlyBodyAndCache};
pub use self::interpret::AssertMessage;
pub use self::query::*;
pub use crate::read_only;

mod cache;
pub mod interpret;
pub mod mono;
mod query;
pub mod tcx;
pub mod traversal;
pub mod visit;
Expand Down Expand Up @@ -2581,221 +2579,6 @@ impl Location {
}
}

#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
pub enum UnsafetyViolationKind {
General,
/// Permitted both in `const fn`s and regular `fn`s.
GeneralAndConstFn,
BorrowPacked(hir::HirId),
}

#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
pub struct UnsafetyViolation {
pub source_info: SourceInfo,
pub description: Symbol,
pub details: Symbol,
pub kind: UnsafetyViolationKind,
}

#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
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.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
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>>,

/// 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>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
pub struct BorrowCheckResult<'tcx> {
pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
pub used_mut_upvars: SmallVec<[Field; 8]>,
}

/// The result of the `mir_const_qualif` query.
///
/// Each field corresponds to an implementer of the `Qualif` trait in
/// `librustc_mir/transform/check_consts/qualifs.rs`. See that file for more information on each
/// `Qualif`.
#[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)]
pub struct ConstQualifs {
pub has_mut_interior: bool,
pub needs_drop: bool,
}

/// 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.
///
/// 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 that we treat the free
/// regions in the closure's type "as if" they were erased, so their
/// precise identity is not important, only their position.
///
/// Example: If type check produces a closure with the closure substs:
///
/// ```text
/// ClosureSubsts = [
/// i8, // the "closure kind"
/// for<'x> fn(&'a &'x u32) -> &'x u32, // the "closure signature"
/// &'a String, // some upvar
/// ]
/// ```
///
/// here, there is one unique free region (`'a`) but it appears
/// twice. We would "renumber" each occurrence to a unique vid, as follows:
///
/// ```text
/// ClosureSubsts = [
/// i8, // the "closure kind"
/// for<'x> fn(&'1 &'x u32) -> &'x u32, // the "closure signature"
/// &'2 String, // some upvar
/// ]
/// ```
///
/// 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.
///
/// 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 as `ReClosureBound`
/// instances assigned one of these same indices. Those regions will
/// be substituted away by the creator. We use `ReClosureBound` in
/// that case because the regions must be allocated in the global
/// `TyCtxt`, and hence we cannot use `ReVar` (which is what we use
/// internally within the rest of the NLL code).
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
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.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
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.
///
/// See also [rustc_mir::borrow_check::nll::constraints].
#[derive(
Copy,
Clone,
Debug,
Eq,
PartialEq,
PartialOrd,
Ord,
Hash,
RustcEncodable,
RustcDecodable,
HashStable
)]
pub enum ConstraintCategory {
Return,
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,

/// 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,
}

/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
/// that must outlive some region.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
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),
}

/*
* `TypeFoldable` implementations for MIR types
*/
Expand Down

0 comments on commit b358929

Please sign in to comment.