diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index c47f4fd8ec64b..5ca5ce1648f2f 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -11,8 +11,8 @@ //! rustbuild, the Rust build system //! //! This is the entry point for the build system used to compile the `rustc` -//! compiler. Lots of documentation can be found in the `README.md` file next to -//! this file, and otherwise documentation can be found throughout the `build` +//! compiler. Lots of documentation can be found in the `README.md` file in the +//! parent directory, and otherwise documentation can be found throughout the `build` //! directory in each respective module. #![deny(warnings)] diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 85e8dbce1a955..bc8341102421b 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -438,14 +438,14 @@ def main(): rb.use_vendored_sources = '\nvendor = true' in rb.config_toml or \ 'CFG_ENABLE_VENDOR' in rb.config_mk - if 'SUDO_USER' in os.environ: - if os.environ['USER'] != os.environ['SUDO_USER']: + if 'SUDO_USER' in os.environ and not rb.use_vendored_sources: + if os.environ.get('USER') != os.environ['SUDO_USER']: rb.use_vendored_sources = True print('info: looks like you are running this command under `sudo`') print(' and so in order to preserve your $HOME this will now') print(' use vendored sources by default. Note that if this') print(' does not work you should run a normal build first') - print(' before running a command like `sudo make intall`') + print(' before running a command like `sudo make install`') if rb.use_vendored_sources: if not os.path.exists('.cargo'): diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 5fac142f777ff..9327cc0cf7faf 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -381,7 +381,8 @@ pub fn rust_src(build: &Build) { "README.md", "RELEASES.md", "configure", - "Makefile.in" + "Makefile.in", + "x.py", ]; let src_dirs = [ "man", diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index b7c2a708baf49..23e0295ba5401 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -1088,7 +1088,7 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> { #[unstable(feature = "fused", issue = "35602")] impl<'a, T: 'a> FusedIterator for Drain<'a, T> {} -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "binary_heap_extras_15", since = "1.5.0")] impl From> for BinaryHeap { fn from(vec: Vec) -> BinaryHeap { let mut heap = BinaryHeap { data: vec }; @@ -1097,7 +1097,7 @@ impl From> for BinaryHeap { } } -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "binary_heap_extras_15", since = "1.5.0")] impl From> for Vec { fn from(heap: BinaryHeap) -> Vec { heap.data diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 367422f55364a..78764091cf032 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -588,7 +588,7 @@ impl ExactSizeIterator for EscapeUnicode { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeUnicode {} -#[stable(feature = "char_struct_display", since = "1.17.0")] +#[stable(feature = "char_struct_display", since = "1.16.0")] impl fmt::Display for EscapeUnicode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for c in self.clone() { @@ -701,7 +701,7 @@ impl ExactSizeIterator for EscapeDefault { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeDefault {} -#[stable(feature = "char_struct_display", since = "1.17.0")] +#[stable(feature = "char_struct_display", since = "1.16.0")] impl fmt::Display for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for c in self.clone() { @@ -735,7 +735,7 @@ impl ExactSizeIterator for EscapeDebug { } #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeDebug {} -#[stable(feature = "char_struct_display", since = "1.17.0")] +#[unstable(feature = "char_escape_debug", issue = "35068")] impl fmt::Display for EscapeDebug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index abd686b15e22b..4e170794c1d6e 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -225,7 +225,7 @@ pub trait TryFrom: Sized { type Err; /// Performs the conversion. - fn try_from(T) -> Result; + fn try_from(value: T) -> Result; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/internal_macros.rs b/src/libcore/internal_macros.rs index f2cdc9d6a98c5..9a7914064fdd5 100644 --- a/src/libcore/internal_macros.rs +++ b/src/libcore/internal_macros.rs @@ -13,7 +13,11 @@ // based on "op T" where T is expected to be `Copy`able macro_rules! forward_ref_unop { (impl $imp:ident, $method:ident for $t:ty) => { - #[stable(feature = "rust1", since = "1.0.0")] + forward_ref_unop!(impl $imp, $method for $t, + #[stable(feature = "rust1", since = "1.0.0")]); + }; + (impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => { + #[$attr] impl<'a> $imp for &'a $t { type Output = <$t as $imp>::Output; @@ -29,7 +33,11 @@ macro_rules! forward_ref_unop { // based on "T op U" where T and U are expected to be `Copy`able macro_rules! forward_ref_binop { (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { - #[stable(feature = "rust1", since = "1.0.0")] + forward_ref_binop!(impl $imp, $method for $t, $u, + #[stable(feature = "rust1", since = "1.0.0")]); + }; + (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { + #[$attr] impl<'a> $imp<$u> for &'a $t { type Output = <$t as $imp<$u>>::Output; @@ -39,7 +47,7 @@ macro_rules! forward_ref_binop { } } - #[stable(feature = "rust1", since = "1.0.0")] + #[$attr] impl<'a> $imp<&'a $u> for $t { type Output = <$t as $imp<$u>>::Output; @@ -49,7 +57,7 @@ macro_rules! forward_ref_binop { } } - #[stable(feature = "rust1", since = "1.0.0")] + #[$attr] impl<'a, 'b> $imp<&'a $u> for &'b $t { type Output = <$t as $imp<$u>>::Output; diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 3999db0d63c99..d9b8c5ea589fd 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1086,7 +1086,7 @@ impl Iterator for Filter where P: FnMut(&I::Item) -> bool #[inline] fn next(&mut self) -> Option { - for x in self.iter.by_ref() { + for x in &mut self.iter { if (self.predicate)(&x) { return Some(x); } @@ -1099,6 +1099,26 @@ impl Iterator for Filter where P: FnMut(&I::Item) -> bool let (_, upper) = self.iter.size_hint(); (0, upper) // can't know a lower bound, due to the predicate } + + // this special case allows the compiler to make `.filter(_).count()` + // branchless. Barring perfect branch prediction (which is unattainable in + // the general case), this will be much faster in >90% of cases (containing + // virtually all real workloads) and only a tiny bit slower in the rest. + // + // Having this specialization thus allows us to write `.filter(p).count()` + // where we would otherwise write `.map(|x| p(x) as usize).sum()`, which is + // less readable and also less backwards-compatible to Rust before 1.10. + // + // Using the branchless version will also simplify the LLVM byte code, thus + // leaving more budget for LLVM optimizations. + #[inline] + fn count(mut self) -> usize { + let mut count = 0; + for x in &mut self.iter { + count += (self.predicate)(&x) as usize; + } + count + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index a86ceb9ac0d37..cb180110d3cc0 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -661,29 +661,29 @@ pub trait Product: Sized { // NB: explicitly use Add and Mul here to inherit overflow checks macro_rules! integer_sum_product { - (@impls $zero:expr, $one:expr, $($a:ty)*) => ($( - #[stable(feature = "iter_arith_traits", since = "1.12.0")] + (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($( + #[$attr] impl Sum for $a { fn sum>(iter: I) -> $a { iter.fold($zero, Add::add) } } - #[stable(feature = "iter_arith_traits", since = "1.12.0")] + #[$attr] impl Product for $a { fn product>(iter: I) -> $a { iter.fold($one, Mul::mul) } } - #[stable(feature = "iter_arith_traits", since = "1.12.0")] + #[$attr] impl<'a> Sum<&'a $a> for $a { fn sum>(iter: I) -> $a { iter.fold($zero, Add::add) } } - #[stable(feature = "iter_arith_traits", since = "1.12.0")] + #[$attr] impl<'a> Product<&'a $a> for $a { fn product>(iter: I) -> $a { iter.fold($one, Mul::mul) @@ -691,8 +691,12 @@ macro_rules! integer_sum_product { } )*); ($($a:ty)*) => ( - integer_sum_product!(@impls 0, 1, $($a)+); - integer_sum_product!(@impls Wrapping(0), Wrapping(1), $(Wrapping<$a>)+); + integer_sum_product!(@impls 0, 1, + #[stable(feature = "iter_arith_traits", since = "1.12.0")], + $($a)+); + integer_sum_product!(@impls Wrapping(0), Wrapping(1), + #[stable(feature = "wrapping_iter_arith", since = "1.14.0")], + $(Wrapping<$a>)+); ); } diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 04311d687ea92..3b1612a4ee29f 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -12,12 +12,12 @@ macro_rules! int_module { ($T:ident) => (int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); - ($T:ident, $($attr: tt)*) => ( + ($T:ident, #[$attr:meta]) => ( /// The smallest value that can be represented by this integer type. - $($attr)* + #[$attr] pub const MIN: $T = $T::min_value(); /// The largest value that can be represented by this integer type. - $($attr)* + #[$attr] pub const MAX: $T = $T::max_value(); ) } diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index 2e59b39278ab6..f7e1f78d69ebf 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -12,12 +12,12 @@ macro_rules! uint_module { ($T:ident) => (uint_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); - ($T:ident, $($attr: tt)*) => ( + ($T:ident, #[$attr:meta]) => ( /// The smallest value that can be represented by this integer type. - $($attr)* + #[$attr] pub const MIN: $T = $T::min_value(); /// The largest value that can be represented by this integer type. - $($attr)* + #[$attr] pub const MAX: $T = $T::max_value(); ) } diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index 50007c7d9b01a..013f02685bad1 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -131,7 +131,8 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_add(other.0)) } } - forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl AddAssign for Wrapping<$t> { @@ -150,7 +151,8 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_sub(other.0)) } } - forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl SubAssign for Wrapping<$t> { @@ -169,7 +171,8 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_mul(other.0)) } } - forward_ref_binop! { impl Mul, mul for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl Mul, mul for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl MulAssign for Wrapping<$t> { @@ -188,7 +191,8 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_div(other.0)) } } - forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl DivAssign for Wrapping<$t> { @@ -207,7 +211,8 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_rem(other.0)) } } - forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl RemAssign for Wrapping<$t> { @@ -226,7 +231,8 @@ macro_rules! wrapping_impl { Wrapping(!self.0) } } - forward_ref_unop! { impl Not, not for Wrapping<$t> } + forward_ref_unop! { impl Not, not for Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "rust1", since = "1.0.0")] impl BitXor for Wrapping<$t> { @@ -237,7 +243,8 @@ macro_rules! wrapping_impl { Wrapping(self.0 ^ other.0) } } - forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl BitXorAssign for Wrapping<$t> { @@ -256,7 +263,8 @@ macro_rules! wrapping_impl { Wrapping(self.0 | other.0) } } - forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl BitOrAssign for Wrapping<$t> { @@ -275,7 +283,8 @@ macro_rules! wrapping_impl { Wrapping(self.0 & other.0) } } - forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl BitAndAssign for Wrapping<$t> { @@ -293,7 +302,8 @@ macro_rules! wrapping_impl { Wrapping(0) - self } } - forward_ref_unop! { impl Neg, neg for Wrapping<$t> } + forward_ref_unop! { impl Neg, neg for Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } )*) } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index c4d7b2dcf96fb..9df8350d90ffd 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -632,6 +632,76 @@ impl Option { } } + ///////////////////////////////////////////////////////////////////////// + // Entry-like operations to insert if None and return a reference + ///////////////////////////////////////////////////////////////////////// + + /// Inserts `v` into the option if it is `None`, then + /// returns a mutable reference to the contained value. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_entry)] + /// + /// let mut x = None; + /// + /// { + /// let y: &mut u32 = x.get_or_insert(5); + /// assert_eq!(y, &5); + /// + /// *y = 7; + /// } + /// + /// assert_eq!(x, Some(7)); + /// ``` + #[inline] + #[unstable(feature = "option_entry", issue = "39288")] + pub fn get_or_insert(&mut self, v: T) -> &mut T { + match *self { + None => *self = Some(v), + _ => (), + } + + match *self { + Some(ref mut v) => v, + _ => unreachable!(), + } + } + + /// Inserts a value computed from `f` into the option if it is `None`, then + /// returns a mutable reference to the contained value. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_entry)] + /// + /// let mut x = None; + /// + /// { + /// let y: &mut u32 = x.get_or_insert_with(|| 5); + /// assert_eq!(y, &5); + /// + /// *y = 7; + /// } + /// + /// assert_eq!(x, Some(7)); + /// ``` + #[inline] + #[unstable(feature = "option_entry", issue = "39288")] + pub fn get_or_insert_with T>(&mut self, f: F) -> &mut T { + match *self { + None => *self = Some(f()), + _ => (), + } + + match *self { + Some(ref mut v) => v, + _ => unreachable!(), + } + } + ///////////////////////////////////////////////////////////////////////// // Misc ///////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index b942d85f9808b..1a482b75731c1 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -616,7 +616,7 @@ pub trait SliceIndex { fn index_mut(self, slice: &mut [T]) -> &mut Self::Output; } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] impl SliceIndex for usize { type Output = T; @@ -665,7 +665,7 @@ impl SliceIndex for usize { } } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] impl SliceIndex for ops::Range { type Output = [T]; @@ -726,7 +726,7 @@ impl SliceIndex for ops::Range { } } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] impl SliceIndex for ops::RangeTo { type Output = [T]; @@ -761,7 +761,7 @@ impl SliceIndex for ops::RangeTo { } } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] impl SliceIndex for ops::RangeFrom { type Output = [T]; @@ -796,7 +796,7 @@ impl SliceIndex for ops::RangeFrom { } } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] impl SliceIndex for ops::RangeFull { type Output = [T]; @@ -832,7 +832,7 @@ impl SliceIndex for ops::RangeFull { } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] impl SliceIndex for ops::RangeInclusive { type Output = [T]; @@ -895,7 +895,7 @@ impl SliceIndex for ops::RangeInclusive { } } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] impl SliceIndex for ops::RangeToInclusive { type Output = [T]; diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 743e3c41170a3..58cd0af7ee387 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -1318,6 +1318,24 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), u64 AtomicU64 ATOMIC_U64_INIT } +#[cfg(not(stage0))] +#[cfg(target_has_atomic = "128")] +atomic_int! { + unstable(feature = "i128", issue = "35118"), + unstable(feature = "i128", issue = "35118"), + unstable(feature = "i128", issue = "35118"), + unstable(feature = "i128", issue = "35118"), + i128 AtomicI128 ATOMIC_I128_INIT +} +#[cfg(not(stage0))] +#[cfg(target_has_atomic = "128")] +atomic_int! { + unstable(feature = "i128", issue = "35118"), + unstable(feature = "i128", issue = "35118"), + unstable(feature = "i128", issue = "35118"), + unstable(feature = "i128", issue = "35118"), + u128 AtomicU128 ATOMIC_U128_INIT +} #[cfg(target_has_atomic = "ptr")] atomic_int!{ stable(feature = "rust1", since = "1.0.0"), diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 6d02f76c33d16..c7833dbd15629 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -191,6 +191,12 @@ fn test_iterator_enumerate_count() { assert_eq!(xs.iter().count(), 6); } +#[test] +fn test_iterator_filter_count() { + let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + assert_eq!(xs.iter().filter(|&&x| x % 2 == 0).count(), 5); +} + #[test] fn test_iterator_peekable() { let xs = vec![0, 1, 2, 3, 4, 5]; diff --git a/src/liblibc b/src/liblibc index 7d57bdcdbb565..cb7f66732175e 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 7d57bdcdbb56540f37afe5a934ce12d33a6ca7fc +Subproject commit cb7f66732175e6171587ed69656b7aae7dd2e6ec diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index e1605959922c0..70f03e02f46d9 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -192,6 +192,13 @@ declare_lint! { "lifetimes or labels named `'_` were erroneously allowed" } +declare_lint! { + pub RESOLVE_TRAIT_ON_DEFAULTED_UNIT, + Warn, + "attempt to resolve a trait on an expression whose type cannot be inferred but which \ + currently defaults to ()" +} + declare_lint! { pub SAFE_EXTERN_STATICS, Warn, @@ -272,6 +279,7 @@ impl LintPass for HardwiredLints { SUPER_OR_SELF_IN_GLOBAL_PATH, HR_LIFETIME_IN_ASSOC_TYPE, LIFETIME_UNDERSCORE, + RESOLVE_TRAIT_ON_DEFAULTED_UNIT, SAFE_EXTERN_STATICS, PATTERNS_IN_FNS_WITHOUT_BODY, EXTRA_REQUIREMENT_IN_IMPL, diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 0e8e1921de700..9d1bcb8164a9e 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -1199,7 +1199,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { PatKind::Tuple(ref subpats, ddpos) => { // (p1, ..., pN) let expected_len = match self.pat_ty(&pat)?.sty { - ty::TyTuple(ref tys) => tys.len(), + ty::TyTuple(ref tys, _) => tys.len(), ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty), }; for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 03530945e046d..f1268521d6708 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -163,7 +163,7 @@ impl<'tcx> Rvalue<'tcx> { let lhs_ty = lhs.ty(mir, tcx); let rhs_ty = rhs.ty(mir, tcx); let ty = op.ty(tcx, lhs_ty, rhs_ty); - let ty = tcx.intern_tup(&[ty, tcx.types.bool]); + let ty = tcx.intern_tup(&[ty, tcx.types.bool], false); Some(ty) } &Rvalue::UnaryOp(_, ref operand) => { @@ -184,7 +184,8 @@ impl<'tcx> Rvalue<'tcx> { } AggregateKind::Tuple => { Some(tcx.mk_tup( - ops.iter().map(|op| op.ty(mir, tcx)) + ops.iter().map(|op| op.ty(mir, tcx)), + false )) } AggregateKind::Adt(def, _, substs, _) => { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index d51332f833d77..41f3f825c3d19 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -52,6 +52,7 @@ use std::mem; use std::rc::Rc; use syntax::abi::Abi; use hir; +use lint; use util::nodemap::FxHashMap; struct InferredObligationsSnapshotVecDelegate<'tcx> { @@ -407,19 +408,62 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("select({:?})", obligation); assert!(!obligation.predicate.has_escaping_regions()); + let tcx = self.tcx(); let dep_node = obligation.predicate.dep_node(); - let _task = self.tcx().dep_graph.in_task(dep_node); + let _task = tcx.dep_graph.in_task(dep_node); let stack = self.push_stack(TraitObligationStackList::empty(), obligation); - match self.candidate_from_obligation(&stack)? { - None => Ok(None), + let ret = match self.candidate_from_obligation(&stack)? { + None => None, Some(candidate) => { let mut candidate = self.confirm_candidate(obligation, candidate)?; let inferred_obligations = (*self.inferred_obligations).into_iter().cloned(); candidate.nested_obligations_mut().extend(inferred_obligations); - Ok(Some(candidate)) + Some(candidate) }, + }; + + // Test whether this is a `()` which was produced by defaulting a + // diverging type variable with `!` disabled. If so, we may need + // to raise a warning. + if obligation.predicate.skip_binder().self_ty().is_defaulted_unit() { + let mut raise_warning = true; + // Don't raise a warning if the trait is implemented for ! and only + // permits a trivial implementation for !. This stops us warning + // about (for example) `(): Clone` becoming `!: Clone` because such + // a switch can't cause code to stop compiling or execute + // differently. + let mut never_obligation = obligation.clone(); + let def_id = never_obligation.predicate.skip_binder().trait_ref.def_id; + never_obligation.predicate = never_obligation.predicate.map_bound(|mut trait_pred| { + // Swap out () with ! so we can check if the trait is impld for ! + { + let mut trait_ref = &mut trait_pred.trait_ref; + let unit_substs = trait_ref.substs; + let mut never_substs = Vec::with_capacity(unit_substs.len()); + never_substs.push(From::from(tcx.types.never)); + never_substs.extend(&unit_substs[1..]); + trait_ref.substs = tcx.intern_substs(&never_substs); + } + trait_pred + }); + if let Ok(Some(..)) = self.select(&never_obligation) { + if !tcx.trait_relevant_for_never(def_id) { + // The trait is also implemented for ! and the resulting + // implementation cannot actually be invoked in any way. + raise_warning = false; + } + } + + if raise_warning { + tcx.sess.add_lint(lint::builtin::RESOLVE_TRAIT_ON_DEFAULTED_UNIT, + obligation.cause.body_id, + obligation.cause.span, + format!("code relies on type inference rules which are likely \ + to change")); + } } + Ok(ret) } /////////////////////////////////////////////////////////////////////////// @@ -1744,7 +1788,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) => Never, - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { Where(ty::Binder(tys.last().into_iter().cloned().collect())) } @@ -1752,7 +1796,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let sized_crit = def.sized_constraint(self.tcx()); // (*) binder moved here Where(ty::Binder(match sized_crit.sty { - ty::TyTuple(tys) => tys.to_vec().subst(self.tcx(), substs), + ty::TyTuple(tys, _) => tys.to_vec().subst(self.tcx(), substs), ty::TyBool => vec![], _ => vec![sized_crit.subst(self.tcx(), substs)] })) @@ -1799,7 +1843,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Where(ty::Binder(vec![element_ty])) } - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { // (*) binder moved here Where(ty::Binder(tys.to_vec())) } @@ -1874,7 +1918,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { vec![element_ty] } - ty::TyTuple(ref tys) => { + ty::TyTuple(ref tys, _) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet tys.to_vec() } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index cebd8bf87d736..7b2882bb64f2c 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -489,7 +489,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let arguments_tuple = match tuple_arguments { TupleArgumentsFlag::No => sig.skip_binder().inputs()[0], TupleArgumentsFlag::Yes => - self.intern_tup(sig.skip_binder().inputs()), + self.intern_tup(sig.skip_binder().inputs(), false), }; let trait_ref = ty::TraitRef { def_id: fn_trait_def_id, diff --git a/src/librustc/ty/contents.rs b/src/librustc/ty/contents.rs index 00c6dca21b1ef..56621c57eb8f7 100644 --- a/src/librustc/ty/contents.rs +++ b/src/librustc/ty/contents.rs @@ -201,7 +201,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { |ty| tc_ty(tcx, &ty, cache)) } - ty::TyTuple(ref tys) => { + ty::TyTuple(ref tys, _) => { TypeContents::union(&tys[..], |ty| tc_ty(tcx, *ty, cache)) } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 7dcbe04caf82b..a0eae33c4402b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1384,23 +1384,24 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_ty(TySlice(ty)) } - pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> { - self.mk_ty(TyTuple(self.intern_type_list(ts))) + pub fn intern_tup(self, ts: &[Ty<'tcx>], defaulted: bool) -> Ty<'tcx> { + self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted)) } - pub fn mk_tup], Ty<'tcx>>>(self, iter: I) -> I::Output { - iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts)))) + pub fn mk_tup], Ty<'tcx>>>(self, iter: I, + defaulted: bool) -> I::Output { + iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted))) } pub fn mk_nil(self) -> Ty<'tcx> { - self.intern_tup(&[]) + self.intern_tup(&[], false) } pub fn mk_diverging_default(self) -> Ty<'tcx> { if self.sess.features.borrow().never_type { self.types.never } else { - self.mk_nil() + self.intern_tup(&[], true) } } diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 29d855a7fcb78..3ab3fc899e78c 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -178,7 +178,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { match self.sty { ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyNever => self.to_string(), - ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(), + ty::TyTuple(ref tys, _) if tys.is_empty() => self.to_string(), ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)), ty::TyArray(_, n) => format!("array of {} elements", n), @@ -209,7 +209,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { |p| format!("trait {}", tcx.item_path_str(p.def_id()))) } ty::TyClosure(..) => "closure".to_string(), - ty::TyTuple(_) => "tuple".to_string(), + ty::TyTuple(..) => "tuple".to_string(), ty::TyInfer(ty::TyVar(_)) => "inferred type".to_string(), ty::TyInfer(ty::IntVar(_)) => "integral variable".to_string(), ty::TyInfer(ty::FloatVar(_)) => "floating-point variable".to_string(), diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 94b9abc72025f..981cf0897a034 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -72,7 +72,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, Some(ClosureSimplifiedType(def_id)) } ty::TyNever => Some(NeverSimplifiedType), - ty::TyTuple(ref tys) => { + ty::TyTuple(ref tys, _) => { Some(TupleSimplifiedType(tys.len())) } ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => { diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 0de77526b5a46..2012917f93a87 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -151,7 +151,7 @@ impl FlagComputation { self.add_ty(m.ty); } - &ty::TyTuple(ref ts) => { + &ty::TyTuple(ref ts, _) => { self.add_tys(&ts[..]); } diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 6c49493a65559..18a3f1a218d85 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -178,7 +178,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { }, TyNever => DefIdForest::full(tcx), - TyTuple(ref tys) => { + TyTuple(ref tys, _) => { DefIdForest::union(tcx, tys.iter().map(|ty| { ty.uninhabited_from(visited, tcx) })) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index b719911d18cf8..f45f00b4dec96 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -319,9 +319,9 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option { ty::TyRawPtr(mt) | ty::TyRef(_, mt) => characteristic_def_id_of_type(mt.ty), - ty::TyTuple(ref tys) => tys.iter() - .filter_map(|ty| characteristic_def_id_of_type(ty)) - .next(), + ty::TyTuple(ref tys, _) => tys.iter() + .filter_map(|ty| characteristic_def_id_of_type(ty)) + .next(), ty::TyFnDef(def_id, ..) | ty::TyClosure(def_id, _) => Some(def_id), diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index b5efd2cfc686a..ff3ac3586a787 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -791,7 +791,7 @@ impl<'a, 'gcx, 'tcx> Struct { Some(&variant.memory_index[..])) } // Can we use one of the fields in this tuple? - (&Univariant { ref variant, .. }, &ty::TyTuple(tys)) => { + (&Univariant { ref variant, .. }, &ty::TyTuple(tys, _)) => { Struct::non_zero_field_paths(infcx, tys.iter().cloned(), Some(&variant.memory_index[..])) } @@ -1157,7 +1157,7 @@ impl<'a, 'gcx, 'tcx> Layout { Univariant { variant: st, non_zero: false } } - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { // FIXME(camlorn): if we ever allow unsized tuples, this needs to be checked. // See the univariant case below to learn how. let st = Struct::new(dl, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 5ab45e746e7f2..c9ae3b3df028c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -197,6 +197,17 @@ impl AssociatedItem { AssociatedKind::Type => Def::AssociatedTy(self.def_id), } } + + /// Tests whether the associated item admits a non-trivial implementation + /// for ! + pub fn relevant_for_never<'tcx>(&self) -> bool { + match self.kind { + AssociatedKind::Const => true, + AssociatedKind::Type => true, + // FIXME(canndrew): Be more thorough here, check if any argument is uninhabited. + AssociatedKind::Method => !self.method_has_self_argument, + } + } } #[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable)] @@ -1603,7 +1614,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { _ if tys.references_error() => tcx.types.err, 0 => tcx.types.bool, 1 => tys[0], - _ => tcx.intern_tup(&tys[..]) + _ => tcx.intern_tup(&tys[..], false) }; let old = tcx.adt_sized_constraint.borrow().get(&self.did).cloned(); @@ -1638,7 +1649,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { vec![ty] } - TyTuple(ref tys) => { + TyTuple(ref tys, _) => { match tys.last() { None => vec![], Some(ty) => self.sized_constraint_for_ty(tcx, stack, ty) @@ -1652,7 +1663,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { .subst(tcx, substs); debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_ty); - if let ty::TyTuple(ref tys) = adt_ty.sty { + if let ty::TyTuple(ref tys, _) = adt_ty.sty { tys.iter().flat_map(|ty| { self.sized_constraint_for_ty(tcx, stack, ty) }).collect() @@ -2010,6 +2021,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + pub fn trait_relevant_for_never(self, did: DefId) -> bool { + self.associated_items(did).any(|item| { + item.relevant_for_never() + }) + } + pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceUnsized { self.custom_coerce_unsized_kinds.memoize(did, || { let (kind, src) = if did.krate != LOCAL_CRATE { diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 89514085e1c78..adedf78bba7c0 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -447,10 +447,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, Ok(tcx.mk_slice(t)) } - (&ty::TyTuple(as_), &ty::TyTuple(bs)) => + (&ty::TyTuple(as_, a_defaulted), &ty::TyTuple(bs, b_defaulted)) => { if as_.len() == bs.len() { - Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)))?) + let defaulted = a_defaulted || b_defaulted; + Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)), defaulted)?) } else if !(as_.is_empty() || bs.is_empty()) { Err(TypeError::TupleSize( expected_found(relation, &as_.len(), &bs.len()))) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 05f4abad46921..aa74e7cc0d043 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -474,7 +474,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)), ty::TyDynamic(ref trait_ty, ref region) => ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)), - ty::TyTuple(ts) => ty::TyTuple(ts.fold_with(folder)), + ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted), ty::TyFnDef(def_id, substs, f) => { ty::TyFnDef(def_id, substs.fold_with(folder), @@ -511,7 +511,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyAdt(_, substs) => substs.visit_with(visitor), ty::TyDynamic(ref trait_ty, ref reg) => trait_ty.visit_with(visitor) || reg.visit_with(visitor), - ty::TyTuple(ts) => ts.visit_with(visitor), + ty::TyTuple(ts, _) => ts.visit_with(visitor), ty::TyFnDef(_, substs, ref f) => { substs.visit_with(visitor) || f.visit_with(visitor) } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 113534e4529cd..9bba4c6e37a69 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -151,7 +151,11 @@ pub enum TypeVariants<'tcx> { TyNever, /// A tuple type. For example, `(i32, bool)`. - TyTuple(&'tcx Slice>), + /// The bool indicates whether this is a unit tuple and was created by + /// defaulting a diverging type variable with feature(never_type) disabled. + /// It's only purpose is for raising future-compatibility warnings for when + /// diverging type variables start defaulting to ! instead of (). + TyTuple(&'tcx Slice>, bool), /// The projection of an associated type. For example, /// `>::N`. @@ -961,7 +965,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_nil(&self) -> bool { match self.sty { - TyTuple(ref tys) => tys.is_empty(), + TyTuple(ref tys, _) => tys.is_empty(), _ => false } } @@ -973,6 +977,15 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } + // Test whether this is a `()` which was produced by defaulting a + // diverging type variable with feature(never_type) disabled. + pub fn is_defaulted_unit(&self) -> bool { + match self.sty { + TyTuple(_, true) => true, + _ => false, + } + } + /// Checks whether a type is visibly uninhabited from a particular module. /// # Example /// ```rust @@ -1355,7 +1368,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { TySlice(_) | TyRawPtr(_) | TyNever | - TyTuple(_) | + TyTuple(..) | TyParam(_) | TyInfer(_) | TyError => { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index ba49aa1ef4866..b01b77bbcf8a5 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -207,7 +207,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Don't use `struct_variant`, this may be a univariant enum. adt.variants[0].fields.get(i).map(|f| f.ty(self, substs)) } - (&TyTuple(ref v), None) => v.get(i).cloned(), + (&TyTuple(ref v, _), None) => v.get(i).cloned(), _ => None } } @@ -466,8 +466,9 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W> self.def_id(d); } } - TyTuple(tys) => { + TyTuple(tys, defaulted) => { self.hash(tys.len()); + self.hash(defaulted); } TyParam(p) => { self.hash(p.idx); @@ -675,7 +676,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { seen: &mut Vec>, ty: Ty<'tcx>) -> Representability { match ty.sty { - TyTuple(ref ts) => { + TyTuple(ref ts, _) => { find_nonrepresentable(tcx, sp, seen, ts.iter().cloned()) } // Fixed-length vectors. diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 0d1dc2e4d7c21..01f31e5024c0d 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -112,7 +112,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::TyClosure(_, ref substs) => { stack.extend(substs.substs.types().rev()); } - ty::TyTuple(ts) => { + ty::TyTuple(ts, _) => { stack.extend(ts.iter().cloned().rev()); } ty::TyFnDef(_, substs, ref ft) => { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 33b70b09dcb7b..8a5bd6862cf45 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -315,7 +315,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { self.require_sized(subty, traits::SliceOrArrayElem); } - ty::TyTuple(ref tys) => { + ty::TyTuple(ref tys, _) => { if let Some((_last, rest)) = tys.split_last() { for elem in rest { self.require_sized(elem, traits::TupleElem); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index aa2eb2955debe..5d6ee1a277a5f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -156,7 +156,7 @@ pub fn parameterized(f: &mut fmt::Formatter, if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { let projection_ty = projections[0].ty; - if let TyTuple(ref args) = substs.type_at(1).sty { + if let TyTuple(ref args, _) = substs.type_at(1).sty { return fn_sig(f, args, false, projection_ty); } } @@ -724,7 +724,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { write!(f, "{}", tm) } TyNever => write!(f, "!"), - TyTuple(ref tys) => { + TyTuple(ref tys, _) => { write!(f, "(")?; let mut tys = tys.iter(); if let Some(&ty) = tys.next() { diff --git a/src/librustc_back/target/asmjs_unknown_emscripten.rs b/src/librustc_back/target/asmjs_unknown_emscripten.rs index 2dbaeaf26e970..4d38b0d170596 100644 --- a/src/librustc_back/target/asmjs_unknown_emscripten.rs +++ b/src/librustc_back/target/asmjs_unknown_emscripten.rs @@ -22,6 +22,7 @@ pub fn target() -> Result { linker_is_gnu: true, allow_asm: false, obj_is_bitcode: true, + is_like_emscripten: true, max_atomic_width: Some(32), post_link_args: vec!["-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()], target_family: Some("unix".to_string()), diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 5afa85d155279..d2b76b1d55a98 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -330,6 +330,10 @@ pub struct TargetOptions { /// Whether the target toolchain is like Android's. Only useful for compiling against Android. /// Defaults to false. pub is_like_android: bool, + /// Whether the target toolchain is like Emscripten's. Only useful for compiling with + /// Emscripten toolchain. + /// Defaults to false. + pub is_like_emscripten: bool, /// Whether the linker support GNU-like arguments such as -O. Defaults to false. pub linker_is_gnu: bool, /// The MinGW toolchain has a known issue that prevents it from correctly @@ -428,6 +432,7 @@ impl Default for TargetOptions { is_like_solaris: false, is_like_windows: false, is_like_android: false, + is_like_emscripten: false, is_like_msvc: false, linker_is_gnu: false, allows_weak_linkage: true, @@ -603,6 +608,7 @@ impl Target { key!(is_like_solaris, bool); key!(is_like_windows, bool); key!(is_like_msvc, bool); + key!(is_like_emscripten, bool); key!(is_like_android, bool); key!(linker_is_gnu, bool); key!(allows_weak_linkage, bool); @@ -767,6 +773,7 @@ impl ToJson for Target { target_option_val!(is_like_solaris); target_option_val!(is_like_windows); target_option_val!(is_like_msvc); + target_option_val!(is_like_emscripten); target_option_val!(is_like_android); target_option_val!(linker_is_gnu); target_option_val!(allows_weak_linkage); diff --git a/src/librustc_back/target/wasm32_unknown_emscripten.rs b/src/librustc_back/target/wasm32_unknown_emscripten.rs index a06980767fd75..b1967fa8f37a7 100644 --- a/src/librustc_back/target/wasm32_unknown_emscripten.rs +++ b/src/librustc_back/target/wasm32_unknown_emscripten.rs @@ -24,6 +24,7 @@ pub fn target() -> Result { linker_is_gnu: true, allow_asm: false, obj_is_bitcode: true, + is_like_emscripten: true, max_atomic_width: Some(32), post_link_args: vec!["-s".to_string(), "BINARYEN=1".to_string(), "-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()], diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs index 285f3ab9047c8..dbab3bca52b4e 100644 --- a/src/librustc_borrowck/borrowck/fragments.rs +++ b/src/librustc_borrowck/borrowck/fragments.rs @@ -423,7 +423,7 @@ fn add_fragment_siblings_for_extension<'a, 'tcx>(this: &MoveData<'tcx>, }; match parent_ty.sty { - ty::TyTuple(ref v) => { + ty::TyTuple(ref v, _) => { let tuple_idx = match *origin_field_name { mc::PositionalField(tuple_idx) => tuple_idx, mc::NamedField(_) => diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 9e89a3689c7ac..d2f744bde2d63 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -713,7 +713,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx).collect(); self.open_drop_for_tuple(c, &tys) } - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { self.open_drop_for_tuple(c, tys) } ty::TyAdt(def, _) if def.is_box() => { diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index 94b2ba58c9aa5..7a64ff7114a7e 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -721,7 +721,7 @@ fn pat_constructors(_cx: &mut MatchCheckCtxt, fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize { debug!("constructor_arity({:?}, {:?})", ctor, ty); match ty.sty { - ty::TyTuple(ref fs) => fs.len(), + ty::TyTuple(ref fs, _) => fs.len(), ty::TySlice(..) | ty::TyArray(..) => match *ctor { Slice(length) => length, ConstantValue(_) => 0, @@ -745,7 +745,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>, { debug!("constructor_sub_pattern_tys({:?}, {:?})", ctor, ty); match ty.sty { - ty::TyTuple(ref fs) => fs.into_iter().map(|t| *t).collect(), + ty::TyTuple(ref fs, _) => fs.into_iter().map(|t| *t).collect(), ty::TySlice(ty) | ty::TyArray(ty, _) => match *ctor { Slice(length) => repeat(ty).take(length).collect(), ConstantValue(_) => vec![], diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index c6272613f4d09..609fb3e39d62c 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -342,7 +342,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { PatKind::Tuple(ref subpatterns, ddpos) => { let ty = self.tables.node_id_to_type(pat.id); match ty.sty { - ty::TyTuple(ref tys) => { + ty::TyTuple(ref tys, _) => { let subpatterns = subpatterns.iter() .enumerate_and_adjust(tys.len(), ddpos) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 1086d75f02cb4..5481de1811d78 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> { - self.infcx.tcx.intern_tup(&[ty1, ty2]) + self.infcx.tcx.intern_tup(&[ty1, ty2], false) } pub fn t_param(&self, index: u32) -> Ty<'tcx> { @@ -803,8 +803,8 @@ fn walk_ty() { let tcx = env.infcx.tcx; let int_ty = tcx.types.isize; let uint_ty = tcx.types.usize; - let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty]); - let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty]); + let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty], false); + let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty], false); let walked: Vec<_> = tup2_ty.walk().collect(); assert_eq!(walked, [tup2_ty, tup1_ty, int_ty, uint_ty, int_ty, uint_ty, tup1_ty, int_ty, @@ -818,8 +818,8 @@ fn walk_ty_skip_subtree() { let tcx = env.infcx.tcx; let int_ty = tcx.types.isize; let uint_ty = tcx.types.usize; - let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty]); - let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty]); + let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty], false); + let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty], false); // types we expect to see (in order), plus a boolean saying // whether to skip the subtree. diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index d1ad3730aa2b3..8fb1740e66eac 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -219,6 +219,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { id: LintId::of(LIFETIME_UNDERSCORE), reference: "issue #36892 ", }, + FutureIncompatibleInfo { + id: LintId::of(RESOLVE_TRAIT_ON_DEFAULTED_UNIT), + reference: "issue #39216 ", + }, FutureIncompatibleInfo { id: LintId::of(SAFE_EXTERN_STATICS), reference: "issue #36247 ", diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 2c3d71cd8de1d..e42e038ea4d6c 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -532,7 +532,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { consider using a `*const libc::c_char`") } - ty::TyTuple(_) => { + ty::TyTuple(..) => { FfiUnsafe("found Rust tuple type in foreign module; \ consider using a struct instead") } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index a85b47c8ada7a..28ce9126019eb 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -141,7 +141,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { let t = cx.tables.expr_ty(&expr); let warned = match t.sty { - ty::TyTuple(ref tys) if tys.is_empty() => return, + ty::TyTuple(ref tys, _) if tys.is_empty() => return, ty::TyNever => return, ty::TyBool => return, ty::TyAdt(def, _) => { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index f0d056b96f150..81a4f7c93b6e9 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -584,7 +584,7 @@ impl<'a> CrateLoader<'a> { use proc_macro::TokenStream; use proc_macro::__internal::Registry; use rustc_back::dynamic_lib::DynamicLibrary; - use syntax_ext::deriving::custom::CustomDerive; + use syntax_ext::deriving::custom::ProcMacroDerive; use syntax_ext::proc_macro_impl::AttrProcMacro; let path = match dylib { @@ -616,8 +616,8 @@ impl<'a> CrateLoader<'a> { expand: fn(TokenStream) -> TokenStream, attributes: &[&'static str]) { let attrs = attributes.iter().cloned().map(Symbol::intern).collect(); - let derive = SyntaxExtension::CustomDerive( - Box::new(CustomDerive::new(expand, attrs)) + let derive = SyntaxExtension::ProcMacroDerive( + Box::new(ProcMacroDerive::new(expand, attrs)) ); self.0.push((Symbol::intern(trait_name), Rc::new(derive))); } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index b1e1e75912da3..dad1d713168cd 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -257,7 +257,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source_info = self.source_info(span); let bool_ty = self.hir.bool_ty(); if self.hir.check_overflow() && op.is_checkable() && ty.is_integral() { - let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty]); + let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty], false); let result_value = self.temp(result_tup); self.cfg.push_assign(block, source_info, diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index c9195f29f1784..529fe564af02b 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -282,7 +282,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { }) } } - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { return match tys.get(field.index()) { Some(&ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index eb6c7f4bed5de..4679b6be88b6f 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -559,7 +559,7 @@ impl<'a> Resolver<'a> { "an `extern crate` loading macros must be at the crate root"); } else if !self.use_extern_macros && !used && self.session.cstore.dep_kind(module.def_id().unwrap().krate).macros_only() { - let msg = "custom derive crates and `#[no_link]` crates have no effect without \ + let msg = "proc macro crates and `#[no_link]` crates have no effect without \ `#[macro_use]`"; self.session.span_warn(item.span, msg); used = true; // Avoid the normal unused extern crate warning diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 682b3ff834fad..ea3112b2463f8 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -250,6 +250,32 @@ impl<'a> base::Resolver for Resolver<'a> { } result } + + fn resolve_builtin_macro(&mut self, tname: Name) -> Result, Determinacy> { + match self.builtin_macros.get(&tname).cloned() { + Some(binding) => Ok(binding.get_macro(self)), + None => Err(Determinacy::Undetermined), + } + } + + fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) + -> Result, Determinacy> { + let ast::Path { span, .. } = *path; + match self.resolve_macro(scope, path, false) { + Ok(ext) => match *ext { + SyntaxExtension::BuiltinDerive(..) | + SyntaxExtension::ProcMacroDerive(..) => Ok(ext), + _ => Err(Determinacy::Determined), + }, + Err(Determinacy::Undetermined) if force => { + let msg = format!("cannot find derive macro `{}` in this scope", path); + let mut err = self.session.struct_span_err(span, &msg); + err.emit(); + Err(Determinacy::Determined) + }, + Err(err) => Err(err), + } + } } impl<'a> Resolver<'a> { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 65cdeb9253d89..dbc8bca548b76 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -639,7 +639,19 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let names = resolutions.iter().filter_map(|(&(ref i, _), resolution)| { if *i == ident { return None; } // Never suggest the same name match *resolution.borrow() { - NameResolution { binding: Some(_), .. } => Some(&i.name), + NameResolution { binding: Some(name_binding), .. } => { + match name_binding.kind { + NameBindingKind::Import { binding, .. } => { + match binding.kind { + // Never suggest the name that has binding error + // i.e. the name that cannot be previously resolved + NameBindingKind::Def(Def::Err) => return None, + _ => Some(&i.name), + } + }, + _ => Some(&i.name), + } + }, NameResolution { single_imports: SingleImports::None, .. } => None, _ => Some(&i.name), } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index f128167bbf621..41f91a1d2acc1 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1440,7 +1440,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, }.lower(self.tcx)); } } - ty::TyTuple(_) => {} + ty::TyTuple(..) => {} _ => span_bug!(ex.span, "Expected struct or tuple type, found {:?}", ty), diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 8d0cdd1678c73..ebb33a12c8703 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -430,6 +430,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { -> Option { self.lookup_ref_id(trait_ref.ref_id).and_then(|def_id| { let span = trait_ref.path.span; + if generated_code(span) { + return None; + } let sub_span = self.span_utils.sub_span_for_type_name(span).or(Some(span)); filter!(self.span_utils, sub_span, span, None); Some(TypeRefData { diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index d392ebaa33d42..a476b1d29e5fb 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -367,7 +367,7 @@ impl FnType { assert!(!sig.variadic && extra_args.is_empty()); match sig.inputs().last().unwrap().sty { - ty::TyTuple(ref tupled_arguments) => { + ty::TyTuple(ref tupled_arguments, _) => { inputs = &sig.inputs()[0..sig.inputs().len() - 1]; &tupled_arguments[..] } diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index c3b9a56ac9778..bc1e07e708c24 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -72,7 +72,7 @@ pub fn compute_fields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, monomorphize::field_ty(cx.tcx(), substs, f) }).collect::>() }, - ty::TyTuple(fields) => fields.to_vec(), + ty::TyTuple(fields, _) => fields.to_vec(), ty::TyClosure(def_id, substs) => { if variant_index > 0 { bug!("{} is a closure, which only has one variant", t);} substs.upvar_tys(def_id, cx.tcx()).collect() diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 20842ea3fe54d..4ddf8a883bc48 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -29,6 +29,7 @@ use rustc::dep_graph::DepNode; use rustc::hir::def_id::CrateNum; use rustc::hir::svh::Svh; use rustc_back::tempdir::TempDir; +use rustc_back::PanicStrategy; use rustc_incremental::IncrementalHashesMap; use std::ascii; @@ -714,6 +715,11 @@ fn link_natively(sess: &Session, cmd.arg(root.join(obj)); } + if sess.target.target.options.is_like_emscripten && + sess.panic_strategy() == PanicStrategy::Abort { + cmd.args(&["-s", "DISABLE_EXCEPTION_CATCHING=1"]); + } + { let mut linker = trans.linker_info.to_linker(&mut cmd, &sess); link_args(&mut *linker, sess, crate_type, tmpdir, diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 58d0c46850353..c6b86c6ba48de 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -485,7 +485,7 @@ fn trans_fn_pointer_shim<'a, 'tcx>( } }; let sig = tcx.erase_late_bound_regions_and_normalize(sig); - let tuple_input_ty = tcx.intern_tup(sig.inputs()); + let tuple_input_ty = tcx.intern_tup(sig.inputs(), false); let sig = tcx.mk_fn_sig( [bare_fn_ty_maybe_ref, tuple_input_ty].iter().cloned(), sig.output(), diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 392c270c130a8..89f5c00e9c11a 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -823,7 +823,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, output.push(TransItem::DropGlue(DropGlueKind::Ty(inner_type))); } } - ty::TyTuple(args) => { + ty::TyTuple(args, _) => { for arg in args { let arg = glue::get_drop_glue_type(scx, arg); if scx.type_needs_drop(arg) { diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 01b2aeef004db..725b0e06e3088 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -93,7 +93,7 @@ pub fn type_pair_fields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) } })) } - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { if tys.len() != 2 { return None; } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index b7e319f2de434..c83e2f4854bf5 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -383,7 +383,7 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // return type signature_metadata.push(match signature.output().sty { - ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(), + ty::TyTuple(ref tys, _) if tys.is_empty() => ptr::null_mut(), _ => type_metadata(cx, signature.output(), span) }); @@ -528,7 +528,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::TyFloat(_) => { MetadataCreationResult::new(basic_type_metadata(cx, t), false) } - ty::TyTuple(ref elements) if elements.is_empty() => { + ty::TyTuple(ref elements, _) if elements.is_empty() => { MetadataCreationResult::new(basic_type_metadata(cx, t), false) } ty::TyArray(typ, len) => { @@ -603,7 +603,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, usage_site_span).finalize(cx) } }, - ty::TyTuple(ref elements) => { + ty::TyTuple(ref elements, _) => { prepare_tuple_metadata(cx, t, &elements[..], @@ -706,7 +706,7 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let (name, encoding) = match t.sty { ty::TyNever => ("!", DW_ATE_unsigned), - ty::TyTuple(ref elements) if elements.is_empty() => + ty::TyTuple(ref elements, _) if elements.is_empty() => ("()", DW_ATE_unsigned), ty::TyBool => ("bool", DW_ATE_boolean), ty::TyChar => ("char", DW_ATE_unsigned_char), diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index e9468e56637d2..501f891befa8d 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -295,7 +295,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Return type -- llvm::DIBuilder wants this at index 0 signature.push(match sig.output().sty { - ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(), + ty::TyTuple(ref tys, _) if tys.is_empty() => ptr::null_mut(), _ => type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP) }); @@ -311,7 +311,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } if abi == Abi::RustCall && !sig.inputs().is_empty() { - if let ty::TyTuple(args) = sig.inputs()[sig.inputs().len() - 1].sty { + if let ty::TyTuple(args, _) = sig.inputs()[sig.inputs().len() - 1].sty { for &argument_type in args { signature.push(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP)); } diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 8e11bf6b8976a..018bbb6e97d34 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -48,7 +48,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, push_item_name(cx, def.did, qualified, output); push_type_params(cx, substs, output); }, - ty::TyTuple(component_types) => { + ty::TyTuple(component_types, _) => { output.push('('); for &component_type in component_types { push_debuginfo_type_name(cx, component_type, true, output); diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 1415ca6029f53..fdefd37549ced 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -442,7 +442,7 @@ fn drop_structural_ty<'a, 'tcx>( cx = tvec::slice_for_each(&cx, ptr.llval, unit_ty, ptr.llextra, |bb, vv| drop_ty(bb, LvalueRef::new_sized_ty(vv, unit_ty))); } - ty::TyTuple(ref args) => { + ty::TyTuple(ref args, _) => { for (i, arg) in args.iter().enumerate() { let llfld_a = ptr.trans_field_ptr(&cx, i); drop_ty(&cx, LvalueRef::new_sized_ty(llfld_a, *arg)); diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 7d4a1ab5ae70e..027779aca63e4 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -695,7 +695,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let tuple = self.trans_operand(bcx, operand); let arg_types = match tuple.ty.sty { - ty::TyTuple(ref tys) => tys, + ty::TyTuple(ref tys, _) => tys, _ => span_bug!(self.mir.span, "bad final argument to \"rust-call\" fn {:?}", tuple.ty) }; diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 3d5e1694355b3..c8a680d25195a 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -735,7 +735,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let rhs = self.const_operand(rhs, span)?; let ty = lhs.ty; let val_ty = op.ty(tcx, lhs.ty, rhs.ty); - let binop_ty = tcx.intern_tup(&[val_ty, tcx.types.bool]); + let binop_ty = tcx.intern_tup(&[val_ty, tcx.types.bool], false); let (lhs, rhs) = (lhs.llval, rhs.llval); assert!(!ty.is_fp()); diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index 30c138310da9c..8a0a97a563439 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -384,7 +384,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, // individual LLVM function arguments. let tupled_arg_tys = match arg_ty.sty { - ty::TyTuple(ref tys) => tys, + ty::TyTuple(ref tys, _) => tys, _ => bug!("spread argument isn't a tuple?!") }; diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 1b97a8d010cfe..81b241b485175 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -402,7 +402,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { lhs.immediate(), rhs.immediate(), lhs.ty); let val_ty = op.ty(bcx.tcx(), lhs.ty, rhs.ty); - let operand_ty = bcx.tcx().intern_tup(&[val_ty, bcx.tcx().types.bool]); + let operand_ty = bcx.tcx().intern_tup(&[val_ty, bcx.tcx().types.bool], false); let operand = OperandRef { val: result, ty: operand_ty diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index d58a93e3cb71c..04a6cb27501b3 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -409,7 +409,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { self.push_def_path(adt_def.did, output); self.push_type_params(substs, iter::empty(), output); }, - ty::TyTuple(component_types) => { + ty::TyTuple(component_types, _) => { output.push('('); for &component_type in component_types { self.push_type_name(component_type, output); diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 4df0e989ada99..87af3b6c5e153 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -74,7 +74,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ Type::array(&llty, size) } - ty::TyTuple(ref tys) if tys.is_empty() => { + ty::TyTuple(ref tys, _) if tys.is_empty() => { Type::nil(cx) } @@ -276,7 +276,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> let sig = cx.tcx().erase_late_bound_regions_and_normalize(&f.sig); FnType::new(cx, f.abi, &sig, &[]).llvm_type(cx).ptr_to() } - ty::TyTuple(ref tys) if tys.is_empty() => Type::nil(cx), + ty::TyTuple(ref tys, _) if tys.is_empty() => Type::nil(cx), ty::TyTuple(..) => { adt::type_of(cx, t) } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index bb9a487802e7b..a3373f6da2852 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -421,7 +421,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span: output_span }; - (self.tcx().mk_ty(ty::TyTuple(inputs)), output_binding) + (self.tcx().mk_ty(ty::TyTuple(inputs, false)), output_binding) } /// Instantiates the path for the given trait reference, assuming that it's @@ -1170,7 +1170,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.types.never }, hir::TyTup(ref fields) => { - tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t))) + tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)), false) } hir::TyBareFn(ref bf) => { require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 932e7ae1dd426..feed5752cf8fb 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -164,7 +164,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut expected_len = elements.len(); if ddpos.is_some() { // Require known type only when `..` is present - if let ty::TyTuple(ref tys) = + if let ty::TyTuple(ref tys, _) = self.structurally_resolved_type(pat.span, expected).sty { expected_len = tys.len(); } @@ -176,7 +176,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // from all tuple elements isn't trivial. TypeVariableOrigin::TypeInference(pat.span))); let element_tys = tcx.mk_type_list(element_tys_iter); - let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys)); + let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys, false)); self.demand_eqtype(pat.span, expected, pat_ty); for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { self.check_pat(elem, &element_tys[i]); diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 2e6592b550179..7979edbf5e27a 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -89,7 +89,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Tuple up the arguments and insert the resulting function type into // the `closures` table. fn_ty.sig.0 = self.tcx.mk_fn_sig( - iter::once(self.tcx.intern_tup(fn_ty.sig.skip_binder().inputs())), + iter::once(self.tcx.intern_tup(fn_ty.sig.skip_binder().inputs(), false)), fn_ty.sig.skip_binder().output(), fn_ty.sig.variadic() ); @@ -218,7 +218,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { arg_param_ty); let input_tys = match arg_param_ty.sty { - ty::TyTuple(tys) => tys.into_iter(), + ty::TyTuple(tys, _) => tys.into_iter(), _ => { return None; } diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 34aa4eda772ad..f701bc3220848 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -489,7 +489,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>( Ok(()) } - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { for ty in tys { iterate_over_potentially_unsafe_regions_in_type(cx, context, ty, depth+1)? } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 7ead7ada893d7..cb4e85e842c2a 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -87,7 +87,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { "cxchg" | "cxchgweak" => (1, vec![tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0), param(ccx, 0)], - tcx.intern_tup(&[param(ccx, 0), tcx.types.bool])), + tcx.intern_tup(&[param(ccx, 0), tcx.types.bool], false)), "load" => (1, vec![tcx.mk_imm_ptr(param(ccx, 0))], param(ccx, 0)), "store" => (1, vec![tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)], @@ -272,7 +272,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => (1, vec![param(ccx, 0), param(ccx, 0)], - tcx.intern_tup(&[param(ccx, 0), tcx.types.bool])), + tcx.intern_tup(&[param(ccx, 0), tcx.types.bool], false)), "unchecked_div" | "unchecked_rem" => (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)), @@ -420,7 +420,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>( match *expected { Void => match t.sty { - ty::TyTuple(ref v) if v.is_empty() => {}, + ty::TyTuple(ref v, _) if v.is_empty() => {}, _ => simple_error(&format!("`{}`", t), "()"), }, // (The width we pass to LLVM doesn't concern the type checker.) @@ -494,7 +494,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>( } Aggregate(_flatten, ref expected_contents) => { match t.sty { - ty::TyTuple(contents) => { + ty::TyTuple(contents, _) => { if contents.len() != expected_contents.len() { simple_error(&format!("tuple with length {}", contents.len()), &format!("tuple with length {}", expected_contents.len())); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1d9913cd96dc3..c4a366c2f17fe 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1947,7 +1947,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } /// Apply "fallbacks" to some types - /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64. + /// unconstrained types get replaced with ! or () (depending on whether + /// feature(never_type) is enabled), unconstrained ints with i32, and + /// unconstrained floats with f64. fn default_type_parameters(&self) { use rustc::ty::error::UnconstrainedNumeric::Neither; use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat}; @@ -2408,7 +2410,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let err_inputs = match tuple_arguments { DontTupleArguments => err_inputs, - TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..])], + TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..], false)], }; self.check_argument_types(sp, &err_inputs[..], &[], args_no_rcvr, @@ -2505,16 +2507,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let formal_tys = if tuple_arguments == TupleArguments { let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]); match tuple_type.sty { - ty::TyTuple(arg_types) if arg_types.len() != args.len() => { + ty::TyTuple(arg_types, _) if arg_types.len() != args.len() => { parameter_count_error(tcx.sess, sp_args, arg_types.len(), args.len(), "E0057", false, def_span); expected_arg_tys = &[]; self.err_args(args.len()) } - ty::TyTuple(arg_types) => { + ty::TyTuple(arg_types, _) => { expected_arg_tys = match expected_arg_tys.get(0) { Some(&ty) => match ty.sty { - ty::TyTuple(ref tys) => &tys, + ty::TyTuple(ref tys, _) => &tys, _ => &[] }, None => &[] @@ -3072,7 +3074,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }) } - ty::TyTuple(ref v) => { + ty::TyTuple(ref v, _) => { tuple_like = true; v.get(idx.node).cloned() } @@ -3864,7 +3866,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::ExprTup(ref elts) => { let flds = expected.only_has_type(self).and_then(|ty| { match ty.sty { - ty::TyTuple(ref flds) => Some(&flds[..]), + ty::TyTuple(ref flds, _) => Some(&flds[..]), _ => None } }); @@ -3882,7 +3884,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; t }); - let tuple = tcx.mk_tup(elt_ts_iter); + let tuple = tcx.mk_tup(elt_ts_iter, false); if tuple.references_error() { tcx.types.err } else { @@ -3923,7 +3925,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }, base_t); // Try to give some advice about indexing tuples. - if let ty::TyTuple(_) = base_t.sty { + if let ty::TyTuple(..) = base_t.sty { let mut needs_note = true; // If the index is an integer, we can show the actual // fixed expression: diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 40e82959336de..860f6d98370ad 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -338,7 +338,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_mt(generics, mt, variance); } - ty::TyTuple(subtys) => { + ty::TyTuple(subtys, _) => { for &subty in subtys { self.add_constraints_from_ty(generics, subty, variance); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fe2edcad25c20..dc2aa1f138d62 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -655,7 +655,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option, has_self: boo Some(did) if cx.tcx.lang_items.fn_trait_kind(did).is_some() => { assert_eq!(types.len(), 1); let inputs = match types[0].sty { - ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(), + ty::TyTuple(ref tys, _) => tys.iter().map(|t| t.clean(cx)).collect(), _ => { return PathParameters::AngleBracketed { lifetimes: lifetimes, @@ -667,7 +667,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option, has_self: boo let output = None; // FIXME(#20299) return type comes from a projection now // match types[1].sty { - // ty::TyTuple(ref v) if v.is_empty() => None, // -> () + // ty::TyTuple(ref v, _) if v.is_empty() => None, // -> () // _ => Some(types[1].clean(cx)) // }; PathParameters::Parenthesized { @@ -710,7 +710,7 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { // collect any late bound regions let mut late_bounds = vec![]; for ty_s in self.input_types().skip(1) { - if let ty::TyTuple(ts) = ty_s.sty { + if let ty::TyTuple(ts, _) = ty_s.sty { for &ty_s in ts { if let ty::TyRef(ref reg, _) = ty_s.sty { if let &ty::Region::ReLateBound(..) = *reg { @@ -1895,7 +1895,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { Never } } - ty::TyTuple(ref t) => Tuple(t.clean(cx)), + ty::TyTuple(ref t, _) => Tuple(t.clean(cx)), ty::TyProjection(ref data) => data.clean(cx), diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 503ef4c3183d2..84f69cd35045c 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -193,7 +193,7 @@ pub fn main_args(args: &[String]) -> isize { nightly_options::check_nightly_options(&matches, &opts()); if matches.opt_present("h") || matches.opt_present("help") { - usage(&args[0]); + usage("rustdoc"); return 0; } else if matches.opt_present("version") { rustc_driver::version("rustdoc", &matches); diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index b220504d2b4f5..35c388ba076ce 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -399,7 +399,7 @@ impl ExactSizeIterator for EscapeDefault {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeDefault {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("EscapeDefault { .. }") diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 8058972e75093..ffb7a1a1fc15f 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1283,7 +1283,7 @@ impl<'a, K, V> Clone for Iter<'a, K, V> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: Debug, V: Debug> fmt::Debug for Iter<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -1318,7 +1318,7 @@ impl<'a, K, V> Clone for Keys<'a, K, V> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: Debug, V: Debug> fmt::Debug for Keys<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -1341,7 +1341,7 @@ impl<'a, K, V> Clone for Values<'a, K, V> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: Debug, V: Debug> fmt::Debug for Values<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -1591,7 +1591,7 @@ impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K, V> fmt::Debug for IterMut<'a, K, V> where K: fmt::Debug, V: fmt::Debug, @@ -1626,7 +1626,7 @@ impl ExactSizeIterator for IntoIter { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -1704,7 +1704,7 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K, V> fmt::Debug for ValuesMut<'a, K, V> where K: fmt::Debug, V: fmt::Debug, @@ -1739,7 +1739,7 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for Drain<'a, K, V> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K, V> fmt::Debug for Drain<'a, K, V> where K: fmt::Debug, V: fmt::Debug, @@ -2227,7 +2227,7 @@ impl Default for RandomState { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for RandomState { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("RandomState { .. }") diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 341b050862f5c..a3f7e13bbf913 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -948,7 +948,7 @@ impl<'a, K> ExactSizeIterator for Iter<'a, K> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K> FusedIterator for Iter<'a, K> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: fmt::Debug> fmt::Debug for Iter<'a, K> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -977,7 +977,7 @@ impl ExactSizeIterator for IntoIter { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let entries_iter = self.iter.inner.iter().map(|(k, _)| k); @@ -1007,7 +1007,7 @@ impl<'a, K> ExactSizeIterator for Drain<'a, K> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K> FusedIterator for Drain<'a, K> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: fmt::Debug> fmt::Debug for Drain<'a, K> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let entries_iter = self.iter.inner.iter().map(|(k, _)| k); @@ -1050,7 +1050,7 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S> } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T, S> fmt::Debug for Intersection<'a, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, @@ -1109,7 +1109,7 @@ impl<'a, T, S> FusedIterator for Difference<'a, T, S> { } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T, S> fmt::Debug for Difference<'a, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, @@ -1150,7 +1150,7 @@ impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S> { } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T, S> fmt::Debug for SymmetricDifference<'a, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, @@ -1176,7 +1176,7 @@ impl<'a, T, S> FusedIterator for Union<'a, T, S> { } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T, S> fmt::Debug for Union<'a, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, diff --git a/src/libstd/env.rs b/src/libstd/env.rs index c3a6b2433ed88..29f2ac6ab444c 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -145,7 +145,7 @@ impl Iterator for Vars { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Vars { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Vars { .. }") @@ -159,7 +159,7 @@ impl Iterator for VarsOs { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for VarsOs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("VarsOs { .. }") @@ -382,7 +382,7 @@ impl<'a> Iterator for SplitPaths<'a> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a> fmt::Debug for SplitPaths<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("SplitPaths { .. }") @@ -665,7 +665,7 @@ impl DoubleEndedIterator for Args { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Args { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Args { .. }") @@ -690,7 +690,7 @@ impl DoubleEndedIterator for ArgsOs { fn next_back(&mut self) -> Option { self.inner.next_back() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ArgsOs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ArgsOs { .. }") diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 249627c430cb7..e5562d05f10ae 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -869,7 +869,7 @@ impl Metadata { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Metadata { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Metadata") diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index de5fc5bfad137..8cb7b2bda7554 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1450,7 +1450,7 @@ pub struct Chain { done_first: bool, } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Chain { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Chain") diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 83a675eb512e5..e16e8019b5f73 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -282,7 +282,7 @@ impl Stdin { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stdin { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Stdin { .. }") @@ -321,7 +321,7 @@ impl<'a> BufRead for StdinLock<'a> { fn consume(&mut self, n: usize) { self.inner.consume(n) } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a> fmt::Debug for StdinLock<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("StdinLock { .. }") @@ -438,7 +438,7 @@ impl Stdout { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stdout { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Stdout { .. }") @@ -470,7 +470,7 @@ impl<'a> Write for StdoutLock<'a> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a> fmt::Debug for StdoutLock<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("StdoutLock { .. }") @@ -573,7 +573,7 @@ impl Stderr { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stderr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Stderr { .. }") @@ -605,7 +605,7 @@ impl<'a> Write for StderrLock<'a> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a> fmt::Debug for StderrLock<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("StderrLock { .. }") diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index e50665120eb47..4163187488e65 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -98,7 +98,7 @@ impl BufRead for Empty { fn consume(&mut self, _n: usize) {} } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Empty { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Empty { .. }") @@ -141,7 +141,7 @@ impl Read for Repeat { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Repeat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Repeat { .. }") @@ -180,7 +180,7 @@ impl Write for Sink { fn flush(&mut self) -> io::Result<()> { Ok(()) } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Sink { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Sink { .. }") diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 181694dead03c..9bcecebf693d2 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -277,6 +277,7 @@ #![feature(oom)] #![feature(optin_builtin_traits)] #![feature(panic_unwind)] +#![feature(peek)] #![feature(placement_in_syntax)] #![feature(prelude_import)] #![feature(pub_restricted)] diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index 2b60fc38198ec..b0d2e3e4687b4 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -106,7 +106,10 @@ impl Iterator for LookupHost { fn next(&mut self) -> Option { self.0.next() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[unstable(feature = "lookup_host", reason = "unsure about the returned \ + iterator and returning socket \ + addresses", + issue = "27705")] impl fmt::Debug for LookupHost { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("LookupHost { .. }") diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index cbc672c28bc6a..9bead22ef7f5e 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -296,6 +296,29 @@ impl TcpStream { self.0.write_timeout() } + /// Receives data on the socket from the remote adress to which it is + /// connected, without removing that data from the queue. On success, + /// returns the number of bytes peeked. + /// + /// Successive calls return the same data. This is accomplished by passing + /// `MSG_PEEK` as a flag to the underlying `recv` system call. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(peek)] + /// use std::net::TcpStream; + /// + /// let stream = TcpStream::connect("127.0.0.1:8000") + /// .expect("couldn't bind to address"); + /// let mut buf = [0; 10]; + /// let len = stream.peek(&mut buf).expect("peek failed"); + /// ``` + #[unstable(feature = "peek", issue = "38980")] + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.0.peek(buf) + } + /// Sets the value of the `TCP_NODELAY` option on this socket. /// /// If set, this option disables the Nagle algorithm. This means that @@ -1406,4 +1429,35 @@ mod tests { Err(e) => panic!("unexpected error {}", e), } } + + #[test] + fn peek() { + each_ip(&mut |addr| { + let (txdone, rxdone) = channel(); + + let srv = t!(TcpListener::bind(&addr)); + let _t = thread::spawn(move|| { + let mut cl = t!(srv.accept()).0; + cl.write(&[1,3,3,7]).unwrap(); + t!(rxdone.recv()); + }); + + let mut c = t!(TcpStream::connect(&addr)); + let mut b = [0; 10]; + for _ in 1..3 { + let len = c.peek(&mut b).unwrap(); + assert_eq!(len, 4); + } + let len = c.read(&mut b).unwrap(); + assert_eq!(len, 4); + + t!(c.set_nonblocking(true)); + match c.peek(&mut b) { + Ok(_) => panic!("expected error"), + Err(ref e) if e.kind() == ErrorKind::WouldBlock => {} + Err(e) => panic!("unexpected error {}", e), + } + t!(txdone.send(())); + }) + } } diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 492e57f6e44e5..f452c75d38966 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -83,6 +83,30 @@ impl UdpSocket { self.0.recv_from(buf) } + /// Receives data from the socket, without removing it from the queue. + /// + /// Successive calls return the same data. This is accomplished by passing + /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call. + /// + /// On success, returns the number of bytes peeked and the address from + /// whence the data came. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(peek)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// let mut buf = [0; 10]; + /// let (number_of_bytes, src_addr) = socket.peek_from(&mut buf) + /// .expect("Didn't receive data"); + /// ``` + #[unstable(feature = "peek", issue = "38980")] + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.0.peek_from(buf) + } + /// Sends data on the socket to the given address. On success, returns the /// number of bytes written. /// @@ -579,6 +603,37 @@ impl UdpSocket { self.0.recv(buf) } + /// Receives data on the socket from the remote adress to which it is + /// connected, without removing that data from the queue. On success, + /// returns the number of bytes peeked. + /// + /// Successive calls return the same data. This is accomplished by passing + /// `MSG_PEEK` as a flag to the underlying `recv` system call. + /// + /// # Errors + /// + /// This method will fail if the socket is not connected. The `connect` method + /// will connect this socket to a remote address. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(peek)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.connect("127.0.0.1:8080").expect("connect function failed"); + /// let mut buf = [0; 10]; + /// match socket.peek(&mut buf) { + /// Ok(received) => println!("received {} bytes", received), + /// Err(e) => println!("peek function failed: {:?}", e), + /// } + /// ``` + #[unstable(feature = "peek", issue = "38980")] + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.0.peek(buf) + } + /// Moves this UDP socket into or out of nonblocking mode. /// /// On Unix this corresponds to calling fcntl, and on Windows this @@ -869,6 +924,48 @@ mod tests { assert_eq!(b"hello world", &buf[..]); } + #[test] + fn connect_send_peek_recv() { + each_ip(&mut |addr, _| { + let socket = t!(UdpSocket::bind(&addr)); + t!(socket.connect(addr)); + + t!(socket.send(b"hello world")); + + for _ in 1..3 { + let mut buf = [0; 11]; + let size = t!(socket.peek(&mut buf)); + assert_eq!(b"hello world", &buf[..]); + assert_eq!(size, 11); + } + + let mut buf = [0; 11]; + let size = t!(socket.recv(&mut buf)); + assert_eq!(b"hello world", &buf[..]); + assert_eq!(size, 11); + }) + } + + #[test] + fn peek_from() { + each_ip(&mut |addr, _| { + let socket = t!(UdpSocket::bind(&addr)); + t!(socket.send_to(b"hello world", &addr)); + + for _ in 1..3 { + let mut buf = [0; 11]; + let (size, _) = t!(socket.peek_from(&mut buf)); + assert_eq!(b"hello world", &buf[..]); + assert_eq!(size, 11); + } + + let mut buf = [0; 11]; + let (size, _) = t!(socket.recv_from(&mut buf)); + assert_eq!(b"hello world", &buf[..]); + assert_eq!(size, 11); + }) + } + #[test] fn ttl() { let ttl = 100; diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs index cc154f7ab413b..68d4ca900195c 100644 --- a/src/libstd/os/raw.rs +++ b/src/libstd/os/raw.rs @@ -73,7 +73,7 @@ pub enum c_void { #[doc(hidden)] __variant2, } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for c_void { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("c_void") diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index faf4949e86192..ac0d0d2afb803 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -297,7 +297,7 @@ impl R> FnOnce<()> for AssertUnwindSafe { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for AssertUnwindSafe { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("AssertUnwindSafe") diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 5af4ba53bf9a5..c16b97ebda5e3 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -114,7 +114,7 @@ impl IntoInner for Child { fn into_inner(self) -> imp::Process { self.handle } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Child { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Child") @@ -160,7 +160,7 @@ impl FromInner for ChildStdin { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ChildStdin { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ChildStdin { .. }") @@ -201,7 +201,7 @@ impl FromInner for ChildStdout { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ChildStdout { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ChildStdout { .. }") @@ -242,7 +242,7 @@ impl FromInner for ChildStderr { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ChildStderr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ChildStderr { .. }") @@ -696,7 +696,7 @@ impl FromInner for Stdio { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stdio { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Stdio { .. }") @@ -959,10 +959,27 @@ impl Child { /// /// # Examples /// +/// Due to this function’s behavior regarding destructors, a conventional way +/// to use the function is to extract the actual computation to another +/// function and compute the exit code from its return value: +/// /// ``` -/// use std::process; +/// use std::io::{self, Write}; +/// +/// fn run_app() -> Result<(), ()> { +/// // Application logic here +/// Ok(()) +/// } /// -/// process::exit(0); +/// fn main() { +/// ::std::process::exit(match run_app() { +/// Ok(_) => 0, +/// Err(err) => { +/// writeln!(io::stderr(), "error: {:?}", err).unwrap(); +/// 1 +/// } +/// }); +/// } /// ``` /// /// Due to [platform-specific behavior], the exit code for this example will be diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index b8e83dced8d4b..fc4fd4ce92b1b 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -55,7 +55,7 @@ struct BarrierState { #[stable(feature = "rust1", since = "1.0.0")] pub struct BarrierWaitResult(bool); -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Barrier { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Barrier { .. }") @@ -110,7 +110,7 @@ impl Barrier { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for BarrierWaitResult { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("BarrierWaitResult") diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 5c85c4879a839..7ee1c98565cfd 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -240,7 +240,7 @@ impl Condvar { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Condvar { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Condvar { .. }") diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 2efddeb4610dd..0d6ad5e38e98b 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -428,7 +428,7 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("MutexGuard") diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index a9747639aacd7..ba99375139139 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -330,7 +330,7 @@ impl Once { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Once { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Once { .. }") diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index adbb98e4b1f4f..a3db0adeda00d 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -361,7 +361,7 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RwLockReadGuard") @@ -370,7 +370,7 @@ impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RwLockWriteGuard") diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 585dcbb9a34a1..2961c4ec58245 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -67,10 +67,20 @@ pub trait CommandExt { /// an error indicating why the exec (or another part of the setup of the /// `Command`) failed. /// + /// `exec` not returning has the same implications as calling + /// [`process::exit`] – no destructors on the current stack or any other + /// thread’s stack will be run. Therefore, it is recommended to only call + /// `exec` at a point where it is fine to not run any destructors. Note, + /// that the `execvp` syscall independently guarantees that all memory is + /// freed and all file descriptors with the `CLOEXEC` option (set by default + /// on all file descriptors opened by the standard library) are closed. + /// /// This function, unlike `spawn`, will **not** `fork` the process to create /// a new child. Like spawn, however, the default behavior for the stdio /// descriptors will be to inherited from the current process. /// + /// [`process::exit`]: ../../../process/fn.exit.html + /// /// # Notes /// /// The process may be in a "broken state" if this function returns in diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index ad287bbec3889..5efddca110f05 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -10,12 +10,13 @@ use ffi::CStr; use io; -use libc::{self, c_int, size_t, sockaddr, socklen_t, EAI_SYSTEM}; +use libc::{self, c_int, c_void, size_t, sockaddr, socklen_t, EAI_SYSTEM, MSG_PEEK}; +use mem; use net::{SocketAddr, Shutdown}; use str; use sys::fd::FileDesc; use sys_common::{AsInner, FromInner, IntoInner}; -use sys_common::net::{getsockopt, setsockopt}; +use sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; use time::Duration; pub use sys::{cvt, cvt_r}; @@ -155,8 +156,46 @@ impl Socket { self.0.duplicate().map(Socket) } + fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result { + let ret = cvt(unsafe { + libc::recv(self.0.raw(), + buf.as_mut_ptr() as *mut c_void, + buf.len(), + flags) + })?; + Ok(ret as usize) + } + pub fn read(&self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) + self.recv_with_flags(buf, 0) + } + + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.recv_with_flags(buf, MSG_PEEK) + } + + fn recv_from_with_flags(&self, buf: &mut [u8], flags: c_int) + -> io::Result<(usize, SocketAddr)> { + let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; + let mut addrlen = mem::size_of_val(&storage) as libc::socklen_t; + + let n = cvt(unsafe { + libc::recvfrom(self.0.raw(), + buf.as_mut_ptr() as *mut c_void, + buf.len(), + flags, + &mut storage as *mut _ as *mut _, + &mut addrlen) + })?; + Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) + } + + pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, 0) + } + + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, MSG_PEEK) } pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 1b29bf73c7aec..850d6f49612ee 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -167,6 +167,7 @@ pub const SYMLINK_FLAG_RELATIVE: DWORD = 0x00000001; pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4; pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1; +pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2; // Note that these are not actually HANDLEs, just values to pass to GetStdHandle pub const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD; @@ -245,6 +246,7 @@ pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; pub const IPV6_ADD_MEMBERSHIP: c_int = 12; pub const IPV6_DROP_MEMBERSHIP: c_int = 13; +pub const MSG_PEEK: c_int = 0x2; #[repr(C)] pub struct ip_mreq { diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index c410fcd1ee0ed..4efc68afdc4c7 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -646,9 +646,25 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> { let src = to_u16s(src)?; let dst = to_u16s(dst)?; let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 }; - cvt(unsafe { - c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL - })?; + // Formerly, symlink creation required the SeCreateSymbolicLink privilege. For the Windows 10 + // Creators Update, Microsoft loosened this to allow unprivileged symlink creation if the + // computer is in Developer Mode, but SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE must be + // added to dwFlags to opt into this behaviour. + let result = cvt(unsafe { + c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), + flags | c::SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) as c::BOOL + }); + if let Err(err) = result { + if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as i32) { + // Older Windows objects to SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE, + // so if we encounter ERROR_INVALID_PARAMETER, retry without that flag. + cvt(unsafe { + c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL + })?; + } else { + return Err(err); + } + } Ok(()) } diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index aca6994503ff8..adf6210d82e89 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -147,12 +147,12 @@ impl Socket { Ok(socket) } - pub fn read(&self, buf: &mut [u8]) -> io::Result { + fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result { // On unix when a socket is shut down all further reads return 0, so we // do the same on windows to map a shut down socket to returning EOF. let len = cmp::min(buf.len(), i32::max_value() as usize) as i32; unsafe { - match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, 0) { + match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, flags) { -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0), -1 => Err(last_error()), n => Ok(n as usize) @@ -160,6 +160,46 @@ impl Socket { } } + pub fn read(&self, buf: &mut [u8]) -> io::Result { + self.recv_with_flags(buf, 0) + } + + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.recv_with_flags(buf, c::MSG_PEEK) + } + + fn recv_from_with_flags(&self, buf: &mut [u8], flags: c_int) + -> io::Result<(usize, SocketAddr)> { + let mut storage: c::SOCKADDR_STORAGE_LH = unsafe { mem::zeroed() }; + let mut addrlen = mem::size_of_val(&storage) as c::socklen_t; + let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; + + // On unix when a socket is shut down all further reads return 0, so we + // do the same on windows to map a shut down socket to returning EOF. + unsafe { + match c::recvfrom(self.0, + buf.as_mut_ptr() as *mut c_void, + len, + flags, + &mut storage as *mut _ as *mut _, + &mut addrlen) { + -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => { + Ok((0, net::sockaddr_to_addr(&storage, addrlen as usize)?)) + }, + -1 => Err(last_error()), + n => Ok((n as usize, net::sockaddr_to_addr(&storage, addrlen as usize)?)), + } + } + } + + pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, 0) + } + + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, c::MSG_PEEK) + } + pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { let mut me = self; (&mut me).read_to_end(buf) diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index 10ad61f4c800c..3cdeb51194575 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -91,7 +91,7 @@ fn sockname(f: F) -> io::Result } } -fn sockaddr_to_addr(storage: &c::sockaddr_storage, +pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result { match storage.ss_family as c_int { c::AF_INET => { @@ -222,6 +222,10 @@ impl TcpStream { self.inner.timeout(c::SO_SNDTIMEO) } + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.inner.peek(buf) + } + pub fn read(&self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } @@ -441,17 +445,11 @@ impl UdpSocket { } pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() }; - let mut addrlen = mem::size_of_val(&storage) as c::socklen_t; - let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; + self.inner.recv_from(buf) + } - let n = cvt(unsafe { - c::recvfrom(*self.inner.as_inner(), - buf.as_mut_ptr() as *mut c_void, - len, 0, - &mut storage as *mut _ as *mut _, &mut addrlen) - })?; - Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.inner.peek_from(buf) } pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result { @@ -578,6 +576,10 @@ impl UdpSocket { self.inner.read(buf) } + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.inner.peek(buf) + } + pub fn send(&self, buf: &[u8]) -> io::Result { let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; let ret = cvt(unsafe { diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 01584979aabaa..5166ddf8a21b6 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -99,7 +99,7 @@ pub struct LocalKey { init: fn() -> T, } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for LocalKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("LocalKey { .. }") @@ -332,7 +332,6 @@ pub mod os { marker: marker::PhantomData>, } - #[stable(feature = "std_debug", since = "1.15.0")] impl fmt::Debug for Key { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Key { .. }") diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 8789006436c0c..93e320c45223c 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -698,7 +698,7 @@ impl ThreadId { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[unstable(feature = "thread_id", issue = "21507")] impl fmt::Debug for ThreadId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ThreadId { .. }") @@ -1002,7 +1002,7 @@ impl IntoInner for JoinHandle { fn into_inner(self) -> imp::Thread { self.0.native.unwrap() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for JoinHandle { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("JoinHandle { .. }") diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index f2c53efda1737..4269ce8534bd0 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -131,7 +131,6 @@ impl Iterator for CaseMappingIter { } } -#[stable(feature = "char_struct_display", since = "1.17.0")] impl fmt::Display for CaseMappingIter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -152,14 +151,14 @@ impl fmt::Display for CaseMappingIter { } } -#[stable(feature = "char_struct_display", since = "1.17.0")] +#[stable(feature = "char_struct_display", since = "1.16.0")] impl fmt::Display for ToLowercase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } } -#[stable(feature = "char_struct_display", since = "1.17.0")] +#[stable(feature = "char_struct_display", since = "1.16.0")] impl fmt::Display for ToUppercase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index edf74e1fe19f1..9a717b86d091e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -10,7 +10,7 @@ pub use self::SyntaxExtension::{MultiDecorator, MultiModifier, NormalTT, IdentTT}; -use ast::{self, Attribute, Name, PatKind}; +use ast::{self, Attribute, Name, PatKind, MetaItem}; use attr::HasAttrs; use codemap::{self, CodeMap, ExpnInfo, Spanned, respan}; use syntax_pos::{Span, ExpnId, NO_EXPANSION}; @@ -471,6 +471,9 @@ impl MacResult for DummyResult { } } +pub type BuiltinDeriveFn = + for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable)); + /// An enum representing the different kinds of syntax extensions. pub enum SyntaxExtension { /// A syntax extension that is attached to an item and creates new items @@ -507,7 +510,14 @@ pub enum SyntaxExtension { /// IdentTT(Box, Option, bool), - CustomDerive(Box), + /// An attribute-like procedural macro. TokenStream -> TokenStream. + /// The input is the annotated item. + /// Allows generating code to implement a Trait for a given struct + /// or enum item. + ProcMacroDerive(Box), + + /// An attribute-like procedural macro that derives a builtin trait. + BuiltinDerive(BuiltinDeriveFn), } pub type NamedSyntaxExtension = (Name, SyntaxExtension); @@ -526,6 +536,9 @@ pub trait Resolver { fn find_attr_invoc(&mut self, attrs: &mut Vec) -> Option; fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) -> Result, Determinacy>; + fn resolve_builtin_macro(&mut self, tname: Name) -> Result, Determinacy>; + fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) + -> Result, Determinacy>; } #[derive(Copy, Clone, Debug)] @@ -552,6 +565,13 @@ impl Resolver for DummyResolver { -> Result, Determinacy> { Err(Determinacy::Determined) } + fn resolve_builtin_macro(&mut self, _tname: Name) -> Result, Determinacy> { + Err(Determinacy::Determined) + } + fn resolve_derive_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool) + -> Result, Determinacy> { + Err(Determinacy::Determined) + } } #[derive(Clone)] diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs new file mode 100644 index 0000000000000..946448eaaee99 --- /dev/null +++ b/src/libsyntax/ext/derive.rs @@ -0,0 +1,218 @@ +// Copyright 2012-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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ast::Name; +use attr; +use ast::{self, NestedMetaItem}; use ext::base::{ExtCtxt, SyntaxExtension}; +use codemap; +use ext::build::AstBuilder; +use feature_gate; +use symbol::Symbol; +use syntax_pos::Span; + +pub fn derive_attr_trait<'a>(cx: &mut ExtCtxt, attr: &'a ast::Attribute) + -> Option<&'a NestedMetaItem> { + if attr.name() != "derive" { + return None; + } + if attr.value_str().is_some() { + cx.span_err(attr.span, "unexpected value in `derive`"); + return None; + } + + let traits = attr.meta_item_list().unwrap_or(&[]); + + if traits.is_empty() { + cx.span_warn(attr.span, "empty trait list in `derive`"); + return None; + } + + return traits.get(0); +} + +pub fn verify_derive_attrs(cx: &mut ExtCtxt, attrs: &[ast::Attribute]) { + for attr in attrs { + if attr.name() != "derive" { + continue; + } + + if attr.value_str().is_some() { + cx.span_err(attr.span, "unexpected value in `derive`"); + } + + let traits = attr.meta_item_list().unwrap_or(&[]).to_owned(); + + if traits.is_empty() { + cx.span_warn(attr.span, "empty trait list in `derive`"); + attr::mark_used(&attr); + continue; + } + for titem in traits { + if titem.word().is_none() { + cx.span_err(titem.span, "malformed `derive` entry"); + } + } + } +} + +#[derive(PartialEq, Debug, Clone, Copy)] +pub enum DeriveType { + Legacy, + ProcMacro, + Builtin +} + +impl DeriveType { + // Classify a derive trait name by resolving the macro. + pub fn classify(cx: &mut ExtCtxt, tname: Name) -> DeriveType { + let legacy_derive_name = Symbol::intern(&format!("derive_{}", tname)); + + if let Ok(_) = cx.resolver.resolve_builtin_macro(legacy_derive_name) { + return DeriveType::Legacy; + } + + match cx.resolver.resolve_builtin_macro(tname) { + Ok(ext) => match *ext { + SyntaxExtension::BuiltinDerive(..) => DeriveType::Builtin, + _ => DeriveType::ProcMacro, + }, + Err(_) => DeriveType::ProcMacro, + } + } +} + +pub fn get_derive_attr(cx: &mut ExtCtxt, attrs: &mut Vec, + derive_type: DeriveType) -> Option { + for i in 0..attrs.len() { + if attrs[i].name() != "derive" { + continue; + } + + if attrs[i].value_str().is_some() { + continue; + } + + let mut traits = attrs[i].meta_item_list().unwrap_or(&[]).to_owned(); + + // First, weed out malformed #[derive] + traits.retain(|titem| titem.word().is_some()); + + let mut titem = None; + + // See if we can find a matching trait. + for j in 0..traits.len() { + let tname = match traits[j].name() { + Some(tname) => tname, + _ => continue, + }; + + if DeriveType::classify(cx, tname) == derive_type { + titem = Some(traits.remove(j)); + break; + } + } + + // If we find a trait, remove the trait from the attribute. + if let Some(titem) = titem { + if traits.len() == 0 { + attrs.remove(i); + } else { + let derive = Symbol::intern("derive"); + let mitem = cx.meta_list(titem.span, derive, traits); + attrs[i] = cx.attribute(titem.span, mitem); + } + let derive = Symbol::intern("derive"); + let mitem = cx.meta_list(titem.span, derive, vec![titem]); + return Some(cx.attribute(mitem.span, mitem)); + } + } + return None; +} + +fn allow_unstable(cx: &mut ExtCtxt, span: Span, attr_name: &str) -> Span { + Span { + expn_id: cx.codemap().record_expansion(codemap::ExpnInfo { + call_site: span, + callee: codemap::NameAndSpan { + format: codemap::MacroAttribute(Symbol::intern(attr_name)), + span: Some(span), + allow_internal_unstable: true, + }, + }), + ..span + } +} + +pub fn add_derived_markers(cx: &mut ExtCtxt, attrs: &mut Vec) { + if attrs.is_empty() { + return; + } + + let titems = attrs.iter().filter(|a| { + a.name() == "derive" + }).flat_map(|a| { + a.meta_item_list().unwrap_or(&[]).iter() + }).filter_map(|titem| { + titem.name() + }).collect::>(); + + let span = attrs[0].span; + + if !attrs.iter().any(|a| a.name() == "structural_match") && + titems.iter().any(|t| *t == "PartialEq") && titems.iter().any(|t| *t == "Eq") { + let structural_match = Symbol::intern("structural_match"); + let span = allow_unstable(cx, span, "derive(PartialEq, Eq)"); + let meta = cx.meta_word(span, structural_match); + attrs.push(cx.attribute(span, meta)); + } + + if !attrs.iter().any(|a| a.name() == "rustc_copy_clone_marker") && + titems.iter().any(|t| *t == "Copy") && titems.iter().any(|t| *t == "Clone") { + let structural_match = Symbol::intern("rustc_copy_clone_marker"); + let span = allow_unstable(cx, span, "derive(Copy, Clone)"); + let meta = cx.meta_word(span, structural_match); + attrs.push(cx.attribute(span, meta)); + } +} + +pub fn find_derive_attr(cx: &mut ExtCtxt, attrs: &mut Vec) + -> Option { + verify_derive_attrs(cx, attrs); + get_derive_attr(cx, attrs, DeriveType::Legacy).and_then(|a| { + let titem = derive_attr_trait(cx, &a); + titem.and_then(|titem| { + let tword = titem.word().unwrap(); + let tname = tword.name(); + if !cx.ecfg.enable_custom_derive() { + feature_gate::emit_feature_err( + &cx.parse_sess, + "custom_derive", + titem.span, + feature_gate::GateIssue::Language, + feature_gate::EXPLAIN_CUSTOM_DERIVE + ); + None + } else { + let name = Symbol::intern(&format!("derive_{}", tname)); + if !cx.resolver.is_whitelisted_legacy_custom_derive(name) { + cx.span_warn(titem.span, + feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE); + } + let mitem = cx.meta_word(titem.span, name); + Some(cx.attribute(mitem.span, mitem)) + } + }) + }).or_else(|| { + get_derive_attr(cx, attrs, DeriveType::ProcMacro) + }).or_else(|| { + add_derived_markers(cx, attrs); + get_derive_attr(cx, attrs, DeriveType::Builtin) + }) +} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 226625ebc8e5e..8e7f8830eafbc 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -8,26 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{Block, Ident, Mac_, PatKind}; +use ast::{self, Block, Ident, Mac_, PatKind}; use ast::{Name, MacStmtStyle, StmtKind, ItemKind}; -use ast; -use ext::hygiene::Mark; -use ext::placeholders::{placeholder, PlaceholderExpander}; use attr::{self, HasAttrs}; use codemap::{ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; -use syntax_pos::{self, Span, ExpnId}; use config::{is_test_or_bench, StripUnconfigured}; use ext::base::*; +use ext::derive::{find_derive_attr, derive_attr_trait}; +use ext::hygiene::Mark; +use ext::placeholders::{placeholder, PlaceholderExpander}; use feature_gate::{self, Features}; use fold; use fold::*; -use parse::{ParseSess, DirectoryOwnership, PResult, filemap_to_tts}; use parse::parser::Parser; use parse::token; +use parse::{ParseSess, DirectoryOwnership, PResult, filemap_to_tts}; use print::pprust; use ptr::P; use std_inject; +use symbol::Symbol; use symbol::keywords; +use syntax_pos::{self, Span, ExpnId}; use tokenstream::{TokenTree, TokenStream}; use util::small_vector::SmallVector; use visit::Visitor; @@ -166,6 +167,10 @@ pub enum InvocationKind { attr: ast::Attribute, item: Annotatable, }, + Derive { + attr: ast::Attribute, + item: Annotatable, + }, } impl Invocation { @@ -173,6 +178,7 @@ impl Invocation { match self.kind { InvocationKind::Bang { span, .. } => span, InvocationKind::Attr { ref attr, .. } => attr.span, + InvocationKind::Derive { ref attr, .. } => attr.span, } } } @@ -250,6 +256,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let path = ast::Path::from_ident(attr.span, ident); self.cx.resolver.resolve_macro(scope, &path, force) } + InvocationKind::Derive { ref attr, .. } => { + let titem = derive_attr_trait(self.cx, &attr).unwrap(); + let tname = titem.name().expect("Expected derive macro name"); + let ident = Ident::with_empty_ctxt(tname); + let path = ast::Path::from_ident(attr.span, ident); + self.cx.resolver.resolve_derive_macro(scope, &path, force) + } }; let ext = match resolution { Ok(ext) => Some(ext), @@ -330,6 +343,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { match invoc.kind { InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext), InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext), + InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext), } } @@ -370,7 +384,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks); self.parse_expansion(tok_result, kind, name, attr.span) } - SyntaxExtension::CustomDerive(_) => { + SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => { self.cx.span_err(attr.span, &format!("`{}` is a derive mode", name)); kind.dummy(attr.span) } @@ -440,7 +454,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { return kind.dummy(span); } - SyntaxExtension::CustomDerive(..) => { + SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => { self.cx.span_err(path.span, &format!("`{}` is a derive mode", extname)); return kind.dummy(span); } @@ -486,6 +500,71 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }) } + /// Expand a derive invocation. Returns the result of expansion. + fn expand_derive_invoc(&mut self, invoc: Invocation, ext: Rc) -> Expansion { + let Invocation { expansion_kind: kind, .. } = invoc; + let (attr, item) = match invoc.kind { + InvocationKind::Derive { attr, item } => (attr, item), + _ => unreachable!(), + }; + + attr::mark_used(&attr); + let titem = derive_attr_trait(self.cx, &attr).unwrap(); + let tname = ast::Ident::with_empty_ctxt(titem.name().unwrap()); + let name = Symbol::intern(&format!("derive({})", tname)); + let mitem = &attr.value; + + self.cx.bt_push(ExpnInfo { + call_site: attr.span, + callee: NameAndSpan { + format: MacroAttribute(attr.name()), + span: Some(attr.span), + allow_internal_unstable: false, + } + }); + + match *ext { + SyntaxExtension::ProcMacroDerive(ref ext) => { + let span = Span { + expn_id: self.cx.codemap().record_expansion(ExpnInfo { + call_site: mitem.span, + callee: NameAndSpan { + format: MacroAttribute(Symbol::intern(&format!("derive({})", tname))), + span: None, + allow_internal_unstable: false, + }, + }), + ..mitem.span + }; + return kind.expect_from_annotatables(ext.expand(self.cx, span, &mitem, item)); + } + SyntaxExtension::BuiltinDerive(func) => { + let span = Span { + expn_id: self.cx.codemap().record_expansion(ExpnInfo { + call_site: titem.span, + callee: NameAndSpan { + format: MacroAttribute(name), + span: None, + allow_internal_unstable: true, + }, + }), + ..titem.span + }; + let mut items = Vec::new(); + func(self.cx, span, &mitem, &item, &mut |a| { + items.push(a) + }); + items.insert(0, item); + return kind.expect_from_annotatables(items); + } + _ => { + let msg = &format!("macro `{}` may not be used for derive attributes", name); + self.cx.span_err(attr.span, &msg); + kind.dummy(attr.span) + } + } + } + fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, name: Name, span: Span) -> Expansion { let mut parser = self.cx.new_parser_from_tts(&toks.trees().cloned().collect::>()); @@ -595,16 +674,31 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect_attr(&mut self, attr: ast::Attribute, item: Annotatable, kind: ExpansionKind) -> Expansion { - self.collect(kind, InvocationKind::Attr { attr: attr, item: item }) + let invoc_kind = if attr.name() == "derive" { + if kind == ExpansionKind::TraitItems || kind == ExpansionKind::ImplItems { + self.cx.span_err(attr.span, "`derive` can be only be applied to items"); + return kind.expect_from_annotatables(::std::iter::once(item)); + } + InvocationKind::Derive { attr: attr, item: item } + } else { + InvocationKind::Attr { attr: attr, item: item } + }; + + self.collect(kind, invoc_kind) } // If `item` is an attr invocation, remove and return the macro attribute. fn classify_item(&mut self, mut item: T) -> (T, Option) { let mut attr = None; + item = item.map_attrs(|mut attrs| { - attr = self.cx.resolver.find_attr_invoc(&mut attrs); + attr = self.cx.resolver.find_attr_invoc(&mut attrs).or_else(|| { + find_derive_attr(self.cx, &mut attrs) + }); + attrs }); + (item, attr) } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 970c37045dfc4..52ef2a05fcf19 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -318,7 +318,7 @@ declare_features! ( (active, abi_unadjusted, "1.16.0", None), // Macros 1.1 - (active, proc_macro, "1.16.0", Some(35900)), + (active, proc_macro, "1.16.0", Some(38356)), // Allows attributes on struct literal fields. (active, struct_field_attributes, "1.16.0", Some(38814)), @@ -381,7 +381,7 @@ declare_features! ( (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)), (accepted, item_like_imports, "1.14.0", Some(35120)), // Allows using `Self` and associated types in struct expressions and patterns. - (accepted, more_struct_aliases, "1.14.0", Some(37544)), + (accepted, more_struct_aliases, "1.16.0", Some(37544)), ); // (changing above list without updating src/doc/reference.md makes @cmr sad) diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 25be9e91a6ac9..87a03adf6b77c 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -128,6 +128,7 @@ pub mod print { pub mod ext { pub mod base; pub mod build; + pub mod derive; pub mod expand; pub mod placeholders; pub mod hygiene; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index fd7c56f136f48..45d8354d317dc 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1691,6 +1691,7 @@ impl<'a> Parser<'a> { } // Assemble the span. + // FIXME(#39450) This is bogus if part of the path is macro generated. let span = mk_sp(lo, self.prev_span.hi); // Assemble the result. diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index 2ce6fc03f7731..974e86a574124 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -32,18 +32,18 @@ impl<'a> Visitor<'a> for MarkAttrs<'a> { fn visit_mac(&mut self, _mac: &Mac) {} } -pub struct CustomDerive { +pub struct ProcMacroDerive { inner: fn(TokenStream) -> TokenStream, attrs: Vec, } -impl CustomDerive { - pub fn new(inner: fn(TokenStream) -> TokenStream, attrs: Vec) -> CustomDerive { - CustomDerive { inner: inner, attrs: attrs } +impl ProcMacroDerive { + pub fn new(inner: fn(TokenStream) -> TokenStream, attrs: Vec) -> ProcMacroDerive { + ProcMacroDerive { inner: inner, attrs: attrs } } } -impl MultiItemModifier for CustomDerive { +impl MultiItemModifier for ProcMacroDerive { fn expand(&self, ecx: &mut ExtCtxt, span: Span, @@ -54,7 +54,7 @@ impl MultiItemModifier for CustomDerive { Annotatable::Item(item) => item, Annotatable::ImplItem(_) | Annotatable::TraitItem(_) => { - ecx.span_err(span, "custom derive attributes may only be \ + ecx.span_err(span, "proc-macro derives may only be \ applied to struct/enum items"); return Vec::new() } @@ -63,7 +63,7 @@ impl MultiItemModifier for CustomDerive { ItemKind::Struct(..) | ItemKind::Enum(..) => {}, _ => { - ecx.span_err(span, "custom derive attributes may only be \ + ecx.span_err(span, "proc-macro derives may only be \ applied to struct/enum items"); return Vec::new() } @@ -81,7 +81,7 @@ impl MultiItemModifier for CustomDerive { let stream = match res { Ok(stream) => stream, Err(e) => { - let msg = "custom derive attribute panicked"; + let msg = "proc-macro derive panicked"; let mut err = ecx.struct_span_fatal(span, msg); if let Some(s) = e.downcast_ref::() { err.help(&format!("message: {}", s)); @@ -100,7 +100,7 @@ impl MultiItemModifier for CustomDerive { Ok(new_items) => new_items, Err(_) => { // FIXME: handle this better - let msg = "custom derive produced unparseable tokens"; + let msg = "proc-macro derive produced unparseable tokens"; ecx.struct_span_fatal(span, msg).emit(); panic!(FatalError); } diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index e2634c60dcaad..498f2348b80f1 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -13,6 +13,7 @@ use deriving; use deriving::generic::*; use deriving::generic::ty::*; +use deriving::warn_if_deprecated; use syntax::ast; use syntax::ast::{Expr, MetaItem, Mutability}; @@ -35,6 +36,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt, mitem: &MetaItem, item: &Annotatable, push: &mut FnMut(Annotatable)) { + warn_if_deprecated(cx, span, "Decodable"); expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize") } diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 092738ab8a03d..9d155c22ad031 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -91,6 +91,7 @@ use deriving; use deriving::generic::*; use deriving::generic::ty::*; +use deriving::warn_if_deprecated; use syntax::ast::{Expr, ExprKind, MetaItem, Mutability}; use syntax::ext::base::{Annotatable, ExtCtxt}; @@ -112,6 +113,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt, mitem: &MetaItem, item: &Annotatable, push: &mut FnMut(Annotatable)) { + warn_if_deprecated(cx, span, "Encodable"); expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize") } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 096f6dfd5d8d8..3bceb02f3d6c5 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -10,12 +10,11 @@ //! The compiler code necessary to implement the `#[derive]` extensions. -use syntax::ast::{self, MetaItem}; -use syntax::attr::HasAttrs; +use std::rc::Rc; +use syntax::ast; use syntax::codemap; -use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension}; +use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver}; use syntax::ext::build::AstBuilder; -use syntax::feature_gate; use syntax::ptr::P; use syntax::symbol::Symbol; use syntax_pos::Span; @@ -89,234 +88,6 @@ fn allow_unstable(cx: &mut ExtCtxt, span: Span, attr_name: &str) -> Span { } } -pub fn expand_derive(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - annotatable: Annotatable) - -> Vec { - debug!("expand_derive: span = {:?}", span); - debug!("expand_derive: mitem = {:?}", mitem); - debug!("expand_derive: annotatable input = {:?}", annotatable); - let mut item = match annotatable { - Annotatable::Item(item) => item, - other => { - cx.span_err(span, "`derive` can only be applied to items"); - return vec![other] - } - }; - - let derive = Symbol::intern("derive"); - let mut derive_attrs = Vec::new(); - item = item.map_attrs(|attrs| { - let partition = attrs.into_iter().partition(|attr| attr.name() == derive); - derive_attrs = partition.0; - partition.1 - }); - - // Expand `#[derive]`s after other attribute macro invocations. - if cx.resolver.find_attr_invoc(&mut item.attrs.clone()).is_some() { - return vec![Annotatable::Item(item.map_attrs(|mut attrs| { - attrs.push(cx.attribute(span, mitem.clone())); - attrs.extend(derive_attrs); - attrs - }))]; - } - - let get_traits = |mitem: &MetaItem, cx: &ExtCtxt| { - if mitem.value_str().is_some() { - cx.span_err(mitem.span, "unexpected value in `derive`"); - } - - let traits = mitem.meta_item_list().unwrap_or(&[]).to_owned(); - if traits.is_empty() { - cx.span_warn(mitem.span, "empty trait list in `derive`"); - } - traits - }; - - let mut traits = get_traits(mitem, cx); - for derive_attr in derive_attrs { - traits.extend(get_traits(&derive_attr.value, cx)); - } - - // First, weed out malformed #[derive] - traits.retain(|titem| { - if titem.word().is_none() { - cx.span_err(titem.span, "malformed `derive` entry"); - false - } else { - true - } - }); - - // Next, check for old-style #[derive(Foo)] - // - // These all get expanded to `#[derive_Foo]` and will get expanded first. If - // we actually add any attributes here then we return to get those expanded - // and then eventually we'll come back to finish off the other derive modes. - let mut new_attributes = Vec::new(); - traits.retain(|titem| { - let tword = titem.word().unwrap(); - let tname = tword.name(); - - if is_builtin_trait(tname) || { - let derive_mode = ast::Path::from_ident(titem.span, ast::Ident::with_empty_ctxt(tname)); - cx.resolver.resolve_macro(cx.current_expansion.mark, &derive_mode, false).map(|ext| { - if let SyntaxExtension::CustomDerive(_) = *ext { true } else { false } - }).unwrap_or(false) - } { - return true; - } - - if !cx.ecfg.enable_custom_derive() { - feature_gate::emit_feature_err(&cx.parse_sess, - "custom_derive", - titem.span, - feature_gate::GateIssue::Language, - feature_gate::EXPLAIN_CUSTOM_DERIVE); - } else { - let name = Symbol::intern(&format!("derive_{}", tname)); - if !cx.resolver.is_whitelisted_legacy_custom_derive(name) { - cx.span_warn(titem.span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE); - } - let mitem = cx.meta_word(titem.span, name); - new_attributes.push(cx.attribute(mitem.span, mitem)); - } - false - }); - if new_attributes.len() > 0 { - item = item.map(|mut i| { - i.attrs.extend(new_attributes); - if traits.len() > 0 { - let list = cx.meta_list(mitem.span, derive, traits); - i.attrs.push(cx.attribute(mitem.span, list)); - } - i - }); - return vec![Annotatable::Item(item)] - } - - // Now check for macros-1.1 style custom #[derive]. - // - // Expand each of them in order given, but *before* we expand any built-in - // derive modes. The logic here is to: - // - // 1. Collect the remaining `#[derive]` annotations into a list. If - // there are any left, attach a `#[derive]` attribute to the item - // that we're currently expanding with the remaining derive modes. - // 2. Manufacture a `#[derive(Foo)]` attribute to pass to the expander. - // 3. Expand the current item we're expanding, getting back a list of - // items that replace it. - // 4. Extend the returned list with the current list of items we've - // collected so far. - // 5. Return everything! - // - // If custom derive extensions end up threading through the `#[derive]` - // attribute, we'll get called again later on to continue expanding - // those modes. - let macros_11_derive = traits.iter() - .cloned() - .enumerate() - .filter(|&(_, ref name)| !is_builtin_trait(name.name().unwrap())) - .next(); - if let Some((i, titem)) = macros_11_derive { - let tname = ast::Ident::with_empty_ctxt(titem.name().unwrap()); - let path = ast::Path::from_ident(titem.span, tname); - let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap(); - - traits.remove(i); - if traits.len() > 0 { - item = item.map(|mut i| { - let list = cx.meta_list(mitem.span, derive, traits); - i.attrs.push(cx.attribute(mitem.span, list)); - i - }); - } - let titem = cx.meta_list_item_word(titem.span, titem.name().unwrap()); - let mitem = cx.meta_list(titem.span, derive, vec![titem]); - let item = Annotatable::Item(item); - - let span = Span { - expn_id: cx.codemap().record_expansion(codemap::ExpnInfo { - call_site: mitem.span, - callee: codemap::NameAndSpan { - format: codemap::MacroAttribute(Symbol::intern(&format!("derive({})", tname))), - span: None, - allow_internal_unstable: false, - }, - }), - ..mitem.span - }; - - if let SyntaxExtension::CustomDerive(ref ext) = *ext { - return ext.expand(cx, span, &mitem, item); - } else { - unreachable!() - } - } - - // Ok, at this point we know that there are no old-style `#[derive_Foo]` nor - // any macros-1.1 style `#[derive(Foo)]`. Expand all built-in traits here. - - // RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted) - // `#[structural_match]` attribute. - let (partial_eq, eq) = (Symbol::intern("PartialEq"), Symbol::intern("Eq")); - if traits.iter().any(|t| t.name() == Some(partial_eq)) && - traits.iter().any(|t| t.name() == Some(eq)) { - let structural_match = Symbol::intern("structural_match"); - let span = allow_unstable(cx, span, "derive(PartialEq, Eq)"); - let meta = cx.meta_word(span, structural_match); - item = item.map(|mut i| { - i.attrs.push(cx.attribute(span, meta)); - i - }); - } - - // RFC #1521. `Clone` can assume that `Copy` types' clone implementation is - // the same as the copy implementation. - // - // Add a marker attribute here picked up during #[derive(Clone)] - let (copy, clone) = (Symbol::intern("Copy"), Symbol::intern("Clone")); - if traits.iter().any(|t| t.name() == Some(clone)) && - traits.iter().any(|t| t.name() == Some(copy)) { - let marker = Symbol::intern("rustc_copy_clone_marker"); - let span = allow_unstable(cx, span, "derive(Copy, Clone)"); - let meta = cx.meta_word(span, marker); - item = item.map(|mut i| { - i.attrs.push(cx.attribute(span, meta)); - i - }); - } - - let mut items = Vec::new(); - for titem in traits.iter() { - let tname = titem.word().unwrap().name(); - let name = Symbol::intern(&format!("derive({})", tname)); - let mitem = cx.meta_word(titem.span, name); - - let span = Span { - expn_id: cx.codemap().record_expansion(codemap::ExpnInfo { - call_site: titem.span, - callee: codemap::NameAndSpan { - format: codemap::MacroAttribute(name), - span: None, - allow_internal_unstable: true, - }, - }), - ..titem.span - }; - - let my_item = Annotatable::Item(item); - expand_builtin(&tname.as_str(), cx, span, &mitem, &my_item, &mut |a| { - items.push(a); - }); - item = my_item.expect_item(); - } - - items.insert(0, Annotatable::Item(item)); - return items -} - macro_rules! derive_traits { ($( $name:expr => $func:path, )+) => { pub fn is_builtin_trait(name: ast::Name) -> bool { @@ -326,21 +97,13 @@ macro_rules! derive_traits { } } - fn expand_builtin(name: &str, - ecx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut FnMut(Annotatable)) { - match name { - $( - $name => { - warn_if_deprecated(ecx, span, $name); - $func(ecx, span, mitem, item, push); - } - )* - _ => panic!("not a builtin derive mode: {}", name), - } + pub fn register_builtin_derives(resolver: &mut Resolver) { + $( + resolver.add_ext( + ast::Ident::with_empty_ctxt(Symbol::intern($name)), + Rc::new(SyntaxExtension::BuiltinDerive($func)) + ); + )* } } } diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index ebec23d0901a0..7533171b08556 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -24,7 +24,6 @@ #![feature(staged_api)] extern crate fmt_macros; -#[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -51,12 +50,14 @@ pub mod proc_macro_impl; use std::rc::Rc; use syntax::ast; -use syntax::ext::base::{MacroExpanderFn, NormalTT, MultiModifier, NamedSyntaxExtension}; +use syntax::ext::base::{MacroExpanderFn, NormalTT, NamedSyntaxExtension}; use syntax::symbol::Symbol; pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, user_exts: Vec, enable_quotes: bool) { + deriving::register_builtin_derives(resolver); + let mut register = |name, ext| { resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext)); }; @@ -112,8 +113,6 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, register(Symbol::intern("format_args"), NormalTT(Box::new(format::expand_format_args), None, true)); - register(Symbol::intern("derive"), MultiModifier(Box::new(deriving::expand_derive))); - for (name, ext) in user_exts { register(name, ext); } diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index c8af16e9242f0..325f09a83ddab 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -27,7 +27,7 @@ use syntax_pos::{Span, DUMMY_SP}; use deriving; -struct CustomDerive { +struct ProcMacroDerive { trait_name: ast::Name, function_name: Ident, span: Span, @@ -40,7 +40,7 @@ struct AttrProcMacro { } struct CollectProcMacros<'a> { - derives: Vec, + derives: Vec, attr_macros: Vec, in_root: bool, handler: &'a errors::Handler, @@ -176,7 +176,7 @@ impl<'a> CollectProcMacros<'a> { }; if self.in_root && item.vis == ast::Visibility::Public { - self.derives.push(CustomDerive { + self.derives.push(ProcMacroDerive { span: item.span, trait_name: trait_name, function_name: item.ident, @@ -319,7 +319,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { // } // } fn mk_registrar(cx: &mut ExtCtxt, - custom_derives: &[CustomDerive], + custom_derives: &[ProcMacroDerive], custom_attrs: &[AttrProcMacro]) -> P { let eid = cx.codemap().record_expansion(ExpnInfo { call_site: DUMMY_SP, diff --git a/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs b/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs index a5359946c09c2..42fad803bfa68 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs @@ -16,7 +16,7 @@ extern crate derive_bad; #[derive( A )] -//~^^ ERROR: custom derive produced unparseable tokens +//~^^ ERROR: proc-macro derive produced unparseable tokens struct A; fn main() {} diff --git a/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs b/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs index f9906b650fb87..c483c048b418f 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs @@ -14,7 +14,7 @@ extern crate derive_panic; #[derive(A)] -//~^ ERROR: custom derive attribute panicked +//~^ ERROR: proc-macro derive panicked //~| HELP: message: nope! struct Foo; diff --git a/src/test/compile-fail-fulldeps/proc-macro/no-macro-use-attr.rs b/src/test/compile-fail-fulldeps/proc-macro/no-macro-use-attr.rs index f61b8b4073b6f..e47a4aefb5e0b 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/no-macro-use-attr.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/no-macro-use-attr.rs @@ -13,7 +13,7 @@ #![feature(rustc_attrs)] extern crate derive_a; -//~^ WARN custom derive crates and `#[no_link]` crates have no effect without `#[macro_use]` +//~^ WARN proc macro crates and `#[no_link]` crates have no effect without `#[macro_use]` #[rustc_error] fn main() {} //~ ERROR compilation successful diff --git a/src/test/compile-fail/defaulted-unit-warning.rs b/src/test/compile-fail/defaulted-unit-warning.rs new file mode 100644 index 0000000000000..5213a189714dd --- /dev/null +++ b/src/test/compile-fail/defaulted-unit-warning.rs @@ -0,0 +1,51 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] +#![allow(unreachable_code)] +#![deny(resolve_trait_on_defaulted_unit)] + +trait Deserialize: Sized { + fn deserialize() -> Result; +} + +impl Deserialize for () { + fn deserialize() -> Result<(), String> { + Ok(()) + } +} + +fn doit() -> Result<(), String> { + let _ = match Deserialize::deserialize() { + //~^ ERROR code relies on type + //~| WARNING previously accepted + Ok(x) => x, + Err(e) => return Err(e), + }; + Ok(()) +} + +trait ImplementedForUnitButNotNever {} + +impl ImplementedForUnitButNotNever for () {} + +fn foo(_t: T) {} + +fn smeg() { + let _x = return; + foo(_x); + //~^ ERROR code relies on type + //~| WARNING previously accepted +} + +fn main() { + let _ = doit(); +} + diff --git a/src/test/compile-fail/deriving-meta-unknown-trait.rs b/src/test/compile-fail/deriving-meta-unknown-trait.rs index 596cc1e7d5816..d388ece084417 100644 --- a/src/test/compile-fail/deriving-meta-unknown-trait.rs +++ b/src/test/compile-fail/deriving-meta-unknown-trait.rs @@ -11,7 +11,7 @@ // ignore-tidy-linelength #[derive(Eqr)] -//~^ ERROR `#[derive]` for custom traits is not stable enough for use. It is deprecated and will be removed in v1.15 (see issue #29644) +//~^ ERROR cannot find derive macro `Eqr` in this scope struct Foo; pub fn main() {} diff --git a/src/test/compile-fail/deriving-primitive.rs b/src/test/compile-fail/deriving-primitive.rs index be822a173ab58..97a39a46c19a8 100644 --- a/src/test/compile-fail/deriving-primitive.rs +++ b/src/test/compile-fail/deriving-primitive.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(FromPrimitive)] //~ERROR `#[derive]` for custom traits is not stable +#[derive(FromPrimitive)] //~ERROR cannot find derive macro `FromPrimitive` in this scope enum Foo {} fn main() {} diff --git a/src/test/compile-fail/macro-error.rs b/src/test/compile-fail/macro-error.rs index 4a6dbf014a1ca..f467ba3b1e195 100644 --- a/src/test/compile-fail/macro-error.rs +++ b/src/test/compile-fail/macro-error.rs @@ -16,5 +16,5 @@ fn main() { foo!(0); // Check that we report errors at macro definition, not expansion. let _: cfg!(foo) = (); //~ ERROR non-type macro in type position - derive!(); //~ ERROR `derive` can only be used in attributes + derive!(); //~ ERROR macro undefined: 'derive!' } diff --git a/src/test/compile-fail/macros-nonfatal-errors.rs b/src/test/compile-fail/macros-nonfatal-errors.rs index 723e936212a5b..3f710af8ac9a8 100644 --- a/src/test/compile-fail/macros-nonfatal-errors.rs +++ b/src/test/compile-fail/macros-nonfatal-errors.rs @@ -14,9 +14,11 @@ #![feature(asm)] #![feature(trace_macros, concat_idents)] -#[derive(Default, //~ ERROR - Zero)] //~ ERROR -enum CantDeriveThose {} +#[derive(Zero)] //~ ERROR +struct CantDeriveThis; + +#[derive(Default)] //~ ERROR +enum OrDeriveThis {} fn main() { doesnt_exist!(); //~ ERROR diff --git a/src/test/compile-fail/no-link.rs b/src/test/compile-fail/no-link.rs index d8e7411bded2c..f74ff55e2c08e 100644 --- a/src/test/compile-fail/no-link.rs +++ b/src/test/compile-fail/no-link.rs @@ -12,7 +12,7 @@ #[no_link] extern crate empty_struct; -//~^ WARN custom derive crates and `#[no_link]` crates have no effect without `#[macro_use]` +//~^ WARN proc macro crates and `#[no_link]` crates have no effect without `#[macro_use]` fn main() { empty_struct::XEmpty1; //~ ERROR cannot find value `XEmpty1` in module `empty_struct` diff --git a/src/test/pretty/attr-derive.rs b/src/test/pretty/attr-derive.rs new file mode 100644 index 0000000000000..a1c581a18682c --- /dev/null +++ b/src/test/pretty/attr-derive.rs @@ -0,0 +1,43 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:derive-foo.rs +// ignore-stage1 +// pp-exact +// Testing that both the inner item and next outer item are +// preserved, and that the first outer item parsed in main is not +// accidentally carried over to each inner function + +#[macro_use] +extern crate derive_foo; + +#[derive(Foo)] +struct X; + +#[derive(Foo)] +#[Bar] +struct Y; + +#[derive(Foo)] +struct WithRef { + x: X, + #[Bar] + y: Y, +} + +#[derive(Foo)] +enum Enum { + + #[Bar] + Asdf, + Qwerty, +} + +fn main() { } diff --git a/src/test/pretty/attr-variant-data.rs b/src/test/pretty/attr-variant-data.rs deleted file mode 100644 index 1ffacaa9f5a5d..0000000000000 --- a/src/test/pretty/attr-variant-data.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// pp-exact -// Testing that both the inner item and next outer item are -// preserved, and that the first outer item parsed in main is not -// accidentally carried over to each inner function - -#![feature(custom_attribute)] -#![feature(custom_derive)] - -#[derive(Serialize, Deserialize)] -struct X; - -#[derive(Serialize, Deserialize)] -struct WithRef<'a, T: 'a> { - #[serde(skip_deserializing)] - t: Option<&'a T>, - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - x: X, -} - -#[derive(Serialize, Deserialize)] -enum EnumWith { - Unit, - Newtype( - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - X), - Tuple(T, - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - X), - Struct { - t: T, - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - x: X, - }, -} - -#[derive(Serialize, Deserialize)] -struct Tuple(T, - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - X); - -fn main() { } diff --git a/src/test/pretty/auxiliary/derive-foo.rs b/src/test/pretty/auxiliary/derive-foo.rs new file mode 100644 index 0000000000000..bd81d3e5a3b53 --- /dev/null +++ b/src/test/pretty/auxiliary/derive-foo.rs @@ -0,0 +1,22 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo, attributes(Bar))] +pub fn derive(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/run-make/atomic-lock-free/atomic_lock_free.rs b/src/test/run-make/atomic-lock-free/atomic_lock_free.rs index 023f2218b87ae..5ac50e04b8d2f 100644 --- a/src/test/run-make/atomic-lock-free/atomic_lock_free.rs +++ b/src/test/run-make/atomic-lock-free/atomic_lock_free.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(cfg_target_has_atomic, no_core, intrinsics, lang_items)] +#![feature(cfg_target_has_atomic, no_core, intrinsics, lang_items, i128_type)] #![crate_type="rlib"] #![no_core] @@ -54,6 +54,14 @@ pub unsafe fn atomic_u64(x: *mut u64) { pub unsafe fn atomic_i64(x: *mut i64) { atomic_xadd(x, 1); } +#[cfg(target_has_atomic = "128")] +pub unsafe fn atomic_u128(x: *mut u128) { + atomic_xadd(x, 1); +} +#[cfg(target_has_atomic = "128")] +pub unsafe fn atomic_i128(x: *mut i128) { + atomic_xadd(x, 1); +} #[cfg(target_has_atomic = "ptr")] pub unsafe fn atomic_usize(x: *mut usize) { atomic_xadd(x, 1); diff --git a/src/test/ui/custom-derive/issue-36935.stderr b/src/test/ui/custom-derive/issue-36935.stderr index 213366a307d40..9a5e2de14e3b0 100644 --- a/src/test/ui/custom-derive/issue-36935.stderr +++ b/src/test/ui/custom-derive/issue-36935.stderr @@ -1,4 +1,4 @@ -error: custom derive attribute panicked +error: proc-macro derive panicked --> $DIR/issue-36935.rs:17:15 | 17 | #[derive(Foo, Bar)] diff --git a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs new file mode 100644 index 0000000000000..1938d33e53030 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use Foo; + +use Foo1; + +fn main() {} diff --git a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr new file mode 100644 index 0000000000000..325f55e686c62 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr @@ -0,0 +1,14 @@ +error[E0432]: unresolved import `Foo` + --> $DIR/issue-38054-do-not-show-unresolved-names.rs:11:5 + | +11 | use Foo; + | ^^^ no `Foo` in the root + +error[E0432]: unresolved import `Foo1` + --> $DIR/issue-38054-do-not-show-unresolved-names.rs:13:5 + | +13 | use Foo1; + | ^^^^ no `Foo1` in the root + +error: aborting due to 2 previous errors +