Auto merge of #56186 - kennytm:rollup, r=kennytm

Rollup of 14 pull requests

Successful merges:

 - #55767 (Disable some pretty-printers when gdb is rust-enabled)
 - #55838 (Fix #[cfg] for step impl on ranges)
 - #55869 (Add std::iter::unfold)
 - #55945 (Ensure that the argument to `static_assert` is a `bool`)
 - #56022 (When popping in CTFE, perform validation before jumping to next statement to have a better span for the error)
 - #56048 (Add rustc_codegen_ssa to sysroot)
 - #56091 (Fix json output in the self-profiler)
 - #56097 (Fix invalid bitcast taking bool out of a union represented as a scalar)
 - #56116 (ci: Download clang/lldb from tarballs)
 - #56120 (Add unstable Literal::subspan().)
 - #56154 (Pass additional linker flags when targeting Fuchsia)
 - #56162 (std::str Adapt documentation to reality)
 - #56163 ([master] Backport 1.30.1 release notes)
 - #56168 (Fix the tracking issue for hash_raw_entry)

Failed merges:

r? @ghost
This commit is contained in:
bors 2018-11-23 18:42:20 +00:00
commit 1f57e48411
27 changed files with 606 additions and 96 deletions

View file

@ -2073,6 +2073,7 @@ dependencies = [
name = "rustc-main" name = "rustc-main"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"rustc_codegen_ssa 0.0.0",
"rustc_driver 0.0.0", "rustc_driver 0.0.0",
"rustc_target 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)", "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)", "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-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_codegen_ssa 0.0.0",
"rustc_llvm 0.0.0", "rustc_llvm 0.0.0",
] ]
@ -2177,10 +2177,27 @@ dependencies = [
name = "rustc_codegen_ssa" name = "rustc_codegen_ssa"
version = "0.0.0" version = "0.0.0"
dependencies = [ 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)", "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)", "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)", "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-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]] [[package]]

View file

@ -74,6 +74,14 @@ Cargo
[cargo-rename-reference]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml [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 [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) Version 1.30.0 (2018-10-25)
========================== ==========================

View file

@ -55,6 +55,7 @@ function fetch_submodule {
} }
included="src/llvm src/llvm-emscripten src/doc/book src/doc/rust-by-example" 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="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)"
modules=($modules) modules=($modules)
use_git="" use_git=""

View file

@ -18,6 +18,8 @@ import debugger_pretty_printers_common as rustpp
if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
xrange = range xrange = range
rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string = True)
#=============================================================================== #===============================================================================
# GDB Pretty Printing Module for Rust # GDB Pretty Printing Module for Rust
#=============================================================================== #===============================================================================
@ -99,27 +101,9 @@ def rust_pretty_printer_lookup_function(gdb_val):
val = GdbValue(gdb_val) val = GdbValue(gdb_val)
type_kind = val.type.get_type_kind() 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: if type_kind == rustpp.TYPE_KIND_SLICE:
return RustSlicePrinter(val) return RustSlicePrinter(val)
if type_kind == rustpp.TYPE_KIND_STR_SLICE:
return RustStringSlicePrinter(val)
if type_kind == rustpp.TYPE_KIND_STD_VEC: if type_kind == rustpp.TYPE_KIND_STD_VEC:
return RustStdVecPrinter(val) return RustStdVecPrinter(val)
@ -138,6 +122,29 @@ def rust_pretty_printer_lookup_function(gdb_val):
if type_kind == rustpp.TYPE_KIND_OS_STRING: if type_kind == rustpp.TYPE_KIND_OS_STRING:
return RustOsStringPrinter(val) 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: if type_kind == rustpp.TYPE_KIND_TUPLE:
return RustStructPrinter(val, return RustStructPrinter(val,
omit_first_field = False, omit_first_field = False,

View file

@ -112,10 +112,10 @@
//! //!
//! // next() is the only required method //! // next() is the only required method
//! fn next(&mut self) -> Option<usize> { //! fn next(&mut self) -> Option<usize> {
//! // increment our count. This is why we started at zero. //! // Increment our count. This is why we started at zero.
//! self.count += 1; //! 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 { //! if self.count < 6 {
//! Some(self.count) //! Some(self.count)
//! } else { //! } else {
@ -339,6 +339,8 @@ pub use self::sources::{RepeatWith, repeat_with};
pub use self::sources::{Empty, empty}; pub use self::sources::{Empty, empty};
#[stable(feature = "iter_once", since = "1.2.0")] #[stable(feature = "iter_once", since = "1.2.0")]
pub use self::sources::{Once, once}; 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")] #[stable(feature = "rust1", since = "1.0.0")]
pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend}; pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend};

