diff --git a/RELEASES.md b/RELEASES.md index 13042ab07e217..e969b91b2b643 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -216,7 +216,7 @@ Language Compiler -------- -- [Added the `armv5te-unknown-linux-musl` target.][50423] +- [Added the `armv5te-unknown-linux-musleabi` target.][50423] Libraries --------- diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 5efe1e23309a7..cc913dfbb4b01 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -690,14 +690,20 @@ impl Vec { /// [`drain`]: #method.drain #[stable(feature = "rust1", since = "1.0.0")] pub fn truncate(&mut self, len: usize) { + let current_len = self.len; unsafe { + let mut ptr = self.as_mut_ptr().offset(self.len as isize); + // Set the final length at the end, keeping in mind that + // dropping an element might panic. Works around a missed + // optimization, as seen in the following issue: + // https://github.com/rust-lang/rust/issues/51802 + let mut local_len = SetLenOnDrop::new(&mut self.len); + // drop any extra elements - while len < self.len { - // decrement len before the drop_in_place(), so a panic on Drop - // doesn't re-drop the just-failed value. - self.len -= 1; - let len = self.len; - ptr::drop_in_place(self.get_unchecked_mut(len)); + for _ in len..current_len { + local_len.decrement_len(1); + ptr = ptr.offset(-1); + ptr::drop_in_place(ptr); } } } @@ -1512,6 +1518,11 @@ impl<'a> SetLenOnDrop<'a> { fn increment_len(&mut self, increment: usize) { self.local_len += increment; } + + #[inline] + fn decrement_len(&mut self, decrement: usize) { + self.local_len -= decrement; + } } impl<'a> Drop for SetLenOnDrop<'a> { diff --git a/src/libcore/slice/memchr.rs b/src/libcore/slice/memchr.rs index 72e7b57a6cb3c..c9d3c7fea9839 100644 --- a/src/libcore/slice/memchr.rs +++ b/src/libcore/slice/memchr.rs @@ -100,24 +100,30 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option { // - the first remaining bytes, < 2 word size let len = text.len(); let ptr = text.as_ptr(); - let usize_bytes = mem::size_of::(); + type Chunk = usize; - let mut offset = { - // We call this just to obtain the length of the suffix - let (_, _, suffix) = unsafe { text.align_to::() }; - len - suffix.len() + let (min_aligned_offset, max_aligned_offset) = { + // We call this just to obtain the length of the prefix and suffix. + // In the middle we always process two chunks at once. + let (prefix, _, suffix) = unsafe { text.align_to::<(Chunk, Chunk)>() }; + (prefix.len(), len - suffix.len()) }; + + let mut offset = max_aligned_offset; if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) { return Some(offset + index); } - // search the body of the text + // search the body of the text, make sure we don't cross min_aligned_offset. + // offset is always aligned, so just testing `>` is sufficient and avoids possible + // overflow. let repeated_x = repeat_byte(x); + let chunk_bytes = mem::size_of::(); - while offset >= 2 * usize_bytes { + while offset > min_aligned_offset { unsafe { - let u = *(ptr.offset(offset as isize - 2 * usize_bytes as isize) as *const usize); - let v = *(ptr.offset(offset as isize - usize_bytes as isize) as *const usize); + let u = *(ptr.offset(offset as isize - 2 * chunk_bytes as isize) as *const Chunk); + let v = *(ptr.offset(offset as isize - chunk_bytes as isize) as *const Chunk); // break if there is a matching byte let zu = contains_zero_byte(u ^ repeated_x); @@ -126,7 +132,7 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option { break; } } - offset -= 2 * usize_bytes; + offset -= 2 * chunk_bytes; } // find the byte before the point the body loop stopped diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index 86fd825850fc5..c178a9063c9ac 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use super::*; @@ -32,7 +32,7 @@ use super::*; #[derive(Clone)] pub struct Preorder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, - visited: BitVector, + visited: BitArray, worklist: Vec, } @@ -42,7 +42,7 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> { Preorder { mir, - visited: BitVector::new(mir.basic_blocks().len()), + visited: BitArray::new(mir.basic_blocks().len()), worklist, } } @@ -104,7 +104,7 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {} /// A Postorder traversal of this graph is `D B C A` or `D C B A` pub struct Postorder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, - visited: BitVector, + visited: BitArray, visit_stack: Vec<(BasicBlock, Successors<'a>)> } @@ -112,7 +112,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> { let mut po = Postorder { mir, - visited: BitVector::new(mir.basic_blocks().len()), + visited: BitArray::new(mir.basic_blocks().len()), visit_stack: Vec::new() }; diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 40171345f558b..35184ca6a2559 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -45,7 +45,7 @@ use middle::lang_items; use mir::interpret::{GlobalId}; use rustc_data_structures::sync::Lock; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use std::iter; use std::cmp; use std::fmt; @@ -3056,7 +3056,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } else { return Err(Unimplemented); }; - let mut ty_params = BitVector::new(substs_a.types().count()); + let mut ty_params = BitArray::new(substs_a.types().count()); let mut found = false; for ty in field.walk() { if let ty::TyParam(p) = ty.sty { diff --git a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs index 5273032f2d7f5..a76f1d50fa7bf 100644 --- a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs +++ b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs @@ -21,7 +21,7 @@ use libc::c_uint; use syntax_pos::Pos; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use syntax_pos::BytePos; @@ -64,7 +64,7 @@ pub fn create_mir_scopes( }; // Find all the scopes with variables defined in them. - let mut has_variables = BitVector::new(mir.source_scopes.len()); + let mut has_variables = BitArray::new(mir.source_scopes.len()); for var in mir.vars_iter() { let decl = &mir.local_decls[var]; has_variables.insert(decl.visibility_scope); @@ -81,7 +81,7 @@ pub fn create_mir_scopes( fn make_mir_scope(cx: &CodegenCx<'ll, '_>, mir: &Mir, - has_variables: &BitVector, + has_variables: &BitArray, debug_context: &FunctionDebugContextData<'ll>, scope: SourceScope, scopes: &mut IndexVec>) { diff --git a/src/librustc_codegen_llvm/mir/analyze.rs b/src/librustc_codegen_llvm/mir/analyze.rs index 2c2058035241f..993138aee1cec 100644 --- a/src/librustc_codegen_llvm/mir/analyze.rs +++ b/src/librustc_codegen_llvm/mir/analyze.rs @@ -11,7 +11,7 @@ //! An analysis to determine which locals require allocas and //! which do not. -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use rustc_data_structures::graph::dominators::Dominators; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::{self, Location, TerminatorKind}; @@ -22,7 +22,7 @@ use rustc::ty::layout::LayoutOf; use type_of::LayoutLlvmExt; use super::FunctionCx; -pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitVector { +pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitArray { let mir = fx.mir; let mut analyzer = LocalAnalyzer::new(fx); @@ -54,7 +54,7 @@ pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitVector { struct LocalAnalyzer<'mir, 'a: 'mir, 'll: 'a, 'tcx: 'll> { fx: &'mir FunctionCx<'a, 'll, 'tcx>, dominators: Dominators, - non_ssa_locals: BitVector, + non_ssa_locals: BitArray, // The location of the first visited direct assignment to each // local, or an invalid location (out of bounds `block` index). first_assignment: IndexVec @@ -67,7 +67,7 @@ impl LocalAnalyzer<'mir, 'a, 'll, 'tcx> { let mut analyzer = LocalAnalyzer { fx, dominators: fx.mir.dominators(), - non_ssa_locals: BitVector::new(fx.mir.local_decls.len()), + non_ssa_locals: BitArray::new(fx.mir.local_decls.len()), first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls) }; diff --git a/src/librustc_codegen_llvm/mir/mod.rs b/src/librustc_codegen_llvm/mir/mod.rs index 8cdd0398eff96..a099cb5c64b21 100644 --- a/src/librustc_codegen_llvm/mir/mod.rs +++ b/src/librustc_codegen_llvm/mir/mod.rs @@ -31,7 +31,7 @@ use syntax::symbol::keywords; use std::iter; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; pub use self::constant::codegen_static_initializer; @@ -323,7 +323,7 @@ pub fn codegen_mir( debuginfo::start_emitting_source_locations(&fx.debug_context); let rpo = traversal::reverse_postorder(&mir); - let mut visited = BitVector::new(mir.basic_blocks().len()); + let mut visited = BitArray::new(mir.basic_blocks().len()); // Codegen the body of each block using reverse postorder for (bb, _) in rpo { @@ -417,7 +417,7 @@ fn arg_local_refs( bx: &Builder<'a, 'll, 'tcx>, fx: &FunctionCx<'a, 'll, 'tcx>, scopes: &IndexVec>, - memory_locals: &BitVector, + memory_locals: &BitArray, ) -> Vec> { let mir = fx.mir; let tcx = bx.tcx(); diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs index 04d6cb5e2a6d2..6e8a45d034250 100644 --- a/src/librustc_data_structures/bitvec.rs +++ b/src/librustc_data_structures/bitvec.rs @@ -9,24 +9,74 @@ // except according to those terms. use indexed_vec::{Idx, IndexVec}; -use std::iter::FromIterator; use std::marker::PhantomData; type Word = u128; const WORD_BITS: usize = 128; -/// A very simple BitVector type. +/// A very simple BitArray type. +/// +/// It does not support resizing after creation; use `BitVector` for that. #[derive(Clone, Debug, PartialEq)] -pub struct BitVector { +pub struct BitArray { data: Vec, marker: PhantomData, } +#[derive(Clone, Debug, PartialEq)] +pub struct BitVector { + data: BitArray, +} + impl BitVector { + pub fn grow(&mut self, num_bits: C) { + self.data.grow(num_bits) + } + + pub fn new() -> BitVector { + BitVector { + data: BitArray::new(0), + } + } + + pub fn with_capacity(bits: usize) -> BitVector { + BitVector { + data: BitArray::new(bits), + } + } + + /// Returns true if the bit has changed. + #[inline] + pub fn insert(&mut self, bit: C) -> bool { + self.grow(bit); + self.data.insert(bit) + } + #[inline] - pub fn new(num_bits: usize) -> BitVector { + pub fn contains(&self, bit: C) -> bool { + let (word, mask) = word_mask(bit); + if let Some(word) = self.data.data.get(word) { + (word & mask) != 0 + } else { + false + } + } +} + +impl BitArray { + // Do not make this method public, instead switch your use case to BitVector. + #[inline] + fn grow(&mut self, num_bits: C) { let num_words = words(num_bits); - BitVector { + if self.data.len() <= num_words { + self.data.resize(num_words + 1, 0) + } + } + + #[inline] + pub fn new(num_bits: usize) -> BitArray { + let num_words = words(num_bits); + BitArray { data: vec![0; num_words], marker: PhantomData, } @@ -54,7 +104,7 @@ impl BitVector { /// /// The two vectors must have the same length. #[inline] - pub fn contains_all(&self, other: &BitVector) -> bool { + pub fn contains_all(&self, other: &BitArray) -> bool { assert_eq!(self.data.len(), other.data.len()); self.data.iter().zip(&other.data).all(|(a, b)| (a & b) == *b) } @@ -94,7 +144,7 @@ impl BitVector { } #[inline] - pub fn merge(&mut self, all: &BitVector) -> bool { + pub fn merge(&mut self, all: &BitArray) -> bool { assert!(self.data.len() == all.data.len()); let mut changed = false; for (i, j) in self.data.iter_mut().zip(&all.data) { @@ -107,18 +157,10 @@ impl BitVector { changed } - #[inline] - pub fn grow(&mut self, num_bits: C) { - let num_words = words(num_bits); - if self.data.len() < num_words { - self.data.resize(num_words, 0) - } - } - /// Iterates over indexes of set bits in a sorted order #[inline] - pub fn iter<'a>(&'a self) -> BitVectorIter<'a, C> { - BitVectorIter { + pub fn iter<'a>(&'a self) -> BitIter<'a, C> { + BitIter { iter: self.data.iter(), current: 0, idx: 0, @@ -127,14 +169,14 @@ impl BitVector { } } -pub struct BitVectorIter<'a, C: Idx> { +pub struct BitIter<'a, C: Idx> { iter: ::std::slice::Iter<'a, Word>, current: Word, idx: usize, marker: PhantomData } -impl<'a, C: Idx> Iterator for BitVectorIter<'a, C> { +impl<'a, C: Idx> Iterator for BitIter<'a, C> { type Item = C; fn next(&mut self) -> Option { while self.current == 0 { @@ -163,30 +205,6 @@ impl<'a, C: Idx> Iterator for BitVectorIter<'a, C> { } } -impl FromIterator for BitVector { - fn from_iter(iter: I) -> BitVector - where - I: IntoIterator, - { - let iter = iter.into_iter(); - let (len, _) = iter.size_hint(); - // Make the minimum length for the bitvector WORD_BITS bits since that's - // the smallest non-zero size anyway. - let len = if len < WORD_BITS { WORD_BITS } else { len }; - let mut bv = BitVector::new(len); - for (idx, val) in iter.enumerate() { - if idx > len { - bv.grow(C::new(idx)); - } - if val { - bv.insert(C::new(idx)); - } - } - - bv - } -} - /// A "bit matrix" is basically a matrix of booleans represented as /// one gigantic bitvector. In other words, it is as if you have /// `rows` bitvectors, each of length `columns`. @@ -288,9 +306,9 @@ impl BitMatrix { /// Iterates through all the columns set to true in a given row of /// the matrix. - pub fn iter<'a>(&'a self, row: R) -> BitVectorIter<'a, C> { + pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> { let (start, end) = self.range(row); - BitVectorIter { + BitIter { iter: self.vector[start..end].iter(), current: 0, idx: 0, @@ -308,7 +326,7 @@ where C: Idx, { columns: usize, - vector: IndexVec>, + vector: IndexVec>, } impl SparseBitMatrix { @@ -323,7 +341,7 @@ impl SparseBitMatrix { fn ensure_row(&mut self, row: R) { let columns = self.columns; self.vector - .ensure_contains_elem(row, || BitVector::new(columns)); + .ensure_contains_elem(row, || BitArray::new(columns)); } /// Sets the cell at `(row, column)` to true. Put another way, insert @@ -361,7 +379,7 @@ impl SparseBitMatrix { } /// Merge a row, `from`, into the `into` row. - pub fn merge_into(&mut self, into: R, from: &BitVector) -> bool { + pub fn merge_into(&mut self, into: R, from: &BitArray) -> bool { self.ensure_row(into); self.vector[into].merge(from) } @@ -388,11 +406,11 @@ impl SparseBitMatrix { } /// Iterates through each row and the accompanying bit set. - pub fn iter_enumerated<'a>(&'a self) -> impl Iterator)> + 'a { + pub fn iter_enumerated<'a>(&'a self) -> impl Iterator)> + 'a { self.vector.iter_enumerated() } - pub fn row(&self, row: R) -> Option<&BitVector> { + pub fn row(&self, row: R) -> Option<&BitArray> { self.vector.get(row) } } @@ -412,7 +430,7 @@ fn word_mask(index: C) -> (usize, Word) { #[test] fn bitvec_iter_works() { - let mut bitvec: BitVector = BitVector::new(100); + let mut bitvec: BitArray = BitArray::new(100); bitvec.insert(1); bitvec.insert(10); bitvec.insert(19); @@ -430,7 +448,7 @@ fn bitvec_iter_works() { #[test] fn bitvec_iter_works_2() { - let mut bitvec: BitVector = BitVector::new(319); + let mut bitvec: BitArray = BitArray::new(319); bitvec.insert(0); bitvec.insert(127); bitvec.insert(191); @@ -441,8 +459,8 @@ fn bitvec_iter_works_2() { #[test] fn union_two_vecs() { - let mut vec1: BitVector = BitVector::new(65); - let mut vec2: BitVector = BitVector::new(65); + let mut vec1: BitArray = BitArray::new(65); + let mut vec2: BitArray = BitArray::new(65); assert!(vec1.insert(3)); assert!(!vec1.insert(3)); assert!(vec2.insert(5)); @@ -458,7 +476,7 @@ fn union_two_vecs() { #[test] fn grow() { - let mut vec1: BitVector = BitVector::new(65); + let mut vec1: BitVector = BitVector::with_capacity(65); for index in 0..65 { assert!(vec1.insert(index)); assert!(!vec1.insert(index)); diff --git a/src/librustc_data_structures/graph/implementation/mod.rs b/src/librustc_data_structures/graph/implementation/mod.rs index dbfc09116bbaa..cf9403db658f4 100644 --- a/src/librustc_data_structures/graph/implementation/mod.rs +++ b/src/librustc_data_structures/graph/implementation/mod.rs @@ -30,7 +30,7 @@ //! the field `next_edge`). Each of those fields is an array that should //! be indexed by the direction (see the type `Direction`). -use bitvec::BitVector; +use bitvec::BitArray; use std::fmt::Debug; use std::usize; use snapshot_vec::{SnapshotVec, SnapshotVecDelegate}; @@ -266,7 +266,7 @@ impl Graph { direction: Direction, entry_node: NodeIndex, ) -> Vec { - let mut visited = BitVector::new(self.len_nodes()); + let mut visited = BitArray::new(self.len_nodes()); let mut stack = vec![]; let mut result = Vec::with_capacity(self.len_nodes()); let mut push_node = |stack: &mut Vec<_>, node: NodeIndex| { @@ -348,7 +348,7 @@ where { graph: &'g Graph, stack: Vec, - visited: BitVector, + visited: BitArray, direction: Direction, } @@ -358,7 +358,7 @@ impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> { start_node: NodeIndex, direction: Direction, ) -> Self { - let mut visited = BitVector::new(graph.len_nodes()); + let mut visited = BitArray::new(graph.len_nodes()); visited.insert(start_node.node_id()); DepthFirstTraversal { graph, diff --git a/src/librustc_data_structures/small_vec.rs b/src/librustc_data_structures/small_vec.rs index b5f52d54ae471..76b01beb4bad3 100644 --- a/src/librustc_data_structures/small_vec.rs +++ b/src/librustc_data_structures/small_vec.rs @@ -169,18 +169,11 @@ impl FromIterator for SmallVec { impl Extend for SmallVec { fn extend>(&mut self, iter: I) { - if self.is_array() { - let iter = iter.into_iter(); - self.reserve(iter.size_hint().0); - - for el in iter { - self.push(el); - } - } else { - match self.0 { - AccumulateVec::Heap(ref mut vec) => vec.extend(iter), - _ => unreachable!() - } + let iter = iter.into_iter(); + self.reserve(iter.size_hint().0); + match self.0 { + AccumulateVec::Heap(ref mut vec) => vec.extend(iter), + _ => iter.for_each(|el| self.push(el)) } } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 78a8c494f48c5..b92ac0ff57bd8 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -45,7 +45,6 @@ use rustc::lint::{LateContext, LateLintPass, LintPass, LintArray}; use rustc::lint::builtin::{ BARE_TRAIT_OBJECTS, ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, - MACRO_USE_EXTERN_CRATE, ELIDED_LIFETIMES_IN_PATHS, parser::QUESTION_MARK_MACRO_SEP }; @@ -195,11 +194,18 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { add_lint_group!(sess, "rust_2018_idioms", BARE_TRAIT_OBJECTS, - UNREACHABLE_PUB, UNUSED_EXTERN_CRATES, - MACRO_USE_EXTERN_CRATE, - ELIDED_LIFETIMES_IN_PATHS, - ELLIPSIS_INCLUSIVE_RANGE_PATTERNS); + ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, + ELIDED_LIFETIMES_IN_PATHS + + // FIXME(#52665, #47816) not always applicable and not all + // macros are ready for this yet. + // UNREACHABLE_PUB, + + // FIXME macro crates are not up for this yet, too much + // breakage is seen if we try to encourage this lint. + // MACRO_USE_EXTERN_CRATE, + ); // Guidelines for creating a future incompatibility lint: // diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index c44af00365479..640ae31d45b34 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -329,6 +329,13 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>( } (Place::Promoted(p1), Place::Promoted(p2)) => { if p1.0 == p2.0 { + if let ty::TyArray(_, size) = p1.1.sty { + if size.unwrap_usize(tcx) == 0 { + // Ignore conflicts with promoted [T; 0]. + debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED"); + return Overlap::Disjoint; + } + } // the same promoted - base case, equal debug!("place_element_conflict: DISJOINT-OR-EQ-PROMOTED"); Overlap::EqualOrDisjoint diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 6a447d81dc3cb..6b6ec749bcbe6 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -18,7 +18,7 @@ use build::{GuardFrame, GuardFrameLocal, LocalsForNode}; use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard}; use build::scope::{CachedBlock, DropKind}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use rustc::ty::{self, Ty}; use rustc::mir::*; use rustc::hir; @@ -496,7 +496,7 @@ enum TestKind<'tcx> { // test the branches of enum Switch { adt_def: &'tcx ty::AdtDef, - variants: BitVector, + variants: BitArray, }, // test the branches of enum diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index f8bfb5b48ba99..7106e02284da3 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -19,7 +19,7 @@ use build::Builder; use build::matches::{Candidate, MatchPair, Test, TestKind}; use hair::*; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use rustc::ty::{self, Ty}; use rustc::ty::util::IntTypeExt; use rustc::mir::*; @@ -38,7 +38,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { span: match_pair.pattern.span, kind: TestKind::Switch { adt_def: adt_def.clone(), - variants: BitVector::new(adt_def.variants.len()), + variants: BitArray::new(adt_def.variants.len()), }, } } @@ -149,7 +149,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn add_variants_to_switch<'pat>(&mut self, test_place: &Place<'tcx>, candidate: &Candidate<'pat, 'tcx>, - variants: &mut BitVector) + variants: &mut BitArray) -> bool { let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) { diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index 96f4c6b60f511..c8c41c13b0fbb 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -15,9 +15,9 @@ use rustc::mir::visit::Visitor; use dataflow::BitDenotation; /// This calculates if any part of a MIR local could have previously been borrowed. -/// This means that once a local has been borrowed, its bit will always be set -/// from that point and onwards, even if the borrow ends. You could also think of this -/// as computing the lifetimes of infinite borrows. +/// This means that once a local has been borrowed, its bit will be set +/// from that point and onwards, until we see a StorageDead statement for the local, +/// at which points there is no memory associated with the local, so it cannot be borrowed. /// This is used to compute which locals are live during a yield expression for /// immovable generators. #[derive(Copy, Clone)] @@ -50,9 +50,17 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> { fn statement_effect(&self, sets: &mut BlockSets, loc: Location) { + let stmt = &self.mir[loc.block].statements[loc.statement_index]; + BorrowedLocalsVisitor { sets, - }.visit_statement(loc.block, &self.mir[loc.block].statements[loc.statement_index], loc); + }.visit_statement(loc.block, stmt, loc); + + // StorageDead invalidates all borrows and raw pointers to a local + match stmt.kind { + StatementKind::StorageDead(l) => sets.kill(&l), + _ => (), + } } fn terminator_effect(&self, diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 5f05783b15cce..6283ee9cfe648 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -240,7 +240,7 @@ impl<'tcx> InliningMap<'tcx> { InliningMap { index: FxHashMap(), targets: Vec::new(), - inlines: BitVector::new(1024), + inlines: BitVector::with_capacity(1024), } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 6a9258fe2c918..a3647edd155d3 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -433,7 +433,8 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // The `liveness` variable contains the liveness of MIR locals ignoring borrows. // This is correct for movable generators since borrows cannot live across // suspension points. However for immovable generators we need to account for - // borrows, so we conseratively assume that all borrowed locals live forever. + // borrows, so we conseratively assume that all borrowed locals are live until + // we find a StorageDead statement referencing the locals. // To do this we just union our `liveness` result with `borrowed_locals`, which // contains all the locals which has been borrowed before this suspension point. // If a borrow is converted to a raw reference, we must also assume that it lives diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 46fab544aafe9..85115427edae9 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -14,7 +14,7 @@ use rustc::hir; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::DefId; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::*; @@ -271,7 +271,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { // Traverse the MIR manually so we can account for the effects of // inlining on the CFG. let mut work_list = vec![START_BLOCK]; - let mut visited = BitVector::new(callee_mir.basic_blocks().len()); + let mut visited = BitArray::new(callee_mir.basic_blocks().len()); while let Some(bb) = work_list.pop() { if !visited.insert(bb.index()) { continue; } let blk = &callee_mir.basic_blocks()[bb]; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 8a12a604ef202..208679d2aa08a 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -14,7 +14,7 @@ //! The Qualif flags below can be used to also provide better //! diagnostics as to why a constant rvalue wasn't promoted. -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::fx::FxHashSet; @@ -116,7 +116,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { param_env: ty::ParamEnv<'tcx>, local_qualif: IndexVec>, qualif: Qualif, - const_fn_arg_vars: BitVector, + const_fn_arg_vars: BitArray, temp_promotion_state: IndexVec, promotion_candidates: Vec } @@ -150,7 +150,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { param_env, local_qualif, qualif: Qualif::empty(), - const_fn_arg_vars: BitVector::new(mir.local_decls.len()), + const_fn_arg_vars: BitArray::new(mir.local_decls.len()), temp_promotion_state: temps, promotion_candidates: vec![] } @@ -284,7 +284,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { let mir = self.mir; - let mut seen_blocks = BitVector::new(mir.basic_blocks().len()); + let mut seen_blocks = BitArray::new(mir.basic_blocks().len()); let mut bb = START_BLOCK; loop { seen_blocks.insert(bb.index()); diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index a7ef93eaec6b9..04a7a81eb126f 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -10,7 +10,7 @@ use rustc::ty::TyCtxt; use rustc::mir::*; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use transform::{MirPass, MirSource}; use util::patch::MirPatch; @@ -45,7 +45,7 @@ impl RemoveNoopLandingPads { &self, bb: BasicBlock, mir: &Mir, - nop_landing_pads: &BitVector, + nop_landing_pads: &BitArray, ) -> bool { for stmt in &mir[bb].statements { match stmt.kind { @@ -111,7 +111,7 @@ impl RemoveNoopLandingPads { let mut jumps_folded = 0; let mut landing_pads_removed = 0; - let mut nop_landing_pads = BitVector::new(mir.basic_blocks().len()); + let mut nop_landing_pads = BitArray::new(mir.basic_blocks().len()); // This is a post-order traversal, so that if A post-dominates B // then A will be visited before B. diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 6b8d5a1489388..6e8471c672934 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -37,7 +37,7 @@ //! naively generate still contains the `_a = ()` write in the unreachable block "after" the //! return. -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::ty::TyCtxt; use rustc::mir::*; @@ -249,7 +249,7 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> { } pub fn remove_dead_blocks(mir: &mut Mir) { - let mut seen = BitVector::new(mir.basic_blocks().len()); + let mut seen = BitArray::new(mir.basic_blocks().len()); for (bb, _) in traversal::preorder(mir) { seen.insert(bb.index()); } @@ -285,7 +285,7 @@ impl MirPass for SimplifyLocals { tcx: TyCtxt<'a, 'tcx, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { - let mut marker = DeclMarker { locals: BitVector::new(mir.local_decls.len()) }; + let mut marker = DeclMarker { locals: BitArray::new(mir.local_decls.len()) }; marker.visit_mir(mir); // Return pointer and arguments are always live marker.locals.insert(RETURN_PLACE); @@ -310,7 +310,7 @@ impl MirPass for SimplifyLocals { /// Construct the mapping while swapping out unused stuff out from the `vec`. fn make_local_map<'tcx, V>( vec: &mut IndexVec, - mask: BitVector, + mask: BitArray, ) -> IndexVec> { let mut map: IndexVec> = IndexVec::from_elem(None, &*vec); let mut used = Local::new(0); @@ -326,7 +326,7 @@ fn make_local_map<'tcx, V>( } struct DeclMarker { - pub locals: BitVector, + pub locals: BitArray, } impl<'tcx> Visitor<'tcx> for DeclMarker { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 260179de99b80..b6ad2f316a0a2 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -691,6 +691,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { expansion: directive.expansion, }); let _ = self.try_define(directive.parent, target, TypeNS, binding); + let import = self.import_map.entry(directive.id).or_default(); + import[TypeNS] = Some(PathResolution::new(binding.def())); return None; } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7454f79ed6bbb..45566230fdaae 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1194,7 +1194,8 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option })?; match ty.def { Def::Struct(did) | Def::Union(did) | Def::Enum(did) | Def::TyAlias(did) => { - let item = cx.tcx.inherent_impls(did).iter() + let item = cx.tcx.inherent_impls(did) + .iter() .flat_map(|imp| cx.tcx.associated_items(*imp)) .find(|item| item.ident.name == item_name); if let Some(item) = item { @@ -1205,26 +1206,29 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option }; Ok((ty.def, Some(format!("{}.{}", out, item_name)))) } else { - let is_enum = match ty.def { - Def::Enum(_) => true, - _ => false, - }; - let elem = if is_enum { - cx.tcx.adt_def(did).all_fields().find(|item| item.ident.name == item_name) - } else { - cx.tcx.adt_def(did) - .non_enum_variant() - .fields - .iter() - .find(|item| item.ident.name == item_name) - }; - if let Some(item) = elem { - Ok((ty.def, - Some(format!("{}.{}", - if is_enum { "variant" } else { "structfield" }, - item.ident)))) - } else { - Err(()) + match cx.tcx.type_of(did).sty { + ty::TyAdt(def, _) => { + if let Some(item) = if def.is_enum() { + def.all_fields().find(|item| item.ident.name == item_name) + } else { + def.non_enum_variant() + .fields + .iter() + .find(|item| item.ident.name == item_name) + } { + Ok((ty.def, + Some(format!("{}.{}", + if def.is_enum() { + "variant" + } else { + "structfield" + }, + item.ident)))) + } else { + Err(()) + } + } + _ => Err(()), } } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 09d304b71a2c1..287913d2cc9b8 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -105,8 +105,8 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { } pub fn visit_variant_data(&mut self, item: &hir::Item, - name: ast::Name, sd: &hir::VariantData, - generics: &hir::Generics) -> Struct { + name: ast::Name, sd: &hir::VariantData, + generics: &hir::Generics) -> Struct { debug!("Visiting struct"); let struct_type = struct_type_from_def(&*sd); Struct { diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 5e89ad45f81d2..b83f3fbe7a59c 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -354,19 +354,26 @@ fn append_to_string(buf: &mut String, f: F) -> Result // avoid paying to allocate and zero a huge chunk of memory if the reader only // has 4 bytes while still making large reads if the reader does have a ton // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every -// time is 4,500 times (!) slower than this if the reader has a very small -// amount of data to return. +// time is 4,500 times (!) slower than a default reservation size of 32 if the +// reader has a very small amount of data to return. // // Because we're extending the buffer with uninitialized data for trusted // readers, we need to make sure to truncate that if any of this panics. fn read_to_end(r: &mut R, buf: &mut Vec) -> Result { + read_to_end_with_reservation(r, buf, 32) +} + +fn read_to_end_with_reservation(r: &mut R, + buf: &mut Vec, + reservation_size: usize) -> Result +{ let start_len = buf.len(); let mut g = Guard { len: buf.len(), buf: buf }; let ret; loop { if g.len == g.buf.len() { unsafe { - g.buf.reserve(32); + g.buf.reserve(reservation_size); let capacity = g.buf.capacity(); g.buf.set_len(capacity); r.initializer().initialize(&mut g.buf[g.len..]); @@ -1899,6 +1906,12 @@ impl Read for Take { unsafe fn initializer(&self) -> Initializer { self.inner.initializer() } + + fn read_to_end(&mut self, buf: &mut Vec) -> Result { + let reservation_size = cmp::min(self.limit, 32) as usize; + + read_to_end_with_reservation(self, buf, reservation_size) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d59c9dd6b53e8..28c1e4324de7a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -23,6 +23,7 @@ use ext::hygiene::{Mark, SyntaxContext}; use print::pprust; use ptr::P; use rustc_data_structures::indexed_vec; +use rustc_data_structures::indexed_vec::Idx; use symbol::{Symbol, keywords}; use tokenstream::{ThinTokenStream, TokenStream}; @@ -1910,9 +1911,18 @@ pub enum AttrStyle { Inner, } -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, PartialOrd, Ord, Copy)] pub struct AttrId(pub usize); +impl Idx for AttrId { + fn new(idx: usize) -> Self { + AttrId(idx) + } + fn index(self) -> usize { + self.0 + } +} + /// Meta-data associated with an item /// Doc-comments are promoted to attributes that have is_sugared_doc = true #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 137b94230a3cd..7fbc5d4c41a50 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -41,51 +41,27 @@ use std::iter; pub fn mark_used(attr: &Attribute) { debug!("Marking {:?} as used.", attr); - let AttrId(id) = attr.id; GLOBALS.with(|globals| { - let mut slot = globals.used_attrs.lock(); - let idx = (id / 64) as usize; - let shift = id % 64; - if slot.len() <= idx { - slot.resize(idx + 1, 0); - } - slot[idx] |= 1 << shift; + globals.used_attrs.lock().insert(attr.id); }); } pub fn is_used(attr: &Attribute) -> bool { - let AttrId(id) = attr.id; GLOBALS.with(|globals| { - let slot = globals.used_attrs.lock(); - let idx = (id / 64) as usize; - let shift = id % 64; - slot.get(idx).map(|bits| bits & (1 << shift) != 0) - .unwrap_or(false) + globals.used_attrs.lock().contains(attr.id) }) } pub fn mark_known(attr: &Attribute) { debug!("Marking {:?} as known.", attr); - let AttrId(id) = attr.id; GLOBALS.with(|globals| { - let mut slot = globals.known_attrs.lock(); - let idx = (id / 64) as usize; - let shift = id % 64; - if slot.len() <= idx { - slot.resize(idx + 1, 0); - } - slot[idx] |= 1 << shift; + globals.known_attrs.lock().insert(attr.id); }); } pub fn is_known(attr: &Attribute) -> bool { - let AttrId(id) = attr.id; GLOBALS.with(|globals| { - let slot = globals.known_attrs.lock(); - let idx = (id / 64) as usize; - let shift = id % 64; - slot.get(idx).map(|bits| bits & (1 << shift) != 0) - .unwrap_or(false) + globals.known_attrs.lock().contains(attr.id) }) } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 60de94821bba0..0c105865e0c2e 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -43,6 +43,8 @@ extern crate rustc_target; extern crate serialize as rustc_serialize; // used by deriving use rustc_data_structures::sync::Lock; +use rustc_data_structures::bitvec::BitVector; +use ast::AttrId; // A variant of 'try!' that panics on an Err. This is used as a crutch on the // way towards a non-panic!-prone parser. It should be used for fatal parsing @@ -75,16 +77,18 @@ macro_rules! unwrap_or { } pub struct Globals { - used_attrs: Lock>, - known_attrs: Lock>, + used_attrs: Lock>, + known_attrs: Lock>, syntax_pos_globals: syntax_pos::Globals, } impl Globals { fn new() -> Globals { Globals { - used_attrs: Lock::new(Vec::new()), - known_attrs: Lock::new(Vec::new()), + // We have no idea how many attributes their will be, so just + // initiate the vectors with 0 bits. We'll grow them as necessary. + used_attrs: Lock::new(BitVector::new()), + known_attrs: Lock::new(BitVector::new()), syntax_pos_globals: syntax_pos::Globals::new(), } } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index fd8f394a600f0..c449cc0a6525a 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -104,6 +104,7 @@ pub(crate) fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool { !ident_token.is_reserved_ident() || ident_token.is_path_segment_keyword() || [ + keywords::Async.name(), keywords::Do.name(), keywords::Box.name(), keywords::Break.name(), diff --git a/src/test/codegen/vec-clear.rs b/src/test/codegen/vec-clear.rs new file mode 100644 index 0000000000000..a73dd077cea11 --- /dev/null +++ b/src/test/codegen/vec-clear.rs @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -O + +#![crate_type = "lib"] + +// CHECK-LABEL: @vec_clear +#[no_mangle] +pub fn vec_clear(x: &mut Vec) { + // CHECK-NOT: load + // CHECK-NOT: icmp + x.clear() +} diff --git a/src/test/compile-fail/auxiliary/issue-52489.rs b/src/test/compile-fail/auxiliary/issue-52489.rs new file mode 100644 index 0000000000000..68d1ef8d776aa --- /dev/null +++ b/src/test/compile-fail/auxiliary/issue-52489.rs @@ -0,0 +1,13 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "lib"] +#![unstable(feature = "issue_52489_unstable", issue = "0")] +#![feature(staged_api)] diff --git a/src/test/compile-fail/issue-52489.rs b/src/test/compile-fail/issue-52489.rs new file mode 100644 index 0000000000000..c43cc12ca0229 --- /dev/null +++ b/src/test/compile-fail/issue-52489.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// edition:2018 +// aux-build:issue-52489.rs + +use issue_52489; +//~^ ERROR use of unstable library feature 'issue_52489_unstable' + +fn main() {} diff --git a/src/test/run-pass/generator/yield-in-initializer.rs b/src/test/run-pass/generator/yield-in-initializer.rs new file mode 100644 index 0000000000000..3042061226b39 --- /dev/null +++ b/src/test/run-pass/generator/yield-in-initializer.rs @@ -0,0 +1,25 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(generators)] + +fn main() { + static || { + loop { + // Test that `opt` is not live across the yield, even when borrowed in a loop + // See https://github.com/rust-lang/rust/issues/52792 + let opt = { + yield; + true + }; + &opt; + } + }; +} diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.rs b/src/test/rustdoc-ui/intra-doc-alias-ice.rs new file mode 100644 index 0000000000000..a459ab5dd2bea --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc-alias-ice.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![deny(intra_doc_link_resolution_failure)] + +pub type TypeAlias = usize; + +/// [broken cross-reference](TypeAlias::hoge) //~ ERROR +pub fn some_public_item() {} diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.stderr b/src/test/rustdoc-ui/intra-doc-alias-ice.stderr new file mode 100644 index 0000000000000..231963976ea75 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc-alias-ice.stderr @@ -0,0 +1,13 @@ +error: `[TypeAlias::hoge]` cannot be resolved, ignoring it... + --> $DIR/intra-doc-alias-ice.rs:15:30 + | +15 | /// [broken cross-reference](TypeAlias::hoge) //~ ERROR + | ^^^^^^^^^^^^^^^ cannot be resolved, ignoring + | +note: lint level defined here + --> $DIR/intra-doc-alias-ice.rs:11:9 + | +11 | #![deny(intra_doc_link_resolution_failure)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + diff --git a/src/test/ui/asm-out-assign-imm.nll.stderr b/src/test/ui/asm-out-assign-imm.nll.stderr index fbd58cd4c2260..45b0c84275be4 100644 --- a/src/test/ui/asm-out-assign-imm.nll.stderr +++ b/src/test/ui/asm-out-assign-imm.nll.stderr @@ -1,5 +1,5 @@ error[E0384]: cannot assign twice to immutable variable `x` - --> $DIR/asm-out-assign-imm.rs:33:9 + --> $DIR/asm-out-assign-imm.rs:34:9 | LL | let x: isize; | - consider changing this to `mut x` diff --git a/src/test/ui/asm-out-assign-imm.rs b/src/test/ui/asm-out-assign-imm.rs index f5bb07a9b35aa..73143f1154631 100644 --- a/src/test/ui/asm-out-assign-imm.rs +++ b/src/test/ui/asm-out-assign-imm.rs @@ -16,6 +16,7 @@ // ignore-sparc // ignore-sparc64 // ignore-mips +// ignore-mips64 #![feature(asm)] diff --git a/src/test/ui/asm-out-assign-imm.stderr b/src/test/ui/asm-out-assign-imm.stderr index 7075914fa04bd..83cb8092e16a2 100644 --- a/src/test/ui/asm-out-assign-imm.stderr +++ b/src/test/ui/asm-out-assign-imm.stderr @@ -1,5 +1,5 @@ error[E0384]: cannot assign twice to immutable variable `x` - --> $DIR/asm-out-assign-imm.rs:33:9 + --> $DIR/asm-out-assign-imm.rs:34:9 | LL | x = 1; | ----- first assignment to `x` diff --git a/src/test/ui/async-matches-expr.rs b/src/test/ui/async-matches-expr.rs new file mode 100644 index 0000000000000..d6959f9ddd805 --- /dev/null +++ b/src/test/ui/async-matches-expr.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass +// edition:2018 + +#![feature(async_await, await_macro)] + +macro_rules! match_expr { + ($x:expr) => {} +} + +fn main() { + match_expr!(async {}); + match_expr!(async || {}); +} diff --git a/src/test/ui/issue-49579.rs b/src/test/ui/issue-49579.rs new file mode 100644 index 0000000000000..e4e97c58d8aa3 --- /dev/null +++ b/src/test/ui/issue-49579.rs @@ -0,0 +1,27 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +// compile-pass + +#![feature(nll)] + +fn fibs(n: u32) -> impl Iterator { + (0 .. n) + .scan((0, 1), |st, _| { + *st = (st.1, st.0 + st.1); + Some(*st) + }) + .map(&|(f, _)| f) +} + +fn main() { + println!("{:?}", fibs(10).collect::>()); +} diff --git a/src/test/ui/issue-49824.nll.stderr b/src/test/ui/issue-49824.nll.stderr new file mode 100644 index 0000000000000..59345754e9f59 --- /dev/null +++ b/src/test/ui/issue-49824.nll.stderr @@ -0,0 +1,20 @@ +error: unsatisfied lifetime constraints + --> $DIR/issue-49824.rs:22:9 + | +LL | || { + | _____- + | |_____| + | || +LL | || || { + | ||_________^ +LL | ||| let _y = &mut x; +LL | ||| } + | |||_________^ requires that `'1` must outlive `'2` +LL | || }; + | || - + | ||_____| + | |______lifetime `'1` represents the closure body + | lifetime `'2` appears in return type + +error: aborting due to previous error + diff --git a/src/test/ui/issue-49824.rs b/src/test/ui/issue-49824.rs new file mode 100644 index 0000000000000..1f3e575288427 --- /dev/null +++ b/src/test/ui/issue-49824.rs @@ -0,0 +1,26 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +// This test checks that a failure occurs with NLL but does not fail with the +// legacy AST output. Check issue-49824.nll.stderr for expected compilation error +// output under NLL and #49824 for more information. + +#[rustc_error] +fn main() { + //~^ compilation successful + let mut x = 0; + || { + || { + let _y = &mut x; + } + }; +} diff --git a/src/test/ui/issue-49824.stderr b/src/test/ui/issue-49824.stderr new file mode 100644 index 0000000000000..b6cafe5e9e994 --- /dev/null +++ b/src/test/ui/issue-49824.stderr @@ -0,0 +1,14 @@ +error: compilation successful + --> $DIR/issue-49824.rs:18:1 + | +LL | / fn main() { +LL | | //~^ compilation successful +LL | | let mut x = 0; +LL | | || { +... | +LL | | }; +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs b/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs new file mode 100644 index 0000000000000..be38556961271 --- /dev/null +++ b/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that mutable promoted length zero arrays don't check for conflicting +// access + +// run-pass + +#![feature(nll)] + +pub fn main() { + let mut x: Vec<&[i32; 0]> = Vec::new(); + for i in 0..10 { + x.push(&[]); + } +} diff --git a/src/test/ui/rust-2018/macro-use-warned-against.rs b/src/test/ui/rust-2018/macro-use-warned-against.rs index f7a6b56028080..f50419434ae1d 100644 --- a/src/test/ui/rust-2018/macro-use-warned-against.rs +++ b/src/test/ui/rust-2018/macro-use-warned-against.rs @@ -12,7 +12,7 @@ // aux-build:macro-use-warned-against2.rs // compile-pass -#![warn(rust_2018_idioms, unused)] +#![warn(macro_use_extern_crate, unused)] #![feature(use_extern_macros)] #[macro_use] //~ WARN should be replaced at use sites with a `use` statement diff --git a/src/test/ui/rust-2018/macro-use-warned-against.stderr b/src/test/ui/rust-2018/macro-use-warned-against.stderr index bebad31510f56..7af404fab790e 100644 --- a/src/test/ui/rust-2018/macro-use-warned-against.stderr +++ b/src/test/ui/rust-2018/macro-use-warned-against.stderr @@ -7,9 +7,8 @@ LL | #[macro_use] //~ WARN should be replaced at use sites with a `use` statemen note: lint level defined here --> $DIR/macro-use-warned-against.rs:15:9 | -LL | #![warn(rust_2018_idioms, unused)] - | ^^^^^^^^^^^^^^^^ - = note: #[warn(macro_use_extern_crate)] implied by #[warn(rust_2018_idioms)] +LL | #![warn(macro_use_extern_crate, unused)] + | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused `#[macro_use]` import --> $DIR/macro-use-warned-against.rs:20:1 @@ -18,9 +17,9 @@ LL | #[macro_use] //~ WARN unused `#[macro_use]` | ^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/macro-use-warned-against.rs:15:27 + --> $DIR/macro-use-warned-against.rs:15:33 | -LL | #![warn(rust_2018_idioms, unused)] - | ^^^^^^ +LL | #![warn(macro_use_extern_crate, unused)] + | ^^^^^^ = note: #[warn(unused_imports)] implied by #[warn(unused)] diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs index 69208f151360b..c2dc927c4b524 100644 --- a/src/test/ui/target-feature-gate.rs +++ b/src/test/ui/target-feature-gate.rs @@ -12,6 +12,8 @@ // ignore-aarch64 // ignore-wasm // ignore-emscripten +// ignore-mips +// ignore-mips64 // gate-test-sse4a_target_feature // gate-test-powerpc_target_feature // gate-test-avx512_target_feature diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr index a6f794a1a1ab2..24141d0064fb0 100644 --- a/src/test/ui/target-feature-gate.stderr +++ b/src/test/ui/target-feature-gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839) - --> $DIR/target-feature-gate.rs:26:18 + --> $DIR/target-feature-gate.rs:28:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/target-feature-wrong.rs b/src/test/ui/target-feature-wrong.rs index 8983c0ea79bd9..fe611141379c4 100644 --- a/src/test/ui/target-feature-wrong.rs +++ b/src/test/ui/target-feature-wrong.rs @@ -13,6 +13,7 @@ // ignore-wasm // ignore-emscripten // ignore-mips +// ignore-mips64 // ignore-powerpc // ignore-powerpc64 // ignore-powerpc64le diff --git a/src/test/ui/target-feature-wrong.stderr b/src/test/ui/target-feature-wrong.stderr index d4e1c978104b6..21c73b7ddbff0 100644 --- a/src/test/ui/target-feature-wrong.stderr +++ b/src/test/ui/target-feature-wrong.stderr @@ -1,35 +1,35 @@ error: #[target_feature] attribute must be of the form #[target_feature(..)] - --> $DIR/target-feature-wrong.rs:25:1 + --> $DIR/target-feature-wrong.rs:26:1 | LL | #[target_feature = "+sse2"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the feature named `foo` is not valid for this target - --> $DIR/target-feature-wrong.rs:27:18 + --> $DIR/target-feature-wrong.rs:28:18 | LL | #[target_feature(enable = "foo")] | ^^^^^^^^^^^^^^ error: #[target_feature(..)] only accepts sub-keys of `enable` currently - --> $DIR/target-feature-wrong.rs:29:18 + --> $DIR/target-feature-wrong.rs:30:18 | LL | #[target_feature(bar)] | ^^^ error: #[target_feature(..)] only accepts sub-keys of `enable` currently - --> $DIR/target-feature-wrong.rs:31:18 + --> $DIR/target-feature-wrong.rs:32:18 | LL | #[target_feature(disable = "baz")] | ^^^^^^^^^^^^^^^ error: #[target_feature(..)] can only be applied to `unsafe` function - --> $DIR/target-feature-wrong.rs:35:1 + --> $DIR/target-feature-wrong.rs:36:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: attribute should be applied to a function - --> $DIR/target-feature-wrong.rs:39:1 + --> $DIR/target-feature-wrong.rs:40:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | mod another {} | -------------- not a function error: cannot use #[inline(always)] with #[target_feature] - --> $DIR/target-feature-wrong.rs:43:1 + --> $DIR/target-feature-wrong.rs:44:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^