Auto merge of #67901 - matthewjasper:split-mir-build, r=nagisa

Split MIR building into its own crate

This moves `rustc_mir::{build, hair, lints}` to `rustc_mir_build`.
The new crate only has a `provide` function as it's public API.

Based on #67898

cc @Centril @rust-lang/compiler
r? @oli-obk
This commit is contained in:
bors 2020-01-12 09:44:55 +00:00
commit 59c1db0339
45 changed files with 621 additions and 525 deletions

View File

@ -3633,6 +3633,7 @@ dependencies = [
"rustc_lint",
"rustc_metadata",
"rustc_mir",
"rustc_mir_build",
"rustc_parse",
"rustc_passes",
"rustc_plugin_impl",
@ -3722,7 +3723,6 @@ dependencies = [
name = "rustc_mir"
version = "0.0.0"
dependencies = [
"arena",
"either",
"graphviz",
"itertools 0.8.0",
@ -3745,6 +3745,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"

View File

@ -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
@ -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;
@ -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;
@ -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
*/

223
src/librustc/mir/query.rs Normal file
View File

@ -0,0 +1,223 @@
//! Values computed by queries that use MIR.
use crate::ty::{self, Ty};
use rustc_data_structures::sync::Lrc;
use rustc_hir as hir;
use rustc_index::bit_set::BitMatrix;
use rustc_index::vec::IndexVec;
use rustc_span::{Span, Symbol};
use rustc_target::abi::VariantIdx;
use smallvec::SmallVec;
use super::{Field, SourceInfo};
#[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)]
#[derive(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),
}
/// The constituent parts of an ADT or array.
#[derive(Copy, Clone, Debug, HashStable)]
pub struct DestructuredConst<'tcx> {
pub variant: VariantIdx,
pub fields: &'tcx [&'tcx ty::Const<'tcx>],
}

View File

@ -505,6 +505,15 @@ rustc_queries! {
desc { "extract field of const" }
}
/// Destructure a constant ADT or array into its variant indent and its
/// field values.
query destructure_const(
key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
) -> mir::DestructuredConst<'tcx> {
no_force
desc { "destructure constant" }
}
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> &'tcx ty::Const<'tcx> {
no_force
desc { "get a &core::panic::Location referring to a span" }

View File

@ -142,7 +142,7 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
}
}
impl<'tcx> Key for ty::Const<'tcx> {
impl<'tcx> Key for &'tcx ty::Const<'tcx> {
fn query_crate(&self) -> CrateNum {
LOCAL_CRATE
}

View File

@ -32,6 +32,7 @@ rustc_codegen_llvm = { path = "../librustc_codegen_llvm", optional = true }
rustc_hir = { path = "../librustc_hir" }
rustc_metadata = { path = "../librustc_metadata" }
rustc_mir = { path = "../librustc_mir" }
rustc_mir_build = { path = "../librustc_mir_build" }
rustc_passes = { path = "../librustc_passes" }
rustc_typeck = { path = "../librustc_typeck" }
rustc_lint = { path = "../librustc_lint" }

View File

@ -29,6 +29,7 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_incremental;
use rustc_lint::LintStore;
use rustc_mir as mir;
use rustc_mir_build as mir_build;
use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
use rustc_passes::{self, hir_stats, layout_test};
use rustc_plugin_impl as plugin;
@ -671,6 +672,7 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) {
plugin::build::provide(providers);
rustc::hir::provide(providers);
mir::provide(providers);
mir_build::provide(providers);
rustc_privacy::provide(providers);
typeck::provide(providers);
ty::provide(providers);

View File

@ -10,7 +10,6 @@ path = "lib.rs"
doctest = false
[dependencies]
arena = { path = "../libarena" }
either = "1.5.0"
dot = { path = "../libgraphviz", package = "graphviz" }
itertools = "0.8"

View File

@ -61,15 +61,32 @@ pub(crate) fn const_caller_location<'tcx>(
tcx.mk_const(loc_const)
}
// this function uses `unwrap` copiously, because an already validated constant must have valid
// fields and can thus never fail outside of compiler bugs
pub(crate) fn const_variant_index<'tcx>(
// this function uses `unwrap` copiously, because an already validated constant
// must have valid fields and can thus never fail outside of compiler bugs
pub(crate) fn destructure_const<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
val: &'tcx ty::Const<'tcx>,
) -> VariantIdx {
trace!("const_variant_index: {:?}", val);
) -> mir::DestructuredConst<'tcx> {
trace!("destructure_const: {:?}", val);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
let op = ecx.eval_const_to_op(val, None).unwrap();
ecx.read_discriminant(op).unwrap().1
let variant = ecx.read_discriminant(op).unwrap().1;
let field_count = match val.ty.kind {
ty::Array(_, len) => len.eval_usize(tcx, param_env),
ty::Adt(def, _) => def.variants[variant].fields.len() as u64,
ty::Tuple(substs) => substs.len() as u64,
_ => bug!("cannot destructure constant {:?}", val),
};
let down = ecx.operand_downcast(op, variant).unwrap();
let fields_iter = (0..field_count).map(|i| {
let field_op = ecx.operand_field(down, i).unwrap();
op_to_const(&ecx, field_op)
});
let fields = tcx.arena.alloc_from_iter(fields_iter);
mir::DestructuredConst { variant, fields }
}

View File

@ -36,12 +36,9 @@ extern crate log;
extern crate rustc;
mod borrow_check;
mod build;
pub mod const_eval;
pub mod dataflow;
mod hair;
pub mod interpret;
mod lints;
pub mod monomorphize;
mod shim;
pub mod transform;
@ -57,10 +54,13 @@ pub fn provide(providers: &mut Providers<'_>) {
monomorphize::partitioning::provide(providers);
providers.const_eval_validated = const_eval::const_eval_validated_provider;
providers.const_eval_raw = const_eval::const_eval_raw_provider;
providers.check_match = hair::pattern::check_match;
providers.const_caller_location = const_eval::const_caller_location;
providers.const_field = |tcx, param_env_and_value| {
let (param_env, (value, field)) = param_env_and_value.into_parts();
const_eval::const_field(tcx, param_env, None, field, value)
};
providers.destructure_const = |tcx, param_env_and_value| {
let (param_env, value) = param_env_and_value.into_parts();
const_eval::destructure_const(tcx, param_env, value)
}
}

View File

