Auto merge of #81545 - JohnTitor:rollup-zlt3tn6, r=JohnTitor

Rollup of 16 pull requests

Successful merges:

 - #79023 (Add `core::stream::Stream`)
 - #80562 (Consider Scalar to be a bool only if its unsigned)
 - #80886 (Stabilize raw ref macros)
 - #80959 (Stabilize `unsigned_abs`)
 - #81291 (Support FRU pattern with `[feature(capture_disjoint_fields)]`)
 - #81409 (Slight simplification of chars().count())
 - #81468 (cfg(version): treat nightlies as complete)
 - #81473 (Warn write-only fields)
 - #81495 (rustdoc: Remove unnecessary optional)
 - #81499 (Updated Vec::splice documentation)
 - #81501 (update rustfmt to v1.4.34)
 - #81505 (`fn cold_path` doesn't need to be pub)
 - #81512 (Add missing variants in match binding)
 - #81515 (Fix typo in pat.rs)
 - #81519 (Don't print error output from rustup when detecting default build triple)
 - #81520 (Don't clone LLVM submodule when download-ci-llvm is set)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-01-30 10:50:16 +00:00
commit 7ce1b3b244
52 changed files with 598 additions and 95 deletions

View File

@ -4442,7 +4442,7 @@ dependencies = [
[[package]]
name = "rustfmt-nightly"
version = "1.4.32"
version = "1.4.34"
dependencies = [
"annotate-snippets 0.6.1",
"anyhow",

View File

@ -32,7 +32,7 @@ use std::slice;
#[inline(never)]
#[cold]
pub fn cold_path<F: FnOnce() -> R, R>(f: F) -> R {
fn cold_path<F: FnOnce() -> R, R>(f: F) -> R {
f()
}

View File

@ -586,12 +586,14 @@ pub fn eval_condition(
return false;
}
};
let channel = env!("CFG_RELEASE_CHANNEL");
let nightly = channel == "nightly" || channel == "dev";
let rustc_version = parse_version(env!("CFG_RELEASE"), true).unwrap();
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-625474439 for details
if nightly { rustc_version > min_version } else { rustc_version >= min_version }
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
if sess.assume_incomplete_release {
rustc_version > min_version
} else {
rustc_version >= min_version
}
}
ast::MetaItemKind::List(ref mis) => {
for mi in mis.iter() {

View File

@ -540,6 +540,7 @@ fn test_debugging_options_tracking_hash() {
// This list is in alphabetical order.
tracked!(allow_features, Some(vec![String::from("lang_items")]));
tracked!(always_encode_mir, true);
tracked!(assume_incomplete_release, true);
tracked!(asm_comments, true);
tracked!(binary_dep_depinfo, true);
tracked!(chalk, true);

View File

@ -588,12 +588,3 @@ pub fn read_target_uint(endianness: Endian, mut source: &[u8]) -> Result<u128, i
debug_assert!(source.len() == 0); // We should have consumed the source buffer.
uint
}
/// Computes the unsigned absolute value without wrapping or panicking.
#[inline]
pub fn uabs(value: i64) -> u64 {
// The only tricky part here is if value == i64::MIN. In that case,
// wrapping_abs() returns i64::MIN == -2^63. Casting this value to a u64
// gives 2^63, the correct value.
value.wrapping_abs() as u64
}

View File

@ -1,4 +1,4 @@
use super::{uabs, AllocId, InterpResult};
use super::{AllocId, InterpResult};
use rustc_macros::HashStable;
use rustc_target::abi::{HasDataLayout, Size};
@ -57,7 +57,7 @@ pub trait PointerArithmetic: HasDataLayout {
#[inline]
fn overflowing_signed_offset(&self, val: u64, i: i64) -> (u64, bool) {
// We need to make sure that i fits in a machine isize.
let n = uabs(i);
let n = i.unsigned_abs();
if i >= 0 {
let (val, over) = self.overflowing_offset(val, n);
(val, over || i > self.machine_isize_max())

View File

@ -7,7 +7,7 @@ use std::convert::TryFrom;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::{
self,
interpret::{uabs, ConstValue, GlobalId, InterpResult, Scalar},
interpret::{ConstValue, GlobalId, InterpResult, Scalar},
BinOp,
};
use rustc_middle::ty;
@ -542,7 +542,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// memory between these pointers must be accessible. Note that we do not require the
// pointers to be properly aligned (unlike a read/write operation).
let min_ptr = if offset_bytes >= 0 { ptr } else { offset_ptr };
let size: u64 = uabs(offset_bytes);
let size = offset_bytes.unsigned_abs();
// This call handles checking for integer/NULL pointers.
self.memory.check_ptr_access_align(
min_ptr,

View File

@ -303,7 +303,7 @@ impl<'tcx> PlaceBuilder<'tcx> {
self.base
}
fn field(self, f: Field, ty: Ty<'tcx>) -> Self {
crate fn field(self, f: Field, ty: Ty<'tcx>) -> Self {
self.project(PlaceElem::Field(f, ty))
}

View File

@ -296,7 +296,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let field_names = this.hir.all_fields(adt_def, variant_index);
let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base {
let base = unpack!(block = this.as_place(block, base));
let place_builder = unpack!(block = this.as_place_builder(block, base));
// MIR does not natively support FRU, so for each
// base-supplied field, generate an operand that
@ -306,9 +306,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
.zip(field_types.into_iter())
.map(|(n, ty)| match fields_map.get(&n) {
Some(v) => v.clone(),
None => this.consume_by_copy_or_move(
this.hir.tcx().mk_place_field(base, n, ty),
),
None => {
let place_builder = place_builder.clone();
this.consume_by_copy_or_move(
place_builder
.field(n, ty)
.into_place(this.hir.tcx(), this.hir.typeck_results()),
)
},
})
.collect()
} else {

View File

@ -240,7 +240,7 @@ impl<'a> Parser<'a> {
Err(err)
}
/// Parse and throw away a parentesized comma separated
/// Parse and throw away a parenthesized comma separated
/// sequence of patterns until `)` is reached.
fn skip_pat_list(&mut self) -> PResult<'a, ()> {
while !self.check(&token::CloseDelim(token::Paren)) {

View File

@ -37,6 +37,15 @@ fn should_explore(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
)
}
fn base_expr<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
loop {
match expr.kind {
hir::ExprKind::Field(base, ..) => expr = base,
_ => return expr,
}
}
}
struct MarkSymbolVisitor<'tcx> {
worklist: Vec<hir::HirId>,
tcx: TyCtxt<'tcx>,
@ -263,6 +272,12 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
hir::ExprKind::MethodCall(..) => {
self.lookup_and_handle_method(expr.hir_id);
}
hir::ExprKind::Assign(ref left, ref right, ..) => {
// Ignore write to field
self.visit_expr(base_expr(left));
self.visit_expr(right);
return;
}
hir::ExprKind::Field(ref lhs, ..) => {
self.handle_field_access(&lhs, expr.hir_id);
}

View File

@ -977,7 +977,7 @@ impl<'a> Resolver<'a> {
});
if let Some(def_span) = def_span {
if span.overlaps(def_span) {
// Don't suggest typo suggestion for itself like in the followoing:
// Don't suggest typo suggestion for itself like in the following:
// error[E0423]: expected function, tuple struct or tuple variant, found struct `X`
// --> $DIR/issue-64792-bad-unicode-ctor.rs:3:14
// |

View File

@ -854,6 +854,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"only allow the listed language features to be enabled in code (space separated)"),
always_encode_mir: bool = (false, parse_bool, [TRACKED],
"encode MIR of all functions into the crate metadata (default: no)"),
assume_incomplete_release: bool = (false, parse_bool, [TRACKED],
"make cfg(version) treat the current version as incomplete (default: no)"),
asm_comments: bool = (false, parse_bool, [TRACKED],
"generate comments into the assembly (may change behavior) (default: no)"),
ast_json: bool = (false, parse_bool, [UNTRACKED],

View File

@ -138,6 +138,8 @@ pub struct ParseSess {
pub env_depinfo: Lock<FxHashSet<(Symbol, Option<Symbol>)>>,
/// All the type ascriptions expressions that have had a suggestion for likely path typo.
pub type_ascription_path_suggestions: Lock<FxHashSet<Span>>,
/// Whether cfg(version) should treat the current release as incomplete
pub assume_incomplete_release: bool,
}
impl ParseSess {
@ -164,6 +166,7 @@ impl ParseSess {
reached_eof: Lock::new(false),
env_depinfo: Default::default(),
type_ascription_path_suggestions: Default::default(),
assume_incomplete_release: false,
}
}

View File

@ -1344,7 +1344,8 @@ pub fn build_session(
None
};
let parse_sess = ParseSess::with_span_handler(span_diagnostic, source_map);
let mut parse_sess = ParseSess::with_span_handler(span_diagnostic, source_map);
parse_sess.assume_incomplete_release = sopts.debugging_opts.assume_incomplete_release;
let sysroot = match &sopts.maybe_sysroot {
Some(sysroot) => sysroot.clone(),
None => filesearch::get_or_default_sysroot(),

View File

@ -530,7 +530,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
if val < 0 {
neg = true;
}
Some(val.wrapping_abs() as u128)
Some(val.unsigned_abs())
})
}
_ => {

View File

@ -103,7 +103,12 @@ impl ArgAttributes {
}
pub fn ext(&mut self, ext: ArgExtension) -> &mut Self {
assert!(self.arg_ext == ArgExtension::None || self.arg_ext == ext);
assert!(
self.arg_ext == ArgExtension::None || self.arg_ext == ext,
"cannot set {:?} when {:?} is already set",
ext,
self.arg_ext
);
self.arg_ext = ext;
self
}

View File

@ -682,7 +682,7 @@ pub struct Scalar {
impl Scalar {
pub fn is_bool(&self) -> bool {
if let Int(I8, _) = self.value { self.valid_range == (0..=1) } else { false }
matches!(self.value, Int(I8, false)) && self.valid_range == (0..=1)
}
/// Returns the valid range as a `x..y` range.

View File

@ -149,6 +149,7 @@ use core::ops::{
};
use core::pin::Pin;
use core::ptr::{self, Unique};
use core::stream::Stream;
use core::task::{Context, Poll};
use crate::alloc::{handle_alloc_error, AllocError, Allocator, Global, Layout, WriteCloneIntoRaw};
@ -1621,3 +1622,16 @@ where
F::poll(Pin::new(&mut *self), cx)
}
}
#[unstable(feature = "async_stream", issue = "79024")]
impl<S: ?Sized + Stream + Unpin> Stream for Box<S> {
type Item = S::Item;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
Pin::new(&mut **self).poll_next(cx)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(**self).size_hint()
}
}

View File

@ -545,8 +545,8 @@ impl<'a, K, V, Type> NodeRef<marker::ValMut<'a>, K, V, Type> {
// to avoid aliasing with outstanding references to other elements,
// in particular, those returned to the caller in earlier iterations.
let leaf = Self::as_leaf_ptr(&mut self);
let keys = unsafe { &raw const (*leaf).keys };
let vals = unsafe { &raw mut (*leaf).vals };
let keys = unsafe { ptr::addr_of!((*leaf).keys) };
let vals = unsafe { ptr::addr_of_mut!((*leaf).vals) };
// We must coerce to unsized array pointers because of Rust issue #74679.
let keys: *const [_] = keys;
let vals: *mut [_] = vals;

View File

@ -82,6 +82,7 @@
#![feature(array_windows)]
#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(async_stream)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(cfg_sanitize)]
@ -115,7 +116,6 @@
#![feature(pattern)]
#![feature(ptr_internals)]
#![feature(range_bounds_assert_len)]
#![feature(raw_ref_op)]
#![feature(rustc_attrs)]
#![feature(receiver_trait)]
#![cfg_attr(bootstrap, feature(min_const_generics))]

View File

@ -398,7 +398,7 @@ impl<T> Rc<T> {
unsafe {
let inner = init_ptr.as_ptr();
ptr::write(&raw mut (*inner).value, data);
ptr::write(ptr::addr_of_mut!((*inner).value), data);
let prev_value = (*inner).strong.get();
debug_assert_eq!(prev_value, 0, "No prior strong references should exist");
@ -804,7 +804,7 @@ impl<T: ?Sized> Rc<T> {
// SAFETY: This cannot go through Deref::deref or Rc::inner because
// this is required to retain raw/mut provenance such that e.g. `get_mut` can
// write through the pointer after the Rc is recovered through `from_raw`.
unsafe { &raw const (*ptr).value }
unsafe { ptr::addr_of_mut!((*ptr).value) }
}
/// Constructs an `Rc<T>` from a raw pointer.
@ -1917,7 +1917,7 @@ impl<T: ?Sized> Weak<T> {
// SAFETY: if is_dangling returns false, then the pointer is dereferencable.
// The payload may be dropped at this point, and we have to maintain provenance,
// so use raw pointer manipulation.
unsafe { &raw const (*ptr).value }
unsafe { ptr::addr_of_mut!((*ptr).value) }
}
}

View File

@ -384,7 +384,7 @@ impl<T> Arc<T> {
// reference into a strong reference.
unsafe {
let inner = init_ptr.as_ptr();
ptr::write(&raw mut (*inner).data, data);
ptr::write(ptr::addr_of_mut!((*inner).data), data);
// The above write to the data field must be visible to any threads which
// observe a non-zero strong count. Therefore we need at least "Release" ordering
@ -800,7 +800,7 @@ impl<T: ?Sized> Arc<T> {
// SAFETY: This cannot go through Deref::deref or RcBoxPtr::inner because
// this is required to retain raw/mut provenance such that e.g. `get_mut` can
// write through the pointer after the Rc is recovered through `from_raw`.
unsafe { &raw const (*ptr).data }
unsafe { ptr::addr_of_mut!((*ptr).data) }
}
/// Constructs an `Arc<T>` from a raw pointer.
@ -1677,7 +1677,7 @@ impl<T: ?Sized> Weak<T> {
// SAFETY: if is_dangling returns false, then the pointer is dereferencable.
// The payload may be dropped at this point, and we have to maintain provenance,
// so use raw pointer manipulation.
unsafe { &raw mut (*ptr).data }
unsafe { ptr::addr_of_mut!((*ptr).data) }
}
}

View File

@ -2211,7 +2211,7 @@ impl<T, A: Allocator> Vec<T, A> {
/// This is optimal if:
///
/// * The tail (elements in the vector after `range`) is empty,
/// * or `replace_with` yields fewer elements than `range`s length
/// * or `replace_with` yields fewer or equal elements than `range`s length
/// * or the lower bound of its `size_hint()` is exact.
///
/// Otherwise, a temporary vector is allocated and the tail is moved twice.

View File

@ -126,7 +126,6 @@
#![feature(auto_traits)]
#![feature(or_patterns)]
#![feature(prelude_import)]
#![feature(raw_ref_macros)]
#![feature(repr_simd, platform_intrinsics)]
#![feature(rustc_attrs)]
#![feature(simd_ffi)]
@ -254,6 +253,8 @@ pub mod panicking;
pub mod pin;
pub mod raw;
pub mod result;
#[unstable(feature = "async_stream", issue = "79024")]
pub mod stream;
pub mod sync;
pub mod fmt;

View File

@ -332,7 +332,7 @@ fn bound_intermediate_digits(decimal: &Decimal<'_>, e: i64) -> u64 {
// It tries to find a positive number k such that `f << k / 10^e` is an in-range
// significand. This will result in about `2^53 * f * 10^e` < `10^17 * f * 10^e`.
// One input that triggers this is 0.33...33 (375 x 3).
f_len + (e.abs() as u64) + 17
f_len + e.unsigned_abs() + 17
}
}

View File

@ -1158,12 +1158,12 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
/// #![feature(unsigned_abs)]
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".unsigned_abs(), 100", stringify!($UnsignedT), ");")]
#[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").unsigned_abs(), 100", stringify!($UnsignedT), ");")]
/// assert_eq!((-128i8).unsigned_abs(), 128u8);
/// ```
#[unstable(feature = "unsigned_abs", issue = "74913")]
#[stable(feature = "unsigned_abs", since = "1.51.0")]
#[rustc_const_stable(feature = "unsigned_abs", since = "1.51.0")]
#[inline]
pub const fn unsigned_abs(self) -> $UnsignedT {
self.wrapping_abs() as $UnsignedT

View File

@ -1501,7 +1501,6 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L }
/// # Example
///
/// ```
/// #![feature(raw_ref_macros)]
/// use std::ptr;
///
/// #[repr(packed)]
@ -1512,14 +1511,14 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L }
///
/// let packed = Packed { f1: 1, f2: 2 };
/// // `&packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
/// let raw_f2 = ptr::raw_const!(packed.f2);
/// let raw_f2 = ptr::addr_of!(packed.f2);
/// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
/// ```
#[unstable(feature = "raw_ref_macros", issue = "73394")]
#[stable(feature = "raw_ref_macros", since = "1.51.0")]
#[rustc_macro_transparency = "semitransparent"]
#[allow_internal_unstable(raw_ref_op)]
pub macro raw_const($e:expr) {
&raw const $e
pub macro addr_of($place:expr) {
&raw const $place
}
/// Create a `mut` raw pointer to a place, without creating an intermediate reference.
@ -1534,7 +1533,6 @@ pub macro raw_const($e:expr) {
/// # Example
///
/// ```
/// #![feature(raw_ref_macros)]
/// use std::ptr;
///
/// #[repr(packed)]
@ -1545,13 +1543,13 @@ pub macro raw_const($e:expr) {
///
/// let mut packed = Packed { f1: 1, f2: 2 };
/// // `&mut packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
/// let raw_f2 = ptr::raw_mut!(packed.f2);
/// let raw_f2 = ptr::addr_of_mut!(packed.f2);
/// unsafe { raw_f2.write_unaligned(42); }
/// assert_eq!({packed.f2}, 42); // `{...}` forces copying the field instead of creating a reference.
/// ```
#[unstable(feature = "raw_ref_macros", issue = "73394")]
#[stable(feature = "raw_ref_macros", since = "1.51.0")]
#[rustc_macro_transparency = "semitransparent"]
#[allow_internal_unstable(raw_ref_op)]
pub macro raw_mut($e:expr) {
&raw mut $e
pub macro addr_of_mut($place:expr) {
&raw mut $place
}

View File

@ -543,8 +543,8 @@ impl<T> [T] {
#[inline]
pub fn swap(&mut self, a: usize, b: usize) {
// Can't take two mutable loans from one vector, so instead use raw pointers.
let pa = ptr::raw_mut!(self[a]);
let pb = ptr::raw_mut!(self[b]);
let pa = ptr::addr_of_mut!(self[a]);
let pb = ptr::addr_of_mut!(self[b]);
// SAFETY: `pa` and `pb` have been created from safe mutable references and refer
// to elements in the slice and therefore are guaranteed to be valid and aligned.
// Note that accessing the elements behind `a` and `b` is checked and will

View File

@ -47,12 +47,7 @@ impl<'a> Iterator for Chars<'a> {
#[inline]
fn count(self) -> usize {
// length in `char` is equal to the number of non-continuation bytes
let bytes_len = self.iter.len();
let mut cont_bytes = 0;
for &byte in self.iter {
cont_bytes += utf8_is_cont_byte(byte) as usize;
}
bytes_len - cont_bytes
self.iter.filter(|&&byte| !utf8_is_cont_byte(byte)).count()
}
#[inline]

View File

@ -0,0 +1,127 @@
//! Composable asynchronous iteration.
//!
//! If futures are asynchronous values, then streams are asynchronous
//! iterators. If you've found yourself with an asynchronous collection of some kind,
//! and needed to perform an operation on the elements of said collection,
//! you'll quickly run into 'streams'. Streams are heavily used in idiomatic
//! asynchronous Rust code, so it's worth becoming familiar with them.
//!
//! Before explaining more, let's talk about how this module is structured:
//!
//! # Organization
//!
//! This module is largely organized by type:
//!
//! * [Traits] are the core portion: these traits define what kind of streams
//! exist and what you can do with them. The methods of these traits are worth
//! putting some extra study time into.
//! * Functions provide some helpful ways to create some basic streams.
//! * Structs are often the return types of the various methods on this
//! module's traits. You'll usually want to look at the method that creates
//! the `struct`, rather than the `struct` itself. For more detail about why,
//! see '[Implementing Stream](#implementing-stream)'.
//!
//! [Traits]: #traits
//!
//! That's it! Let's dig into streams.
//!
//! # Stream
//!
//! The heart and soul of this module is the [`Stream`] trait. The core of
//! [`Stream`] looks like this:
//!
//! ```
//! # use core::task::{Context, Poll};
//! # use core::pin::Pin;
//! trait Stream {
//! type Item;
//! fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;
//! }
//! ```
//!
//! Unlike `Iterator`, `Stream` makes a distinction between the [`poll_next`]
//! method which is used when implementing a `Stream`, and a (to-be-implemented)
//! `next` method which is used when consuming a stream. Consumers of `Stream`
//! only need to consider `next`, which when called, returns a future which
//! yields `Option<Stream::Item>`.
//!
//! The future returned by `next` will yield `Some(Item)` as long as there are
//! elements, and once they've all been exhausted, will yield `None` to indicate
//! that iteration is finished. If we're waiting on something asynchronous to
//! resolve, the future will wait until the stream is ready to yield again.
//!
//! Individual streams may choose to resume iteration, and so calling `next`
//! again may or may not eventually yield `Some(Item)` again at some point.
//!
//! [`Stream`]'s full definition includes a number of other methods as well,
//! but they are default methods, built on top of [`poll_next`], and so you get
//! them for free.
//!
//! [`Poll`]: super::task::Poll
//! [`poll_next`]: Stream::poll_next
//!
//! # Implementing Stream
//!
//! Creating a stream of your own involves two steps: creating a `struct` to
//! hold the stream's state, and then implementing [`Stream`] for that
//! `struct`.
//!
//! Let's make a stream named `Counter` which counts from `1` to `5`:
//!
//! ```no_run
//! #![feature(async_stream)]
//! # use core::stream::Stream;
//! # use core::task::{Context, Poll};
//! # use core::pin::Pin;
//!
//! // First, the struct:
//!
//! /// A stream which counts from one to five
//! struct Counter {
//! count: usize,
//! }
//!
//! // we want our count to start at one, so let's add a new() method to help.
//! // This isn't strictly necessary, but is convenient. Note that we start
//! // `count` at zero, we'll see why in `poll_next()`'s implementation below.
//! impl Counter {
//! fn new() -> Counter {
//! Counter { count: 0 }
//! }
//! }
//!
//! // Then, we implement `Stream` for our `Counter`:
//!
//! impl Stream for Counter {
//! // we will be counting with usize
//! type Item = usize;
//!
//! // poll_next() is the only required method
//! fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
//! // Increment our count. This is why we started at zero.
//! self.count += 1;
//!
//! // Check to see if we've finished counting or not.
//! if self.count < 6 {
//! Poll::Ready(Some(self.count))
//! } else {
//! Poll::Ready(None)
//! }
//! }
//! }
//! ```
//!
//! # Laziness
//!
//! Streams are *lazy*. This means that just creating a stream doesn't _do_ a
//! whole lot. Nothing really happens until you call `next`. This is sometimes a
//! source of confusion when creating a stream solely for its side effects. The
//! compiler will warn us about this kind of behavior:
//!
//! ```text
//! warning: unused result that must be used: streams do nothing unless polled
//! ```
mod stream;
pub use stream::Stream;

View File

@ -0,0 +1,110 @@
use crate::ops::DerefMut;
use crate::pin::Pin;
use crate::task::{Context, Poll};
/// An interface for dealing with asynchronous iterators.
///
/// This is the main stream trait. For more about the concept of streams
/// generally, please see the [module-level documentation]. In particular, you
/// may want to know how to [implement `Stream`][impl].
///
/// [module-level documentation]: index.html
/// [impl]: index.html#implementing-stream
#[unstable(feature = "async_stream", issue = "79024")]
#[must_use = "streams do nothing unless polled"]
pub trait Stream {
/// The type of items yielded by the stream.
type Item;
/// Attempt to pull out the next value of this stream, registering the
/// current task for wakeup if the value is not yet available, and returning
/// `None` if the stream is exhausted.
///
/// # Return value
///
/// There are several possible return values, each indicating a distinct
/// stream state:
///
/// - `Poll::Pending` means that this stream's next value is not ready
/// yet. Implementations will ensure that the current task will be notified
/// when the next value may be ready.
///
/// - `Poll::Ready(Some(val))` means that the stream has successfully
/// produced a value, `val`, and may produce further values on subsequent
/// `poll_next` calls.
///
/// - `Poll::Ready(None)` means that the stream has terminated, and
/// `poll_next` should not be invoked again.
///
/// # Panics
///
/// Once a stream has finished (returned `Ready(None)` from `poll_next`), calling its
/// `poll_next` method again may panic, block forever, or cause other kinds of
/// problems; the `Stream` trait places no requirements on the effects of
/// such a call. However, as the `poll_next` method is not marked `unsafe`,
/// Rust's usual rules apply: calls must never cause undefined behavior
/// (memory corruption, incorrect use of `unsafe` functions, or the like),
/// regardless of the stream's state.
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;
/// Returns the bounds on the remaining length of the stream.
///
/// Specifically, `size_hint()` returns a tuple where the first element
/// is the lower bound, and the second element is the upper bound.
///
/// The second half of the tuple that is returned is an [`Option`]`<`[`usize`]`>`.
/// A [`None`] here means that either there is no known upper bound, or the
/// upper bound is larger than [`usize`].
///
/// # Implementation notes
///
/// It is not enforced that a stream implementation yields the declared
/// number of elements. A buggy stream may yield less than the lower bound
/// or more than the upper bound of elements.
///
/// `size_hint()` is primarily intended to be used for optimizations such as
/// reserving space for the elements of the stream, but must not be
/// trusted to e.g., omit bounds checks in unsafe code. An incorrect
/// implementation of `size_hint()` should not lead to memory safety
/// violations.
///
/// That said, the implementation should provide a correct estimation,
/// because otherwise it would be a violation of the trait's protocol.
///
/// The default implementation returns `(0, `[`None`]`)` which is correct for any
/// stream.
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
#[unstable(feature = "async_stream", issue = "79024")]
impl<S: ?Sized + Stream + Unpin> Stream for &mut S {
type Item = S::Item;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
S::poll_next(Pin::new(&mut **self), cx)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(**self).size_hint()
}
}
#[unstable(feature = "async_stream", issue = "79024")]
impl<P> Stream for Pin<P>
where
P: DerefMut + Unpin,
P::Target: Stream,
{
type Item = <P::Target as Stream>::Item;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.get_mut().as_mut().poll_next(cx)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(**self).size_hint()
}
}

View File

@ -224,6 +224,7 @@
#![feature(allocator_internals)]
#![feature(allow_internal_unsafe)]
#![feature(allow_internal_unstable)]
#![feature(async_stream)]
#![feature(arbitrary_self_types)]
#![feature(array_error_internals)]
#![feature(asm)]
@ -298,7 +299,6 @@
#![feature(prelude_import)]
#![feature(ptr_internals)]
#![feature(raw)]
#![feature(raw_ref_macros)]
#![feature(ready_macro)]
#![feature(rustc_attrs)]
#![feature(rustc_private)]
@ -450,6 +450,8 @@ pub use core::ptr;
pub use core::raw;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::result;
#[unstable(feature = "async_stream", issue = "79024")]
pub use core::stream;
#[stable(feature = "i128", since = "1.26.0")]
#[allow(deprecated, deprecated_in_future)]
pub use core::u128;

View File

@ -12,6 +12,7 @@ use crate::panicking;
use crate::pin::Pin;
use crate::ptr::{NonNull, Unique};
use crate::rc::Rc;
use crate::stream::Stream;
use crate::sync::atomic;
use crate::sync::{Arc, Mutex, RwLock};
use crate::task::{Context, Poll};
@ -340,6 +341,19 @@ impl<F: Future> Future for AssertUnwindSafe<F> {
}
}
#[unstable(feature = "async_stream", issue = "79024")]
impl<S: Stream> Stream for AssertUnwindSafe<S> {
type Item = S::Item;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<S::Item>> {
unsafe { self.map_unchecked_mut(|x| &mut x.0) }.poll_next(cx)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
/// Invokes a closure, capturing the cause of an unwinding panic if one occurs.
///
/// This function will return `Ok` with the closure's result if the closure

View File

@ -194,7 +194,8 @@ def default_build_triple(verbose):
# being detected as GNU instead of MSVC.
default_encoding = sys.getdefaultencoding()
try:
version = subprocess.check_output(["rustc", "--version", "--verbose"])
version = subprocess.check_output(["rustc", "--version", "--verbose"],
stderr=subprocess.DEVNULL)
version = version.decode(default_encoding)
host = next(x for x in version.split('\n') if x.startswith("host: "))
triple = host.split("host: ")[1]
@ -1085,10 +1086,10 @@ def bootstrap(help_triggered):
else:
build.set_normal_environment()
build.build = args.build or build.build_triple()
build.update_submodules()
# Fetch/build the bootstrap
build.build = args.build or build.build_triple()
build.download_stage0()
sys.stdout.flush()
build.ensure_vendored()

View File

@ -1436,8 +1436,7 @@ impl Type {
Array(..) => PrimitiveType::Array,
RawPointer(..) => PrimitiveType::RawPointer,
QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
// FIXME: remove this wildcard
_ => return None,
Generic(_) | Infer | ImplTrait(_) => return None,
};
cache.and_then(|c| Primitive(t).def_id_full(c))
}

View File

@ -35,6 +35,12 @@ crate enum OutputFormat {
Html,
}
impl Default for OutputFormat {
fn default() -> OutputFormat {
OutputFormat::Html
}
}
impl OutputFormat {
crate fn is_json(&self) -> bool {
matches!(self, OutputFormat::Json)
@ -118,7 +124,7 @@ crate struct Options {
crate enable_per_target_ignores: bool,
/// The path to a rustc-like binary to build tests with. If not set, we
/// default to loading from $sysroot/bin/rustc.
/// default to loading from `$sysroot/bin/rustc`.
crate test_builder: Option<PathBuf>,
// Options that affect the documentation process
@ -142,8 +148,10 @@ crate struct Options {
crate crate_version: Option<String>,
/// Collected options specific to outputting final pages.
crate render_options: RenderOptions,
/// Output format rendering (used only for "show-coverage" option for the moment)
crate output_format: Option<OutputFormat>,
/// The format that we output when rendering.
///
/// Currently used only for the `--show-coverage` option.
crate output_format: OutputFormat,
/// If this option is set to `true`, rustdoc will only run checks and not generate
/// documentation.
crate run_check: bool,
@ -271,7 +279,7 @@ crate struct RenderInfo {
crate deref_trait_did: Option<DefId>,
crate deref_mut_trait_did: Option<DefId>,
crate owned_box_did: Option<DefId>,
crate output_format: Option<OutputFormat>,
crate output_format: OutputFormat,
}
impl Options {
@ -537,28 +545,28 @@ impl Options {
let output_format = match matches.opt_str("output-format") {
Some(s) => match OutputFormat::try_from(s.as_str()) {
Ok(o) => {
if o.is_json()
Ok(out_fmt) => {
if out_fmt.is_json()
&& !(show_coverage || nightly_options::match_is_nightly_build(matches))
{
diag.struct_err("json output format isn't supported for doc generation")
.emit();
return Err(1);
} else if !o.is_json() && show_coverage {
} else if !out_fmt.is_json() && show_coverage {
diag.struct_err(
"html output format isn't supported for the --show-coverage option",
)
.emit();
return Err(1);
}
Some(o)
out_fmt
}
Err(e) => {
diag.struct_err(&e).emit();
return Err(1);
}
},
None => None,
None => OutputFormat::default(),
};
let crate_name = matches.opt_str("crate-name");
let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);

View File

@ -463,7 +463,7 @@ crate fn run_global_ctxt(
mut default_passes: passes::DefaultPassOption,
mut manual_passes: Vec<String>,
render_options: RenderOptions,
output_format: Option<OutputFormat>,
output_format: OutputFormat,
) -> (clean::Crate, RenderInfo, RenderOptions) {
// Certain queries assume that some checks were run elsewhere
// (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425),

View File

@ -578,7 +578,7 @@ fn main_options(options: config::Options) -> MainResult {
let (error_format, edition, debugging_options) = diag_opts;
let diag = core::new_handler(error_format, None, &debugging_options);
match output_format {
None | Some(config::OutputFormat::Html) => sess.time("render_html", || {
config::OutputFormat::Html => sess.time("render_html", || {
run_renderer::<html::render::Context<'_>>(
krate,
render_opts,
@ -588,7 +588,7 @@ fn main_options(options: config::Options) -> MainResult {
tcx,
)
}),
Some(config::OutputFormat::Json) => sess.time("render_json", || {
config::OutputFormat::Json => sess.time("render_json", || {
run_renderer::<json::JsonRenderer<'_>>(
krate,
render_opts,

View File

@ -132,7 +132,7 @@ impl<'a, 'b> CoverageCalculator<'a, 'b> {
fn print_results(&self) {
let output_format = self.ctx.renderinfo.borrow().output_format;
if output_format.map(|o| o.is_json()).unwrap_or_else(|| false) {
if output_format.is_json() {
println!("{}", self.to_json());
return;
}

View File

@ -0,0 +1,13 @@
#![crate_type="lib"]
#[repr(i8)]
pub enum Type {
Type1 = 0,
Type2 = 1
}
// CHECK: define signext i8 @test()
#[no_mangle]
pub extern "C" fn test() -> Type {
Type::Type1
}

View File

@ -1,5 +1,6 @@
// run-pass
// pretty-expanded FIXME #23616
#![allow(dead_code)]
pub fn main() {
struct A {

View File

@ -0,0 +1,38 @@
// run-pass
// aux-build:ver-cfg-rel.rs
// revisions: assume no_assume
// [assume]compile-flags: -Z assume-incomplete-release
#![feature(cfg_version)]
extern crate ver_cfg_rel;
use ver_cfg_rel::ver_cfg_rel;
#[ver_cfg_rel("-2")]
fn foo_2() { }
#[ver_cfg_rel("-1")]
fn foo_1() { }
#[cfg(assume)]
#[ver_cfg_rel("0")]
fn foo() { compile_error!("wrong+0") }
#[cfg(no_assume)]
#[ver_cfg_rel("0")]
fn foo() { }
#[ver_cfg_rel("1")]
fn bar() { compile_error!("wrong+1") }
#[ver_cfg_rel("2")]
fn bar() { compile_error!("wrong+2") }
fn main() {
foo_2();
foo_1();
#[cfg(no_assume)]
foo();
}

View File

@ -0,0 +1,56 @@
// force-host
// no-prefer-dynamic
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::{TokenStream, TokenTree as Tt};
use std::str::FromStr;
// String containing the current version number of the tip, i.e. "1.41.2"
static VERSION_NUMBER: &str = include_str!("../../../../../version");
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Version {
major: i16,
minor: i16,
patch: i16,
}
fn parse_version(s: &str) -> Option<Version> {
let mut digits = s.splitn(3, '.');
let major = digits.next()?.parse().ok()?;
let minor = digits.next()?.parse().ok()?;
let patch = digits.next().unwrap_or("0").trim().parse().ok()?;
Some(Version { major, minor, patch })
}
#[proc_macro_attribute]
/// Emits a #[cfg(version)] relative to the current one, so passing
/// -1 as argument on compiler 1.50 will emit #[cfg(version("1.49.0"))],
/// while 1 will emit #[cfg(version("1.51.0"))]
pub fn ver_cfg_rel(attr: TokenStream, input: TokenStream) -> TokenStream {
let mut v_rel = None;
for a in attr.into_iter() {
match a {
Tt::Literal(l) => {
let mut s = l.to_string();
let s = s.trim_matches('"');
let v: i16 = s.parse().unwrap();
v_rel = Some(v);
break;
},
_ => panic!("{:?}", a),
}
}
let v_rel = v_rel.unwrap();
let mut v = parse_version(VERSION_NUMBER).unwrap();
v.minor += v_rel;
let attr_str = format!("#[cfg(version(\"{}.{}.{}\"))]", v.major, v.minor, v.patch);
let mut res = Vec::<Tt>::new();
res.extend(TokenStream::from_str(&attr_str).unwrap().into_iter());
res.extend(input.into_iter());
res.into_iter().collect()
}

View File

@ -0,0 +1,46 @@
// run-pass
// Test that functional record update/struct update syntax works inside
// a closure when the feature `capture_disjoint_fields` is enabled.
#![feature(capture_disjoint_fields)]
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
//~| NOTE: `#[warn(incomplete_features)]` on by default
//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
#[derive(Clone)]
struct S {
a: String,
b: String,
}
struct T {
a: String,
s: S,
}
fn main() {
let a = String::new();
let b = String::new();
let c = String::new();
let s = S {a, b};
let t = T {
a: c,
s: s.clone()
};
let c = || {
let s2 = S {
a: format!("New s2"),
..s
};
let s3 = S {
a: format!("New s3"),
..t.s
};
println!("{} {}", s2.a, s2.b);
println!("{} {} {}", s3.a, s3.b, t.a);
};
c();
}

View File

@ -0,0 +1,11 @@
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/fru_syntax.rs:6:12
|
LL | #![feature(capture_disjoint_fields)]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
warning: 1 warning emitted

View File

@ -1,11 +1,10 @@
// check-pass
#![feature(const_raw_ptr_deref)]
#![feature(raw_ref_macros)]
use std::ptr;
const fn test_fn(x: *const i32) {
let x2 = unsafe { ptr::raw_const!(*x) };
let x2 = unsafe { ptr::addr_of!(*x) };
}
fn main() {}

View File

@ -9,8 +9,7 @@
core_intrinsics,
const_raw_ptr_comparison,
const_ptr_offset,
const_raw_ptr_deref,
raw_ref_macros
const_raw_ptr_deref
)]
const FOO: &usize = &42;
@ -64,7 +63,7 @@ const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
const _: *const u8 =
//~^ NOTE
unsafe { std::ptr::raw_const!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
//~^ ERROR any use of this value will cause an error
//~| NOTE

View File

@ -6,9 +6,9 @@ LL | unsafe { intrinsics::offset(self, count) }
| |
| inbounds test failed: pointer must be in-bounds at offset $TWO_WORDS, but is outside bounds of alloc2 which has size $WORD
| inside `ptr::const_ptr::<impl *const usize>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
| inside `_` at $DIR/ptr_comparisons.rs:62:34
| inside `_` at $DIR/ptr_comparisons.rs:61:34
|
::: $DIR/ptr_comparisons.rs:62:1
::: $DIR/ptr_comparisons.rs:61:1
|
LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
| -------------------------------------------------------------------
@ -16,17 +16,17 @@ LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
= note: `#[deny(const_err)]` on by default
error: any use of this value will cause an error
--> $DIR/ptr_comparisons.rs:67:35
--> $DIR/ptr_comparisons.rs:66:33
|
LL | / const _: *const u8 =
LL | |
LL | | unsafe { std::ptr::raw_const!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
| |___________________________________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___-
| |
| memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD
LL | | unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
| |_________________________________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___-
| |
| memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD
error: any use of this value will cause an error
--> $DIR/ptr_comparisons.rs:71:27
--> $DIR/ptr_comparisons.rs:70:27
|
LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
| --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@ -34,7 +34,7 @@ LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) +
| "pointer-to-integer cast" needs an rfc before being allowed inside constants
error: any use of this value will cause an error
--> $DIR/ptr_comparisons.rs:76:27
--> $DIR/ptr_comparisons.rs:75:27
|
LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
| --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---

View File

@ -0,0 +1,20 @@
#![deny(dead_code)]
struct S {
f: i32, //~ ERROR: field is never read
sub: Sub, //~ ERROR: field is never read
}
struct Sub {
f: i32, //~ ERROR: field is never read
}
fn field_write(s: &mut S) {
s.f = 1;
s.sub.f = 2;
}
fn main() {
let mut s = S { f: 0, sub: Sub { f: 0 } };
field_write(&mut s);
}

View File

@ -0,0 +1,26 @@
error: field is never read: `f`
--> $DIR/write-only-field.rs:4:5
|
LL | f: i32,
| ^^^^^^
|
note: the lint level is defined here
--> $DIR/write-only-field.rs:1:9
|
LL | #![deny(dead_code)]
| ^^^^^^^^^
error: field is never read: `sub`
--> $DIR/write-only-field.rs:5:5
|
LL | sub: Sub,
| ^^^^^^^^
error: field is never read: `f`
--> $DIR/write-only-field.rs:9:5
|
LL | f: i32,
| ^^^^^^
error: aborting due to 3 previous errors

@ -1 +1 @@
Subproject commit 216a64300563351cad20bb3847110c14561687e0
Subproject commit ea268b9f559fbafcfc24f4982173b01dfad9e443