View file

@ -166,14 +166,14 @@ macro_rules! step_impl_no_between {
} }
step_impl_unsigned!(usize u8 u16); step_impl_unsigned!(usize u8 u16);
#[cfg(not(target_pointer_witdth = "16"))] #[cfg(not(target_pointer_width = "16"))]
step_impl_unsigned!(u32); step_impl_unsigned!(u32);
#[cfg(target_pointer_witdth = "16")] #[cfg(target_pointer_width = "16")]
step_impl_no_between!(u32); step_impl_no_between!(u32);
step_impl_signed!([isize: usize] [i8: u8] [i16: u16]); 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]); step_impl_signed!([i32: u32]);
#[cfg(target_pointer_witdth = "16")] #[cfg(target_pointer_width = "16")]
step_impl_no_between!(i32); step_impl_no_between!(i32);
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]
step_impl_unsigned!(u64); step_impl_unsigned!(u64);

View file

@ -386,3 +386,164 @@ impl<T> FusedIterator for Once<T> {}
pub fn once<T>(value: T) -> Once<T> { pub fn once<T>(value: T) -> Once<T> {
Once { inner: Some(value).into_iter() } Once { inner: Some(value).into_iter() }
} }
/// Creates a new iterator where each iteration calls the provided closure
/// `F: FnMut(&mut St) -> Option<T>`.
///
/// 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 doesnt 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
///
/// Lets 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::<Vec<_>>(), &[1, 2, 3, 4, 5]);
/// ```
#[inline]
#[unstable(feature = "iter_unfold", issue = "55977")]
pub fn unfold<St, T, F>(initial_state: St, f: F) -> Unfold<St, F>
where F: FnMut(&mut St) -> Option<T>
{
Unfold {
state: initial_state,
f,
}
}
/// An iterator where each iteration calls the provided closure `F: FnMut(&mut St) -> Option<T>`.
///
/// 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<St, F> {
state: St,
f: F,
}
#[unstable(feature = "iter_unfold", issue = "55977")]
impl<St, T, F> Iterator for Unfold<St, F>
where F: FnMut(&mut St) -> Option<T>
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
(self.f)(&mut self.state)
}
}
#[unstable(feature = "iter_unfold", issue = "55977")]
impl<St: fmt::Debug, F> fmt::Debug for Unfold<St, F> {
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<T>` closure to compute each items 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::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
/// ```
#[unstable(feature = "iter_unfold", issue = "55977")]
pub fn successors<T, F>(first: Option<T>, succ: F) -> Successors<T, F>
where F: FnMut(&T) -> Option<T>
{
// If this function returned `impl Iterator<Item=T>`
// it could be based on `unfold` and not need a dedicated type.
// However having a named `Successors<T, F>` 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<T, F> {
next: Option<T>,
succ: F,
}
#[unstable(feature = "iter_unfold", issue = "55977")]
impl<T, F> Iterator for Successors<T, F>
where F: FnMut(&T) -> Option<T>
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.next.take().map(|item| {
self.next = (self.succ)(&item);
item
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
if self.next.is_some() {
(1, None)
} else {
(0, Some(0))
}
}
}
#[unstable(feature = "iter_unfold", issue = "55977")]
impl<T, F> FusedIterator for Successors<T, F>
where F: FnMut(&T) -> Option<T>
{}
#[unstable(feature = "iter_unfold", issue = "55977")]
impl<T: fmt::Debug, F> fmt::Debug for Successors<T, F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Successors")
.field("next", &self.next)
.finish()
}
}

View file

@ -1424,10 +1424,8 @@ fn contains_nonascii(x: usize) -> bool {
(x & NONASCII_MASK) != 0 (x & NONASCII_MASK) != 0
} }
/// Walks through `iter` checking that it's a valid UTF-8 sequence, /// Walks through `v` checking that it's a valid UTF-8 sequence,
/// returning `true` in that case, or, if it is invalid, `false` with /// returning `Ok(())` in that case, or, if it is invalid, `Err(err)`.
/// `iter` reset such that it is pointing at the first byte in the
/// invalid sequence.
#[inline] #[inline]
fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
let mut index = 0; let mut index = 0;