@ -1,4 +1,4 @@
use crate::{build, shim};
use crate::{shim, util};
use rustc::hir::map::Map;
use rustc::mir::{BodyAndCache, ConstQualifs, MirPhase, Promoted};
use rustc::ty::query::Providers;
@ -41,7 +41,6 @@ pub(crate) fn provide(providers: &mut Providers<'_>) {
self::check_unsafety::provide(providers);
*providers = Providers {
mir_keys,
mir_built,
mir_const,
mir_const_qualif,
mir_validated,
@ -98,11 +97,6 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> &DefIdSet {
tcx.arena.alloc(set)
}
fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyAndCache<'_>> {
let mir = build::mir_build(tcx, def_id);
tcx.alloc_steal_mir(mir)
}
/// Where a specific `mir::Body` comes from.
#[derive(Debug, Copy, Clone)]
pub struct MirSource<'tcx> {
@ -222,6 +216,9 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyAndCache<'_>> {
let _ = tcx.unsafety_check_result(def_id);
let mut body = tcx.mir_built(def_id).steal();
util::dump_mir(tcx, None, "mir_map", &0, MirSource::item(def_id), &body, |_, _| Ok(()));
run_passes(
tcx,
&mut body,

View File

@ -0,0 +1,28 @@
[package]
authors = ["The Rust Project Developers"]
name = "rustc_mir_build"
version = "0.0.0"
edition = "2018"
[lib]
name = "rustc_mir_build"
path = "lib.rs"
doctest = false
[dependencies]
arena = { path = "../libarena" }
itertools = "0.8"
log = "0.4"
rustc = { path = "../librustc" }
rustc_apfloat = { path = "../librustc_apfloat" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_index = { path = "../librustc_index" }
rustc_errors = { path = "../librustc_errors" }
rustc_hir = { path = "../librustc_hir" }
rustc_macros = { path = "../librustc_macros" }
rustc_serialize = { path = "../libserialize", package = "serialize" }
rustc_span = { path = "../librustc_span" }
rustc_target = { path = "../librustc_target" }
syntax = { path = "../libsyntax" }
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
rustc_error_codes = { path = "../librustc_error_codes" }

View File

@ -7,7 +7,7 @@ use rustc_hir as hir;
use rustc_span::Span;
impl<'a, 'tcx> Builder<'a, 'tcx> {
pub fn ast_block(
crate fn ast_block(
&mut self,
destination: &Place<'tcx>,
block: BasicBlock,

View File

@ -4,33 +4,33 @@ use crate::build::CFG;
use rustc::mir::*;
impl<'tcx> CFG<'tcx> {
pub fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
crate fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
&self.basic_blocks[blk]
}
pub fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> {
crate fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> {
&mut self.basic_blocks[blk]
}
// llvm.org/PR32488 makes this function use an excess of stack space. Mark
// it as #[inline(never)] to keep rustc's stack use in check.
#[inline(never)]
pub fn start_new_block(&mut self) -> BasicBlock {
crate fn start_new_block(&mut self) -> BasicBlock {
self.basic_blocks.push(BasicBlockData::new(None))
}
pub fn start_new_cleanup_block(&mut self) -> BasicBlock {
crate fn start_new_cleanup_block(&mut self) -> BasicBlock {
let bb = self.start_new_block();
self.block_data_mut(bb).is_cleanup = true;
bb
}
pub fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
crate fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
debug!("push({:?}, {:?})", block, statement);
self.block_data_mut(block).statements.push(statement);
}
pub fn push_assign(
crate fn push_assign(
&mut self,
block: BasicBlock,
source_info: SourceInfo,
@ -43,7 +43,7 @@ impl<'tcx> CFG<'tcx> {
);
}
pub fn push_assign_constant(
crate fn push_assign_constant(
&mut self,
block: BasicBlock,
source_info: SourceInfo,
@ -53,7 +53,7 @@ impl<'tcx> CFG<'tcx> {
self.push_assign(block, source_info, temp, Rvalue::Use(Operand::Constant(box constant)));
}
pub fn push_assign_unit(
crate fn push_assign_unit(
&mut self,
block: BasicBlock,
source_info: SourceInfo,
@ -67,7 +67,7 @@ impl<'tcx> CFG<'tcx> {
);
}
pub fn push_fake_read(
crate fn push_fake_read(
&mut self,
block: BasicBlock,
source_info: SourceInfo,
@ -79,7 +79,7 @@ impl<'tcx> CFG<'tcx> {
self.push(block, stmt);
}
pub fn terminate(
crate fn terminate(
&mut self,
block: BasicBlock,
source_info: SourceInfo,
@ -96,7 +96,7 @@ impl<'tcx> CFG<'tcx> {
}
/// In the `origin` block, push a `goto -> target` terminator.
pub fn goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock) {
crate fn goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock) {
self.terminate(origin, source_info, TerminatorKind::Goto { target })
}
}

View File

@ -8,7 +8,7 @@ use rustc::ty::CanonicalUserTypeAnnotation;
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, yielding a compile-time constant. Assumes that
/// `expr` is a valid compile-time constant!
pub fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
crate fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{

View File

@ -13,7 +13,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// The operand returned from this function will *not be valid* after
/// an ExprKind::Scope is passed, so please do *not* return it from
/// functions to avoid bad miscompiles.
pub fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
@ -27,7 +27,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// this time.
///
/// The operand is known to be live until the end of `scope`.
pub fn as_operand<M>(
crate fn as_operand<M>(
&mut self,
block: BasicBlock,
scope: Option<region::Scope>,

View File

@ -24,7 +24,7 @@ struct PlaceBuilder<'tcx> {
projection: Vec<PlaceElem<'tcx>>,
}
impl PlaceBuilder<'tcx> {
impl<'tcx> PlaceBuilder<'tcx> {
fn into_place(self, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
Place { local: self.local, projection: tcx.intern_place_elems(&self.projection) }
}
@ -47,7 +47,7 @@ impl PlaceBuilder<'tcx> {
}
}
impl From<Local> for PlaceBuilder<'tcx> {
impl<'tcx> From<Local> for PlaceBuilder<'tcx> {
fn from(local: Local) -> Self {
Self { local, projection: Vec::new() }
}
@ -66,7 +66,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Extra care is needed if any user code is allowed to run between calling
/// this method and using it, as is the case for `match` and index
/// expressions.
pub fn as_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
crate fn as_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
@ -89,7 +89,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// place. The place itself may or may not be mutable:
/// * If this expr is a place expr like a.b, then we will return that place.
/// * Otherwise, a temporary is created: in that event, it will be an immutable temporary.
pub fn as_read_only_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
crate fn as_read_only_place<M>(
&mut self,
mut block: BasicBlock,
expr: M,
) -> BlockAnd<Place<'tcx>>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{

View File

@ -18,7 +18,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// The operand returned from this function will *not be valid* after
/// an ExprKind::Scope is passed, so please do *not* return it from
/// functions to avoid bad miscompiles.
pub fn as_local_rvalue<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Rvalue<'tcx>>
crate fn as_local_rvalue<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Rvalue<'tcx>>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
@ -276,7 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}
pub fn build_binary_op(
crate fn build_binary_op(
&mut self,
mut block: BasicBlock,
op: BinOp,

View File

@ -11,7 +11,7 @@ use rustc_span::symbol::sym;
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr` into a fresh temporary. This is used when building
/// up rvalues so as to freeze the value that will be consumed.
pub fn as_temp<M>(
crate fn as_temp<M>(
&mut self,
block: BasicBlock,
temp_lifetime: Option<region::Scope>,

View File

@ -1,7 +1,7 @@
use crate::hair::*;
#[derive(Debug, PartialEq)]
pub enum Category {
crate enum Category {
// An assignable memory location like `x`, `x.f`, `foo()[3]`, that
// sort of thing. Something that could appear on the LHS of an `=`
// sign.
@ -19,7 +19,7 @@ pub enum Category {
// Rvalues fall into different "styles" that will determine which fn
// is best suited to generate them.
#[derive(Debug, PartialEq)]
pub enum RvalueFunc {
crate enum RvalueFunc {
// Best generated by `into`. This is generally exprs that
// cause branching, like `match`, but also includes calls.
Into,
@ -31,7 +31,7 @@ pub enum RvalueFunc {
/// Determines the category for a given expression. Note that scope
/// and paren expressions have no category.
impl Category {
pub fn of(ek: &ExprKind<'_>) -> Option<Category> {
crate fn of(ek: &ExprKind<'_>) -> Option<Category> {
match *ek {
ExprKind::Scope { .. } => None,

View File

@ -14,7 +14,7 @@ use rustc_target::spec::abi::Abi;
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, storing the result into `destination`, which
/// is assumed to be uninitialized.
pub fn into_expr(
crate fn into_expr(
&mut self,
destination: &Place<'tcx>,
mut block: BasicBlock,

View File

@ -10,7 +10,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
/// span of that statement (including its semicolon, if any).
/// The scope is used if a statement temporary must be dropped.
pub fn stmt_expr(
crate fn stmt_expr(
&mut self,
mut block: BasicBlock,
expr: Expr<'tcx>,

View File

@ -18,7 +18,12 @@ pub(in crate::build) trait EvalInto<'tcx> {
}
impl<'a, 'tcx> Builder<'a, 'tcx> {
pub fn into<E>(&mut self, destination: &Place<'tcx>, block: BasicBlock, expr: E) -> BlockAnd<()>
crate fn into<E>(
&mut self,
destination: &Place<'tcx>,
block: BasicBlock,
expr: E,
) -> BlockAnd<()>
where
E: EvalInto<'tcx>,
{

View File

@ -81,7 +81,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
///
/// * From each prebinding block to the next prebinding block.
/// * From each otherwise block to the next prebinding block.
pub fn match_expr(
crate fn match_expr(
&mut self,
destination: &Place<'tcx>,
span: Span,
@ -417,7 +417,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}
pub fn place_into_pattern(
crate fn place_into_pattern(
&mut self,
block: BasicBlock,
irrefutable_pat: Pat<'tcx>,
@ -488,7 +488,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// scope for the bindings in these patterns, if such a scope had to be
/// created. NOTE: Declaring the bindings should always be done in their
/// drop scope.
pub fn declare_bindings(
crate fn declare_bindings(
&mut self,
mut visibility_scope: Option<SourceScope>,
scope_span: Span,
@ -525,7 +525,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
visibility_scope
}
pub fn storage_live_binding(
crate fn storage_live_binding(
&mut self,
block: BasicBlock,
var: HirId,
@ -540,7 +540,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Place::from(local_id)
}
pub fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) {
crate fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) {
let local_id = self.var_local_id(var, for_guard);
let region_scope = self.hir.region_scope_tree.var_scope(var.local_id);
self.schedule_drop(span, region_scope, local_id, DropKind::Value);
@ -641,7 +641,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
#[derive(Debug)]
pub struct Candidate<'pat, 'tcx> {
crate struct Candidate<'pat, 'tcx> {
// span of the original pattern that gave rise to this candidate
span: Span,
@ -685,7 +685,7 @@ struct Ascription<'tcx> {
}
#[derive(Clone, Debug)]
pub struct MatchPair<'pat, 'tcx> {
crate struct MatchPair<'pat, 'tcx> {
// this place...
place: Place<'tcx>,
@ -739,7 +739,7 @@ enum TestKind<'tcx> {
}
#[derive(Debug)]
pub struct Test<'tcx> {
crate struct Test<'tcx> {
span: Span,
kind: TestKind<'tcx>,
}
@ -747,7 +747,7 @@ pub struct Test<'tcx> {
/// ArmHasGuard is isomorphic to a boolean flag. It indicates whether
/// a match arm has a guard expression attached to it.
#[derive(Copy, Clone, Debug)]
pub(crate) struct ArmHasGuard(pub bool);
crate struct ArmHasGuard(crate bool);
///////////////////////////////////////////////////////////////////////////
// Main matching algorithm

View File

@ -24,7 +24,7 @@ use syntax::attr::{SignedInt, UnsignedInt};
use std::mem;
impl<'a, 'tcx> Builder<'a, 'tcx> {
pub fn simplify_candidate<'pat>(&mut self, candidate: &mut Candidate<'pat, 'tcx>) {
crate fn simplify_candidate<'pat>(&mut self, candidate: &mut Candidate<'pat, 'tcx>) {
// repeatedly simplify match pairs until fixed point is reached
loop {
let match_pairs = mem::take(&mut candidate.match_pairs);

View File

@ -24,7 +24,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Identifies what test is needed to decide if `match_pair` is applicable.
///
/// It is a bug to call this with a simplifiable pattern.
pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
crate fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
match *match_pair.pattern.kind {
PatKind::Variant { ref adt_def, substs: _, variant_index: _, subpatterns: _ } => Test {
span: match_pair.pattern.span,
@ -85,7 +85,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}
pub fn add_cases_to_switch<'pat>(
crate fn add_cases_to_switch<'pat>(
&mut self,
test_place: &Place<'tcx>,
candidate: &Candidate<'pat, 'tcx>,
@ -129,7 +129,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}
pub fn add_variants_to_switch<'pat>(
crate fn add_variants_to_switch<'pat>(
&mut self,
test_place: &Place<'tcx>,
candidate: &Candidate<'pat, 'tcx>,
@ -156,7 +156,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}
pub fn perform_test(
crate fn perform_test(
&mut self,
block: BasicBlock,
place: &Place<'tcx>,
@ -507,7 +507,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// that it *doesn't* apply. For now, we return false, indicate that the
/// test does not apply to this candidate, but it might be we can get
/// tighter match code if we do something a bit different.
pub fn sort_candidate<'pat>(
crate fn sort_candidate<'pat>(
&mut self,
test_place: &Place<'tcx>,
test: &Test<'tcx>,

View File

@ -8,7 +8,7 @@ use std::convert::TryInto;
use std::u32;
impl<'a, 'tcx> Builder<'a, 'tcx> {
pub fn field_match_pairs<'pat>(
crate fn field_match_pairs<'pat>(
&mut self,
place: Place<'tcx>,
subpatterns: &'pat [FieldPat<'tcx>],
@ -26,7 +26,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
.collect()
}
pub fn prefix_slice_suffix<'pat>(
crate fn prefix_slice_suffix<'pat>(
&mut self,
match_pairs: &mut SmallVec<[MatchPair<'pat, 'tcx>; 1]>,
place: &Place<'tcx>,
@ -77,7 +77,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Creates a false edge to `imaginary_target` and a real edge to
/// real_target. If `imaginary_target` is none, or is the same as the real
/// target, a Goto is generated instead to simplify the generated MIR.
pub fn false_edges(
crate fn false_edges(
&mut self,
from_block: BasicBlock,
real_target: BasicBlock,
@ -98,7 +98,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
pub fn new(place: Place<'tcx>, pattern: &'pat Pat<'tcx>) -> MatchPair<'pat, 'tcx> {
crate fn new(place: Place<'tcx>, pattern: &'pat Pat<'tcx>) -> MatchPair<'pat, 'tcx> {
MatchPair { place, pattern }
}
}

View File

@ -14,7 +14,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
///
/// N.B., **No cleanup is scheduled for this temporary.** You should
/// call `schedule_drop` once the temporary is initialized.
pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
crate fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
let temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
let place = Place::from(temp);
debug!("temp: created temp {:?} with type {:?}", place, self.local_decls[temp].ty);
@ -23,24 +23,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Convenience function for creating a literal operand, one
/// without any user type annotation.
pub fn literal_operand(&mut self, span: Span, literal: &'tcx ty::Const<'tcx>) -> Operand<'tcx> {
crate fn literal_operand(
&mut self,
span: Span,
literal: &'tcx ty::Const<'tcx>,
) -> Operand<'tcx> {
let constant = box Constant { span, user_ty: None, literal };
Operand::Constant(constant)
}
pub fn unit_rvalue(&mut self) -> Rvalue<'tcx> {
crate fn unit_rvalue(&mut self) -> Rvalue<'tcx> {
Rvalue::Aggregate(box AggregateKind::Tuple, vec![])
}
// Returns a zero literal operand for the appropriate type, works for
// bool, char and integers.
pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
crate fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
let literal = ty::Const::from_bits(self.hir.tcx(), 0, ty::ParamEnv::empty().and(ty));
self.literal_operand(span, literal)
}
pub fn push_usize(
crate fn push_usize(
&mut self,
block: BasicBlock,
source_info: SourceInfo,
@ -61,7 +65,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
temp
}
pub fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
crate fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
let tcx = self.hir.tcx();
let ty = place.ty(&self.local_decls, tcx).ty;
if !self.hir.type_is_copy_modulo_regions(ty, DUMMY_SP) {

View File

@ -2,8 +2,6 @@ use crate::build;
use crate::build::scope::DropKind;
use crate::hair::cx::Cx;
use crate::hair::{BindingMode, LintLevel, PatKind};
use crate::transform::MirSource;
use crate::util as mir_util;
use rustc::middle::lang_items;
use rustc::middle::region;
use rustc::mir::*;
@ -22,8 +20,12 @@ use syntax::attr::{self, UnwindAttr};
use super::lints;
crate fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::steal::Steal<BodyAndCache<'_>> {
tcx.alloc_steal_mir(mir_build(tcx, def_id))
}
/// Construct the MIR for a given `DefId`.
pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
// Figure out what primary body this item has.
@ -172,8 +174,6 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
build::construct_const(cx, body_id, return_ty, return_ty_span)
};
mir_util::dump_mir(tcx, None, "mir_map", &0, MirSource::item(def_id), &body, |_, _| Ok(()));
lints::check(tcx, &body, def_id);
let mut body = BodyAndCache::new(body);
@ -202,7 +202,7 @@ fn liberated_closure_env_ty(
}
#[derive(Debug, PartialEq, Eq)]
pub enum BlockFrame {
enum BlockFrame {
/// Evaluation is currently within a statement.
///
/// Examples include:
@ -461,7 +461,7 @@ struct CFG<'tcx> {
}
rustc_index::newtype_index! {
pub struct ScopeId { .. }
struct ScopeId { .. }
}
///////////////////////////////////////////////////////////////////////////

View File

@ -123,7 +123,7 @@ struct Scope {
}
#[derive(Debug, Default)]
pub struct Scopes<'tcx> {
crate struct Scopes<'tcx> {
scopes: Vec<Scope>,
/// The current set of breakable scopes. See module comment for more details.
breakable_scopes: Vec<BreakableScope<'tcx>>,
@ -183,7 +183,7 @@ struct BreakableScope<'tcx> {
/// The target of an expression that breaks out of a scope
#[derive(Clone, Copy, Debug)]
pub enum BreakableTarget {
crate enum BreakableTarget {
Continue(region::Scope),
Break(region::Scope),
Return,
@ -371,7 +371,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// ==========================
// Start a breakable scope, which tracks where `continue`, `break` and
// `return` should branch to.
pub fn in_breakable_scope<F, R>(
crate fn in_breakable_scope<F, R>(
&mut self,
loop_block: Option<BasicBlock>,
break_block: BasicBlock,
@ -395,7 +395,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
res
}
pub fn in_opt_scope<F, R>(
crate fn in_opt_scope<F, R>(
&mut self,
opt_scope: Option<(region::Scope, SourceInfo)>,
f: F,
@ -418,7 +418,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Convenience wrapper that pushes a scope and then executes `f`
/// to build its contents, popping the scope afterwards.
pub fn in_scope<F, R>(
crate fn in_scope<F, R>(
&mut self,
region_scope: (region::Scope, SourceInfo),
lint_level: LintLevel,
@ -463,14 +463,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// scope and call `pop_scope` afterwards. Note that these two
/// calls must be paired; using `in_scope` as a convenience
/// wrapper maybe preferable.
pub fn push_scope(&mut self, region_scope: (region::Scope, SourceInfo)) {
crate fn push_scope(&mut self, region_scope: (region::Scope, SourceInfo)) {
self.scopes.push_scope(region_scope, self.source_scope);
}
/// Pops a scope, which should have region scope `region_scope`,
/// adding any drops onto the end of `block` that are needed.
/// This must match 1-to-1 with `push_scope`.
pub fn pop_scope(
crate fn pop_scope(
&mut self,
region_scope: (region::Scope, SourceInfo),
mut block: BasicBlock,
@ -500,7 +500,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block.unit()
}
pub fn break_scope(
crate fn break_scope(
&mut self,
mut block: BasicBlock,
value: Option<ExprRef<'tcx>>,
@ -535,7 +535,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Branch out of `block` to `target`, exiting all scopes up to
/// and including `region_scope`. This will insert whatever drops are
/// needed. See module comment for details.
pub fn exit_scope(
crate fn exit_scope(
&mut self,
span: Span,
region_scope: region::Scope,
@ -604,7 +604,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
///
/// This path terminates in GeneratorDrop. Returns the start of the path.
/// None indicates theres no cleanup to do at this point.
pub fn generator_drop_cleanup(&mut self) -> Option<BasicBlock> {
crate fn generator_drop_cleanup(&mut self) -> Option<BasicBlock> {
// Fill in the cache for unwinds
self.diverge_cleanup_gen(true);
@ -656,7 +656,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
/// Creates a new source scope, nested in the current one.
pub fn new_source_scope(
crate fn new_source_scope(
&mut self,
span: Span,
lint_level: LintLevel,
@ -689,7 +689,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
/// Given a span and the current source scope, make a SourceInfo.
pub fn source_info(&self, span: Span) -> SourceInfo {
crate fn source_info(&self, span: Span) -> SourceInfo {
SourceInfo { span, scope: self.source_scope }
}
@ -717,7 +717,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
///
/// When building statics/constants, returns `None` since
/// intermediate values do not have to be dropped in that case.
pub fn local_scope(&self) -> Option<region::Scope> {
crate fn local_scope(&self) -> Option<region::Scope> {
match self.hir.body_owner_kind {
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) =>
// No need to free storage in this context.
@ -729,7 +729,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
// Schedule an abort block - this is used for some ABIs that cannot unwind
pub fn schedule_abort(&mut self) -> BasicBlock {
crate fn schedule_abort(&mut self) -> BasicBlock {
let source_info = self.scopes.source_info(self.scopes.len(), self.fn_span);
let abortblk = self.cfg.start_new_cleanup_block();
self.cfg.terminate(abortblk, source_info, TerminatorKind::Abort);
@ -739,7 +739,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Scheduling drops
// ================
pub fn schedule_drop_storage_and_value(
crate fn schedule_drop_storage_and_value(
&mut self,
span: Span,
region_scope: region::Scope,
@ -754,7 +754,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
///
/// When called with `DropKind::Storage`, `place` should be a local
/// with an index higher than the current `self.arg_count`.
pub fn schedule_drop(
crate fn schedule_drop(
&mut self,
span: Span,
region_scope: region::Scope,
@ -884,7 +884,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// spurious borrow-check errors -- the problem, ironically, is
/// not the `DROP(_X)` itself, but the (spurious) unwind pathways
/// that it creates. See #64391 for an example.
pub fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) {
crate fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) {
let scope = match self.local_scope() {
None => {
// if there is no local scope, operands won't be dropped anyway
@ -921,7 +921,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
///
/// This is a special case because the temporary for the condition needs to
/// be dropped on both the true and the false arm.
pub fn test_bool(
crate fn test_bool(
&mut self,
mut block: BasicBlock,
condition: Expr<'tcx>,
@ -978,7 +978,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
///
/// This path terminates in Resume. Returns the start of the path.
/// See module comment for more details.
pub fn diverge_cleanup(&mut self) -> BasicBlock {
crate fn diverge_cleanup(&mut self) -> BasicBlock {
self.diverge_cleanup_gen(false)
}
@ -1033,7 +1033,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
/// Utility function for *non*-scope code to build their own drops
pub fn build_drop_and_replace(
crate fn build_drop_and_replace(
&mut self,
block: BasicBlock,
span: Span,
@ -1059,7 +1059,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Creates an Assert terminator and return the success block.
/// If the boolean condition operand is not the expected value,
/// a runtime panic will be caused with the given message.
pub fn assert(
crate fn assert(
&mut self,
block: BasicBlock,
cond: Operand<'tcx>,
@ -1293,7 +1293,7 @@ fn build_diverge_scope<'tcx>(
target
}
fn push_storage_deads(
fn push_storage_deads<'tcx>(
cfg: &mut CFG<'tcx>,
target: BasicBlock,
storage_deads: &mut Vec<Statement<'tcx>>,

View File

@ -101,7 +101,7 @@ fn mirror_stmts<'a, 'tcx>(
return result;
}
pub fn to_expr_ref<'a, 'tcx>(
crate fn to_expr_ref<'a, 'tcx>(
cx: &mut Cx<'a, 'tcx>,
block: &'tcx hir::Block<'tcx>,
) -> ExprRef<'tcx> {

View File

@ -577,8 +577,8 @@ fn make_mirror_unadjusted<'a, 'tcx>(
Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
}
fn user_substs_applied_to_res(
cx: &mut Cx<'a, 'tcx>,
fn user_substs_applied_to_res<'tcx>(
cx: &mut Cx<'_, 'tcx>,
hir_id: hir::HirId,
res: Res,
) -> Option<ty::CanonicalUserType<'tcx>> {
@ -775,7 +775,7 @@ fn convert_path_expr<'a, 'tcx>(
}
}
fn convert_var(
fn convert_var<'tcx>(
cx: &mut Cx<'_, 'tcx>,
expr: &'tcx hir::Expr<'tcx>,
var_hir_id: hir::HirId,

View File

@ -21,18 +21,18 @@ use syntax::ast;
use syntax::attr;
#[derive(Clone)]
pub struct Cx<'a, 'tcx> {
crate struct Cx<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
infcx: &'a InferCtxt<'a, 'tcx>,
pub root_lint_level: hir::HirId,
pub param_env: ty::ParamEnv<'tcx>,
crate root_lint_level: hir::HirId,
crate param_env: ty::ParamEnv<'tcx>,
/// Identity `InternalSubsts` for use with const-evaluation.
pub identity_substs: &'tcx InternalSubsts<'tcx>,
crate identity_substs: &'tcx InternalSubsts<'tcx>,
pub region_scope_tree: &'tcx region::ScopeTree,
pub tables: &'a ty::TypeckTables<'tcx>,
crate region_scope_tree: &'tcx region::ScopeTree,
crate tables: &'a ty::TypeckTables<'tcx>,
/// This is `Constness::Const` if we are compiling a `static`,
/// `const`, or the body of a `const fn`.
@ -42,7 +42,7 @@ pub struct Cx<'a, 'tcx> {
body_owner: DefId,
/// What kind of body is being compiled.
pub body_owner_kind: hir::BodyOwnerKind,
crate body_owner_kind: hir::BodyOwnerKind,
/// Whether this constant/function needs overflow checks.
check_overflow: bool,
@ -52,7 +52,7 @@ pub struct Cx<'a, 'tcx> {
}
impl<'a, 'tcx> Cx<'a, 'tcx> {
pub fn new(infcx: &'a InferCtxt<'a, 'tcx>, src_id: hir::HirId) -> Cx<'a, 'tcx> {
crate fn new(infcx: &'a InferCtxt<'a, 'tcx>, src_id: hir::HirId) -> Cx<'a, 'tcx> {
let tcx = infcx.tcx;
let src_def_id = tcx.hir().local_def_id(src_id);
let tables = tcx.typeck_tables_of(src_def_id);
@ -92,42 +92,42 @@ impl<'a, 'tcx> Cx<'a, 'tcx> {
}
}
pub fn control_flow_destroyed(self) -> Vec<(Span, String)> {
crate fn control_flow_destroyed(self) -> Vec<(Span, String)> {
self.control_flow_destroyed
}
}
impl<'a, 'tcx> Cx<'a, 'tcx> {
/// Normalizes `ast` into the appropriate "mirror" type.
pub fn mirror<M: Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
crate fn mirror<M: Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
ast.make_mirror(self)
}
pub fn usize_ty(&mut self) -> Ty<'tcx> {
crate fn usize_ty(&mut self) -> Ty<'tcx> {
self.tcx.types.usize
}
pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
crate fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
ty::Const::from_usize(self.tcx, value)
}
pub fn bool_ty(&mut self) -> Ty<'tcx> {
crate fn bool_ty(&mut self) -> Ty<'tcx> {
self.tcx.types.bool
}
pub fn unit_ty(&mut self) -> Ty<'tcx> {
crate fn unit_ty(&mut self) -> Ty<'tcx> {
self.tcx.mk_unit()
}
pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
crate fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
ty::Const::from_bool(self.tcx, true)
}
pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
crate fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
ty::Const::from_bool(self.tcx, false)
}
pub fn const_eval_literal(
crate fn const_eval_literal(
&mut self,
lit: &'tcx ast::LitKind,
ty: Ty<'tcx>,
@ -151,15 +151,15 @@ impl<'a, 'tcx> Cx<'a, 'tcx> {
}
}
pub fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
crate fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
let p = match self.tcx.hir().get(p.hir_id) {
Node::Pat(p) | Node::Binding(p) => p,
node => bug!("pattern became {:?}", node),
};
Pat::from_hir(self.tcx, self.param_env.and(self.identity_substs), self.tables(), p)
Pat::from_hir(self.tcx, self.param_env, self.tables(), p)
}
pub fn trait_method(
crate fn trait_method(
&mut self,
trait_def_id: DefId,
method_name: Symbol,
@ -168,6 +168,8 @@ impl<'a, 'tcx> Cx<'a, 'tcx> {
) -> &'tcx ty::Const<'tcx> {
let substs = self.tcx.mk_substs_trait(self_ty, params);
for item in self.tcx.associated_items(trait_def_id) {
// The unhygienic comparison here is acceptable because this is only
// used on known traits.
if item.kind == ty::AssocKind::Method && item.ident.name == method_name {
let method_ty = self.tcx.type_of(item.def_id);
let method_ty = method_ty.subst(self.tcx, substs);
@ -178,32 +180,32 @@ impl<'a, 'tcx> Cx<'a, 'tcx> {
bug!("found no method `{}` in `{:?}`", method_name, trait_def_id);
}
pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec<Field> {
crate fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec<Field> {
(0..adt_def.variants[variant_index].fields.len()).map(Field::new).collect()
}
pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
crate fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
ty.needs_drop(self.tcx, self.param_env)
}
pub fn tcx(&self) -> TyCtxt<'tcx> {
crate fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
pub fn tables(&self) -> &'a ty::TypeckTables<'tcx> {
crate fn tables(&self) -> &'a ty::TypeckTables<'tcx> {
self.tables
}
pub fn check_overflow(&self) -> bool {
crate fn check_overflow(&self) -> bool {
self.check_overflow
}
pub fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool {
crate fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool {
self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span)
}
}
impl UserAnnotatedTyHelpers<'tcx> for Cx<'_, 'tcx> {
impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx()
}

View File

@ -2,7 +2,7 @@ use crate::hair::*;
use rustc_hir as hir;
pub trait ToRef {
crate trait ToRef {
type Output;
fn to_ref(self) -> Self::Output;
}

View File

@ -17,33 +17,33 @@ use rustc_hir::def_id::DefId;
use rustc_span::Span;
mod constant;
pub mod cx;
crate mod cx;
pub mod pattern;
pub(crate) use self::pattern::PatTyProj;
pub use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
crate mod pattern;
crate use self::pattern::PatTyProj;
crate use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
mod util;
#[derive(Copy, Clone, Debug)]
pub enum LintLevel {
crate enum LintLevel {
Inherited,
Explicit(hir::HirId),
}
#[derive(Clone, Debug)]
pub struct Block<'tcx> {
pub targeted_by_break: bool,
pub region_scope: region::Scope,
pub opt_destruction_scope: Option<region::Scope>,
pub span: Span,
pub stmts: Vec<StmtRef<'tcx>>,
pub expr: Option<ExprRef<'tcx>>,
pub safety_mode: BlockSafety,
crate struct Block<'tcx> {
crate targeted_by_break: bool,
crate region_scope: region::Scope,
crate opt_destruction_scope: Option<region::Scope>,
crate span: Span,
crate stmts: Vec<StmtRef<'tcx>>,
crate expr: Option<ExprRef<'tcx>>,
crate safety_mode: BlockSafety,
}
#[derive(Copy, Clone, Debug)]
pub enum BlockSafety {
crate enum BlockSafety {
Safe,
ExplicitUnsafe(hir::HirId),
PushUnsafe,
@ -51,18 +51,18 @@ pub enum BlockSafety {
}
#[derive(Clone, Debug)]
pub enum StmtRef<'tcx> {
crate enum StmtRef<'tcx> {
Mirror(Box<Stmt<'tcx>>),
}
#[derive(Clone, Debug)]
pub struct Stmt<'tcx> {
pub kind: StmtKind<'tcx>,
pub opt_destruction_scope: Option<region::Scope>,
crate struct Stmt<'tcx> {
crate kind: StmtKind<'tcx>,
crate opt_destruction_scope: Option<region::Scope>,
}
#[derive(Clone, Debug)]
pub enum StmtKind<'tcx> {
crate enum StmtKind<'tcx> {
Expr {
/// scope for this statement; may be used as lifetime of temporaries
scope: region::Scope,
@ -112,23 +112,23 @@ rustc_data_structures::static_assert_size!(Expr<'_>, 168);
/// example, method calls and overloaded operators are absent: they are
/// expected to be converted into `Expr::Call` instances.
#[derive(Clone, Debug)]
pub struct Expr<'tcx> {
crate struct Expr<'tcx> {
/// type of this expression
pub ty: Ty<'tcx>,
crate ty: Ty<'tcx>,
/// lifetime of this expression if it should be spilled into a
/// temporary; should be None only if in a constant context
pub temp_lifetime: Option<region::Scope>,
crate temp_lifetime: Option<region::Scope>,
/// span of the expression in the source
pub span: Span,
crate span: Span,
/// kind of expression
pub kind: ExprKind<'tcx>,
crate kind: ExprKind<'tcx>,
}
#[derive(Clone, Debug)]
pub enum ExprKind<'tcx> {
crate enum ExprKind<'tcx> {
Scope {
region_scope: region::Scope,
lint_level: LintLevel,
@ -288,37 +288,37 @@ pub enum ExprKind<'tcx> {
}
#[derive(Clone, Debug)]
pub enum ExprRef<'tcx> {
crate enum ExprRef<'tcx> {
Hair(&'tcx hir::Expr<'tcx>),
Mirror(Box<Expr<'tcx>>),
}
#[derive(Clone, Debug)]
pub struct FieldExprRef<'tcx> {
pub name: Field,
pub expr: ExprRef<'tcx>,
crate struct FieldExprRef<'tcx> {
crate name: Field,
crate expr: ExprRef<'tcx>,
}
#[derive(Clone, Debug)]
pub struct FruInfo<'tcx> {
pub base: ExprRef<'tcx>,
pub field_types: Vec<Ty<'tcx>>,
crate struct FruInfo<'tcx> {
crate base: ExprRef<'tcx>,
crate field_types: Vec<Ty<'tcx>>,
}
#[derive(Clone, Debug)]
pub struct Arm<'tcx> {
pub pattern: Pat<'tcx>,
pub guard: Option<Guard<'tcx>>,
pub body: ExprRef<'tcx>,
pub lint_level: LintLevel,
pub scope: region::Scope,
pub span: Span,
crate struct Arm<'tcx> {
crate pattern: Pat<'tcx>,
crate guard: Option<Guard<'tcx>>,
crate body: ExprRef<'tcx>,
crate lint_level: LintLevel,
crate scope: region::Scope,
crate span: Span,
}
impl Arm<'tcx> {
impl<'tcx> Arm<'tcx> {
// HACK(or_patterns; Centril | dlrobertson): Remove this and
// correctly handle each case in which this method is used.
pub fn top_pats_hack(&self) -> &[Pat<'tcx>] {
crate fn top_pats_hack(&self) -> &[Pat<'tcx>] {
match &*self.pattern.kind {
PatKind::Or { pats } => pats,
_ => std::slice::from_ref(&self.pattern),
@ -327,18 +327,18 @@ impl Arm<'tcx> {
}
#[derive(Clone, Debug)]
pub enum Guard<'tcx> {
crate enum Guard<'tcx> {
If(ExprRef<'tcx>),
}
#[derive(Copy, Clone, Debug)]
pub enum LogicalOp {
crate enum LogicalOp {
And,
Or,
}
impl<'tcx> ExprRef<'tcx> {
pub fn span(&self) -> Span {
crate fn span(&self) -> Span {
match self {
ExprRef::Hair(expr) => expr.span,
ExprRef::Mirror(expr) => expr.span,
@ -361,7 +361,7 @@ impl<'tcx> ExprRef<'tcx> {
/// mirrored. This allows a single AST node from the compiler to
/// expand into one or more Hair nodes, which lets the Hair nodes be
/// simpler.
pub trait Mirror<'tcx> {
crate trait Mirror<'tcx> {
type Output;
fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Self::Output;
@ -378,7 +378,7 @@ impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
type Output = Expr<'tcx>;
fn make_mirror(self, hir: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
fn make_mirror(self, hir: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
match self {
ExprRef::Hair(h) => h.make_mirror(hir),
ExprRef::Mirror(m) => *m,

View File

@ -230,7 +230,6 @@ use self::Usefulness::*;
use self::WitnessPreference::*;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashMap;
use rustc_index::vec::Idx;
use super::{compare_const_vals, PatternFoldable, PatternFolder};
@ -260,7 +259,7 @@ use std::iter::{FromIterator, IntoIterator};
use std::ops::RangeInclusive;
use std::u128;
pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pat<'tcx>) -> Pat<'tcx> {
crate fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pat<'tcx>) -> Pat<'tcx> {
LiteralExpander { tcx: cx.tcx, param_env: cx.param_env }.fold_pattern(&pat)
}
@ -269,7 +268,7 @@ struct LiteralExpander<'tcx> {
param_env: ty::ParamEnv<'tcx>,
}
impl LiteralExpander<'tcx> {
impl<'tcx> LiteralExpander<'tcx> {
/// Derefs `val` and potentially unsizes the value if `crty` is an array and `rty` a slice.
///
/// `crty` and `rty` can differ because you can use array constants in the presence of slice
@ -323,7 +322,7 @@ impl LiteralExpander<'tcx> {
}
}
impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
impl<'tcx> PatternFolder<'tcx> for LiteralExpander<'tcx> {
fn fold_pattern(&mut self, pat: &Pat<'tcx>) -> Pat<'tcx> {
debug!("fold_pattern {:?} {:?} {:?}", pat, pat.ty.kind, pat.kind);
match (&pat.ty.kind, &*pat.kind) {
@ -381,10 +380,10 @@ impl<'tcx> Pat<'tcx> {
/// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
/// works well.
#[derive(Debug, Clone)]
pub struct PatStack<'p, 'tcx>(SmallVec<[&'p Pat<'tcx>; 2]>);
crate struct PatStack<'p, 'tcx>(SmallVec<[&'p Pat<'tcx>; 2]>);
impl<'p, 'tcx> PatStack<'p, 'tcx> {
pub fn from_pattern(pat: &'p Pat<'tcx>) -> Self {
crate fn from_pattern(pat: &'p Pat<'tcx>) -> Self {
PatStack(smallvec![pat])
}
@ -472,15 +471,15 @@ impl<'p, 'tcx> FromIterator<&'p Pat<'tcx>> for PatStack<'p, 'tcx> {
/// A 2D matrix.
#[derive(Clone)]
pub struct Matrix<'p, 'tcx>(Vec<PatStack<'p, 'tcx>>);
crate struct Matrix<'p, 'tcx>(Vec<PatStack<'p, 'tcx>>);
impl<'p, 'tcx> Matrix<'p, 'tcx> {
pub fn empty() -> Self {
crate fn empty() -> Self {
Matrix(vec![])
}
/// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
pub fn push(&mut self, row: PatStack<'p, 'tcx>) {
crate fn push(&mut self, row: PatStack<'p, 'tcx>) {
if let Some(rows) = row.expand_or_pat() {
self.0.extend(rows);
} else {
@ -569,22 +568,21 @@ impl<'p, 'tcx> FromIterator<PatStack<'p, 'tcx>> for Matrix<'p, 'tcx> {
}
}
pub struct MatchCheckCtxt<'a, 'tcx> {
pub tcx: TyCtxt<'tcx>,
crate struct MatchCheckCtxt<'a, 'tcx> {
crate tcx: TyCtxt<'tcx>,
/// The module in which the match occurs. This is necessary for
/// checking inhabited-ness of types because whether a type is (visibly)
/// inhabited can depend on whether it was defined in the current module or
/// not. E.g., `struct Foo { _private: ! }` cannot be seen to be empty
/// outside it's module and should not be matchable with an empty match
/// statement.
pub module: DefId,
crate module: DefId,
param_env: ty::ParamEnv<'tcx>,
pub pattern_arena: &'a TypedArena<Pat<'tcx>>,
pub byte_array_map: FxHashMap<*const Pat<'tcx>, Vec<&'a Pat<'tcx>>>,
crate pattern_arena: &'a TypedArena<Pat<'tcx>>,
}
impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
pub fn create_and_enter<F, R>(
crate fn create_and_enter<F, R>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
module: DefId,
@ -595,13 +593,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
{
let pattern_arena = TypedArena::default();
f(MatchCheckCtxt {
tcx,
param_env,
module,
pattern_arena: &pattern_arena,
byte_array_map: FxHashMap::default(),
})
f(MatchCheckCtxt { tcx, param_env, module, pattern_arena: &pattern_arena })
}
fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
@ -613,7 +605,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
}
// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
pub fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
crate fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
match ty.kind {
ty::Adt(def, ..) => {
def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did.is_local()
@ -773,13 +765,13 @@ impl<'tcx> Constructor<'tcx> {
cx: &MatchCheckCtxt<'a, 'tcx>,
adt: &'tcx ty::AdtDef,
) -> VariantIdx {
match self {
Variant(id) => adt.variant_index_with_id(*id),
match *self {
Variant(id) => adt.variant_index_with_id(id),
Single => {
assert!(!adt.is_enum());
VariantIdx::new(0)
}
ConstantValue(c) => crate::const_eval::const_variant_index(cx.tcx, cx.param_env, c),
ConstantValue(c) => cx.tcx.destructure_const(cx.param_env.and(c)).variant,
_ => bug!("bad constructor {:?} for adt {:?}", self, adt),
}
}
@ -1058,7 +1050,7 @@ impl<'tcx> Constructor<'tcx> {
}
#[derive(Clone, Debug)]
pub enum Usefulness<'tcx, 'p> {
crate enum Usefulness<'tcx, 'p> {
/// Carries a list of unreachable subpatterns. Used only in the presence of or-patterns.
Useful(Vec<&'p Pat<'tcx>>),
/// Carries a list of witnesses of non-exhaustiveness.
@ -1146,7 +1138,7 @@ impl<'tcx, 'p> Usefulness<'tcx, 'p> {
}
#[derive(Copy, Clone, Debug)]
pub enum WitnessPreference {
crate enum WitnessPreference {
ConstructWitness,
LeaveOutWitness,
}
@ -1190,10 +1182,10 @@ struct PatCtxt<'tcx> {
///
/// The final `Pair(Some(_), true)` is then the resulting witness.
#[derive(Clone, Debug)]
pub struct Witness<'tcx>(Vec<Pat<'tcx>>);
crate struct Witness<'tcx>(Vec<Pat<'tcx>>);
impl<'tcx> Witness<'tcx> {
pub fn single_pattern(self) -> Pat<'tcx> {
crate fn single_pattern(self) -> Pat<'tcx> {
assert_eq!(self.0.len(), 1);
self.0.into_iter().next().unwrap()
}
@ -1358,9 +1350,9 @@ fn all_constructors<'a, 'tcx>(
/// around the (offset) space: i.e., `range.lo <= range.hi`.
#[derive(Clone, Debug)]
struct IntRange<'tcx> {
pub range: RangeInclusive<u128>,
pub ty: Ty<'tcx>,
pub span: Span,
range: RangeInclusive<u128>,
ty: Ty<'tcx>,
span: Span,
}
impl<'tcx> IntRange<'tcx> {
@ -1631,7 +1623,7 @@ impl<'tcx> fmt::Debug for MissingConstructors<'tcx> {
/// relation to preceding patterns, it is not reachable) and exhaustiveness
/// checking (if a wildcard pattern is useful in relation to a matrix, the
/// matrix isn't exhaustive).
pub fn is_useful<'p, 'tcx>(
crate fn is_useful<'p, 'tcx>(
cx: &mut MatchCheckCtxt<'p, 'tcx>,
matrix: &Matrix<'p, 'tcx>,
v: &PatStack<'p, 'tcx>,
@ -2238,7 +2230,7 @@ fn split_grouped_constructors<'p, 'tcx>(
split_ctors
}
fn lint_overlapping_patterns(
fn lint_overlapping_patterns<'tcx>(
tcx: TyCtxt<'tcx>,
hir_id: Option<HirId>,
ctor_range: IntRange<'tcx>,

View File

@ -8,7 +8,6 @@ use rustc::hir::map::Map;
use rustc::lint;
use rustc::session::parse::feature_err;
use rustc::session::Session;
use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::ty::{self, Ty, TyCtxt};
use rustc_error_codes::*;
use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder};
@ -29,12 +28,8 @@ crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
Some(id) => tcx.hir().body_owned_by(id),
};
let mut visitor = MatchVisitor {
tcx,
tables: tcx.body_tables(body_id),
param_env: tcx.param_env(def_id),
identity_substs: InternalSubsts::identity_for_item(tcx, def_id),
};
let mut visitor =
MatchVisitor { tcx, tables: tcx.body_tables(body_id), param_env: tcx.param_env(def_id) };
visitor.visit_body(tcx.hir().body(body_id));
}
@ -46,7 +41,6 @@ struct MatchVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
param_env: ty::ParamEnv<'tcx>,
identity_substs: SubstsRef<'tcx>,
}
impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
@ -153,11 +147,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
let inlined_arms: Vec<_> = arms
.iter()
.map(|arm| {
let mut patcx = PatCtxt::new(
self.tcx,
self.param_env.and(self.identity_substs),
self.tables,
);
let mut patcx = PatCtxt::new(self.tcx, self.param_env, self.tables);
patcx.include_lint_checks();
let pattern = patcx.lower_pattern(&arm.pat);
let pattern: &_ = cx.pattern_arena.alloc(expand_pattern(cx, pattern));
@ -189,8 +179,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option<Span>) {
let module = self.tcx.hir().get_module_parent(pat.hir_id);
MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| {
let mut patcx =
PatCtxt::new(self.tcx, self.param_env.and(self.identity_substs), self.tables);
let mut patcx = PatCtxt::new(self.tcx, self.param_env, self.tables);
patcx.include_lint_checks();
let pattern = patcx.lower_pattern(pat);
let pattern_ty = pattern.ty;

View File

@ -1,5 +1,3 @@
use crate::const_eval::const_variant_index;
use rustc::infer::InferCtxt;
use rustc::lint;
use rustc::mir::Field;
@ -167,18 +165,14 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
let tcx = self.tcx();
let param_env = self.param_env;
let adt_subpattern = |i, variant_opt| {
let field = Field::new(i);
let val = crate::const_eval::const_field(tcx, param_env, variant_opt, field, cv);
self.recur(val)
};
let adt_subpatterns = |n, variant_opt| {
(0..n)
.map(|i| {
let field = Field::new(i);
FieldPat { field, pattern: adt_subpattern(i, variant_opt) }
let field_pats = |vals: &[&'tcx ty::Const<'tcx>]| {
vals.iter()
.enumerate()
.map(|(idx, val)| {
let field = Field::new(idx);
FieldPat { field, pattern: self.recur(val) }
})
.collect::<Vec<_>>()
.collect()
};
let kind = match cv.ty.kind {
@ -235,21 +229,28 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
PatKind::Wild
}
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
let variant_index = const_variant_index(tcx, self.param_env, cv);
let subpatterns = adt_subpatterns(
adt_def.variants[variant_index].fields.len(),
Some(variant_index),
);
PatKind::Variant { adt_def, substs, variant_index, subpatterns }
let destructured = tcx.destructure_const(param_env.and(cv));
PatKind::Variant {
adt_def,
substs,
variant_index: destructured.variant,
subpatterns: field_pats(destructured.fields),
}
}
ty::Adt(adt_def, _) => {
let struct_var = adt_def.non_enum_variant();
PatKind::Leaf { subpatterns: adt_subpatterns(struct_var.fields.len(), None) }
ty::Adt(_, _) => {
let destructured = tcx.destructure_const(param_env.and(cv));
PatKind::Leaf { subpatterns: field_pats(destructured.fields) }
}
ty::Tuple(fields) => PatKind::Leaf { subpatterns: adt_subpatterns(fields.len(), None) },
ty::Array(_, n) => PatKind::Array {
prefix: (0..n.eval_usize(tcx, self.param_env))
.map(|i| adt_subpattern(i as usize, None))
ty::Tuple(_) => {
let destructured = tcx.destructure_const(param_env.and(cv));
PatKind::Leaf { subpatterns: field_pats(destructured.fields) }
}
ty::Array(..) => PatKind::Array {
prefix: tcx
.destructure_const(param_env.and(cv))
.fields
.iter()
.map(|val| self.recur(val))
.collect(),
slice: None,
suffix: Vec::new(),

View File

@ -31,7 +31,7 @@ use std::fmt;
use rustc_error_codes::*;
#[derive(Clone, Debug)]
pub enum PatternError {
crate enum PatternError {
AssocConstInPattern(Span),
StaticInPattern(Span),
FloatBug,
@ -39,22 +39,22 @@ pub enum PatternError {
}
#[derive(Copy, Clone, Debug)]
pub enum BindingMode {
crate enum BindingMode {
ByValue,
ByRef(BorrowKind),
}
#[derive(Clone, Debug)]
pub struct FieldPat<'tcx> {
pub field: Field,
pub pattern: Pat<'tcx>,
crate struct FieldPat<'tcx> {
crate field: Field,
crate pattern: Pat<'tcx>,
}
#[derive(Clone, Debug)]
pub struct Pat<'tcx> {
pub ty: Ty<'tcx>,
pub span: Span,
pub kind: Box<PatKind<'tcx>>,
crate struct Pat<'tcx> {
crate ty: Ty<'tcx>,
crate span: Span,
crate kind: Box<PatKind<'tcx>>,
}
impl<'tcx> Pat<'tcx> {
@ -64,8 +64,8 @@ impl<'tcx> Pat<'tcx> {
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct PatTyProj<'tcx> {
pub user_ty: CanonicalUserType<'tcx>,
crate struct PatTyProj<'tcx> {
crate user_ty: CanonicalUserType<'tcx>,
}
impl<'tcx> PatTyProj<'tcx> {
@ -91,8 +91,8 @@ impl<'tcx> PatTyProj<'tcx> {
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Ascription<'tcx> {
pub user_ty: PatTyProj<'tcx>,
crate struct Ascription<'tcx> {
crate user_ty: PatTyProj<'tcx>,
/// Variance to use when relating the type `user_ty` to the **type of the value being
/// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
/// have a type that is some subtype of the ascribed type.
@ -111,12 +111,12 @@ pub struct Ascription<'tcx> {
/// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
/// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
/// of the old type-check for now. See #57280 for details.
pub variance: ty::Variance,
pub user_ty_span: Span,
crate variance: ty::Variance,
crate user_ty_span: Span,
}
#[derive(Clone, Debug)]
pub enum PatKind<'tcx> {
crate enum PatKind<'tcx> {
Wild,
AscribeUserType {
@ -184,10 +184,10 @@ pub enum PatKind<'tcx> {
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct PatRange<'tcx> {
pub lo: &'tcx ty::Const<'tcx>,
pub hi: &'tcx ty::Const<'tcx>,
pub end: RangeEnd,
crate struct PatRange<'tcx> {
crate lo: &'tcx ty::Const<'tcx>,
crate hi: &'tcx ty::Const<'tcx>,
crate end: RangeEnd,
}
impl<'tcx> fmt::Display for Pat<'tcx> {
@ -342,23 +342,22 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
}
}
pub struct PatCtxt<'a, 'tcx> {
pub tcx: TyCtxt<'tcx>,
pub param_env: ty::ParamEnv<'tcx>,
pub tables: &'a ty::TypeckTables<'tcx>,
pub substs: SubstsRef<'tcx>,
pub errors: Vec<PatternError>,
crate struct PatCtxt<'a, 'tcx> {
crate tcx: TyCtxt<'tcx>,
crate param_env: ty::ParamEnv<'tcx>,
crate tables: &'a ty::TypeckTables<'tcx>,
crate errors: Vec<PatternError>,
include_lint_checks: bool,
}
impl<'a, 'tcx> Pat<'tcx> {
pub fn from_hir(
crate fn from_hir(
tcx: TyCtxt<'tcx>,
param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
param_env: ty::ParamEnv<'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
pat: &'tcx hir::Pat<'tcx>,
) -> Self {
let mut pcx = PatCtxt::new(tcx, param_env_and_substs, tables);
let mut pcx = PatCtxt::new(tcx, param_env, tables);
let result = pcx.lower_pattern(pat);
if !pcx.errors.is_empty() {
let msg = format!("encountered errors lowering pattern: {:?}", pcx.errors);
@ -370,27 +369,20 @@ impl<'a, 'tcx> Pat<'tcx> {
}
impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
pub fn new(
crate fn new(
tcx: TyCtxt<'tcx>,
param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
param_env: ty::ParamEnv<'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
) -> Self {
PatCtxt {
tcx,
param_env: param_env_and_substs.param_env,
tables,
substs: param_env_and_substs.value,
errors: vec![],
include_lint_checks: false,
}
PatCtxt { tcx, param_env, tables, errors: vec![], include_lint_checks: false }
}
pub fn include_lint_checks(&mut self) -> &mut Self {
crate fn include_lint_checks(&mut self) -> &mut Self {
self.include_lint_checks = true;
self
}
pub fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
crate fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
// When implicit dereferences have been inserted in this pattern, the unadjusted lowered
// pattern has the type that results *after* dereferencing. For example, in this code:
//
@ -863,7 +855,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
}
}
impl UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> {
impl<'tcx> UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
@ -873,7 +865,7 @@ impl UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> {
}
}
pub trait PatternFoldable<'tcx>: Sized {
crate trait PatternFoldable<'tcx>: Sized {
fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
self.super_fold_with(folder)
}
@ -881,7 +873,7 @@ pub trait PatternFoldable<'tcx>: Sized {
fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self;
}
pub trait PatternFolder<'tcx>: Sized {
crate trait PatternFolder<'tcx>: Sized {
fn fold_pattern(&mut self, pattern: &Pat<'tcx>) -> Pat<'tcx> {
pattern.super_fold_with(self)
}
@ -1009,7 +1001,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> {
}
}
pub fn compare_const_vals<'tcx>(
crate fn compare_const_vals<'tcx>(
tcx: TyCtxt<'tcx>,
a: &'tcx ty::Const<'tcx>,
b: &'tcx ty::Const<'tcx>,

View File

@ -0,0 +1,26 @@
//! Construction of MIR from HIR.
//!
//! This crate also contains the match exhaustiveness and usefulness checking.
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(crate_visibility_modifier)]
#![feature(slice_patterns)]
#![feature(bool_to_option)]
#![recursion_limit = "256"]
#[macro_use]
extern crate log;
#[macro_use]
extern crate rustc;
mod build;
mod hair;
mod lints;
use rustc::ty::query::Providers;
pub fn provide(providers: &mut Providers<'_>) {
providers.check_match = hair::pattern::check_match;
providers.mir_built = build::mir_built;
}

View File

@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::FnKind;
use rustc_index::bit_set::BitSet;
pub fn check(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) {
crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir().get(hir_id)) {
@ -15,7 +15,7 @@ pub fn check(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) {
}
}
fn check_fn_for_unconditional_recursion(
fn check_fn_for_unconditional_recursion<'tcx>(
tcx: TyCtxt<'tcx>,
fn_kind: FnKind<'_>,
body: &Body<'tcx>,

View File

@ -1,4 +1,4 @@
thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:LL:CC
thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir_build/hair/pattern/_match.rs:LL:CC
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
error: internal compiler error: unexpected panic