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

Rollup of 14 pull requests

- Successful merges: #46636, #46780, #46784, #46809, #46814, #46820, #46839, #46847, #46858, #46878, #46884, #46890, #46898, #46918
- Failed merges:
This commit is contained in:
bors 2017-12-21 23:01:27 +00:00
commit ba2741594b
40 changed files with 453 additions and 329 deletions

View File

@ -112,14 +112,17 @@ There are large number of options provided in this config file that will alter t
configuration used in the build process. Some options to note:
#### `[llvm]`:
- `assertions = true` = This enables LLVM assertions, which makes LLVM misuse cause an assertion failure instead of weird misbehavior. This also slows down the compiler's runtime by ~20%.
- `ccache = true` - Use ccache when building llvm
#### `[build]`:
- `compiler-docs = true` - Build compiler documentation
#### `[rust]`:
- `debuginfo = true` - Build a compiler with debuginfo
- `optimize = false` - Disable optimizations to speed up compilation of stage1 rust
- `debuginfo = true` - Build a compiler with debuginfo. Makes building rustc slower, but then you can use a debugger to debug `rustc`.
- `debuginfo-lines = true` - An alternative to `debuginfo = true` that doesn't let you use a debugger, but doesn't make building rustc slower and still gives you line numbers in backtraces.
- `debug-assertions = true` - Makes the log output of `debug!` work.
- `optimize = false` - Disable optimizations to speed up compilation of stage1 rust, but makes the stage1 compiler x100 slower.
For more options, the `config.toml` file contains commented out defaults, with
descriptions of what each option will do.
@ -273,6 +276,27 @@ build, you'll need to build rustdoc specially, since it's not normally built in
stage 1. `python x.py build --stage 1 src/libstd src/tools/rustdoc` will build
rustdoc and libstd, which will allow rustdoc to be run with that toolchain.)
### Out-of-tree builds
[out-of-tree-builds]: #out-of-tree-builds
Rust's `x.py` script fully supports out-of-tree builds - it looks for
the Rust source code from the directory `x.py` was found in, but it
reads the `config.toml` configuration file from the directory it's
run in, and places all build artifacts within a subdirectory named `build`.
This means that if you want to do an out-of-tree build, you can just do it:
```
$ cd my/build/dir
$ cp ~/my-config.toml config.toml # Or fill in config.toml otherwise
$ path/to/rust/x.py build
...
$ # This will use the Rust source code in `path/to/rust`, but build
$ # artifacts will now be in ./build
```
It's absolutely fine to have multiple build directories with different
`config.toml` configurations using the same code.
## Pull Requests
[pull-requests]: #pull-requests

View File

@ -224,8 +224,10 @@ use Bound::{Excluded, Included, Unbounded};
/// types inside a `Vec`, it will not allocate space for them. *Note that in this case
/// the `Vec` may not report a [`capacity`] of 0*. `Vec` will allocate if and only
/// if [`mem::size_of::<T>`]`() * capacity() > 0`. In general, `Vec`'s allocation
/// details are subtle enough that it is strongly recommended that you only
/// free memory allocated by a `Vec` by creating a new `Vec` and dropping it.
/// details are very subtle &mdash; if you intend to allocate memory using a `Vec`
/// and use it for something else (either to pass to unsafe code, or to build your
/// own memory-backed collection), be sure to deallocate this memory by using
/// `from_raw_parts` to recover the `Vec` and then dropping it.
///
/// If a `Vec` *has* allocated memory, then the memory it points to is on the heap
/// (as defined by the allocator Rust is configured to use by default), and its

@ -1 +1 @@
Subproject commit 18feaccbfd0dfbd5ab5d0a2a6eac9c04be667266
Subproject commit 000d06a57a622eb4db4a15d0f76db48571f4d8e4

View File