View file

@ -1759,6 +1759,17 @@ fn test_repeat_with_take_collect() {
assert_eq!(v, vec![1, 2, 4, 8, 16]); 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::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
assert_eq!(powers_of_10.next(), None);
let mut empty = successors(None::<u32>, |_| unimplemented!());
assert_eq!(empty.next(), None);
assert_eq!(empty.next(), None);
}
#[test] #[test]
fn test_fuse() { fn test_fuse() {
let mut it = 0..3; let mut it = 0..3;

View file

@ -19,6 +19,7 @@
#![feature(flt2dec)] #![feature(flt2dec)]
#![feature(fmt_internals)] #![feature(fmt_internals)]
#![feature(hashmap_internals)] #![feature(hashmap_internals)]
#![feature(iter_unfold)]
#![feature(pattern)] #![feature(pattern)]
#![feature(range_is_empty)] #![feature(range_is_empty)]
#![feature(raw)] #![feature(raw)]

View file

@ -50,6 +50,7 @@ mod diagnostic;
#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
pub use diagnostic::{Diagnostic, Level, MultiSpan}; pub use diagnostic::{Diagnostic, Level, MultiSpan};
use std::ops::{Bound, RangeBounds};
use std::{ascii, fmt, iter}; use std::{ascii, fmt, iter};
use std::path::PathBuf; use std::path::PathBuf;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
@ -59,7 +60,7 @@ use syntax::errors::DiagnosticBuilder;
use syntax::parse::{self, token}; use syntax::parse::{self, token};
use syntax::symbol::Symbol; use syntax::symbol::Symbol;
use syntax::tokenstream::{self, DelimSpan}; 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 /// The main type provided by this crate, representing an abstract stream of
/// tokens, or, more specifically, a sequence of token trees. /// tokens, or, more specifically, a sequence of token trees.
@ -1168,6 +1169,50 @@ impl Literal {
pub fn set_span(&mut self, span: Span) { pub fn set_span(&mut self, span: Span) {
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<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
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 /// Prints the literal as a string that should be losslessly convertible

View file

@ -93,16 +93,27 @@ macro_rules! define_categories {
$( $(
let (hits, total) = self.query_counts.$name; 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!( json.push_str(&format!(
"{{ \"category\": {}, \"time_ms\": {}, "{{ \"category\": {}, \"time_ms\": {},
\"query_count\": {}, \"query_hits\": {} }}", \"query_count\": {}, \"query_hits\": {} }},",
stringify!($name), stringify!($name),
self.times.$name / 1_000_000, self.times.$name / 1_000_000,
total, total,
format!("{:.2}", (((hits as f32) / (total as f32)) * 100.0)) format!("{:.2}", hit_percent)
)); ));
)* )*
//remove the trailing ',' character
json.pop();
json.push(']'); json.push(']');
json json

View file

@ -13,7 +13,6 @@ test = false
cc = "1.0.1" cc = "1.0.1"
num_cpus = "1.0" num_cpus = "1.0"
rustc-demangle = "0.1.4" rustc-demangle = "0.1.4"
rustc_codegen_ssa = { path = "../librustc_codegen_ssa" }
rustc_llvm = { path = "../librustc_llvm" } rustc_llvm = { path = "../librustc_llvm" }
memmap = "0.6" memmap = "0.6"

View file

@ -19,7 +19,7 @@ use super::rpath::RPathConfig;
use super::rpath; use super::rpath;
use metadata::METADATA_FILENAME; use metadata::METADATA_FILENAME;
use rustc::session::config::{self, DebugInfo, OutputFilenames, OutputType, PrintRequest}; 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::filesearch;
use rustc::session::search_paths::PathKind; use rustc::session::search_paths::PathKind;
use rustc::session::Session; use rustc::session::Session;
@ -491,6 +491,14 @@ fn link_natively(sess: &Session,
} }
cmd.args(&sess.opts.debugging_opts.pre_link_arg); 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 { let pre_link_objects = if crate_type == config::CrateType::Executable {
&sess.target.target.options.pre_link_objects_exe &sess.target.target.options.pre_link_objects_exe
} else { } else {

View file

@ -6,10 +6,29 @@ version = "0.0.0"
[lib] [lib]
name = "rustc_codegen_ssa" name = "rustc_codegen_ssa"
path = "lib.rs" path = "lib.rs"
crate-type = ["dylib"]
test = false test = false
[dependencies] [dependencies]
bitflags = "1.0.4"
cc = "1.0.1" cc = "1.0.1"
num_cpus = "1.0" num_cpus = "1.0"
rustc-demangle = "0.1.4" rustc-demangle = "0.1.4"
memmap = "0.6" 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" }

View file

@ -244,13 +244,24 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
}; };
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. // 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 { match val {
OperandValue::Immediate(ref mut llval) => { 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) => { OperandValue::Pair(ref mut a, ref mut b) => {
*a = bx.bitcast(*a, bx.cx().scalar_pair_element_backend_type(field, 0, true)); *a = to_immediate_or_cast(bx, *a, bx.cx()
*b = bx.bitcast(*b, bx.cx().scalar_pair_element_backend_type(field, 1, true)); .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!() OperandValue::Ref(..) => bug!()
} }

View file

@ -11,11 +11,12 @@
/// A simple static assertion macro. The first argument should be a unique /// A simple static assertion macro. The first argument should be a unique
/// ALL_CAPS identifier that describes the condition. /// ALL_CAPS identifier that describes the condition.
#[macro_export] #[macro_export]
#[allow_internal_unstable]
macro_rules! static_assert { macro_rules! static_assert {
($name:ident: $test:expr) => { ($name:ident: $test:expr) => {
// Use the bool to access an array such that if the bool is false, the access // Use the bool to access an array such that if the bool is false, the access
// is out-of-bounds. // is out-of-bounds.
#[allow(dead_code)] #[allow(dead_code)]
static $name: () = [()][!$test as usize]; static $name: () = [()][!($test: bool) as usize];
} }
} }

View file

@ -504,15 +504,14 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
let frame = self.stack.pop().expect( let frame = self.stack.pop().expect(
"tried to pop a stack frame, but there were none", "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 { match frame.return_to_block {
StackPopCleanup::Goto(block) => { StackPopCleanup::Goto(_) => {},
self.goto_block(block)?;
}
StackPopCleanup::None { cleanup } => { StackPopCleanup::None { cleanup } => {
if !cleanup { if !cleanup {
// Leak the locals. Also skip validation, this is only used by assert!(self.stack.is_empty(), "only the topmost frame should ever be leaked");
// static/const computation which does its own (stronger) final // Leak the locals, skip validation.
// validation.
return Ok(()); 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 { for local in frame.locals {
self.deallocate_local(local)?; 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 let Some(return_place) = frame.return_place {
if M::enforce_validity(self) { if M::enforce_validity(self) {
// Data got changed, better make sure it matches the type! // 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 // Uh, that shouldn't happen... the function did not intend to return
return err!(Unreachable); 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... if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc...
debug!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); debug!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance);

View file

@ -12,9 +12,11 @@ use spec::{LldFlavor, LinkArgs, LinkerFlavor, TargetOptions};
use std::default::Default; use std::default::Default;
pub fn opts() -> TargetOptions { pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new(); let mut pre_link_args = LinkArgs::new();
args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec![ pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec![
"--build-id".to_string(), "--hash-style=gnu".to_string(), "--build-id".to_string(),
"--eh-frame-hdr".to_string(),
"--hash-style=gnu".to_string(),
"-z".to_string(), "rodynamic".to_string(), "-z".to_string(), "rodynamic".to_string(),
]); ]);
@ -24,9 +26,13 @@ pub fn opts() -> TargetOptions {
dynamic_linking: true, dynamic_linking: true,
executables: true, executables: true,
target_family: Some("unix".to_string()), target_family: Some("unix".to_string()),
is_like_fuchsia: true,
linker_is_gnu: true, linker_is_gnu: true,
has_rpath: false, 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, position_independent_executables: true,
has_elf_tls: true, has_elf_tls: true,
.. Default::default() .. Default::default()

View file

@ -560,6 +560,8 @@ pub struct TargetOptions {
/// Emscripten toolchain. /// Emscripten toolchain.
/// Defaults to false. /// Defaults to false.
pub is_like_emscripten: bool, 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. /// Whether the linker support GNU-like arguments such as -O. Defaults to false.
pub linker_is_gnu: bool, pub linker_is_gnu: bool,
/// The MinGW toolchain has a known issue that prevents it from correctly /// 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_android: false,
is_like_emscripten: false, is_like_emscripten: false,
is_like_msvc: false, is_like_msvc: false,
is_like_fuchsia: false,
linker_is_gnu: false, linker_is_gnu: false,
allows_weak_linkage: true, allows_weak_linkage: true,
has_rpath: false, has_rpath: false,
@ -1028,6 +1031,7 @@ impl Target {
key!(is_like_msvc, bool); key!(is_like_msvc, bool);
key!(is_like_emscripten, bool); key!(is_like_emscripten, bool);
key!(is_like_android, bool); key!(is_like_android, bool);
key!(is_like_fuchsia, bool);
key!(linker_is_gnu, bool); key!(linker_is_gnu, bool);
key!(allows_weak_linkage, bool); key!(allows_weak_linkage, bool);
key!(has_rpath, bool); key!(has_rpath, bool);
@ -1238,6 +1242,7 @@ impl ToJson for Target {
target_option_val!(is_like_msvc); target_option_val!(is_like_msvc);
target_option_val!(is_like_emscripten); target_option_val!(is_like_emscripten);
target_option_val!(is_like_android); target_option_val!(is_like_android);
target_option_val!(is_like_fuchsia);
target_option_val!(linker_is_gnu); target_option_val!(linker_is_gnu);
target_option_val!(allows_weak_linkage); target_option_val!(allows_weak_linkage);
target_option_val!(has_rpath); target_option_val!(has_rpath);

View file

@ -1571,7 +1571,7 @@ impl<K, V, S> HashMap<K, V, S>
/// so that the map now contains keys which compare equal, search may start /// so that the map now contains keys which compare equal, search may start
/// acting erratically, with two keys randomly masking each other. Implementations /// acting erratically, with two keys randomly masking each other. Implementations
/// are free to assume this doesn't happen (within the limits of memory-safety). /// 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<K, V, S> { pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<K, V, S> {
self.reserve(1); self.reserve(1);
RawEntryBuilderMut { map: self } RawEntryBuilderMut { map: self }
@ -1592,7 +1592,7 @@ impl<K, V, S> HashMap<K, V, S>
/// `get` should be preferred. /// `get` should be preferred.
/// ///
/// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`. /// 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<K, V, S> { pub fn raw_entry(&self) -> RawEntryBuilder<K, V, S> {
RawEntryBuilder { map: self } RawEntryBuilder { map: self }
} }
@ -1844,7 +1844,7 @@ impl<'a, K, V> InternalEntry<K, V, &'a mut RawTable<K, V>> {
/// ///
/// [`HashMap::raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut /// [`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> { pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> {
map: &'a mut HashMap<K, V, S>, map: &'a mut HashMap<K, V, S>,
} }
@ -1858,7 +1858,7 @@ pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> {
/// [`HashMap`]: struct.HashMap.html /// [`HashMap`]: struct.HashMap.html
/// [`Entry`]: enum.Entry.html /// [`Entry`]: enum.Entry.html
/// [`raw_entry`]: struct.HashMap.html#method.raw_entry /// [`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> { pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> {
/// An occupied entry. /// An occupied entry.
Occupied(RawOccupiedEntryMut<'a, K, V>), 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. /// It is part of the [`RawEntryMut`] enum.
/// ///
/// [`RawEntryMut`]: enum.RawEntryMut.html /// [`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> { pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> {
elem: FullBucket<K, V, &'a mut RawTable<K, V>>, elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
} }
@ -1879,7 +1879,7 @@ pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> {
/// It is part of the [`RawEntryMut`] enum. /// It is part of the [`RawEntryMut`] enum.
/// ///
/// [`RawEntryMut`]: enum.RawEntryMut.html /// [`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> { pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> {
elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>, elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>,
hash_builder: &'a S, 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. /// See the [`HashMap::raw_entry`] docs for usage examples.
/// ///
/// [`HashMap::raw_entry`]: struct.HashMap.html#method.raw_entry /// [`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> { pub struct RawEntryBuilder<'a, K: 'a, V: 'a, S: 'a> {
map: &'a HashMap<K, V, S>, map: &'a HashMap<K, V, S>,
} }
@ -1900,7 +1900,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S>
K: Eq + Hash, K: Eq + Hash,
{ {
/// Create a `RawEntryMut` from the given key. /// 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<Q: ?Sized>(self, k: &Q) -> RawEntryMut<'a, K, V, S> pub fn from_key<Q: ?Sized>(self, k: &Q) -> RawEntryMut<'a, K, V, S>
where K: Borrow<Q>, where K: Borrow<Q>,
Q: Hash + Eq 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. /// 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<Q: ?Sized>(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S> pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S>
where K: Borrow<Q>, where K: Borrow<Q>,
Q: Eq Q: Eq
@ -1941,7 +1941,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S>
} }
} }
/// Create a `RawEntryMut` from the given hash. /// 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<F>(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S> pub fn from_hash<F>(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S>
where for<'b> F: FnMut(&'b K) -> bool, 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 /// 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 /// one of them. There is no guarantee that all keys passed to `is_match` will have the provided
/// hash. /// hash.
#[unstable(feature = "hash_raw_entry", issue = "54043")] #[unstable(feature = "hash_raw_entry", issue = "56167")]
pub fn search_bucket<F>(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S> pub fn search_bucket<F>(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S>
where for<'b> F: FnMut(&'b K) -> bool, 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, where S: BuildHasher,
{ {
/// Access an entry by key. /// Access an entry by key.
#[unstable(feature = "hash_raw_entry", issue = "54043")] #[unstable(feature = "hash_raw_entry", issue = "56167")]
pub fn from_key<Q: ?Sized>(self, k: &Q) -> Option<(&'a K, &'a V)> pub fn from_key<Q: ?Sized>(self, k: &Q) -> Option<(&'a K, &'a V)>
where K: Borrow<Q>, where K: Borrow<Q>,
Q: Hash + Eq 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. /// 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<Q: ?Sized>(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)> pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)>
where K: Borrow<Q>, where K: Borrow<Q>,
Q: Hash + Eq Q: Hash + Eq
@ -1997,7 +1997,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S>
} }
/// Access an entry by hash. /// Access an entry by hash.
#[unstable(feature = "hash_raw_entry", issue = "54043")] #[unstable(feature = "hash_raw_entry", issue = "56167")]
pub fn from_hash<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)> pub fn from_hash<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)>
where F: FnMut(&K) -> bool 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 /// 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 /// one of them. There is no guarantee that all keys passed to `is_match` will have the provided
/// hash. /// hash.
#[unstable(feature = "hash_raw_entry", issue = "54043")] #[unstable(feature = "hash_raw_entry", issue = "56167")]
pub fn search_bucket<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)> pub fn search_bucket<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)>
where F: FnMut(&K) -> bool 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; /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2;
/// assert_eq!(map["poneyland"], 6); /// 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) pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V)
where K: Hash, where K: Hash,
S: BuildHasher, S: BuildHasher,
@ -2061,7 +2061,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
/// ///
/// assert_eq!(map["poneyland"], "hoho".to_string()); /// 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<F>(self, default: F) -> (&'a mut K, &'a mut V) pub fn or_insert_with<F>(self, default: F) -> (&'a mut K, &'a mut V)
where F: FnOnce() -> (K, V), where F: FnOnce() -> (K, V),
K: Hash, K: Hash,
@ -2099,7 +2099,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
/// .or_insert("poneyland", 0); /// .or_insert("poneyland", 0);
/// assert_eq!(map["poneyland"], 43); /// assert_eq!(map["poneyland"], 43);
/// ``` /// ```
#[unstable(feature = "hash_raw_entry", issue = "54043")] #[unstable(feature = "hash_raw_entry", issue = "56167")]
pub fn and_modify<F>(self, f: F) -> Self pub fn and_modify<F>(self, f: F) -> Self
where F: FnOnce(&mut K, &mut V) 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> { impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> {
/// Gets a reference to the key in the entry. /// 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 { pub fn key(&self) -> &K {
self.elem.read().0 self.elem.read().0
} }
/// Gets a mutable reference to the key in the entry. /// 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 { pub fn key_mut(&mut self) -> &mut K {
self.elem.read_mut().0 self.elem.read_mut().0
} }
/// Converts the entry into a mutable reference to the key in the entry /// Converts the entry into a mutable reference to the key in the entry
/// with a lifetime bound to the map itself. /// 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 { pub fn into_key(self) -> &'a mut K {
self.elem.into_mut_refs().0 self.elem.into_mut_refs().0
} }
/// Gets a reference to the value in the entry. /// 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 { pub fn get(&self) -> &V {
self.elem.read().1 self.elem.read().1
} }
/// Converts the OccupiedEntry into a mutable reference to the value in the entry /// Converts the OccupiedEntry into a mutable reference to the value in the entry
/// with a lifetime bound to the map itself. /// 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 { pub fn into_mut(self) -> &'a mut V {
self.elem.into_mut_refs().1 self.elem.into_mut_refs().1
} }
/// Gets a mutable reference to the value in the entry. /// 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 { pub fn get_mut(&mut self) -> &mut V {
self.elem.read_mut().1 self.elem.read_mut().1
} }
/// Gets a reference to the key and value in the entry. /// 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) { pub fn get_key_value(&mut self) -> (&K, &V) {
self.elem.read() self.elem.read()
} }
/// Gets a mutable reference to the key and value in the entry. /// 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) { pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) {
self.elem.read_mut() self.elem.read_mut()
} }
/// Converts the OccupiedEntry into a mutable reference to the key and value in the entry /// Converts the OccupiedEntry into a mutable reference to the key and value in the entry
/// with a lifetime bound to the map itself. /// 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) { pub fn into_key_value(self) -> (&'a mut K, &'a mut V) {
self.elem.into_mut_refs() self.elem.into_mut_refs()
} }
/// Sets the value of the entry, and returns the entry's old 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(&mut self, value: V) -> V { pub fn insert(&mut self, value: V) -> V {
mem::replace(self.get_mut(), value) mem::replace(self.get_mut(), value)
} }
/// Sets the value of the entry, and returns the entry's old 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 { pub fn insert_key(&mut self, key: K) -> K {
mem::replace(self.key_mut(), key) mem::replace(self.key_mut(), key)
} }
/// Takes the value out of the entry, and returns it. /// 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 { pub fn remove(self) -> V {
pop_internal(self.elem).1 pop_internal(self.elem).1
} }
/// Take the ownership of the key and value from the map. /// 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) { pub fn remove_entry(self) -> (K, V) {
let (k, v, _) = pop_internal(self.elem); let (k, v, _) = pop_internal(self.elem);
(k, v) (k, v)
@ -2203,7 +2203,7 @@ impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> {
impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> {
/// Sets the value of the entry with the VacantEntry's key, /// Sets the value of the entry with the VacantEntry's key,
/// and returns a mutable reference to it. /// 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) pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V)
where K: Hash, where K: Hash,
S: BuildHasher, 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, /// Sets the value of the entry with the VacantEntry's key,
/// and returns a mutable reference to it. /// 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) { pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) {
let hash = SafeHash::new(hash); let hash = SafeHash::new(hash);
let b = match self.elem { 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> { impl<'a, K, V, S> Debug for RawEntryBuilderMut<'a, K, V, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("RawEntryBuilder") 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> { impl<'a, K: Debug, V: Debug, S> Debug for RawEntryMut<'a, K, V, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { 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> { impl<'a, K: Debug, V: Debug> Debug for RawOccupiedEntryMut<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("RawOccupiedEntryMut") 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> { impl<'a, K, V, S> Debug for RawVacantEntryMut<'a, K, V, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("RawVacantEntryMut") 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> { impl<'a, K, V, S> Debug for RawEntryBuilder<'a, K, V, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("RawEntryBuilder") f.debug_struct("RawEntryBuilder")

View file

@ -11,5 +11,9 @@ path = "rustc.rs"
rustc_target = { path = "../librustc_target" } rustc_target = { path = "../librustc_target" }
rustc_driver = { path = "../librustc_driver" } 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] [features]
jemalloc = ['rustc_driver/jemalloc-sys'] jemalloc = ['rustc_driver/jemalloc-sys']

View file

@ -78,3 +78,9 @@ pub union CUnionU128{a:u128}
#[no_mangle] #[no_mangle]
pub fn test_CUnionU128(_: CUnionU128) { loop {} } 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

View file

@ -8,34 +8,34 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // 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-tidy-linelength
// ignore-lldb // ignore-lldb
// ignore-android: FIXME(#10381) // ignore-android: FIXME(#10381)
// min-gdb-version: 7.11
// compile-flags:-g // compile-flags:-g
// gdb-command: run // gdb-command: run
// gdb-command: print regular_struct // 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-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 // gdb-command: print c_style_enum1
// gdbg-check:$3 = CStyleEnumVar1 // 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 // gdb-command: print c_style_enum2
// gdbg-check:$4 = CStyleEnumVar2 // 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 // gdb-command: print c_style_enum3
// gdbg-check:$5 = CStyleEnumVar3 // 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)] #![allow(dead_code, unused_variables)]

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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()
}

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() { }

View file

@ -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