diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 9d66863ef70e1..cef0ae65f658d 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -611,11 +611,18 @@ fn get_flow_results<'a, 'tcx>( ) -> Results<'tcx, Borrowck<'a, 'tcx>> { // We compute these three analyses individually, but them combine them into // a single results so that `mbcx` can visit them all together. - let borrows = Borrows::new(tcx, body, regioncx, borrow_set).iterate_to_fixpoint( - tcx, - body, - Some("borrowck"), - ); + let borrows_analysis = Borrows::new(tcx, body, regioncx, borrow_set); + let borrows = if borrow_set.location_map().is_empty() { + // A body without borrows has an empty dataflow domain: every entry + // state is the bottom value, so skip running the fixpoint engine. + let bottom = borrows_analysis.bottom_value(body); + Results { + analysis: borrows_analysis, + entry_states: IndexVec::from_elem_n(bottom, body.basic_blocks.len()), + } + } else { + borrows_analysis.iterate_to_fixpoint(tcx, body, Some("borrowck")) + }; let uninits = MaybeUninitializedPlaces::new(tcx, body, move_data).iterate_to_fixpoint( tcx, body, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index ff6b15b173ed1..bcd90eb77bb6c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -532,9 +532,11 @@ impl<'a> TraitDef<'a> { _ => unreachable!(), }; // Keep the lint attributes of the previous item to control how the - // generated implementations are linted - let mut attrs = newitem.attrs.clone(); - attrs.extend( + // generated implementations are linted. `newitem` is already + // owned, so extend its attributes in place rather than deep- + // cloning the whole generated impl. + let mut newitem = newitem; + newitem.attrs.extend( item.attrs .iter() .filter(|a| { @@ -549,7 +551,7 @@ impl<'a> TraitDef<'a> { }) .cloned(), ); - push(Annotatable::Item(Box::new(ast::Item { attrs, ..(*newitem).clone() }))) + push(Annotatable::Item(newitem)) } _ => unreachable!(), } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index c6bbeda36e930..05756f0d9786b 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -2186,6 +2186,12 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } } + // The overwhelming majority of nodes have no cfg or macro attribute + // to strip; skip the mutable attribute pass entirely for them. + if cfg_pos.is_none() && attr_pos.is_none() { + return None; + } + item.visit_attrs(|attrs| { attr = Some(match (cfg_pos, attr_pos) { (Some(pos), _) => (attrs.remove(pos), pos, Vec::new()), diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index bed2be51a3468..8dff1e7be62f8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -277,14 +277,10 @@ impl<'a> MetaDecoder for &'a MetadataBlob { fn decoder(self, pos: usize) -> Self::Context { BlobDecodeContext { - // FIXME: This unwrap should never panic because we check that it won't when creating - // `MetadataBlob`. Ideally we'd just have a `MetadataDecoder` and hand out subslices of - // it as we do elsewhere in the compiler using `MetadataDecoder::split_at`. But we own - // the data for the decoder so holding onto the `MemDecoder` too would make us a - // self-referential struct which is downright goofy because `MetadataBlob` is already - // self-referential. Probably `MemDecoder` should contain an `OwnedSlice`, but that - // demands a significant refactoring due to our crate graph. - opaque: MemDecoder::new(self, pos).unwrap(), + // The blob passed full `MemDecoder` validation when the + // `MetadataBlob` was created, so skip re-validating the magic + // suffix here: this runs for every lazily-decoded item. + opaque: MemDecoder::new_prevalidated(self, pos), lazy_state: LazyState::NoNode, blob: self.blob(), } diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index 4a644d3bb6eac..e9a899ef58771 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -293,6 +293,18 @@ impl<'a> MemDecoder<'a> { Ok(MemDecoder { start, current: data[position..].as_ptr(), end, _marker: PhantomData }) } + /// Like [`MemDecoder::new`], but skips re-validating the `MAGIC_END_BYTES` + /// suffix. Callers must have validated `data` before (e.g. with a prior + /// successful `MemDecoder::new`); this is worthwhile because a decoder is + /// constructed for every lazily-decoded metadata item. + #[inline] + pub fn new_prevalidated(data: &'a [u8], position: usize) -> MemDecoder<'a> { + debug_assert!(data.ends_with(MAGIC_END_BYTES)); + let data = &data[..data.len() - MAGIC_END_BYTES.len()]; + let Range { start, end } = data.as_ptr_range(); + MemDecoder { start, current: data[position..].as_ptr(), end, _marker: PhantomData } + } + #[inline] pub fn split_at(&self, position: usize) -> MemDecoder<'a> { assert!(position <= self.len());