diff --git a/Cargo.lock b/Cargo.lock index 26727c5c1db60..4287b3e5e5f77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1823,9 +1823,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" -version = "0.2.64" +version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74dfca3d9957906e8d1e6a0b641dc9a59848e793f1da2165889fd4f62d10d79c" +checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" dependencies = [ "rustc-std-workspace-core", ] diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 66d27a275192e..854942dad3ded 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -202,53 +202,18 @@ impl TypedArena { #[inline] pub fn alloc_from_iter>(&self, iter: I) -> &mut [T] { assert!(mem::size_of::() != 0); - let mut iter = iter.into_iter(); - let size_hint = iter.size_hint(); - - match size_hint { - (min, Some(max)) if min == max => { - // We know the exact number of elements the iterator will produce here - let len = min; - - if len == 0 { - return &mut []; - } - - self.ensure_capacity(len); - - let slice = self.ptr.get(); - - unsafe { - let mut ptr = self.ptr.get(); - for _ in 0..len { - // Write into uninitialized memory. - ptr::write(ptr, iter.next().unwrap()); - // Advance the pointer. - ptr = ptr.offset(1); - // Update the pointer per iteration so if `iter.next()` panics - // we destroy the correct amount - self.ptr.set(ptr); - } - slice::from_raw_parts_mut(slice, len) - } - } - _ => { - cold_path(move || -> &mut [T] { - let mut vec: SmallVec<[_; 8]> = iter.collect(); - if vec.is_empty() { - return &mut []; - } - // Move the content to the arena by copying it and then forgetting - // the content of the SmallVec - unsafe { - let len = vec.len(); - let start_ptr = self.alloc_raw_slice(len); - vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); - vec.set_len(0); - slice::from_raw_parts_mut(start_ptr, len) - } - }) - } + let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect(); + if vec.is_empty() { + return &mut []; + } + // Move the content to the arena by copying it and then forgetting + // the content of the SmallVec + unsafe { + let len = vec.len(); + let start_ptr = self.alloc_raw_slice(len); + vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); + vec.set_len(0); + slice::from_raw_parts_mut(start_ptr, len) } } diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 4f572fe21b30b..5eaacc0c90be8 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -129,6 +129,9 @@ const UNWIND_DATA_REG: (i32, i32) = (24, 25); // I0, I1 #[cfg(target_arch = "hexagon")] const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 +#[cfg(target_arch = "riscv64")] +const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11 + // The following code is based on GCC's C and C++ personality routines. For reference, see: // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 364a35f1b6faa..eb7a170980154 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -23,17 +23,17 @@ macro_rules! arena_types { [] generics: rustc::ty::Generics, [] trait_def: rustc::ty::TraitDef, [] adt_def: rustc::ty::AdtDef, - [] steal_mir: rustc::ty::steal::Steal>, - [] mir: rustc::mir::BodyCache<$tcx>, + [] steal_mir: rustc::ty::steal::Steal>, + [] mir: rustc::mir::BodyAndCache<$tcx>, [] steal_promoted: rustc::ty::steal::Steal< rustc_index::vec::IndexVec< rustc::mir::Promoted, - rustc::mir::BodyCache<$tcx> + rustc::mir::BodyAndCache<$tcx> > >, [] promoted: rustc_index::vec::IndexVec< rustc::mir::Promoted, - rustc::mir::BodyCache<$tcx> + rustc::mir::BodyAndCache<$tcx> >, [] tables: rustc::ty::TypeckTables<$tcx>, [] const_allocs: rustc::mir::interpret::Allocation, diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 95e9f098da3fb..0704771f6ee95 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -115,16 +115,16 @@ impl Cache { } #[derive(Clone, Debug, HashStable, RustcEncodable, RustcDecodable, TypeFoldable)] -pub struct BodyCache<'tcx> { - cache: Cache, +pub struct BodyAndCache<'tcx> { body: Body<'tcx>, + cache: Cache, } -impl BodyCache<'tcx> { +impl BodyAndCache<'tcx> { pub fn new(body: Body<'tcx>) -> Self { Self { - cache: Cache::new(), body, + cache: Cache::new(), } } } @@ -139,7 +139,7 @@ macro_rules! read_only { }; } -impl BodyCache<'tcx> { +impl BodyAndCache<'tcx> { pub fn ensure_predecessors(&mut self) { self.cache.ensure_predecessors(&self.body); } @@ -148,8 +148,8 @@ impl BodyCache<'tcx> { self.cache.predecessors(&self.body) } - pub fn unwrap_read_only(&self) -> ReadOnlyBodyCache<'_, 'tcx> { - ReadOnlyBodyCache::new(&self.cache, &self.body) + pub fn unwrap_read_only(&self) -> ReadOnlyBodyAndCache<'_, 'tcx> { + ReadOnlyBodyAndCache::new(&self.body, &self.cache) } pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { @@ -163,7 +163,7 @@ impl BodyCache<'tcx> { } } -impl<'tcx> Index for BodyCache<'tcx> { +impl<'tcx> Index for BodyAndCache<'tcx> { type Output = BasicBlockData<'tcx>; fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> { @@ -171,13 +171,13 @@ impl<'tcx> Index for BodyCache<'tcx> { } } -impl<'tcx> IndexMut for BodyCache<'tcx> { +impl<'tcx> IndexMut for BodyAndCache<'tcx> { fn index_mut(&mut self, index: BasicBlock) -> &mut Self::Output { &mut self.basic_blocks_mut()[index] } } -impl<'tcx> Deref for BodyCache<'tcx> { +impl<'tcx> Deref for BodyAndCache<'tcx> { type Target = Body<'tcx>; fn deref(&self) -> &Self::Target { @@ -185,26 +185,26 @@ impl<'tcx> Deref for BodyCache<'tcx> { } } -impl<'tcx> DerefMut for BodyCache<'tcx> { +impl<'tcx> DerefMut for BodyAndCache<'tcx> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.body } } #[derive(Copy, Clone, Debug)] -pub struct ReadOnlyBodyCache<'a, 'tcx> { - cache: &'a Cache, +pub struct ReadOnlyBodyAndCache<'a, 'tcx> { body: &'a Body<'tcx>, + cache: &'a Cache, } -impl ReadOnlyBodyCache<'a, 'tcx> { - fn new(cache: &'a Cache, body: &'a Body<'tcx>) -> Self { +impl ReadOnlyBodyAndCache<'a, 'tcx> { + fn new(body: &'a Body<'tcx>, cache: &'a Cache) -> Self { assert!( cache.predecessors.is_some(), - "Cannot construct ReadOnlyBodyCache without computed predecessors"); + "Cannot construct ReadOnlyBodyAndCache without computed predecessors"); Self { - cache, body, + cache, } } @@ -220,10 +220,6 @@ impl ReadOnlyBodyCache<'a, 'tcx> { self.cache.unwrap_predecessor_locations(loc, self.body) } - pub fn body(&self) -> &'a Body<'tcx> { - self.body - } - pub fn basic_blocks(&self) -> &IndexVec> { &self.body.basic_blocks } @@ -233,16 +229,16 @@ impl ReadOnlyBodyCache<'a, 'tcx> { } } -impl graph::DirectedGraph for ReadOnlyBodyCache<'a, 'tcx> { +impl graph::DirectedGraph for ReadOnlyBodyAndCache<'a, 'tcx> { type Node = BasicBlock; } -impl graph::GraphPredecessors<'graph> for ReadOnlyBodyCache<'a, 'tcx> { +impl graph::GraphPredecessors<'graph> for ReadOnlyBodyAndCache<'a, 'tcx> { type Item = BasicBlock; type Iter = IntoIter; } -impl graph::WithPredecessors for ReadOnlyBodyCache<'a, 'tcx> { +impl graph::WithPredecessors for ReadOnlyBodyAndCache<'a, 'tcx> { fn predecessors( &self, node: Self::Node, @@ -251,19 +247,19 @@ impl graph::WithPredecessors for ReadOnlyBodyCache<'a, 'tcx> { } } -impl graph::WithNumNodes for ReadOnlyBodyCache<'a, 'tcx> { +impl graph::WithNumNodes for ReadOnlyBodyAndCache<'a, 'tcx> { fn num_nodes(&self) -> usize { self.body.num_nodes() } } -impl graph::WithStartNode for ReadOnlyBodyCache<'a, 'tcx> { +impl graph::WithStartNode for ReadOnlyBodyAndCache<'a, 'tcx> { fn start_node(&self) -> Self::Node { self.body.start_node() } } -impl graph::WithSuccessors for ReadOnlyBodyCache<'a, 'tcx> { +impl graph::WithSuccessors for ReadOnlyBodyAndCache<'a, 'tcx> { fn successors( &self, node: Self::Node, @@ -272,13 +268,13 @@ impl graph::WithSuccessors for ReadOnlyBodyCache<'a, 'tcx> { } } -impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for ReadOnlyBodyCache<'a, 'tcx> { +impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for ReadOnlyBodyAndCache<'a, 'tcx> { type Item = BasicBlock; type Iter = iter::Cloned>; } -impl Deref for ReadOnlyBodyCache<'a, 'tcx> { +impl Deref for ReadOnlyBodyAndCache<'a, 'tcx> { type Target = &'a Body<'tcx>; fn deref(&self) -> &Self::Target { diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 557310650faeb..0dec7c071bfee 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -370,6 +370,14 @@ pub enum UndefinedBehaviorInfo { Unreachable, /// An enum discriminant was set to a value which was outside the range of valid values. InvalidDiscriminant(ScalarMaybeUndef), + /// A slice/array index projection went out-of-bounds. + BoundsCheckFailed { len: u64, index: u64 }, + /// Something was divided by 0 (x / 0). + DivisionByZero, + /// Something was "remainded" by 0 (x % 0). + RemainderByZero, + /// Overflowing inbounds pointer arithmetic. + PointerArithOverflow, } impl fmt::Debug for UndefinedBehaviorInfo { @@ -379,9 +387,18 @@ impl fmt::Debug for UndefinedBehaviorInfo { Ub(msg) | UbExperimental(msg) => write!(f, "{}", msg), Unreachable => - write!(f, "entered unreachable code"), + write!(f, "entering unreachable code"), InvalidDiscriminant(val) => - write!(f, "encountered invalid enum discriminant {}", val), + write!(f, "encountering invalid enum discriminant {}", val), + BoundsCheckFailed { ref len, ref index } => + write!(f, "indexing out of bounds: the len is {:?} but the index is {:?}", + len, index), + DivisionByZero => + write!(f, "dividing by zero"), + RemainderByZero => + write!(f, "calculating the remainder with a divisor of zero"), + PointerArithOverflow => + write!(f, "overflowing in-bounds pointer arithmetic"), } } } diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index 78320c769f680..0b27f512e55b8 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -1,6 +1,5 @@ use super::{AllocId, InterpResult}; -use crate::mir; use crate::ty::layout::{self, HasDataLayout, Size}; use rustc_macros::HashStable; @@ -88,13 +87,13 @@ pub trait PointerArithmetic: layout::HasDataLayout { #[inline] fn offset<'tcx>(&self, val: u64, i: u64) -> InterpResult<'tcx, u64> { let (res, over) = self.overflowing_offset(val, i); - if over { throw_panic!(Overflow(mir::BinOp::Add)) } else { Ok(res) } + if over { throw_ub!(PointerArithOverflow) } else { Ok(res) } } #[inline] fn signed_offset<'tcx>(&self, val: u64, i: i64) -> InterpResult<'tcx, u64> { let (res, over) = self.overflowing_signed_offset(val, i128::from(i)); - if over { throw_panic!(Overflow(mir::BinOp::Add)) } else { Ok(res) } + if over { throw_ub!(PointerArithOverflow) } else { Ok(res) } } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 814c244ecbc2b..a7f5a22692515 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -38,7 +38,7 @@ use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; pub use crate::mir::interpret::AssertMessage; -pub use crate::mir::cache::{BodyCache, ReadOnlyBodyCache}; +pub use crate::mir::cache::{BodyAndCache, ReadOnlyBodyAndCache}; pub use crate::read_only; mod cache; @@ -108,7 +108,7 @@ pub struct Body<'tcx> { pub yield_ty: Option>, /// Generator drop glue. - pub generator_drop: Option>>, + pub generator_drop: Option>>, /// The layout of a generator. Produced by the state transformation. pub generator_layout: Option>, @@ -2597,7 +2597,7 @@ impl Location { pub fn is_predecessor_of<'tcx>( &self, other: Location, - body: ReadOnlyBodyCache<'_, 'tcx> + body: ReadOnlyBodyAndCache<'_, 'tcx> ) -> bool { // If we are in the same block as the other location and are an earlier statement // then we are a predecessor of `other`. diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 47a1d67d5d6db..703e0cc78c207 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -67,10 +67,10 @@ use syntax_pos::Span; macro_rules! body_cache_type { (mut $a:lifetime, $tcx:lifetime) => { - &mut BodyCache<$tcx> + &mut BodyAndCache<$tcx> }; ($a:lifetime, $tcx:lifetime) => { - ReadOnlyBodyCache<$a, $tcx> + ReadOnlyBodyAndCache<$a, $tcx> }; } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index a6d7e5c9291dc..538b13c79ce1c 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -106,30 +106,30 @@ rustc_queries! { /// Fetch the MIR for a given `DefId` right after it's built - this includes /// unreachable code. - query mir_built(_: DefId) -> &'tcx Steal> {} + query mir_built(_: DefId) -> &'tcx Steal> {} /// Fetch the MIR for a given `DefId` up till the point where it is /// ready for const evaluation. /// /// See the README for the `mir` module for details. - query mir_const(_: DefId) -> &'tcx Steal> { + query mir_const(_: DefId) -> &'tcx Steal> { no_hash } query mir_validated(_: DefId) -> ( - &'tcx Steal>, - &'tcx Steal>> + &'tcx Steal>, + &'tcx Steal>> ) { no_hash } /// MIR after our optimization passes have run. This is MIR that is ready /// for codegen. This is also the only query that can fetch non-local MIR, at present. - query optimized_mir(key: DefId) -> &'tcx mir::BodyCache<'tcx> { + query optimized_mir(key: DefId) -> &'tcx mir::BodyAndCache<'tcx> { cache_on_disk_if { key.is_local() } load_cached(tcx, id) { - let mir: Option> + let mir: Option> = tcx.queries.on_disk_cache.try_load_query_result(tcx, id); mir.map(|x| { let cache = tcx.arena.alloc(x); @@ -139,13 +139,13 @@ rustc_queries! { } } - query promoted_mir(key: DefId) -> &'tcx IndexVec> { + query promoted_mir(key: DefId) -> &'tcx IndexVec> { cache_on_disk_if { key.is_local() } load_cached(tcx, id) { let promoted: Option< rustc_index::vec::IndexVec< crate::mir::Promoted, - crate::mir::BodyCache<'tcx> + crate::mir::BodyAndCache<'tcx> >> = tcx.queries.on_disk_cache.try_load_query_result(tcx, id); promoted.map(|p| { let cache = tcx.arena.alloc(p); @@ -512,7 +512,7 @@ rustc_queries! { /// in the case of closures, this will be redirected to the enclosing function. query region_scope_tree(_: DefId) -> &'tcx region::ScopeTree {} - query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::BodyCache<'tcx> { + query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::BodyAndCache<'tcx> { no_force desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 6a0002cd80fd0..2771058ccf45d 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -22,7 +22,7 @@ use crate::middle::cstore::EncodedMetadata; use crate::middle::lang_items; use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use crate::middle::stability; -use crate::mir::{BodyCache, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted}; +use crate::mir::{BodyAndCache, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted}; use crate::mir::interpret::{ConstValue, Allocation, Scalar}; use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef, Subst}; use crate::ty::ReprOptions; @@ -1083,17 +1083,17 @@ impl<'tcx> TyCtxt<'tcx> { &self.hir_map } - pub fn alloc_steal_mir(self, mir: BodyCache<'tcx>) -> &'tcx Steal> { + pub fn alloc_steal_mir(self, mir: BodyAndCache<'tcx>) -> &'tcx Steal> { self.arena.alloc(Steal::new(mir)) } - pub fn alloc_steal_promoted(self, promoted: IndexVec>) -> - &'tcx Steal>> { + pub fn alloc_steal_promoted(self, promoted: IndexVec>) -> + &'tcx Steal>> { self.arena.alloc(Steal::new(promoted)) } - pub fn intern_promoted(self, promoted: IndexVec>) -> - &'tcx IndexVec> { + pub fn intern_promoted(self, promoted: IndexVec>) -> + &'tcx IndexVec> { self.arena.alloc(promoted) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 05a2704cc5dfc..78a31f4e54466 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -18,7 +18,7 @@ use crate::infer::canonical::Canonical; use crate::middle::cstore::CrateStoreDyn; use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use crate::middle::resolve_lifetime::ObjectLifetimeDefault; -use crate::mir::ReadOnlyBodyCache; +use crate::mir::ReadOnlyBodyAndCache; use crate::mir::interpret::{GlobalId, ErrorHandled}; use crate::mir::GeneratorLayout; use crate::session::CrateDisambiguator; @@ -2981,7 +2981,7 @@ impl<'tcx> TyCtxt<'tcx> { } /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair. - pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> ReadOnlyBodyCache<'tcx, 'tcx> { + pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> ReadOnlyBodyAndCache<'tcx, 'tcx> { match instance { ty::InstanceDef::Item(did) => { self.optimized_mir(did).unwrap_read_only() diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index ce703f2433506..3d6e273194291 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -153,7 +153,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { // a loop. fn maybe_sideeffect>( &self, - mir: mir::ReadOnlyBodyCache<'tcx, 'tcx>, + mir: mir::ReadOnlyBodyAndCache<'tcx, 'tcx>, bx: &mut Bx, targets: &[mir::BasicBlock], ) { diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 3a157ca24a470..0bdccd81408bd 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -21,7 +21,7 @@ use self::operand::{OperandRef, OperandValue}; pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { instance: Instance<'tcx>, - mir: mir::ReadOnlyBodyCache<'tcx, 'tcx>, + mir: mir::ReadOnlyBodyAndCache<'tcx, 'tcx>, debug_context: Option>, @@ -156,7 +156,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }).collect(); let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs); - let mir_body: &mir::Body<'_> = mir.body(); + let mir_body: &mir::Body<'_> = *mir; let mut fx = FunctionCx { instance, mir, diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 6edd17fe9abef..0107a22772fd2 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -18,7 +18,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc::dep_graph::{self, DepNodeIndex}; use rustc::middle::lang_items; -use rustc::mir::{self, BodyCache, interpret, Promoted}; +use rustc::mir::{self, BodyAndCache, interpret, Promoted}; use rustc::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; @@ -1079,7 +1079,7 @@ impl<'a, 'tcx> CrateMetadata { self.root.per_def.mir.get(self, id).is_some() } - fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> BodyCache<'tcx> { + fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> BodyAndCache<'tcx> { let mut cache = self.root.per_def.mir.get(self, id) .filter(|_| !self.is_proc_macro(id)) .unwrap_or_else(|| { @@ -1094,7 +1094,7 @@ impl<'a, 'tcx> CrateMetadata { &self, tcx: TyCtxt<'tcx>, id: DefIndex, - ) -> IndexVec> { + ) -> IndexVec> { let mut cache = self.root.per_def.promoted_mir.get(self, id) .filter(|_| !self.is_proc_macro(id)) .unwrap_or_else(|| { diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index fdf43f06eb10f..5abae4293731d 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -276,8 +276,8 @@ define_per_def_tables! { // Also, as an optimization, a missing entry indicates an empty `&[]`. inferred_outlives: Table, Span)])>, super_predicates: Table)>, - mir: Table)>, - promoted_mir: Table>)>, + mir: Table)>, + promoted_mir: Table>)>, } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index 802464ce86b86..2980483bfa4c7 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -5,7 +5,7 @@ use crate::dataflow::indexes::BorrowIndex; use crate::dataflow::move_paths::MoveData; use rustc::mir::traversal; use rustc::mir::visit::{PlaceContext, Visitor, NonUseContext, MutatingUseContext}; -use rustc::mir::{self, Location, Body, Local, ReadOnlyBodyCache}; +use rustc::mir::{self, Location, Body, Local, ReadOnlyBodyAndCache}; use rustc::ty::{RegionVid, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_index::vec::IndexVec; @@ -90,7 +90,7 @@ crate enum LocalsStateAtExit { impl LocalsStateAtExit { fn build( locals_are_invalidated_at_exit: bool, - body: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, move_data: &MoveData<'tcx> ) -> Self { struct HasStorageDead(BitSet); @@ -124,7 +124,7 @@ impl LocalsStateAtExit { impl<'tcx> BorrowSet<'tcx> { pub fn build( tcx: TyCtxt<'tcx>, - body: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, locals_are_invalidated_at_exit: bool, move_data: &MoveData<'tcx>, ) -> Self { diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index d14957b9017da..a0f126fb2cb30 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -240,15 +240,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let tcx = self.infcx.tcx; let generics = tcx.generics_of(self.mir_def_id); let param = generics.type_param(¶m_ty, tcx); - let generics = tcx.hir().get_generics(self.mir_def_id).unwrap(); - suggest_constraining_type_param( - generics, - &mut err, - ¶m.name.as_str(), - "Copy", - tcx.sess.source_map(), - span, - ); + if let Some(generics) = tcx.hir().get_generics(self.mir_def_id) { + suggest_constraining_type_param( + generics, + &mut err, + ¶m.name.as_str(), + "Copy", + tcx.sess.source_map(), + span, + ); + } } let span = if let Some(local) = place.as_local() { let decl = &self.body.local_decls[local]; diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index 6449ae349abf2..016a3195c982d 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -1,6 +1,6 @@ use rustc::hir; use rustc::hir::Node; -use rustc::mir::{self, ClearCrossCrate, Local, LocalInfo, Location, ReadOnlyBodyCache}; +use rustc::mir::{self, ClearCrossCrate, Local, LocalInfo, Location, ReadOnlyBodyAndCache}; use rustc::mir::{Mutability, Place, PlaceRef, PlaceBase, ProjectionElem}; use rustc::ty::{self, Ty, TyCtxt}; use rustc_index::vec::Idx; @@ -533,7 +533,7 @@ fn suggest_ampmut_self<'tcx>( // by trying (3.), then (2.) and finally falling back on (1.). fn suggest_ampmut<'tcx>( tcx: TyCtxt<'tcx>, - body: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, local: Local, local_decl: &mir::LocalDecl<'tcx>, opt_ty_info: Option, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index a1932b551c144..427003f24cb14 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -9,8 +9,8 @@ use rustc::lint::builtin::UNUSED_MUT; use rustc::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT}; use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc::mir::{ - ClearCrossCrate, Local, Location, Body, BodyCache, Mutability, Operand, Place, PlaceBase, - PlaceElem, PlaceRef, ReadOnlyBodyCache, Static, StaticKind, read_only + ClearCrossCrate, Local, Location, Body, BodyAndCache, Mutability, Operand, Place, PlaceBase, + PlaceElem, PlaceRef, ReadOnlyBodyAndCache, Static, StaticKind, read_only }; use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; @@ -99,7 +99,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> { fn do_mir_borrowck<'a, 'tcx>( infcx: &InferCtxt<'a, 'tcx>, input_body: &Body<'tcx>, - input_promoted: &IndexVec>, + input_promoted: &IndexVec>, def_id: DefId, ) -> BorrowCheckResult<'tcx> { debug!("do_mir_borrowck(def_id = {:?})", def_id); @@ -161,7 +161,7 @@ fn do_mir_borrowck<'a, 'tcx>( // will have a lifetime tied to the inference context. let body_clone: Body<'tcx> = input_body.clone(); let mut promoted = input_promoted.clone(); - let mut body = BodyCache::new(body_clone); + let mut body = BodyAndCache::new(body_clone); let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted); let body = read_only!(body); // no further changes @@ -402,7 +402,7 @@ fn do_mir_borrowck<'a, 'tcx>( crate struct MirBorrowckCtxt<'cx, 'tcx> { crate infcx: &'cx InferCtxt<'cx, 'tcx>, - body: ReadOnlyBodyCache<'cx, 'tcx>, + body: ReadOnlyBodyAndCache<'cx, 'tcx>, mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, move_data: &'cx MoveData<'tcx>, @@ -493,7 +493,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx type FlowState = Flows<'cx, 'tcx>; fn body(&self) -> &'cx Body<'tcx> { - self.body.body() + *self.body } fn visit_block_entry(&mut self, bb: BasicBlock, flow_state: &Self::FlowState) { diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 98679f236db50..2442bdf8a9b4e 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -11,7 +11,7 @@ use crate::borrow_check::path_utils::*; use crate::dataflow::indexes::BorrowIndex; use rustc::ty::{self, TyCtxt}; use rustc::mir::visit::Visitor; -use rustc::mir::{BasicBlock, Location, Body, Place, ReadOnlyBodyCache, Rvalue}; +use rustc::mir::{BasicBlock, Location, Body, Place, ReadOnlyBodyAndCache, Rvalue}; use rustc::mir::{Statement, StatementKind}; use rustc::mir::TerminatorKind; use rustc::mir::{Operand, BorrowKind}; @@ -22,7 +22,7 @@ pub(super) fn generate_invalidates<'tcx>( param_env: ty::ParamEnv<'tcx>, all_facts: &mut Option, location_table: &LocationTable, - body: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, borrow_set: &BorrowSet<'tcx>, ) { if all_facts.is_none() { diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 7a5bbb4d89298..49a03ce1ed232 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -12,8 +12,8 @@ use crate::borrow_check::Upvar; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, - Local, Location, Body, BodyCache, LocalKind, BasicBlock, - Promoted, ReadOnlyBodyCache}; + Local, Location, Body, BodyAndCache, LocalKind, BasicBlock, + Promoted, ReadOnlyBodyAndCache}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc_index::vec::IndexVec; use rustc_errors::Diagnostic; @@ -55,8 +55,8 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, def_id: DefId, param_env: ty::ParamEnv<'tcx>, - body: &mut BodyCache<'tcx>, - promoted: &mut IndexVec>, + body: &mut BodyAndCache<'tcx>, + promoted: &mut IndexVec>, ) -> UniversalRegions<'tcx> { debug!("replace_regions_in_mir(def_id={:?})", def_id); @@ -158,8 +158,8 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, def_id: DefId, universal_regions: UniversalRegions<'tcx>, - body: ReadOnlyBodyCache<'_, 'tcx>, - promoted: &IndexVec>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, + promoted: &IndexVec>, local_names: &IndexVec>, upvars: &[Upvar], location_table: &LocationTable, diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index b4414c514c532..0bf0cd37cd843 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -1,4 +1,4 @@ -use rustc::mir::{BasicBlock, Location, Body, ReadOnlyBodyCache}; +use rustc::mir::{BasicBlock, Location, Body, ReadOnlyBodyAndCache}; use rustc::ty::{self, RegionVid}; use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix}; use rustc_data_structures::fx::FxHashMap; @@ -92,7 +92,7 @@ impl RegionValueElements { /// Pushes all predecessors of `index` onto `stack`. crate fn push_predecessors( &self, - body: ReadOnlyBodyCache<'_, '_>, + body: ReadOnlyBodyAndCache<'_, '_>, index: PointIndex, stack: &mut Vec, ) { diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index db15d2c54fdbc..ba323b113e9eb 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,6 +1,6 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::mir::{BodyCache, Location, PlaceElem, Promoted}; +use rustc::mir::{BodyAndCache, Location, PlaceElem, Promoted}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc_index::vec::IndexVec; @@ -9,8 +9,8 @@ use rustc_index::vec::IndexVec; /// inference variables, returning the number of variables created. pub fn renumber_mir<'tcx>( infcx: &InferCtxt<'_, 'tcx>, - body: &mut BodyCache<'tcx>, - promoted: &mut IndexVec>, + body: &mut BodyAndCache<'tcx>, + promoted: &mut IndexVec>, ) { debug!("renumber_mir()"); debug!("renumber_mir: body.arg_count={:?}", body.arg_count); diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs index d6aa31449daa7..ab8c6f279733b 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs @@ -1,7 +1,7 @@ use crate::borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements}; use crate::util::liveness::{categorize, DefUse}; use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc::mir::{Local, Location, ReadOnlyBodyCache}; +use rustc::mir::{Local, Location, ReadOnlyBodyAndCache}; use rustc_index::vec::{Idx, IndexVec}; use rustc_data_structures::vec_linked_list as vll; @@ -60,7 +60,7 @@ impl LocalUseMap { crate fn build( live_locals: &Vec, elements: &RegionValueElements, - body: ReadOnlyBodyCache<'_, '_>, + body: ReadOnlyBodyAndCache<'_, '_>, ) -> Self { let nones = IndexVec::from_elem_n(None, body.local_decls.len()); let mut local_use_map = LocalUseMap { diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs index dfd505f6b613a..8f8e9af797963 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs @@ -7,7 +7,7 @@ use crate::borrow_check::nll::ToRegionVid; use crate::dataflow::move_paths::MoveData; use crate::dataflow::FlowAtLocation; use crate::dataflow::MaybeInitializedPlaces; -use rustc::mir::{Body, Local, ReadOnlyBodyCache}; +use rustc::mir::{Body, Local, ReadOnlyBodyAndCache}; use rustc::ty::{RegionVid, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use std::rc::Rc; @@ -28,7 +28,7 @@ mod trace; /// performed before pub(super) fn generate<'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, - body: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, elements: &Rc, flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>, move_data: &MoveData<'tcx>, diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs index e67de6c99f026..810811f9f5cf3 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs @@ -3,7 +3,7 @@ use crate::dataflow::indexes::MovePathIndex; use crate::dataflow::move_paths::{LookupResult, MoveData}; use crate::util::liveness::{categorize, DefUse}; use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; -use rustc::mir::{Local, Location, Place, ReadOnlyBodyCache}; +use rustc::mir::{Local, Location, Place, ReadOnlyBodyAndCache}; use rustc::ty::subst::GenericArg; use rustc::ty::Ty; @@ -97,7 +97,7 @@ fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty pub(super) fn populate_access_facts( typeck: &mut TypeChecker<'_, 'tcx>, - body: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, location_table: &LocationTable, move_data: &MoveData<'_>, drop_used: &mut Vec<(Local, Location)>, diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 229cbed64c272..bdd7c84fcd7dc 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -7,7 +7,7 @@ use crate::dataflow::indexes::MovePathIndex; use crate::dataflow::move_paths::MoveData; use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces}; use rustc::infer::canonical::QueryRegionConstraints; -use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, ReadOnlyBodyCache}; +use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, ReadOnlyBodyAndCache}; use rustc::traits::query::dropck_outlives::DropckOutlivesResult; use rustc::traits::query::type_op::outlives::DropckOutlives; use rustc::traits::query::type_op::TypeOp; @@ -32,7 +32,7 @@ use std::rc::Rc; /// this respects `#[may_dangle]` annotations). pub(super) fn trace( typeck: &mut TypeChecker<'_, 'tcx>, - body: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, elements: &Rc, flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>, move_data: &MoveData<'tcx>, @@ -71,7 +71,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> { elements: &'me RegionValueElements, /// MIR we are analyzing. - body: ReadOnlyBodyCache<'me, 'tcx>, + body: ReadOnlyBodyAndCache<'me, 'tcx>, /// Mapping to/from the various indices used for initialization tracking. move_data: &'me MoveData<'tcx>, diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index de304202a0840..8d4e76cadbfc2 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -117,8 +117,8 @@ mod relate_tys; pub(crate) fn type_check<'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, - body: ReadOnlyBodyCache<'_, 'tcx>, - promoted: &IndexVec>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, + promoted: &IndexVec>, mir_def_id: DefId, universal_regions: &Rc>, location_table: &LocationTable, @@ -196,8 +196,8 @@ fn type_check_internal<'a, 'tcx, R>( infcx: &'a InferCtxt<'a, 'tcx>, mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, - body: ReadOnlyBodyCache<'a, 'tcx>, - promoted: &'a IndexVec>, + body: ReadOnlyBodyAndCache<'a, 'tcx>, + promoted: &'a IndexVec>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, @@ -206,7 +206,7 @@ fn type_check_internal<'a, 'tcx, R>( ) -> R { let mut checker = TypeChecker::new( infcx, - body.body(), + *body, mir_def_id, param_env, region_bound_pairs, @@ -215,7 +215,7 @@ fn type_check_internal<'a, 'tcx, R>( universal_region_relations, ); let errors_reported = { - let mut verifier = TypeVerifier::new(&mut checker, body.body(), promoted); + let mut verifier = TypeVerifier::new(&mut checker, *body, promoted); verifier.visit_body(body); verifier.errors_reported }; @@ -272,7 +272,7 @@ enum FieldAccessError { struct TypeVerifier<'a, 'b, 'tcx> { cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, - promoted: &'b IndexVec>, + promoted: &'b IndexVec>, last_span: Span, mir_def_id: DefId, errors_reported: bool, @@ -396,7 +396,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } } - fn visit_body(&mut self, body: ReadOnlyBodyCache<'_, 'tcx>) { + fn visit_body(&mut self, body: ReadOnlyBodyAndCache<'_, 'tcx>) { self.sanitize_type(&"return type", body.return_ty()); for local_decl in &body.local_decls { self.sanitize_type(local_decl, local_decl.ty); @@ -412,7 +412,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { fn new( cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, - promoted: &'b IndexVec>, + promoted: &'b IndexVec>, ) -> Self { TypeVerifier { body, @@ -548,14 +548,14 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { fn sanitize_promoted( &mut self, - promoted_body: ReadOnlyBodyCache<'b, 'tcx>, + promoted_body: ReadOnlyBodyAndCache<'b, 'tcx>, location: Location ) { // Determine the constraints from the promoted MIR by running the type // checker on the promoted MIR, then transfer the constraints back to // the main MIR, changing the locations to the provided location. - let parent_body = mem::replace(&mut self.body, promoted_body.body()); + let parent_body = mem::replace(&mut self.body, *promoted_body); // Use new sets of constraints and closure bounds so that we can // modify their locations. @@ -1378,7 +1378,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { fn check_stmt( &mut self, - body: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, stmt: &Statement<'tcx>, location: Location) { @@ -1994,7 +1994,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { fn check_rvalue( &mut self, - body: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { @@ -2766,7 +2766,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }) } - fn typeck_mir(&mut self, body: ReadOnlyBodyCache<'_, 'tcx>) { + fn typeck_mir(&mut self, body: ReadOnlyBodyAndCache<'_, 'tcx>) { self.last_span = body.span; debug!("run_on_mir: {:?}", body.span); diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index b58bf737a3575..248faa56777de 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -11,7 +11,7 @@ use super::MirBorrowckCtxt; use rustc::hir; use rustc::ty::{self, TyCtxt}; -use rustc::mir::{Place, PlaceBase, PlaceRef, ProjectionElem, ReadOnlyBodyCache}; +use rustc::mir::{Place, PlaceBase, PlaceRef, ProjectionElem, ReadOnlyBodyAndCache}; pub trait IsPrefixOf<'cx, 'tcx> { fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool; @@ -26,7 +26,7 @@ impl<'cx, 'tcx> IsPrefixOf<'cx, 'tcx> for PlaceRef<'cx, 'tcx> { } pub(super) struct Prefixes<'cx, 'tcx> { - body: ReadOnlyBodyCache<'cx, 'tcx>, + body: ReadOnlyBodyAndCache<'cx, 'tcx>, tcx: TyCtxt<'tcx>, kind: PrefixSet, next: Option>, diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index b84461d6b9275..0009eb45cc035 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -24,7 +24,7 @@ use syntax_pos::Span; use super::lints; /// Construct the MIR for a given `DefId`. -pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyCache<'_> { +pub 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. @@ -196,7 +196,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyCache<'_> { lints::check(tcx, &body, def_id); - let mut body = BodyCache::new(body); + let mut body = BodyAndCache::new(body); body.ensure_predecessors(); body }) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 968a8a71ba0ba..697ef58b0aa05 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -366,7 +366,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } // This is a const fn. Call it. Ok(Some(match ecx.load_mir(instance.def, None) { - Ok(body) => body.body(), + Ok(body) => *body, Err(err) => { if let err_unsup!(NoMirFor(ref path)) = err.kind { return Err( @@ -743,7 +743,7 @@ pub fn const_eval_raw_provider<'tcx>( let res = ecx.load_mir(cid.instance.def, cid.promoted); res.and_then( - |body| eval_body_using_ecx(&mut ecx, cid, body.body()) + |body| eval_body_using_ecx(&mut ecx, cid, *body) ).and_then(|place| { Ok(RawConst { alloc_id: place.ptr.assert_ptr().alloc_id, diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index c4b97d12e6270..b8abe6d70edbd 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -75,20 +75,20 @@ impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> { /// Dataflow analysis that determines whether each local requires storage at a /// given location; i.e. whether its storage can go away without being observed. pub struct RequiresStorage<'mir, 'tcx> { - body: ReadOnlyBodyCache<'mir, 'tcx>, + body: ReadOnlyBodyAndCache<'mir, 'tcx>, borrowed_locals: RefCell>>, } impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> { pub fn new( - body: ReadOnlyBodyCache<'mir, 'tcx>, + body: ReadOnlyBodyAndCache<'mir, 'tcx>, borrowed_locals: &'mir DataflowResults<'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>, ) -> Self { RequiresStorage { body, borrowed_locals: RefCell::new( - DataflowResultsCursor::new(borrowed_locals, body.body()) + DataflowResultsCursor::new(borrowed_locals, *body) ), } } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 9af47f3e77f93..653718c462f07 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -312,7 +312,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, instance: ty::InstanceDef<'tcx>, promoted: Option, - ) -> InterpResult<'tcx, mir::ReadOnlyBodyCache<'tcx, 'tcx>> { + ) -> InterpResult<'tcx, mir::ReadOnlyBodyAndCache<'tcx, 'tcx>> { // do not continue if typeck errors occurred (can only occur in local crate) let did = instance.def_id(); if did.is_local() diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 176b084f22587..68004294c5dc9 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -177,8 +177,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok((Scalar::from_bool(op(&l, &r)), false, self.tcx.types.bool)); } let op: Option (i128, bool)> = match bin_op { - Div if r == 0 => throw_panic!(DivisionByZero), - Rem if r == 0 => throw_panic!(RemainderByZero), + Div if r == 0 => throw_ub!(DivisionByZero), + Rem if r == 0 => throw_ub!(RemainderByZero), Div => Some(i128::overflowing_div), Rem => Some(i128::overflowing_rem), Add => Some(i128::overflowing_add), @@ -234,8 +234,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Add => u128::overflowing_add, Sub => u128::overflowing_sub, Mul => u128::overflowing_mul, - Div if r == 0 => throw_panic!(DivisionByZero), - Rem if r == 0 => throw_panic!(RemainderByZero), + Div if r == 0 => throw_ub!(DivisionByZero), + Rem if r == 0 => throw_ub!(RemainderByZero), Div => u128::overflowing_div, Rem => u128::overflowing_rem, _ => bug!(), diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 902472d18beae..a600eb11e1d03 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -384,10 +384,8 @@ where layout::FieldPlacement::Array { stride, .. } => { let len = base.len(self)?; if field >= len { - // This can be violated because the index (field) can be a runtime value - // provided by the user. - debug!("tried to access element {} of array/slice with length {}", field, len); - throw_panic!(BoundsCheck { len, index: field }); + // This can only be reached in ConstProp and non-rustc-MIR. + throw_ub!(BoundsCheckFailed { len, index: field }); } stride * field } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 5b208dd858763..47b08048f8389 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -26,7 +26,7 @@ pub fn provide(providers: &mut Providers<'_>) { providers.mir_shims = make_shim; } -fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx BodyCache<'tcx> { +fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx BodyAndCache<'tcx> { debug!("make_shim({:?})", instance); let mut result = match instance { @@ -170,7 +170,7 @@ fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>, span: Span) fn build_drop_shim<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option> -) -> BodyCache<'tcx> { +) -> BodyAndCache<'tcx> { debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty); // Check if this is a generator, if so, return the drop glue for it @@ -208,7 +208,7 @@ fn build_drop_shim<'tcx>( sig.inputs().len(), span); - let mut body = BodyCache::new(body); + let mut body = BodyAndCache::new(body); if let Some(..) = ty { // The first argument (index 0), but add 1 for the return value. @@ -322,7 +322,11 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { } /// Builds a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`. -fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> BodyCache<'tcx> { +fn build_clone_shim<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + self_ty: Ty<'tcx>, +) -> BodyAndCache<'tcx> { debug!("build_clone_shim(def_id={:?})", def_id); let param_env = tcx.param_env(def_id); @@ -351,7 +355,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - } }; - BodyCache::new(builder.into_mir()) + BodyAndCache::new(builder.into_mir()) } struct CloneShimBuilder<'tcx> { @@ -712,7 +716,7 @@ fn build_call_shim<'tcx>( rcvr_adjustment: Adjustment, call_kind: CallKind, untuple_args: Option<&[Ty<'tcx>]>, -) -> BodyCache<'tcx> { +) -> BodyAndCache<'tcx> { debug!("build_call_shim(instance={:?}, rcvr_adjustment={:?}, \ call_kind={:?}, untuple_args={:?})", instance, rcvr_adjustment, call_kind, untuple_args); @@ -853,10 +857,10 @@ fn build_call_shim<'tcx>( if let Abi::RustCall = sig.abi { body.spread_arg = Some(Local::new(sig.inputs().len())); } - BodyCache::new(body) + BodyAndCache::new(body) } -pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &BodyCache<'_> { +pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &BodyAndCache<'_> { debug_assert!(tcx.is_constructor(ctor_id)); let span = tcx.hir().span_if_local(ctor_id) @@ -940,7 +944,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &BodyCache<'_> { |_, _| Ok(()), ); - let mut body = BodyCache::new(body); + let mut body = BodyAndCache::new(body); body.ensure_predecessors(); tcx.arena.alloc(body) } diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index 35238e2d08a2e..d1832ebf962a4 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -32,14 +32,14 @@ pub use self::AddCallGuards::*; impl<'tcx> MirPass<'tcx> for AddCallGuards { fn run_pass( - &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx> + &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx> ) { self.add_call_guards(body); } } impl AddCallGuards { - pub fn add_call_guards(&self, body: &mut BodyCache<'_>) { + pub fn add_call_guards(&self, body: &mut BodyAndCache<'_>) { let pred_count: IndexVec<_, _> = body.predecessors().iter().map(|ps| ps.len()).collect(); // We need a place to store the new blocks generated diff --git a/src/librustc_mir/transform/add_moves_for_packed_drops.rs b/src/librustc_mir/transform/add_moves_for_packed_drops.rs index 98c6a5ed07780..861e7fea4f903 100644 --- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs +++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs @@ -40,14 +40,14 @@ use crate::util; pub struct AddMovesForPackedDrops; impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { debug!("add_moves_for_packed_drops({:?} @ {:?})", src, body.span); add_moves_for_packed_drops(tcx, body, src.def_id()); } } pub fn add_moves_for_packed_drops<'tcx>( - tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>, def_id: DefId + tcx: TyCtxt<'tcx>, body: &mut BodyAndCache<'tcx>, def_id: DefId ) { let patch = add_moves_for_packed_drops_patch(tcx, body, def_id); patch.apply(body); diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index e6ad37ae11362..dc21c674eea2f 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -59,7 +59,7 @@ fn may_be_reference<'tcx>(ty: Ty<'tcx>) -> bool { } impl<'tcx> MirPass<'tcx> for AddRetag { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { if !tcx.sess.opts.debugging_opts.mir_emit_retag { return; } diff --git a/src/librustc_mir/transform/check_consts/mod.rs b/src/librustc_mir/transform/check_consts/mod.rs index 82ffafbedf858..89672e81c7cd4 100644 --- a/src/librustc_mir/transform/check_consts/mod.rs +++ b/src/librustc_mir/transform/check_consts/mod.rs @@ -20,7 +20,7 @@ pub mod validation; /// Information about the item currently being const-checked, as well as a reference to the global /// context. pub struct Item<'mir, 'tcx> { - pub body: mir::ReadOnlyBodyCache<'mir, 'tcx>, + pub body: mir::ReadOnlyBodyAndCache<'mir, 'tcx>, pub tcx: TyCtxt<'tcx>, pub def_id: DefId, pub param_env: ty::ParamEnv<'tcx>, @@ -31,7 +31,7 @@ impl Item<'mir, 'tcx> { pub fn new( tcx: TyCtxt<'tcx>, def_id: DefId, - body: mir::ReadOnlyBodyCache<'mir, 'tcx>, + body: mir::ReadOnlyBodyAndCache<'mir, 'tcx>, ) -> Self { let param_env = tcx.param_env(def_id); let const_kind = ConstKind::for_item(tcx, def_id); diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 7170857926b37..6261315c711cd 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -40,7 +40,7 @@ impl QualifCursor<'a, 'mir, 'tcx, Q> { let results = dataflow::Engine::new(item.tcx, &item.body, item.def_id, dead_unwinds, analysis) .iterate_to_fixpoint(); - let cursor = dataflow::ResultsCursor::new(item.body.body(), results); + let cursor = dataflow::ResultsCursor::new(*item.body, results); let mut in_any_value_of_ty = BitSet::new_empty(item.body.local_decls.len()); for (local, decl) in item.body.local_decls.iter_enumerated() { @@ -175,13 +175,13 @@ impl Validator<'a, 'mir, 'tcx> { item.def_id, &item.tcx.get_attrs(item.def_id), &dead_unwinds, - old_dataflow::IndirectlyMutableLocals::new(item.tcx, item.body.body(), item.param_env), + old_dataflow::IndirectlyMutableLocals::new(item.tcx, *item.body, item.param_env), |_, local| old_dataflow::DebugFormatted::new(&local), ); let indirectly_mutable = old_dataflow::DataflowResultsCursor::new( indirectly_mutable, - item.body.body(), + *item.body, ); let qualifs = Qualifs { diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index d9dd7c9d84776..34519bc9fa627 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -16,7 +16,7 @@ //! [`FakeRead`]: rustc::mir::StatementKind::FakeRead //! [`Nop`]: rustc::mir::StatementKind::Nop -use rustc::mir::{BodyCache, BorrowKind, Rvalue, Location}; +use rustc::mir::{BodyAndCache, BorrowKind, Rvalue, Location}; use rustc::mir::{Statement, StatementKind}; use rustc::mir::visit::MutVisitor; use rustc::ty::TyCtxt; @@ -30,7 +30,7 @@ pub struct DeleteNonCodegenStatements<'tcx> { impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements { fn run_pass( - &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx> ) { let mut delete = DeleteNonCodegenStatements { tcx }; delete.visit_body(body); diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 95de635d634e4..884312514e47e 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -7,9 +7,9 @@ use std::cell::Cell; use rustc::hir::def::DefKind; use rustc::hir::def_id::DefId; use rustc::mir::{ - AggregateKind, Constant, Location, Place, PlaceBase, Body, BodyCache, Operand, Local, UnOp, - Rvalue, StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate, - SourceInfo, BinOp, SourceScope, SourceScopeData, LocalDecl, BasicBlock, ReadOnlyBodyCache, + AggregateKind, Constant, Location, Place, PlaceBase, Body, BodyAndCache, Operand, Local, UnOp, + Rvalue, StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate, + SourceInfo, BinOp, SourceScope, SourceScopeData, LocalDecl, BasicBlock, ReadOnlyBodyAndCache, read_only, RETURN_PLACE }; use rustc::mir::visit::{ @@ -43,7 +43,7 @@ pub struct ConstProp; impl<'tcx> MirPass<'tcx> for ConstProp { fn run_pass( - &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx> ) { // will be evaluated by miri and produce its errors there if source.promoted.is_some() { @@ -296,7 +296,7 @@ impl<'mir, 'tcx> HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> { impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { fn new( - body: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, dummy_body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, @@ -690,7 +690,7 @@ struct CanConstProp { impl CanConstProp { /// returns true if `local` can be propagated - fn check(body: ReadOnlyBodyCache<'_, '_>) -> IndexVec { + fn check(body: ReadOnlyBodyAndCache<'_, '_>) -> IndexVec { let mut cpv = CanConstProp { can_const_prop: IndexVec::from_elem(true, &body.local_decls), found_assignment: IndexVec::from_elem(false, &body.local_decls), diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index 5e4caf2f36d2d..272f6e9ce1937 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -20,7 +20,7 @@ //! future. use rustc::mir::{ - Constant, Local, LocalKind, Location, Place, Body, BodyCache, Operand, Rvalue, + Constant, Local, LocalKind, Location, Place, Body, BodyAndCache, Operand, Rvalue, StatementKind, read_only }; use rustc::mir::visit::MutVisitor; @@ -32,7 +32,7 @@ pub struct CopyPropagation; impl<'tcx> MirPass<'tcx> for CopyPropagation { fn run_pass( - &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx> ) { // We only run when the MIR optimization level is > 1. // This avoids a slow pass, and messing up debug info. @@ -250,7 +250,7 @@ impl<'tcx> Action<'tcx> { } fn perform(self, - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, def_use_analysis: &DefUseAnalysis, dest_local: Local, location: Location, diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index 933936e7efff7..cd77c9c60fa5a 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -7,7 +7,7 @@ pub struct Deaggregator; impl<'tcx> MirPass<'tcx> for Deaggregator { fn run_pass( - &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx> ) { let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); let local_decls = &*local_decls; diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index 13b3bb6da4ef9..221ced3a71c4b 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -5,7 +5,7 @@ use std::fmt; use std::fs::File; use std::io; -use rustc::mir::{Body, BodyCache}; +use rustc::mir::{Body, BodyAndCache}; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::ty::TyCtxt; use crate::transform::{MirPass, MirSource}; @@ -19,7 +19,7 @@ impl<'tcx> MirPass<'tcx> for Marker { } fn run_pass( - &self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut BodyCache<'tcx> + &self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut BodyAndCache<'tcx> ) {} } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 42daba93bd293..9970752a37698 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -21,7 +21,7 @@ use syntax_pos::Span; pub struct ElaborateDrops; impl<'tcx> MirPass<'tcx> for ElaborateDrops { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", src, body.span); let def_id = src.def_id(); diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 882e67432a5ed..1eef3f254f053 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -62,7 +62,7 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { pub struct EraseRegions; impl<'tcx> MirPass<'tcx> for EraseRegions { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { EraseRegionsVisitor::new(tcx).visit_body(body); } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index e55737e8859ef..3d15d04717211 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -378,7 +378,7 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { fn make_generator_state_argument_indirect<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, ) { let gen_ty = body.local_decls.raw[1].ty; @@ -401,7 +401,7 @@ fn make_generator_state_argument_indirect<'tcx>( DerefArgVisitor { tcx }.visit_body(body); } -fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>) { +fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyAndCache<'tcx>) { let ref_gen_ty = body.local_decls.raw[1].ty; let pin_did = tcx.lang_items().pin_type().unwrap(); @@ -418,7 +418,7 @@ fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body fn replace_result_variable<'tcx>( ret_ty: Ty<'tcx>, - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, tcx: TyCtxt<'tcx>, ) -> Local { let source_info = source_info(body); @@ -481,7 +481,7 @@ struct LivenessInfo { fn locals_live_across_suspend_points( tcx: TyCtxt<'tcx>, - body: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, source: MirSource<'tcx>, movable: bool, ) -> LivenessInfo { @@ -751,7 +751,7 @@ fn compute_layout<'tcx>( upvars: &Vec>, interior: Ty<'tcx>, movable: bool, - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, ) -> ( FxHashMap, VariantIdx, usize)>, GeneratorLayout<'tcx>, @@ -830,7 +830,7 @@ fn compute_layout<'tcx>( } fn insert_switch<'tcx>( - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, cases: Vec<(usize, BasicBlock)>, transform: &TransformVisitor<'tcx>, default: TerminatorKind<'tcx>, @@ -862,7 +862,7 @@ fn insert_switch<'tcx>( } fn elaborate_generator_drops<'tcx>( - tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut BodyCache<'tcx> + tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut BodyAndCache<'tcx> ) { use crate::util::elaborate_drops::{elaborate_drop, Unwind}; use crate::util::patch::MirPatch; @@ -928,9 +928,9 @@ fn create_generator_drop_shim<'tcx>( def_id: DefId, source: MirSource<'tcx>, gen_ty: Ty<'tcx>, - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, drop_clean: BasicBlock, -) -> BodyCache<'tcx> { +) -> BodyAndCache<'tcx> { let mut body = body.clone(); let source_info = source_info(&body); @@ -997,7 +997,7 @@ fn create_generator_drop_shim<'tcx>( } fn insert_term_block<'tcx>( - body: &mut BodyCache<'tcx>, kind: TerminatorKind<'tcx> + body: &mut BodyAndCache<'tcx>, kind: TerminatorKind<'tcx> ) -> BasicBlock { let term_block = BasicBlock::new(body.basic_blocks().len()); let source_info = source_info(body); @@ -1014,7 +1014,7 @@ fn insert_term_block<'tcx>( fn insert_panic_block<'tcx>( tcx: TyCtxt<'tcx>, - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, message: AssertMessage<'tcx>, ) -> BasicBlock { let assert_block = BasicBlock::new(body.basic_blocks().len()); @@ -1048,7 +1048,7 @@ fn create_generator_resume_function<'tcx>( transform: TransformVisitor<'tcx>, def_id: DefId, source: MirSource<'tcx>, - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, ) { // Poison the generator when it unwinds for block in body.basic_blocks_mut() { @@ -1101,7 +1101,7 @@ fn source_info(body: &Body<'_>) -> SourceInfo { } } -fn insert_clean_drop(body: &mut BodyCache<'_>) -> BasicBlock { +fn insert_clean_drop(body: &mut BodyAndCache<'_>) -> BasicBlock { let return_block = insert_term_block(body, TerminatorKind::Return); // Create a block to destroy an unresumed generators. This can only destroy upvars. @@ -1125,7 +1125,7 @@ fn insert_clean_drop(body: &mut BodyCache<'_>) -> BasicBlock { } fn create_cases<'tcx, F>( - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, transform: &TransformVisitor<'tcx>, target: F, ) -> Vec<(usize, BasicBlock)> @@ -1170,7 +1170,7 @@ where impl<'tcx> MirPass<'tcx> for StateTransform { fn run_pass( - &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx> ) { let yield_ty = if let Some(yield_ty) = body.yield_ty { yield_ty diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 79cb7fb0b7692..05b58d2e49bf1 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -39,7 +39,7 @@ struct CallSite<'tcx> { impl<'tcx> MirPass<'tcx> for Inline { fn run_pass( - &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx> ) { if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { Inliner { tcx, source }.run_pass(body); @@ -53,7 +53,7 @@ struct Inliner<'tcx> { } impl Inliner<'tcx> { - fn run_pass(&self, caller_body: &mut BodyCache<'tcx>) { + fn run_pass(&self, caller_body: &mut BodyAndCache<'tcx>) { // Keep a queue of callsites to try inlining on. We take // advantage of the fact that queries detect cycles here to // allow us to try and fetch the fully optimized MIR of a @@ -380,8 +380,8 @@ impl Inliner<'tcx> { fn inline_call(&self, callsite: CallSite<'tcx>, - caller_body: &mut BodyCache<'tcx>, - mut callee_body: BodyCache<'tcx>) -> bool { + caller_body: &mut BodyAndCache<'tcx>, + mut callee_body: BodyAndCache<'tcx>) -> bool { let terminator = caller_body[callsite.bb].terminator.take().unwrap(); match terminator.kind { // FIXME: Handle inlining of diverging calls @@ -517,7 +517,7 @@ impl Inliner<'tcx> { &self, args: Vec>, callsite: &CallSite<'tcx>, - caller_body: &mut BodyCache<'tcx>, + caller_body: &mut BodyAndCache<'tcx>, ) -> Vec { let tcx = self.tcx; @@ -590,7 +590,7 @@ impl Inliner<'tcx> { &self, arg: Operand<'tcx>, callsite: &CallSite<'tcx>, - caller_body: &mut BodyCache<'tcx>, + caller_body: &mut BodyAndCache<'tcx>, ) -> Local { // FIXME: Analysis of the usage of the arguments to avoid // unnecessary temporaries. diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index bd237b5813298..eca1b596a4846 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -1,7 +1,7 @@ //! Performs various peephole optimizations. use rustc::mir::{ - Constant, Location, Place, PlaceBase, PlaceRef, Body, BodyCache, Operand, ProjectionElem, + Constant, Location, Place, PlaceBase, PlaceRef, Body, BodyAndCache, Operand, ProjectionElem, Rvalue, Local, read_only }; use rustc::mir::visit::{MutVisitor, Visitor}; @@ -14,7 +14,7 @@ use crate::transform::{MirPass, MirSource}; pub struct InstCombine; impl<'tcx> MirPass<'tcx> for InstCombine { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { // We only run when optimizing MIR (at any level). if tcx.sess.opts.debugging_opts.mir_opt_level == 0 { return diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index df4cb7615336a..bedf2a95c026e 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -1,7 +1,7 @@ use crate::{build, shim}; use rustc_index::vec::IndexVec; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc::mir::{BodyCache, MirPhase, Promoted, ConstQualifs}; +use rustc::mir::{BodyAndCache, MirPhase, Promoted, ConstQualifs}; use rustc::ty::{TyCtxt, InstanceDef, TypeFoldable}; use rustc::ty::query::Providers; use rustc::ty::steal::Steal; @@ -97,7 +97,7 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> &DefIdSet { tcx.arena.alloc(set) } -fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { +fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { let mir = build::mir_build(tcx, def_id); tcx.alloc_steal_mir(mir) } @@ -144,12 +144,12 @@ pub trait MirPass<'tcx> { default_name::() } - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>); + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>); } pub fn run_passes( tcx: TyCtxt<'tcx>, - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, instance: InstanceDef<'tcx>, promoted: Option, mir_phase: MirPhase, @@ -220,7 +220,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs { validator.qualifs_in_return_place().into() } -fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { +fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { // Unsafety check uses the raw mir, so make sure it is run let _ = tcx.unsafety_check_result(def_id); @@ -238,7 +238,7 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { fn mir_validated( tcx: TyCtxt<'tcx>, def_id: DefId, -) -> (&'tcx Steal>, &'tcx Steal>>) { +) -> (&'tcx Steal>, &'tcx Steal>>) { // Ensure that we compute the `mir_const_qualif` for constants at // this point, before we steal the mir-const result. let _ = tcx.mir_const_qualif(def_id); @@ -257,7 +257,7 @@ fn mir_validated( fn run_optimization_passes<'tcx>( tcx: TyCtxt<'tcx>, - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, def_id: DefId, promoted: Option, ) { @@ -319,7 +319,7 @@ fn run_optimization_passes<'tcx>( ]); } -fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyCache<'_> { +fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyAndCache<'_> { if tcx.is_constructor(def_id) { // There's no reason to run all of the MIR passes on constructors when // we can just output the MIR we want directly. This also saves const @@ -339,7 +339,7 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyCache<'_> { tcx.arena.alloc(body) } -fn promoted_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &IndexVec> { +fn promoted_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &IndexVec> { if tcx.is_constructor(def_id) { return tcx.intern_promoted(IndexVec::new()); } diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs index 5e1d29d47ade9..d4fe72f6ed7c8 100644 --- a/src/librustc_mir/transform/no_landing_pads.rs +++ b/src/librustc_mir/transform/no_landing_pads.rs @@ -17,12 +17,12 @@ impl<'tcx> NoLandingPads<'tcx> { } impl<'tcx> MirPass<'tcx> for NoLandingPads<'tcx> { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { no_landing_pads(tcx, body) } } -pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>) { +pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyAndCache<'tcx>) { if tcx.sess.no_landing_pads() { NoLandingPads::new(tcx).visit_body(body); } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index c758ccfd11d91..4c723199102be 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -41,11 +41,11 @@ use crate::transform::check_consts::{qualifs, Item, ConstKind, is_lang_panic_fn} /// newly created `StaticKind::Promoted`. #[derive(Default)] pub struct PromoteTemps<'tcx> { - pub promoted_fragments: Cell>>, + pub promoted_fragments: Cell>>, } impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { // There's not really any point in promoting errorful MIR. // // This does not include MIR that failed const-checking, which we still try to promote. @@ -742,7 +742,7 @@ impl<'tcx> Validator<'_, 'tcx> { // FIXME(eddyb) remove the differences for promotability in `static`, `const`, `const fn`. pub fn validate_candidates( tcx: TyCtxt<'tcx>, - body: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, def_id: DefId, temps: &IndexVec, candidates: &[Candidate], @@ -775,8 +775,8 @@ pub fn validate_candidates( struct Promoter<'a, 'tcx> { tcx: TyCtxt<'tcx>, - source: &'a mut BodyCache<'tcx>, - promoted: BodyCache<'tcx>, + source: &'a mut BodyAndCache<'tcx>, + promoted: BodyAndCache<'tcx>, temps: &'a mut IndexVec, /// If true, all nested temps are also kept in the @@ -924,7 +924,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { def_id: DefId, candidate: Candidate, next_promoted_id: usize, - ) -> Option> { + ) -> Option> { let mut operand = { let promoted = &mut self.promoted; let promoted_id = Promoted::new(next_promoted_id); @@ -1045,11 +1045,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { pub fn promote_candidates<'tcx>( def_id: DefId, - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, tcx: TyCtxt<'tcx>, mut temps: IndexVec, candidates: Vec, -) -> IndexVec> { +) -> IndexVec> { // Visit candidates in reverse, in case they're nested. debug!("promote_candidates({:?})", candidates); @@ -1081,7 +1081,7 @@ pub fn promote_candidates<'tcx>( ).collect(); let promoter = Promoter { - promoted: BodyCache::new(Body::new( + promoted: BodyAndCache::new(Body::new( IndexVec::new(), // FIXME: maybe try to filter this to avoid blowing up // memory usage? @@ -1150,7 +1150,7 @@ pub fn promote_candidates<'tcx>( crate fn should_suggest_const_in_array_repeat_expressions_attribute<'tcx>( tcx: TyCtxt<'tcx>, mir_def_id: DefId, - body: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyAndCache<'_, 'tcx>, operand: &Operand<'tcx>, ) -> bool { let mut rpo = traversal::reverse_postorder(&body); diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index c636aba9fc607..5799d0c38b01d 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -9,7 +9,7 @@ use crate::util::patch::MirPatch; /// code for these. pub struct RemoveNoopLandingPads; -pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>) { +pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyAndCache<'tcx>) { if tcx.sess.no_landing_pads() { return } @@ -19,7 +19,7 @@ pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyCache<'t } impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { remove_noop_landing_pads(tcx, body); } } @@ -84,7 +84,7 @@ impl RemoveNoopLandingPads { } } - fn remove_nop_landing_pads(&self, body: &mut BodyCache<'_>) { + fn remove_nop_landing_pads(&self, body: &mut BodyAndCache<'_>) { // make sure there's a single resume block let resume_block = { let patch = MirPatch::new(body); diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 794ced1cb0ef5..2a81e97b8ff25 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -5,7 +5,7 @@ use syntax_pos::Span; use rustc::ty::{self, TyCtxt, Ty}; use rustc::hir::def_id::DefId; -use rustc::mir::{self, Body, BodyCache, Location, Local}; +use rustc::mir::{self, Body, BodyAndCache, Location, Local}; use rustc_index::bit_set::BitSet; use crate::transform::{MirPass, MirSource}; @@ -26,7 +26,7 @@ use crate::dataflow::has_rustc_mir_with; pub struct SanityCheck; impl<'tcx> MirPass<'tcx> for SanityCheck { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { let def_id = src.def_id(); if !tcx.has_attr(def_id, sym::rustc_mir) { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 900752d3ce06c..eef39f8040ea0 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -43,7 +43,7 @@ impl SimplifyCfg { } } -pub fn simplify_cfg(body: &mut BodyCache<'_>) { +pub fn simplify_cfg(body: &mut BodyAndCache<'_>) { CfgSimplifier::new(body).simplify(); remove_dead_blocks(body); @@ -57,7 +57,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg { } fn run_pass( - &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx> + &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx> ) { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body); simplify_cfg(body); @@ -70,7 +70,7 @@ pub struct CfgSimplifier<'a, 'tcx> { } impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { - pub fn new(body: &'a mut BodyCache<'tcx>) -> Self { + pub fn new(body: &'a mut BodyAndCache<'tcx>) -> Self { let mut pred_count = IndexVec::from_elem(0u32, body.basic_blocks()); // we can't use mir.predecessors() here because that counts @@ -262,7 +262,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } } -pub fn remove_dead_blocks(body: &mut BodyCache<'_>) { +pub fn remove_dead_blocks(body: &mut BodyAndCache<'_>) { let mut seen = BitSet::new_empty(body.basic_blocks().len()); for (bb, _) in traversal::preorder(body) { seen.insert(bb.index()); @@ -296,7 +296,7 @@ pub struct SimplifyLocals; impl<'tcx> MirPass<'tcx> for SimplifyLocals { fn run_pass( - &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx> ) { trace!("running SimplifyLocals on {:?}", source); let locals = { diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index c8d0f37f9a509..aa3c5b01be35f 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -19,7 +19,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches { Cow::Borrowed(&self.label) } - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { let param_env = tcx.param_env(src.def_id()); for block in body.basic_blocks_mut() { let terminator = block.terminator_mut(); diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs index 2235de9a1533a..752e852895738 100644 --- a/src/librustc_mir/transform/simplify_try.rs +++ b/src/librustc_mir/transform/simplify_try.rs @@ -33,7 +33,7 @@ use itertools::Itertools as _; pub struct SimplifyArmIdentity; impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity { - fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); for bb in basic_blocks { // Need 3 statements: @@ -151,7 +151,7 @@ fn match_variant_field_place<'tcx>(place: &Place<'tcx>) -> Option<(Local, VarFie pub struct SimplifyBranchSame; impl<'tcx> MirPass<'tcx> for SimplifyBranchSame { - fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { let mut did_remove_blocks = false; let bbs = body.basic_blocks_mut(); for bb_idx in bbs.indices() { diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index 3fc76ef6b00e0..71dd405386aa7 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -37,7 +37,7 @@ use crate::util::patch::MirPatch; pub struct UniformArrayMoveOut; impl<'tcx> MirPass<'tcx> for UniformArrayMoveOut { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { let mut patch = MirPatch::new(body); let param_env = tcx.param_env(src.def_id()); { @@ -186,7 +186,7 @@ pub struct RestoreSubsliceArrayMoveOut<'tcx> { } impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { let mut patch = MirPatch::new(body); let param_env = tcx.param_env(src.def_id()); { diff --git a/src/librustc_mir/transform/uninhabited_enum_branching.rs b/src/librustc_mir/transform/uninhabited_enum_branching.rs index 26081d9394664..0bf0ff2852d72 100644 --- a/src/librustc_mir/transform/uninhabited_enum_branching.rs +++ b/src/librustc_mir/transform/uninhabited_enum_branching.rs @@ -2,7 +2,7 @@ use crate::transform::{MirPass, MirSource}; use rustc::mir::{ - BasicBlock, BasicBlockData, Body, BodyCache, Local, Operand, Rvalue, StatementKind, + BasicBlock, BasicBlockData, Body, BodyAndCache, Local, Operand, Rvalue, StatementKind, TerminatorKind, }; use rustc::ty::layout::{Abi, TyLayout, Variants}; @@ -66,7 +66,7 @@ fn variant_discriminants<'tcx>( } impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { if source.promoted.is_some() { return; } diff --git a/src/librustc_mir/util/collect_writes.rs b/src/librustc_mir/util/collect_writes.rs index f94bea2002461..4006787f260fc 100644 --- a/src/librustc_mir/util/collect_writes.rs +++ b/src/librustc_mir/util/collect_writes.rs @@ -1,5 +1,5 @@ use rustc::mir::{Local, Location}; -use rustc::mir::ReadOnlyBodyCache; +use rustc::mir::ReadOnlyBodyAndCache; use rustc::mir::visit::PlaceContext; use rustc::mir::visit::Visitor; @@ -9,7 +9,7 @@ crate trait FindAssignments { fn find_assignments(&self, local: Local) -> Vec; } -impl<'a, 'tcx> FindAssignments for ReadOnlyBodyCache<'a, 'tcx>{ +impl<'a, 'tcx> FindAssignments for ReadOnlyBodyAndCache<'a, 'tcx>{ fn find_assignments(&self, local: Local) -> Vec{ let mut visitor = FindLocalAssignmentVisitor{ needle: local, locations: vec![]}; visitor.visit_body(*self); diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 1907e9bdc9746..cf98755eb6d90 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -1,6 +1,8 @@ //! Def-use analysis. -use rustc::mir::{Body, BodyCache, Local, Location, PlaceElem, ReadOnlyBodyCache, VarDebugInfo}; +use rustc::mir::{ + Body, BodyAndCache, Local, Location, PlaceElem, ReadOnlyBodyAndCache, VarDebugInfo, +}; use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor}; use rustc::ty::TyCtxt; use rustc_index::vec::IndexVec; @@ -30,7 +32,7 @@ impl DefUseAnalysis { } } - pub fn analyze(&mut self, body: ReadOnlyBodyCache<'_, '_>) { + pub fn analyze(&mut self, body: ReadOnlyBodyAndCache<'_, '_>) { self.clear(); let mut finder = DefUseFinder { @@ -55,7 +57,7 @@ impl DefUseAnalysis { fn mutate_defs_and_uses( &self, local: Local, - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, new_local: Local, tcx: TyCtxt<'tcx>, ) { @@ -73,7 +75,7 @@ impl DefUseAnalysis { // FIXME(pcwalton): this should update the def-use chains. pub fn replace_all_defs_and_uses_with(&self, local: Local, - body: &mut BodyCache<'tcx>, + body: &mut BodyAndCache<'tcx>, new_local: Local, tcx: TyCtxt<'tcx>) { self.mutate_defs_and_uses(local, body, new_local, tcx) diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 334975373e5f3..68c2e16399a59 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -57,7 +57,7 @@ pub struct LivenessResult { /// Computes which local variables are live within the given function /// `mir`, including drops. pub fn liveness_of_locals( - body: ReadOnlyBodyCache<'_, '_>, + body: ReadOnlyBodyAndCache<'_, '_>, ) -> LivenessResult { let num_live_vars = body.local_decls.len(); diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index 47bb0b699c048..575b6d25de20d 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -127,7 +127,7 @@ impl<'tcx> MirPatch<'tcx> { self.make_nop.push(loc); } - pub fn apply(self, body: &mut BodyCache<'tcx>) { + pub fn apply(self, body: &mut BodyAndCache<'tcx>) { debug!("MirPatch: make nops at: {:?}", self.make_nop); for loc in self.make_nop { body.make_statement_nop(loc); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4d8d0040cdcd7..327be40a58f2f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -5,12 +5,12 @@ pub mod inline; pub mod cfg; -mod simplify; mod auto_trait; mod blanket_impl; +mod simplify; +pub mod types; use rustc_index::vec::{IndexVec, Idx}; -use rustc_target::spec::abi::Abi; use rustc_typeck::hir_ty_to_ty; use rustc::infer::region_constraints::{RegionConstraintData, Constraint}; use rustc::middle::resolve_lifetime as rl; @@ -24,46 +24,33 @@ use rustc::hir::ptr::P; use rustc::ty::subst::{InternalSubsts, SubstsRef, GenericArgKind}; use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind}; use rustc::ty::fold::TypeFolder; -use rustc::ty::layout::VariantIdx; use rustc::util::nodemap::{FxHashMap, FxHashSet}; -use syntax::ast::{self, Attribute, AttrStyle, AttrKind, Ident}; +use syntax::ast::{self, Ident}; use syntax::attr; -use syntax::util::comments; -use syntax::source_map::DUMMY_SP; use syntax_pos::symbol::{Symbol, kw, sym}; use syntax_pos::hygiene::MacroKind; -use syntax_pos::{self, Pos, FileName}; +use syntax_pos::{self, Pos}; use std::collections::hash_map::Entry; -use std::fmt; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; use std::default::Default; -use std::{mem, slice, vec}; -use std::num::NonZeroU32; -use std::iter::FromIterator; +use std::{mem, vec}; use std::rc::Rc; -use std::cell::RefCell; -use std::sync::Arc; use std::u32; use crate::core::{self, DocContext, ImplTraitParam}; use crate::doctree; -use crate::html::render::{cache, ExternalLocation}; -use crate::html::item_type::ItemType; - -use self::cfg::Cfg; use self::auto_trait::AutoTraitFinder; use self::blanket_impl::BlanketImplFinder; -pub use self::Type::*; -pub use self::Mutability::*; -pub use self::ItemEnum::*; -pub use self::SelfTy::*; -pub use self::FunctionRetTy::*; -pub use self::Visibility::{Public, Inherited}; - -thread_local!(pub static MAX_DEF_ID: RefCell> = Default::default()); +pub use self::types::*; +pub use self::types::Type::*; +pub use self::types::Mutability::*; +pub use self::types::ItemEnum::*; +pub use self::types::SelfTy::*; +pub use self::types::FunctionRetTy::*; +pub use self::types::Visibility::{Public, Inherited}; const FN_OUTPUT_NAME: &'static str = "Output"; @@ -122,21 +109,6 @@ impl, U> Clean> for P<[T]> { } } -#[derive(Clone, Debug)] -pub struct Crate { - pub name: String, - pub version: Option, - pub src: FileName, - pub module: Option, - pub externs: Vec<(CrateNum, ExternalCrate)>, - pub primitives: Vec<(DefId, PrimitiveType, Attributes)>, - // These are later on moved into `CACHEKEY`, leaving the map empty. - // Only here so that they can be filtered through the rustdoc passes. - pub external_traits: Rc>>, - pub masked_crates: FxHashSet, - pub collapsed: bool, -} - pub fn krate(mut cx: &mut DocContext<'_>) -> Crate { use crate::visit_lib::LibEmbargoVisitor; @@ -222,15 +194,6 @@ pub fn krate(mut cx: &mut DocContext<'_>) -> Crate { } } -#[derive(Clone, Debug)] -pub struct ExternalCrate { - pub name: String, - pub src: FileName, - pub attrs: Attributes, - pub primitives: Vec<(DefId, PrimitiveType, Attributes)>, - pub keywords: Vec<(DefId, String, Attributes)>, -} - impl Clean for CrateNum { fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate { let root = DefId { krate: *self, index: CRATE_DEF_INDEX }; @@ -351,237 +314,6 @@ impl Clean for CrateNum { } } -/// Anything with a source location and set of attributes and, optionally, a -/// name. That is, anything that can be documented. This doesn't correspond -/// directly to the AST's concept of an item; it's a strict superset. -#[derive(Clone)] -pub struct Item { - /// Stringified span - pub source: Span, - /// Not everything has a name. E.g., impls - pub name: Option, - pub attrs: Attributes, - pub inner: ItemEnum, - pub visibility: Visibility, - pub def_id: DefId, - pub stability: Option, - pub deprecation: Option, -} - -impl fmt::Debug for Item { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - - let fake = MAX_DEF_ID.with(|m| m.borrow().get(&self.def_id.krate) - .map(|id| self.def_id >= *id).unwrap_or(false)); - let def_id: &dyn fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id }; - - fmt.debug_struct("Item") - .field("source", &self.source) - .field("name", &self.name) - .field("attrs", &self.attrs) - .field("inner", &self.inner) - .field("visibility", &self.visibility) - .field("def_id", def_id) - .field("stability", &self.stability) - .field("deprecation", &self.deprecation) - .finish() - } -} - -impl Item { - /// Finds the `doc` attribute as a NameValue and returns the corresponding - /// value found. - pub fn doc_value(&self) -> Option<&str> { - self.attrs.doc_value() - } - /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined - /// with newlines. - pub fn collapsed_doc_value(&self) -> Option { - self.attrs.collapsed_doc_value() - } - - pub fn links(&self) -> Vec<(String, String)> { - self.attrs.links(&self.def_id.krate) - } - - pub fn is_crate(&self) -> bool { - match self.inner { - StrippedItem(box ModuleItem(Module { is_crate: true, ..})) | - ModuleItem(Module { is_crate: true, ..}) => true, - _ => false, - } - } - pub fn is_mod(&self) -> bool { - self.type_() == ItemType::Module - } - pub fn is_trait(&self) -> bool { - self.type_() == ItemType::Trait - } - pub fn is_struct(&self) -> bool { - self.type_() == ItemType::Struct - } - pub fn is_enum(&self) -> bool { - self.type_() == ItemType::Enum - } - pub fn is_variant(&self) -> bool { - self.type_() == ItemType::Variant - } - pub fn is_associated_type(&self) -> bool { - self.type_() == ItemType::AssocType - } - pub fn is_associated_const(&self) -> bool { - self.type_() == ItemType::AssocConst - } - pub fn is_method(&self) -> bool { - self.type_() == ItemType::Method - } - pub fn is_ty_method(&self) -> bool { - self.type_() == ItemType::TyMethod - } - pub fn is_typedef(&self) -> bool { - self.type_() == ItemType::Typedef - } - pub fn is_primitive(&self) -> bool { - self.type_() == ItemType::Primitive - } - pub fn is_union(&self) -> bool { - self.type_() == ItemType::Union - } - pub fn is_import(&self) -> bool { - self.type_() == ItemType::Import - } - pub fn is_extern_crate(&self) -> bool { - self.type_() == ItemType::ExternCrate - } - pub fn is_keyword(&self) -> bool { - self.type_() == ItemType::Keyword - } - - pub fn is_stripped(&self) -> bool { - match self.inner { StrippedItem(..) => true, _ => false } - } - pub fn has_stripped_fields(&self) -> Option { - match self.inner { - StructItem(ref _struct) => Some(_struct.fields_stripped), - UnionItem(ref union) => Some(union.fields_stripped), - VariantItem(Variant { kind: VariantKind::Struct(ref vstruct)} ) => { - Some(vstruct.fields_stripped) - }, - _ => None, - } - } - - pub fn stability_class(&self) -> Option { - self.stability.as_ref().and_then(|ref s| { - let mut classes = Vec::with_capacity(2); - - if s.level == stability::Unstable { - classes.push("unstable"); - } - - if s.deprecation.is_some() { - classes.push("deprecated"); - } - - if classes.len() != 0 { - Some(classes.join(" ")) - } else { - None - } - }) - } - - pub fn stable_since(&self) -> Option<&str> { - self.stability.as_ref().map(|s| &s.since[..]) - } - - pub fn is_non_exhaustive(&self) -> bool { - self.attrs.other_attrs.iter() - .any(|a| a.check_name(sym::non_exhaustive)) - } - - /// Returns a documentation-level item type from the item. - pub fn type_(&self) -> ItemType { - ItemType::from(self) - } - - /// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes. - /// - /// If the item is not deprecated, returns `None`. - pub fn deprecation(&self) -> Option<&Deprecation> { - self.deprecation - .as_ref() - .or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref())) - } - pub fn is_default(&self) -> bool { - match self.inner { - ItemEnum::MethodItem(ref meth) => { - if let Some(defaultness) = meth.defaultness { - defaultness.has_value() && !defaultness.is_final() - } else { - false - } - } - _ => false, - } - } -} - -#[derive(Clone, Debug)] -pub enum ItemEnum { - ExternCrateItem(String, Option), - ImportItem(Import), - StructItem(Struct), - UnionItem(Union), - EnumItem(Enum), - FunctionItem(Function), - ModuleItem(Module), - TypedefItem(Typedef, bool /* is associated type */), - OpaqueTyItem(OpaqueTy, bool /* is associated type */), - StaticItem(Static), - ConstantItem(Constant), - TraitItem(Trait), - TraitAliasItem(TraitAlias), - ImplItem(Impl), - /// A method signature only. Used for required methods in traits (ie, - /// non-default-methods). - TyMethodItem(TyMethod), - /// A method with a body. - MethodItem(Method), - StructFieldItem(Type), - VariantItem(Variant), - /// `fn`s from an extern block - ForeignFunctionItem(Function), - /// `static`s from an extern block - ForeignStaticItem(Static), - /// `type`s from an extern block - ForeignTypeItem, - MacroItem(Macro), - ProcMacroItem(ProcMacro), - PrimitiveItem(PrimitiveType), - AssocConstItem(Type, Option), - AssocTypeItem(Vec, Option), - /// An item that has been stripped by a rustdoc pass - StrippedItem(Box), - KeywordItem(String), -} - -impl ItemEnum { - pub fn is_associated(&self) -> bool { - match *self { - ItemEnum::TypedefItem(_, _) | - ItemEnum::AssocTypeItem(_, _) => true, - _ => false, - } - } -} - -#[derive(Clone, Debug)] -pub struct Module { - pub items: Vec, - pub is_crate: bool, -} - impl Clean for doctree::Module<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let name = if self.name.is_some() { @@ -645,465 +377,12 @@ impl Clean for doctree::Module<'_> { } } -pub struct ListAttributesIter<'a> { - attrs: slice::Iter<'a, ast::Attribute>, - current_list: vec::IntoIter, - name: Symbol, -} - -impl<'a> Iterator for ListAttributesIter<'a> { - type Item = ast::NestedMetaItem; - - fn next(&mut self) -> Option { - if let Some(nested) = self.current_list.next() { - return Some(nested); - } - - for attr in &mut self.attrs { - if let Some(list) = attr.meta_item_list() { - if attr.check_name(self.name) { - self.current_list = list.into_iter(); - if let Some(nested) = self.current_list.next() { - return Some(nested); - } - } - } - } - - None - } - - fn size_hint(&self) -> (usize, Option) { - let lower = self.current_list.len(); - (lower, None) - } -} - -pub trait AttributesExt { - /// Finds an attribute as List and returns the list of attributes nested inside. - fn lists(&self, name: Symbol) -> ListAttributesIter<'_>; -} - -impl AttributesExt for [ast::Attribute] { - fn lists(&self, name: Symbol) -> ListAttributesIter<'_> { - ListAttributesIter { - attrs: self.iter(), - current_list: Vec::new().into_iter(), - name, - } - } -} - -pub trait NestedAttributesExt { - /// Returns `true` if the attribute list contains a specific `Word` - fn has_word(self, word: Symbol) -> bool; -} - -impl> NestedAttributesExt for I { - fn has_word(self, word: Symbol) -> bool { - self.into_iter().any(|attr| attr.is_word() && attr.check_name(word)) - } -} - -/// A portion of documentation, extracted from a `#[doc]` attribute. -/// -/// Each variant contains the line number within the complete doc-comment where the fragment -/// starts, as well as the Span where the corresponding doc comment or attribute is located. -/// -/// Included files are kept separate from inline doc comments so that proper line-number -/// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are -/// kept separate because of issue #42760. -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum DocFragment { - /// A doc fragment created from a `///` or `//!` doc comment. - SugaredDoc(usize, syntax_pos::Span, String), - /// A doc fragment created from a "raw" `#[doc=""]` attribute. - RawDoc(usize, syntax_pos::Span, String), - /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the - /// given filename and the file contents. - Include(usize, syntax_pos::Span, String, String), -} - -impl DocFragment { - pub fn as_str(&self) -> &str { - match *self { - DocFragment::SugaredDoc(_, _, ref s) => &s[..], - DocFragment::RawDoc(_, _, ref s) => &s[..], - DocFragment::Include(_, _, _, ref s) => &s[..], - } - } - - pub fn span(&self) -> syntax_pos::Span { - match *self { - DocFragment::SugaredDoc(_, span, _) | - DocFragment::RawDoc(_, span, _) | - DocFragment::Include(_, span, _, _) => span, - } - } -} - -impl<'a> FromIterator<&'a DocFragment> for String { - fn from_iter(iter: T) -> Self - where - T: IntoIterator - { - iter.into_iter().fold(String::new(), |mut acc, frag| { - if !acc.is_empty() { - acc.push('\n'); - } - match *frag { - DocFragment::SugaredDoc(_, _, ref docs) - | DocFragment::RawDoc(_, _, ref docs) - | DocFragment::Include(_, _, _, ref docs) => - acc.push_str(docs), - } - - acc - }) - } -} - -#[derive(Clone, Debug, Default)] -pub struct Attributes { - pub doc_strings: Vec, - pub other_attrs: Vec, - pub cfg: Option>, - pub span: Option, - /// map from Rust paths to resolved defs and potential URL fragments - pub links: Vec<(String, Option, Option)>, - pub inner_docs: bool, -} - -impl Attributes { - /// Extracts the content from an attribute `#[doc(cfg(content))]`. - fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> { - use syntax::ast::NestedMetaItem::MetaItem; - - if let ast::MetaItemKind::List(ref nmis) = mi.kind { - if nmis.len() == 1 { - if let MetaItem(ref cfg_mi) = nmis[0] { - if cfg_mi.check_name(sym::cfg) { - if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind { - if cfg_nmis.len() == 1 { - if let MetaItem(ref content_mi) = cfg_nmis[0] { - return Some(content_mi); - } - } - } - } - } - } - } - - None - } - - /// Reads a `MetaItem` from within an attribute, looks for whether it is a - /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from - /// its expansion. - fn extract_include(mi: &ast::MetaItem) - -> Option<(String, String)> - { - mi.meta_item_list().and_then(|list| { - for meta in list { - if meta.check_name(sym::include) { - // the actual compiled `#[doc(include="filename")]` gets expanded to - // `#[doc(include(file="filename", contents="file contents")]` so we need to - // look for that instead - return meta.meta_item_list().and_then(|list| { - let mut filename: Option = None; - let mut contents: Option = None; - - for it in list { - if it.check_name(sym::file) { - if let Some(name) = it.value_str() { - filename = Some(name.to_string()); - } - } else if it.check_name(sym::contents) { - if let Some(docs) = it.value_str() { - contents = Some(docs.to_string()); - } - } - } - - if let (Some(filename), Some(contents)) = (filename, contents) { - Some((filename, contents)) - } else { - None - } - }); - } - } - - None - }) - } - - pub fn has_doc_flag(&self, flag: Symbol) -> bool { - for attr in &self.other_attrs { - if !attr.check_name(sym::doc) { continue; } - - if let Some(items) = attr.meta_item_list() { - if items.iter().filter_map(|i| i.meta_item()).any(|it| it.check_name(flag)) { - return true; - } - } - } - - false - } - - pub fn from_ast(diagnostic: &::errors::Handler, - attrs: &[ast::Attribute]) -> Attributes { - let mut doc_strings = vec![]; - let mut sp = None; - let mut cfg = Cfg::True; - let mut doc_line = 0; - - /// If `attr` is a doc comment, strips the leading and (if present) - /// trailing comments symbols, e.g. `///`, `/**`, and `*/`. Otherwise, - /// returns `attr` unchanged. - pub fn with_doc_comment_markers_stripped( - attr: &Attribute, - f: impl FnOnce(&Attribute) -> T - ) -> T { - match attr.kind { - AttrKind::Normal(_) => { - f(attr) - } - AttrKind::DocComment(comment) => { - let comment = - Symbol::intern(&comments::strip_doc_comment_decoration(&comment.as_str())); - f(&Attribute { - kind: AttrKind::DocComment(comment), - id: attr.id, - style: attr.style, - span: attr.span, - }) - } - } - } - - let other_attrs = attrs.iter().filter_map(|attr| { - with_doc_comment_markers_stripped(attr, |attr| { - if attr.check_name(sym::doc) { - if let Some(mi) = attr.meta() { - if let Some(value) = mi.value_str() { - // Extracted #[doc = "..."] - let value = value.to_string(); - let line = doc_line; - doc_line += value.lines().count(); - - if attr.is_doc_comment() { - doc_strings.push(DocFragment::SugaredDoc(line, attr.span, value)); - } else { - doc_strings.push(DocFragment::RawDoc(line, attr.span, value)); - } - - if sp.is_none() { - sp = Some(attr.span); - } - return None; - } else if let Some(cfg_mi) = Attributes::extract_cfg(&mi) { - // Extracted #[doc(cfg(...))] - match Cfg::parse(cfg_mi) { - Ok(new_cfg) => cfg &= new_cfg, - Err(e) => diagnostic.span_err(e.span, e.msg), - } - return None; - } else if let Some((filename, contents)) = Attributes::extract_include(&mi) - { - let line = doc_line; - doc_line += contents.lines().count(); - doc_strings.push(DocFragment::Include(line, - attr.span, - filename, - contents)); - } - } - } - Some(attr.clone()) - }) - }).collect(); - - // treat #[target_feature(enable = "feat")] attributes as if they were - // #[doc(cfg(target_feature = "feat"))] attributes as well - for attr in attrs.lists(sym::target_feature) { - if attr.check_name(sym::enable) { - if let Some(feat) = attr.value_str() { - let meta = attr::mk_name_value_item_str( - Ident::with_dummy_span(sym::target_feature), feat, DUMMY_SP - ); - if let Ok(feat_cfg) = Cfg::parse(&meta) { - cfg &= feat_cfg; - } - } - } - } - - let inner_docs = attrs.iter() - .filter(|a| a.check_name(sym::doc)) - .next() - .map_or(true, |a| a.style == AttrStyle::Inner); - - Attributes { - doc_strings, - other_attrs, - cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }, - span: sp, - links: vec![], - inner_docs, - } - } - - /// Finds the `doc` attribute as a NameValue and returns the corresponding - /// value found. - pub fn doc_value(&self) -> Option<&str> { - self.doc_strings.first().map(|s| s.as_str()) - } - - /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined - /// with newlines. - pub fn collapsed_doc_value(&self) -> Option { - if !self.doc_strings.is_empty() { - Some(self.doc_strings.iter().collect()) - } else { - None - } - } - - /// Gets links as a vector - /// - /// Cache must be populated before call - pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> { - use crate::html::format::href; - - self.links.iter().filter_map(|&(ref s, did, ref fragment)| { - match did { - Some(did) => { - if let Some((mut href, ..)) = href(did) { - if let Some(ref fragment) = *fragment { - href.push_str("#"); - href.push_str(fragment); - } - Some((s.clone(), href)) - } else { - None - } - } - None => { - if let Some(ref fragment) = *fragment { - let cache = cache(); - let url = match cache.extern_locations.get(krate) { - Some(&(_, ref src, ExternalLocation::Local)) => - src.to_str().expect("invalid file path"), - Some(&(_, _, ExternalLocation::Remote(ref s))) => s, - Some(&(_, _, ExternalLocation::Unknown)) | None => - "https://doc.rust-lang.org/nightly", - }; - // This is a primitive so the url is done "by hand". - let tail = fragment.find('#').unwrap_or_else(|| fragment.len()); - Some((s.clone(), - format!("{}{}std/primitive.{}.html{}", - url, - if !url.ends_with('/') { "/" } else { "" }, - &fragment[..tail], - &fragment[tail..]))) - } else { - panic!("This isn't a primitive?!"); - } - } - } - }).collect() - } -} - -impl PartialEq for Attributes { - fn eq(&self, rhs: &Self) -> bool { - self.doc_strings == rhs.doc_strings && - self.cfg == rhs.cfg && - self.span == rhs.span && - self.links == rhs.links && - self.other_attrs.iter().map(|attr| attr.id).eq(rhs.other_attrs.iter().map(|attr| attr.id)) - } -} - -impl Eq for Attributes {} - -impl Hash for Attributes { - fn hash(&self, hasher: &mut H) { - self.doc_strings.hash(hasher); - self.cfg.hash(hasher); - self.span.hash(hasher); - self.links.hash(hasher); - for attr in &self.other_attrs { - attr.id.hash(hasher); - } - } -} - -impl AttributesExt for Attributes { - fn lists(&self, name: Symbol) -> ListAttributesIter<'_> { - self.other_attrs.lists(name) - } -} - impl Clean for [ast::Attribute] { fn clean(&self, cx: &DocContext<'_>) -> Attributes { Attributes::from_ast(cx.sess().diagnostic(), self) } } -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum GenericBound { - TraitBound(PolyTrait, hir::TraitBoundModifier), - Outlives(Lifetime), -} - -impl GenericBound { - fn maybe_sized(cx: &DocContext<'_>) -> GenericBound { - let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); - let empty = cx.tcx.intern_substs(&[]); - let path = external_path(cx, cx.tcx.item_name(did), - Some(did), false, vec![], empty); - inline::record_extern_fqn(cx, did, TypeKind::Trait); - GenericBound::TraitBound(PolyTrait { - trait_: ResolvedPath { - path, - param_names: None, - did, - is_generic: false, - }, - generic_params: Vec::new(), - }, hir::TraitBoundModifier::Maybe) - } - - fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool { - use rustc::hir::TraitBoundModifier as TBM; - if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self { - if trait_.def_id() == cx.tcx.lang_items().sized_trait() { - return true; - } - } - false - } - - fn get_poly_trait(&self) -> Option { - if let GenericBound::TraitBound(ref p, _) = *self { - return Some(p.clone()) - } - None - } - - fn get_trait_type(&self) -> Option { - if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self { - Some(trait_.clone()) - } else { - None - } - } -} - impl Clean for hir::GenericBound { fn clean(&self, cx: &DocContext<'_>) -> GenericBound { match *self { @@ -1237,21 +516,6 @@ impl<'tcx> Clean>> for InternalSubsts<'tcx> { } } -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct Lifetime(String); - -impl Lifetime { - pub fn get_ref<'a>(&'a self) -> &'a str { - let Lifetime(ref s) = *self; - let s: &'a str = s; - s - } - - pub fn statik() -> Lifetime { - Lifetime("'static".to_string()) - } -} - impl Clean for hir::Lifetime { fn clean(&self, cx: &DocContext<'_>) -> Lifetime { if self.hir_id != hir::DUMMY_HIR_ID { @@ -1332,23 +596,6 @@ impl Clean> for ty::RegionKind { } } -#[derive(Clone, Debug)] -pub enum WherePredicate { - BoundPredicate { ty: Type, bounds: Vec }, - RegionPredicate { lifetime: Lifetime, bounds: Vec }, - EqPredicate { lhs: Type, rhs: Type }, -} - -impl WherePredicate { - pub fn get_bounds(&self) -> Option<&[GenericBound]> { - match *self { - WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds), - WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds), - _ => None, - } - } -} - impl Clean for hir::WherePredicate { fn clean(&self, cx: &DocContext<'_>) -> WherePredicate { match *self { @@ -1470,73 +717,6 @@ impl<'tcx> Clean for ty::ProjectionTy<'tcx> { } } -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum GenericParamDefKind { - Lifetime, - Type { - did: DefId, - bounds: Vec, - default: Option, - synthetic: Option, - }, - Const { - did: DefId, - ty: Type, - }, -} - -impl GenericParamDefKind { - pub fn is_type(&self) -> bool { - match *self { - GenericParamDefKind::Type { .. } => true, - _ => false, - } - } - - // FIXME(eddyb) this either returns the default of a type parameter, or the - // type of a `const` parameter. It seems that the intention is to *visit* - // any embedded types, but `get_type` seems to be the wrong name for that. - pub fn get_type(&self) -> Option { - match self { - GenericParamDefKind::Type { default, .. } => default.clone(), - GenericParamDefKind::Const { ty, .. } => Some(ty.clone()), - GenericParamDefKind::Lifetime => None, - } - } -} - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct GenericParamDef { - pub name: String, - - pub kind: GenericParamDefKind, -} - -impl GenericParamDef { - pub fn is_synthetic_type_param(&self) -> bool { - match self.kind { - GenericParamDefKind::Lifetime | - GenericParamDefKind::Const { .. } => false, - GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(), - } - } - - pub fn is_type(&self) -> bool { - self.kind.is_type() - } - - pub fn get_type(&self) -> Option { - self.kind.get_type() - } - - pub fn get_bounds(&self) -> Option<&[GenericBound]> { - match self.kind { - GenericParamDefKind::Type { ref bounds, .. } => Some(bounds), - _ => None, - } - } -} - impl Clean for ty::GenericParamDef { fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef { let (name, kind) = match self.kind { @@ -1614,13 +794,6 @@ impl Clean for hir::GenericParam { } } -// maybe use a Generic enum and use Vec? -#[derive(Clone, Debug, Default)] -pub struct Generics { - pub params: Vec, - pub where_predicates: Vec, -} - impl Clean for hir::Generics { fn clean(&self, cx: &DocContext<'_>) -> Generics { // Synthetic type-parameters are inserted after normal ones. @@ -1975,16 +1148,6 @@ pub fn get_all_types( (all_types.into_iter().collect(), ret_types) } -#[derive(Clone, Debug)] -pub struct Method { - pub generics: Generics, - pub decl: FnDecl, - pub header: hir::FnHeader, - pub defaultness: Option, - pub all_types: Vec, - pub ret_types: Vec, -} - impl<'a> Clean for (&'a hir::FnSig, &'a hir::Generics, hir::BodyId, Option) { fn clean(&self, cx: &DocContext<'_>) -> Method { @@ -2003,24 +1166,6 @@ impl<'a> Clean for (&'a hir::FnSig, &'a hir::Generics, hir::BodyId, } } -#[derive(Clone, Debug)] -pub struct TyMethod { - pub header: hir::FnHeader, - pub decl: FnDecl, - pub generics: Generics, - pub all_types: Vec, - pub ret_types: Vec, -} - -#[derive(Clone, Debug)] -pub struct Function { - pub decl: FnDecl, - pub generics: Generics, - pub header: hir::FnHeader, - pub all_types: Vec, - pub ret_types: Vec, -} - impl Clean for doctree::Function<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let (generics, decl) = enter_impl_trait(cx, || { @@ -2053,49 +1198,6 @@ impl Clean for doctree::Function<'_> { } } -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct FnDecl { - pub inputs: Arguments, - pub output: FunctionRetTy, - pub c_variadic: bool, - pub attrs: Attributes, -} - -impl FnDecl { - pub fn self_type(&self) -> Option { - self.inputs.values.get(0).and_then(|v| v.to_self()) - } - - /// Returns the sugared return type for an async function. - /// - /// For example, if the return type is `impl std::future::Future`, this function - /// will return `i32`. - /// - /// # Panics - /// - /// This function will panic if the return type does not match the expected sugaring for async - /// functions. - pub fn sugared_async_return_type(&self) -> FunctionRetTy { - match &self.output { - FunctionRetTy::Return(Type::ImplTrait(bounds)) => { - match &bounds[0] { - GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => { - let bindings = trait_.bindings().unwrap(); - FunctionRetTy::Return(bindings[0].ty().clone()) - } - _ => panic!("unexpected desugaring of async function"), - } - } - _ => panic!("unexpected desugaring of async function"), - } - } -} - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct Arguments { - pub values: Vec, -} - impl<'a> Clean for (&'a [hir::Ty], &'a [ast::Ident]) { fn clean(&self, cx: &DocContext<'_>) -> Arguments { Arguments { @@ -2167,42 +1269,6 @@ impl<'tcx> Clean for (DefId, ty::PolyFnSig<'tcx>) { } } -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct Argument { - pub type_: Type, - pub name: String, -} - -#[derive(Clone, PartialEq, Debug)] -pub enum SelfTy { - SelfValue, - SelfBorrowed(Option, Mutability), - SelfExplicit(Type), -} - -impl Argument { - pub fn to_self(&self) -> Option { - if self.name != "self" { - return None; - } - if self.type_.is_self_type() { - return Some(SelfValue); - } - match self.type_ { - BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => { - Some(SelfBorrowed(lifetime.clone(), mutability)) - } - _ => Some(SelfExplicit(self.type_.clone())) - } - } -} - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum FunctionRetTy { - Return(Type), - DefaultReturn, -} - impl Clean for hir::FunctionRetTy { fn clean(&self, cx: &DocContext<'_>) -> FunctionRetTy { match *self { @@ -2212,26 +1278,6 @@ impl Clean for hir::FunctionRetTy { } } -impl GetDefId for FunctionRetTy { - fn def_id(&self) -> Option { - match *self { - Return(ref ty) => ty.def_id(), - DefaultReturn => None, - } - } -} - -#[derive(Clone, Debug)] -pub struct Trait { - pub auto: bool, - pub unsafety: hir::Unsafety, - pub items: Vec, - pub generics: Generics, - pub bounds: Vec, - pub is_spotlight: bool, - pub is_auto: bool, -} - impl Clean for doctree::Trait<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let attrs = self.attrs.clean(cx); @@ -2257,12 +1303,6 @@ impl Clean for doctree::Trait<'_> { } } -#[derive(Clone, Debug)] -pub struct TraitAlias { - pub generics: Generics, - pub bounds: Vec, -} - impl Clean for doctree::TraitAlias<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let attrs = self.attrs.clean(cx); @@ -2541,321 +1581,6 @@ impl Clean for ty::AssocItem { } } -/// A trait reference, which may have higher ranked lifetimes. -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct PolyTrait { - pub trait_: Type, - pub generic_params: Vec, -} - -/// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original -/// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most -/// importantly, it does not preserve mutability or boxes. -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum Type { - /// Structs/enums/traits (most that would be an `hir::TyKind::Path`). - ResolvedPath { - path: Path, - param_names: Option>, - did: DefId, - /// `true` if is a `T::Name` path for associated types. - is_generic: bool, - }, - /// For parameterized types, so the consumer of the JSON don't go - /// looking for types which don't exist anywhere. - Generic(String), - /// Primitives are the fixed-size numeric types (plus int/usize/float), char, - /// arrays, slices, and tuples. - Primitive(PrimitiveType), - /// `extern "ABI" fn` - BareFunction(Box), - Tuple(Vec), - Slice(Box), - Array(Box, String), - Never, - RawPointer(Mutability, Box), - BorrowedRef { - lifetime: Option, - mutability: Mutability, - type_: Box, - }, - - // `::Name` - QPath { - name: String, - self_type: Box, - trait_: Box - }, - - // `_` - Infer, - - // `impl TraitA + TraitB + ...` - ImplTrait(Vec), -} - -#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)] -pub enum PrimitiveType { - Isize, I8, I16, I32, I64, I128, - Usize, U8, U16, U32, U64, U128, - F32, F64, - Char, - Bool, - Str, - Slice, - Array, - Tuple, - Unit, - RawPointer, - Reference, - Fn, - Never, -} - -#[derive(Clone, Copy, Debug)] -pub enum TypeKind { - Enum, - Function, - Module, - Const, - Static, - Struct, - Union, - Trait, - Typedef, - Foreign, - Macro, - Attr, - Derive, - TraitAlias, -} - -pub trait GetDefId { - fn def_id(&self) -> Option; -} - -impl GetDefId for Option { - fn def_id(&self) -> Option { - self.as_ref().and_then(|d| d.def_id()) - } -} - -impl Type { - pub fn primitive_type(&self) -> Option { - match *self { - Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p), - Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice), - Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array), - Tuple(ref tys) => if tys.is_empty() { - Some(PrimitiveType::Unit) - } else { - Some(PrimitiveType::Tuple) - }, - RawPointer(..) => Some(PrimitiveType::RawPointer), - BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference), - BareFunction(..) => Some(PrimitiveType::Fn), - Never => Some(PrimitiveType::Never), - _ => None, - } - } - - pub fn is_generic(&self) -> bool { - match *self { - ResolvedPath { is_generic, .. } => is_generic, - _ => false, - } - } - - pub fn is_self_type(&self) -> bool { - match *self { - Generic(ref name) => name == "Self", - _ => false - } - } - - pub fn generics(&self) -> Option> { - match *self { - ResolvedPath { ref path, .. } => { - path.segments.last().and_then(|seg| { - if let GenericArgs::AngleBracketed { ref args, .. } = seg.args { - Some(args.iter().filter_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty.clone()), - _ => None, - }).collect()) - } else { - None - } - }) - } - _ => None, - } - } - - pub fn bindings(&self) -> Option<&[TypeBinding]> { - match *self { - ResolvedPath { ref path, .. } => { - path.segments.last().and_then(|seg| { - if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args { - Some(&**bindings) - } else { - None - } - }) - } - _ => None - } - } - - pub fn is_full_generic(&self) -> bool { - match *self { - Type::Generic(_) => true, - _ => false, - } - } - - pub fn projection(&self) -> Option<(&Type, DefId, &str)> { - let (self_, trait_, name) = match self { - QPath { ref self_type, ref trait_, ref name } => { - (self_type, trait_, name) - } - _ => return None, - }; - let trait_did = match **trait_ { - ResolvedPath { did, .. } => did, - _ => return None, - }; - Some((&self_, trait_did, name)) - } - -} - -impl GetDefId for Type { - fn def_id(&self) -> Option { - match *self { - ResolvedPath { did, .. } => Some(did), - Primitive(p) => crate::html::render::cache().primitive_locations.get(&p).cloned(), - BorrowedRef { type_: box Generic(..), .. } => - Primitive(PrimitiveType::Reference).def_id(), - BorrowedRef { ref type_, .. } => type_.def_id(), - Tuple(ref tys) => if tys.is_empty() { - Primitive(PrimitiveType::Unit).def_id() - } else { - Primitive(PrimitiveType::Tuple).def_id() - }, - BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(), - Never => Primitive(PrimitiveType::Never).def_id(), - Slice(..) => Primitive(PrimitiveType::Slice).def_id(), - Array(..) => Primitive(PrimitiveType::Array).def_id(), - RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(), - QPath { ref self_type, .. } => self_type.def_id(), - _ => None, - } - } -} - -impl PrimitiveType { - fn from_str(s: &str) -> Option { - match s { - "isize" => Some(PrimitiveType::Isize), - "i8" => Some(PrimitiveType::I8), - "i16" => Some(PrimitiveType::I16), - "i32" => Some(PrimitiveType::I32), - "i64" => Some(PrimitiveType::I64), - "i128" => Some(PrimitiveType::I128), - "usize" => Some(PrimitiveType::Usize), - "u8" => Some(PrimitiveType::U8), - "u16" => Some(PrimitiveType::U16), - "u32" => Some(PrimitiveType::U32), - "u64" => Some(PrimitiveType::U64), - "u128" => Some(PrimitiveType::U128), - "bool" => Some(PrimitiveType::Bool), - "char" => Some(PrimitiveType::Char), - "str" => Some(PrimitiveType::Str), - "f32" => Some(PrimitiveType::F32), - "f64" => Some(PrimitiveType::F64), - "array" => Some(PrimitiveType::Array), - "slice" => Some(PrimitiveType::Slice), - "tuple" => Some(PrimitiveType::Tuple), - "unit" => Some(PrimitiveType::Unit), - "pointer" => Some(PrimitiveType::RawPointer), - "reference" => Some(PrimitiveType::Reference), - "fn" => Some(PrimitiveType::Fn), - "never" => Some(PrimitiveType::Never), - _ => None, - } - } - - pub fn as_str(&self) -> &'static str { - use self::PrimitiveType::*; - match *self { - Isize => "isize", - I8 => "i8", - I16 => "i16", - I32 => "i32", - I64 => "i64", - I128 => "i128", - Usize => "usize", - U8 => "u8", - U16 => "u16", - U32 => "u32", - U64 => "u64", - U128 => "u128", - F32 => "f32", - F64 => "f64", - Str => "str", - Bool => "bool", - Char => "char", - Array => "array", - Slice => "slice", - Tuple => "tuple", - Unit => "unit", - RawPointer => "pointer", - Reference => "reference", - Fn => "fn", - Never => "never", - } - } - - pub fn to_url_str(&self) -> &'static str { - self.as_str() - } -} - -impl From for PrimitiveType { - fn from(int_ty: ast::IntTy) -> PrimitiveType { - match int_ty { - ast::IntTy::Isize => PrimitiveType::Isize, - ast::IntTy::I8 => PrimitiveType::I8, - ast::IntTy::I16 => PrimitiveType::I16, - ast::IntTy::I32 => PrimitiveType::I32, - ast::IntTy::I64 => PrimitiveType::I64, - ast::IntTy::I128 => PrimitiveType::I128, - } - } -} - -impl From for PrimitiveType { - fn from(uint_ty: ast::UintTy) -> PrimitiveType { - match uint_ty { - ast::UintTy::Usize => PrimitiveType::Usize, - ast::UintTy::U8 => PrimitiveType::U8, - ast::UintTy::U16 => PrimitiveType::U16, - ast::UintTy::U32 => PrimitiveType::U32, - ast::UintTy::U64 => PrimitiveType::U64, - ast::UintTy::U128 => PrimitiveType::U128, - } - } -} - -impl From for PrimitiveType { - fn from(float_ty: ast::FloatTy) -> PrimitiveType { - match float_ty { - ast::FloatTy::F32 => PrimitiveType::F32, - ast::FloatTy::F64 => PrimitiveType::F64, - } - } -} - impl Clean for hir::Ty { fn clean(&self, cx: &DocContext<'_>) -> Type { use rustc::hir::*; @@ -3310,14 +2035,6 @@ impl Clean for ty::FieldDef { } } -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum Visibility { - Public, - Inherited, - Crate, - Restricted(DefId, Path), -} - impl Clean for hir::Visibility { fn clean(&self, cx: &DocContext<'_>) -> Visibility { match self.node { @@ -3339,22 +2056,6 @@ impl Clean for ty::Visibility { } } -#[derive(Clone, Debug)] -pub struct Struct { - pub struct_type: doctree::StructType, - pub generics: Generics, - pub fields: Vec, - pub fields_stripped: bool, -} - -#[derive(Clone, Debug)] -pub struct Union { - pub struct_type: doctree::StructType, - pub generics: Generics, - pub fields: Vec, - pub fields_stripped: bool, -} - impl Clean for doctree::Struct<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { Item { @@ -3395,16 +2096,6 @@ impl Clean for doctree::Union<'_> { } } -/// This is a more limited form of the standard Struct, different in that -/// it lacks the things most items have (name, id, parameterization). Found -/// only as a variant in an enum. -#[derive(Clone, Debug)] -pub struct VariantStruct { - pub struct_type: doctree::StructType, - pub fields: Vec, - pub fields_stripped: bool, -} - impl Clean for ::rustc::hir::VariantData { fn clean(&self, cx: &DocContext<'_>) -> VariantStruct { VariantStruct { @@ -3415,13 +2106,6 @@ impl Clean for ::rustc::hir::VariantData { } } -#[derive(Clone, Debug)] -pub struct Enum { - pub variants: IndexVec, - pub generics: Generics, - pub variants_stripped: bool, -} - impl Clean for doctree::Enum<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { Item { @@ -3441,11 +2125,6 @@ impl Clean for doctree::Enum<'_> { } } -#[derive(Clone, Debug)] -pub struct Variant { - pub kind: VariantKind, -} - impl Clean for doctree::Variant<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { Item { @@ -3504,13 +2183,6 @@ impl Clean for ty::VariantDef { } } -#[derive(Clone, Debug)] -pub enum VariantKind { - CLike, - Tuple(Vec), - Struct(VariantStruct), -} - impl Clean for hir::VariantData { fn clean(&self, cx: &DocContext<'_>) -> VariantKind { match self { @@ -3522,31 +2194,6 @@ impl Clean for hir::VariantData { } } -#[derive(Clone, Debug)] -pub struct Span { - pub filename: FileName, - pub loline: usize, - pub locol: usize, - pub hiline: usize, - pub hicol: usize, - pub original: syntax_pos::Span, -} - -impl Span { - pub fn empty() -> Span { - Span { - filename: FileName::Anon(0), - loline: 0, locol: 0, - hiline: 0, hicol: 0, - original: syntax_pos::DUMMY_SP, - } - } - - pub fn span(&self) -> syntax_pos::Span { - self.original - } -} - impl Clean for syntax_pos::Span { fn clean(&self, cx: &DocContext<'_>) -> Span { if self.is_dummy() { @@ -3568,19 +2215,6 @@ impl Clean for syntax_pos::Span { } } -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct Path { - pub global: bool, - pub res: Res, - pub segments: Vec, -} - -impl Path { - pub fn last_name(&self) -> &str { - self.segments.last().expect("segments were empty").name.as_str() - } -} - impl Clean for hir::Path { fn clean(&self, cx: &DocContext<'_>) -> Path { Path { @@ -3591,25 +2225,6 @@ impl Clean for hir::Path { } } -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum GenericArg { - Lifetime(Lifetime), - Type(Type), - Const(Constant), -} - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum GenericArgs { - AngleBracketed { - args: Vec, - bindings: Vec, - }, - Parenthesized { - inputs: Vec, - output: Option, - } -} - impl Clean for hir::GenericArgs { fn clean(&self, cx: &DocContext<'_>) -> GenericArgs { if self.parenthesized { @@ -3638,12 +2253,6 @@ impl Clean for hir::GenericArgs { } } -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct PathSegment { - pub name: String, - pub args: GenericArgs, -} - impl Clean for hir::PathSegment { fn clean(&self, cx: &DocContext<'_>) -> PathSegment { PathSegment { @@ -3727,12 +2336,6 @@ impl Clean for ast::Name { } } -#[derive(Clone, Debug)] -pub struct Typedef { - pub type_: Type, - pub generics: Generics, -} - impl Clean for doctree::Typedef<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { Item { @@ -3751,12 +2354,6 @@ impl Clean for doctree::Typedef<'_> { } } -#[derive(Clone, Debug)] -pub struct OpaqueTy { - pub bounds: Vec, - pub generics: Generics, -} - impl Clean for doctree::OpaqueTy<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { Item { @@ -3775,14 +2372,6 @@ impl Clean for doctree::OpaqueTy<'_> { } } -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct BareFunctionDecl { - pub unsafety: hir::Unsafety, - pub generic_params: Vec, - pub decl: FnDecl, - pub abi: Abi, -} - impl Clean for hir::BareFnTy { fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl { let (generic_params, decl) = enter_impl_trait(cx, || { @@ -3797,16 +2386,6 @@ impl Clean for hir::BareFnTy { } } -#[derive(Clone, Debug)] -pub struct Static { - pub type_: Type, - pub mutability: Mutability, - /// It's useful to have the value of a static documented, but I have no - /// desire to represent expressions (that'd basically be all of the AST, - /// which is huge!). So, have a string. - pub expr: String, -} - impl Clean for doctree::Static<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { debug!("cleaning static {}: {:?}", self.name.clean(cx), self); @@ -3827,12 +2406,6 @@ impl Clean for doctree::Static<'_> { } } -#[derive(Clone, PartialEq, Eq, Hash, Debug)] -pub struct Constant { - pub type_: Type, - pub expr: String, -} - impl Clean for doctree::Constant<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { Item { @@ -3851,12 +2424,6 @@ impl Clean for doctree::Constant<'_> { } } -#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)] -pub enum Mutability { - Mutable, - Immutable, -} - impl Clean for hir::Mutability { fn clean(&self, _: &DocContext<'_>) -> Mutability { match self { @@ -3866,12 +2433,6 @@ impl Clean for hir::Mutability { } } -#[derive(Clone, PartialEq, Debug)] -pub enum ImplPolarity { - Positive, - Negative, -} - impl Clean for ty::ImplPolarity { fn clean(&self, _: &DocContext<'_>) -> ImplPolarity { match self { @@ -3883,19 +2444,6 @@ impl Clean for ty::ImplPolarity { } } -#[derive(Clone, Debug)] -pub struct Impl { - pub unsafety: hir::Unsafety, - pub generics: Generics, - pub provided_trait_methods: FxHashSet, - pub trait_: Option, - pub for_: Type, - pub items: Vec, - pub polarity: Option, - pub synthetic: bool, - pub blanket_impl: Option, -} - pub fn get_auto_trait_and_blanket_impls( cx: &DocContext<'tcx>, ty: Ty<'tcx>, @@ -4115,20 +2663,6 @@ impl Clean> for doctree::Import<'_> { } } -#[derive(Clone, Debug)] -pub enum Import { - // use source as str; - Simple(String, ImportSource), - // use source::*; - Glob(ImportSource) -} - -#[derive(Clone, Debug)] -pub struct ImportSource { - pub path: Path, - pub did: Option, -} - impl Clean for doctree::ForeignItem<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let inner = match self.kind { @@ -4340,12 +2874,6 @@ fn resolve_use_source(cx: &DocContext<'_>, path: Path) -> ImportSource { } } -#[derive(Clone, Debug)] -pub struct Macro { - pub source: String, - pub imported_from: Option, -} - impl Clean for doctree::Macro<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let name = self.name.clean(cx); @@ -4369,12 +2897,6 @@ impl Clean for doctree::Macro<'_> { } } -#[derive(Clone, Debug)] -pub struct ProcMacro { - pub kind: MacroKind, - pub helpers: Vec, -} - impl Clean for doctree::ProcMacro<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { Item { @@ -4393,22 +2915,6 @@ impl Clean for doctree::ProcMacro<'_> { } } -#[derive(Clone, Debug)] -pub struct Stability { - pub level: stability::StabilityLevel, - pub feature: Option, - pub since: String, - pub deprecation: Option, - pub unstable_reason: Option, - pub issue: Option, -} - -#[derive(Clone, Debug)] -pub struct Deprecation { - pub since: Option, - pub note: Option, -} - impl Clean for attr::Stability { fn clean(&self, _: &DocContext<'_>) -> Stability { Stability { @@ -4451,33 +2957,6 @@ impl Clean for attr::Deprecation { } } -/// An type binding on an associated type (e.g., `A = Bar` in `Foo` or -/// `A: Send + Sync` in `Foo`). -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct TypeBinding { - pub name: String, - pub kind: TypeBindingKind, -} - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum TypeBindingKind { - Equality { - ty: Type, - }, - Constraint { - bounds: Vec, - }, -} - -impl TypeBinding { - pub fn ty(&self) -> &Type { - match self.kind { - TypeBindingKind::Equality { ref ty } => ty, - _ => panic!("expected equality type binding for parenthesized generic args"), - } - } -} - impl Clean for hir::TypeBinding { fn clean(&self, cx: &DocContext<'_>) -> TypeBinding { TypeBinding { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs new file mode 100644 index 0000000000000..bd3f2a3690a27 --- /dev/null +++ b/src/librustdoc/clean/types.rs @@ -0,0 +1,1545 @@ +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::default::Default; +use std::{slice, vec}; +use std::num::NonZeroU32; +use std::iter::FromIterator; +use std::rc::Rc; +use std::cell::RefCell; +use std::sync::Arc; + +use rustc::middle::lang_items; +use rustc::middle::stability; +use rustc::hir; +use rustc::hir::def::Res; +use rustc::hir::def_id::{CrateNum, DefId}; +use rustc::ty::layout::VariantIdx; +use rustc::util::nodemap::{FxHashMap, FxHashSet}; +use rustc_index::vec::IndexVec; +use rustc_target::spec::abi::Abi; +use syntax::ast::{self, Attribute, AttrStyle, AttrKind, Ident}; +use syntax::attr; +use syntax::util::comments; +use syntax::source_map::DUMMY_SP; +use syntax_pos::hygiene::MacroKind; +use syntax_pos::symbol::{Symbol, sym}; +use syntax_pos::{self, FileName}; + +use crate::core::DocContext; +use crate::clean::cfg::Cfg; +use crate::clean::inline; +use crate::clean::external_path; +use crate::clean::types::Type::{QPath, ResolvedPath}; +use crate::doctree; +use crate::html::item_type::ItemType; +use crate::html::render::{cache, ExternalLocation}; + +use self::Type::*; +use self::ItemEnum::*; +use self::SelfTy::*; +use self::FunctionRetTy::*; + +thread_local!(pub static MAX_DEF_ID: RefCell> = Default::default()); + +#[derive(Clone, Debug)] +pub struct Crate { + pub name: String, + pub version: Option, + pub src: FileName, + pub module: Option, + pub externs: Vec<(CrateNum, ExternalCrate)>, + pub primitives: Vec<(DefId, PrimitiveType, Attributes)>, + // These are later on moved into `CACHEKEY`, leaving the map empty. + // Only here so that they can be filtered through the rustdoc passes. + pub external_traits: Rc>>, + pub masked_crates: FxHashSet, + pub collapsed: bool, +} + +#[derive(Clone, Debug)] +pub struct ExternalCrate { + pub name: String, + pub src: FileName, + pub attrs: Attributes, + pub primitives: Vec<(DefId, PrimitiveType, Attributes)>, + pub keywords: Vec<(DefId, String, Attributes)>, +} + +/// Anything with a source location and set of attributes and, optionally, a +/// name. That is, anything that can be documented. This doesn't correspond +/// directly to the AST's concept of an item; it's a strict superset. +#[derive(Clone)] +pub struct Item { + /// Stringified span + pub source: Span, + /// Not everything has a name. E.g., impls + pub name: Option, + pub attrs: Attributes, + pub inner: ItemEnum, + pub visibility: Visibility, + pub def_id: DefId, + pub stability: Option, + pub deprecation: Option, +} + +impl fmt::Debug for Item { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let fake = MAX_DEF_ID.with(|m| m.borrow().get(&self.def_id.krate) + .map(|id| self.def_id >= *id).unwrap_or(false)); + let def_id: &dyn fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id }; + + fmt.debug_struct("Item") + .field("source", &self.source) + .field("name", &self.name) + .field("attrs", &self.attrs) + .field("inner", &self.inner) + .field("visibility", &self.visibility) + .field("def_id", def_id) + .field("stability", &self.stability) + .field("deprecation", &self.deprecation) + .finish() + } +} + +impl Item { + /// Finds the `doc` attribute as a NameValue and returns the corresponding + /// value found. + pub fn doc_value(&self) -> Option<&str> { + self.attrs.doc_value() + } + + /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined + /// with newlines. + pub fn collapsed_doc_value(&self) -> Option { + self.attrs.collapsed_doc_value() + } + + pub fn links(&self) -> Vec<(String, String)> { + self.attrs.links(&self.def_id.krate) + } + + pub fn is_crate(&self) -> bool { + match self.inner { + StrippedItem(box ModuleItem(Module { is_crate: true, ..})) | + ModuleItem(Module { is_crate: true, ..}) => true, + _ => false, + } + } + pub fn is_mod(&self) -> bool { + self.type_() == ItemType::Module + } + pub fn is_trait(&self) -> bool { + self.type_() == ItemType::Trait + } + pub fn is_struct(&self) -> bool { + self.type_() == ItemType::Struct + } + pub fn is_enum(&self) -> bool { + self.type_() == ItemType::Enum + } + pub fn is_variant(&self) -> bool { + self.type_() == ItemType::Variant + } + pub fn is_associated_type(&self) -> bool { + self.type_() == ItemType::AssocType + } + pub fn is_associated_const(&self) -> bool { + self.type_() == ItemType::AssocConst + } + pub fn is_method(&self) -> bool { + self.type_() == ItemType::Method + } + pub fn is_ty_method(&self) -> bool { + self.type_() == ItemType::TyMethod + } + pub fn is_typedef(&self) -> bool { + self.type_() == ItemType::Typedef + } + pub fn is_primitive(&self) -> bool { + self.type_() == ItemType::Primitive + } + pub fn is_union(&self) -> bool { + self.type_() == ItemType::Union + } + pub fn is_import(&self) -> bool { + self.type_() == ItemType::Import + } + pub fn is_extern_crate(&self) -> bool { + self.type_() == ItemType::ExternCrate + } + pub fn is_keyword(&self) -> bool { + self.type_() == ItemType::Keyword + } + pub fn is_stripped(&self) -> bool { + match self.inner { StrippedItem(..) => true, _ => false } + } + pub fn has_stripped_fields(&self) -> Option { + match self.inner { + StructItem(ref _struct) => Some(_struct.fields_stripped), + UnionItem(ref union) => Some(union.fields_stripped), + VariantItem(Variant { kind: VariantKind::Struct(ref vstruct)} ) => { + Some(vstruct.fields_stripped) + }, + _ => None, + } + } + + pub fn stability_class(&self) -> Option { + self.stability.as_ref().and_then(|ref s| { + let mut classes = Vec::with_capacity(2); + + if s.level == stability::Unstable { + classes.push("unstable"); + } + + if s.deprecation.is_some() { + classes.push("deprecated"); + } + + if classes.len() != 0 { + Some(classes.join(" ")) + } else { + None + } + }) + } + + pub fn stable_since(&self) -> Option<&str> { + self.stability.as_ref().map(|s| &s.since[..]) + } + + pub fn is_non_exhaustive(&self) -> bool { + self.attrs.other_attrs.iter() + .any(|a| a.check_name(sym::non_exhaustive)) + } + + /// Returns a documentation-level item type from the item. + pub fn type_(&self) -> ItemType { + ItemType::from(self) + } + + /// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes. + /// + /// If the item is not deprecated, returns `None`. + pub fn deprecation(&self) -> Option<&Deprecation> { + self.deprecation + .as_ref() + .or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref())) + } + pub fn is_default(&self) -> bool { + match self.inner { + ItemEnum::MethodItem(ref meth) => { + if let Some(defaultness) = meth.defaultness { + defaultness.has_value() && !defaultness.is_final() + } else { + false + } + } + _ => false, + } + } +} + +#[derive(Clone, Debug)] +pub enum ItemEnum { + ExternCrateItem(String, Option), + ImportItem(Import), + StructItem(Struct), + UnionItem(Union), + EnumItem(Enum), + FunctionItem(Function), + ModuleItem(Module), + TypedefItem(Typedef, bool /* is associated type */), + OpaqueTyItem(OpaqueTy, bool /* is associated type */), + StaticItem(Static), + ConstantItem(Constant), + TraitItem(Trait), + TraitAliasItem(TraitAlias), + ImplItem(Impl), + /// A method signature only. Used for required methods in traits (ie, + /// non-default-methods). + TyMethodItem(TyMethod), + /// A method with a body. + MethodItem(Method), + StructFieldItem(Type), + VariantItem(Variant), + /// `fn`s from an extern block + ForeignFunctionItem(Function), + /// `static`s from an extern block + ForeignStaticItem(Static), + /// `type`s from an extern block + ForeignTypeItem, + MacroItem(Macro), + ProcMacroItem(ProcMacro), + PrimitiveItem(PrimitiveType), + AssocConstItem(Type, Option), + AssocTypeItem(Vec, Option), + /// An item that has been stripped by a rustdoc pass + StrippedItem(Box), + KeywordItem(String), +} + +impl ItemEnum { + pub fn is_associated(&self) -> bool { + match *self { + ItemEnum::TypedefItem(_, _) | + ItemEnum::AssocTypeItem(_, _) => true, + _ => false, + } + } +} + +#[derive(Clone, Debug)] +pub struct Module { + pub items: Vec, + pub is_crate: bool, +} + +pub struct ListAttributesIter<'a> { + attrs: slice::Iter<'a, ast::Attribute>, + current_list: vec::IntoIter, + name: Symbol, +} + +impl<'a> Iterator for ListAttributesIter<'a> { + type Item = ast::NestedMetaItem; + + fn next(&mut self) -> Option { + if let Some(nested) = self.current_list.next() { + return Some(nested); + } + + for attr in &mut self.attrs { + if let Some(list) = attr.meta_item_list() { + if attr.check_name(self.name) { + self.current_list = list.into_iter(); + if let Some(nested) = self.current_list.next() { + return Some(nested); + } + } + } + } + + None + } + + fn size_hint(&self) -> (usize, Option) { + let lower = self.current_list.len(); + (lower, None) + } +} + +pub trait AttributesExt { + /// Finds an attribute as List and returns the list of attributes nested inside. + fn lists(&self, name: Symbol) -> ListAttributesIter<'_>; +} + +impl AttributesExt for [ast::Attribute] { + fn lists(&self, name: Symbol) -> ListAttributesIter<'_> { + ListAttributesIter { + attrs: self.iter(), + current_list: Vec::new().into_iter(), + name, + } + } +} + +pub trait NestedAttributesExt { + /// Returns `true` if the attribute list contains a specific `Word` + fn has_word(self, word: Symbol) -> bool; +} + +impl> NestedAttributesExt for I { + fn has_word(self, word: Symbol) -> bool { + self.into_iter().any(|attr| attr.is_word() && attr.check_name(word)) + } +} + +/// A portion of documentation, extracted from a `#[doc]` attribute. +/// +/// Each variant contains the line number within the complete doc-comment where the fragment +/// starts, as well as the Span where the corresponding doc comment or attribute is located. +/// +/// Included files are kept separate from inline doc comments so that proper line-number +/// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are +/// kept separate because of issue #42760. +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum DocFragment { + /// A doc fragment created from a `///` or `//!` doc comment. + SugaredDoc(usize, syntax_pos::Span, String), + /// A doc fragment created from a "raw" `#[doc=""]` attribute. + RawDoc(usize, syntax_pos::Span, String), + /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the + /// given filename and the file contents. + Include(usize, syntax_pos::Span, String, String), +} + +impl DocFragment { + pub fn as_str(&self) -> &str { + match *self { + DocFragment::SugaredDoc(_, _, ref s) => &s[..], + DocFragment::RawDoc(_, _, ref s) => &s[..], + DocFragment::Include(_, _, _, ref s) => &s[..], + } + } + + pub fn span(&self) -> syntax_pos::Span { + match *self { + DocFragment::SugaredDoc(_, span, _) | + DocFragment::RawDoc(_, span, _) | + DocFragment::Include(_, span, _, _) => span, + } + } +} + +impl<'a> FromIterator<&'a DocFragment> for String { + fn from_iter(iter: T) -> Self + where + T: IntoIterator + { + iter.into_iter().fold(String::new(), |mut acc, frag| { + if !acc.is_empty() { + acc.push('\n'); + } + match *frag { + DocFragment::SugaredDoc(_, _, ref docs) + | DocFragment::RawDoc(_, _, ref docs) + | DocFragment::Include(_, _, _, ref docs) => + acc.push_str(docs), + } + + acc + }) + } +} + +#[derive(Clone, Debug, Default)] +pub struct Attributes { + pub doc_strings: Vec, + pub other_attrs: Vec, + pub cfg: Option>, + pub span: Option, + /// map from Rust paths to resolved defs and potential URL fragments + pub links: Vec<(String, Option, Option)>, + pub inner_docs: bool, +} + +impl Attributes { + /// Extracts the content from an attribute `#[doc(cfg(content))]`. + pub fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> { + use syntax::ast::NestedMetaItem::MetaItem; + + if let ast::MetaItemKind::List(ref nmis) = mi.kind { + if nmis.len() == 1 { + if let MetaItem(ref cfg_mi) = nmis[0] { + if cfg_mi.check_name(sym::cfg) { + if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind { + if cfg_nmis.len() == 1 { + if let MetaItem(ref content_mi) = cfg_nmis[0] { + return Some(content_mi); + } + } + } + } + } + } + } + + None + } + + /// Reads a `MetaItem` from within an attribute, looks for whether it is a + /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from + /// its expansion. + pub fn extract_include(mi: &ast::MetaItem) -> Option<(String, String)> { + mi.meta_item_list().and_then(|list| { + for meta in list { + if meta.check_name(sym::include) { + // the actual compiled `#[doc(include="filename")]` gets expanded to + // `#[doc(include(file="filename", contents="file contents")]` so we need to + // look for that instead + return meta.meta_item_list().and_then(|list| { + let mut filename: Option = None; + let mut contents: Option = None; + + for it in list { + if it.check_name(sym::file) { + if let Some(name) = it.value_str() { + filename = Some(name.to_string()); + } + } else if it.check_name(sym::contents) { + if let Some(docs) = it.value_str() { + contents = Some(docs.to_string()); + } + } + } + + if let (Some(filename), Some(contents)) = (filename, contents) { + Some((filename, contents)) + } else { + None + } + }); + } + } + + None + }) + } + + pub fn has_doc_flag(&self, flag: Symbol) -> bool { + for attr in &self.other_attrs { + if !attr.check_name(sym::doc) { continue; } + + if let Some(items) = attr.meta_item_list() { + if items.iter().filter_map(|i| i.meta_item()).any(|it| it.check_name(flag)) { + return true; + } + } + } + + false + } + + pub fn from_ast(diagnostic: &::errors::Handler, attrs: &[ast::Attribute]) -> Attributes { + let mut doc_strings = vec![]; + let mut sp = None; + let mut cfg = Cfg::True; + let mut doc_line = 0; + + /// If `attr` is a doc comment, strips the leading and (if present) + /// trailing comments symbols, e.g. `///`, `/**`, and `*/`. Otherwise, + /// returns `attr` unchanged. + pub fn with_doc_comment_markers_stripped( + attr: &Attribute, + f: impl FnOnce(&Attribute) -> T, + ) -> T { + match attr.kind { + AttrKind::Normal(_) => { + f(attr) + } + AttrKind::DocComment(comment) => { + let comment = + Symbol::intern(&comments::strip_doc_comment_decoration(&comment.as_str())); + f(&Attribute { + kind: AttrKind::DocComment(comment), + id: attr.id, + style: attr.style, + span: attr.span, + }) + } + } + } + + let other_attrs = attrs.iter().filter_map(|attr| { + with_doc_comment_markers_stripped(attr, |attr| { + if attr.check_name(sym::doc) { + if let Some(mi) = attr.meta() { + if let Some(value) = mi.value_str() { + // Extracted #[doc = "..."] + let value = value.to_string(); + let line = doc_line; + doc_line += value.lines().count(); + + if attr.is_doc_comment() { + doc_strings.push(DocFragment::SugaredDoc(line, attr.span, value)); + } else { + doc_strings.push(DocFragment::RawDoc(line, attr.span, value)); + } + + if sp.is_none() { + sp = Some(attr.span); + } + return None; + } else if let Some(cfg_mi) = Attributes::extract_cfg(&mi) { + // Extracted #[doc(cfg(...))] + match Cfg::parse(cfg_mi) { + Ok(new_cfg) => cfg &= new_cfg, + Err(e) => diagnostic.span_err(e.span, e.msg), + } + return None; + } else if let Some((filename, contents)) = Attributes::extract_include(&mi) + { + let line = doc_line; + doc_line += contents.lines().count(); + doc_strings.push(DocFragment::Include(line, + attr.span, + filename, + contents)); + } + } + } + Some(attr.clone()) + }) + }).collect(); + + // treat #[target_feature(enable = "feat")] attributes as if they were + // #[doc(cfg(target_feature = "feat"))] attributes as well + for attr in attrs.lists(sym::target_feature) { + if attr.check_name(sym::enable) { + if let Some(feat) = attr.value_str() { + let meta = attr::mk_name_value_item_str( + Ident::with_dummy_span(sym::target_feature), feat, DUMMY_SP + ); + if let Ok(feat_cfg) = Cfg::parse(&meta) { + cfg &= feat_cfg; + } + } + } + } + + let inner_docs = attrs.iter() + .filter(|a| a.check_name(sym::doc)) + .next() + .map_or(true, |a| a.style == AttrStyle::Inner); + + Attributes { + doc_strings, + other_attrs, + cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }, + span: sp, + links: vec![], + inner_docs, + } + } + + /// Finds the `doc` attribute as a NameValue and returns the corresponding + /// value found. + pub fn doc_value(&self) -> Option<&str> { + self.doc_strings.first().map(|s| s.as_str()) + } + + /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined + /// with newlines. + pub fn collapsed_doc_value(&self) -> Option { + if !self.doc_strings.is_empty() { + Some(self.doc_strings.iter().collect()) + } else { + None + } + } + + /// Gets links as a vector + /// + /// Cache must be populated before call + pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> { + use crate::html::format::href; + + self.links.iter().filter_map(|&(ref s, did, ref fragment)| { + match did { + Some(did) => { + if let Some((mut href, ..)) = href(did) { + if let Some(ref fragment) = *fragment { + href.push_str("#"); + href.push_str(fragment); + } + Some((s.clone(), href)) + } else { + None + } + } + None => { + if let Some(ref fragment) = *fragment { + let cache = cache(); + let url = match cache.extern_locations.get(krate) { + Some(&(_, ref src, ExternalLocation::Local)) => + src.to_str().expect("invalid file path"), + Some(&(_, _, ExternalLocation::Remote(ref s))) => s, + Some(&(_, _, ExternalLocation::Unknown)) | None => + "https://doc.rust-lang.org/nightly", + }; + // This is a primitive so the url is done "by hand". + let tail = fragment.find('#').unwrap_or_else(|| fragment.len()); + Some((s.clone(), + format!("{}{}std/primitive.{}.html{}", + url, + if !url.ends_with('/') { "/" } else { "" }, + &fragment[..tail], + &fragment[tail..]))) + } else { + panic!("This isn't a primitive?!"); + } + } + } + }).collect() + } +} + +impl PartialEq for Attributes { + fn eq(&self, rhs: &Self) -> bool { + self.doc_strings == rhs.doc_strings && + self.cfg == rhs.cfg && + self.span == rhs.span && + self.links == rhs.links && + self.other_attrs.iter().map(|attr| attr.id).eq(rhs.other_attrs.iter().map(|attr| attr.id)) + } +} + +impl Eq for Attributes {} + +impl Hash for Attributes { + fn hash(&self, hasher: &mut H) { + self.doc_strings.hash(hasher); + self.cfg.hash(hasher); + self.span.hash(hasher); + self.links.hash(hasher); + for attr in &self.other_attrs { + attr.id.hash(hasher); + } + } +} + +impl AttributesExt for Attributes { + fn lists(&self, name: Symbol) -> ListAttributesIter<'_> { + self.other_attrs.lists(name) + } +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum GenericBound { + TraitBound(PolyTrait, hir::TraitBoundModifier), + Outlives(Lifetime), +} + +impl GenericBound { + pub fn maybe_sized(cx: &DocContext<'_>) -> GenericBound { + let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); + let empty = cx.tcx.intern_substs(&[]); + let path = external_path(cx, cx.tcx.item_name(did), + Some(did), false, vec![], empty); + inline::record_extern_fqn(cx, did, TypeKind::Trait); + GenericBound::TraitBound(PolyTrait { + trait_: ResolvedPath { + path, + param_names: None, + did, + is_generic: false, + }, + generic_params: Vec::new(), + }, hir::TraitBoundModifier::Maybe) + } + + pub fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool { + use rustc::hir::TraitBoundModifier as TBM; + if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self { + if trait_.def_id() == cx.tcx.lang_items().sized_trait() { + return true; + } + } + false + } + + pub fn get_poly_trait(&self) -> Option { + if let GenericBound::TraitBound(ref p, _) = *self { + return Some(p.clone()) + } + None + } + + pub fn get_trait_type(&self) -> Option { + if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self { + Some(trait_.clone()) + } else { + None + } + } +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct Lifetime(pub String); + +impl Lifetime { + pub fn get_ref<'a>(&'a self) -> &'a str { + let Lifetime(ref s) = *self; + let s: &'a str = s; + s + } + + pub fn statik() -> Lifetime { + Lifetime("'static".to_string()) + } +} + +#[derive(Clone, Debug)] +pub enum WherePredicate { + BoundPredicate { ty: Type, bounds: Vec }, + RegionPredicate { lifetime: Lifetime, bounds: Vec }, + EqPredicate { lhs: Type, rhs: Type }, +} + +impl WherePredicate { + pub fn get_bounds(&self) -> Option<&[GenericBound]> { + match *self { + WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds), + WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds), + _ => None, + } + } +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum GenericParamDefKind { + Lifetime, + Type { + did: DefId, + bounds: Vec, + default: Option, + synthetic: Option, + }, + Const { + did: DefId, + ty: Type, + }, +} + +impl GenericParamDefKind { + pub fn is_type(&self) -> bool { + match *self { + GenericParamDefKind::Type { .. } => true, + _ => false, + } + } + + // FIXME(eddyb) this either returns the default of a type parameter, or the + // type of a `const` parameter. It seems that the intention is to *visit* + // any embedded types, but `get_type` seems to be the wrong name for that. + pub fn get_type(&self) -> Option { + match self { + GenericParamDefKind::Type { default, .. } => default.clone(), + GenericParamDefKind::Const { ty, .. } => Some(ty.clone()), + GenericParamDefKind::Lifetime => None, + } + } +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct GenericParamDef { + pub name: String, + pub kind: GenericParamDefKind, +} + +impl GenericParamDef { + pub fn is_synthetic_type_param(&self) -> bool { + match self.kind { + GenericParamDefKind::Lifetime | + GenericParamDefKind::Const { .. } => false, + GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(), + } + } + + pub fn is_type(&self) -> bool { + self.kind.is_type() + } + + pub fn get_type(&self) -> Option { + self.kind.get_type() + } + + pub fn get_bounds(&self) -> Option<&[GenericBound]> { + match self.kind { + GenericParamDefKind::Type { ref bounds, .. } => Some(bounds), + _ => None, + } + } +} + +// maybe use a Generic enum and use Vec? +#[derive(Clone, Debug, Default)] +pub struct Generics { + pub params: Vec, + pub where_predicates: Vec, +} + +#[derive(Clone, Debug)] +pub struct Method { + pub generics: Generics, + pub decl: FnDecl, + pub header: hir::FnHeader, + pub defaultness: Option, + pub all_types: Vec, + pub ret_types: Vec, +} + +#[derive(Clone, Debug)] +pub struct TyMethod { + pub header: hir::FnHeader, + pub decl: FnDecl, + pub generics: Generics, + pub all_types: Vec, + pub ret_types: Vec, +} + +#[derive(Clone, Debug)] +pub struct Function { + pub decl: FnDecl, + pub generics: Generics, + pub header: hir::FnHeader, + pub all_types: Vec, + pub ret_types: Vec, +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct FnDecl { + pub inputs: Arguments, + pub output: FunctionRetTy, + pub c_variadic: bool, + pub attrs: Attributes, +} + +impl FnDecl { + pub fn self_type(&self) -> Option { + self.inputs.values.get(0).and_then(|v| v.to_self()) + } + + /// Returns the sugared return type for an async function. + /// + /// For example, if the return type is `impl std::future::Future`, this function + /// will return `i32`. + /// + /// # Panics + /// + /// This function will panic if the return type does not match the expected sugaring for async + /// functions. + pub fn sugared_async_return_type(&self) -> FunctionRetTy { + match &self.output { + FunctionRetTy::Return(Type::ImplTrait(bounds)) => { + match &bounds[0] { + GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => { + let bindings = trait_.bindings().unwrap(); + FunctionRetTy::Return(bindings[0].ty().clone()) + } + _ => panic!("unexpected desugaring of async function"), + } + } + _ => panic!("unexpected desugaring of async function"), + } + } +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct Arguments { + pub values: Vec, +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct Argument { + pub type_: Type, + pub name: String, +} + +#[derive(Clone, PartialEq, Debug)] +pub enum SelfTy { + SelfValue, + SelfBorrowed(Option, Mutability), + SelfExplicit(Type), +} + +impl Argument { + pub fn to_self(&self) -> Option { + if self.name != "self" { + return None; + } + if self.type_.is_self_type() { + return Some(SelfValue); + } + match self.type_ { + BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => { + Some(SelfBorrowed(lifetime.clone(), mutability)) + } + _ => Some(SelfExplicit(self.type_.clone())) + } + } +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum FunctionRetTy { + Return(Type), + DefaultReturn, +} + +impl GetDefId for FunctionRetTy { + fn def_id(&self) -> Option { + match *self { + Return(ref ty) => ty.def_id(), + DefaultReturn => None, + } + } +} + +#[derive(Clone, Debug)] +pub struct Trait { + pub auto: bool, + pub unsafety: hir::Unsafety, + pub items: Vec, + pub generics: Generics, + pub bounds: Vec, + pub is_spotlight: bool, + pub is_auto: bool, +} + +#[derive(Clone, Debug)] +pub struct TraitAlias { + pub generics: Generics, + pub bounds: Vec, +} + +/// A trait reference, which may have higher ranked lifetimes. +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct PolyTrait { + pub trait_: Type, + pub generic_params: Vec, +} + +/// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original +/// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most +/// importantly, it does not preserve mutability or boxes. +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum Type { + /// Structs/enums/traits (most that would be an `hir::TyKind::Path`). + ResolvedPath { + path: Path, + param_names: Option>, + did: DefId, + /// `true` if is a `T::Name` path for associated types. + is_generic: bool, + }, + /// For parameterized types, so the consumer of the JSON don't go + /// looking for types which don't exist anywhere. + Generic(String), + /// Primitives are the fixed-size numeric types (plus int/usize/float), char, + /// arrays, slices, and tuples. + Primitive(PrimitiveType), + /// `extern "ABI" fn` + BareFunction(Box), + Tuple(Vec), + Slice(Box), + Array(Box, String), + Never, + RawPointer(Mutability, Box), + BorrowedRef { + lifetime: Option, + mutability: Mutability, + type_: Box, + }, + + // `::Name` + QPath { + name: String, + self_type: Box, + trait_: Box + }, + + // `_` + Infer, + + // `impl TraitA + TraitB + ...` + ImplTrait(Vec), +} + +#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)] +pub enum PrimitiveType { + Isize, I8, I16, I32, I64, I128, + Usize, U8, U16, U32, U64, U128, + F32, F64, + Char, + Bool, + Str, + Slice, + Array, + Tuple, + Unit, + RawPointer, + Reference, + Fn, + Never, +} + +#[derive(Clone, Copy, Debug)] +pub enum TypeKind { + Enum, + Function, + Module, + Const, + Static, + Struct, + Union, + Trait, + Typedef, + Foreign, + Macro, + Attr, + Derive, + TraitAlias, +} + +pub trait GetDefId { + fn def_id(&self) -> Option; +} + +impl GetDefId for Option { + fn def_id(&self) -> Option { + self.as_ref().and_then(|d| d.def_id()) + } +} + +impl Type { + pub fn primitive_type(&self) -> Option { + match *self { + Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p), + Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice), + Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array), + Tuple(ref tys) => if tys.is_empty() { + Some(PrimitiveType::Unit) + } else { + Some(PrimitiveType::Tuple) + }, + RawPointer(..) => Some(PrimitiveType::RawPointer), + BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference), + BareFunction(..) => Some(PrimitiveType::Fn), + Never => Some(PrimitiveType::Never), + _ => None, + } + } + + pub fn is_generic(&self) -> bool { + match *self { + ResolvedPath { is_generic, .. } => is_generic, + _ => false, + } + } + + pub fn is_self_type(&self) -> bool { + match *self { + Generic(ref name) => name == "Self", + _ => false + } + } + + pub fn generics(&self) -> Option> { + match *self { + ResolvedPath { ref path, .. } => { + path.segments.last().and_then(|seg| { + if let GenericArgs::AngleBracketed { ref args, .. } = seg.args { + Some(args.iter().filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty.clone()), + _ => None, + }).collect()) + } else { + None + } + }) + } + _ => None, + } + } + + pub fn bindings(&self) -> Option<&[TypeBinding]> { + match *self { + ResolvedPath { ref path, .. } => { + path.segments.last().and_then(|seg| { + if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args { + Some(&**bindings) + } else { + None + } + }) + } + _ => None + } + } + + pub fn is_full_generic(&self) -> bool { + match *self { + Type::Generic(_) => true, + _ => false, + } + } + + pub fn projection(&self) -> Option<(&Type, DefId, &str)> { + let (self_, trait_, name) = match self { + QPath { ref self_type, ref trait_, ref name } => { + (self_type, trait_, name) + } + _ => return None, + }; + let trait_did = match **trait_ { + ResolvedPath { did, .. } => did, + _ => return None, + }; + Some((&self_, trait_did, name)) + } + +} + +impl GetDefId for Type { + fn def_id(&self) -> Option { + match *self { + ResolvedPath { did, .. } => Some(did), + Primitive(p) => crate::html::render::cache().primitive_locations.get(&p).cloned(), + BorrowedRef { type_: box Generic(..), .. } => + Primitive(PrimitiveType::Reference).def_id(), + BorrowedRef { ref type_, .. } => type_.def_id(), + Tuple(ref tys) => if tys.is_empty() { + Primitive(PrimitiveType::Unit).def_id() + } else { + Primitive(PrimitiveType::Tuple).def_id() + }, + BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(), + Never => Primitive(PrimitiveType::Never).def_id(), + Slice(..) => Primitive(PrimitiveType::Slice).def_id(), + Array(..) => Primitive(PrimitiveType::Array).def_id(), + RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(), + QPath { ref self_type, .. } => self_type.def_id(), + _ => None, + } + } +} + +impl PrimitiveType { + pub fn from_str(s: &str) -> Option { + match s { + "isize" => Some(PrimitiveType::Isize), + "i8" => Some(PrimitiveType::I8), + "i16" => Some(PrimitiveType::I16), + "i32" => Some(PrimitiveType::I32), + "i64" => Some(PrimitiveType::I64), + "i128" => Some(PrimitiveType::I128), + "usize" => Some(PrimitiveType::Usize), + "u8" => Some(PrimitiveType::U8), + "u16" => Some(PrimitiveType::U16), + "u32" => Some(PrimitiveType::U32), + "u64" => Some(PrimitiveType::U64), + "u128" => Some(PrimitiveType::U128), + "bool" => Some(PrimitiveType::Bool), + "char" => Some(PrimitiveType::Char), + "str" => Some(PrimitiveType::Str), + "f32" => Some(PrimitiveType::F32), + "f64" => Some(PrimitiveType::F64), + "array" => Some(PrimitiveType::Array), + "slice" => Some(PrimitiveType::Slice), + "tuple" => Some(PrimitiveType::Tuple), + "unit" => Some(PrimitiveType::Unit), + "pointer" => Some(PrimitiveType::RawPointer), + "reference" => Some(PrimitiveType::Reference), + "fn" => Some(PrimitiveType::Fn), + "never" => Some(PrimitiveType::Never), + _ => None, + } + } + + pub fn as_str(&self) -> &'static str { + use self::PrimitiveType::*; + match *self { + Isize => "isize", + I8 => "i8", + I16 => "i16", + I32 => "i32", + I64 => "i64", + I128 => "i128", + Usize => "usize", + U8 => "u8", + U16 => "u16", + U32 => "u32", + U64 => "u64", + U128 => "u128", + F32 => "f32", + F64 => "f64", + Str => "str", + Bool => "bool", + Char => "char", + Array => "array", + Slice => "slice", + Tuple => "tuple", + Unit => "unit", + RawPointer => "pointer", + Reference => "reference", + Fn => "fn", + Never => "never", + } + } + + pub fn to_url_str(&self) -> &'static str { + self.as_str() + } +} + +impl From for PrimitiveType { + fn from(int_ty: ast::IntTy) -> PrimitiveType { + match int_ty { + ast::IntTy::Isize => PrimitiveType::Isize, + ast::IntTy::I8 => PrimitiveType::I8, + ast::IntTy::I16 => PrimitiveType::I16, + ast::IntTy::I32 => PrimitiveType::I32, + ast::IntTy::I64 => PrimitiveType::I64, + ast::IntTy::I128 => PrimitiveType::I128, + } + } +} + +impl From for PrimitiveType { + fn from(uint_ty: ast::UintTy) -> PrimitiveType { + match uint_ty { + ast::UintTy::Usize => PrimitiveType::Usize, + ast::UintTy::U8 => PrimitiveType::U8, + ast::UintTy::U16 => PrimitiveType::U16, + ast::UintTy::U32 => PrimitiveType::U32, + ast::UintTy::U64 => PrimitiveType::U64, + ast::UintTy::U128 => PrimitiveType::U128, + } + } +} + +impl From for PrimitiveType { + fn from(float_ty: ast::FloatTy) -> PrimitiveType { + match float_ty { + ast::FloatTy::F32 => PrimitiveType::F32, + ast::FloatTy::F64 => PrimitiveType::F64, + } + } +} + +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum Visibility { + Public, + Inherited, + Crate, + Restricted(DefId, Path), +} + +#[derive(Clone, Debug)] +pub struct Struct { + pub struct_type: doctree::StructType, + pub generics: Generics, + pub fields: Vec, + pub fields_stripped: bool, +} + +#[derive(Clone, Debug)] +pub struct Union { + pub struct_type: doctree::StructType, + pub generics: Generics, + pub fields: Vec, + pub fields_stripped: bool, +} + +/// This is a more limited form of the standard Struct, different in that +/// it lacks the things most items have (name, id, parameterization). Found +/// only as a variant in an enum. +#[derive(Clone, Debug)] +pub struct VariantStruct { + pub struct_type: doctree::StructType, + pub fields: Vec, + pub fields_stripped: bool, +} + +#[derive(Clone, Debug)] +pub struct Enum { + pub variants: IndexVec, + pub generics: Generics, + pub variants_stripped: bool, +} + +#[derive(Clone, Debug)] +pub struct Variant { + pub kind: VariantKind, +} + +#[derive(Clone, Debug)] +pub enum VariantKind { + CLike, + Tuple(Vec), + Struct(VariantStruct), +} + +#[derive(Clone, Debug)] +pub struct Span { + pub filename: FileName, + pub loline: usize, + pub locol: usize, + pub hiline: usize, + pub hicol: usize, + pub original: syntax_pos::Span, +} + +impl Span { + pub fn empty() -> Span { + Span { + filename: FileName::Anon(0), + loline: 0, locol: 0, + hiline: 0, hicol: 0, + original: syntax_pos::DUMMY_SP, + } + } + + pub fn span(&self) -> syntax_pos::Span { + self.original + } +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct Path { + pub global: bool, + pub res: Res, + pub segments: Vec, +} + +impl Path { + pub fn last_name(&self) -> &str { + self.segments.last().expect("segments were empty").name.as_str() + } +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum GenericArg { + Lifetime(Lifetime), + Type(Type), + Const(Constant), +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum GenericArgs { + AngleBracketed { + args: Vec, + bindings: Vec, + }, + Parenthesized { + inputs: Vec, + output: Option, + } +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct PathSegment { + pub name: String, + pub args: GenericArgs, +} + +#[derive(Clone, Debug)] +pub struct Typedef { + pub type_: Type, + pub generics: Generics, +} + +#[derive(Clone, Debug)] +pub struct OpaqueTy { + pub bounds: Vec, + pub generics: Generics, +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct BareFunctionDecl { + pub unsafety: hir::Unsafety, + pub generic_params: Vec, + pub decl: FnDecl, + pub abi: Abi, +} + +#[derive(Clone, Debug)] +pub struct Static { + pub type_: Type, + pub mutability: Mutability, + /// It's useful to have the value of a static documented, but I have no + /// desire to represent expressions (that'd basically be all of the AST, + /// which is huge!). So, have a string. + pub expr: String, +} + +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct Constant { + pub type_: Type, + pub expr: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)] +pub enum Mutability { + Mutable, + Immutable, +} + +#[derive(Clone, PartialEq, Debug)] +pub enum ImplPolarity { + Positive, + Negative, +} + +#[derive(Clone, Debug)] +pub struct Impl { + pub unsafety: hir::Unsafety, + pub generics: Generics, + pub provided_trait_methods: FxHashSet, + pub trait_: Option, + pub for_: Type, + pub items: Vec, + pub polarity: Option, + pub synthetic: bool, + pub blanket_impl: Option, +} + +#[derive(Clone, Debug)] +pub enum Import { + // use source as str; + Simple(String, ImportSource), + // use source::*; + Glob(ImportSource) +} + +#[derive(Clone, Debug)] +pub struct ImportSource { + pub path: Path, + pub did: Option, +} + +#[derive(Clone, Debug)] +pub struct Macro { + pub source: String, + pub imported_from: Option, +} + +#[derive(Clone, Debug)] +pub struct ProcMacro { + pub kind: MacroKind, + pub helpers: Vec, +} + +#[derive(Clone, Debug)] +pub struct Stability { + pub level: stability::StabilityLevel, + pub feature: Option, + pub since: String, + pub deprecation: Option, + pub unstable_reason: Option, + pub issue: Option, +} + +#[derive(Clone, Debug)] +pub struct Deprecation { + pub since: Option, + pub note: Option, +} + +/// An type binding on an associated type (e.g., `A = Bar` in `Foo` or +/// `A: Send + Sync` in `Foo`). +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct TypeBinding { + pub name: String, + pub kind: TypeBindingKind, +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum TypeBindingKind { + Equality { + ty: Type, + }, + Constraint { + bounds: Vec, + }, +} + +impl TypeBinding { + pub fn ty(&self) -> &Type { + match self.kind { + TypeBindingKind::Equality { ref ty } => ty, + _ => panic!("expected equality type binding for parenthesized generic args"), + } + } +} diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 1f839f165320f..8db7bc12cd308 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -54,7 +54,5 @@ fn main() { } println!("cargo:rustc-link-lib=c"); println!("cargo:rustc-link-lib=compiler_rt"); - } else if target.contains("hermit") { - println!("cargo:rustc-link-lib=hermit"); } } diff --git a/src/libstd/env.rs b/src/libstd/env.rs index cf71b61b917a7..b5867e400026e 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -1033,6 +1033,11 @@ mod arch { pub const ARCH: &'static str = "hexagon"; } +#[cfg(target_arch = "riscv64")] +mod arch { + pub const ARCH: &'static str = "riscv64"; +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs index d9b2236047bdf..0caec97bb7b90 100644 --- a/src/libstd/os/linux/raw.rs +++ b/src/libstd/os/linux/raw.rs @@ -230,7 +230,12 @@ mod arch { } } -#[cfg(any(target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64"))] +#[cfg(any( + target_arch = "mips64", + target_arch = "s390x", + target_arch = "sparc64", + target_arch = "riscv64" +))] mod arch { pub use libc::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; } diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs index e09012007f2d4..47daf0cce1b37 100644 --- a/src/libstd/os/raw/mod.rs +++ b/src/libstd/os/raw/mod.rs @@ -18,7 +18,8 @@ target_arch = "hexagon", target_arch = "powerpc", target_arch = "powerpc64", - target_arch = "s390x" + target_arch = "s390x", + target_arch = "riscv64" ) ), all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")), @@ -60,7 +61,8 @@ pub type c_char = u8; target_arch = "hexagon", target_arch = "powerpc", target_arch = "powerpc64", - target_arch = "s390x" + target_arch = "s390x", + target_arch = "riscv64" ) ), all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")), diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 8669c48e3bb50..08fb088c86103 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -57,6 +57,7 @@ macro_rules! cfg_has_statx { // target_arch = "mips64", // target_arch = "s390x", target_arch = "sparc64", + target_arch = "riscv64", )))] { $($then_tt)* } else { @@ -76,6 +77,7 @@ macro_rules! cfg_has_statx { // target_arch = "mips64", // target_arch = "s390x", target_arch = "sparc64", + target_arch = "riscv64", )))] { $($block_inner)* diff --git a/src/libstd/sys_common/alloc.rs b/src/libstd/sys_common/alloc.rs index 713b9949f6461..c669410078592 100644 --- a/src/libstd/sys_common/alloc.rs +++ b/src/libstd/sys_common/alloc.rs @@ -22,7 +22,8 @@ pub const MIN_ALIGN: usize = 8; target_arch = "aarch64", target_arch = "mips64", target_arch = "s390x", - target_arch = "sparc64" + target_arch = "sparc64", + target_arch = "riscv64" )))] pub const MIN_ALIGN: usize = 16; diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs index 0b39503c0d034..4867a0f7f92b7 100644 --- a/src/libunwind/libunwind.rs +++ b/src/libunwind/libunwind.rs @@ -53,6 +53,9 @@ pub const unwinder_private_data_size: usize = 2; #[cfg(target_arch = "sparc64")] pub const unwinder_private_data_size: usize = 2; +#[cfg(target_arch = "riscv64")] +pub const unwinder_private_data_size: usize = 2; + #[cfg(target_os = "emscripten")] pub const unwinder_private_data_size: usize = 20; diff --git a/src/test/compile-fail/consts/const-err3.rs b/src/test/compile-fail/consts/const-err3.rs index add4eef13c784..fc10824f0c03c 100644 --- a/src/test/compile-fail/consts/const-err3.rs +++ b/src/test/compile-fail/consts/const-err3.rs @@ -14,7 +14,6 @@ fn main() { //~^ ERROR const_err let _e = [5u8][1]; //~^ ERROR const_err - //~| ERROR this expression will panic at runtime black_box(b); black_box(c); black_box(d); diff --git a/src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs b/src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs new file mode 100644 index 0000000000000..c8c2702ec447e --- /dev/null +++ b/src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs @@ -0,0 +1,15 @@ +// edition:2018 + +struct Ia(S); + +impl Ia { + fn partial(_: S) {} + fn full(self) {} + + async fn crash(self) { + Self::partial(self.0); + Self::full(self); //~ ERROR use of moved value: `self` + } +} + +fn main() {} diff --git a/src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr b/src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr new file mode 100644 index 0000000000000..9177b83dd48d7 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `self` + --> $DIR/issue-66958-non-copy-infered-type-arg.rs:11:20 + | +LL | Self::partial(self.0); + | ------ value moved here +LL | Self::full(self); + | ^^^^ value used here after partial move + | + = note: move occurs because `self.0` has type `S`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr index 0ddc2a0e79cd3..f4d4e6f969b36 100644 --- a/src/test/ui/consts/array-literal-index-oob.stderr +++ b/src/test/ui/consts/array-literal-index-oob.stderr @@ -12,7 +12,7 @@ error: reaching this expression at runtime will panic or abort LL | &{[1, 2, 3][4]}; | --^^^^^^^^^^^^- | | - | index out of bounds: the len is 3 but the index is 4 + | indexing out of bounds: the len is 3 but the index is 4 error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs index e5ee90fc9f11f..ecbcc2a4b496f 100644 --- a/src/test/ui/consts/const-err2.rs +++ b/src/test/ui/consts/const-err2.rs @@ -23,7 +23,6 @@ fn main() { //~^ ERROR const_err let _e = [5u8][1]; //~^ ERROR index out of bounds - //~| ERROR this expression will panic at runtime black_box(a); black_box(b); black_box(c); diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr index 0a09a7213dabc..1d84d44dc27b3 100644 --- a/src/test/ui/consts/const-err2.stderr +++ b/src/test/ui/consts/const-err2.stderr @@ -34,11 +34,5 @@ error: index out of bounds: the len is 1 but the index is 1 LL | let _e = [5u8][1]; | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/const-err2.rs:24:14 - | -LL | let _e = [5u8][1]; - | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/consts/const-err3.rs b/src/test/ui/consts/const-err3.rs index 89373f99f75c2..a9cf04cda7a5a 100644 --- a/src/test/ui/consts/const-err3.rs +++ b/src/test/ui/consts/const-err3.rs @@ -23,7 +23,6 @@ fn main() { //~^ ERROR const_err let _e = [5u8][1]; //~^ ERROR const_err - //~| ERROR this expression will panic at runtime black_box(a); black_box(b); black_box(c); diff --git a/src/test/ui/consts/const-err3.stderr b/src/test/ui/consts/const-err3.stderr index 42de247c8f7e0..0602707be7040 100644 --- a/src/test/ui/consts/const-err3.stderr +++ b/src/test/ui/consts/const-err3.stderr @@ -34,11 +34,5 @@ error: index out of bounds: the len is 1 but the index is 1 LL | let _e = [5u8][1]; | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/const-err3.rs:24:14 - | -LL | let _e = [5u8][1]; - | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index 45941398f4b66..dfa6863082cdb 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -8,14 +8,12 @@ fn main() { //~^ ERROR const_err println!("{}", 1/(1-1)); //~^ ERROR attempt to divide by zero [const_err] - //~| ERROR reaching this expression at runtime will panic or abort [const_err] + //~| ERROR const_err let _x = 1/(1-1); //~^ ERROR const_err - //~| ERROR const_err println!("{}", 1/(false as u32)); //~^ ERROR attempt to divide by zero [const_err] - //~| ERROR reaching this expression at runtime will panic or abort [const_err] + //~| ERROR const_err let _x = 1/(false as u32); //~^ ERROR const_err - //~| ERROR const_err } diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr index 40d5c73e86679..848a880ba492f 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.stderr @@ -20,7 +20,7 @@ error: reaching this expression at runtime will panic or abort --> $DIR/promoted_errors.rs:9:20 | LL | println!("{}", 1/(1-1)); - | ^^^^^^^ attempt to divide by zero + | ^^^^^^^ dividing by zero error: attempt to divide by zero --> $DIR/promoted_errors.rs:12:14 @@ -28,35 +28,23 @@ error: attempt to divide by zero LL | let _x = 1/(1-1); | ^^^^^^^ -error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:12:14 - | -LL | let _x = 1/(1-1); - | ^^^^^^^ attempt to divide by zero - error: attempt to divide by zero - --> $DIR/promoted_errors.rs:15:20 + --> $DIR/promoted_errors.rs:14:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:15:20 + --> $DIR/promoted_errors.rs:14:20 | LL | println!("{}", 1/(false as u32)); - | ^^^^^^^^^^^^^^^^ attempt to divide by zero + | ^^^^^^^^^^^^^^^^ dividing by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:18:14 + --> $DIR/promoted_errors.rs:17:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:18:14 - | -LL | let _x = 1/(false as u32); - | ^^^^^^^^^^^^^^^^ attempt to divide by zero - -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs index 7adb394144bdd..58b1794091228 100644 --- a/src/test/ui/consts/const-eval/promoted_errors2.rs +++ b/src/test/ui/consts/const-eval/promoted_errors2.rs @@ -9,14 +9,12 @@ fn main() { //~^ ERROR attempt to subtract with overflow println!("{}", 1/(1-1)); //~^ ERROR attempt to divide by zero [const_err] - //~| ERROR reaching this expression at runtime will panic or abort [const_err] + //~| ERROR const_err let _x = 1/(1-1); //~^ ERROR const_err - //~| ERROR const_err println!("{}", 1/(false as u32)); //~^ ERROR attempt to divide by zero [const_err] - //~| ERROR reaching this expression at runtime will panic or abort [const_err] + //~| ERROR const_err let _x = 1/(false as u32); //~^ ERROR const_err - //~| ERROR const_err } diff --git a/src/test/ui/consts/const-eval/promoted_errors2.stderr b/src/test/ui/consts/const-eval/promoted_errors2.stderr index 2819e6e8fdbe0..6f4b1c045f462 100644 --- a/src/test/ui/consts/const-eval/promoted_errors2.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors2.stderr @@ -26,7 +26,7 @@ error: reaching this expression at runtime will panic or abort --> $DIR/promoted_errors2.rs:10:20 | LL | println!("{}", 1/(1-1)); - | ^^^^^^^ attempt to divide by zero + | ^^^^^^^ dividing by zero error: attempt to divide by zero --> $DIR/promoted_errors2.rs:13:14 @@ -34,35 +34,23 @@ error: attempt to divide by zero LL | let _x = 1/(1-1); | ^^^^^^^ -error: this expression will panic at runtime - --> $DIR/promoted_errors2.rs:13:14 - | -LL | let _x = 1/(1-1); - | ^^^^^^^ attempt to divide by zero - error: attempt to divide by zero - --> $DIR/promoted_errors2.rs:16:20 + --> $DIR/promoted_errors2.rs:15:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors2.rs:16:20 + --> $DIR/promoted_errors2.rs:15:20 | LL | println!("{}", 1/(false as u32)); - | ^^^^^^^^^^^^^^^^ attempt to divide by zero + | ^^^^^^^^^^^^^^^^ dividing by zero error: attempt to divide by zero - --> $DIR/promoted_errors2.rs:19:14 + --> $DIR/promoted_errors2.rs:18:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/promoted_errors2.rs:19:14 - | -LL | let _x = 1/(false as u32); - | ^^^^^^^^^^^^^^^^ attempt to divide by zero - -error: aborting due to 10 previous errors +error: aborting due to 8 previous errors diff --git a/src/test/ui/consts/const-prop-ice.rs b/src/test/ui/consts/const-prop-ice.rs index 48c4b7da942e4..13309f978b672 100644 --- a/src/test/ui/consts/const-prop-ice.rs +++ b/src/test/ui/consts/const-prop-ice.rs @@ -1,4 +1,3 @@ fn main() { [0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3 - //~| ERROR this expression will panic at runtime } diff --git a/src/test/ui/consts/const-prop-ice.stderr b/src/test/ui/consts/const-prop-ice.stderr index 8ecc6f4bc6b12..4b3880198bf2d 100644 --- a/src/test/ui/consts/const-prop-ice.stderr +++ b/src/test/ui/consts/const-prop-ice.stderr @@ -6,11 +6,5 @@ LL | [0; 3][3u64 as usize]; | = note: `#[deny(const_err)]` on by default -error: this expression will panic at runtime - --> $DIR/const-prop-ice.rs:2:5 - | -LL | [0; 3][3u64 as usize]; - | ^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 3 - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/issues/issue-54348.rs b/src/test/ui/issues/issue-54348.rs index e7221e2cbb1e1..68d838054776e 100644 --- a/src/test/ui/issues/issue-54348.rs +++ b/src/test/ui/issues/issue-54348.rs @@ -1,7 +1,5 @@ fn main() { [1][0u64 as usize]; [1][1.5 as usize]; //~ ERROR index out of bounds - //~| ERROR this expression will panic at runtime [1][1u64 as usize]; //~ ERROR index out of bounds - //~| ERROR this expression will panic at runtime } diff --git a/src/test/ui/issues/issue-54348.stderr b/src/test/ui/issues/issue-54348.stderr index 79320ef4f31c7..fa77bd6fd7797 100644 --- a/src/test/ui/issues/issue-54348.stderr +++ b/src/test/ui/issues/issue-54348.stderr @@ -6,23 +6,11 @@ LL | [1][1.5 as usize]; | = note: `#[deny(const_err)]` on by default -error: this expression will panic at runtime - --> $DIR/issue-54348.rs:3:5 - | -LL | [1][1.5 as usize]; - | ^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1 - error: index out of bounds: the len is 1 but the index is 1 - --> $DIR/issue-54348.rs:5:5 + --> $DIR/issue-54348.rs:4:5 | LL | [1][1u64 as usize]; | ^^^^^^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-54348.rs:5:5 - | -LL | [1][1u64 as usize]; - | ^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1 - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs index 4637814b277a4..71e2b58031ce7 100644 --- a/src/test/ui/issues/issue-8460-const.rs +++ b/src/test/ui/issues/issue-8460-const.rs @@ -23,19 +23,14 @@ fn main() { //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow //~| ERROR this expression will panic at runtime @@ -53,17 +48,12 @@ fn main() { //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero - //~| ERROR this expression will panic at runtime } diff --git a/src/test/ui/issues/issue-8460-const.stderr b/src/test/ui/issues/issue-8460-const.stderr index 7e5a22e651ee5..c6750e653d7bb 100644 --- a/src/test/ui/issues/issue-8460-const.stderr +++ b/src/test/ui/issues/issue-8460-const.stderr @@ -70,179 +70,119 @@ error: attempt to divide by zero LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:24:36 - | -LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); - | ^^^^^^^^^^ attempt to divide by zero - error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:27:36 + --> $DIR/issue-8460-const.rs:26:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:27:36 - | -LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); - | ^^^^^^^ attempt to divide by zero - error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:30:36 + --> $DIR/issue-8460-const.rs:28:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:30:36 - | -LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); - | ^^^^^^^^ attempt to divide by zero - error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:33:36 + --> $DIR/issue-8460-const.rs:30:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:33:36 - | -LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); - | ^^^^^^^^ attempt to divide by zero - error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:36:36 + --> $DIR/issue-8460-const.rs:32:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:36:36 - | -LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); - | ^^^^^^^^ attempt to divide by zero - error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:39:36 + --> $DIR/issue-8460-const.rs:34:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:39:36 + --> $DIR/issue-8460-const.rs:34:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:42:36 + --> $DIR/issue-8460-const.rs:37:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:42:36 + --> $DIR/issue-8460-const.rs:37:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:45:36 + --> $DIR/issue-8460-const.rs:40:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:45:36 + --> $DIR/issue-8460-const.rs:40:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:48:36 + --> $DIR/issue-8460-const.rs:43:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:48:36 + --> $DIR/issue-8460-const.rs:43:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:51:36 + --> $DIR/issue-8460-const.rs:46:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:51:36 + --> $DIR/issue-8460-const.rs:46:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:54:36 + --> $DIR/issue-8460-const.rs:49:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:54:36 - | -LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); - | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero - error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:57:36 + --> $DIR/issue-8460-const.rs:51:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:57:36 - | -LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); - | ^^^^^^^ attempt to calculate the remainder with a divisor of zero - error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:60:36 + --> $DIR/issue-8460-const.rs:53:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:60:36 - | -LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); - | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero - error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:63:36 + --> $DIR/issue-8460-const.rs:55:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:63:36 - | -LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); - | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero - error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:66:36 + --> $DIR/issue-8460-const.rs:57:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:66:36 - | -LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); - | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero - -error: aborting due to 40 previous errors +error: aborting due to 30 previous errors diff --git a/src/test/ui/issues/issue-8460-const2.rs b/src/test/ui/issues/issue-8460-const2.rs index c3f53e3298b2b..723a17940a3a5 100644 --- a/src/test/ui/issues/issue-8460-const2.rs +++ b/src/test/ui/issues/issue-8460-const2.rs @@ -18,19 +18,14 @@ fn main() { //~^ ERROR attempt to divide with overflow assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); //~^ ERROR attempt to divide by zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with overflow assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); @@ -43,17 +38,12 @@ fn main() { //~^ ERROR attempt to calculate the remainder with overflow assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero - //~| ERROR this expression will panic at runtime assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); //~^ ERROR attempt to calculate the remainder with a divisor of zero - //~| ERROR this expression will panic at runtime } diff --git a/src/test/ui/issues/issue-8460-const2.stderr b/src/test/ui/issues/issue-8460-const2.stderr index b688ec1367794..87b9b2daa6f60 100644 --- a/src/test/ui/issues/issue-8460-const2.stderr +++ b/src/test/ui/issues/issue-8460-const2.stderr @@ -40,149 +40,89 @@ error: attempt to divide by zero LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const2.rs:19:36 - | -LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); - | ^^^^^^^^^^ attempt to divide by zero - error: attempt to divide by zero - --> $DIR/issue-8460-const2.rs:22:36 + --> $DIR/issue-8460-const2.rs:21:36 | LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); | ^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const2.rs:22:36 - | -LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); - | ^^^^^^^ attempt to divide by zero - error: attempt to divide by zero - --> $DIR/issue-8460-const2.rs:25:36 + --> $DIR/issue-8460-const2.rs:23:36 | LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const2.rs:25:36 - | -LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); - | ^^^^^^^^ attempt to divide by zero - error: attempt to divide by zero - --> $DIR/issue-8460-const2.rs:28:36 + --> $DIR/issue-8460-const2.rs:25:36 | LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const2.rs:28:36 - | -LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); - | ^^^^^^^^ attempt to divide by zero - error: attempt to divide by zero - --> $DIR/issue-8460-const2.rs:31:36 + --> $DIR/issue-8460-const2.rs:27:36 | LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const2.rs:31:36 - | -LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); - | ^^^^^^^^ attempt to divide by zero - error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const2.rs:34:36 + --> $DIR/issue-8460-const2.rs:29:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const2.rs:36:36 + --> $DIR/issue-8460-const2.rs:31:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const2.rs:38:36 + --> $DIR/issue-8460-const2.rs:33:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const2.rs:40:36 + --> $DIR/issue-8460-const2.rs:35:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const2.rs:42:36 + --> $DIR/issue-8460-const2.rs:37:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const2.rs:44:36 + --> $DIR/issue-8460-const2.rs:39:36 | LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); | ^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const2.rs:44:36 - | -LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); - | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero - error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const2.rs:47:36 + --> $DIR/issue-8460-const2.rs:41:36 | LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); | ^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const2.rs:47:36 - | -LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); - | ^^^^^^^ attempt to calculate the remainder with a divisor of zero - error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const2.rs:50:36 + --> $DIR/issue-8460-const2.rs:43:36 | LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const2.rs:50:36 - | -LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); - | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero - error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const2.rs:53:36 + --> $DIR/issue-8460-const2.rs:45:36 | LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const2.rs:53:36 - | -LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); - | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero - error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const2.rs:56:36 + --> $DIR/issue-8460-const2.rs:47:36 | LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); | ^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/issue-8460-const2.rs:56:36 - | -LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); - | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero - -error: aborting due to 30 previous errors +error: aborting due to 20 previous errors