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/hir/def.rs b/src/librustc/hir/def.rs index 1c355e35fd6ea..cb5e1e600d3d2 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -49,6 +49,7 @@ pub enum Def { PrimTy(hir::PrimTy), TyParam(DefId), SelfTy(Option /* trait */, Option /* impl */), + ToolMod, // e.g. `rustfmt` in `#[rustfmt::skip]` // Value namespace Fn(DefId), @@ -67,6 +68,7 @@ pub enum Def { // Macro namespace Macro(DefId, MacroKind), + NonMacroAttr, // e.g. `#[inline]` or `#[rustfmt::skip]` GlobalAsm(DefId), @@ -259,6 +261,8 @@ impl Def { Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | + Def::ToolMod | + Def::NonMacroAttr | Def::Err => { bug!("attempted .def_id() on invalid def: {:?}", self) } @@ -299,6 +303,8 @@ impl Def { Def::SelfTy(..) => "self type", Def::Macro(.., macro_kind) => macro_kind.descr(), Def::GlobalAsm(..) => "global asm", + Def::ToolMod => "tool module", + Def::NonMacroAttr => "non-macro attribute", Def::Err => "unresolved item", } } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 410d578d4044c..cac0d182d3a48 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -1016,6 +1016,8 @@ impl_stable_hash_for!(enum hir::def::Def { Label(node_id), Macro(def_id, macro_kind), GlobalAsm(def_id), + ToolMod, + NonMacroAttr, Err }); 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_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/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/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/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 4553a2ab5779f..ab4d15d0b9040 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -629,7 +629,8 @@ impl<'a> Resolver<'a> { pub fn get_macro(&mut self, def: Def) -> Lrc { let def_id = match def { Def::Macro(def_id, ..) => def_id, - _ => panic!("Expected Def::Macro(..)"), + Def::NonMacroAttr => return Lrc::new(SyntaxExtension::NonMacroAttr), + _ => panic!("Expected Def::Macro(..) or Def::NonMacroAttr"), }; if let Some(ext) = self.macro_map.get(&def_id) { return ext.clone(); diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index ec067a6477b6d..4c12591c83207 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -131,8 +131,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) { directive.vis.get() == ty::Visibility::Public || directive.span.is_dummy() => { if let ImportDirectiveSubclass::MacroUse = directive.subclass { - if resolver.session.features_untracked().use_extern_macros && - !directive.span.is_dummy() { + if resolver.use_extern_macros && !directive.span.is_dummy() { resolver.session.buffer_lint( lint::builtin::MACRO_USE_EXTERN_CRATE, directive.id, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ca42cf6dace2e..9c58d2c1f0b0c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -86,6 +86,10 @@ mod check_unused; mod build_reduced_graph; mod resolve_imports; +fn is_known_tool(name: Name) -> bool { + ["clippy", "rustfmt"].contains(&&*name.as_str()) +} + /// A free importable items suggested in case of resolution failure. struct ImportSuggestion { path: Path, @@ -200,15 +204,10 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, err.span_label(typaram_span, "type variable from outer function"); } }, - Def::Mod(..) | Def::Struct(..) | Def::Union(..) | Def::Enum(..) | Def::Variant(..) | - Def::Trait(..) | Def::TyAlias(..) | Def::TyForeign(..) | Def::TraitAlias(..) | - Def::AssociatedTy(..) | Def::PrimTy(..) | Def::Fn(..) | Def::Const(..) | - Def::Static(..) | Def::StructCtor(..) | Def::VariantCtor(..) | Def::Method(..) | - Def::AssociatedConst(..) | Def::Local(..) | Def::Upvar(..) | Def::Label(..) | - Def::Existential(..) | Def::AssociatedExistential(..) | - Def::Macro(..) | Def::GlobalAsm(..) | Def::Err => + _ => { bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy or \ Def::TyParam") + } } // Try to retrieve the span of the function signature and generate a new message with @@ -1711,9 +1710,7 @@ impl<'a> Resolver<'a> { vis: ty::Visibility::Public, }), - // The `proc_macro` and `decl_macro` features imply `use_extern_macros` - use_extern_macros: - features.use_extern_macros || features.decl_macro, + use_extern_macros: features.use_extern_macros(), crate_loader, macro_names: FxHashSet(), @@ -1846,6 +1843,7 @@ impl<'a> Resolver<'a> { path_span: Span) -> Option> { let record_used = record_used_id.is_some(); + assert!(ns == TypeNS || ns == ValueNS); if ns == TypeNS { ident.span = if ident.name == keywords::SelfType.name() { // FIXME(jseyfried) improve `Self` hygiene @@ -1922,8 +1920,9 @@ impl<'a> Resolver<'a> { return Some(LexicalScopeBinding::Item(binding)) } _ if poisoned.is_some() => break, - Err(Undetermined) => return None, - Err(Determined) => {} + Err(Determined) => continue, + Err(Undetermined) => + span_bug!(ident.span, "undetermined resolution during main resolution pass"), } } @@ -1945,6 +1944,11 @@ impl<'a> Resolver<'a> { ident.span, Mark::root()).to_name_binding(self.arenas); return Some(LexicalScopeBinding::Item(binding)); } + if ns == TypeNS && is_known_tool(ident.name) { + let binding = (Def::ToolMod, ty::Visibility::Public, + ident.span, Mark::root()).to_name_binding(self.arenas); + return Some(LexicalScopeBinding::Item(binding)); + } if let Some(prelude) = self.prelude { if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns, false, false, path_span) { @@ -3505,6 +3509,8 @@ impl<'a> Resolver<'a> { let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def); if let Some(next_module) = binding.module() { module = Some(next_module); + } else if def == Def::ToolMod && i + 1 != path.len() { + return PathResult::NonModule(PathResolution::new(Def::NonMacroAttr)) } else if def == Def::Err { return PathResult::NonModule(err_path_resolution()); } else if opt_ns.is_some() && (is_last || maybe_assoc) { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 1d42ad4e4902e..60a6bcf499db4 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use {AmbiguityError, CrateLint, Resolver, ResolutionError, resolve_error}; -use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult}; -use Namespace::{self, MacroNS}; +use {AmbiguityError, CrateLint, Resolver, ResolutionError, is_known_tool, resolve_error}; +use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding}; +use Namespace::{self, TypeNS, MacroNS}; use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport}; use resolve_imports::ImportResolver; use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex, @@ -27,7 +27,7 @@ use syntax::ext::expand::{self, AstFragment, AstFragmentKind, Invocation, Invoca use syntax::ext::hygiene::{self, Mark}; use syntax::ext::placeholders::placeholder; use syntax::ext::tt::macro_rules; -use syntax::feature_gate::{self, emit_feature_err, GateIssue}; +use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue}; use syntax::fold::{self, Folder}; use syntax::parse::parser::PathStyle; use syntax::parse::token::{self, Token}; @@ -326,6 +326,18 @@ impl<'a> base::Resolver for Resolver<'a> { if let Def::Macro(_, MacroKind::ProcMacroStub) = def { self.report_proc_macro_stub(invoc.span()); return Err(Determinacy::Determined); + } else if let Def::NonMacroAttr = def { + if let InvocationKind::Attr { .. } = invoc.kind { + if !self.session.features_untracked().tool_attributes { + feature_err(&self.session.parse_sess, "tool_attributes", + invoc.span(), GateIssue::Language, + "tool attributes are unstable").emit(); + } + return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr))); + } else { + self.report_non_macro_attr(invoc.path_span()); + return Err(Determinacy::Determined); + } } let def_id = def.def_id(); @@ -348,6 +360,9 @@ impl<'a> base::Resolver for Resolver<'a> { if let Def::Macro(_, MacroKind::ProcMacroStub) = def { self.report_proc_macro_stub(path.span); return Err(Determinacy::Determined); + } else if let Def::NonMacroAttr = def { + self.report_non_macro_attr(path.span); + return Err(Determinacy::Determined); } self.unused_macros.remove(&def.def_id()); Ok(self.get_macro(def)) @@ -378,6 +393,11 @@ impl<'a> Resolver<'a> { "can't use a procedural macro from the same crate that defines it"); } + fn report_non_macro_attr(&self, span: Span) { + self.session.span_err(span, + "expected a macro, found non-macro attribute"); + } + fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: bool) -> Result { let (attr, traits, item) = match invoc.kind { @@ -450,7 +470,15 @@ impl<'a> Resolver<'a> { fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) -> Result { - if kind != MacroKind::Bang && path.segments.len() > 1 { + let def = self.resolve_macro_to_def_inner(scope, path, kind, force); + if def != Err(Determinacy::Undetermined) { + // Do not report duplicated errors on every undetermined resolution. + path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| { + self.session.span_err(segment.args.as_ref().unwrap().span(), + "generic arguments in macro path"); + }); + } + if kind != MacroKind::Bang && path.segments.len() > 1 && def != Ok(Def::NonMacroAttr) { if !self.session.features_untracked().proc_macro_path_invoc { emit_feature_err( &self.session.parse_sess, @@ -462,15 +490,6 @@ impl<'a> Resolver<'a> { ); } } - - let def = self.resolve_macro_to_def_inner(scope, path, kind, force); - if def != Err(Determinacy::Undetermined) { - // Do not report duplicated errors on every undetermined resolution. - path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| { - self.session.span_err(segment.args.as_ref().unwrap().span(), - "generic arguments in macro path"); - }); - } def } @@ -544,67 +563,226 @@ impl<'a> Resolver<'a> { result } - // Resolve the initial segment of a non-global macro path (e.g. `foo` in `foo::bar!();`) + // Resolve the initial segment of a non-global macro path + // (e.g. `foo` in `foo::bar!(); or `foo!();`). + // This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during + // expansion and import resolution (perhaps they can be merged in the future). pub fn resolve_lexical_macro_path_segment(&mut self, mut ident: Ident, ns: Namespace, record_used: bool, path_span: Span) -> Result, Determinacy> { + // General principles: + // 1. Not controlled (user-defined) names should have higher priority than controlled names + // built into the language or standard library. This way we can add new names into the + // language or standard library without breaking user code. + // 2. "Closed set" below means new names can appear after the current resolution attempt. + // Places to search (in order of decreasing priority): + // (Type NS) + // 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet + // (open set, not controlled). + // 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents + // (open, not controlled). + // 3. Extern prelude (closed, not controlled). + // 4. Tool modules (closed, controlled right now, but not in the future). + // 5. Standard library prelude (de-facto closed, controlled). + // 6. Language prelude (closed, controlled). + // (Macro NS) + // 1. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents + // (open, not controlled). + // 2. Macro prelude (language, standard library, user-defined legacy plugins lumped into + // one set) (open, the open part is from macro expansions, not controlled). + // 2a. User-defined prelude from macro-use + // (open, the open part is from macro expansions, not controlled). + // 2b. Standard library prelude, currently just a macro-use (closed, controlled) + // 2c. Language prelude, perhaps including builtin attributes + // (closed, controlled, except for legacy plugins). + // 3. Builtin attributes (closed, controlled). + + assert!(ns == TypeNS || ns == MacroNS); ident = ident.modern(); - let mut module = Some(self.current_module); - let mut potential_illegal_shadower = Err(Determinacy::Determined); - let determinacy = - if record_used { Determinacy::Determined } else { Determinacy::Undetermined }; + + // Names from inner scope that can't shadow names from outer scopes, e.g. + // mod m { ... } + // { + // use prefix::*; // if this imports another `m`, then it can't shadow the outer `m` + // // and we have and ambiguity error + // m::mac!(); + // } + // This includes names from globs and from macro expansions. + let mut potentially_ambiguous_result: Option = None; + + enum WhereToResolve<'a> { + Module(Module<'a>), + MacroPrelude, + BuiltinAttrs, + ExternPrelude, + ToolPrelude, + StdLibPrelude, + PrimitiveTypes, + } + + // Go through all the scopes and try to resolve the name. + let mut where_to_resolve = WhereToResolve::Module(self.current_module); + let mut use_prelude = !self.current_module.no_implicit_prelude; loop { - let orig_current_module = self.current_module; - let result = if let Some(module) = module { - self.current_module = module; // Lexical resolutions can never be a privacy error. - // Since expanded macros may not shadow the lexical scope and - // globs may not shadow global macros (both enforced below), - // we resolve with restricted shadowing (indicated by the penultimate argument). - self.resolve_ident_in_module_unadjusted( - module, ident, ns, true, record_used, path_span, - ).map(MacroBinding::Modern) - } else { - self.macro_prelude.get(&ident.name).cloned().ok_or(determinacy) - .map(MacroBinding::Global) + let result = match where_to_resolve { + WhereToResolve::Module(module) => { + let orig_current_module = mem::replace(&mut self.current_module, module); + let binding = self.resolve_ident_in_module_unadjusted( + module, ident, ns, true, record_used, path_span, + ); + self.current_module = orig_current_module; + binding.map(MacroBinding::Modern) + } + WhereToResolve::MacroPrelude => { + match self.macro_prelude.get(&ident.name).cloned() { + Some(binding) => Ok(MacroBinding::Global(binding)), + None => Err(Determinacy::Determined), + } + } + WhereToResolve::BuiltinAttrs => { + if is_builtin_attr_name(ident.name) { + let binding = (Def::NonMacroAttr, ty::Visibility::Public, + ident.span, Mark::root()).to_name_binding(self.arenas); + Ok(MacroBinding::Global(binding)) + } else { + Err(Determinacy::Determined) + } + } + WhereToResolve::ExternPrelude => { + if use_prelude && self.extern_prelude.contains(&ident.name) { + if !self.session.features_untracked().extern_prelude && + !self.ignore_extern_prelude_feature { + feature_err(&self.session.parse_sess, "extern_prelude", + ident.span, GateIssue::Language, + "access to extern crates through prelude is experimental") + .emit(); + } + + let crate_id = + self.crate_loader.process_path_extern(ident.name, ident.span); + let crate_root = + self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); + self.populate_module_if_necessary(crate_root); + + let binding = (crate_root, ty::Visibility::Public, + ident.span, Mark::root()).to_name_binding(self.arenas); + Ok(MacroBinding::Global(binding)) + } else { + Err(Determinacy::Determined) + } + } + WhereToResolve::ToolPrelude => { + if use_prelude && is_known_tool(ident.name) { + let binding = (Def::ToolMod, ty::Visibility::Public, + ident.span, Mark::root()).to_name_binding(self.arenas); + Ok(MacroBinding::Global(binding)) + } else { + Err(Determinacy::Determined) + } + } + WhereToResolve::StdLibPrelude => { + let mut result = Err(Determinacy::Determined); + if use_prelude { + if let Some(prelude) = self.prelude { + if let Ok(binding) = + self.resolve_ident_in_module_unadjusted(prelude, ident, ns, + false, false, path_span) { + result = Ok(MacroBinding::Global(binding)); + } + } + } + result + } + WhereToResolve::PrimitiveTypes => { + if let Some(prim_ty) = + self.primitive_type_table.primitive_types.get(&ident.name).cloned() { + let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public, + ident.span, Mark::root()).to_name_binding(self.arenas); + Ok(MacroBinding::Global(binding)) + } else { + Err(Determinacy::Determined) + } + } }; - self.current_module = orig_current_module; - match result.map(MacroBinding::binding) { - Ok(binding) => { + macro_rules! continue_search { () => { + where_to_resolve = match where_to_resolve { + WhereToResolve::Module(module) => { + match self.hygienic_lexical_parent(module, &mut ident.span) { + Some(parent_module) => WhereToResolve::Module(parent_module), + None => { + use_prelude = !module.no_implicit_prelude; + if ns == MacroNS { + WhereToResolve::MacroPrelude + } else { + WhereToResolve::ExternPrelude + } + } + } + } + WhereToResolve::MacroPrelude => WhereToResolve::BuiltinAttrs, + WhereToResolve::BuiltinAttrs => break, // nowhere else to search + WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude, + WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude, + WhereToResolve::StdLibPrelude => WhereToResolve::PrimitiveTypes, + WhereToResolve::PrimitiveTypes => break, // nowhere else to search + }; + + continue; + }} + + match result { + Ok(result) => { if !record_used { - return result; + return Ok(result); } - if let Ok(MacroBinding::Modern(shadower)) = potential_illegal_shadower { - if shadower.def() != binding.def() { - let name = ident.name; + + let binding = result.binding(); + + // Found a solution that is ambiguous with a previously found solution. + // Push an ambiguity error for later reporting and + // return something for better recovery. + if let Some(previous_result) = potentially_ambiguous_result { + if binding.def() != previous_result.binding().def() { self.ambiguity_errors.push(AmbiguityError { span: path_span, - name, - b1: shadower, + name: ident.name, + b1: previous_result.binding(), b2: binding, lexical: true, }); - return potential_illegal_shadower; + return Ok(previous_result); } } + + // Found a solution that's not an ambiguity yet, but is "suspicious" and + // can participate in ambiguities later on. + // Remember it and go search for other solutions in outer scopes. if binding.is_glob_import() || binding.expansion != Mark::root() { - potential_illegal_shadower = result; - } else { - return result; + potentially_ambiguous_result = Some(result); + + continue_search!(); } + + // Found a solution that can't be ambiguous, great success. + return Ok(result); }, + Err(Determinacy::Determined) => { + continue_search!(); + } Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined), - Err(Determinacy::Determined) => {} } + } - module = match module { - Some(module) => self.hygienic_lexical_parent(module, &mut ident.span), - None => return potential_illegal_shadower, - } + // Previously found potentially ambiguous result turned out to not be ambiguous after all. + if let Some(previous_result) = potentially_ambiguous_result { + return Ok(previous_result); } + + if record_used { Err(Determinacy::Determined) } else { Err(Determinacy::Undetermined) } } pub fn resolve_legacy_scope(&mut self, 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/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 761521c8807ca..240b33c3c9478 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -811,6 +811,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { HirDef::Label(..) | HirDef::Macro(..) | HirDef::GlobalAsm(..) | + HirDef::ToolMod | + HirDef::NonMacroAttr | HirDef::Err => 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..b3b173db70b89 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -41,65 +41,32 @@ 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) }) } -const RUST_KNOWN_TOOL: &[&str] = &["clippy", "rustfmt"]; -const RUST_KNOWN_LINT_TOOL: &[&str] = &["clippy"]; - -pub fn is_known_tool(attr: &Attribute) -> bool { - let tool_name = - attr.path.segments.iter().next().expect("empty path in attribute").ident.name; - RUST_KNOWN_TOOL.contains(&tool_name.as_str().as_ref()) -} - pub fn is_known_lint_tool(m_item: Ident) -> bool { - RUST_KNOWN_LINT_TOOL.contains(&m_item.as_str().as_ref()) + ["clippy"].contains(&m_item.as_str().as_ref()) } impl NestedMetaItem { @@ -245,10 +212,6 @@ impl Attribute { pub fn is_value_str(&self) -> bool { self.value_str().is_some() } - - pub fn is_scoped(&self) -> bool { - self.path.segments.len() > 1 - } } impl MetaItem { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index b55c4f99206c4..8450daa3f7c94 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -588,6 +588,9 @@ impl MacroKind { /// An enum representing the different kinds of syntax extensions. pub enum SyntaxExtension { + /// A trivial "extension" that does nothing, only keeps the attribute and marks it as known. + NonMacroAttr, + /// A syntax extension that is attached to an item and creates new items /// based upon it. /// @@ -667,6 +670,7 @@ impl SyntaxExtension { SyntaxExtension::IdentTT(..) | SyntaxExtension::ProcMacro { .. } => MacroKind::Bang, + SyntaxExtension::NonMacroAttr | SyntaxExtension::MultiDecorator(..) | SyntaxExtension::MultiModifier(..) | SyntaxExtension::AttrProcMacro(..) => @@ -696,6 +700,7 @@ impl SyntaxExtension { SyntaxExtension::AttrProcMacro(.., edition) | SyntaxExtension::ProcMacroDerive(.., edition) => edition, // Unstable legacy stuff + SyntaxExtension::NonMacroAttr | SyntaxExtension::IdentTT(..) | SyntaxExtension::MultiDecorator(..) | SyntaxExtension::MultiModifier(..) | diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 9f8909e16264e..1fd77045a4550 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -36,7 +36,7 @@ use visit::{self, Visitor}; use std::collections::HashMap; use std::fs::File; use std::io::Read; -use std::mem; +use std::{iter, mem}; use std::rc::Rc; use std::path::PathBuf; @@ -243,6 +243,15 @@ impl Invocation { } } + pub fn path_span(&self) -> Span { + match self.kind { + InvocationKind::Bang { ref mac, .. } => mac.node.path.span, + InvocationKind::Attr { attr: Some(ref attr), .. } => attr.path.span, + InvocationKind::Attr { attr: None, .. } => DUMMY_SP, + InvocationKind::Derive { ref path, .. } => path.span, + } + } + pub fn attr_id(&self) -> Option { match self.kind { InvocationKind::Attr { attr: Some(ref attr), .. } => Some(attr.id), @@ -566,6 +575,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }); match *ext { + NonMacroAttr => { + attr::mark_known(&attr); + let item = item.map_attrs(|mut attrs| { attrs.push(attr); attrs }); + Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item))) + } MultiModifier(ref mac) => { let meta = attr.parse_meta(self.cx.parse_sess) .map_err(|mut e| { e.emit(); }).ok()?; @@ -810,7 +824,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } - MultiDecorator(..) | MultiModifier(..) | AttrProcMacro(..) => { + MultiDecorator(..) | MultiModifier(..) | + AttrProcMacro(..) | SyntaxExtension::NonMacroAttr => { self.cx.span_err(path.span, &format!("`{}` can only be used in attributes", path)); self.cx.trace_macros_diag(); @@ -1612,13 +1627,16 @@ impl<'feat> ExpansionConfig<'feat> { fn enable_allow_internal_unstable = allow_internal_unstable, fn enable_custom_derive = custom_derive, fn enable_format_args_nl = format_args_nl, - fn use_extern_macros_enabled = use_extern_macros, fn macros_in_extern_enabled = macros_in_extern, fn proc_macro_mod = proc_macro_mod, fn proc_macro_gen = proc_macro_gen, fn proc_macro_expr = proc_macro_expr, fn proc_macro_non_items = proc_macro_non_items, } + + pub fn use_extern_macros_enabled(&self) -> bool { + self.features.map_or(false, |features| features.use_extern_macros()) + } } // A Marker adds the given mark to the syntax context. diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 37a021a952914..77e3faa5b1fac 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -80,6 +80,11 @@ macro_rules! declare_features { { $(f(stringify!($feature), self.$feature);)+ } + + pub fn use_extern_macros(&self) -> bool { + // The `decl_macro` and `tool_attributes` features imply `use_extern_macros`. + self.use_extern_macros || self.decl_macro || self.tool_attributes + } } }; @@ -689,6 +694,10 @@ pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, Att BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect() } +pub fn is_builtin_attr_name(name: ast::Name) -> bool { + BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| name == builtin_name) +} + pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name)) || attr.name().as_str().starts_with("rustc_") @@ -1198,28 +1207,9 @@ impl<'a> Context<'a> { // before the plugin attributes are registered // so we skip this then if !is_macro { - if attr.is_scoped() { - gate_feature!(self, tool_attributes, attr.span, - &format!("scoped attribute `{}` is experimental", attr.path)); - if attr::is_known_tool(attr) { - attr::mark_used(attr); - } else { - span_err!( - self.parse_sess.span_diagnostic, - attr.span, - E0694, - "an unknown tool name found in scoped attribute: `{}`.", - attr.path - ); - } - } else { - gate_feature!(self, custom_attribute, attr.span, - &format!("The attribute `{}` is currently \ - unknown to the compiler and \ - may have meaning \ - added to it in the future", - attr.path)); - } + let msg = format!("The attribute `{}` is currently unknown to the compiler and \ + may have meaning added to it in the future", attr.path); + gate_feature!(self, custom_attribute, attr.span, &msg); } } } @@ -1529,7 +1519,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - if self.context.features.use_extern_macros && attr::is_known(attr) { + if self.context.features.use_extern_macros() && attr::is_known(attr) { return } @@ -2004,7 +1994,7 @@ impl FeatureChecker { // the branching can be eliminated by modifying `set!()` to set these spans // only for the features that need to be checked for mutual exclusion. fn collect(&mut self, features: &Features, span: Span) { - if features.use_extern_macros { + if features.use_extern_macros() { // If self.use_extern_macros is None, set to Some(span) self.use_extern_macros = self.use_extern_macros.or(Some(span)); } 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/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/feature-gate-tool_attributes.rs b/src/test/compile-fail/auxiliary/issue-52489.rs similarity index 79% rename from src/test/compile-fail/feature-gate-tool_attributes.rs rename to src/test/compile-fail/auxiliary/issue-52489.rs index 5a7536ca3304b..68d1ef8d776aa 100644 --- a/src/test/compile-fail/feature-gate-tool_attributes.rs +++ b/src/test/compile-fail/auxiliary/issue-52489.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() { - #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental - let x = - 3; -} +#![crate_type = "lib"] +#![unstable(feature = "issue_52489_unstable", issue = "0")] +#![feature(staged_api)] diff --git a/src/test/compile-fail/unknown_tool_attributes-1.rs b/src/test/compile-fail/issue-52489.rs similarity index 62% rename from src/test/compile-fail/unknown_tool_attributes-1.rs rename to src/test/compile-fail/issue-52489.rs index ba38c297a1127..c43cc12ca0229 100644 --- a/src/test/compile-fail/unknown_tool_attributes-1.rs +++ b/src/test/compile-fail/issue-52489.rs @@ -8,11 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Make sure that 'custom_attributes' feature does not allow scoped attributes. +// edition:2018 +// aux-build:issue-52489.rs -#![feature(custom_attributes)] +use issue_52489; +//~^ ERROR use of unstable library feature 'issue_52489_unstable' -#[foo::bar] -//~^ ERROR scoped attribute `foo::bar` is experimental (see issue #44690) [E0658] -//~^^ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694] fn main() {} diff --git a/src/test/compile-fail/unknown-tool-name.rs b/src/test/compile-fail/unknown-tool-name.rs index c2192a21d9050..c4d22e6d39210 100644 --- a/src/test/compile-fail/unknown-tool-name.rs +++ b/src/test/compile-fail/unknown-tool-name.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(tool_attributes)] +#![feature(use_extern_macros, proc_macro_path_invoc)] -#![foo::bar] //~ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694] - -#[foo::bar] //~ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694] +#[foo::bar] //~ ERROR failed to resolve. Use of undeclared type or module `foo` fn main() {} diff --git a/src/test/run-pass-fulldeps/proc-macro/issue-42708.rs b/src/test/run-pass-fulldeps/proc-macro/issue-42708.rs index df4a1d8994b54..d4af99f97c5c8 100644 --- a/src/test/run-pass-fulldeps/proc-macro/issue-42708.rs +++ b/src/test/run-pass-fulldeps/proc-macro/issue-42708.rs @@ -11,7 +11,7 @@ // aux-build:issue-42708.rs // ignore-stage1 -#![feature(decl_macro, use_extern_macros, proc_macro_path_invoc)] +#![feature(decl_macro, proc_macro_path_invoc)] #![allow(unused)] extern crate issue_42708; diff --git a/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs b/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs index 15dff94c88c18..53783e7fedb29 100644 --- a/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs +++ b/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs @@ -11,7 +11,7 @@ // aux-build:issue-50061.rs // ignore-stage1 -#![feature(use_extern_macros, proc_macro_path_invoc, decl_macro)] +#![feature(proc_macro_path_invoc, decl_macro)] extern crate issue_50061; 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-fulldeps/proc-macro/parent-source-spans.rs b/src/test/ui-fulldeps/proc-macro/parent-source-spans.rs index a60841d848c16..18f5b0f506cc2 100644 --- a/src/test/ui-fulldeps/proc-macro/parent-source-spans.rs +++ b/src/test/ui-fulldeps/proc-macro/parent-source-spans.rs @@ -11,7 +11,7 @@ // aux-build:parent-source-spans.rs // ignore-stage1 -#![feature(use_extern_macros, decl_macro, proc_macro_non_items)] +#![feature(decl_macro, proc_macro_non_items)] extern crate parent_source_spans; 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/auxiliary/macro-in-other-crate.rs b/src/test/ui/auxiliary/macro-in-other-crate.rs index 01282f2ad24b2..c787cedc2d0ea 100644 --- a/src/test/ui/auxiliary/macro-in-other-crate.rs +++ b/src/test/ui/auxiliary/macro-in-other-crate.rs @@ -12,3 +12,8 @@ macro_rules! mac { ($ident:ident) => { let $ident = 42; } } + +#[macro_export] +macro_rules! inline { + () => () +} diff --git a/src/test/ui/feature-gate-macros_in_extern.stderr b/src/test/ui/feature-gate-macros_in_extern.stderr index 748adc390d8bb..5d7e01fbbb752 100644 --- a/src/test/ui/feature-gate-macros_in_extern.stderr +++ b/src/test/ui/feature-gate-macros_in_extern.stderr @@ -1,4 +1,4 @@ -error[E0658]: macro invocations in `extern {}` blocks are experimental. (see issue #49476) +error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476) --> $DIR/feature-gate-macros_in_extern.rs:29:5 | LL | returns_isize!(rust_get_test_int); @@ -6,7 +6,7 @@ LL | returns_isize!(rust_get_test_int); | = help: add #![feature(macros_in_extern)] to the crate attributes to enable -error[E0658]: macro invocations in `extern {}` blocks are experimental. (see issue #49476) +error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476) --> $DIR/feature-gate-macros_in_extern.rs:31:5 | LL | takes_u32_returns_u32!(rust_dbg_extern_identity_u32); @@ -14,7 +14,7 @@ LL | takes_u32_returns_u32!(rust_dbg_extern_identity_u32); | = help: add #![feature(macros_in_extern)] to the crate attributes to enable -error[E0658]: macro invocations in `extern {}` blocks are experimental. (see issue #49476) +error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476) --> $DIR/feature-gate-macros_in_extern.rs:33:5 | LL | emits_nothing!(); diff --git a/src/test/ui/feature-gate-tool_attributes.rs b/src/test/ui/feature-gate-tool_attributes.rs index 2b7cf56d93812..47c623574ec90 100644 --- a/src/test/ui/feature-gate-tool_attributes.rs +++ b/src/test/ui/feature-gate-tool_attributes.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(use_extern_macros)] + fn main() { - #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental + #[rustfmt::skip] //~ ERROR tool attributes are unstable let x = 3 ; } diff --git a/src/test/ui/feature-gate-tool_attributes.stderr b/src/test/ui/feature-gate-tool_attributes.stderr index da89c4a5ef692..ebc266e004ecc 100644 --- a/src/test/ui/feature-gate-tool_attributes.stderr +++ b/src/test/ui/feature-gate-tool_attributes.stderr @@ -1,7 +1,7 @@ -error[E0658]: scoped attribute `rustfmt::skip` is experimental (see issue #44690) - --> $DIR/feature-gate-tool_attributes.rs:12:5 +error[E0658]: tool attributes are unstable (see issue #44690) + --> $DIR/feature-gate-tool_attributes.rs:14:5 | -LL | #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental +LL | #[rustfmt::skip] //~ ERROR tool attributes are unstable | ^^^^^^^^^^^^^^^^ | = help: add #![feature(tool_attributes)] to the crate attributes to enable diff --git a/src/test/ui/issue-11692-1.rs b/src/test/ui/issue-11692-1.rs index f577aad04e620..ff6009da72fd9 100644 --- a/src/test/ui/issue-11692-1.rs +++ b/src/test/ui/issue-11692-1.rs @@ -9,6 +9,6 @@ // except according to those terms. fn main() { - print!(test!()); + print!(testo!()); //~^ ERROR: format argument must be a string literal } diff --git a/src/test/ui/issue-11692-1.stderr b/src/test/ui/issue-11692-1.stderr index bee73e9f568b6..61ff455d16ca5 100644 --- a/src/test/ui/issue-11692-1.stderr +++ b/src/test/ui/issue-11692-1.stderr @@ -1,11 +1,11 @@ error: format argument must be a string literal --> $DIR/issue-11692-1.rs:12:12 | -LL | print!(test!()); - | ^^^^^^^ +LL | print!(testo!()); + | ^^^^^^^^ help: you might be missing a string literal to format with | -LL | print!("{}", test!()); +LL | print!("{}", testo!()); | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issue-11692-2.rs b/src/test/ui/issue-11692-2.rs index acac2d151fe9a..c595b0fb2c2d8 100644 --- a/src/test/ui/issue-11692-2.rs +++ b/src/test/ui/issue-11692-2.rs @@ -10,5 +10,5 @@ fn main() { concat!(test!()); - //~^ ERROR cannot find macro `test!` in this scope + //~^ ERROR expected a macro, found non-macro attribute } diff --git a/src/test/ui/issue-11692-2.stderr b/src/test/ui/issue-11692-2.stderr index 51d6041e92220..3d080bd46dcc9 100644 --- a/src/test/ui/issue-11692-2.stderr +++ b/src/test/ui/issue-11692-2.stderr @@ -1,4 +1,4 @@ -error: cannot find macro `test!` in this scope +error: expected a macro, found non-macro attribute --> $DIR/issue-11692-2.rs:12:13 | LL | concat!(test!()); diff --git a/src/test/ui/issue-50187.rs b/src/test/ui/issue-50187.rs index 87acf10639331..ccb2742841cc5 100644 --- a/src/test/ui/issue-50187.rs +++ b/src/test/ui/issue-50187.rs @@ -10,7 +10,7 @@ // compile-pass -#![feature(use_extern_macros, decl_macro)] +#![feature(decl_macro)] mod type_ns { pub type A = u8; diff --git a/src/test/ui/macro-path-prelude-fail-1.rs b/src/test/ui/macro-path-prelude-fail-1.rs new file mode 100644 index 0000000000000..b953805a7eb2f --- /dev/null +++ b/src/test/ui/macro-path-prelude-fail-1.rs @@ -0,0 +1,20 @@ +// 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(use_extern_macros, extern_prelude)] + +mod m { + fn check() { + Vec::clone!(); //~ ERROR failed to resolve. Not a module `Vec` + u8::clone!(); //~ ERROR failed to resolve. Not a module `u8` + } +} + +fn main() {} diff --git a/src/test/ui/macro-path-prelude-fail-1.stderr b/src/test/ui/macro-path-prelude-fail-1.stderr new file mode 100644 index 0000000000000..fc74937d91200 --- /dev/null +++ b/src/test/ui/macro-path-prelude-fail-1.stderr @@ -0,0 +1,15 @@ +error[E0433]: failed to resolve. Not a module `Vec` + --> $DIR/macro-path-prelude-fail-1.rs:15:9 + | +LL | Vec::clone!(); //~ ERROR failed to resolve. Not a module `Vec` + | ^^^ Not a module `Vec` + +error[E0433]: failed to resolve. Not a module `u8` + --> $DIR/macro-path-prelude-fail-1.rs:16:9 + | +LL | u8::clone!(); //~ ERROR failed to resolve. Not a module `u8` + | ^^ Not a module `u8` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/macro-path-prelude-fail-2.rs b/src/test/ui/macro-path-prelude-fail-2.rs new file mode 100644 index 0000000000000..ec77e276bd403 --- /dev/null +++ b/src/test/ui/macro-path-prelude-fail-2.rs @@ -0,0 +1,19 @@ +// 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(use_extern_macros)] + +mod m { + fn check() { + Result::Ok!(); //~ ERROR fail to resolve non-ident macro path + } +} + +fn main() {} diff --git a/src/test/ui/macro-path-prelude-fail-2.stderr b/src/test/ui/macro-path-prelude-fail-2.stderr new file mode 100644 index 0000000000000..d23aed847a30c --- /dev/null +++ b/src/test/ui/macro-path-prelude-fail-2.stderr @@ -0,0 +1,8 @@ +error: fail to resolve non-ident macro path + --> $DIR/macro-path-prelude-fail-2.rs:15:9 + | +LL | Result::Ok!(); //~ ERROR fail to resolve non-ident macro path + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/macro-path-prelude-fail-3.rs b/src/test/ui/macro-path-prelude-fail-3.rs new file mode 100644 index 0000000000000..4cf90019d40eb --- /dev/null +++ b/src/test/ui/macro-path-prelude-fail-3.rs @@ -0,0 +1,18 @@ +// 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(use_extern_macros)] + +#[derive(inline)] //~ ERROR expected a macro, found non-macro attribute +struct S; + +fn main() { + inline!(); //~ ERROR expected a macro, found non-macro attribute +} diff --git a/src/test/ui/macro-path-prelude-fail-3.stderr b/src/test/ui/macro-path-prelude-fail-3.stderr new file mode 100644 index 0000000000000..bd1015b7ee10e --- /dev/null +++ b/src/test/ui/macro-path-prelude-fail-3.stderr @@ -0,0 +1,14 @@ +error: expected a macro, found non-macro attribute + --> $DIR/macro-path-prelude-fail-3.rs:13:10 + | +LL | #[derive(inline)] //~ ERROR expected a macro, found non-macro attribute + | ^^^^^^ + +error: expected a macro, found non-macro attribute + --> $DIR/macro-path-prelude-fail-3.rs:17:5 + | +LL | inline!(); //~ ERROR expected a macro, found non-macro attribute + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/macro-path-prelude-pass.rs b/src/test/ui/macro-path-prelude-pass.rs new file mode 100644 index 0000000000000..bc58754513b6d --- /dev/null +++ b/src/test/ui/macro-path-prelude-pass.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-pass + +#![feature(use_extern_macros, extern_prelude)] + +mod m { + fn check() { + std::panic!(); // OK + } +} + +fn main() {} diff --git a/src/test/ui/macro-path-prelude-shadowing.rs b/src/test/ui/macro-path-prelude-shadowing.rs new file mode 100644 index 0000000000000..1aff7777ef7b1 --- /dev/null +++ b/src/test/ui/macro-path-prelude-shadowing.rs @@ -0,0 +1,41 @@ +// 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. + +// aux-build:macro-in-other-crate.rs + +#![feature(decl_macro, extern_prelude)] + +macro_rules! add_macro_expanded_things_to_macro_prelude {() => { + #[macro_use] + extern crate macro_in_other_crate; +}} + +add_macro_expanded_things_to_macro_prelude!(); + +mod m1 { + fn check() { + inline!(); //~ ERROR `inline` is ambiguous + } +} + +mod m2 { + pub mod std { + pub macro panic() {} + } +} + +mod m3 { + use m2::*; // glob-import user-defined `std` + fn check() { + std::panic!(); //~ ERROR `std` is ambiguous + } +} + +fn main() {} diff --git a/src/test/ui/macro-path-prelude-shadowing.stderr b/src/test/ui/macro-path-prelude-shadowing.stderr new file mode 100644 index 0000000000000..0e1b9a985a3c3 --- /dev/null +++ b/src/test/ui/macro-path-prelude-shadowing.stderr @@ -0,0 +1,42 @@ +error[E0659]: `inline` is ambiguous + --> $DIR/macro-path-prelude-shadowing.rs:24:9 + | +LL | inline!(); //~ ERROR `inline` is ambiguous + | ^^^^^^ + | +note: `inline` could refer to the name imported here + --> $DIR/macro-path-prelude-shadowing.rs:16:5 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ +... +LL | add_macro_expanded_things_to_macro_prelude!(); + | ---------------------------------------------- in this macro invocation +note: `inline` could also refer to the name defined here + --> $DIR/macro-path-prelude-shadowing.rs:24:9 + | +LL | inline!(); //~ ERROR `inline` is ambiguous + | ^^^^^^ + = note: macro-expanded macro imports do not shadow + +error[E0659]: `std` is ambiguous + --> $DIR/macro-path-prelude-shadowing.rs:37:9 + | +LL | std::panic!(); //~ ERROR `std` is ambiguous + | ^^^^^^^^^^ + | +note: `std` could refer to the name imported here + --> $DIR/macro-path-prelude-shadowing.rs:35:9 + | +LL | use m2::*; // glob-import user-defined `std` + | ^^^^^ +note: `std` could also refer to the name defined here + --> $DIR/macro-path-prelude-shadowing.rs:37:9 + | +LL | std::panic!(); //~ ERROR `std` is ambiguous + | ^^^ + = note: consider adding an explicit import of `std` to disambiguate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0659`. 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)] | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/tool-attributes-disabled-1.rs b/src/test/ui/tool-attributes-disabled-1.rs new file mode 100644 index 0000000000000..87d47b75607c1 --- /dev/null +++ b/src/test/ui/tool-attributes-disabled-1.rs @@ -0,0 +1,15 @@ +// 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. + +// If macro modularization (`use_extern_macros`) is not enabled, +// then tool attributes are treated as custom attributes. + +#[rustfmt::bar] //~ ERROR The attribute `rustfmt::bar` is currently unknown to the compiler +fn main() {} diff --git a/src/test/ui/tool-attributes-disabled-1.stderr b/src/test/ui/tool-attributes-disabled-1.stderr new file mode 100644 index 0000000000000..6302c06057aa2 --- /dev/null +++ b/src/test/ui/tool-attributes-disabled-1.stderr @@ -0,0 +1,11 @@ +error[E0658]: The attribute `rustfmt::bar` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/tool-attributes-disabled-1.rs:14:1 + | +LL | #[rustfmt::bar] //~ ERROR The attribute `rustfmt::bar` is currently unknown to the compiler + | ^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/tool-attributes-disabled-2.rs b/src/test/ui/tool-attributes-disabled-2.rs new file mode 100644 index 0000000000000..160dda05b1ed6 --- /dev/null +++ b/src/test/ui/tool-attributes-disabled-2.rs @@ -0,0 +1,19 @@ +// 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. + +// If macro modularization (`use_extern_macros`) is not enabled, +// then tool attributes are treated as custom attributes. + +// compile-pass + +#![feature(custom_attribute)] + +#[rustfmt::bar] +fn main() {} diff --git a/src/test/ui/tool-attributes-misplaced-1.rs b/src/test/ui/tool-attributes-misplaced-1.rs new file mode 100644 index 0000000000000..b335535242379 --- /dev/null +++ b/src/test/ui/tool-attributes-misplaced-1.rs @@ -0,0 +1,28 @@ +// 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(tool_attributes)] + +type A = rustfmt; //~ ERROR expected type, found tool module `rustfmt` +type B = rustfmt::skip; //~ ERROR expected type, found non-macro attribute `rustfmt::skip` + +#[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope +struct S; + +#[rustfmt] //~ ERROR cannot find attribute macro `rustfmt` in this scope +fn check() {} + +#[rustfmt::skip] // OK +fn main() { + rustfmt; //~ ERROR expected value, found tool module `rustfmt` + rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope + + rustfmt::skip; //~ ERROR expected value, found non-macro attribute `rustfmt::skip` +} diff --git a/src/test/ui/tool-attributes-misplaced-1.stderr b/src/test/ui/tool-attributes-misplaced-1.stderr new file mode 100644 index 0000000000000..b9e61121406ed --- /dev/null +++ b/src/test/ui/tool-attributes-misplaced-1.stderr @@ -0,0 +1,46 @@ +error: cannot find derive macro `rustfmt` in this scope + --> $DIR/tool-attributes-misplaced-1.rs:16:10 + | +LL | #[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope + | ^^^^^^^ + +error: cannot find attribute macro `rustfmt` in this scope + --> $DIR/tool-attributes-misplaced-1.rs:19:3 + | +LL | #[rustfmt] //~ ERROR cannot find attribute macro `rustfmt` in this scope + | ^^^^^^^ + +error: cannot find macro `rustfmt!` in this scope + --> $DIR/tool-attributes-misplaced-1.rs:25:5 + | +LL | rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope + | ^^^^^^^ + +error[E0573]: expected type, found tool module `rustfmt` + --> $DIR/tool-attributes-misplaced-1.rs:13:10 + | +LL | type A = rustfmt; //~ ERROR expected type, found tool module `rustfmt` + | ^^^^^^^ not a type + +error[E0573]: expected type, found non-macro attribute `rustfmt::skip` + --> $DIR/tool-attributes-misplaced-1.rs:14:10 + | +LL | type B = rustfmt::skip; //~ ERROR expected type, found non-macro attribute `rustfmt::skip` + | ^^^^^^^^^^^^^ not a type + +error[E0423]: expected value, found tool module `rustfmt` + --> $DIR/tool-attributes-misplaced-1.rs:24:5 + | +LL | rustfmt; //~ ERROR expected value, found tool module `rustfmt` + | ^^^^^^^ not a value + +error[E0423]: expected value, found non-macro attribute `rustfmt::skip` + --> $DIR/tool-attributes-misplaced-1.rs:27:5 + | +LL | rustfmt::skip; //~ ERROR expected value, found non-macro attribute `rustfmt::skip` + | ^^^^^^^^^^^^^ not a value + +error: aborting due to 7 previous errors + +Some errors occurred: E0423, E0573. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/tool-attributes-misplaced-2.rs b/src/test/ui/tool-attributes-misplaced-2.rs new file mode 100644 index 0000000000000..3bb0e3dc34382 --- /dev/null +++ b/src/test/ui/tool-attributes-misplaced-2.rs @@ -0,0 +1,18 @@ +// 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(tool_attributes)] + +#[derive(rustfmt::skip)] //~ ERROR expected a macro, found non-macro attribute +struct S; + +fn main() { + rustfmt::skip!(); //~ ERROR expected a macro, found non-macro attribute +} diff --git a/src/test/ui/tool-attributes-misplaced-2.stderr b/src/test/ui/tool-attributes-misplaced-2.stderr new file mode 100644 index 0000000000000..66452267e947b --- /dev/null +++ b/src/test/ui/tool-attributes-misplaced-2.stderr @@ -0,0 +1,14 @@ +error: expected a macro, found non-macro attribute + --> $DIR/tool-attributes-misplaced-2.rs:13:10 + | +LL | #[derive(rustfmt::skip)] //~ ERROR expected a macro, found non-macro attribute + | ^^^^^^^^^^^^^ + +error: expected a macro, found non-macro attribute + --> $DIR/tool-attributes-misplaced-2.rs:17:5 + | +LL | rustfmt::skip!(); //~ ERROR expected a macro, found non-macro attribute + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/tool-attributes-shadowing.rs b/src/test/ui/tool-attributes-shadowing.rs new file mode 100644 index 0000000000000..7913c9f40b553 --- /dev/null +++ b/src/test/ui/tool-attributes-shadowing.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. + +#![feature(tool_attributes, proc_macro_path_invoc)] + +mod rustfmt {} + +#[rustfmt::skip] //~ ERROR failed to resolve. Could not find `skip` in `rustfmt` +fn main() {} diff --git a/src/test/ui/tool-attributes-shadowing.stderr b/src/test/ui/tool-attributes-shadowing.stderr new file mode 100644 index 0000000000000..f668d677f7a20 --- /dev/null +++ b/src/test/ui/tool-attributes-shadowing.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve. Could not find `skip` in `rustfmt` + --> $DIR/tool-attributes-shadowing.rs:15:12 + | +LL | #[rustfmt::skip] //~ ERROR failed to resolve. Could not find `skip` in `rustfmt` + | ^^^^ Could not find `skip` in `rustfmt` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`.