@ -114,7 +114,7 @@ macro_rules! define_bignum {
/// copying it recklessly may result in the performance hit.
/// Thus this is intentionally not `Copy`.
///
/// All operations available to bignums panic in the case of over/underflows.
/// All operations available to bignums panic in the case of overflows.
/// The caller is responsible to use large enough bignum types.
pub struct $name {
/// One plus the offset to the maximum "digit" in use.

View File

@ -98,10 +98,7 @@ pub mod diy_float;
// `Int` + `SignedInt` implemented for signed integers
macro_rules! int_impl {
($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr,
$add_with_overflow:path,
$sub_with_overflow:path,
$mul_with_overflow:path) => {
($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr) => {
/// Returns the smallest value that can be represented by this integer type.
///
/// # Examples
@ -402,7 +399,7 @@ macro_rules! int_impl {
}
/// Checked integer subtraction. Computes `self - rhs`, returning
/// `None` if underflow occurred.
/// `None` if overflow occurred.
///
/// # Examples
///
@ -420,7 +417,7 @@ macro_rules! int_impl {
}
/// Checked integer multiplication. Computes `self * rhs`, returning
/// `None` if underflow or overflow occurred.
/// `None` if overflow occurred.
///
/// # Examples
///
@ -438,7 +435,7 @@ macro_rules! int_impl {
}
/// Checked integer division. Computes `self / rhs`, returning `None`
/// if `rhs == 0` or the operation results in underflow or overflow.
/// if `rhs == 0` or the operation results in overflow.
///
/// # Examples
///
@ -460,7 +457,7 @@ macro_rules! int_impl {
}
/// Checked integer remainder. Computes `self % rhs`, returning `None`
/// if `rhs == 0` or the operation results in underflow or overflow.
/// if `rhs == 0` or the operation results in overflow.
///
/// # Examples
///
@ -865,11 +862,11 @@ macro_rules! int_impl {
#[inline]
#[stable(feature = "wrapping", since = "1.7.0")]
pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
unsafe {
let (a, b) = $add_with_overflow(self as $ActualT,
rhs as $ActualT);
(a as Self, b)
}
let (a, b) = unsafe {
intrinsics::add_with_overflow(self as $ActualT,
rhs as $ActualT)
};
(a as Self, b)
}
/// Calculates `self` - `rhs`
@ -891,11 +888,11 @@ macro_rules! int_impl {
#[inline]
#[stable(feature = "wrapping", since = "1.7.0")]
pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
unsafe {
let (a, b) = $sub_with_overflow(self as $ActualT,
rhs as $ActualT);
(a as Self, b)
}
let (a, b) = unsafe {
intrinsics::sub_with_overflow(self as $ActualT,
rhs as $ActualT)
};
(a as Self, b)
}
/// Calculates the multiplication of `self` and `rhs`.
@ -915,11 +912,11 @@ macro_rules! int_impl {
#[inline]
#[stable(feature = "wrapping", since = "1.7.0")]
pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
unsafe {
let (a, b) = $mul_with_overflow(self as $ActualT,
rhs as $ActualT);
(a as Self, b)
}
let (a, b) = unsafe {
intrinsics::mul_with_overflow(self as $ActualT,
rhs as $ActualT)
};
(a as Self, b)
}
/// Calculates the divisor when `self` is divided by `rhs`.
@ -1207,82 +1204,50 @@ macro_rules! int_impl {
#[lang = "i8"]
impl i8 {
int_impl! { i8, i8, u8, 8,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
int_impl! { i8, i8, u8, 8 }
}
#[lang = "i16"]
impl i16 {
int_impl! { i16, i16, u16, 16,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
int_impl! { i16, i16, u16, 16 }
}
#[lang = "i32"]
impl i32 {
int_impl! { i32, i32, u32, 32,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
int_impl! { i32, i32, u32, 32 }
}
#[lang = "i64"]
impl i64 {
int_impl! { i64, i64, u64, 64,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
int_impl! { i64, i64, u64, 64 }
}
#[lang = "i128"]
impl i128 {
int_impl! { i128, i128, u128, 128,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
int_impl! { i128, i128, u128, 128 }
}
#[cfg(target_pointer_width = "16")]
#[lang = "isize"]
impl isize {
int_impl! { isize, i16, u16, 16,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
int_impl! { isize, i16, u16, 16 }
}
#[cfg(target_pointer_width = "32")]
#[lang = "isize"]
impl isize {
int_impl! { isize, i32, u32, 32,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
int_impl! { isize, i32, u32, 32 }
}
#[cfg(target_pointer_width = "64")]
#[lang = "isize"]
impl isize {
int_impl! { isize, i64, u64, 64,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
int_impl! { isize, i64, u64, 64 }
}
// `Int` + `UnsignedInt` implemented for unsigned integers
macro_rules! uint_impl {
($SelfT:ty, $ActualT:ty, $BITS:expr,
$ctpop:path,
$ctlz:path,
$ctlz_nonzero:path,
$cttz:path,
$bswap:path,
$add_with_overflow:path,
$sub_with_overflow:path,
$mul_with_overflow:path) => {
($SelfT:ty, $ActualT:ty, $BITS:expr) => {
/// Returns the smallest value that can be represented by this integer type.
///
/// # Examples
@ -1346,7 +1311,7 @@ macro_rules! uint_impl {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn count_ones(self) -> u32 {
unsafe { $ctpop(self as $ActualT) as u32 }
unsafe { intrinsics::ctpop(self as $ActualT) as u32 }
}
/// Returns the number of zeros in the binary representation of `self`.
@ -1381,7 +1346,7 @@ macro_rules! uint_impl {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn leading_zeros(self) -> u32 {
unsafe { $ctlz(self as $ActualT) as u32 }
unsafe { intrinsics::ctlz(self as $ActualT) as u32 }
}
/// Returns the number of trailing zeros in the binary representation
@ -1480,7 +1445,7 @@ macro_rules! uint_impl {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn swap_bytes(self) -> Self {
unsafe { $bswap(self as $ActualT) as Self }
unsafe { intrinsics::bswap(self as $ActualT) as Self }
}
/// Converts an integer from big endian to the target's endianness.
@ -1598,7 +1563,7 @@ macro_rules! uint_impl {
}
/// Checked integer subtraction. Computes `self - rhs`, returning
/// `None` if underflow occurred.
/// `None` if overflow occurred.
///
/// # Examples
///
@ -1616,7 +1581,7 @@ macro_rules! uint_impl {
}
/// Checked integer multiplication. Computes `self * rhs`, returning
/// `None` if underflow or overflow occurred.
/// `None` if overflow occurred.
///
/// # Examples
///
@ -1634,7 +1599,7 @@ macro_rules! uint_impl {
}
/// Checked integer division. Computes `self / rhs`, returning `None`
/// if `rhs == 0` or the operation results in underflow or overflow.
/// if `rhs == 0` or the operation results in overflow.
///
/// # Examples
///
@ -1654,7 +1619,7 @@ macro_rules! uint_impl {
}
/// Checked integer remainder. Computes `self % rhs`, returning `None`
/// if `rhs == 0` or the operation results in underflow or overflow.
/// if `rhs == 0` or the operation results in overflow.
///
/// # Examples
///
@ -1984,11 +1949,11 @@ macro_rules! uint_impl {
#[inline]
#[stable(feature = "wrapping", since = "1.7.0")]
pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
unsafe {
let (a, b) = $add_with_overflow(self as $ActualT,
rhs as $ActualT);
(a as Self, b)
}
let (a, b) = unsafe {
intrinsics::add_with_overflow(self as $ActualT,
rhs as $ActualT)
};
(a as Self, b)
}
/// Calculates `self` - `rhs`
@ -2010,11 +1975,11 @@ macro_rules! uint_impl {
#[inline]
#[stable(feature = "wrapping", since = "1.7.0")]
pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
unsafe {
let (a, b) = $sub_with_overflow(self as $ActualT,
rhs as $ActualT);
(a as Self, b)
}
let (a, b) = unsafe {
intrinsics::sub_with_overflow(self as $ActualT,
rhs as $ActualT)
};
(a as Self, b)
}
/// Calculates the multiplication of `self` and `rhs`.
@ -2034,11 +1999,11 @@ macro_rules! uint_impl {
#[inline]
#[stable(feature = "wrapping", since = "1.7.0")]
pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
unsafe {
let (a, b) = $mul_with_overflow(self as $ActualT,
rhs as $ActualT);
(a as Self, b)
}
let (a, b) = unsafe {
intrinsics::mul_with_overflow(self as $ActualT,
rhs as $ActualT)
};
(a as Self, b)
}
/// Calculates the divisor when `self` is divided by `rhs`.
@ -2223,7 +2188,7 @@ macro_rules! uint_impl {
// (such as intel pre-haswell) have more efficient ctlz
// intrinsics when the argument is non-zero.
let p = self - 1;
let z = unsafe { $ctlz_nonzero(p) };
let z = unsafe { intrinsics::ctlz_nonzero(p) };
<$SelfT>::max_value() >> z
}
@ -2270,15 +2235,7 @@ macro_rules! uint_impl {
#[lang = "u8"]
impl u8 {
uint_impl! { u8, u8, 8,
intrinsics::ctpop,
intrinsics::ctlz,
intrinsics::ctlz_nonzero,
intrinsics::cttz,
intrinsics::bswap,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
uint_impl! { u8, u8, 8 }
/// Checks if the value is within the ASCII range.
@ -2824,95 +2781,39 @@ impl u8 {
#[lang = "u16"]
impl u16 {
uint_impl! { u16, u16, 16,
intrinsics::ctpop,
intrinsics::ctlz,
intrinsics::ctlz_nonzero,
intrinsics::cttz,
intrinsics::bswap,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
uint_impl! { u16, u16, 16 }
}
#[lang = "u32"]
impl u32 {
uint_impl! { u32, u32, 32,
intrinsics::ctpop,
intrinsics::ctlz,
intrinsics::ctlz_nonzero,
intrinsics::cttz,
intrinsics::bswap,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
uint_impl! { u32, u32, 32 }
}
#[lang = "u64"]
impl u64 {
uint_impl! { u64, u64, 64,
intrinsics::ctpop,
intrinsics::ctlz,
intrinsics::ctlz_nonzero,
intrinsics::cttz,
intrinsics::bswap,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
uint_impl! { u64, u64, 64 }
}
#[lang = "u128"]
impl u128 {
uint_impl! { u128, u128, 128,
intrinsics::ctpop,
intrinsics::ctlz,
intrinsics::ctlz_nonzero,
intrinsics::cttz,
intrinsics::bswap,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
uint_impl! { u128, u128, 128 }
}
#[cfg(target_pointer_width = "16")]
#[lang = "usize"]
impl usize {
uint_impl! { usize, u16, 16,
intrinsics::ctpop,
intrinsics::ctlz,
intrinsics::ctlz_nonzero,
intrinsics::cttz,
intrinsics::bswap,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
uint_impl! { usize, u16, 16 }
}
#[cfg(target_pointer_width = "32")]
#[lang = "usize"]
impl usize {
uint_impl! { usize, u32, 32,
intrinsics::ctpop,
intrinsics::ctlz,
intrinsics::ctlz_nonzero,
intrinsics::cttz,
intrinsics::bswap,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
uint_impl! { usize, u32, 32 }
}
#[cfg(target_pointer_width = "64")]
#[lang = "usize"]
impl usize {
uint_impl! { usize, u64, 64,
intrinsics::ctpop,
intrinsics::ctlz,
intrinsics::ctlz_nonzero,
intrinsics::cttz,
intrinsics::bswap,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
uint_impl! { usize, u64, 64 }
}
/// A classification of floating point numbers.

View File

@ -581,8 +581,7 @@ impl<T: ?Sized> *const T {
/// * Both the starting and resulting pointer must be either in bounds or one
/// byte past the end of an allocated object.
///
/// * The computed offset, **in bytes**, cannot overflow or underflow an
/// `isize`.
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
///
/// * The offset being in bounds cannot rely on "wrapping around" the address
/// space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
@ -714,8 +713,7 @@ impl<T: ?Sized> *const T {
/// * Both the starting and resulting pointer must be either in bounds or one
/// byte past the end of an allocated object.
///
/// * The computed offset, **in bytes**, cannot overflow or underflow an
/// `isize`.
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
///
/// * The offset being in bounds cannot rely on "wrapping around" the address
/// space. That is, the infinite-precision sum must fit in a `usize`.
@ -1219,8 +1217,7 @@ impl<T: ?Sized> *mut T {
/// * Both the starting and resulting pointer must be either in bounds or one
/// byte past the end of an allocated object.
///
/// * The computed offset, **in bytes**, cannot overflow or underflow an
/// `isize`.
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
///
/// * The offset being in bounds cannot rely on "wrapping around" the address
/// space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
@ -1419,8 +1416,7 @@ impl<T: ?Sized> *mut T {
/// * Both the starting and resulting pointer must be either in bounds or one
/// byte past the end of an allocated object.
///
/// * The computed offset, **in bytes**, cannot overflow or underflow an
/// `isize`.
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
///
/// * The offset being in bounds cannot rely on "wrapping around" the address
/// space. That is, the infinite-precision sum must fit in a `usize`.

View File

@ -413,27 +413,14 @@ impl<'a> Id<'a> {
/// quotes, ...) will return an empty `Err` value.
pub fn new<Name: IntoCow<'a, str>>(name: Name) -> Result<Id<'a>, ()> {
let name = name.into_cow();
{
let mut chars = name.chars();
match chars.next() {
Some(c) if is_letter_or_underscore(c) => {}
_ => return Err(()),
}
if !chars.all(is_constituent) {
return Err(());
}
match name.chars().next() {
Some(c) if c.is_ascii_alphabetic() || c == '_' => {}
_ => return Err(()),
}
if !name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' ) {
return Err(());
}
return Ok(Id { name: name });
fn is_letter_or_underscore(c: char) -> bool {
in_range('a', c, 'z') || in_range('A', c, 'Z') || c == '_'
}
fn is_constituent(c: char) -> bool {
is_letter_or_underscore(c) || in_range('0', c, '9')
}
fn in_range(low: char, c: char, high: char) -> bool {
low as usize <= c as usize && c as usize <= high as usize
}
}
pub fn as_slice(&'a self) -> &'a str {
@ -484,8 +471,7 @@ pub trait Labeller<'a> {
/// Maps `e` to a label that will be used in the rendered output.
/// The label need not be unique, and may be the empty string; the
/// default is in fact the empty string.
fn edge_label(&'a self, e: &Self::Edge) -> LabelText<'a> {
let _ignored = e;
fn edge_label(&'a self, _e: &Self::Edge) -> LabelText<'a> {
LabelStr("".into_cow())
}
@ -655,79 +641,58 @@ pub fn render_opts<'a, N, E, G, W>(g: &'a G,
G: Labeller<'a, Node=N, Edge=E> + GraphWalk<'a, Node=N, Edge=E>,
W: Write
{
fn writeln<W: Write>(w: &mut W, arg: &[&str]) -> io::Result<()> {
for &s in arg {
w.write_all(s.as_bytes())?;
}
write!(w, "\n")
}
fn indent<W: Write>(w: &mut W) -> io::Result<()> {
w.write_all(b" ")
}
writeln(w, &["digraph ", g.graph_id().as_slice(), " {"])?;
writeln!(w, "digraph {} {{", g.graph_id().as_slice())?;
for n in g.nodes().iter() {
indent(w)?;
write!(w, " ")?;
let id = g.node_id(n);
let escaped = &g.node_label(n).to_dot_string();
let shape;
let mut text = vec![id.as_slice()];
let mut text = Vec::new();
write!(text, "{}", id.as_slice()).unwrap();
if !options.contains(&RenderOption::NoNodeLabels) {
text.push("[label=");
text.push(escaped);
text.push("]");
write!(text, "[label={}]", escaped).unwrap();
}
let style = g.node_style(n);
if !options.contains(&RenderOption::NoNodeStyles) && style != Style::None {
text.push("[style=\"");
text.push(style.as_slice());
text.push("\"]");
write!(text, "[style=\"{}\"]", style.as_slice()).unwrap();
}
if let Some(s) = g.node_shape(n) {
shape = s.to_dot_string();
text.push("[shape=");
text.push(&shape);
text.push("]");
write!(text, "[shape={}]", &s.to_dot_string()).unwrap();
}
text.push(";");
writeln(w, &text)?;
writeln!(text, ";").unwrap();
w.write_all(&text[..])?;
}
for e in g.edges().iter() {
let escaped_label = &g.edge_label(e).to_dot_string();
indent(w)?;
write!(w, " ")?;
let source = g.source(e);
let target = g.target(e);
let source_id = g.node_id(&source);
let target_id = g.node_id(&target);
let mut text = vec![source_id.as_slice(), " -> ", target_id.as_slice()];
let mut text = Vec::new();
write!(text, "{} -> {}", source_id.as_slice(), target_id.as_slice()).unwrap();
if !options.contains(&RenderOption::NoEdgeLabels) {
text.push("[label=");
text.push(escaped_label);
text.push("]");
write!(text, "[label={}]", escaped_label).unwrap();
}
let style = g.edge_style(e);
if !options.contains(&RenderOption::NoEdgeStyles) && style != Style::None {
text.push("[style=\"");
text.push(style.as_slice());
text.push("\"]");
write!(text, "[style=\"{}\"]", style.as_slice()).unwrap();
}
text.push(";");
writeln(w, &text)?;
writeln!(text, ";").unwrap();
w.write_all(&text[..])?;
}
writeln(w, &["}"])
writeln!(w, "}}")
}
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {

View File

@ -341,7 +341,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Span {
std_hash::Hash::hash(&TAG_VALID_SPAN, hasher);
// We truncate the stable_id hash and line and col numbers. The chances
// of causing a collision this way should be minimal.
std_hash::Hash::hash(&file_lo.name, hasher);
std_hash::Hash::hash(&(file_lo.name_hash as u64), hasher);
let col = (col_lo.0 as u64) & 0xFF;
let line = ((line_lo as u64) & 0xFF_FF_FF) << 8;

View File

@ -387,7 +387,8 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for FileMap {
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
let FileMap {
ref name,
name: _, // We hash the smaller name_hash instead of this
name_hash,
name_was_remapped,
unmapped_path: _,
crate_of_origin,
@ -402,7 +403,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for FileMap {
ref non_narrow_chars,
} = *self;
name.hash_stable(hcx, hasher);
(name_hash as u64).hash_stable(hcx, hasher);
name_was_remapped.hash_stable(hcx, hasher);
DefId {

View File

@ -558,24 +558,29 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
}
ty::TyError => { }
_ => {
let def_id = self.mc.tables.type_dependent_defs()[call.hir_id].def_id();
let call_scope = region::Scope::Node(call.hir_id.local_id);
match OverloadedCallType::from_method_id(self.tcx(), def_id) {
FnMutOverloadedCall => {
let call_scope_r = self.tcx().mk_region(ty::ReScope(call_scope));
self.borrow_expr(callee,
call_scope_r,
ty::MutBorrow,
ClosureInvocation);
if let Some(def) = self.mc.tables.type_dependent_defs().get(call.hir_id) {
let def_id = def.def_id();
let call_scope = region::Scope::Node(call.hir_id.local_id);
match OverloadedCallType::from_method_id(self.tcx(), def_id) {
FnMutOverloadedCall => {
let call_scope_r = self.tcx().mk_region(ty::ReScope(call_scope));
self.borrow_expr(callee,
call_scope_r,
ty::MutBorrow,
ClosureInvocation);
}
FnOverloadedCall => {
let call_scope_r = self.tcx().mk_region(ty::ReScope(call_scope));
self.borrow_expr(callee,
call_scope_r,
ty::ImmBorrow,
ClosureInvocation);
}
FnOnceOverloadedCall => self.consume_expr(callee),
}
FnOverloadedCall => {
let call_scope_r = self.tcx().mk_region(ty::ReScope(call_scope));
self.borrow_expr(callee,
call_scope_r,
ty::ImmBorrow,
ClosureInvocation);
}
FnOnceOverloadedCall => self.consume_expr(callee),
} else {
self.tcx().sess.delay_span_bug(call.span,
"no type-dependent def for overloaded call");
}
}
}

View File

@ -528,6 +528,25 @@ impl OutputFilenames {
pub fn filestem(&self) -> String {
format!("{}{}", self.out_filestem, self.extra)
}
pub fn contains_path(&self, input_path: &PathBuf) -> bool {
let input_path = input_path.canonicalize().ok();
if input_path.is_none() {
return false
}
match self.single_output_file {
Some(ref output_path) => output_path.canonicalize().ok() == input_path,
None => {
for k in self.outputs.keys() {
let output_path = self.path(k.to_owned());
if output_path.canonicalize().ok() == input_path {
return true;
}
}
false
}
}
}
}
pub fn host_triple() -> &'static str {
@ -596,6 +615,12 @@ impl Options {
).map(|(src, dst)| (src.clone(), dst.clone())).collect()
)
}
/// True if there will be an output file generated
pub fn will_create_output_file(&self) -> bool {
!self.debugging_opts.parse_only && // The file is just being parsed
!self.debugging_opts.ls // The file is just being queried
}
}
// The type of entry function, so

View File

@ -1484,27 +1484,25 @@ impl<'a, 'tcx> LayoutDetails {
Some(niche) => niche,
None => continue
};
let mut align = dl.aggregate_align;
let st = variants.iter().enumerate().map(|(j, v)| {
let mut st = univariant_uninterned(v,
&def.repr, StructKind::AlwaysSized)?;
st.variants = Variants::Single { index: j };
align = align.max(st.align);
Ok(st)
}).collect::<Result<Vec<_>, _>>()?;
let offset = st[i].fields.offset(field_index) + offset;
let LayoutDetails { mut size, mut align, .. } = st[i];
let size = st[i].size;
let mut niche_align = niche.value.align(dl);
let abi = if offset.bytes() == 0 && niche.value.size(dl) == size {
Abi::Scalar(niche.clone())
} else {
if offset.abi_align(niche_align) != offset {
niche_align = dl.i8_align;
}
Abi::Aggregate { sized: true }
};
align = align.max(niche_align);
size = size.abi_align(align);
return Ok(tcx.intern_layout(LayoutDetails {
variants: Variants::NicheFilling {

View File

@ -71,6 +71,7 @@ use profile;
pub fn compile_input(sess: &Session,
cstore: &CStore,
input_path: &Option<PathBuf>,
input: &Input,
outdir: &Option<PathBuf>,
output: &Option<PathBuf>,
@ -142,6 +143,20 @@ pub fn compile_input(sess: &Session,
};
let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
// Ensure the source file isn't accidentally overwritten during compilation.
match *input_path {
Some(ref input_path) => {
if outputs.contains_path(input_path) && sess.opts.will_create_output_file() {
sess.err(&format!(
"the input file \"{}\" would be overwritten by the generated executable",
input_path.display()));
return Err(CompileIncomplete::Stopped);
}
},
None => {}
}
let crate_name =
::rustc_trans_utils::link::find_crate_name(Some(sess), &krate.attrs, input);
let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {

View File

@ -232,7 +232,7 @@ pub fn run_compiler<'a>(args: &[String],
let loader = file_loader.unwrap_or(box RealFileLoader);
let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
let mut sess = session::build_session_with_codemap(
sopts, input_file_path, descriptions, codemap, emitter_dest,
sopts, input_file_path.clone(), descriptions, codemap, emitter_dest,
);
rustc_trans::init(&sess);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
@ -252,6 +252,7 @@ pub fn run_compiler<'a>(args: &[String],
let control = callbacks.build_controller(&sess, &matches);
(driver::compile_input(&sess,
&cstore,
&input_file_path,
&input,
&odir,
&ofile,

View File

@ -349,7 +349,27 @@ impl MissingDoc {
}
}
let has_doc = attrs.iter().any(|a| a.is_value_str() && a.check_name("doc"));
fn has_doc(attr: &ast::Attribute) -> bool {
if !attr.check_name("doc") {
return false;
}
if attr.is_value_str() {
return true;
}
if let Some(list) = attr.meta_item_list() {
for meta in list {
if meta.check_name("include") {
return true;
}
}
}
false
}
let has_doc = attrs.iter().any(|a| has_doc(a));
if !has_doc {
cx.span_lint(MISSING_DOCS,
cx.tcx.sess.codemap().def_span(sp),

View File

@ -1129,6 +1129,7 @@ impl<'a, 'tcx> CrateMetadata {
lines,
multibyte_chars,
non_narrow_chars,
name_hash,
.. } = filemap_to_import;
let source_length = (end_pos - start_pos).to_usize();
@ -1155,6 +1156,7 @@ impl<'a, 'tcx> CrateMetadata {
name_was_remapped,
self.cnum.as_u32(),
src_hash,
name_hash,
source_length,
lines,
multibyte_chars,

View File

@ -28,8 +28,10 @@ use rustc::ty::codec::{self as ty_codec, TyEncoder};
use rustc::session::config::{self, CrateTypeProcMacro};
use rustc::util::nodemap::{FxHashMap, NodeSet};
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
use std::hash::Hash;
use std::io::prelude::*;
use std::io::Cursor;
use std::path::Path;
@ -290,6 +292,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} else {
let mut adapted = (**filemap).clone();
adapted.name = Path::new(&working_dir).join(name).into();
adapted.name_hash = {
let mut hasher: StableHasher<u128> = StableHasher::new();
adapted.name.hash(&mut hasher);
hasher.finish()
};
Rc::new(adapted)
}
},

View File

@ -377,6 +377,17 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<
assert!(target_cgu_count >= 1);
let codegen_units = &mut initial_partitioning.codegen_units;
// Note that at this point in time the `codegen_units` here may not be in a
// deterministic order (but we know they're deterministically the same set).
// We want this merging to produce a deterministic ordering of codegen units
// from the input.
//
// Due to basically how we've implemented the merging below (merge the two
// smallest into each other) we're sure to start off with a deterministic
// order (sorted by name). This'll mean that if two cgus have the same size
// the stable sort below will keep everything nice and deterministic.
codegen_units.sort_by_key(|cgu| cgu.name().clone());
// Merge the two smallest codegen units until the target size is reached.
// Note that "size" is estimated here rather inaccurately as the number of
// translation items in a given unit. This could be improved on.

View File

@ -3720,9 +3720,10 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
})).and_then(|did| c.impls.get(&did));
if let Some(impls) = inner_impl {
out.push_str("<a class=\"sidebar-title\" href=\"#deref-methods\">");
out.push_str(&format!("Methods from {:#}&lt;Target={:#}&gt;",
impl_.inner_impl().trait_.as_ref().unwrap(),
target));
out.push_str(&format!("Methods from {}&lt;Target={}&gt;",
Escape(&format!("{:#}",
impl_.inner_impl().trait_.as_ref().unwrap())),
Escape(&format!("{:#}", target))));
out.push_str("</a>");
let ret = impls.iter()
.filter(|i| i.inner_impl().trait_.is_none())

View File

@ -263,7 +263,7 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, cfgs: Vec<String>,
}
let res = panic::catch_unwind(AssertUnwindSafe(|| {
driver::compile_input(&sess, &cstore, &input, &out, &None, None, &control)
driver::compile_input(&sess, &cstore, &None, &input, &out, &None, None, &control)
}));
let compile_result = match res {
@ -533,7 +533,7 @@ impl Collector {
should_panic: testing::ShouldPanic::No,
allow_fail,
},
testfn: testing::DynTestFn(box move |()| {
testfn: testing::DynTestFn(box move || {
let panic = io::set_panic(None);
let print = io::set_print(None);
match {

View File

@ -263,7 +263,7 @@ impl<R: Seek> Seek for BufReader<R> {
/// See `std::io::Seek` for more details.
///
/// Note: In the edge case where you're seeking with `SeekFrom::Current(n)`
/// where `n` minus the internal buffer length underflows an `i64`, two
/// where `n` minus the internal buffer length overflows an `i64`, two
/// seeks will be performed instead of one. If the second seek returns
/// `Err`, the underlying reader will be left at the same position it would
/// have if you seeked to `SeekFrom::Current(0)`.

View File

@ -290,7 +290,7 @@ impl Duration {
}
/// Checked `Duration` subtraction. Computes `self - other`, returning [`None`]
/// if the result would be negative or if underflow occurred.
/// if the result would be negative or if overflow occurred.
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
///

View File

@ -246,6 +246,7 @@ impl CodeMap {
name_was_remapped: bool,
crate_of_origin: u32,
src_hash: u128,
name_hash: u128,
source_len: usize,
mut file_local_lines: Vec<BytePos>,
mut file_local_multibyte_chars: Vec<MultiByteChar>,
@ -282,6 +283,7 @@ impl CodeMap {
lines: RefCell::new(file_local_lines),
multibyte_chars: RefCell::new(file_local_multibyte_chars),
non_narrow_chars: RefCell::new(file_local_non_narrow_chars),
name_hash,
});
files.push(filemap.clone());

View File

@ -1115,15 +1115,19 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
match File::open(&filename).and_then(|mut f| f.read_to_end(&mut buf)) {
Ok(..) => {}
Err(e) => {
self.cx.span_warn(at.span,
&format!("couldn't read {}: {}",
filename.display(),
e));
self.cx.span_err(at.span,
&format!("couldn't read {}: {}",
filename.display(),
e));
}
}
match String::from_utf8(buf) {
Ok(src) => {
// Add this input file to the code map to make it available as
// dependency information
self.cx.codemap().new_filemap_and_lines(&filename, &src);
let include_info = vec![
dummy_spanned(ast::NestedMetaItemKind::MetaItem(
attr::mk_name_value_item_str("file".into(),
@ -1137,9 +1141,9 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
attr::mk_list_item("include".into(), include_info))));
}
Err(_) => {
self.cx.span_warn(at.span,
&format!("{} wasn't a utf-8 file",
filename.display()));
self.cx.span_err(at.span,
&format!("{} wasn't a utf-8 file",
filename.display()));
}
}
} else {

View File

@ -30,7 +30,7 @@ use std::borrow::Cow;
use std::cell::{Cell, RefCell};
use std::cmp::{self, Ordering};
use std::fmt;
use std::hash::Hasher;
use std::hash::{Hasher, Hash};
use std::ops::{Add, Sub};
use std::path::PathBuf;
use std::rc::Rc;
@ -691,6 +691,8 @@ pub struct FileMap {
pub multibyte_chars: RefCell<Vec<MultiByteChar>>,
/// Width of characters that are not narrow in the source code
pub non_narrow_chars: RefCell<Vec<NonNarrowChar>>,
/// A hash of the filename, used for speeding up the incr. comp. hashing.
pub name_hash: u128,
}
impl Encodable for FileMap {
@ -752,6 +754,9 @@ impl Encodable for FileMap {
})?;
s.emit_struct_field("non_narrow_chars", 8, |s| {
(*self.non_narrow_chars.borrow()).encode(s)
})?;
s.emit_struct_field("name_hash", 9, |s| {
self.name_hash.encode(s)
})
})
}
@ -801,6 +806,8 @@ impl Decodable for FileMap {
d.read_struct_field("multibyte_chars", 7, |d| Decodable::decode(d))?;
let non_narrow_chars: Vec<NonNarrowChar> =
d.read_struct_field("non_narrow_chars", 8, |d| Decodable::decode(d))?;
let name_hash: u128 =
d.read_struct_field("name_hash", 9, |d| Decodable::decode(d))?;
Ok(FileMap {
name,
name_was_remapped,
@ -816,7 +823,8 @@ impl Decodable for FileMap {
external_src: RefCell::new(ExternalSource::AbsentOk),
lines: RefCell::new(lines),
multibyte_chars: RefCell::new(multibyte_chars),
non_narrow_chars: RefCell::new(non_narrow_chars)
non_narrow_chars: RefCell::new(non_narrow_chars),
name_hash,
})
})
}
@ -836,9 +844,16 @@ impl FileMap {
start_pos: BytePos) -> FileMap {
remove_bom(&mut src);
let mut hasher: StableHasher<u128> = StableHasher::new();
hasher.write(src.as_bytes());
let src_hash = hasher.finish();
let src_hash = {
let mut hasher: StableHasher<u128> = StableHasher::new();
hasher.write(src.as_bytes());
hasher.finish()
};
let name_hash = {
let mut hasher: StableHasher<u128> = StableHasher::new();
name.hash(&mut hasher);
hasher.finish()
};
let end_pos = start_pos.to_usize() + src.len();
FileMap {
@ -854,6 +869,7 @@ impl FileMap {
lines: RefCell::new(Vec::new()),
multibyte_chars: RefCell::new(Vec::new()),
non_narrow_chars: RefCell::new(Vec::new()),
name_hash,
}
}

View File

@ -35,6 +35,7 @@
#![deny(warnings)]
#![feature(asm)]
#![feature(fnbox)]
#![cfg_attr(unix, feature(libc))]
#![feature(set_stdio)]
#![feature(panic_unwind)]
@ -56,6 +57,7 @@ use self::OutputLocation::*;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::any::Any;
use std::boxed::FnBox;
use std::cmp;
use std::collections::BTreeMap;
use std::env;
@ -133,16 +135,6 @@ pub trait TDynBenchFn: Send {
fn run(&self, harness: &mut Bencher);
}
pub trait FnBox<T>: Send + 'static {
fn call_box(self: Box<Self>, t: T);
}
impl<T, F: FnOnce(T) + Send + 'static> FnBox<T> for F {
fn call_box(self: Box<F>, t: T) {
(*self)(t)
}
}
// A function that runs a test. If the function returns successfully,
// the test succeeds; if the function panics then the test fails. We
// may need to come up with a more clever definition of test in order
@ -150,7 +142,7 @@ impl<T, F: FnOnce(T) + Send + 'static> FnBox<T> for F {
pub enum TestFn {
StaticTestFn(fn()),
StaticBenchFn(fn(&mut Bencher)),
DynTestFn(Box<FnBox<()>>),
DynTestFn(Box<FnBox() + Send>),
DynBenchFn(Box<TDynBenchFn + 'static>),
}
@ -1337,14 +1329,14 @@ pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAnd
tests.into_iter().map(|x| {
let testfn = match x.testfn {
DynBenchFn(bench) => {
DynTestFn(Box::new(move |()| {
DynTestFn(Box::new(move || {
bench::run_once(|b| {
__rust_begin_short_backtrace(|| bench.run(b))
})
}))
}
StaticBenchFn(benchfn) => {
DynTestFn(Box::new(move |()| {
DynTestFn(Box::new(move || {
bench::run_once(|b| {
__rust_begin_short_backtrace(|| benchfn(b))
})
@ -1379,7 +1371,7 @@ pub fn run_test(opts: &TestOpts,
fn run_test_inner(desc: TestDesc,
monitor_ch: Sender<MonitorMsg>,
nocapture: bool,
testfn: Box<FnBox<()>>) {
testfn: Box<FnBox() + Send>) {
struct Sink(Arc<Mutex<Vec<u8>>>);
impl Write for Sink {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
@ -1405,9 +1397,7 @@ pub fn run_test(opts: &TestOpts,
None
};
let result = catch_unwind(AssertUnwindSafe(|| {
testfn.call_box(())
}));
let result = catch_unwind(AssertUnwindSafe(testfn));
if let Some((printio, panicio)) = oldio {
io::set_print(printio);
@ -1449,14 +1439,14 @@ pub fn run_test(opts: &TestOpts,
return;
}
DynTestFn(f) => {
let cb = move |()| {
__rust_begin_short_backtrace(|| f.call_box(()))
let cb = move || {
__rust_begin_short_backtrace(f)
};
run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb))
}
StaticTestFn(f) =>
run_test_inner(desc, monitor_ch, opts.nocapture,
Box::new(move |()| __rust_begin_short_backtrace(f))),
Box::new(move || __rust_begin_short_backtrace(f))),
}
}
@ -1720,7 +1710,7 @@ mod tests {
should_panic: ShouldPanic::No,
allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| f())),
testfn: DynTestFn(Box::new(f)),
};
let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx);
@ -1738,7 +1728,7 @@ mod tests {
should_panic: ShouldPanic::No,
allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| f())),
testfn: DynTestFn(Box::new(f)),
};
let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx);
@ -1758,7 +1748,7 @@ mod tests {
should_panic: ShouldPanic::Yes,
allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| f())),
testfn: DynTestFn(Box::new(f)),
};
let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx);
@ -1778,7 +1768,7 @@ mod tests {
should_panic: ShouldPanic::YesWithMessage("error message"),
allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| f())),
testfn: DynTestFn(Box::new(f)),
};
let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx);
@ -1800,7 +1790,7 @@ mod tests {
should_panic: ShouldPanic::YesWithMessage(expected),
allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| f())),
testfn: DynTestFn(Box::new(f)),
};
let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx);
@ -1818,7 +1808,7 @@ mod tests {
should_panic: ShouldPanic::Yes,
allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| f())),
testfn: DynTestFn(Box::new(f)),
};
let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx);
@ -1852,7 +1842,7 @@ mod tests {
should_panic: ShouldPanic::No,
allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| {})),
testfn: DynTestFn(Box::new(move || {})),
},
TestDescAndFn {
desc: TestDesc {
@ -1861,7 +1851,7 @@ mod tests {
should_panic: ShouldPanic::No,
allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| {})),
testfn: DynTestFn(Box::new(move || {})),
}];
let filtered = filter_tests(&opts, tests);
@ -1885,7 +1875,7 @@ mod tests {
should_panic: ShouldPanic::No,
allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| {}))
testfn: DynTestFn(Box::new(move || {}))
})
.collect()
}
@ -1967,7 +1957,7 @@ mod tests {
should_panic: ShouldPanic::No,
allow_fail: false,
},
testfn: DynTestFn(Box::new(move |()| testfn())),
testfn: DynTestFn(Box::new(testfn)),
};
tests.push(test);
}

View File

@ -35,20 +35,24 @@ The error levels that you can have are:
## Summary of Header Commands
Header commands specify something about the entire test file as a
whole, instead of just a few lines inside the test.
whole. They are normally put right after the copyright comment, e.g.:
```Rust
// Copyright blah blah blah
// except according to those terms.
// ignore-test This doesn't actually work
```
### Ignoring tests
These are used to ignore the test in some situations, which means the test won't
be compiled or run.
* `ignore-X` where `X` is a target detail or stage will ignore the test accordingly (see below)
* `ignore-pretty` will not compile the pretty-printed test (this is done to test the pretty-printer, but might not always work)
* `ignore-test` always ignores the test
* `ignore-lldb` and `ignore-gdb` will skip the debuginfo tests
* `min-{gdb,lldb}-version`
* `should-fail` indicates that the test should fail; used for "meta testing",
where we test the compiletest program itself to check that it will generate
errors in appropriate scenarios. This header is ignored for pretty-printer tests.
* `gate-test-X` where `X` is a feature marks the test as "gate test" for feature X.
Such tests are supposed to ensure that the compiler errors when usage of a gated
feature is attempted without the proper `#![feature(X)]` tag.
Each unstable lang feature is required to have a gate test.
* `ignore-lldb` and `ignore-gdb` will skip a debuginfo test on that debugger.
Some examples of `X` in `ignore-X`:
@ -58,6 +62,22 @@ Some examples of `X` in `ignore-X`:
* Pointer width: `32bit`, `64bit`.
* Stage: `stage0`, `stage1`, `stage2`.
### Other Header Commands
* `min-{gdb,lldb}-version`
* `min-llvm-version`
* `must-compile-successfully` for UI tests, indicates that the test is supposed
to compile, as opposed to the default where the test is supposed to error out.
* `compile-flags` passes extra command-line args to the compiler,
e.g. `compile-flags -g` which forces debuginfo to be enabled.
* `should-fail` indicates that the test should fail; used for "meta testing",
where we test the compiletest program itself to check that it will generate
errors in appropriate scenarios. This header is ignored for pretty-printer tests.
* `gate-test-X` where `X` is a feature marks the test as "gate test" for feature X.
Such tests are supposed to ensure that the compiler errors when usage of a gated
feature is attempted without the proper `#![feature(X)]` tag.
Each unstable lang feature is required to have a gate test.
## Revisions
Certain classes of tests support "revisions" (as of the time of this
@ -109,6 +129,12 @@ fails, we will print out the current output, but it is also saved in
printed as part of the test failure message), so you can run `diff` and
so forth.
Normally, the test-runner checks that UI tests fail compilation. If you want
to do a UI test for code that *compiles* (e.g. to test warnings, or if you
have a collection of tests, only some of which error out), you can use the
`// must-compile-successfully` header command to have the test runner instead
check that the test compiles successfully.
### Editing and updating the reference files
If you have changed the compiler's output intentionally, or you are

View File

@ -0,0 +1,16 @@
// Copyright 2012-2015 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.
#![feature(external_doc)]
#[doc(include = "not-a-file.md")] //~ ERROR: couldn't read
pub struct SomeStruct;
fn main() {}

View File

@ -0,0 +1,14 @@
// Copyright 2017 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.
fn main() {
struct Foo;
(1 .. 2).find(|_| Foo(0) == 0); //~ ERROR expected function, found `main::Foo`
}

View File

@ -8,7 +8,7 @@ ifneq ($(shell uname),FreeBSD)
ifndef IS_WINDOWS
all:
$(RUSTC) --emit dep-info main.rs
$(CGREP) "input.txt" "input.bin" < $(TMPDIR)/main.d
$(CGREP) "input.txt" "input.bin" "input.md" < $(TMPDIR)/main.d
else
all:

View File

@ -0,0 +1 @@
# Hello, world!

View File

@ -8,6 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(external_doc)]
#[doc(include="input.md")]
pub struct SomeStruct;
pub fn main() {
const INPUT_TXT: &'static str = include_str!("input.txt");
const INPUT_BIN: &'static [u8] = include_bytes!("input.bin");

View File

@ -71,5 +71,5 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
let (sess, cstore) = basic_sess(sysroot);
let control = CompileController::basic();
let input = Input::Str { name: FileName::Anon, input: code };
let _ = compile_input(&sess, &cstore, &input, &None, &Some(output), None, &control);
let _ = compile_input(&sess, &cstore, &None, &input, &None, &Some(output), None, &control);
}

View File

@ -0,0 +1,10 @@
-include ../tools.mk
all:
cp foo.rs $(TMPDIR)/foo
$(RUSTC) $(TMPDIR)/foo 2>&1 \
| $(CGREP) -e "the input file \".*foo\" would be overwritten by the generated executable"
$(RUSTC) foo.rs 2>&1 && $(RUSTC) -Z ls $(TMPDIR)/foo 2>&1
cp foo.rs $(TMPDIR)/foo.rs
$(RUSTC) $(TMPDIR)/foo.rs -o $(TMPDIR)/foo.rs 2>&1 \
| $(CGREP) -e "the input file \".*foo.rs\" would be overwritten by the generated executable"

View File

@ -0,0 +1,11 @@
// Copyright 2017 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.
fn main() {}

View File

@ -7,8 +7,8 @@ all:
cp foo.rs $(TMPDIR)/.foo.bar
$(RUSTC) $(TMPDIR)/.foo.bar 2>&1 \
| $(CGREP) -e "invalid character.*in crate name:"
cp foo.rs $(TMPDIR)/+foo+bar
$(RUSTC) $(TMPDIR)/+foo+bar 2>&1 \
cp foo.rs $(TMPDIR)/+foo+bar.rs
$(RUSTC) $(TMPDIR)/+foo+bar.rs 2>&1 \
| $(CGREP) -e "invalid character.*in crate name:"
cp foo.rs $(TMPDIR)/-foo.rs
$(RUSTC) $(TMPDIR)/-foo.rs 2>&1 \

View File

@ -19,7 +19,9 @@ impl<T: Copy> Clone for Packed<T> {
fn sanity_check_size<T: Copy>(one: T) {
let two = [one, one];
let stride = (&two[1] as *const _ as usize) - (&two[0] as *const _ as usize);
assert_eq!(stride, std::mem::size_of_val(&one));
let (size, align) = (std::mem::size_of::<T>(), std::mem::align_of::<T>());
assert_eq!(stride, size);
assert_eq!(size % align, 0);
}
fn main() {
@ -32,5 +34,12 @@ fn main() {
// In #46769, `Option<(Packed<&()>, bool)>` was found to have
// pointer alignment, without actually being aligned in size.
// E.g. on 64-bit platforms, it had alignment `8` but size `9`.
sanity_check_size(Some((Packed(&()), true)));
type PackedRefAndBool<'a> = (Packed<&'a ()>, bool);
sanity_check_size::<Option<PackedRefAndBool>>(Some((Packed(&()), true)));
// Make sure we don't pay for the enum optimization in size,
// e.g. we shouldn't need extra padding after the packed data.
assert_eq!(std::mem::align_of::<Option<PackedRefAndBool>>(), 1);
assert_eq!(std::mem::size_of::<Option<PackedRefAndBool>>(),
std::mem::size_of::<PackedRefAndBool>());
}

View File

@ -9,6 +9,7 @@
// except according to those terms.
#![feature(external_doc)]
#![deny(missing_doc)]
#[doc(include="external-cross-doc.md")]
pub struct NeedMoreDocs;

View File

@ -0,0 +1,45 @@
// Copyright 2017 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.
#![crate_name = "foo"]
use std::ops::{Deref, DerefMut};
#[derive(Debug, Clone)]
pub struct Title {
name: String,
}
#[derive(Debug, Clone)]
pub struct TitleList {
pub members: Vec<Title>,
}
impl TitleList {
pub fn new() -> Self {
TitleList { members: Vec::new() }
}
}
impl Deref for TitleList {
type Target = Vec<Title>;
fn deref(&self) -> &Self::Target {
&self.members
}
}
// @has foo/struct.TitleList.html
// @has - '//*[@class="sidebar-title"]' 'Methods from Deref<Target=Vec<Title>>'
impl DerefMut for TitleList {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.members
}
}

View File

@ -711,7 +711,7 @@ pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName
pub fn make_test_closure(config: &Config, testpaths: &TestPaths) -> test::TestFn {
let config = config.clone();
let testpaths = testpaths.clone();
test::DynTestFn(Box::new(move |()| runtest::run(config, &testpaths)))
test::DynTestFn(Box::new(move || runtest::run(config, &testpaths)))
}
/// Returns (Path to GDB, GDB Version, GDB has Rust Support)