diff options
| author | bors <bors@rust-lang.org> | 2017-12-21 23:01:27 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-12-21 23:01:27 +0000 |
| commit | ba2741594ba2d4de2ad8cea69def6408ff5409af (patch) | |
| tree | 2c17b5743bf95d61eef4f3c307bc2823520d768f /src | |
| parent | 250b492052e94d76bd318a4b932159395da55981 (diff) | |
| parent | 0787ad92614df48096dbb5cbd6f2cf7833c97293 (diff) | |
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:
Diffstat (limited to 'src')
39 files changed, 424 insertions, 324 deletions
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 67ccb5cab6d..93d7e66b7b2 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -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 — 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 diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins -Subproject 18feaccbfd0dfbd5ab5d0a2a6eac9c04be66726 +Subproject 000d06a57a622eb4db4a15d0f76db48571f4d8e diff --git a/src/libcore/num/bignum.rs b/src/libcore/num/bignum.rs index b5553fb2947..732a02e8c42 100644 --- a/src/libcore/num/bignum.rs +++ b/src/libcore/num/bignum.rs @@ -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. diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 245ca83f28f..851c0a0dd6f 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -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. diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 39cf2ec4c21..85bdeae442b 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -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`. diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 5b1cf2dee9a..110493bbec1 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -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(()); - } - } - 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') + match name.chars().next() { + Some(c) if c.is_ascii_alphabetic() || c == '_' => {} + _ => return Err(()), } - fn in_range(low: char, c: char, high: char) -> bool { - low as usize <= c as usize && c as usize <= high as usize + if !name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' ) { + return Err(()); } + return Ok(Id { name: name }); } 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 { diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 7099b951129..2945b1ab912 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -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; diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index c25aa10eb1e..57120d61e7c 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -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 { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 9018b9fe590..3bcde93fde5 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -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); - } - FnOverloadedCall => { - let call_scope_r = self.tcx().mk_region(ty::ReScope(call_scope)); - self.borrow_expr(callee, - call_scope_r, - ty::ImmBorrow, - 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), } - FnOnceOverloadedCall => self.consume_expr(callee), + } else { + self.tcx().sess.delay_span_bug(call.span, + "no type-dependent def for overloaded call"); } } } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 6e0372f009e..7e80139b791 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -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 diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index a2692fb8f5a..978c6c74233 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -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 { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 9e5de8d54e9..a288ff6316f 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -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 } = { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 29d3d31e451..60857505c7a 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -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, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 81db44b0553..501f6bb0c0d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -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), diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 49a017535ff..0e9f4a8f178 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -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, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 29369f9f8bb..5ddbb18450e 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -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) } }, diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index e2640d695c6..b1fef274cba 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -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. diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 515baa2c669..3be44f30958 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -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 {:#}<Target={:#}>", - impl_.inner_impl().trait_.as_ref().unwrap(), - target)); + out.push_str(&format!("Methods from {}<Target={}>", + 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()) diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index abb90200370..8e861f10dd8 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -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 { diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 6d3fbc9d268..8308ab48d9c 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -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)`. diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index a74e8a21c42..15ddb62bab5 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -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 /// diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 2c91d60ce9d..e49a7117192 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -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()); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 07ea6a09086..81baa0c3954 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -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 { diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 8d5d7c81c0e..85f0925b982 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -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, } } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index bc96a5d6740..0d837c470a2 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -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); } diff --git a/src/test/COMPILER_TESTS.md b/src/test/COMPILER_TESTS.md index 021f27dacbe..c255294e790 100644 --- a/src/test/COMPILER_TESTS.md +++ b/src/test/COMPILER_TESTS.md @@ -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 diff --git a/src/test/compile-fail/external-doc-error.rs b/src/test/compile-fail/external-doc-error.rs new file mode 100644 index 00000000000..1ae0d0bd276 --- /dev/null +++ b/src/test/compile-fail/external-doc-error.rs @@ -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() {} diff --git a/src/test/compile-fail/issue-46771.rs b/src/test/compile-fail/issue-46771.rs new file mode 100644 index 00000000000..f8bcd8861f3 --- /dev/null +++ b/src/test/compile-fail/issue-46771.rs @@ -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` +} diff --git a/src/test/run-make/include_bytes_deps/Makefile b/src/test/run-make/include_bytes_deps/Makefile index f7b1d21ace2..1293695b799 100644 --- a/src/test/run-make/include_bytes_deps/Makefile +++ b/src/test/run-make/include_bytes_deps/Makefile @@ -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: diff --git a/src/test/run-make/include_bytes_deps/input.md b/src/test/run-make/include_bytes_deps/input.md new file mode 100644 index 00000000000..2a19b7405f7 --- /dev/null +++ b/src/test/run-make/include_bytes_deps/input.md @@ -0,0 +1 @@ +# Hello, world! diff --git a/src/test/run-make/include_bytes_deps/main.rs b/src/test/run-make/include_bytes_deps/main.rs index 579b2a452a1..27ca1a46a50 100644 --- a/src/test/run-make/include_bytes_deps/main.rs +++ b/src/test/run-make/include_bytes_deps/main.rs @@ -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"); diff --git a/src/test/run-make/issue-19371/foo.rs b/src/test/run-make/issue-19371/foo.rs index cfe8048638a..f0ab1d5dc0f 100644 --- a/src/test/run-make/issue-19371/foo.rs +++ b/src/test/run-make/issue-19371/foo.rs @@ -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); } diff --git a/src/test/run-make/output-filename-overwrites-input/Makefile b/src/test/run-make/output-filename-overwrites-input/Makefile new file mode 100644 index 00000000000..0554627d677 --- /dev/null +++ b/src/test/run-make/output-filename-overwrites-input/Makefile @@ -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" diff --git a/src/test/run-make/output-filename-overwrites-input/foo.rs b/src/test/run-make/output-filename-overwrites-input/foo.rs new file mode 100644 index 00000000000..046d27a9f0f --- /dev/null +++ b/src/test/run-make/output-filename-overwrites-input/foo.rs @@ -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() {} diff --git a/src/test/run-make/weird-output-filenames/Makefile b/src/test/run-make/weird-output-filenames/Makefile index a5543e3b2c4..f161fe9f8e8 100644 --- a/src/test/run-make/weird-output-filenames/Makefile +++ b/src/test/run-make/weird-output-filenames/Makefile @@ -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 \ diff --git a/src/test/run-pass/packed-struct-optimized-enum.rs b/src/test/run-pass/packed-struct-optimized-enum.rs index b8a1e6f2f54..7968ae2278a 100644 --- a/src/test/run-pass/packed-struct-optimized-enum.rs +++ b/src/test/run-pass/packed-struct-optimized-enum.rs @@ -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>()); } diff --git a/src/test/rustdoc/auxiliary/external-cross.rs b/src/test/rustdoc/auxiliary/external-cross.rs index cb14fec7abe..767fb05313a 100644 --- a/src/test/rustdoc/auxiliary/external-cross.rs +++ b/src/test/rustdoc/auxiliary/external-cross.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(external_doc)] +#![deny(missing_doc)] #[doc(include="external-cross-doc.md")] pub struct NeedMoreDocs; diff --git a/src/test/rustdoc/escape-deref-methods.rs b/src/test/rustdoc/escape-deref-methods.rs new file mode 100644 index 00000000000..f31b0ddca9a --- /dev/null +++ b/src/test/rustdoc/escape-deref-methods.rs @@ -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 + } +} diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 8546289fdec..80630b5e2cf 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -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) |
