Skip to content

Rollup of 16 pull requests #62182

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 40 commits into from
Closed
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
b66dcb9
explain better that structural pinning is a per-field choice
RalfJung Jun 15, 2019
c489636
mention that overwrite-without-drop also violates the drop guarantee,…
RalfJung Jun 15, 2019
665aa3e
minor edits
RalfJung Jun 15, 2019
86e283a
keep links in local crate where possible
RalfJung Jun 16, 2019
2eb074d
make example code typecheck at least
RalfJung Jun 16, 2019
f250951
Apply suggestions from code review
RalfJung Jun 19, 2019
bf03a3c
nits
RalfJung Jun 19, 2019
a99a7b7
Remove FnBox.
Centril Jun 22, 2019
1c12b1b
call out explicitly that general read needs to be called with an init…
RalfJung Jun 24, 2019
b75021b
refactor lexer to use idiomatic borrowing
matklad Jun 25, 2019
0f34d7a
Updated RELEASES.md for 1.36.0
XAMPPRocky Jun 23, 2019
ba12e78
Add more tests for async/await
cramertj Jun 25, 2019
57db25e
cleanup: rename name_from to symbol_from
matklad Jun 25, 2019
390f717
tweak wording
RalfJung Jun 25, 2019
5cb841d
Don't ICE on item in `.await` expression
cofibrant Jun 26, 2019
182ce77
remove old fixme
mark-i-m Jun 26, 2019
72ca844
Add regression test for MIR drop generation in async loops
cramertj Jun 26, 2019
7e62050
Update books
ehuss Jun 26, 2019
e053eed
Remove outdated question_mark_macro_sep lint
ia0 Jun 26, 2019
b366f2b
Implement mem::{zeroed,uninitialized} in terms of MaybeUninit.
alex Jun 26, 2019
768d500
save-analysis: use buffered writes
jsgf Jun 27, 2019
b608749
rustc: Retry SIGILL linker invocations
alexcrichton Jun 27, 2019
d79104b
Update RLS
Xanewok Jun 27, 2019
8819420
Add suggestion for missing `.await` keyword
cofibrant Jun 19, 2019
ed8cba1
Rollup merge of #61878 - RalfJung:pin, r=Dylan-DPC
Centril Jun 27, 2019
ebdf01c
Rollup merge of #62043 - Centril:remove-fnbox, r=cramertj
Centril Jun 27, 2019
2cdfff8
Rollup merge of #62067 - doctorn:await_diagnostic, r=matthewjasper
Centril Jun 27, 2019
5343acd
Rollup merge of #62076 - XAMPPRocky:master, r=XAMPPRocky
Centril Jun 27, 2019
d95e074
Rollup merge of #62102 - RalfJung:read, r=Centril
Centril Jun 27, 2019
de92646
Rollup merge of #62106 - cramertj:test-await, r=centril
Centril Jun 27, 2019
13d2727
Rollup merge of #62124 - matklad:without-with, r=petrochenkov
Centril Jun 27, 2019
2a0a6a4
Rollup merge of #62150 - alex:mem-uninit-refactor, r=RalfJung,oli-obk…
Centril Jun 27, 2019
cf53bc6
Rollup merge of #62152 - doctorn:async_let_ice, r=cramertj
Centril Jun 27, 2019
457e9e6
Rollup merge of #62154 - mark-i-m:old-fixme, r=Centril
Centril Jun 27, 2019
54adc9f
Rollup merge of #62155 - cramertj:61872, r=centril
Centril Jun 27, 2019
a067d22
Rollup merge of #62156 - ehuss:update-books, r=ehuss
Centril Jun 27, 2019
9551ab9
Rollup merge of #62160 - ia0:question_mark_macro_sep, r=petrochenkov
Centril Jun 27, 2019
0b690f0
Rollup merge of #62164 - jsgf:buffer-save-analysis, r=Xanewok
Centril Jun 27, 2019
ab7143c
Rollup merge of #62171 - alexcrichton:more-restarts, r=eddyb
Centril Jun 27, 2019
24a356f
Rollup merge of #62176 - Xanewok:update-rls, r=alexcrichton
Centril Jun 27, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 102 additions & 1 deletion RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,104 @@
Version 1.36.0 (2019-07-04)
==========================

Language
--------
- [Non-Lexical Lifetimes are now enabled on the 2015 edition.][59114]
- [The order of traits in trait objects no longer affects the semantics of that
object.][59445] e.g. `dyn Send + fmt::Debug` is now equivalent to
`dyn fmt::Debug + Send`, where this was previously not the case.

Libraries
---------
- [`HashMap`'s implementation has been replaced with `hashbrown::HashMap` implementation.][58623]
- [`TryFromSliceError` now implements `From<Infallible>`.][60318]
- [`mem::needs_drop` is now available as a const fn.][60364]
- [`alloc::Layout::from_size_align_unchecked` is now available as a const fn.][60370]
- [`String` now implements `BorrowMut<str>`.][60404]
- [`io::Cursor` now implements `Default`.][60234]
- [Both `NonNull::{dangling, cast}` are now const fns.][60244]
- [The `alloc` crate is now stable.][59675] `alloc` allows you to use a subset
of `std` (e.g. `Vec`, `Box`, `Arc`) in `#![no_std]` environments if the
environment has access to heap memory allocation.
- [`String` now implements `From<&String>`.][59825]
- [You can now pass multiple arguments to the `dbg!` macro.][59826] `dbg!` will
return a tuple of each argument when there is multiple arguments.
- [`Result::{is_err, is_ok}` are now `#[must_use]` and will produce a warning if
not used.][59648]

Stabilized APIs
---------------
- [`VecDeque::rotate_left`]
- [`VecDeque::rotate_right`]
- [`Iterator::copied`]
- [`io::IoSlice`]
- [`io::IoSliceMut`]
- [`Read::read_vectored`]
- [`Write::write_vectored`]
- [`str::as_mut_ptr`]
- [`mem::MaybeUninit`]
- [`pointer::align_offset`]
- [`future::Future`]
- [`task::Context`]
- [`task::RawWaker`]
- [`task::RawWakerVTable`]
- [`task::Waker`]
- [`task::Poll`]

Cargo
-----
- [Cargo will now produce an error if you attempt to use the name of a required dependency as a feature.][cargo/6860]
- [You can now pass the `--offline` flag to run cargo without accessing the network.][cargo/6934]

You can find further change's in [Cargo's 1.36.0 release notes][cargo-1-36-0].

