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:
commit
59c1db0339
24
Cargo.lock
24
Cargo.lock
@ -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"
|
||||
|
@ -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
223
src/librustc/mir/query.rs
Normal 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>],
|
||||
}
|
@ -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" }
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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" }
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
28
src/librustc_mir_build/Cargo.toml
Normal file
28
src/librustc_mir_build/Cargo.toml
Normal 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" }
|
@ -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,
|
@ -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 })
|
||||
}
|
||||
}
|
@ -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>>,
|
||||
{
|
@ -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>,
|
@ -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>>,
|
||||
{
|
@ -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,
|
@ -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>,
|
@ -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,
|
||||
|
@ -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,
|
@ -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>,
|
@ -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>,
|
||||
{
|
@ -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
|
@ -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);
|
@ -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>,
|
@ -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 }
|
||||
}
|
||||
}
|
@ -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) {
|
@ -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 { .. }
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
@ -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 there’s 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>>,
|
@ -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> {
|
@ -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,
|
@ -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()
|
||||
}
|
@ -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;
|
||||
}
|
@ -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,
|
@ -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>,
|
@ -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;
|
@ -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(),
|
@ -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>,
|
26
src/librustc_mir_build/lib.rs
Normal file
26
src/librustc_mir_build/lib.rs
Normal 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;
|
||||
}
|
@ -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>,
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user