From 85394252e6079e8c094fedb8347358b39a5bb5d4 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Tue, 12 Jan 2021 20:07:34 -0500 Subject: [PATCH 01/26] Stabilize unsigned_abs --- library/core/src/num/int_macros.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 162ed7d1b8dfe..c2e941c691069 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -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 From edf2e3725e8d95b52784990a0c05978db5646bfb Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Tue, 12 Jan 2021 20:12:08 -0500 Subject: [PATCH 02/26] Use unsigned_abs throughout repository --- compiler/rustc_middle/src/mir/interpret/mod.rs | 9 --------- compiler/rustc_middle/src/mir/interpret/pointer.rs | 4 ++-- compiler/rustc_mir/src/interpret/intrinsics.rs | 4 ++-- compiler/rustc_symbol_mangling/src/v0.rs | 2 +- library/core/src/num/dec2flt/mod.rs | 2 +- 5 files changed, 6 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 80b58642136ee..55fe5f971e718 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -588,12 +588,3 @@ pub fn read_target_uint(endianness: Endian, mut source: &[u8]) -> Result 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 -} diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index e3d5a085613aa..8774b48fb3e40 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -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()) diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index 58858c09f44ef..f4309c9cd9572 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -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, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 7b6e6ad0696a1..3355df7787791 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -531,7 +531,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { if val < 0 { neg = true; } - Some(val.wrapping_abs() as u128) + Some(val.unsigned_abs()) }) } _ => { diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs index 039112e9f3468..f145b47770a57 100644 --- a/library/core/src/num/dec2flt/mod.rs +++ b/library/core/src/num/dec2flt/mod.rs @@ -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 } } From 0c8db16a67d02127cb6b4a1f399db054517f6aee Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Fri, 13 Nov 2020 18:24:26 +0100 Subject: [PATCH 03/26] Add `core::stream::Stream` This patch adds the `core::stream` submodule and implements `core::stream::Stream` in accordance with RFC2996. Add feedback from @camelid --- library/alloc/src/boxed.rs | 14 +++ library/alloc/src/lib.rs | 1 + library/core/src/lib.rs | 2 + library/core/src/stream/mod.rs | 154 +++++++++++++++++++++++++ library/core/src/stream/stream/mod.rs | 129 +++++++++++++++++++++ library/core/src/stream/stream/next.rs | 30 +++++ library/std/src/lib.rs | 3 + library/std/src/panic.rs | 14 +++ 8 files changed, 347 insertions(+) create mode 100644 library/core/src/stream/mod.rs create mode 100644 library/core/src/stream/stream/mod.rs create mode 100644 library/core/src/stream/stream/next.rs diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 0aa52b35ced45..e586ff8990215 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -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}; @@ -1618,3 +1619,16 @@ where F::poll(Pin::new(&mut *self), cx) } } + +#[unstable(feature = "async_stream", issue = "79024")] +impl Stream for Box { + type Item = S::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut **self).poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 8d721ed7487ae..e524eb05fcdd7 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -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)] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 263c6c9cf0f26..a4395ab57e8a1 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -254,6 +254,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; diff --git a/library/core/src/stream/mod.rs b/library/core/src/stream/mod.rs new file mode 100644 index 0000000000000..48cca4972929a --- /dev/null +++ b/library/core/src/stream/mod.rs @@ -0,0 +1,154 @@ +//! 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 +//! [Structs]: #structs +//! +//! 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>; +//! } +//! ``` +//! +//! Unlike `Iterator`, `Stream` makes a distinction between the [`poll_next`] +//! method which is used when implementing a `Stream`, and the [`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 +//! yields [`Option`][``]. +//! +//! 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 +//! [`next`]: Stream::next +//! [``]: Stream::Item +//! +//! # 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> { +//! // 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) +//! } +//! } +//! } +//! +//! // And now we can use it! +//! # async fn run() { +//! # +//! let mut counter = Counter::new(); +//! +//! let x = counter.next().await.unwrap(); +//! println!("{}", x); +//! +//! let x = counter.next().await.unwrap(); +//! println!("{}", x); +//! +//! let x = counter.next().await.unwrap(); +//! println!("{}", x); +//! +//! let x = counter.next().await.unwrap(); +//! println!("{}", x); +//! +//! let x = counter.next().await.unwrap(); +//! println!("{}", x); +//! # +//! } +//! ``` +//! +//! This will print `1` through `5`, each on their own line. +//! +//! # 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::{Next, Stream}; diff --git a/library/core/src/stream/stream/mod.rs b/library/core/src/stream/stream/mod.rs new file mode 100644 index 0000000000000..3f92c2e8c1c02 --- /dev/null +++ b/library/core/src/stream/stream/mod.rs @@ -0,0 +1,129 @@ +mod next; + +pub use next::Next; + +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>; + + /// 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) { + (0, None) + } + + /// Advances the stream and returns a future which yields the next value. + /// + /// The returned future yields [`None`] when iteration is finished. + /// Individual stream implementations may choose to resume iteration, and so + /// calling `next()` again may or may not eventually start yielding + /// [`Some(Item)`] again at some point. + /// + /// [`Some(Item)`]: Some + fn next(&mut self) -> Next<'_, Self> + where + Self: Unpin, + { + Next::new(self) + } +} + +#[unstable(feature = "async_stream", issue = "79024")] +impl Stream for &mut S { + type Item = S::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + S::poll_next(Pin::new(&mut **self), cx) + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} + +#[unstable(feature = "async_stream", issue = "79024")] +impl