Clippy
------
There have been numerous additions and fixes to clippy, see [Clippy's 1.36.0 release notes][clippy-1-36-0] for more details.

Misc
----

Compatibility Notes
-------------------
- With the stabilisation of `mem::MaybeUninit`, `mem::uninitialized` use is no
longer recommended, and will be deprecated in 1.38.0.

[60318]: https://github.com/rust-lang/rust/pull/60318/
[60364]: https://github.com/rust-lang/rust/pull/60364/
[60370]: https://github.com/rust-lang/rust/pull/60370/
[60404]: https://github.com/rust-lang/rust/pull/60404/
[60234]: https://github.com/rust-lang/rust/pull/60234/
[60244]: https://github.com/rust-lang/rust/pull/60244/
[58623]: https://github.com/rust-lang/rust/pull/58623/
[59648]: https://github.com/rust-lang/rust/pull/59648/
[59675]: https://github.com/rust-lang/rust/pull/59675/
[59825]: https://github.com/rust-lang/rust/pull/59825/
[59826]: https://github.com/rust-lang/rust/pull/59826/
[59445]: https://github.com/rust-lang/rust/pull/59445/
[59114]: https://github.com/rust-lang/rust/pull/59114/
[cargo/6860]: https://github.com/rust-lang/cargo/pull/6860/
[cargo/6934]: https://github.com/rust-lang/cargo/pull/6934/
[`VecDeque::rotate_left`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.rotate_left
[`VecDeque::rotate_right`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.rotate_right
[`Iterator::copied`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.copied
[`io::IoSlice`]: https://doc.rust-lang.org/std/io/struct.IoSlice.html
[`io::IoSliceMut`]: https://doc.rust-lang.org/std/io/struct.IoSliceMut.html
[`Read::read_vectored`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_vectored
[`Write::write_vectored`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_vectored
[`str::as_mut_ptr`]: https://doc.rust-lang.org/std/primitive.str.html#method.as_mut_ptr
[`mem::MaybeUninit`]: https://doc.rust-lang.org/std/mem/union.MaybeUninit.html
[`pointer::align_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.align_offset
[`future::Future`]: https://doc.rust-lang.org/std/future/trait.Future.html
[`task::Context`]: https://doc.rust-lang.org/beta/std/task/struct.Context.html
[`task::RawWaker`]: https://doc.rust-lang.org/beta/std/task/struct.RawWaker.html
[`task::RawWakerVTable`]: https://doc.rust-lang.org/beta/std/task/struct.RawWakerVTable.html
[`task::Waker`]: https://doc.rust-lang.org/beta/std/task/struct.Waker.html
[`task::Poll`]: https://doc.rust-lang.org/beta/std/task/enum.Poll.html
[clippy-1-36-0]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-136
[cargo-1-36-0]: https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-136-2019-07-04


Version 1.35.0 (2019-05-23)
==========================

@@ -62,7 +163,7 @@ Cargo
- [You can now set `cargo:rustc-cdylib-link-arg` at build time to pass custom
linker arguments when building a `cdylib`.][cargo/6298] Its usage is highly
platform specific.

Misc
----
- [The Rust toolchain is now available natively for musl based distros.][58575]
2 changes: 1 addition & 1 deletion src/doc/nomicon
2 changes: 1 addition & 1 deletion src/doc/reference
2 changes: 1 addition & 1 deletion src/doc/rust-by-example
2 changes: 1 addition & 1 deletion src/doc/rustc-guide
Original file line number Diff line number Diff line change
@@ -117,9 +117,7 @@ fn main () {
}
```

One of the objectives of this feature is to allow `Box<dyn FnOnce>`, instead of `Box<dyn FnBox>` in the future. See [#28796] for details.

[#28796]: https://github.com/rust-lang/rust/issues/28796
One of the objectives of this feature is to allow `Box<dyn FnOnce>`.

## Variable length arrays

32 changes: 0 additions & 32 deletions src/doc/unstable-book/src/library-features/fnbox.md

This file was deleted.

79 changes: 0 additions & 79 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
@@ -761,85 +761,6 @@ impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> {
}
}

/// `FnBox` is deprecated and will be removed.
/// `Box<dyn FnOnce()>` can be called directly, since Rust 1.35.0.
///
/// `FnBox` is a version of the `FnOnce` intended for use with boxed
/// closure objects. The idea was that where one would normally store a
/// `Box<dyn FnOnce()>` in a data structure, you whould use
/// `Box<dyn FnBox()>`. The two traits behave essentially the same, except
/// that a `FnBox` closure can only be called if it is boxed.
///
/// # Examples
///
/// Here is a snippet of code which creates a hashmap full of boxed
/// once closures and then removes them one by one, calling each
/// closure as it is removed. Note that the type of the closures
/// stored in the map is `Box<dyn FnBox() -> i32>` and not `Box<dyn FnOnce()
/// -> i32>`.
///
/// ```
/// #![feature(fnbox)]
/// #![allow(deprecated)]
///
/// use std::boxed::FnBox;
/// use std::collections::HashMap;
///
/// fn make_map() -> HashMap<i32, Box<dyn FnBox() -> i32>> {
/// let mut map: HashMap<i32, Box<dyn FnBox() -> i32>> = HashMap::new();
/// map.insert(1, Box::new(|| 22));
/// map.insert(2, Box::new(|| 44));
/// map
/// }
///
/// fn main() {
/// let mut map = make_map();
/// for i in &[1, 2] {
/// let f = map.remove(&i).unwrap();
/// assert_eq!(f(), i * 22);
/// }
/// }
/// ```
///
/// In Rust 1.35.0 or later, use `FnOnce`, `FnMut`, or `Fn` instead:
///
/// ```
/// use std::collections::HashMap;
///
/// fn make_map() -> HashMap<i32, Box<dyn FnOnce() -> i32>> {
/// let mut map: HashMap<i32, Box<dyn FnOnce() -> i32>> = HashMap::new();
/// map.insert(1, Box::new(|| 22));
/// map.insert(2, Box::new(|| 44));
/// map
/// }
///
/// fn main() {
/// let mut map = make_map();
/// for i in &[1, 2] {
/// let f = map.remove(&i).unwrap();
/// assert_eq!(f(), i * 22);
/// }
/// }
/// ```
#[rustc_paren_sugar]
#[unstable(feature = "fnbox", issue = "28796")]
#[rustc_deprecated(reason = "use `FnOnce`, `FnMut`, or `Fn` instead", since = "1.37.0")]
pub trait FnBox<A>: FnOnce<A> {
/// Performs the call operation.
fn call_box(self: Box<Self>, args: A) -> Self::Output;
}

#[unstable(feature = "fnbox", issue = "28796")]
#[rustc_deprecated(reason = "use `FnOnce`, `FnMut`, or `Fn` instead", since = "1.37.0")]
#[allow(deprecated, deprecated_in_future)]
impl<A, F> FnBox<A> for F
where F: FnOnce<A>
{
fn call_box(self: Box<F>, args: A) -> F::Output {
self.call_once(args)
}
}

#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}

1 change: 1 addition & 0 deletions src/libcore/future/future.rs
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ use crate::task::{Context, Poll};
#[doc(spotlight)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[stable(feature = "futures_api", since = "1.36.0")]
#[cfg_attr(not(bootstrap), lang = "future_trait")]
pub trait Future {
/// The type of value produced on completion.
#[stable(feature = "futures_api", since = "1.36.0")]
16 changes: 7 additions & 9 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
@@ -700,17 +700,15 @@ extern "rust-intrinsic" {
/// which is unsafe unless `T` is `Copy`. Also, even if T is
/// `Copy`, an all-zero value may not correspond to any legitimate
/// state for the type in question.
#[unstable(feature = "core_intrinsics",
reason = "intrinsics are unlikely to ever be stabilized, instead \
they should be used through stabilized interfaces \
in the rest of the standard library",
issue = "0")]
#[rustc_deprecated(reason = "no longer used by rustc, will be removed - use MaybeUnint instead",
since = "1.37.0")]
pub fn init<T>() -> T;

/// Creates an uninitialized value.
///
/// `uninit` is unsafe because there is no guarantee of what its
/// contents are. In particular its drop-flag may be set to any
/// state, which means it may claim either dropped or
/// undropped. In the general case one must use `ptr::write` to
/// initialize memory previous set to the result of `uninit`.
pub fn uninit<T>() -> T;

/// Moves a value out of scope without running drop glue.
pub fn forget<T: ?Sized>(_: T);

6 changes: 2 additions & 4 deletions src/libcore/mem/mod.rs
Original file line number Diff line number Diff line change
@@ -450,8 +450,7 @@ pub const fn needs_drop<T>() -> bool {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn zeroed<T>() -> T {
intrinsics::panic_if_uninhabited::<T>();
intrinsics::init()
MaybeUninit::zeroed().assume_init()
}

/// Bypasses Rust's normal memory-initialization checks by pretending to
@@ -476,8 +475,7 @@ pub unsafe fn zeroed<T>() -> T {
#[rustc_deprecated(since = "1.38.0", reason = "use `mem::MaybeUninit` instead")]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn uninitialized<T>() -> T {
intrinsics::panic_if_uninhabited::<T>();
intrinsics::uninit()
MaybeUninit::uninit().assume_init()
}

/// Swaps the values at two mutable locations, without deinitializing either one.
171 changes: 130 additions & 41 deletions src/libcore/pin.rs
Original file line number Diff line number Diff line change
@@ -138,10 +138,11 @@
//! To make this work, not just moving the data is restricted; deallocating, repurposing, or
//! otherwise invalidating the memory used to store the data is restricted, too.
//! Concretely, for pinned data you have to maintain the invariant
//! that *its memory will not get invalidated from the moment it gets pinned until
//! that *its memory will not get invalidated or repurposed from the moment it gets pinned until
//! when `drop` is called*. Memory can be invalidated by deallocation, but also by
//! replacing a [`Some(v)`] by [`None`], or calling [`Vec::set_len`] to "kill" some elements
//! off of a vector.
//! off of a vector. It can be repurposed by using [`ptr::write`] to overwrite it without
//! calling the destructor first.
//!
//! This is exactly the kind of guarantee that the intrusive linked list from the previous
//! section needs to function correctly.
@@ -166,57 +167,130 @@
//! implementation as well: if an element of your type could have been pinned,
//! you must treat Drop as implicitly taking `Pin<&mut Self>`.
//!
//! In particular, if your type is `#[repr(packed)]`, the compiler will automatically
//! For example, you could implement `Drop` as follows:
//! ```rust,no_run
//! # use std::pin::Pin;
//! # struct Type { }
//! impl Drop for Type {
//! fn drop(&mut self) {
//! // `new_unchecked` is okay because we know this value is never used
//! // again after being dropped.
//! inner_drop(unsafe { Pin::new_unchecked(self)});
//! fn inner_drop(this: Pin<&mut Type>) {
//! // Actual drop code goes here.
//! }
//! }
//! }
//! ```
//! The function `inner_drop` has the type that `drop` *should* have, so this makes sure that
//! you do not accidentally use `self`/`this` in a way that is in conflict with pinning.
//!
//! Moreover, if your type is `#[repr(packed)]`, the compiler will automatically
//! move fields around to be able to drop them. As a consequence, you cannot use
//! pinning with a `#[repr(packed)]` type.
//!
//! # Projections and Structural Pinning
//!
//! One interesting question arises when considering the interaction of pinning
//! and the fields of a struct. When can a struct have a "pinning projection",
//! i.e., an operation with type `fn(Pin<&Struct>) -> Pin<&Field>`? In a
//! similar vein, when can a generic wrapper type (such as `Vec<T>`, `Box<T>`,
//! or `RefCell<T>`) have an operation with type `fn(Pin<&Wrapper<T>>) ->
//! Pin<&T>`?
//!
//! Note: For the entirety of this discussion, the same applies for mutable references as it
//! does for shared references.
//! When working with pinned structs, the question arises how one can access the
//! fields of that struct in a method that takes just `Pin<&mut Struct>`.
//! The usual approach is to write helper methods (so called *projections*)
//! that turn `Pin<&mut Struct>` into a reference to the field, but what
//! type should that reference have? Is it `Pin<&mut Field>` or `&mut Field`?
//! The same question arises with the fields of an `enum`, and also when considering
//! container/wrapper types such as [`Vec<T>`], [`Box<T>`], or [`RefCell<T>`].
//! (This question applies to both mutable and shared references, we just
//! use the more common case of mutable references here for illustration.)
//!
//! It turns out that it is actually up to the author of the data structure
//! to decide whether the pinned projection for a particular field turns
//! `Pin<&mut Struct>` into `Pin<&mut Field>` or `&mut Field`. There are some
//! constraints though, and the most important constraint is *consistency*:
//! every field can be *either* projected to a pinned reference, *or* have
//! pinning removed as part of the projection. If both are done for the same field,
//! that will likely be unsound!
//!
//! As the author of a data structure you get to decide for each field whether pinning
//! "propagates" to this field or not. Pinning that propagates is also called "structural",
//! because it follows the structure of the type.
//! In the following subsections, we describe the considerations that have to be made
//! for either choice.
//!
//! ## Pinning *is not* structural for `field`
//!
//! It may seem counter-intuitive that the field of a pinned struct might not be pinned,
//! but that is actually the easiest choice: if a `Pin<&mut Field>` is never created,
//! nothing can go wrong! So, if you decide that some field does not have structural pinning,
//! all you have to ensure is that you never create a pinned reference to that field.
//!
//! Fields without structural pinning may have a projection method that turns
//! `Pin<&mut Struct>` into `&mut Field`:
//! ```rust,no_run
//! # use std::pin::Pin;
//! # type Field = i32;
//! # struct Struct { field: Field }
//! impl Struct {
//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> &'a mut Field {
//! // This is okay because `field` is never considered pinned.
//! unsafe { &mut self.get_unchecked_mut().field }
//! }
//! }
//! ```
//!
//! Having a pinning projection for some field means that pinning is "structural":
//! when the wrapper is pinned, the field must be considered pinned, too.
//! After all, the pinning projection lets us get a `Pin<&Field>`.
//! You may also `impl Unpin for Struct` *even if* the type of `field`
//! is not `Unpin`. What that type thinks about pinning is not relevant
//! when no `Pin<&mut Field>` is ever created.
//!
//! ## Pinning *is* structural for `field`
//!
//! The other option is to decide that pinning is "structural" for `field`,
//! meaning that if the struct is pinned then so is the field.
//!
//! This allows writing a projection that creates a `Pin<&mut Field>`, thus
//! witnessing that the field is pinned:
//! ```rust,no_run
//! # use std::pin::Pin;
//! # type Field = i32;
//! # struct Struct { field: Field }
//! impl Struct {
//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut Field> {
//! // This is okay because `field` is pinned when `self` is.
//! unsafe { self.map_unchecked_mut(|s| &mut s.field) }
//! }
//! }
//! ```
//!
//! However, structural pinning comes with a few extra requirements, so not all
//! wrappers can be structural and hence not all wrappers can offer pinning projections:
//! However, structural pinning comes with a few extra requirements:
//!
//! 1. The wrapper must only be [`Unpin`] if all the structural fields are
//! 1. The struct must only be [`Unpin`] if all the structural fields are
//! `Unpin`. This is the default, but `Unpin` is a safe trait, so as the author of
//! the wrapper it is your responsibility *not* to add something like
//! `impl<T> Unpin for Wrapper<T>`. (Notice that adding a projection operation
//! the struct it is your responsibility *not* to add something like
//! `impl<T> Unpin for Struct<T>`. (Notice that adding a projection operation
//! requires unsafe code, so the fact that `Unpin` is a safe trait does not break
//! the principle that you only have to worry about any of this if you use `unsafe`.)
//! 2. The destructor of the wrapper must not move structural fields out of its argument. This
//! 2. The destructor of the struct must not move structural fields out of its argument. This
//! is the exact point that was raised in the [previous section][drop-impl]: `drop` takes
//! `&mut self`, but the wrapper (and hence its fields) might have been pinned before.
//! `&mut self`, but the struct (and hence its fields) might have been pinned before.
//! You have to guarantee that you do not move a field inside your `Drop` implementation.
//! In particular, as explained previously, this means that your wrapper type must *not*
//! In particular, as explained previously, this means that your struct must *not*
//! be `#[repr(packed)]`.
//! See that section for how to write `drop` in a way that the compiler can help you
//! not accidentally break pinning.
//! 3. You must make sure that you uphold the [`Drop` guarantee][drop-guarantee]:
//! once your wrapper is pinned, the memory that contains the
//! once your struct is pinned, the memory that contains the
//! content is not overwritten or deallocated without calling the content's destructors.
//! This can be tricky, as witnessed by `VecDeque<T>`: the destructor of `VecDeque<T>` can fail
//! to call `drop` on all elements if one of the destructors panics. This violates the
//! This can be tricky, as witnessed by [`VecDeque<T>`]: the destructor of `VecDeque<T>`
//! can fail to call `drop` on all elements if one of the destructors panics. This violates the
//! `Drop` guarantee, because it can lead to elements being deallocated without
//! their destructor being called. (`VecDeque` has no pinning projections, so this
//! does not cause unsoundness.)
//! 4. You must not offer any other operations that could lead to data being moved out of
//! the fields when your type is pinned. For example, if the wrapper contains an
//! the structural fields when your type is pinned. For example, if the struct contains an
//! `Option<T>` and there is a `take`-like operation with type
//! `fn(Pin<&mut Wrapper<T>>) -> Option<T>`,
//! that operation can be used to move a `T` out of a pinned `Wrapper<T>` -- which means
//! pinning cannot be structural.
//! `fn(Pin<&mut Struct<T>>) -> Option<T>`,
//! that operation can be used to move a `T` out of a pinned `Struct<T>` -- which means
//! pinning cannot be structural for the field holding this data.
//!
//! For a more complex example of moving data out of a pinned type, imagine if `RefCell<T>`
//! For a more complex example of moving data out of a pinned type, imagine if [`RefCell<T>`]
//! had a method `fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>`.
//! Then we could do the following:
//! ```compile_fail
@@ -231,13 +305,16 @@
//! (using `RefCell::get_pin_mut`) and then move that content using the mutable
//! reference we got later.
//!
//! For a type like `Vec<T>`, both possibilites (structural pinning or not) make sense,
//! and the choice is up to the author. A `Vec<T>` with structural pinning could
//! have `get_pin`/`get_pin_mut` projections. However, it could *not* allow calling
//! ## Examples
//!
//! For a type like [`Vec<T>`], both possibilites (structural pinning or not) make sense.
//! A `Vec<T>` with structural pinning could have `get_pin`/`get_pin_mut` methods to get
//! pinned references to elements. However, it could *not* allow calling
//! `pop` on a pinned `Vec<T>` because that would move the (structurally pinned) contents!
//! Nor could it allow `push`, which might reallocate and thus also move the contents.
//! A `Vec<T>` without structural pinning could `impl<T> Unpin for Vec<T>`, because the contents
//! are never pinned and the `Vec<T>` itself is fine with being moved as well.
//! At that point pinning just has no effect on the vector at all.
//!
//! In the standard library, pointer types generally do not have structural pinning,
//! and thus they do not offer pinning projections. This is why `Box<T>: Unpin` holds for all `T`.
@@ -249,16 +326,28 @@
//! whether the content is pinned is entirely independent of whether the pointer is
//! pinned, meaning pinning is *not* structural.
//!
//! When implementing a [`Future`] combinator, you will usually need structural pinning
//! for the nested futures, as you need to get pinned references to them to call `poll`.
//! But if your combinator contains any other data that does not need to be pinned,
//! you can make those fields not structural and hence freely access them with a
//! mutable reference even when you just have `Pin<&mut Self>` (such as in your own
//! `poll` implementation).
//!
//! [`Pin<P>`]: struct.Pin.html
//! [`Unpin`]: ../../std/marker/trait.Unpin.html
//! [`Deref`]: ../../std/ops/trait.Deref.html
//! [`DerefMut`]: ../../std/ops/trait.DerefMut.html
//! [`mem::swap`]: ../../std/mem/fn.swap.html
//! [`mem::forget`]: ../../std/mem/fn.forget.html
//! [`Unpin`]: ../marker/trait.Unpin.html
//! [`Deref`]: ../ops/trait.Deref.html
//! [`DerefMut`]: ../ops/trait.DerefMut.html
//! [`mem::swap`]: ../mem/fn.swap.html
//! [`mem::forget`]: ../mem/fn.forget.html
//! [`Box<T>`]: ../../std/boxed/struct.Box.html
//! [`Vec<T>`]: ../../std/vec/struct.Vec.html
//! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len
//! [`None`]: ../../std/option/enum.Option.html#variant.None
//! [`Some(v)`]: ../../std/option/enum.Option.html#variant.Some
//! [`VecDeque<T>`]: ../../std/collections/struct.VecDeque.html
//! [`RefCell<T>`]: ../cell/struct.RefCell.html
//! [`None`]: ../option/enum.Option.html#variant.None
//! [`Some(v)`]: ../option/enum.Option.html#variant.Some
//! [`ptr::write`]: ../ptr/fn.write.html
//! [`Future`]: ../future/trait.Future.html
//! [drop-impl]: #drop-implementation
//! [drop-guarantee]: #drop-guarantee
1 change: 0 additions & 1 deletion src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
@@ -5795,7 +5795,6 @@ impl<'a> LoweringContext<'a> {
err.span_label(item_sp, "this is not `async`");
}
err.emit();
return hir::ExprKind::Err;
}
}
let span = self.mark_span_with_reason(
2 changes: 1 addition & 1 deletion src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
@@ -1713,7 +1713,7 @@ pub enum GeneratorMovability {
}

/// The yield kind that caused an `ExprKind::Yield`.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable)]
pub enum YieldSource {
/// An `<expr>.await`.
Await,
7 changes: 0 additions & 7 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
@@ -348,12 +348,6 @@ declare_lint! {

/// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`.
pub mod parser {
declare_lint! {
pub QUESTION_MARK_MACRO_SEP,
Allow,
"detects the use of `?` as a macro separator"
}

declare_lint! {
pub ILL_FORMED_ATTRIBUTE_INPUT,
Warn,
@@ -444,7 +438,6 @@ declare_lint_pass! {
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
MACRO_USE_EXTERN_CRATE,
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
parser::QUESTION_MARK_MACRO_SEP,
parser::ILL_FORMED_ATTRIBUTE_INPUT,
DEPRECATED_IN_FUTURE,
AMBIGUOUS_ASSOCIATED_ITEMS,
3 changes: 1 addition & 2 deletions src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ use crate::hir::def_id::{CrateNum, LOCAL_CRATE};
use crate::hir::intravisit;
use crate::hir;
use crate::lint::builtin::BuiltinLintDiagnostics;
use crate::lint::builtin::parser::{QUESTION_MARK_MACRO_SEP, ILL_FORMED_ATTRIBUTE_INPUT};
use crate::lint::builtin::parser::ILL_FORMED_ATTRIBUTE_INPUT;
use crate::session::{Session, DiagnosticMessageId};
use crate::ty::TyCtxt;
use crate::ty::query::Providers;
@@ -80,7 +80,6 @@ impl Lint {
/// Returns the `rust::lint::Lint` for a `syntax::early_buffered_lints::BufferedEarlyLintId`.
pub fn from_parser_lint_id(lint_id: BufferedEarlyLintId) -> &'static Self {
match lint_id {
BufferedEarlyLintId::QuestionMarkMacroSep => QUESTION_MARK_MACRO_SEP,
BufferedEarlyLintId::IllFormedAttributeInput => ILL_FORMED_ATTRIBUTE_INPUT,
}
}
1 change: 1 addition & 0 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
@@ -320,6 +320,7 @@ language_item_table! {
FnMutTraitLangItem, "fn_mut", fn_mut_trait, Target::Trait;
FnOnceTraitLangItem, "fn_once", fn_once_trait, Target::Trait;

FutureTraitLangItem, "future_trait", future_trait, Target::Trait;
GeneratorStateLangItem, "generator_state", gen_state, Target::Enum;
GeneratorTraitLangItem, "generator", gen_trait, Target::Trait;
UnpinTraitLangItem, "unpin", unpin_trait, Target::Trait;
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -234,7 +234,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
return;
}
// Effectively no-ops
"uninit" | "forget" => {
"forget" => {
return;
}
"needs_drop" => {
71 changes: 47 additions & 24 deletions src/librustc_codegen_ssa/back/link.rs
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ use std::fmt;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};
use std::process::{Output, Stdio};
use std::process::{Output, Stdio, ExitStatus};
use std::str;
use std::env;

@@ -510,21 +510,6 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
sess.abort_if_errors();

// Invoke the system linker
//
// Note that there's a terribly awful hack that really shouldn't be present
// in any compiler. Here an environment variable is supported to
// automatically retry the linker invocation if the linker looks like it
// segfaulted.
//
// Gee that seems odd, normally segfaults are things we want to know about!
// Unfortunately though in rust-lang/rust#38878 we're experiencing the
// linker segfaulting on Travis quite a bit which is causing quite a bit of
// pain to land PRs when they spuriously fail due to a segfault.
//
// The issue #38878 has some more debugging information on it as well, but
// this unfortunately looks like it's just a race condition in macOS's linker
// with some thread pool working in the background. It seems that no one
// currently knows a fix for this so in the meantime we're left with this...
info!("{:?}", &cmd);
let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok();
let mut prog;
@@ -567,21 +552,59 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
info!("{:?}", &cmd);
continue;
}

// Here's a terribly awful hack that really shouldn't be present in any
// compiler. Here an environment variable is supported to automatically
// retry the linker invocation if the linker looks like it segfaulted.
//
// Gee that seems odd, normally segfaults are things we want to know
// about! Unfortunately though in rust-lang/rust#38878 we're
// experiencing the linker segfaulting on Travis quite a bit which is
// causing quite a bit of pain to land PRs when they spuriously fail
// due to a segfault.
//
// The issue #38878 has some more debugging information on it as well,
// but this unfortunately looks like it's just a race condition in
// macOS's linker with some thread pool working in the background. It
// seems that no one currently knows a fix for this so in the meantime
// we're left with this...
if !retry_on_segfault || i > 3 {
break
}
let msg_segv = "clang: error: unable to execute command: Segmentation fault: 11";
let msg_bus = "clang: error: unable to execute command: Bus error: 10";
if !(out.contains(msg_segv) || out.contains(msg_bus)) {
break
if out.contains(msg_segv) || out.contains(msg_bus) {
warn!(
"looks like the linker segfaulted when we tried to call it, \
automatically retrying again. cmd = {:?}, out = {}.",
cmd,
out,
);
continue;
}

warn!(
"looks like the linker segfaulted when we tried to call it, \
automatically retrying again. cmd = {:?}, out = {}.",
cmd,
out,
);
if is_illegal_instruction(&output.status) {
warn!(
"looks like the linker hit an illegal instruction when we \
tried to call it, automatically retrying again. cmd = {:?}, ]\
out = {}, status = {}.",
cmd,
out,
output.status,
);
continue;
}

#[cfg(unix)]
fn is_illegal_instruction(status: &ExitStatus) -> bool {
use std::os::unix::prelude::*;
status.signal() == Some(libc::SIGILL)
}

#[cfg(windows)]
fn is_illegal_instruction(_status: &ExitStatus) -> bool {
false
}
}

match prog {
6 changes: 0 additions & 6 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
@@ -42,7 +42,6 @@ use rustc::lint::builtin::{
INTRA_DOC_LINK_RESOLUTION_FAILURE,
MISSING_DOC_CODE_EXAMPLES,
PRIVATE_DOC_TESTS,
parser::QUESTION_MARK_MACRO_SEP,
parser::ILL_FORMED_ATTRIBUTE_INPUT,
};
use rustc::session;
@@ -404,11 +403,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
reference: "issue #50504 <https://github.com/rust-lang/rust/issues/50504>",
edition: None,
},
FutureIncompatibleInfo {
id: LintId::of(QUESTION_MARK_MACRO_SEP),
reference: "issue #48075 <https://github.com/rust-lang/rust/issues/48075>",
edition: Some(Edition::Edition2018),
},
FutureIncompatibleInfo {
id: LintId::of(MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS),
reference: "issue #52234 <https://github.com/rust-lang/rust/issues/52234>",
7 changes: 4 additions & 3 deletions src/librustc_save_analysis/lib.rs
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ use std::cell::Cell;
use std::default::Default;
use std::env;
use std::fs::File;
use std::io::BufWriter;
use std::path::{Path, PathBuf};

use syntax::ast::{self, Attribute, DUMMY_NODE_ID, NodeId, PatKind};
@@ -1025,7 +1026,7 @@ impl<'a> DumpHandler<'a> {
}
}

fn output_file(&self, ctx: &SaveContext<'_, '_>) -> (File, PathBuf) {
fn output_file(&self, ctx: &SaveContext<'_, '_>) -> (BufWriter<File>, PathBuf) {
let sess = &ctx.tcx.sess;
let file_name = match ctx.config.output_file {
Some(ref s) => PathBuf::from(s),
@@ -1059,9 +1060,9 @@ impl<'a> DumpHandler<'a> {

info!("Writing output to {}", file_name.display());

let output_file = File::create(&file_name).unwrap_or_else(
let output_file = BufWriter::new(File::create(&file_name).unwrap_or_else(
|e| sess.fatal(&format!("Could not open {}: {}", file_name.display(), e)),
);
));

(output_file, file_name)
}
1 change: 1 addition & 0 deletions src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
@@ -127,6 +127,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

self.suggest_compatible_variants(&mut err, expr, expected, expr_ty);
self.suggest_ref_or_into(&mut err, expr, expected, expr_ty);
self.suggest_missing_await(&mut err, expr, expected, expr_ty);

(expected, Some(err))
}
20 changes: 16 additions & 4 deletions src/librustc_typeck/check/expr.rs
Original file line number Diff line number Diff line change
@@ -295,8 +295,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ExprKind::Index(ref base, ref idx) => {
self.check_expr_index(base, idx, needs, expr)
}
ExprKind::Yield(ref value, _) => {
self.check_expr_yield(value, expr)
ExprKind::Yield(ref value, ref src) => {
self.check_expr_yield(value, expr, src)
}
hir::ExprKind::Err => {
tcx.types.err
@@ -1541,12 +1541,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

fn check_expr_yield(&self, value: &'tcx hir::Expr, expr: &'tcx hir::Expr) -> Ty<'tcx> {
fn check_expr_yield(
&self,
value: &'tcx hir::Expr,
expr: &'tcx hir::Expr,
src: &'tcx hir::YieldSource
) -> Ty<'tcx> {
match self.yield_ty {
Some(ty) => {
self.check_expr_coercable_to_type(&value, ty);
}
None => {
// Given that this `yield` expression was generated as a result of lowering a `.await`,
// we know that the yield type must be `()`; however, the context won't contain this
// information. Hence, we check the source of the yield expression here and check its
// value's type against `()` (this check should always hold).
None if src == &hir::YieldSource::Await => {
self.check_expr_coercable_to_type(&value, self.tcx.mk_unit());
}
_ => {
struct_span_err!(self.tcx.sess, expr.span, E0627,
"yield statement outside of generator literal").emit();
}
1 change: 0 additions & 1 deletion src/librustc_typeck/check/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -145,7 +145,6 @@ pub fn check_intrinsic_type<'tcx>(tcx: TyCtxt<'tcx>, it: &hir::ForeignItem) {
"rustc_peek" => (1, vec![param(0)], param(0)),
"panic_if_uninhabited" => (1, Vec::new(), tcx.mk_unit()),
"init" => (1, Vec::new(), param(0)),
"uninit" => (1, Vec::new(), param(0)),
"forget" => (1, vec![param(0)], tcx.mk_unit()),
"transmute" => (2, vec![ param(0) ], param(1)),
"move_val_init" => {
66 changes: 66 additions & 0 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -3932,6 +3932,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

/// A possible error is to forget to add `.await` when using futures:
///
/// ```
/// #![feature(async_await)]
///
/// async fn make_u32() -> u32 {
/// 22
/// }
///
/// fn take_u32(x: u32) {}
///
/// async fn foo() {
/// let x = make_u32();
/// take_u32(x);
/// }
/// ```
///
/// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
/// expected type. If this is the case, and we are inside of an async body, it suggests adding
/// `.await` to the tail of the expression.
fn suggest_missing_await(
&self,
err: &mut DiagnosticBuilder<'tcx>,
expr: &hir::Expr,
expected: Ty<'tcx>,
found: Ty<'tcx>,
) {
// `.await` is not permitted outside of `async` bodies, so don't bother to suggest if the
// body isn't `async`.
let item_id = self.tcx().hir().get_parent_node(self.body_id);
if let Some(body_id) = self.tcx().hir().maybe_body_owned_by(item_id) {
let body = self.tcx().hir().body(body_id);
if let Some(hir::GeneratorKind::Async) = body.generator_kind {
let sp = expr.span;
// Check for `Future` implementations by constructing a predicate to
// prove: `<T as Future>::Output == U`
let future_trait = self.tcx.lang_items().future_trait().unwrap();
let item_def_id = self.tcx.associated_items(future_trait).next().unwrap().def_id;
let predicate = ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate {
// `<T as Future>::Output`
projection_ty: ty::ProjectionTy {
// `T`
substs: self.tcx.mk_substs_trait(
found,
self.fresh_substs_for_item(sp, item_def_id)
),
// `Future::Output`
item_def_id,
},
ty: expected,
}));
let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
if self.infcx.predicate_may_hold(&obligation) {
if let Ok(code) = self.sess().source_map().span_to_snippet(sp) {
err.span_suggestion(
sp,
"consider using `.await` here",
format!("{}.await", code),
Applicability::MaybeIncorrect,
);
}
}
}
}
}

/// A common error is to add an extra semicolon:
///
/// ```
11 changes: 10 additions & 1 deletion src/libstd/io/mod.rs
Original file line number Diff line number Diff line change
@@ -506,9 +506,18 @@ pub trait Read {
///
/// No guarantees are provided about the contents of `buf` when this
/// function is called, implementations cannot rely on any property of the
/// contents of `buf` being true. It is recommended that implementations
/// contents of `buf` being true. It is recommended that *implementations*
/// only write data to `buf` instead of reading its contents.
///
/// Correspondingly, however, *callers* of this method may not assume any guarantees
/// about how the implementation uses `buf`. The trait is safe to implement,
// so it is possible that the code that's supposed to write to the buffer might also read
// from it. It is your responsibility to make sure that `buf` is initialized
/// before calling `read`. Calling `read` with an uninitialized `buf` (of the kind one
/// obtains via [`MaybeUninit<T>`]) is not safe, and can lead to undefined behavior.
///
/// [`MaybeUninit<T>`]: ../mem/union.MaybeUninit.html
///
/// # Errors
///
/// If this function encounters any form of I/O or other error, an error
1 change: 0 additions & 1 deletion src/libstd/lib.rs
Original file line number Diff line number Diff line change
@@ -262,7 +262,6 @@
#![feature(exhaustive_patterns)]
#![feature(external_doc)]
#![feature(fn_traits)]
#![feature(fnbox)]
#![feature(generator_trait)]
#![feature(hash_raw_entry)]
#![feature(hashmap_internals)]
2 changes: 0 additions & 2 deletions src/libsyntax/early_buffered_lints.rs
Original file line number Diff line number Diff line change
@@ -9,8 +9,6 @@ use syntax_pos::MultiSpan;
/// Since we cannot import `LintId`s from `rustc::lint`, we define some Ids here which can later be
/// passed to `rustc::lint::Lint::from_parser_lint_id` to get a `rustc::lint::Lint`.
pub enum BufferedEarlyLintId {
/// Usage of `?` as a macro separator is deprecated.
QuestionMarkMacroSep,
IllFormedAttributeInput,
}

2 changes: 1 addition & 1 deletion src/libsyntax/parse/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -942,7 +942,7 @@ impl<'a> Parser<'a> {
// {foo(bar {}}
// - ^
// | |
// | help: `)` may belong here (FIXME: #58270)
// | help: `)` may belong here
// |
// unclosed delimiter
if let Some(sp) = unmatched.unclosed_span {
260 changes: 121 additions & 139 deletions src/libsyntax/parse/lexer/mod.rs

Large diffs are not rendered by default.

13 changes: 0 additions & 13 deletions src/test/run-pass/intrinsics/intrinsic-uninit.rs

This file was deleted.

13 changes: 0 additions & 13 deletions src/test/run-pass/unsized-locals/fnbox-compat.rs

This file was deleted.

59 changes: 59 additions & 0 deletions src/test/ui/async-await/async-fn-nonsend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// compile-fail
// edition:2018
// compile-flags: --crate-type lib

#![feature(async_await)]

use std::{
cell::RefCell,
fmt::Debug,
rc::Rc,
};

fn non_sync() -> impl Debug { RefCell::new(()) }

fn non_send() -> impl Debug { Rc::new(()) }

fn take_ref<T>(_: &T) {}

async fn fut() {}

async fn fut_arg<T>(_: T) {}

async fn local_dropped_before_await() {
// FIXME: it'd be nice for this to be allowed in a `Send` `async fn`
let x = non_send();
drop(x);
fut().await;
}

async fn non_send_temporary_in_match() {
// We could theoretically make this work as well (produce a `Send` future)
// for scrutinees / temporaries that can or will
// be dropped prior to the match body
// (e.g. `Copy` types).
match Some(non_send()) {
Some(_) => fut().await,
None => {}
}
}

async fn non_sync_with_method_call() {
// FIXME: it'd be nice for this to work.
let f: &mut std::fmt::Formatter = panic!();
if non_sync().fmt(f).unwrap() == () {
fut().await;
}
}

fn assert_send(_: impl Send) {}

pub fn pass_assert() {
assert_send(local_dropped_before_await());
//~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely
assert_send(non_send_temporary_in_match());
//~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely
assert_send(non_sync_with_method_call());
//~^ ERROR `dyn std::fmt::Write` cannot be sent between threads safely
//~^^ ERROR `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
}
87 changes: 87 additions & 0 deletions src/test/ui/async-await/async-fn-nonsend.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
--> $DIR/async-fn-nonsend.rs:52:5
|
LL | assert_send(local_dropped_before_await());
| ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
|
= help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>`
= note: required because it appears within the type `impl std::fmt::Debug`
= note: required because it appears within the type `{impl std::fmt::Debug, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:23:39: 28:2 {impl std::fmt::Debug, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:23:39: 28:2 {impl std::fmt::Debug, impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
note: required by `assert_send`
--> $DIR/async-fn-nonsend.rs:49:1
|
LL | fn assert_send(_: impl Send) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
--> $DIR/async-fn-nonsend.rs:54:5
|
LL | assert_send(non_send_temporary_in_match());
| ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
|
= help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>`
= note: required because it appears within the type `impl std::fmt::Debug`
= note: required because it appears within the type `{fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:30:40: 39:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:30:40: 39:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
note: required by `assert_send`
--> $DIR/async-fn-nonsend.rs:49:1
|
LL | fn assert_send(_: impl Send) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely
--> $DIR/async-fn-nonsend.rs:56:5
|
LL | assert_send(non_sync_with_method_call());
| ^^^^^^^^^^^ `dyn std::fmt::Write` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `dyn std::fmt::Write`
= note: required because of the requirements on the impl of `std::marker::Send` for `&mut dyn std::fmt::Write`
= note: required because it appears within the type `std::fmt::Formatter<'_>`
= note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>`
= note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
note: required by `assert_send`
--> $DIR/async-fn-nonsend.rs:49:1
|
LL | fn assert_send(_: impl Send) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
--> $DIR/async-fn-nonsend.rs:56:5
|
LL | assert_send(non_sync_with_method_call());
| ^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
|
= help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
= note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>`
= note: required because it appears within the type `core::fmt::Void`
= note: required because it appears within the type `&core::fmt::Void`
= note: required because it appears within the type `std::fmt::ArgumentV1<'_>`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::slice::Iter<'_, std::fmt::ArgumentV1<'_>>`
= note: required because it appears within the type `std::fmt::Formatter<'_>`
= note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>`
= note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
note: required by `assert_send`
--> $DIR/async-fn-nonsend.rs:49:1
|
LL | fn assert_send(_: impl Send) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0277`.
59 changes: 59 additions & 0 deletions src/test/ui/async-await/async-fn-send-uses-nonsend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// compile-pass
// edition:2018
// compile-flags: --crate-type lib

#![feature(async_await)]

use std::{
cell::RefCell,
fmt::Debug,
rc::Rc,
};

fn non_sync() -> impl Debug { RefCell::new(()) }

fn non_send() -> impl Debug { Rc::new(()) }

fn take_ref<T>(_: &T) {}

async fn fut() {}

async fn fut_arg<T>(_: T) {}

async fn still_send() {
fut().await;
println!("{:?} {:?}", non_send(), non_sync());
fut().await;
drop(non_send());
drop(non_sync());
fut().await;
fut_arg(non_sync()).await;

// Note: all temporaries in `if let` and `match` scrutinee
// are dropped at the *end* of the blocks, so using `non_send()`
// in either of those positions with an await in the middle will
// cause a `!Send` future. It might be nice in the future to allow
// this for `Copy` types, since they can be "dropped" early without
// affecting the end user.
if let Some(_) = Some(non_sync()) {
fut().await;
}
match Some(non_sync()) {
Some(_) => fut().await,
None => fut().await,
}

let _ = non_send();
fut().await;

{
let _x = non_send();
}
fut().await;
}

fn assert_send(_: impl Send) {}

pub fn pass_assert() {
assert_send(still_send());
}
21 changes: 21 additions & 0 deletions src/test/ui/async-await/dont-suggest-missing-await.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// edition:2018

// This test ensures we don't make the suggestion in bodies that aren't `async`.

#![feature(async_await)]

fn take_u32(x: u32) {}

async fn make_u32() -> u32 {
22
}

async fn dont_suggest_await_in_closure() {
|| {
let x = make_u32();
take_u32(x)
//~^ ERROR mismatched types [E0308]
};
}

fn main() {}
12 changes: 12 additions & 0 deletions src/test/ui/async-await/dont-suggest-missing-await.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0308]: mismatched types
--> $DIR/dont-suggest-missing-await.rs:16:18
|
LL | take_u32(x)
| ^ expected u32, found opaque type
|
= note: expected type `u32`
found type `impl std::future::Future`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
90 changes: 90 additions & 0 deletions src/test/ui/async-await/generics-and-bounds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// compile-pass
// edition:2018
// compile-flags: --crate-type lib

#![feature(async_await)]

use std::future::Future;

pub async fn simple_generic<T>() {}

pub trait Foo {
fn foo(&self) {}
}

struct FooType;
impl Foo for FooType {}

pub async fn call_generic_bound<F: Foo>(f: F) {
f.foo()
}

pub async fn call_where_clause<F>(f: F)
where
F: Foo,
{
f.foo()
}

pub async fn call_impl_trait(f: impl Foo) {
f.foo()
}

pub async fn call_with_ref(f: &impl Foo) {
f.foo()
}

pub fn async_fn_with_same_generic_params_unifies() {
let mut a = call_generic_bound(FooType);
a = call_generic_bound(FooType);

let mut b = call_where_clause(FooType);
b = call_where_clause(FooType);

let mut c = call_impl_trait(FooType);
c = call_impl_trait(FooType);

let f_one = FooType;
let f_two = FooType;
let mut d = call_with_ref(&f_one);
d = call_with_ref(&f_two);
}

pub fn simple_generic_block<T>() -> impl Future<Output = ()> {
async move {}
}

pub fn call_generic_bound_block<F: Foo>(f: F) -> impl Future<Output = ()> {
async move { f.foo() }
}

pub fn call_where_clause_block<F>(f: F) -> impl Future<Output = ()>
where
F: Foo,
{
async move { f.foo() }
}

pub fn call_impl_trait_block(f: impl Foo) -> impl Future<Output = ()> {
async move { f.foo() }
}

pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future<Output = ()> + 'a {
async move { f.foo() }
}

pub fn async_block_with_same_generic_params_unifies() {
let mut a = call_generic_bound_block(FooType);
a = call_generic_bound_block(FooType);

let mut b = call_where_clause_block(FooType);
b = call_where_clause_block(FooType);

let mut c = call_impl_trait_block(FooType);
c = call_impl_trait_block(FooType);

let f_one = FooType;
let f_two = FooType;
let mut d = call_with_ref_block(&f_one);
d = call_with_ref_block(&f_two);
}
3 changes: 2 additions & 1 deletion src/test/ui/async-await/issues/issue-51719.rs
Original file line number Diff line number Diff line change
@@ -7,7 +7,8 @@
async fn foo() {}

fn make_generator() {
let _gen = || foo.await; //~ ERROR `await` is only allowed inside `async` functions and blocks
let _gen = || foo().await;
//~^ ERROR `await` is only allowed inside `async` functions and blocks
}

fn main() {}
4 changes: 2 additions & 2 deletions src/test/ui/async-await/issues/issue-51719.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-51719.rs:10:19
|
LL | let _gen = || foo.await;
| -- ^^^^^^^^^ only allowed inside `async` functions and blocks
LL | let _gen = || foo().await;
| -- ^^^^^^^^^^^ only allowed inside `async` functions and blocks
| |
| this is not `async`

21 changes: 21 additions & 0 deletions src/test/ui/async-await/issues/issue-61986.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// compile-pass
// edition:2018
//
// Tests that we properly handle StorageDead/StorageLives for temporaries
// created in async loop bodies.

#![feature(async_await)]

async fn bar() -> Option<()> {
Some(())
}

async fn listen() {
while let Some(_) = bar().await {
String::new();
}
}

fn main() {
listen();
}
19 changes: 19 additions & 0 deletions src/test/ui/async-await/issues/issue-62009.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// edition:2018

#![feature(async_await)]

async fn print_dur() {}

fn main() {
async { let (); }.await;
//~^ ERROR `await` is only allowed inside `async` functions and blocks
async {
//~^ ERROR `await` is only allowed inside `async` functions and blocks
let task1 = print_dur().await;
}.await;
(async || 2333)().await;
//~^ ERROR `await` is only allowed inside `async` functions and blocks
(|_| 2333).await;
//~^ ERROR `await` is only allowed inside `async` functions and blocks
//~^^ ERROR
}
49 changes: 49 additions & 0 deletions src/test/ui/async-await/issues/issue-62009.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009.rs:8:5
|
LL | fn main() {
| ---- this is not `async`
LL | async { let (); }.await;
| ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks

error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009.rs:10:5
|
LL | fn main() {
| ---- this is not `async`
...
LL | / async {
LL | |
LL | | let task1 = print_dur().await;
LL | | }.await;
| |___________^ only allowed inside `async` functions and blocks

error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009.rs:14:5
|
LL | fn main() {
| ---- this is not `async`
...
LL | (async || 2333)().await;
| ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks

error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009.rs:16:5
|
LL | fn main() {
| ---- this is not `async`
...
LL | (|_| 2333).await;
| ^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks

error[E0277]: the trait bound `[closure@$DIR/issue-62009.rs:16:5: 16:15]: std::future::Future` is not satisfied
--> $DIR/issue-62009.rs:16:5
|
LL | (|_| 2333).await;
| ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009.rs:16:5: 16:15]`
|
= note: required by `std::future::poll_with_tls_context`

error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0277`.
8 changes: 8 additions & 0 deletions src/test/ui/async-await/no-async-const.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// compile-fail
// edition:2018
// compile-flags: --crate-type lib

#![feature(async_await)]

pub async const fn x() {}
//~^ ERROR expected one of `fn` or `unsafe`, found `const`
8 changes: 8 additions & 0 deletions src/test/ui/async-await/no-async-const.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: expected one of `fn` or `unsafe`, found `const`
--> $DIR/no-async-const.rs:7:11
|
LL | pub async const fn x() {}
| ^^^^^ expected one of `fn` or `unsafe` here

error: aborting due to previous error

9 changes: 9 additions & 0 deletions src/test/ui/async-await/no-const-async.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// compile-fail
// edition:2018
// compile-flags: --crate-type lib

#![feature(async_await)]

pub const async fn x() {}
//~^ ERROR expected identifier, found reserved keyword `async`
//~^^ expected `:`, found keyword `fn`
18 changes: 18 additions & 0 deletions src/test/ui/async-await/no-const-async.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error: expected identifier, found reserved keyword `async`
--> $DIR/no-const-async.rs:7:11
|
LL | pub const async fn x() {}
| ^^^^^ expected identifier, found reserved keyword
help: you can escape reserved keywords to use them as identifiers
|
LL | pub const r#async fn x() {}
| ^^^^^^^

error: expected `:`, found keyword `fn`
--> $DIR/no-const-async.rs:7:17
|
LL | pub const async fn x() {}
| ^^ expected `:`

error: aborting due to 2 previous errors

32 changes: 32 additions & 0 deletions src/test/ui/async-await/suggest-missing-await.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// edition:2018
// run-rustfix

#![feature(async_await)]

fn take_u32(_x: u32) {}

async fn make_u32() -> u32 {
22
}

#[allow(unused)]
async fn suggest_await_in_async_fn() {
let x = make_u32();
take_u32(x.await)
//~^ ERROR mismatched types [E0308]
//~| HELP consider using `.await` here
//~| SUGGESTION x.await
}

#[allow(unused)]
async fn suggest_await_in_async_closure() {
async || {
let x = make_u32();
take_u32(x.await)
//~^ ERROR mismatched types [E0308]
//~| HELP consider using `.await` here
//~| SUGGESTION x.await
};
}

fn main() {}
32 changes: 32 additions & 0 deletions src/test/ui/async-await/suggest-missing-await.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// edition:2018
// run-rustfix

#![feature(async_await)]

fn take_u32(_x: u32) {}

async fn make_u32() -> u32 {
22
}

#[allow(unused)]
async fn suggest_await_in_async_fn() {
let x = make_u32();
take_u32(x)
//~^ ERROR mismatched types [E0308]
//~| HELP consider using `.await` here
//~| SUGGESTION x.await
}

#[allow(unused)]
async fn suggest_await_in_async_closure() {
async || {
let x = make_u32();
take_u32(x)
//~^ ERROR mismatched types [E0308]
//~| HELP consider using `.await` here
//~| SUGGESTION x.await
};
}

fn main() {}
27 changes: 27 additions & 0 deletions src/test/ui/async-await/suggest-missing-await.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
error[E0308]: mismatched types
--> $DIR/suggest-missing-await.rs:15:14
|
LL | take_u32(x)
| ^
| |
| expected u32, found opaque type
| help: consider using `.await` here: `x.await`
|
= note: expected type `u32`
found type `impl std::future::Future`

error[E0308]: mismatched types
--> $DIR/suggest-missing-await.rs:25:18
|
LL | take_u32(x)
| ^
| |
| expected u32, found opaque type
| help: consider using `.await` here: `x.await`
|
= note: expected type `u32`
found type `impl std::future::Future`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0308`.
1 change: 1 addition & 0 deletions src/test/ui/init-unsafe.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(deprecated)]
#![feature(core_intrinsics)]

use std::intrinsics::{init};
2 changes: 1 addition & 1 deletion src/test/ui/init-unsafe.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/init-unsafe.rs:7:17
--> $DIR/init-unsafe.rs:8:17
|
LL | let stuff = init::<isize>();
| ^^^^^^^^^^^^^^^ call to unsafe function
2 changes: 1 addition & 1 deletion src/tools/rls
Submodule rls updated from 3e5196 to 597c9b