diff --git a/Cargo.lock b/Cargo.lock index 6a2b1bc41eff0..f7d5a1a507bab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2073,6 +2073,7 @@ dependencies = [ name = "rustc-main" version = "0.0.0" dependencies = [ + "rustc_codegen_ssa 0.0.0", "rustc_driver 0.0.0", "rustc_target 0.0.0", ] @@ -2169,7 +2170,6 @@ dependencies = [ "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_codegen_ssa 0.0.0", "rustc_llvm 0.0.0", ] @@ -2177,10 +2177,27 @@ dependencies = [ name = "rustc_codegen_ssa" version = "0.0.0" dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc 0.0.0", "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_allocator 0.0.0", + "rustc_apfloat 0.0.0", + "rustc_codegen_utils 0.0.0", + "rustc_data_structures 0.0.0", + "rustc_errors 0.0.0", + "rustc_fs_util 0.0.0", + "rustc_incremental 0.0.0", + "rustc_mir 0.0.0", + "rustc_target 0.0.0", + "serialize 0.0.0", + "syntax 0.0.0", + "syntax_pos 0.0.0", ] [[package]] diff --git a/RELEASES.md b/RELEASES.md index a455186859f86..da09af3edfe8a 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -74,6 +74,14 @@ Cargo [cargo-rename-reference]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml [const-reference]: https://doc.rust-lang.org/reference/items/functions.html#const-functions +Version 1.30.1 (2018-11-08) +=========================== + +- [Fixed overflow ICE in rustdoc][54199] +- [Cap Cargo progress bar width at 60 in MSYS terminals][cargo/6122] + +[54199]: https://github.com/rust-lang/rust/pull/54199 +[cargo/6122]: https://github.com/rust-lang/cargo/pull/6122 Version 1.30.0 (2018-10-25) ========================== diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh index f2664e6d196c7..8345ab3bc3376 100755 --- a/src/ci/init_repo.sh +++ b/src/ci/init_repo.sh @@ -55,6 +55,7 @@ function fetch_submodule { } included="src/llvm src/llvm-emscripten src/doc/book src/doc/rust-by-example" +included="$included src/tools/lld src/tools/clang src/tools/lldb" modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)" modules=($modules) use_git="" diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index 27275ba37957e..4c74653654723 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -18,6 +18,8 @@ if sys.version_info[0] >= 3: xrange = range +rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string = True) + #=============================================================================== # GDB Pretty Printing Module for Rust #=============================================================================== @@ -99,27 +101,9 @@ def rust_pretty_printer_lookup_function(gdb_val): val = GdbValue(gdb_val) type_kind = val.type.get_type_kind() - if type_kind == rustpp.TYPE_KIND_EMPTY: - return RustEmptyPrinter(val) - - if type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT: - return RustStructPrinter(val, - omit_first_field = False, - omit_type_name = False, - is_tuple_like = False) - - if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT: - return RustStructPrinter(val, - omit_first_field = True, - omit_type_name = False, - is_tuple_like = False) - if type_kind == rustpp.TYPE_KIND_SLICE: return RustSlicePrinter(val) - if type_kind == rustpp.TYPE_KIND_STR_SLICE: - return RustStringSlicePrinter(val) - if type_kind == rustpp.TYPE_KIND_STD_VEC: return RustStdVecPrinter(val) @@ -138,6 +122,29 @@ def rust_pretty_printer_lookup_function(gdb_val): if type_kind == rustpp.TYPE_KIND_OS_STRING: return RustOsStringPrinter(val) + # Checks after this point should only be for "compiler" types -- + # things that gdb's Rust language support knows about. + if rust_enabled: + return None + + if type_kind == rustpp.TYPE_KIND_EMPTY: + return RustEmptyPrinter(val) + + if type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT: + return RustStructPrinter(val, + omit_first_field = False, + omit_type_name = False, + is_tuple_like = False) + + if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT: + return RustStructPrinter(val, + omit_first_field = True, + omit_type_name = False, + is_tuple_like = False) + + if type_kind == rustpp.TYPE_KIND_STR_SLICE: + return RustStringSlicePrinter(val) + if type_kind == rustpp.TYPE_KIND_TUPLE: return RustStructPrinter(val, omit_first_field = False, diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 509068843d193..62e1f9fcb640c 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -112,10 +112,10 @@ //! //! // next() is the only required method //! fn next(&mut self) -> Option { -//! // increment our count. This is why we started at zero. +//! // Increment our count. This is why we started at zero. //! self.count += 1; //! -//! // check to see if we've finished counting or not. +//! // Check to see if we've finished counting or not. //! if self.count < 6 { //! Some(self.count) //! } else { @@ -339,6 +339,8 @@ pub use self::sources::{RepeatWith, repeat_with}; pub use self::sources::{Empty, empty}; #[stable(feature = "iter_once", since = "1.2.0")] pub use self::sources::{Once, once}; +#[unstable(feature = "iter_unfold", issue = "55977")] +pub use self::sources::{Unfold, unfold, Successors, successors}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend}; diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 55addd86bc1ce..f0fd07b43cae0 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -166,14 +166,14 @@ macro_rules! step_impl_no_between { } step_impl_unsigned!(usize u8 u16); -#[cfg(not(target_pointer_witdth = "16"))] +#[cfg(not(target_pointer_width = "16"))] step_impl_unsigned!(u32); -#[cfg(target_pointer_witdth = "16")] +#[cfg(target_pointer_width = "16")] step_impl_no_between!(u32); step_impl_signed!([isize: usize] [i8: u8] [i16: u16]); -#[cfg(not(target_pointer_witdth = "16"))] +#[cfg(not(target_pointer_width = "16"))] step_impl_signed!([i32: u32]); -#[cfg(target_pointer_witdth = "16")] +#[cfg(target_pointer_width = "16")] step_impl_no_between!(i32); #[cfg(target_pointer_width = "64")] step_impl_unsigned!(u64); diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index 7fa3a4bcce7bb..f6a4a7a6fa80a 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -386,3 +386,164 @@ impl FusedIterator for Once {} pub fn once(value: T) -> Once { Once { inner: Some(value).into_iter() } } + +/// Creates a new iterator where each iteration calls the provided closure +/// `F: FnMut(&mut St) -> Option`. +/// +/// This allows creating a custom iterator with any behavior +/// without using the more verbose syntax of creating a dedicated type +/// and implementing the `Iterator` trait for it. +/// +/// In addition to its captures and environment, +/// the closure is given a mutable reference to some state +/// that is preserved across iterations. +/// That state starts as the given `initial_state` value. +/// +/// Note that the `Unfold` iterator doesn’t make assumptions about the behavior of the closure, +/// and therefore conservatively does not implement [`FusedIterator`], +/// or override [`Iterator::size_hint`] from its default `(0, None)`. +/// +/// [`FusedIterator`]: trait.FusedIterator.html +/// [`Iterator::size_hint`]: trait.Iterator.html#method.size_hint +/// +/// # Examples +/// +/// Let’s re-implement the counter iterator from [module-level documentation]: +/// +/// [module-level documentation]: index.html +/// +/// ``` +/// #![feature(iter_unfold)] +/// let counter = std::iter::unfold(0, |count| { +/// // Increment our count. This is why we started at zero. +/// *count += 1; +/// +/// // Check to see if we've finished counting or not. +/// if *count < 6 { +/// Some(*count) +/// } else { +/// None +/// } +/// }); +/// assert_eq!(counter.collect::>(), &[1, 2, 3, 4, 5]); +/// ``` +#[inline] +#[unstable(feature = "iter_unfold", issue = "55977")] +pub fn unfold(initial_state: St, f: F) -> Unfold + where F: FnMut(&mut St) -> Option +{ + Unfold { + state: initial_state, + f, + } +} + +/// An iterator where each iteration calls the provided closure `F: FnMut(&mut St) -> Option`. +/// +/// This `struct` is created by the [`unfold`] function. +/// See its documentation for more. +/// +/// [`unfold`]: fn.unfold.html +#[derive(Clone)] +#[unstable(feature = "iter_unfold", issue = "55977")] +pub struct Unfold { + state: St, + f: F, +} + +#[unstable(feature = "iter_unfold", issue = "55977")] +impl Iterator for Unfold + where F: FnMut(&mut St) -> Option +{ + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + (self.f)(&mut self.state) + } +} + +#[unstable(feature = "iter_unfold", issue = "55977")] +impl fmt::Debug for Unfold { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Unfold") + .field("state", &self.state) + .finish() + } +} + +/// Creates a new iterator where each successive item is computed based on the preceding one. +/// +/// The iterator starts with the given first item (if any) +/// and calls the given `FnMut(&T) -> Option` closure to compute each item’s successor. +/// +/// ``` +/// #![feature(iter_unfold)] +/// use std::iter::successors; +/// +/// let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10)); +/// assert_eq!(powers_of_10.collect::>(), &[1, 10, 100, 1_000, 10_000]); +/// ``` +#[unstable(feature = "iter_unfold", issue = "55977")] +pub fn successors(first: Option, succ: F) -> Successors + where F: FnMut(&T) -> Option +{ + // If this function returned `impl Iterator` + // it could be based on `unfold` and not need a dedicated type. + // However having a named `Successors` type allows it to be `Clone` when `T` and `F` are. + Successors { + next: first, + succ, + } +} + +/// An new iterator where each successive item is computed based on the preceding one. +/// +/// This `struct` is created by the [`successors`] function. +/// See its documentation for more. +/// +/// [`successors`]: fn.successors.html +#[derive(Clone)] +#[unstable(feature = "iter_unfold", issue = "55977")] +pub struct Successors { + next: Option, + succ: F, +} + +#[unstable(feature = "iter_unfold", issue = "55977")] +impl Iterator for Successors + where F: FnMut(&T) -> Option +{ + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.next.take().map(|item| { + self.next = (self.succ)(&item); + item + }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.next.is_some() { + (1, None) + } else { + (0, Some(0)) + } + } +} + +#[unstable(feature = "iter_unfold", issue = "55977")] +impl FusedIterator for Successors + where F: FnMut(&T) -> Option +{} + +#[unstable(feature = "iter_unfold", issue = "55977")] +impl fmt::Debug for Successors { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Successors") + .field("next", &self.next) + .finish() + } +} diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index a316093825ad7..89efa120a6fab 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1424,10 +1424,8 @@ fn contains_nonascii(x: usize) -> bool { (x & NONASCII_MASK) != 0 } -/// Walks through `iter` checking that it's a valid UTF-8 sequence, -/// returning `true` in that case, or, if it is invalid, `false` with -/// `iter` reset such that it is pointing at the first byte in the -/// invalid sequence. +/// Walks through `v` checking that it's a valid UTF-8 sequence, +/// returning `Ok(())` in that case, or, if it is invalid, `Err(err)`. #[inline] fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { let mut index = 0; diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index ec09071b3d0f0..495483db5551c 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1759,6 +1759,17 @@ fn test_repeat_with_take_collect() { assert_eq!(v, vec![1, 2, 4, 8, 16]); } +#[test] +fn test_successors() { + let mut powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10)); + assert_eq!(powers_of_10.by_ref().collect::>(), &[1, 10, 100, 1_000, 10_000]); + assert_eq!(powers_of_10.next(), None); + + let mut empty = successors(None::, |_| unimplemented!()); + assert_eq!(empty.next(), None); + assert_eq!(empty.next(), None); +} + #[test] fn test_fuse() { let mut it = 0..3; diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 5ac8991226898..7d62b4fa90f20 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -19,6 +19,7 @@ #![feature(flt2dec)] #![feature(fmt_internals)] #![feature(hashmap_internals)] +#![feature(iter_unfold)] #![feature(pattern)] #![feature(range_is_empty)] #![feature(raw)] diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 60b6a8bac41d3..e9d2d97e3646b 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -50,6 +50,7 @@ mod diagnostic; #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub use diagnostic::{Diagnostic, Level, MultiSpan}; +use std::ops::{Bound, RangeBounds}; use std::{ascii, fmt, iter}; use std::path::PathBuf; use rustc_data_structures::sync::Lrc; @@ -59,7 +60,7 @@ use syntax::errors::DiagnosticBuilder; use syntax::parse::{self, token}; use syntax::symbol::Symbol; use syntax::tokenstream::{self, DelimSpan}; -use syntax_pos::{Pos, FileName}; +use syntax_pos::{Pos, FileName, BytePos}; /// The main type provided by this crate, representing an abstract stream of /// tokens, or, more specifically, a sequence of token trees. @@ -1168,6 +1169,50 @@ impl Literal { pub fn set_span(&mut self, span: Span) { self.span = span; } + + /// Returns a `Span` that is a subset of `self.span()` containing only the + /// source bytes in range `range`. Returns `None` if the would-be trimmed + /// span is outside the bounds of `self`. + // FIXME(SergioBenitez): check that the byte range starts and ends at a + // UTF-8 boundary of the source. otherwise, it's likely that a panic will + // occur elsewhere when the source text is printed. + // FIXME(SergioBenitez): there is no way for the user to know what + // `self.span()` actually maps to, so this method can currently only be + // called blindly. For example, `to_string()` for the character 'c' returns + // "'\u{63}'"; there is no way for the user to know whether the source text + // was 'c' or whether it was '\u{63}'. + #[unstable(feature = "proc_macro_span", issue = "54725")] + pub fn subspan>(&self, range: R) -> Option { + let inner = self.span().0; + let length = inner.hi().to_usize() - inner.lo().to_usize(); + + let start = match range.start_bound() { + Bound::Included(&lo) => lo, + Bound::Excluded(&lo) => lo + 1, + Bound::Unbounded => 0, + }; + + let end = match range.end_bound() { + Bound::Included(&hi) => hi + 1, + Bound::Excluded(&hi) => hi, + Bound::Unbounded => length, + }; + + // Bounds check the values, preventing addition overflow and OOB spans. + if start > u32::max_value() as usize + || end > u32::max_value() as usize + || (u32::max_value() - start as u32) < inner.lo().to_u32() + || (u32::max_value() - end as u32) < inner.lo().to_u32() + || start >= end + || end > length + { + return None; + } + + let new_lo = inner.lo() + BytePos::from_usize(start); + let new_hi = inner.lo() + BytePos::from_usize(end); + Some(Span(inner.with_lo(new_lo).with_hi(new_hi))) + } } /// Prints the literal as a string that should be losslessly convertible diff --git a/src/librustc/util/profiling.rs b/src/librustc/util/profiling.rs index 37073b6e82080..dfd3f2ee184ce 100644 --- a/src/librustc/util/profiling.rs +++ b/src/librustc/util/profiling.rs @@ -93,16 +93,27 @@ macro_rules! define_categories { $( let (hits, total) = self.query_counts.$name; + //normalize hits to 0% + let hit_percent = + if total > 0 { + ((hits as f32) / (total as f32)) * 100.0 + } else { + 0.0 + }; + json.push_str(&format!( "{{ \"category\": {}, \"time_ms\": {}, - \"query_count\": {}, \"query_hits\": {} }}", + \"query_count\": {}, \"query_hits\": {} }},", stringify!($name), self.times.$name / 1_000_000, total, - format!("{:.2}", (((hits as f32) / (total as f32)) * 100.0)) + format!("{:.2}", hit_percent) )); )* + //remove the trailing ',' character + json.pop(); + json.push(']'); json diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml index 34017009c2838..b711502b14b7f 100644 --- a/src/librustc_codegen_llvm/Cargo.toml +++ b/src/librustc_codegen_llvm/Cargo.toml @@ -13,7 +13,6 @@ test = false cc = "1.0.1" num_cpus = "1.0" rustc-demangle = "0.1.4" -rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } rustc_llvm = { path = "../librustc_llvm" } memmap = "0.6" diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 20f05d110877a..8380b71362138 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -19,7 +19,7 @@ use super::rpath::RPathConfig; use super::rpath; use metadata::METADATA_FILENAME; use rustc::session::config::{self, DebugInfo, OutputFilenames, OutputType, PrintRequest}; -use rustc::session::config::{RUST_CGU_EXT, Lto}; +use rustc::session::config::{RUST_CGU_EXT, Lto, Sanitizer}; use rustc::session::filesearch; use rustc::session::search_paths::PathKind; use rustc::session::Session; @@ -491,6 +491,14 @@ fn link_natively(sess: &Session, } cmd.args(&sess.opts.debugging_opts.pre_link_arg); + if sess.target.target.options.is_like_fuchsia { + let prefix = match sess.opts.debugging_opts.sanitizer { + Some(Sanitizer::Address) => "asan/", + _ => "", + }; + cmd.arg(format!("--dynamic-linker={}ld.so.1", prefix)); + } + let pre_link_objects = if crate_type == config::CrateType::Executable { &sess.target.target.options.pre_link_objects_exe } else { diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index a158c34f9d1c2..7b1c7cfb56f4c 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -6,10 +6,29 @@ version = "0.0.0" [lib] name = "rustc_codegen_ssa" path = "lib.rs" +crate-type = ["dylib"] test = false [dependencies] +bitflags = "1.0.4" cc = "1.0.1" num_cpus = "1.0" rustc-demangle = "0.1.4" memmap = "0.6" +log = "0.4.5" +libc = "0.2.43" +jobserver = "0.1.11" + +serialize = { path = "../libserialize" } +syntax = { path = "../libsyntax" } +syntax_pos = { path = "../libsyntax_pos" } +rustc = { path = "../librustc" } +rustc_allocator = { path = "../librustc_allocator" } +rustc_apfloat = { path = "../librustc_apfloat" } +rustc_codegen_utils = { path = "../librustc_codegen_utils" } +rustc_data_structures = { path = "../librustc_data_structures"} +rustc_errors = { path = "../librustc_errors" } +rustc_fs_util = { path = "../librustc_fs_util" } +rustc_incremental = { path = "../librustc_incremental" } +rustc_mir = { path = "../librustc_mir" } +rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index f6917906d4a8a..92d0219caf06b 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -244,13 +244,24 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { }; // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. + // Bools in union fields needs to be truncated. + let to_immediate_or_cast = |bx: &mut Bx, val, ty| { + if ty == bx.cx().type_i1() { + bx.trunc(val, ty) + } else { + bx.bitcast(val, ty) + } + }; + match val { OperandValue::Immediate(ref mut llval) => { - *llval = bx.bitcast(*llval, bx.cx().immediate_backend_type(field)); + *llval = to_immediate_or_cast(bx, *llval, bx.cx().immediate_backend_type(field)); } OperandValue::Pair(ref mut a, ref mut b) => { - *a = bx.bitcast(*a, bx.cx().scalar_pair_element_backend_type(field, 0, true)); - *b = bx.bitcast(*b, bx.cx().scalar_pair_element_backend_type(field, 1, true)); + *a = to_immediate_or_cast(bx, *a, bx.cx() + .scalar_pair_element_backend_type(field, 0, true)); + *b = to_immediate_or_cast(bx, *b, bx.cx() + .scalar_pair_element_backend_type(field, 1, true)); } OperandValue::Ref(..) => bug!() } diff --git a/src/librustc_data_structures/macros.rs b/src/librustc_data_structures/macros.rs index 3cc91b0e93f04..286a374b280b1 100644 --- a/src/librustc_data_structures/macros.rs +++ b/src/librustc_data_structures/macros.rs @@ -11,11 +11,12 @@ /// A simple static assertion macro. The first argument should be a unique /// ALL_CAPS identifier that describes the condition. #[macro_export] +#[allow_internal_unstable] macro_rules! static_assert { ($name:ident: $test:expr) => { // Use the bool to access an array such that if the bool is false, the access // is out-of-bounds. #[allow(dead_code)] - static $name: () = [()][!$test as usize]; + static $name: () = [()][!($test: bool) as usize]; } } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 936b476df39b9..2eb5f7c853f8c 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -504,15 +504,14 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc let frame = self.stack.pop().expect( "tried to pop a stack frame, but there were none", ); + // Abort early if we do not want to clean up: We also avoid validation in that case, + // because this is CTFE and the final value will be thoroughly validated anyway. match frame.return_to_block { - StackPopCleanup::Goto(block) => { - self.goto_block(block)?; - } + StackPopCleanup::Goto(_) => {}, StackPopCleanup::None { cleanup } => { if !cleanup { - // Leak the locals. Also skip validation, this is only used by - // static/const computation which does its own (stronger) final - // validation. + assert!(self.stack.is_empty(), "only the topmost frame should ever be leaked"); + // Leak the locals, skip validation. return Ok(()); } } @@ -521,7 +520,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc for local in frame.locals { self.deallocate_local(local)?; } - // Validate the return value. + // Validate the return value. Do this after deallocating so that we catch dangling + // references. if let Some(return_place) = frame.return_place { if M::enforce_validity(self) { // Data got changed, better make sure it matches the type! @@ -542,6 +542,13 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc // Uh, that shouldn't happen... the function did not intend to return return err!(Unreachable); } + // Jump to new block -- *after* validation so that the spans make more sense. + match frame.return_to_block { + StackPopCleanup::Goto(block) => { + self.goto_block(block)?; + } + StackPopCleanup::None { .. } => {} + } if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... debug!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); diff --git a/src/librustc_target/spec/fuchsia_base.rs b/src/librustc_target/spec/fuchsia_base.rs index 8c20755492e31..1d0474e1a9a90 100644 --- a/src/librustc_target/spec/fuchsia_base.rs +++ b/src/librustc_target/spec/fuchsia_base.rs @@ -12,9 +12,11 @@ use spec::{LldFlavor, LinkArgs, LinkerFlavor, TargetOptions}; use std::default::Default; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec![ - "--build-id".to_string(), "--hash-style=gnu".to_string(), + let mut pre_link_args = LinkArgs::new(); + pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec![ + "--build-id".to_string(), + "--eh-frame-hdr".to_string(), + "--hash-style=gnu".to_string(), "-z".to_string(), "rodynamic".to_string(), ]); @@ -24,9 +26,13 @@ pub fn opts() -> TargetOptions { dynamic_linking: true, executables: true, target_family: Some("unix".to_string()), + is_like_fuchsia: true, linker_is_gnu: true, has_rpath: false, - pre_link_args: args, + pre_link_args: pre_link_args, + pre_link_objects_exe: vec![ + "Scrt1.o".to_string() + ], position_independent_executables: true, has_elf_tls: true, .. Default::default() diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 75ba4d9bd1105..3285ccfd6c12d 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -560,6 +560,8 @@ pub struct TargetOptions { /// Emscripten toolchain. /// Defaults to false. pub is_like_emscripten: bool, + /// Whether the target toolchain is like Fuchsia's. + pub is_like_fuchsia: bool, /// Whether the linker support GNU-like arguments such as -O. Defaults to false. pub linker_is_gnu: bool, /// The MinGW toolchain has a known issue that prevents it from correctly @@ -729,6 +731,7 @@ impl Default for TargetOptions { is_like_android: false, is_like_emscripten: false, is_like_msvc: false, + is_like_fuchsia: false, linker_is_gnu: false, allows_weak_linkage: true, has_rpath: false, @@ -1028,6 +1031,7 @@ impl Target { key!(is_like_msvc, bool); key!(is_like_emscripten, bool); key!(is_like_android, bool); + key!(is_like_fuchsia, bool); key!(linker_is_gnu, bool); key!(allows_weak_linkage, bool); key!(has_rpath, bool); @@ -1238,6 +1242,7 @@ impl ToJson for Target { target_option_val!(is_like_msvc); target_option_val!(is_like_emscripten); target_option_val!(is_like_android); + target_option_val!(is_like_fuchsia); target_option_val!(linker_is_gnu); target_option_val!(allows_weak_linkage); target_option_val!(has_rpath); diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index d4650bd68d637..7c717d832fa54 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1571,7 +1571,7 @@ impl HashMap /// so that the map now contains keys which compare equal, search may start /// acting erratically, with two keys randomly masking each other. Implementations /// are free to assume this doesn't happen (within the limits of memory-safety). - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut { self.reserve(1); RawEntryBuilderMut { map: self } @@ -1592,7 +1592,7 @@ impl HashMap /// `get` should be preferred. /// /// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn raw_entry(&self) -> RawEntryBuilder { RawEntryBuilder { map: self } } @@ -1844,7 +1844,7 @@ impl<'a, K, V> InternalEntry> { /// /// [`HashMap::raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> { map: &'a mut HashMap, } @@ -1858,7 +1858,7 @@ pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> { /// [`HashMap`]: struct.HashMap.html /// [`Entry`]: enum.Entry.html /// [`raw_entry`]: struct.HashMap.html#method.raw_entry -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> { /// An occupied entry. Occupied(RawOccupiedEntryMut<'a, K, V>), @@ -1870,7 +1870,7 @@ pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> { /// It is part of the [`RawEntryMut`] enum. /// /// [`RawEntryMut`]: enum.RawEntryMut.html -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> { elem: FullBucket>, } @@ -1879,7 +1879,7 @@ pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> { /// It is part of the [`RawEntryMut`] enum. /// /// [`RawEntryMut`]: enum.RawEntryMut.html -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> { elem: VacantEntryState>, hash_builder: &'a S, @@ -1890,7 +1890,7 @@ pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> { /// See the [`HashMap::raw_entry`] docs for usage examples. /// /// [`HashMap::raw_entry`]: struct.HashMap.html#method.raw_entry -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawEntryBuilder<'a, K: 'a, V: 'a, S: 'a> { map: &'a HashMap, } @@ -1900,7 +1900,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> K: Eq + Hash, { /// Create a `RawEntryMut` from the given key. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_key(self, k: &Q) -> RawEntryMut<'a, K, V, S> where K: Borrow, Q: Hash + Eq @@ -1911,7 +1911,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> } /// Create a `RawEntryMut` from the given key and its hash. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S> where K: Borrow, Q: Eq @@ -1941,7 +1941,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> } } /// Create a `RawEntryMut` from the given hash. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_hash(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S> where for<'b> F: FnMut(&'b K) -> bool, { @@ -1951,7 +1951,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> /// Search possible locations for an element with hash `hash` until `is_match` returns true for /// one of them. There is no guarantee that all keys passed to `is_match` will have the provided /// hash. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn search_bucket(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S> where for<'b> F: FnMut(&'b K) -> bool, { @@ -1963,7 +1963,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> where S: BuildHasher, { /// Access an entry by key. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_key(self, k: &Q) -> Option<(&'a K, &'a V)> where K: Borrow, Q: Hash + Eq @@ -1974,7 +1974,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> } /// Access an entry by a key and its hash. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)> where K: Borrow, Q: Hash + Eq @@ -1997,7 +1997,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> } /// Access an entry by hash. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_hash(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)> where F: FnMut(&K) -> bool { @@ -2007,7 +2007,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> /// Search possible locations for an element with hash `hash` until `is_match` returns true for /// one of them. There is no guarantee that all keys passed to `is_match` will have the provided /// hash. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn search_bucket(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)> where F: FnMut(&K) -> bool { @@ -2033,7 +2033,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2; /// assert_eq!(map["poneyland"], 6); /// ``` - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V) where K: Hash, S: BuildHasher, @@ -2061,7 +2061,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// /// assert_eq!(map["poneyland"], "hoho".to_string()); /// ``` - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn or_insert_with(self, default: F) -> (&'a mut K, &'a mut V) where F: FnOnce() -> (K, V), K: Hash, @@ -2099,7 +2099,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// .or_insert("poneyland", 0); /// assert_eq!(map["poneyland"], 43); /// ``` - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn and_modify(self, f: F) -> Self where F: FnOnce(&mut K, &mut V) { @@ -2118,82 +2118,82 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> { /// Gets a reference to the key in the entry. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn key(&self) -> &K { self.elem.read().0 } /// Gets a mutable reference to the key in the entry. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn key_mut(&mut self) -> &mut K { self.elem.read_mut().0 } /// Converts the entry into a mutable reference to the key in the entry /// with a lifetime bound to the map itself. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn into_key(self) -> &'a mut K { self.elem.into_mut_refs().0 } /// Gets a reference to the value in the entry. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get(&self) -> &V { self.elem.read().1 } /// Converts the OccupiedEntry into a mutable reference to the value in the entry /// with a lifetime bound to the map itself. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn into_mut(self) -> &'a mut V { self.elem.into_mut_refs().1 } /// Gets a mutable reference to the value in the entry. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get_mut(&mut self) -> &mut V { self.elem.read_mut().1 } /// Gets a reference to the key and value in the entry. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get_key_value(&mut self) -> (&K, &V) { self.elem.read() } /// Gets a mutable reference to the key and value in the entry. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) { self.elem.read_mut() } /// Converts the OccupiedEntry into a mutable reference to the key and value in the entry /// with a lifetime bound to the map itself. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn into_key_value(self) -> (&'a mut K, &'a mut V) { self.elem.into_mut_refs() } /// Sets the value of the entry, and returns the entry's old value. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn insert(&mut self, value: V) -> V { mem::replace(self.get_mut(), value) } /// Sets the value of the entry, and returns the entry's old value. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn insert_key(&mut self, key: K) -> K { mem::replace(self.key_mut(), key) } /// Takes the value out of the entry, and returns it. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn remove(self) -> V { pop_internal(self.elem).1 } /// Take the ownership of the key and value from the map. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn remove_entry(self) -> (K, V) { let (k, v, _) = pop_internal(self.elem); (k, v) @@ -2203,7 +2203,7 @@ impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> { impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V) where K: Hash, S: BuildHasher, @@ -2215,7 +2215,7 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) { let hash = SafeHash::new(hash); let b = match self.elem { @@ -2236,7 +2236,7 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { } } -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] impl<'a, K, V, S> Debug for RawEntryBuilderMut<'a, K, V, S> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RawEntryBuilder") @@ -2244,7 +2244,7 @@ impl<'a, K, V, S> Debug for RawEntryBuilderMut<'a, K, V, S> { } } -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] impl<'a, K: Debug, V: Debug, S> Debug for RawEntryMut<'a, K, V, S> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -2262,7 +2262,7 @@ impl<'a, K: Debug, V: Debug, S> Debug for RawEntryMut<'a, K, V, S> { } } -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] impl<'a, K: Debug, V: Debug> Debug for RawOccupiedEntryMut<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RawOccupiedEntryMut") @@ -2272,7 +2272,7 @@ impl<'a, K: Debug, V: Debug> Debug for RawOccupiedEntryMut<'a, K, V> { } } -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] impl<'a, K, V, S> Debug for RawVacantEntryMut<'a, K, V, S> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RawVacantEntryMut") @@ -2280,7 +2280,7 @@ impl<'a, K, V, S> Debug for RawVacantEntryMut<'a, K, V, S> { } } -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] impl<'a, K, V, S> Debug for RawEntryBuilder<'a, K, V, S> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RawEntryBuilder") diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml index ec822fddef3eb..32969d09e8567 100644 --- a/src/rustc/Cargo.toml +++ b/src/rustc/Cargo.toml @@ -11,5 +11,9 @@ path = "rustc.rs" rustc_target = { path = "../librustc_target" } rustc_driver = { path = "../librustc_driver" } +# Make sure rustc_codegen_ssa ends up in the sysroot, because this +# crate is intended to be used by codegen backends, which may not be in-tree. +rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } + [features] jemalloc = ['rustc_driver/jemalloc-sys'] diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs index 786968128ec1b..5a6df52502eb5 100644 --- a/src/test/codegen/union-abi.rs +++ b/src/test/codegen/union-abi.rs @@ -78,3 +78,9 @@ pub union CUnionU128{a:u128} #[no_mangle] pub fn test_CUnionU128(_: CUnionU128) { loop {} } +pub union UnionBool { b:bool } +// CHECK: define zeroext i1 @test_UnionBool(i8 %b) +#[no_mangle] +pub fn test_UnionBool(b: UnionBool) -> bool { unsafe { b.b } } +// CHECK: %0 = trunc i8 %b to i1 + diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs similarity index 72% rename from src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs rename to src/test/debuginfo/gdb-pretty-struct-and-enums.rs index 158a1f17fc03d..34fa3bc4b0ce2 100644 --- a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs +++ b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs @@ -8,34 +8,34 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-bitrig -// ignore-solaris -// ignore-windows failing on win32 bot -// ignore-freebsd: gdb package too new // ignore-tidy-linelength // ignore-lldb // ignore-android: FIXME(#10381) +// min-gdb-version: 7.11 + // compile-flags:-g // gdb-command: run // gdb-command: print regular_struct -// gdb-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false} +// gdbg-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false} +// gdbr-check:$1 = gdb_pretty_struct_and_enums::RegularStruct {the_first_field: 101, the_second_field: 102.5, the_third_field: false} // gdb-command: print empty_struct -// gdb-check:$2 = EmptyStruct +// gdbg-check:$2 = EmptyStruct +// gdbr-check:$2 = gdb_pretty_struct_and_enums::EmptyStruct // gdb-command: print c_style_enum1 // gdbg-check:$3 = CStyleEnumVar1 -// gdbr-check:$3 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar1 +// gdbr-check:$3 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar1 // gdb-command: print c_style_enum2 // gdbg-check:$4 = CStyleEnumVar2 -// gdbr-check:$4 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar2 +// gdbr-check:$4 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar2 // gdb-command: print c_style_enum3 // gdbg-check:$5 = CStyleEnumVar3 -// gdbr-check:$5 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar3 +// gdbr-check:$5 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar3 #![allow(dead_code, unused_variables)] diff --git a/src/test/ui-fulldeps/auxiliary/subspan.rs b/src/test/ui-fulldeps/auxiliary/subspan.rs new file mode 100644 index 0000000000000..134b04d7333bc --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/subspan.rs @@ -0,0 +1,47 @@ +// 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. + +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_diagnostic, proc_macro_span)] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span, Diagnostic}; + +fn parse(input: TokenStream) -> Result<(), Diagnostic> { + if let Some(TokenTree::Literal(lit)) = input.into_iter().next() { + let mut spans = vec![]; + let string = lit.to_string(); + for hi in string.matches("hi") { + let index = hi.as_ptr() as usize - string.as_ptr() as usize; + let subspan = lit.subspan(index..(index + hi.len())).unwrap(); + spans.push(subspan); + } + + if !spans.is_empty() { + Err(Span::call_site().error("found 'hi's").span_note(spans, "here")) + } else { + Ok(()) + } + } else { + Err(Span::call_site().error("invalid input: expected string literal")) + } +} + +#[proc_macro] +pub fn subspan(input: TokenStream) -> TokenStream { + if let Err(diag) = parse(input) { + diag.emit(); + } + + TokenStream::new() +} diff --git a/src/test/ui-fulldeps/subspan.rs b/src/test/ui-fulldeps/subspan.rs new file mode 100644 index 0000000000000..437123ca4795e --- /dev/null +++ b/src/test/ui-fulldeps/subspan.rs @@ -0,0 +1,37 @@ +// 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:subspan.rs +// ignore-stage1 + +extern crate subspan; + +use subspan::subspan; + +// This one emits no error. +subspan!(""); + +// Exactly one 'hi'. +subspan!("hi"); //~ ERROR found 'hi's + +// Now two, back to back. +subspan!("hihi"); //~ ERROR found 'hi's + +// Now three, back to back. +subspan!("hihihi"); //~ ERROR found 'hi's + +// Now several, with spacing. +subspan!("why I hide? hi!"); //~ ERROR found 'hi's +subspan!("hey, hi, hidy, hidy, hi hi"); //~ ERROR found 'hi's +subspan!("this is a hi, and this is another hi"); //~ ERROR found 'hi's +subspan!("how are you this evening"); //~ ERROR found 'hi's +subspan!("this is highly eradic"); //~ ERROR found 'hi's + +fn main() { } diff --git a/src/test/ui-fulldeps/subspan.stderr b/src/test/ui-fulldeps/subspan.stderr new file mode 100644 index 0000000000000..4d3928cae723a --- /dev/null +++ b/src/test/ui-fulldeps/subspan.stderr @@ -0,0 +1,98 @@ +error: found 'hi's + --> $DIR/subspan.rs:22:1 + | +LL | subspan!("hi"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:22:11 + | +LL | subspan!("hi"); //~ ERROR found 'hi's + | ^^ + +error: found 'hi's + --> $DIR/subspan.rs:25:1 + | +LL | subspan!("hihi"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:25:11 + | +LL | subspan!("hihi"); //~ ERROR found 'hi's + | ^^^^ + +error: found 'hi's + --> $DIR/subspan.rs:28:1 + | +LL | subspan!("hihihi"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:28:11 + | +LL | subspan!("hihihi"); //~ ERROR found 'hi's + | ^^^^^^ + +error: found 'hi's + --> $DIR/subspan.rs:31:1 + | +LL | subspan!("why I hide? hi!"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:31:17 + | +LL | subspan!("why I hide? hi!"); //~ ERROR found 'hi's + | ^^ ^^ + +error: found 'hi's + --> $DIR/subspan.rs:32:1 + | +LL | subspan!("hey, hi, hidy, hidy, hi hi"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:32:16 + | +LL | subspan!("hey, hi, hidy, hidy, hi hi"); //~ ERROR found 'hi's + | ^^ ^^ ^^ ^^ ^^ + +error: found 'hi's + --> $DIR/subspan.rs:33:1 + | +LL | subspan!("this is a hi, and this is another hi"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:33:12 + | +LL | subspan!("this is a hi, and this is another hi"); //~ ERROR found 'hi's + | ^^ ^^ ^^ ^^ + +error: found 'hi's + --> $DIR/subspan.rs:34:1 + | +LL | subspan!("how are you this evening"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:34:24 + | +LL | subspan!("how are you this evening"); //~ ERROR found 'hi's + | ^^ + +error: found 'hi's + --> $DIR/subspan.rs:35:1 + | +LL | subspan!("this is highly eradic"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:35:12 + | +LL | subspan!("this is highly eradic"); //~ ERROR found 'hi's + | ^^ ^^ + +error: aborting due to 8 previous errors +