Stream for Pin

+where + P: DerefMut + Unpin, + P::Target: Stream, +{ + type Item = ::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.get_mut().as_mut().poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} diff --git a/library/core/src/stream/stream/next.rs b/library/core/src/stream/stream/next.rs new file mode 100644 index 0000000000000..e25d44228e781 --- /dev/null +++ b/library/core/src/stream/stream/next.rs @@ -0,0 +1,30 @@ +use crate::future::Future; +use crate::pin::Pin; +use crate::stream::Stream; +use crate::task::{Context, Poll}; + +/// A future which advances the stream and returns the next value. +/// +/// This `struct` is created by [`Stream::next`]. See its documentation for more. +#[unstable(feature = "async_stream", issue = "79024")] +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Next<'a, S: ?Sized> { + stream: &'a mut S, +} + +impl<'a, S: ?Sized> Next<'a, S> { + /// Create a new instance of `Next`. + pub(crate) fn new(stream: &'a mut S) -> Self { + Self { stream } + } +} + +#[unstable(feature = "async_stream", issue = "79024")] +impl Future for Next<'_, S> { + type Output = Option; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Pin::new(&mut *self.stream).poll_next(cx) + } +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 5ba13c2f91334..f739fffd1c04c 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -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)] @@ -448,6 +449,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; diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index d18b94b6c1aef..66e363bf67b8b 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -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 Future for AssertUnwindSafe { } } +#[unstable(feature = "async_stream", issue = "79024")] +impl Stream for AssertUnwindSafe { + type Item = S::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unsafe { self.map_unchecked_mut(|x| &mut x.0) }.poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + 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 From e94cf57c3eb9dd54b14dcd40419a2f35cd83db57 Mon Sep 17 00:00:00 2001 From: Dhruv Jauhar Date: Fri, 22 Jan 2021 21:24:54 -0500 Subject: [PATCH 04/26] Make functional record update/struct update syntax works inside closures when feature capture_disjoint_fields is enabled --- .../src/build/expr/as_place.rs | 2 +- .../rustc_mir_build/src/build/expr/into.rs | 13 +++++--- .../run_pass/fru_syntax.rs | 30 +++++++++++++++++++ .../run_pass/fru_syntax.stderr | 11 +++++++ 4 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index cf2e4e8916d0a..3e8d4631464f0 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -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)) } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 09281799041ee..0f9d0db750cf8 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -302,7 +302,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 @@ -312,9 +312,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 { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs new file mode 100644 index 0000000000000..426eddec6ff8f --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs @@ -0,0 +1,30 @@ +// 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 + +struct S { + a: String, + b: String, +} + +fn main() { + let a = String::new(); + let b = String::new(); + let s = S {a, b}; + + let c = || { + let s2 = S { + a: format!("New a"), + ..s + }; + println!("{} {}", s2.a, s2.b); + }; + + c(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr new file mode 100644 index 0000000000000..7ed73abba8608 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr @@ -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 for more information + +warning: 1 warning emitted + From a1b11321fb2d6ce00af9c8957c98df76432b1b78 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Fri, 15 Jan 2021 15:54:09 +0100 Subject: [PATCH 05/26] Remove `Stream::next` This is a temporary change only, as we wait to resolve dynamic dispatch issues. The `Stream::next` method and corresponding documentation are expected to be fully restored once we have a path to proceed. Ref: https://github.com/rust-lang/rfcs/pull/2996#issuecomment-757386206 update docs --- library/core/src/stream/mod.rs | 45 ++++++-------------------- library/core/src/stream/stream/mod.rs | 19 ----------- library/core/src/stream/stream/next.rs | 30 ----------------- 3 files changed, 9 insertions(+), 85 deletions(-) delete mode 100644 library/core/src/stream/stream/next.rs diff --git a/library/core/src/stream/mod.rs b/library/core/src/stream/mod.rs index 48cca4972929a..0df18af65ebf0 100644 --- a/library/core/src/stream/mod.rs +++ b/library/core/src/stream/mod.rs @@ -16,13 +16,12 @@ //! 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 +//! * 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 -//! [Structs]: #structs //! //! That's it! Let's dig into streams. //! @@ -41,17 +40,17 @@ //! ``` //! //! Unlike `Iterator`, `Stream` makes a distinction between the [`poll_next`] -//! method which is used when implementing a `Stream`, and the [`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 -//! yields [`Option`][``]. +//! 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`. //! -//! The future returned by [`next`] will yield `Some(Item)` as long as there are +//! 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`] +//! 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, @@ -60,8 +59,6 @@ //! //! [`Poll`]: super::task::Poll //! [`poll_next`]: Stream::poll_next -//! [`next`]: Stream::next -//! [``]: Stream::Item //! //! # Implementing Stream //! @@ -112,36 +109,12 @@ //! } //! } //! } -//! -//! // And now we can use it! -//! # async fn run() { -//! # -//! let mut counter = Counter::new(); -//! -//! let x = counter.next().await.unwrap(); -//! println!("{}", x); -//! -//! let x = counter.next().await.unwrap(); -//! println!("{}", x); -//! -//! let x = counter.next().await.unwrap(); -//! println!("{}", x); -//! -//! let x = counter.next().await.unwrap(); -//! println!("{}", x); -//! -//! let x = counter.next().await.unwrap(); -//! println!("{}", x); -//! # -//! } //! ``` //! -//! This will print `1` through `5`, each on their own line. -//! //! # 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 +//! 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: //! @@ -151,4 +124,4 @@ mod stream; -pub use stream::{Next, Stream}; +pub use stream::Stream; diff --git a/library/core/src/stream/stream/mod.rs b/library/core/src/stream/stream/mod.rs index 3f92c2e8c1c02..e37902dae1f2d 100644 --- a/library/core/src/stream/stream/mod.rs +++ b/library/core/src/stream/stream/mod.rs @@ -1,7 +1,3 @@ -mod next; - -pub use next::Next; - use crate::ops::DerefMut; use crate::pin::Pin; use crate::task::{Context, Poll}; @@ -81,21 +77,6 @@ pub trait Stream { fn size_hint(&self) -> (usize, Option) { (0, None) } - - /// Advances the stream and returns a future which yields the next value. - /// - /// The returned future yields [`None`] when iteration is finished. - /// Individual stream implementations may choose to resume iteration, and so - /// calling `next()` again may or may not eventually start yielding - /// [`Some(Item)`] again at some point. - /// - /// [`Some(Item)`]: Some - fn next(&mut self) -> Next<'_, Self> - where - Self: Unpin, - { - Next::new(self) - } } #[unstable(feature = "async_stream", issue = "79024")] diff --git a/library/core/src/stream/stream/next.rs b/library/core/src/stream/stream/next.rs deleted file mode 100644 index e25d44228e781..0000000000000 --- a/library/core/src/stream/stream/next.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::future::Future; -use crate::pin::Pin; -use crate::stream::Stream; -use crate::task::{Context, Poll}; - -/// A future which advances the stream and returns the next value. -/// -/// This `struct` is created by [`Stream::next`]. See its documentation for more. -#[unstable(feature = "async_stream", issue = "79024")] -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct Next<'a, S: ?Sized> { - stream: &'a mut S, -} - -impl<'a, S: ?Sized> Next<'a, S> { - /// Create a new instance of `Next`. - pub(crate) fn new(stream: &'a mut S) -> Self { - Self { stream } - } -} - -#[unstable(feature = "async_stream", issue = "79024")] -impl Future for Next<'_, S> { - type Output = Option; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - Pin::new(&mut *self.stream).poll_next(cx) - } -} From 328abfb9431c486ab2d0b9ebd7f6115805f613de Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Tue, 26 Jan 2021 11:14:57 +0000 Subject: [PATCH 06/26] Slight simplification of chars().count() --- library/core/src/str/iter.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 8b952eab2946d..c37843434781a 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -47,12 +47,13 @@ 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; + let mut char_count = 0; for &byte in self.iter { - cont_bytes += utf8_is_cont_byte(byte) as usize; + if !utf8_is_cont_byte(byte) { + char_count += 1; + } } - bytes_len - cont_bytes + char_count } #[inline] From 425a70a460abac1182a792c6c2af6dff69663c3c Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Tue, 26 Jan 2021 11:26:58 +0000 Subject: [PATCH 07/26] Removing if so it's more like the previous implementation. --- library/core/src/str/iter.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index c37843434781a..34c31d599a318 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -49,9 +49,7 @@ impl<'a> Iterator for Chars<'a> { // length in `char` is equal to the number of non-continuation bytes let mut char_count = 0; for &byte in self.iter { - if !utf8_is_cont_byte(byte) { - char_count += 1; - } + char_count += !utf8_is_cont_byte(byte) as usize; } char_count } From c07e5585b312aaa76f7bd35e60cf8e8d9164369c Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Tue, 26 Jan 2021 11:36:02 +0000 Subject: [PATCH 08/26] Let's try the most idiomatic way. --- library/core/src/str/iter.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 34c31d599a318..0c74f6e45a784 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -47,11 +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 mut char_count = 0; - for &byte in self.iter { - char_count += !utf8_is_cont_byte(byte) as usize; - } - char_count + self.iter.map(|&byte| !utf8_is_cont_byte(byte) as usize).sum() } #[inline] From a623ea5301737507a8229c2ddae74b20f727bd1b Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Tue, 26 Jan 2021 21:51:18 +0000 Subject: [PATCH 09/26] Same instructions, but simpler. --- library/core/src/str/iter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 0c74f6e45a784..83f484dc570c4 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -47,7 +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 - self.iter.map(|&byte| !utf8_is_cont_byte(byte) as usize).sum() + self.iter.filter(|&&byte| !utf8_is_cont_byte(byte)).count() } #[inline] From d3c69a4c0dd98af2611b7553d1a65afef6a6ccb0 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Thu, 28 Jan 2021 23:56:13 +0900 Subject: [PATCH 10/26] Warn write-only fields --- compiler/rustc_passes/src/dead.rs | 19 ++++++++++++++ .../borrowck/borrowck-assign-to-subfield.rs | 1 + .../ui/lint/dead-code/write-only-field.rs | 20 ++++++++++++++ .../ui/lint/dead-code/write-only-field.stderr | 26 +++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 src/test/ui/lint/dead-code/write-only-field.rs create mode 100644 src/test/ui/lint/dead-code/write-only-field.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 3b1b53553d5e4..a4798b9ae1f0c 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -37,6 +37,19 @@ fn should_explore(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { ) } +fn base_expr<'a>(expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { + let mut current = expr; + loop { + match current.kind { + hir::ExprKind::Field(base, ..) => { + current = base; + } + _ => break, + } + } + current +} + struct MarkSymbolVisitor<'tcx> { worklist: Vec, tcx: TyCtxt<'tcx>, @@ -263,6 +276,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); } diff --git a/src/test/ui/borrowck/borrowck-assign-to-subfield.rs b/src/test/ui/borrowck/borrowck-assign-to-subfield.rs index 050d702b625ab..dfa3a561ec7ee 100644 --- a/src/test/ui/borrowck/borrowck-assign-to-subfield.rs +++ b/src/test/ui/borrowck/borrowck-assign-to-subfield.rs @@ -1,5 +1,6 @@ // run-pass // pretty-expanded FIXME #23616 +#![allow(dead_code)] pub fn main() { struct A { diff --git a/src/test/ui/lint/dead-code/write-only-field.rs b/src/test/ui/lint/dead-code/write-only-field.rs new file mode 100644 index 0000000000000..78cfcfda8f971 --- /dev/null +++ b/src/test/ui/lint/dead-code/write-only-field.rs @@ -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); +} diff --git a/src/test/ui/lint/dead-code/write-only-field.stderr b/src/test/ui/lint/dead-code/write-only-field.stderr new file mode 100644 index 0000000000000..70d2149665b20 --- /dev/null +++ b/src/test/ui/lint/dead-code/write-only-field.stderr @@ -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 + From 899aae465eb4ef295dc1eeb2603f744568e0768c Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Fri, 29 Jan 2021 01:44:15 +0900 Subject: [PATCH 11/26] Simplify base_expr Co-authored-by: Oli Scherer --- compiler/rustc_passes/src/dead.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index a4798b9ae1f0c..3902557e9b52c 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -37,17 +37,13 @@ fn should_explore(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { ) } -fn base_expr<'a>(expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { - let mut current = expr; +fn base_expr<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> loop { - match current.kind { - hir::ExprKind::Field(base, ..) => { - current = base; - } - _ => break, + match expr.kind { + hir::ExprKind::Field(base, ..) => expr = base, + _ => return expr, } } - current } struct MarkSymbolVisitor<'tcx> { From 85ad773049536d7fed9a94ae0ac74f97135c8655 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 28 Jan 2021 17:49:40 +0100 Subject: [PATCH 12/26] Add missing brace --- compiler/rustc_passes/src/dead.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 3902557e9b52c..0d096a0556ba1 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -37,7 +37,7 @@ fn should_explore(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { ) } -fn base_expr<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> +fn base_expr<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { loop { match expr.kind { hir::ExprKind::Field(base, ..) => expr = base, From f620b5ced22e43bf484ca02f08b09dd45a30e0a1 Mon Sep 17 00:00:00 2001 From: Camelid Date: Thu, 28 Jan 2021 18:00:07 -0800 Subject: [PATCH 13/26] rustdoc: Remove unnecessary optional Previously, the HTML output format was represented by both `Some(OutputFormat::Html)` and `None` so there's no need to have an optional. Instead, `OutputFormat::Html` is explicitly the default and we no longer have a "tri-state enum". --- src/librustdoc/config.rs | 26 ++++++++++++------- src/librustdoc/core.rs | 2 +- src/librustdoc/lib.rs | 4 +-- .../passes/calculate_doc_coverage.rs | 2 +- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 94773ac77ccb0..0b6f3b09f0c0a 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -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, // Options that affect the documentation process @@ -142,8 +148,10 @@ crate struct Options { crate crate_version: Option, /// 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, + /// 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, crate deref_mut_trait_did: Option, crate owned_box_did: Option, - crate output_format: Option, + 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); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 16f11e460e6f0..60dbc19483a45 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -460,7 +460,7 @@ crate fn run_global_ctxt( mut default_passes: passes::DefaultPassOption, mut manual_passes: Vec, render_options: RenderOptions, - output_format: Option, + 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), diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index c61cbf78f771a..e98cb237635fe 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -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::>( 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::>( krate, render_opts, diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 61e14c0522277..cdbff62d0645c 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -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; } From 02094f99620b6e2f9c97e25d39fd6ada6a558adf Mon Sep 17 00:00:00 2001 From: Chan Kwan Yin Date: Fri, 29 Jan 2021 12:21:53 +0800 Subject: [PATCH 14/26] Updated Vec::splice documentation Replacing with equal number of values does not increase the length of the vec. Reference: https://stackoverflow.com/a/62559271/3990767 --- library/alloc/src/vec/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 13fcf5207e0c4..9aea19f04c644 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2211,7 +2211,7 @@ impl Vec { /// 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. From 5e983d7b3f03e9243d905e0579f32be00170c9af Mon Sep 17 00:00:00 2001 From: Dhruv Jauhar Date: Thu, 28 Jan 2021 23:22:49 -0500 Subject: [PATCH 15/26] Add a test for syntax like: ..t.s --- .../run_pass/fru_syntax.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs index 426eddec6ff8f..e89cf4550c154 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs @@ -8,22 +8,38 @@ //~| NOTE: `#[warn(incomplete_features)]` on by default //~| NOTE: see issue #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 a"), + 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(); From 63714af3a55dc2bad3a82e3bea81fb8435eedaea Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 28 Jan 2021 22:39:38 -0600 Subject: [PATCH 16/26] update rustfmt to v1.4.34 --- Cargo.lock | 2 +- src/tools/rustfmt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fb5ae6ce66303..fc962f0cc3a65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4432,7 +4432,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.32" +version = "1.4.34" dependencies = [ "annotate-snippets 0.6.1", "anyhow", diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 216a643005633..ea268b9f559fb 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 216a64300563351cad20bb3847110c14561687e0 +Subproject commit ea268b9f559fbafcfc24f4982173b01dfad9e443 From d8b5745d4646e7cb84e8bd6491556658d0578e8b Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 28 Jan 2021 09:24:55 +0100 Subject: [PATCH 17/26] Treat nightlies for a version as complete This commit makes cfg(version) treat the nightlies for version 1.n.0 as 1.n.0, even though that nightly version might not have all stabilizations and features of the released 1.n.0. This is done for greater convenience for people who want to test a newly stabilized feature on nightly. For users who wish to pin nightlies, this commit adds a -Z assume-incomplete-release option that they can enable if there are any issues due to this change. --- compiler/rustc_attr/src/builtin.rs | 10 ++++++---- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/src/options.rs | 2 ++ compiler/rustc_session/src/parse.rs | 3 +++ compiler/rustc_session/src/session.rs | 3 ++- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 26baaf07880f1..5dd4236a8ddad 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -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() { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 55d521a9b5ff5..762a8da632e7e 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -538,6 +538,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); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 30af65e49a075..e8e6a17b4d83f 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -856,6 +856,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], diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index b1a4834241730..81b38347414e8 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -138,6 +138,8 @@ pub struct ParseSess { pub env_depinfo: Lock)>>, /// All the type ascriptions expressions that have had a suggestion for likely path typo. pub type_ascription_path_suggestions: Lock>, + /// 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, } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 6d01854228662..891b9616c2c1d 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1336,7 +1336,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(), From dd18c488f50e7618992bed984cfae9a7099ff488 Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 28 Jan 2021 12:54:30 +0100 Subject: [PATCH 18/26] Add tests --- .../assume-incomplete.rs | 38 +++++++++++++ .../auxiliary/ver-cfg-rel.rs | 56 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 src/test/ui/cfg/assume-incomplete-release/assume-incomplete.rs create mode 100644 src/test/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs diff --git a/src/test/ui/cfg/assume-incomplete-release/assume-incomplete.rs b/src/test/ui/cfg/assume-incomplete-release/assume-incomplete.rs new file mode 100644 index 0000000000000..24d2dc645519d --- /dev/null +++ b/src/test/ui/cfg/assume-incomplete-release/assume-incomplete.rs @@ -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(); +} diff --git a/src/test/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs b/src/test/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs new file mode 100644 index 0000000000000..6787527027e33 --- /dev/null +++ b/src/test/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs @@ -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 { + 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::::new(); + res.extend(TokenStream::from_str(&attr_str).unwrap().into_iter()); + res.extend(input.into_iter()); + res.into_iter().collect() +} From c2c2e8dde16c75eaa75a5d6796ded4813315df58 Mon Sep 17 00:00:00 2001 From: Henry Boisdequin <65845077+henryboisdequin@users.noreply.github.com> Date: Fri, 29 Jan 2021 14:03:01 +0530 Subject: [PATCH 19/26] `fn cold_path` doesn't need to be pub --- compiler/rustc_arena/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index a0493056b816b..54552b499be56 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -32,7 +32,7 @@ use std::slice; #[inline(never)] #[cold] -pub fn cold_path R, R>(f: F) -> R { +fn cold_path R, R>(f: F) -> R { f() } From fd5fb86f05ac7d8f561c2177a5d3e5c80c93dfc7 Mon Sep 17 00:00:00 2001 From: Henry Boisdequin <65845077+henryboisdequin@users.noreply.github.com> Date: Fri, 29 Jan 2021 16:08:49 +0530 Subject: [PATCH 20/26] fix typo --- compiler/rustc_resolve/src/diagnostics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 69fb6870d2c67..9d55bafd2868e 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -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 // | From 08141a5a646555ed188cdbe9a9b4b57c6a4aa2f1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 29 Jan 2021 13:36:49 +0100 Subject: [PATCH 21/26] Add missiong variants in match binding --- src/librustdoc/clean/types.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 86bce8b8707a0..2c6500581fe39 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1437,8 +1437,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)) } From 13ffa43bbb910b5484874f15e7bda824b8fe6782 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 10 Jan 2021 19:35:42 +0100 Subject: [PATCH 22/26] rename raw_const/mut -> const/mut_addr_of, and stabilize them --- library/alloc/src/collections/btree/node.rs | 4 ++-- library/alloc/src/lib.rs | 1 - library/alloc/src/rc.rs | 6 +++--- library/alloc/src/sync.rs | 6 +++--- library/core/src/lib.rs | 1 - library/core/src/ptr/mod.rs | 18 ++++++++---------- library/core/src/slice/mod.rs | 4 ++-- library/std/src/lib.rs | 1 - .../allow_raw_ptr_dereference_const_fn.rs | 3 +-- src/test/ui/consts/ptr_comparisons.rs | 5 ++--- src/test/ui/consts/ptr_comparisons.stderr | 18 +++++++++--------- 11 files changed, 30 insertions(+), 37 deletions(-) diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 8ab3f58c1adba..9733b61666229 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -543,8 +543,8 @@ impl<'a, K, V, Type> NodeRef, 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; diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index d7ae353282e79..e10143b22d108 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -115,7 +115,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))] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index ee03f15eece3f..f67f5fc533b49 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -398,7 +398,7 @@ impl Rc { 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 Rc { // 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` from a raw pointer. @@ -1917,7 +1917,7 @@ impl Weak { // 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) } } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index c0d684fbb4573..d0081097fe10a 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -384,7 +384,7 @@ impl Arc { // 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 Arc { // 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` from a raw pointer. @@ -1677,7 +1677,7 @@ impl Weak { // 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) } } } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 263c6c9cf0f26..df8d9ff371fe4 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -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)] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 8d901c08f91a3..c0108c0f82e81 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -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 } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b06b6e93373f3..315df83115d8c 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -543,8 +543,8 @@ impl [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 diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 92c8b7c177477..933e9229fdb94 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -298,7 +298,6 @@ #![feature(prelude_import)] #![feature(ptr_internals)] #![feature(raw)] -#![feature(raw_ref_macros)] #![feature(ready_macro)] #![feature(rustc_attrs)] #![feature(rustc_private)] diff --git a/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs b/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs index 25dc457d14455..f4279e6b825e2 100644 --- a/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs +++ b/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs @@ -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() {} diff --git a/src/test/ui/consts/ptr_comparisons.rs b/src/test/ui/consts/ptr_comparisons.rs index 595ed30bf9c82..f16f6fd6de4ba 100644 --- a/src/test/ui/consts/ptr_comparisons.rs +++ b/src/test/ui/consts/ptr_comparisons.rs @@ -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 diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr index 49511b84500de..96b63c0acb0a1 100644 --- a/src/test/ui/consts/ptr_comparisons.stderr +++ b/src/test/ui/consts/ptr_comparisons.stderr @@ -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::::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 }; | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- From 718398ccafaa45ed6a08ec550155150b9564eeed Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Fri, 29 Jan 2021 23:30:55 +0900 Subject: [PATCH 23/26] Fix typo in pat.rs parentesized -> parenthesized --- compiler/rustc_parse/src/parser/pat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 456e32680fe50..d888514cf56d6 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -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)) { From 807b5f5591e5c726e7965c0d5ff308b0dc1e874f Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Fri, 29 Jan 2021 17:04:31 +0000 Subject: [PATCH 24/26] Don't print error output from rustup when detecting default build triple Before, it could print this error if no toolchain was configured: ``` error: no default toolchain configured error: backtrace: error: stack backtrace: 0: error_chain::backtrace::imp::InternalBacktrace::new 1: rustup::config::Cfg::toolchain_for_dir 2: rustup_init::run_rustup_inner 3: rustup_init::main 4: std::rt::lang_start::{{closure}} 5: main 6: __libc_start_main 7: _start ``` --- src/bootstrap/bootstrap.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 8576f57959a6f..5b0b89cc2dbff 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -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] From db115f13f398ace4a207afc1beacde6a990f2f53 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Fri, 29 Jan 2021 17:23:36 +0000 Subject: [PATCH 25/26] Don't clone LLVM submodule when download-ci-llvm is set Previously, `downloading_llvm` would check `self.build` while it was still an empty string, and think it was always false. This fixes the check. --- src/bootstrap/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 8576f57959a6f..cc9a233e9afb9 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1085,10 +1085,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() From 915a04e2a401919d8b0e152331c839df471577b7 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Thu, 31 Dec 2020 18:02:52 +0200 Subject: [PATCH 26/26] Consider Scalar to be a bool only if its unsigned This seems right, given that conceptually bools are unsigned, but the implications of this change may have more action at distance that I'm not sure how to exhaustively consider. For instance there are a number of cases where code attaches range metadata if `scalar.is_bool()` holds. Supposedly it would no longer be attached to the `repr(i8)` enums? Though I'm not sure why booleans are being special-cased here in the first place... Fixes #80556 --- compiler/rustc_target/src/abi/call/mod.rs | 7 ++++++- compiler/rustc_target/src/abi/mod.rs | 2 +- src/test/codegen/abi-repr-ext.rs | 13 +++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 src/test/codegen/abi-repr-ext.rs diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index aa1c31bda54df..ce8e56b194980 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -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 } diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 88b2923f6c48f..b14b1ef00db91 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -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. diff --git a/src/test/codegen/abi-repr-ext.rs b/src/test/codegen/abi-repr-ext.rs new file mode 100644 index 0000000000000..f93ccd794117d --- /dev/null +++ b/src/test/codegen/abi-repr-ext.rs @@ -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 +}