mirror of
https://github.com/rust-lang/rust
synced 2024-10-15 04:53:58 +00:00
Auto merge of #39563 - frewsxcv:rollup, r=frewsxcv
Rollup of 19 pull requests - Successful merges: #38518, #38921, #38959, #38983, #39009, #39107, #39193, #39289, #39312, #39393, #39442, #39443, #39453, #39454, #39471, #39477, #39478, #39527, #39552 - Failed merges:
This commit is contained in:
commit
9c8cdb2923
|
@ -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)]
|
||||
|
|
|
@ -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'):
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -1088,7 +1088,7 @@ fn is_empty(&self) -> bool {
|
|||
#[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<T: Ord> From<Vec<T>> for BinaryHeap<T> {
|
||||
fn from(vec: Vec<T>) -> BinaryHeap<T> {
|
||||
let mut heap = BinaryHeap { data: vec };
|
||||
|
@ -1097,7 +1097,7 @@ fn from(vec: Vec<T>) -> BinaryHeap<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
|
||||
impl<T> From<BinaryHeap<T>> for Vec<T> {
|
||||
fn from(heap: BinaryHeap<T>) -> Vec<T> {
|
||||
heap.data
|
||||
|
|
|
@ -588,7 +588,7 @@ fn len(&self) -> usize {
|
|||
#[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 @@ fn len(&self) -> usize {
|
|||
#[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)
|
||||
|
|
|
@ -225,7 +225,7 @@ pub trait TryFrom<T>: Sized {
|
|||
type Err;
|
||||
|
||||
/// Performs the conversion.
|
||||
fn try_from(T) -> Result<Self, Self::Err>;
|
||||
fn try_from(value: T) -> Result<Self, Self::Err>;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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 @@ fn $method(self) -> <$t as $imp>::Output {
|
|||
// 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 @@ fn $method(self, other: $u) -> <$t as $imp<$u>>::Output {
|
|||
}
|
||||
}
|
||||
|
||||
#[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 @@ fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[$attr]
|
||||
impl<'a, 'b> $imp<&'a $u> for &'b $t {
|
||||
type Output = <$t as $imp<$u>>::Output;
|
||||
|
||||
|
|
|
@ -1086,7 +1086,7 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
|
|||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<I::Item> {
|
||||
for x in self.iter.by_ref() {
|
||||
for x in &mut self.iter {
|
||||
if (self.predicate)(&x) {
|
||||
return Some(x);
|
||||
}
|
||||
|
@ -1099,6 +1099,26 @@ fn size_hint(&self) -> (usize, Option<usize>) {
|
|||
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")]
|
||||
|
|
|
@ -661,29 +661,29 @@ pub trait Product<A = Self>: 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<I: Iterator<Item=$a>>(iter: I) -> $a {
|
||||
iter.fold($zero, Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||
#[$attr]
|
||||
impl Product for $a {
|
||||
fn product<I: Iterator<Item=$a>>(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<I: Iterator<Item=&'a $a>>(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<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
|
||||
iter.fold($one, Mul::mul)
|
||||
|
@ -691,8 +691,12 @@ fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
|
|||
}
|
||||
)*);
|
||||
($($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>)+);
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
)
|
||||
}
|
||||
|
|
|
@ -131,7 +131,8 @@ fn add(self, other: Wrapping<$t>) -> Wrapping<$t> {
|
|||
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 @@ fn sub(self, other: Wrapping<$t>) -> Wrapping<$t> {
|
|||
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 @@ fn mul(self, other: Wrapping<$t>) -> Wrapping<$t> {
|
|||
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 @@ fn div(self, other: Wrapping<$t>) -> Wrapping<$t> {
|
|||
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 @@ fn rem(self, other: Wrapping<$t>) -> Wrapping<$t> {
|
|||
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 @@ fn not(self) -> Wrapping<$t> {
|
|||
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 @@ fn bitxor(self, other: Wrapping<$t>) -> Wrapping<$t> {
|
|||
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 @@ fn bitor(self, other: Wrapping<$t>) -> Wrapping<$t> {
|
|||
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 @@ fn bitand(self, other: Wrapping<$t>) -> Wrapping<$t> {
|
|||
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 @@ fn neg(self) -> Self {
|
|||
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")] }
|
||||
)*)
|
||||
}
|
||||
|
||||
|
|
|
@ -632,6 +632,76 @@ pub fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// 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<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
|
||||
match *self {
|
||||
None => *self = Some(f()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
match *self {
|
||||
Some(ref mut v) => v,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Misc
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -616,7 +616,7 @@ pub trait SliceIndex<T> {
|
|||
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<T> SliceIndex<T> for usize {
|
||||
type Output = T;
|
||||
|
||||
|
@ -665,7 +665,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut T {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
|
||||
impl<T> SliceIndex<T> for ops::Range<usize> {
|
||||
type Output = [T];
|
||||
|
||||
|
@ -726,7 +726,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
|
||||
impl<T> SliceIndex<T> for ops::RangeTo<usize> {
|
||||
type Output = [T];
|
||||
|
||||
|
@ -761,7 +761,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
|
||||
impl<T> SliceIndex<T> for ops::RangeFrom<usize> {
|
||||
type Output = [T];
|
||||
|
||||
|
@ -796,7 +796,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
|
||||
impl<T> SliceIndex<T> for ops::RangeFull {
|
||||
type Output = [T];
|
||||
|
||||
|
@ -832,7 +832,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
|
|||
}
|
||||
|
||||
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
|
||||
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
|
||||
impl<T> SliceIndex<T> for ops::RangeInclusive<usize> {
|
||||
type Output = [T];
|
||||
|
||||
|
@ -895,7 +895,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
|
||||
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
|
||||
impl<T> SliceIndex<T> for ops::RangeToInclusive<usize> {
|
||||
type Output = [T];
|
||||
|
||||
|
|
|
@ -1318,6 +1318,24 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
|
|||
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"),
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 7d57bdcdbb56540f37afe5a934ce12d33a6ca7fc
|
||||
Subproject commit cb7f66732175e6171587ed69656b7aae7dd2e6ec
|
|
@ -192,6 +192,13 @@
|
|||
"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 @@ fn get_lints(&self) -> LintArray {
|
|||
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,
|
||||
|
|
|
@ -1199,7 +1199,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResul
|
|||
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) {
|
||||
|
|
|
@ -163,7 +163,7 @@ pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Opti
|
|||
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 @@ pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Opti
|
|||
}
|
||||
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, _) => {
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
use std::rc::Rc;
|
||||
use syntax::abi::Abi;
|
||||
use hir;
|
||||
use lint;
|
||||
use util::nodemap::FxHashMap;
|
||||
|
||||
struct InferredObligationsSnapshotVecDelegate<'tcx> {
|
||||
|
@ -407,19 +408,62 @@ pub fn select(&mut self, obligation: &TraitObligation<'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 @@ fn sized_conditions(&mut self, obligation: &TraitObligation<'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 @@ fn sized_conditions(&mut self, obligation: &TraitObligation<'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 @@ fn copy_conditions(&mut self, obligation: &TraitObligation<'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 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'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()
|
||||
}
|
||||
|
|
|
@ -489,7 +489,7 @@ pub fn closure_trait_ref_and_return_type(self,
|
|||
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,
|
||||
|
|
|
@ -201,7 +201,7 @@ fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|ty| tc_ty(tcx, &ty, cache))
|
||||
}
|
||||
|
||||
ty::TyTuple(ref tys) => {
|
||||
ty::TyTuple(ref tys, _) => {
|
||||
TypeContents::union(&tys[..],
|
||||
|ty| tc_ty(tcx, *ty, cache))
|
||||
}
|
||||
|
|
|
@ -1384,23 +1384,24 @@ pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'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<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output {
|
||||
iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts))))
|
||||
pub fn mk_tup<I: InternAs<[Ty<'tcx>], 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
|
|||
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 @@ pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
|
|||
|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(),
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -151,7 +151,7 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
|
|||
self.add_ty(m.ty);
|
||||
}
|
||||
|
||||
&ty::TyTuple(ref ts) => {
|
||||
&ty::TyTuple(ref ts, _) => {
|
||||
self.add_tys(&ts[..]);
|
||||
}
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ fn uninhabited_from_inner(
|
|||
},
|
||||
|
||||
TyNever => DefIdForest::full(tcx),
|
||||
TyTuple(ref tys) => {
|
||||
TyTuple(ref tys, _) => {
|
||||
DefIdForest::union(tcx, tys.iter().map(|ty| {
|
||||
ty.uninhabited_from(visited, tcx)
|
||||
}))
|
||||
|
|
|
@ -319,9 +319,9 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
|
|||
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),
|
||||
|
|
|
@ -791,7 +791,7 @@ fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
|||
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 @@ pub fn compute_uncached(ty: Ty<'gcx>,
|
|||
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,
|
||||
|
|
|
@ -197,6 +197,17 @@ pub fn def(&self) -> Def {
|
|||
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 @@ fn calculate_sized_constraint_inner(&self,
|
|||
_ 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 @@ fn sized_constraint_for_ty(&self,
|
|||
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 @@ fn sized_constraint_for_ty(&self,
|
|||
.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 @@ pub fn trait_impl_polarity(self, id: DefId) -> hir::ImplPolarity {
|
|||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
|
@ -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())))
|
||||
|
|
|
@ -474,7 +474,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
|
|||
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 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
|||
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)
|
||||
}
|
||||
|
|
|
@ -151,7 +151,11 @@ pub enum TypeVariants<'tcx> {
|
|||
TyNever,
|
||||
|
||||
/// A tuple type. For example, `(i32, bool)`.
|
||||
TyTuple(&'tcx Slice<Ty<'tcx>>),
|
||||
/// 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<Ty<'tcx>>, bool),
|
||||
|
||||
/// The projection of an associated type. For example,
|
||||
/// `<T as Trait<..>>::N`.
|
||||
|
@ -961,7 +965,7 @@ pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
|
|||
|
||||
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 @@ pub fn is_never(&self) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
// 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 @@ pub fn regions(&self) -> Vec<&'tcx ty::Region> {
|
|||
TySlice(_) |
|
||||
TyRawPtr(_) |
|
||||
TyNever |
|
||||
TyTuple(_) |
|
||||
TyTuple(..) |
|
||||
TyParam(_) |
|
||||
TyInfer(_) |
|
||||
TyError => {
|
||||
|
|
|
@ -207,7 +207,7 @@ pub fn positional_element_ty(self,
|
|||
// 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 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
|||
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 @@ fn are_inner_types_recursive<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span,
|
|||
seen: &mut Vec<Ty<'tcx>>, ty: Ty<'tcx>)
|
||||
-> Representability {
|
||||
match ty.sty {
|
||||
TyTuple(ref ts) => {
|
||||
TyTuple(ref ts, _) => {
|
||||
find_nonrepresentable(tcx, sp, seen, ts.iter().cloned())
|
||||
}
|
||||
// Fixed-length vectors.
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -315,7 +315,7 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
|
|||
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);
|
||||
|
|
|
@ -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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|||
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() {
|
||||
|
|
|
@ -22,6 +22,7 @@ pub fn target() -> Result<Target, String> {
|
|||
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()),
|
||||
|
|
|
@ -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 @@ fn default() -> 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 @@ macro_rules! key {
|
|||
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 @@ macro_rules! target_option_val {
|
|||
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);
|
||||
|
|
|
@ -24,6 +24,7 @@ pub fn target() -> Result<Target, String> {
|
|||
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()],
|
||||
|
|
|
@ -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(_) =>
|
||||
|
|
|
@ -713,7 +713,7 @@ fn open_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>) -> BasicBlock {
|
|||
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() => {
|
||||
|
|
|
@ -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![],
|
||||
|
|
|
@ -342,7 +342,7 @@ pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'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)
|
||||
|
|
|
@ -280,7 +280,7 @@ pub fn t_nil(&self) -> Ty<'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.
|
||||
|
|
|
@ -219,6 +219,10 @@ macro_rules! add_lint_group {
|
|||
id: LintId::of(LIFETIME_UNDERSCORE),
|
||||
reference: "issue #36892 <https://github.com/rust-lang/rust/issues/36892>",
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(RESOLVE_TRAIT_ON_DEFAULTED_UNIT),
|
||||
reference: "issue #39216 <https://github.com/rust-lang/rust/issues/39216>",
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(SAFE_EXTERN_STATICS),
|
||||
reference: "issue #36247 <https://github.com/rust-lang/rust/issues/35112>",
|
||||
|
|
|
@ -532,7 +532,7 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet<Ty<'tcx>>, ty: Ty<'tcx>) -> F
|
|||
consider using a `*const libc::c_char`")
|
||||
}
|
||||
|
||||
ty::TyTuple(_) => {
|
||||
ty::TyTuple(..) => {
|
||||
FfiUnsafe("found Rust tuple type in foreign module; \
|
||||
consider using a struct instead")
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
|
|||
|
||||
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, _) => {
|
||||
|
|
|
@ -584,7 +584,7 @@ fn load_derive_macros(&mut self, root: &CrateRoot, dylib: Option<PathBuf>, span:
|
|||
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 @@ fn register_custom_derive(&mut self,
|
|||
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)));
|
||||
}
|
||||
|
|
|
@ -257,7 +257,7 @@ pub fn build_binary_op(&mut self, mut block: BasicBlock,
|
|||
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,
|
||||
|
|
|
@ -282,7 +282,7 @@ fn field_ty(&mut self,
|
|||
})
|
||||
}
|
||||
}
|
||||
ty::TyTuple(tys) => {
|
||||
ty::TyTuple(tys, _) => {
|
||||
return match tys.get(field.index()) {
|
||||
Some(&ty) => Ok(ty),
|
||||
None => Err(FieldAccessError::OutOfRange {
|
||||
|
|
|
@ -559,7 +559,7 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expa
|
|||
"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
|
||||
|
|
|
@ -250,6 +250,32 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
|
|||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn resolve_builtin_macro(&mut self, tname: Name) -> Result<Rc<SyntaxExtension>, 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<Rc<SyntaxExtension>, 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> {
|
||||
|
|
|
@ -639,7 +639,19 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<Stri
|
|||
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),
|
||||
}
|
||||
|
|
|
@ -1440,7 +1440,7 @@ fn visit_expr(&mut self, ex: &'l ast::Expr) {
|
|||
}.lower(self.tcx));
|
||||
}
|
||||
}
|
||||
ty::TyTuple(_) => {}
|
||||
ty::TyTuple(..) => {}
|
||||
_ => span_bug!(ex.span,
|
||||
"Expected struct or tuple type, found {:?}",
|
||||
ty),
|
||||
|
|
|
@ -430,6 +430,9 @@ pub fn get_trait_ref_data(&self,
|
|||
-> Option<TypeRefData> {
|
||||
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 {
|
||||
|
|
|
@ -367,7 +367,7 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
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[..]
|
||||
}
|
||||
|
|
|
@ -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::<Vec<_>>()
|
||||
},
|
||||
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()
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
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,
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -295,7 +295,7 @@ fn get_function_signature<'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 @@ fn get_function_signature<'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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -442,7 +442,7 @@ fn iter_variant_fields<'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));
|
||||
|
|
|
@ -695,7 +695,7 @@ fn trans_arguments_untupled(&mut self,
|
|||
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)
|
||||
};
|
||||
|
|
|
@ -735,7 +735,7 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'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());
|
||||
|
||||
|
|
|
@ -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?!")
|
||||
};
|
||||
|
||||
|
|
|
@ -402,7 +402,7 @@ pub fn trans_rvalue_operand(&mut self,
|
|||
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
|
||||
|
|
|
@ -409,7 +409,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
|
|||
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);
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -421,7 +421,7 @@ fn convert_parenthesized_parameters(&self,
|
|||
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 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
|
|||
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);
|
||||
|
|
|
@ -164,7 +164,7 @@ pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>, is_arg: boo
|
|||
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 @@ pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>, is_arg: boo
|
|||
// 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]);
|
||||
|
|
|
@ -89,7 +89,7 @@ fn check_closure(&self,
|
|||
// 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 @@ fn deduce_sig_from_projection(&self,
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -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)?
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
|
|||
"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 @@ fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
|
|||
|
||||
"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()));
|
||||
|
|
|
@ -1947,7 +1947,9 @@ fn check_casts(&self) {
|
|||
}
|
||||
|
||||
/// 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 @@ fn check_method_argument_types(&self,
|
|||
|
||||
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 @@ fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize,
|
|||
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 @@ fn check_tup_field(&self,
|
|||
}
|
||||
})
|
||||
}
|
||||
ty::TyTuple(ref v) => {
|
||||
ty::TyTuple(ref v, _) => {
|
||||
tuple_like = true;
|
||||
v.get(idx.node).cloned()
|
||||
}
|
||||
|
@ -3864,7 +3866,7 @@ fn check_expr_kind(&self,
|
|||
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 @@ fn check_expr_kind(&self,
|
|||
};
|
||||
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 @@ fn check_expr_kind(&self,
|
|||
},
|
||||
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:
|
||||
|
|
|
@ -338,7 +338,7 @@ fn add_constraints_from_ty(&mut self,
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -655,7 +655,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, 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<DefId>, 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 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
|
|||
// 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 @@ fn clean(&self, cx: &DocContext) -> Type {
|
|||
Never
|
||||
}
|
||||
}
|
||||
ty::TyTuple(ref t) => Tuple(t.clean(cx)),
|
||||
ty::TyTuple(ref t, _) => Tuple(t.clean(cx)),
|
||||
|
||||
ty::TyProjection(ref data) => data.clean(cx),
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 { .. }")
|
||||
|
|
|
@ -1283,7 +1283,7 @@ fn clone(&self) -> 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 @@ fn clone(&self) -> 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 @@ fn clone(&self) -> 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 @@ fn len(&self) -> usize {
|
|||
#[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 @@ fn len(&self) -> usize {
|
|||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<K, V> FusedIterator for IntoIter<K, V> {}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
#[stable(feature = "std_debug", since = "1.16.0")]
|
||||
impl<K: Debug, V: Debug> fmt::Debug for IntoIter<K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
|
@ -1704,7 +1704,7 @@ fn len(&self) -> usize {
|
|||
#[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 @@ fn len(&self) -> usize {
|
|||
#[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 @@ fn default() -> 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 { .. }")
|
||||
|
|
|
@ -948,7 +948,7 @@ fn len(&self) -> usize {
|
|||
#[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 @@ fn len(&self) -> usize {
|
|||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<K> FusedIterator for IntoIter<K> {}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
#[stable(feature = "std_debug", since = "1.16.0")]
|
||||
impl<K: fmt::Debug> fmt::Debug for IntoIter<K> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let entries_iter = self.iter.inner.iter().map(|(k, _)| k);
|
||||
|
@ -1007,7 +1007,7 @@ fn len(&self) -> usize {
|
|||
#[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 @@ fn size_hint(&self) -> (usize, Option<usize>) {
|
|||
}
|
||||
}
|
||||
|
||||
#[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,
|
||||
|
|
|
@ -145,7 +145,7 @@ fn next(&mut self) -> Option<(String, String)> {
|
|||
fn size_hint(&self) -> (usize, Option<usize>) { 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 @@ fn next(&mut self) -> Option<(OsString, OsString)> { self.inner.next() }
|
|||
fn size_hint(&self) -> (usize, Option<usize>) { 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 @@ fn next(&mut self) -> Option<PathBuf> { self.inner.next() }
|
|||
fn size_hint(&self) -> (usize, Option<usize>) { 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 @@ fn next_back(&mut self) -> Option<String> {
|
|||
}
|
||||
}
|
||||
|
||||
#[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<OsString> { 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 { .. }")
|
||||
|
|
|
@ -869,7 +869,7 @@ pub fn created(&self) -> io::Result<SystemTime> {
|
|||
}
|
||||
}
|
||||
|
||||
#[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")
|
||||
|
|
|
@ -1450,7 +1450,7 @@ pub struct Chain<T, U> {
|
|||
done_first: bool,
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
#[stable(feature = "std_debug", since = "1.16.0")]
|
||||
impl<T: fmt::Debug, U: fmt::Debug> fmt::Debug for Chain<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Chain")
|
||||
|
|
|
@ -282,7 +282,7 @@ pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
|
|||
}
|
||||
}
|
||||
|
||||
#[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 @@ fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
|
|||
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 @@ pub fn lock(&self) -> StdoutLock {
|
|||
}
|
||||
}
|
||||
|
||||
#[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 @@ fn flush(&mut self) -> io::Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
#[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 @@ pub fn lock(&self) -> StderrLock {
|
|||
}
|
||||
}
|
||||
|
||||
#[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 @@ fn flush(&mut self) -> io::Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
#[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 { .. }")
|
||||
|
|
|
@ -98,7 +98,7 @@ fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) }
|
|||
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 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|||
}
|
||||
}
|
||||
|
||||
#[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 @@ fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) }
|
|||
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 { .. }")
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -106,7 +106,10 @@ impl Iterator for LookupHost {
|
|||
fn next(&mut self) -> Option<SocketAddr> { 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 { .. }")
|
||||
|
|
|
@ -296,6 +296,29 @@ pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
|
|||
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<usize> {
|
||||
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 @@ fn set_nonblocking() {
|
|||
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(()));
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,6 +83,30 @@ pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
|||
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 @@ pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
|
|||
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<usize> {
|
||||
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 @@ fn connect_send_recv() {
|
|||
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;
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -297,7 +297,7 @@ extern "rust-call" fn call_once(self, _args: ()) -> R {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.15.0")]
|
||||
#[stable(feature = "std_debug", since = "1.16.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("AssertUnwindSafe")
|
||||
|
|
|
@ -114,7 +114,7 @@ impl IntoInner<imp::Process> 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 @@ fn from_inner(pipe: AnonPipe) -> 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 @@ fn from_inner(pipe: AnonPipe) -> 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 @@ fn from_inner(pipe: AnonPipe) -> 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 @@ fn from_inner(inner: imp::Stdio) -> 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 @@ pub fn wait_with_output(mut self) -> io::Result<Output> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::process;
|
||||
/// 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:
|
||||
///
|
||||
/// process::exit(0);
|
||||
/// ```
|
||||
/// use std::io::{self, Write};
|
||||
///
|
||||
/// fn run_app() -> Result<(), ()> {
|
||||
/// // Application logic here
|
||||
/// Ok(())
|
||||
/// }
|
||||
///
|
||||
/// 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
|
||||
|
|
|
@ -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 @@ pub fn wait(&self) -> BarrierWaitResult {
|
|||
}
|
||||
}
|
||||
|
||||
#[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")
|
||||
|
|
|
@ -240,7 +240,7 @@ fn verify(&self, mutex: &sys_mutex::Mutex) {
|
|||
}
|
||||
}
|
||||
|
||||
#[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 { .. }")
|
||||
|
|
|
@ -428,7 +428,7 @@ fn drop(&mut self) {
|
|||
}
|
||||
}
|
||||
|
||||
#[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")
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue