diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index b299b786b35a8..556757ec84daf 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -15,9 +15,8 @@ //! of individual objects while the arena itself is still alive. The benefit //! of an arena is very fast allocation; just a pointer bump. //! -//! This crate has two arenas implemented: `TypedArena`, which is a simpler -//! arena but can only hold objects of a single type, and `Arena`, which is a -//! more complex, slower arena which can hold objects of any type. +//! This crate implements `TypedArena`, a simple arena that can only hold +//! objects of a single type. #![crate_name = "arena"] #![unstable(feature = "rustc_private", issue = "27812")] @@ -51,8 +50,11 @@ use std::ptr; use alloc::heap; use alloc::raw_vec::RawVec; -/// A faster arena that can hold objects of only one type. +/// An arena that can hold objects of only one type. pub struct TypedArena { + /// The capacity of the first chunk (once it is allocated). + first_chunk_capacity: usize, + /// A pointer to the next object to be allocated. ptr: Cell<*mut T>, @@ -60,7 +62,7 @@ pub struct TypedArena { /// reached, a new chunk is allocated. end: Cell<*mut T>, - /// A vector arena segments. + /// A vector of arena chunks. chunks: RefCell>>, /// Marker indicating that dropping the arena causes its owned @@ -69,7 +71,7 @@ pub struct TypedArena { } struct TypedArenaChunk { - /// Pointer to the next arena segment. + /// The raw storage for the arena chunk. storage: RawVec, } @@ -117,7 +119,7 @@ impl TypedArenaChunk { const PAGE: usize = 4096; impl TypedArena { - /// Creates a new `TypedArena` with preallocated space for many objects. + /// Creates a new `TypedArena`. #[inline] pub fn new() -> TypedArena { // Reserve at least one page. @@ -125,18 +127,18 @@ impl TypedArena { TypedArena::with_capacity(PAGE / elem_size) } - /// Creates a new `TypedArena` with preallocated space for the given number of - /// objects. + /// Creates a new `TypedArena`. Each chunk used within the arena will have + /// space for at least the given number of objects. #[inline] pub fn with_capacity(capacity: usize) -> TypedArena { - unsafe { - let chunk = TypedArenaChunk::::new(cmp::max(1, capacity)); - TypedArena { - ptr: Cell::new(chunk.start()), - end: Cell::new(chunk.end()), - chunks: RefCell::new(vec![chunk]), - _own: PhantomData, - } + TypedArena { + first_chunk_capacity: cmp::max(1, capacity), + // We set both `ptr` and `end` to 0 so that the first call to + // alloc() will trigger a grow(). + ptr: Cell::new(0 as *mut T), + end: Cell::new(0 as *mut T), + chunks: RefCell::new(vec![]), + _own: PhantomData, } } @@ -171,16 +173,22 @@ impl TypedArena { fn grow(&self) { unsafe { let mut chunks = self.chunks.borrow_mut(); - let prev_capacity = chunks.last().unwrap().storage.cap(); - let new_capacity = prev_capacity.checked_mul(2).unwrap(); - if chunks.last_mut().unwrap().storage.double_in_place() { - self.end.set(chunks.last().unwrap().end()); + let (chunk, new_capacity); + if let Some(last_chunk) = chunks.last_mut() { + if last_chunk.storage.double_in_place() { + self.end.set(last_chunk.end()); + return; + } else { + let prev_capacity = last_chunk.storage.cap(); + new_capacity = prev_capacity.checked_mul(2).unwrap(); + } } else { - let chunk = TypedArenaChunk::::new(new_capacity); - self.ptr.set(chunk.start()); - self.end.set(chunk.end()); - chunks.push(chunk); + new_capacity = self.first_chunk_capacity; } + chunk = TypedArenaChunk::::new(new_capacity); + self.ptr.set(chunk.start()); + self.end.set(chunk.end()); + chunks.push(chunk); } } /// Clears the arena. Deallocates all but the longest chunk which may be reused. @@ -188,12 +196,14 @@ impl TypedArena { unsafe { // Clear the last chunk, which is partially filled. let mut chunks_borrow = self.chunks.borrow_mut(); - let last_idx = chunks_borrow.len() - 1; - self.clear_last_chunk(&mut chunks_borrow[last_idx]); - // If `T` is ZST, code below has no effect. - for mut chunk in chunks_borrow.drain(..last_idx) { - let cap = chunk.storage.cap(); - chunk.destroy(cap); + if let Some(mut last_chunk) = chunks_borrow.pop() { + self.clear_last_chunk(&mut last_chunk); + // If `T` is ZST, code below has no effect. + for mut chunk in chunks_borrow.drain(..) { + let cap = chunk.storage.cap(); + chunk.destroy(cap); + } + chunks_borrow.push(last_chunk); } } } @@ -230,13 +240,14 @@ impl Drop for TypedArena { unsafe { // Determine how much was filled. let mut chunks_borrow = self.chunks.borrow_mut(); - let mut last_chunk = chunks_borrow.pop().unwrap(); - // Drop the contents of the last chunk. - self.clear_last_chunk(&mut last_chunk); - // The last chunk will be dropped. Destroy all other chunks. - for chunk in chunks_borrow.iter_mut() { - let cap = chunk.storage.cap(); - chunk.destroy(cap); + if let Some(mut last_chunk) = chunks_borrow.pop() { + // Drop the contents of the last chunk. + self.clear_last_chunk(&mut last_chunk); + // The last chunk will be dropped. Destroy all other chunks. + for chunk in chunks_borrow.iter_mut() { + let cap = chunk.storage.cap(); + chunk.destroy(cap); + } } // RawVec handles deallocation of `last_chunk` and `self.chunks`. } @@ -260,6 +271,12 @@ mod tests { z: i32, } + #[test] + pub fn test_unused() { + let arena: TypedArena = TypedArena::new(); + assert!(arena.chunks.borrow().is_empty()); + } + #[test] fn test_arena_alloc_nested() { struct Inner { diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 5cdf4ee88c00c..be0e72efe2e92 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -168,7 +168,7 @@ impl [T] { core_slice::SliceExt::len(self) } - /// Returns true if the slice has a length of 0 + /// Returns true if the slice has a length of 0. /// /// # Example /// @@ -402,7 +402,7 @@ impl [T] { core_slice::SliceExt::get_unchecked_mut(self, index) } - /// Returns an raw pointer to the slice's buffer + /// Returns an raw pointer to the slice's buffer. /// /// The caller must ensure that the slice outlives the pointer this /// function returns, or else it will end up pointing to garbage. @@ -468,7 +468,7 @@ impl [T] { /// /// # Examples /// - /// ```rust + /// ``` /// let mut v = ["a", "b", "c", "d"]; /// v.swap(1, 3); /// assert!(v == ["a", "d", "c", "b"]); @@ -483,7 +483,7 @@ impl [T] { /// /// # Example /// - /// ```rust + /// ``` /// let mut v = [1, 2, 3]; /// v.reverse(); /// assert!(v == [3, 2, 1]); @@ -567,9 +567,9 @@ impl [T] { } /// Returns an iterator over `size` elements of the slice at a - /// time. The chunks are slices and do not overlap. If `size` does not divide the - /// length of the slice, then the last chunk will not have length - /// `size`. + /// time. The chunks are slices and do not overlap. If `size` does + /// not divide the length of the slice, then the last chunk will + /// not have length `size`. /// /// # Panics /// @@ -656,7 +656,7 @@ impl [T] { /// /// # Examples /// - /// ```rust + /// ``` /// let mut v = [1, 2, 3, 4, 5, 6]; /// /// // scoped to restrict the lifetime of the borrows @@ -754,7 +754,7 @@ impl [T] { } /// Returns an iterator over subslices separated by elements that match - /// `pred`, limited to returning at most `n` items. The matched element is + /// `pred`, limited to returning at most `n` items. The matched element is /// not contained in the subslices. /// /// The last element returned, if any, will contain the remainder of the @@ -781,7 +781,7 @@ impl [T] { } /// Returns an iterator over subslices separated by elements that match - /// `pred`, limited to returning at most `n` items. The matched element is + /// `pred`, limited to returning at most `n` items. The matched element is /// not contained in the subslices. /// /// The last element returned, if any, will contain the remainder of the @@ -835,7 +835,7 @@ impl [T] { /// Returns an iterator over subslices separated by elements that match /// `pred` limited to returning at most `n` items. This starts at the end of - /// the slice and works backwards. The matched element is not contained in + /// the slice and works backwards. The matched element is not contained in /// the subslices. /// /// The last element returned, if any, will contain the remainder of the @@ -922,9 +922,9 @@ impl [T] { /// /// Looks up a series of four elements. The first is found, with a /// uniquely determined position; the second and third are not - /// found; the fourth could match any position in `[1,4]`. + /// found; the fourth could match any position in `[1, 4]`. /// - /// ```rust + /// ``` /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; /// /// assert_eq!(s.binary_search(&13), Ok(9)); @@ -956,9 +956,9 @@ impl [T] { /// /// Looks up a series of four elements. The first is found, with a /// uniquely determined position; the second and third are not - /// found; the fourth could match any position in `[1,4]`. + /// found; the fourth could match any position in `[1, 4]`. /// - /// ```rust + /// ``` /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; /// /// let seek = 13; @@ -982,21 +982,23 @@ impl [T] { /// Binary search a sorted slice with a key extraction function. /// /// Assumes that the slice is sorted by the key, for instance with - /// `sort_by_key` using the same key extraction function. + /// [`sort_by_key`] using the same key extraction function. /// /// If a matching value is found then returns `Ok`, containing the /// index for the matched element; if no match is found then `Err` /// is returned, containing the index where a matching element could /// be inserted while maintaining sorted order. /// + /// [`sort_by_key`]: primitive.slice.html#method.sort_by_key + /// /// # Examples /// /// Looks up a series of four elements in a slice of pairs sorted by /// their second elements. The first is found, with a uniquely /// determined position; the second and third are not found; the - /// fourth could match any position in `[1,4]`. + /// fourth could match any position in `[1, 4]`. /// - /// ```rust + /// ``` /// let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1), /// (1, 2), (2, 3), (4, 5), (5, 8), (3, 13), /// (1, 21), (2, 34), (4, 55)]; @@ -1023,7 +1025,7 @@ impl [T] { /// /// # Examples /// - /// ```rust + /// ``` /// let mut v = [-5, 4, 1, -3, 2]; /// /// v.sort(); @@ -1037,7 +1039,7 @@ impl [T] { self.sort_by(|a, b| a.cmp(b)) } - /// Sorts the slice, in place, using `key` to extract a key by which to + /// Sorts the slice, in place, using `f` to extract a key by which to /// order the sort by. /// /// This sort is stable and `O(n log n)` worst-case but allocates @@ -1045,7 +1047,7 @@ impl [T] { /// /// # Examples /// - /// ```rust + /// ``` /// let mut v = [-5i32, 4, 1, -3, 2]; /// /// v.sort_by_key(|k| k.abs()); @@ -1067,7 +1069,7 @@ impl [T] { /// /// # Examples /// - /// ```rust + /// ``` /// let mut v = [5, 4, 1, 3, 2]; /// v.sort_by(|a, b| a.cmp(b)); /// assert!(v == [1, 2, 3, 4, 5]); @@ -1094,7 +1096,7 @@ impl [T] { /// /// # Example /// - /// ```rust + /// ``` /// let mut dst = [0, 0, 0]; /// let src = [1, 2, 3]; /// @@ -1116,7 +1118,7 @@ impl [T] { /// /// # Example /// - /// ```rust + /// ``` /// let mut dst = [0, 0, 0]; /// let src = [1, 2, 3]; /// diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 6a6b450e51863..96efe1a03e351 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -697,7 +697,7 @@ impl str { /// /// Basic usage: /// - /// ```rust + /// ``` /// let bananas = "bananas"; /// /// assert!(bananas.ends_with("anas")); @@ -900,7 +900,7 @@ impl str { /// /// It does _not_ give you: /// - /// ```rust,ignore + /// ```,ignore /// assert_eq!(d, &["a", "b", "c"]); /// ``` /// diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 773e94f1b414e..fd518fdd33013 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -21,7 +21,7 @@ //! //! There are multiple ways to create a new `String` from a string literal: //! -//! ```rust +//! ``` //! let s = "Hello".to_string(); //! //! let s = String::from("world"); @@ -31,7 +31,7 @@ //! You can create a new `String` from an existing one by concatenating with //! `+`: //! -//! ```rust +//! ``` //! let s = "Hello".to_string(); //! //! let message = s + " world!"; @@ -40,7 +40,7 @@ //! If you have a vector of valid UTF-8 bytes, you can make a `String` out of //! it. You can do the reverse too. //! -//! ```rust +//! ``` //! let sparkle_heart = vec![240, 159, 146, 150]; //! //! // We know these bytes are valid, so we'll use `unwrap()`. diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index f8b4a92df2c5d..63494c5b73c7a 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1770,7 +1770,7 @@ impl IntoIter { /// /// # Examples /// - /// ```rust + /// ``` /// # #![feature(vec_into_iter_as_slice)] /// let vec = vec!['a', 'b', 'c']; /// let mut into_iter = vec.into_iter(); @@ -1789,7 +1789,7 @@ impl IntoIter { /// /// # Examples /// - /// ```rust + /// ``` /// # #![feature(vec_into_iter_as_slice)] /// let vec = vec!['a', 'b', 'c']; /// let mut into_iter = vec.into_iter(); diff --git a/src/libcore/option.rs b/src/libcore/option.rs index b9fb2dc90c728..cb18feff73422 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -296,16 +296,14 @@ impl Option { /// Moves the value `v` out of the `Option` if it is `Some(v)`. /// - /// # Panics - /// - /// Panics if the self value equals `None`. - /// - /// # Safety note - /// /// In general, because this function may panic, its use is discouraged. /// Instead, prefer to use pattern matching and handle the `None` /// case explicitly. /// + /// # Panics + /// + /// Panics if the self value equals `None`. + /// /// # Examples /// /// ``` diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index d2f3eea85f228..bc599a8207656 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -81,6 +81,7 @@ pub trait CodeMapper { fn span_to_string(&self, sp: Span) -> String; fn span_to_filename(&self, sp: Span) -> FileName; fn macro_backtrace(&self, span: Span) -> Vec; + fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option; } impl CodeSuggestion { diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index 67e5ec2616d29..0fd208c95d4db 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -54,6 +54,7 @@ use syntax::ast; use syntax::attr; use syntax::attr::IntType; use abi::FAT_PTR_ADDR; +use base; use build::*; use common::*; use debuginfo::DebugLoc; @@ -963,16 +964,32 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, Store(bcx, C_null(llptrty), val); } } - StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => { + StructWrappedNullablePointer { nndiscr, ref discrfield, ref nonnull, .. } => { if discr != nndiscr { - let llptrptr = GEPi(bcx, val, &discrfield[..]); - let llptrty = val_ty(llptrptr).element_type(); - Store(bcx, C_null(llptrty), llptrptr); + if target_sets_discr_via_memset(bcx) { + // Issue #34427: As workaround for LLVM bug on + // ARM, use memset of 0 on whole struct rather + // than storing null to single target field. + let b = B(bcx); + let llptr = b.pointercast(val, Type::i8(b.ccx).ptr_to()); + let fill_byte = C_u8(b.ccx, 0); + let size = C_uint(b.ccx, nonnull.size); + let align = C_i32(b.ccx, nonnull.align as i32); + base::call_memset(&b, llptr, fill_byte, size, align, false); + } else { + let llptrptr = GEPi(bcx, val, &discrfield[..]); + let llptrty = val_ty(llptrptr).element_type(); + Store(bcx, C_null(llptrty), llptrptr); + } } } } } +fn target_sets_discr_via_memset<'blk, 'tcx>(bcx: Block<'blk, 'tcx>) -> bool { + bcx.sess().target.target.arch == "arm" || bcx.sess().target.target.arch == "aarch64" +} + fn assert_discr_in_range(ity: IntType, min: Disr, max: Disr, discr: Disr) { match ity { attr::UnsignedInt(_) => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index baa084212a2d9..7c9467bc5fed6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3094,7 +3094,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(field_name) = Self::suggest_field_name(variant, &field.name, skip_fields.collect()) { - err.span_label(field.name.span,&format!("did you mean `{}`?",field_name)); + err.span_label(field.name.span, + &format!("field does not exist - did you mean `{}`?", field_name)); + } else { + match ty.sty { + ty::TyAdt(adt, ..) if adt.is_enum() => { + err.span_label(field.name.span, &format!("`{}::{}` does not have this field", + ty, variant.name.as_str())); + } + _ => { + err.span_label(field.name.span, &format!("`{}` does not have this field", ty)); + } + } }; err.emit(); } diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index 246c57ab23871..10a0c567e142f 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -83,7 +83,7 @@ impl Duration { /// Returns the number of whole seconds represented by this duration. /// - /// The extra precision represented by this duration is ignored (e.g. extra + /// The extra precision represented by this duration is ignored (i.e. extra /// nanoseconds are not represented in the returned value). #[stable(feature = "duration", since = "1.3.0")] #[inline] @@ -93,7 +93,7 @@ impl Duration { /// /// This method does **not** return the length of the duration when /// represented by nanoseconds. The returned number always represents a - /// fractional portion of a second (e.g. it is less than one billion). + /// fractional portion of a second (i.e. it is less than one billion). #[stable(feature = "duration", since = "1.3.0")] #[inline] pub fn subsec_nanos(&self) -> u32 { self.nanos } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index cd6f2874954b8..6d68ce3646d53 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -364,6 +364,46 @@ impl CodeMap { } } + /// Returns `Some(span)`, a union of the lhs and rhs span. The lhs must precede the rhs. If + /// there are gaps between lhs and rhs, the resulting union will cross these gaps. + /// For this to work, the spans have to be: + /// * the expn_id of both spans much match + /// * the lhs span needs to end on the same line the rhs span begins + /// * the lhs span must start at or before the rhs span + pub fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option { + use std::cmp; + + // make sure we're at the same expansion id + if sp_lhs.expn_id != sp_rhs.expn_id { + return None; + } + + let lhs_end = match self.lookup_line(sp_lhs.hi) { + Ok(x) => x, + Err(_) => return None + }; + let rhs_begin = match self.lookup_line(sp_rhs.lo) { + Ok(x) => x, + Err(_) => return None + }; + + // if we must cross lines to merge, don't merge + if lhs_end.line != rhs_begin.line { + return None; + } + + // ensure these follow the expected order and we don't overlap + if (sp_lhs.lo <= sp_rhs.lo) && (sp_lhs.hi <= sp_rhs.lo) { + Some(Span { + lo: cmp::min(sp_lhs.lo, sp_rhs.lo), + hi: cmp::max(sp_lhs.hi, sp_rhs.hi), + expn_id: sp_lhs.expn_id, + }) + } else { + None + } + } + pub fn span_to_string(&self, sp: Span) -> String { if sp == COMMAND_LINE_SP { return "".to_string(); @@ -819,6 +859,9 @@ impl CodeMapper for CodeMap { fn macro_backtrace(&self, span: Span) -> Vec { self.macro_backtrace(span) } + fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option { + self.merge_spans(sp_lhs, sp_rhs) + } } // _____________________________________________________________________________ @@ -1072,6 +1115,40 @@ mod tests { blork.rs:1:1: 1:12\n `first line.`\n"); } + /// Test merging two spans on the same line + #[test] + fn span_merging() { + let cm = CodeMap::new(); + let inputtext = "bbbb BB bb CCC\n"; + let selection1 = " ~~ \n"; + let selection2 = " ~~~\n"; + cm.new_filemap_and_lines("blork.rs", None, inputtext); + let span1 = span_from_selection(inputtext, selection1); + let span2 = span_from_selection(inputtext, selection2); + + if let Some(sp) = cm.merge_spans(span1, span2) { + let sstr = cm.span_to_expanded_string(sp); + assert_eq!(sstr, "blork.rs:1:6: 1:15\n`BB bb CCC`\n"); + } + else { + assert!(false); + } + } + + /// Test failing to merge two spans on different lines + #[test] + fn span_merging_fail() { + let cm = CodeMap::new(); + let inputtext = "bbbb BB\ncc CCC\n"; + let selection1 = " ~~\n \n"; + let selection2 = " \n ~~~\n"; + cm.new_filemap_and_lines("blork.rs", None, inputtext); + let span1 = span_from_selection(inputtext, selection1); + let span2 = span_from_selection(inputtext, selection2); + + assert!(cm.merge_spans(span1, span2).is_none()); + } + /// Returns the span corresponding to the `n`th occurrence of /// `substring` in `source_text`. trait CodeMapExtension { diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index a0defbc09dc04..9eac024edb17e 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -125,8 +125,8 @@ impl<'a> Parser<'a> { self.expect(&token::OpenDelim(token::Bracket))?; let meta_item = self.parse_meta_item()?; - let hi = self.last_span.hi; self.expect(&token::CloseDelim(token::Bracket))?; + let hi = self.last_span.hi; (mk_sp(lo, hi), meta_item, style) } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index d835f8058fa0e..0c0c62275d4db 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -96,24 +96,6 @@ impl Span { self.lo == other.lo && self.hi == other.hi } - /// Returns `Some(span)`, a union of `self` and `other`, on overlap. - pub fn merge(self, other: Span) -> Option { - if self.expn_id != other.expn_id { - return None; - } - - if (self.lo <= other.lo && self.hi > other.lo) || - (self.lo >= other.lo && self.lo < other.hi) { - Some(Span { - lo: cmp::min(self.lo, other.lo), - hi: cmp::max(self.hi, other.hi), - expn_id: self.expn_id, - }) - } else { - None - } - } - /// Returns `Some(span)`, where the start is trimmed by the end of `other` pub fn trim_start(self, other: Span) -> Option { if self.hi > other.hi { diff --git a/src/test/compile-fail/E0559.rs b/src/test/compile-fail/E0559.rs index aeeeae4222813..fa6c885843e4c 100644 --- a/src/test/compile-fail/E0559.rs +++ b/src/test/compile-fail/E0559.rs @@ -15,5 +15,5 @@ enum Field { fn main() { let s = Field::Fool { joke: 0 }; //~^ ERROR E0559 - //~| NOTE did you mean `x`? + //~| NOTE field does not exist - did you mean `x`? } diff --git a/src/test/compile-fail/E560.rs b/src/test/compile-fail/E0560.rs similarity index 82% rename from src/test/compile-fail/E560.rs rename to src/test/compile-fail/E0560.rs index ec9b86ee1f00f..c6326a0f97740 100644 --- a/src/test/compile-fail/E560.rs +++ b/src/test/compile-fail/E0560.rs @@ -13,5 +13,7 @@ struct Simba { } fn main() { - let s = Simba { mother: 1, father: 0 }; //~ ERROR E0560 + let s = Simba { mother: 1, father: 0 }; + //~^ ERROR E0560 + //~| NOTE `Simba` does not have this field } diff --git a/src/test/compile-fail/issue-19922.rs b/src/test/compile-fail/issue-19922.rs index a8350fe0986c0..d7b2f2b3f991e 100644 --- a/src/test/compile-fail/issue-19922.rs +++ b/src/test/compile-fail/issue-19922.rs @@ -15,4 +15,5 @@ enum Homura { fn main() { let homura = Homura::Akemi { kaname: () }; //~^ ERROR variant `Homura::Akemi` has no field named `kaname` + //~| NOTE field does not exist - did you mean `madoka`? } diff --git a/src/test/compile-fail/numeric-fields.rs b/src/test/compile-fail/numeric-fields.rs index c4aff9471b8a1..a67707257d2f2 100644 --- a/src/test/compile-fail/numeric-fields.rs +++ b/src/test/compile-fail/numeric-fields.rs @@ -13,8 +13,12 @@ struct S(u8, u16); fn main() { - let s = S{0b1: 10, 0: 11}; //~ ERROR struct `S` has no field named `0b1` + let s = S{0b1: 10, 0: 11}; + //~^ ERROR struct `S` has no field named `0b1` + //~| NOTE field does not exist - did you mean `1`? match s { - S{0: a, 0x1: b, ..} => {} //~ ERROR does not have a field named `0x1` + S{0: a, 0x1: b, ..} => {} + //~^ ERROR does not have a field named `0x1` + //~| NOTE struct `S::{{constructor}}` does not have field `0x1` } } diff --git a/src/test/compile-fail/struct-fields-hints-no-dupe.rs b/src/test/compile-fail/struct-fields-hints-no-dupe.rs index f25f01af33fd1..de78503d9044f 100644 --- a/src/test/compile-fail/struct-fields-hints-no-dupe.rs +++ b/src/test/compile-fail/struct-fields-hints-no-dupe.rs @@ -19,7 +19,7 @@ fn main() { foo : 5, bar : 42, //~^ ERROR struct `A` has no field named `bar` - //~| NOTE did you mean `barr`? + //~| NOTE field does not exist - did you mean `barr`? car : 9, }; } diff --git a/src/test/compile-fail/struct-fields-hints.rs b/src/test/compile-fail/struct-fields-hints.rs index 62ec6e6b0d249..628f03f3272ca 100644 --- a/src/test/compile-fail/struct-fields-hints.rs +++ b/src/test/compile-fail/struct-fields-hints.rs @@ -19,6 +19,6 @@ fn main() { foo : 5, bar : 42, //~^ ERROR struct `A` has no field named `bar` - //~| NOTE did you mean `car`? + //~| NOTE field does not exist - did you mean `car`? }; } diff --git a/src/test/compile-fail/struct-fields-too-many.rs b/src/test/compile-fail/struct-fields-too-many.rs index 5d16573f2f1e3..0848ada731a65 100644 --- a/src/test/compile-fail/struct-fields-too-many.rs +++ b/src/test/compile-fail/struct-fields-too-many.rs @@ -15,6 +15,8 @@ struct BuildData { fn main() { let foo = BuildData { foo: 0, - bar: 0 //~ ERROR struct `BuildData` has no field named `bar` + bar: 0 + //~^ ERROR struct `BuildData` has no field named `bar` + //~| NOTE `BuildData` does not have this field }; } diff --git a/src/test/compile-fail/suggest-private-fields.rs b/src/test/compile-fail/suggest-private-fields.rs index 906bfc78498e4..3672e0e90c2a2 100644 --- a/src/test/compile-fail/suggest-private-fields.rs +++ b/src/test/compile-fail/suggest-private-fields.rs @@ -24,18 +24,18 @@ fn main () { let k = B { aa: 20, //~^ ERROR struct `xc::B` has no field named `aa` - //~| NOTE did you mean `a`? + //~| NOTE field does not exist - did you mean `a`? bb: 20, //~^ ERROR struct `xc::B` has no field named `bb` - //~| NOTE did you mean `a`? + //~| NOTE field does not exist - did you mean `a`? }; // local crate struct let l = A { aa: 20, //~^ ERROR struct `A` has no field named `aa` - //~| NOTE did you mean `a`? + //~| NOTE field does not exist - did you mean `a`? bb: 20, //~^ ERROR struct `A` has no field named `bb` - //~| NOTE did you mean `b`? + //~| NOTE field does not exist - did you mean `b`? }; } diff --git a/src/test/compile-fail/union/union-fields.rs b/src/test/compile-fail/union/union-fields.rs index a1721dda7decb..3ee95c2ef4258 100644 --- a/src/test/compile-fail/union/union-fields.rs +++ b/src/test/compile-fail/union/union-fields.rs @@ -21,6 +21,7 @@ fn main() { let u = U { a: 0, b: 1 }; //~ ERROR union expressions should have exactly one field let u = U { a: 0, b: 1, c: 2 }; //~ ERROR union expressions should have exactly one field //~^ ERROR union `U` has no field named `c` + //~| NOTE `U` does not have this field let u = U { ..u }; //~ ERROR union expressions should have exactly one field //~^ ERROR functional record update syntax requires a struct @@ -29,6 +30,7 @@ fn main() { let U { a, b } = u; //~ ERROR union patterns should have exactly one field let U { a, b, c } = u; //~ ERROR union patterns should have exactly one field //~^ ERROR union `U` does not have a field named `c` + //~| NOTE union `U` does not have field `c` let U { .. } = u; //~ ERROR union patterns should have exactly one field //~^ ERROR `..` cannot be used in union patterns let U { a, .. } = u; //~ ERROR `..` cannot be used in union patterns diff --git a/src/test/compile-fail/union/union-suggest-field.rs b/src/test/compile-fail/union/union-suggest-field.rs index 92811b6b5be11..ce421428d883b 100644 --- a/src/test/compile-fail/union/union-suggest-field.rs +++ b/src/test/compile-fail/union/union-suggest-field.rs @@ -21,7 +21,7 @@ impl U { fn main() { let u = U { principle: 0 }; //~^ ERROR union `U` has no field named `principle` - //~| NOTE did you mean `principal`? + //~| NOTE field does not exist - did you mean `principal`? let w = u.principial; //~ ERROR attempted access of field `principial` on type `U` //~^ HELP did you mean `principal`? diff --git a/src/test/run-pass/issue-34427.rs b/src/test/run-pass/issue-34427.rs new file mode 100644 index 0000000000000..6bf8a2ac6a72d --- /dev/null +++ b/src/test/run-pass/issue-34427.rs @@ -0,0 +1,26 @@ +// Copyright 2016 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. + +// Issue #34427: On ARM, the code in `foo` at one time was generating +// a machine code instruction of the form: `str r0, [r0, rN]!` (for +// some N), which is not legal because the source register and base +// register cannot be identical in the preindexed form signalled by +// the `!`. +// +// See LLVM bug: https://llvm.org/bugs/show_bug.cgi?id=28809 + +#[inline(never)] +fn foo(n: usize) -> Vec> { + (0..n).map(|_| None).collect() +} + +fn main() { + let _ = (foo(10), foo(32)); +} diff --git a/src/test/ui/span/issue-36530.rs b/src/test/ui/span/issue-36530.rs new file mode 100644 index 0000000000000..893c2168c2e16 --- /dev/null +++ b/src/test/ui/span/issue-36530.rs @@ -0,0 +1,14 @@ +// Copyright 2014 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. + +#[foo] +mod foo { + #![foo] +} diff --git a/src/test/ui/span/issue-36530.stderr b/src/test/ui/span/issue-36530.stderr new file mode 100644 index 0000000000000..dc6190c2e76b0 --- /dev/null +++ b/src/test/ui/span/issue-36530.stderr @@ -0,0 +1,18 @@ +error: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/issue-36530.rs:11:1 + | +11 | #[foo] + | ^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/issue-36530.rs:13:5 + | +13 | #![foo] + | ^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: aborting due to 2 previous errors +