Auto merge of #60224 - Centril:rollup-lfuhhsk, r=Centril
Rollup of 5 pull requests Successful merges: - #56278 (Future-proof MIR for dedicated debuginfo.) - #59739 (Stabilize futures_api) - #59822 (Fix dark css rule) - #60186 (Temporarily accept [i|u][32|size] suffixes on a tuple index and warn) - #60190 (Don't generate unnecessary rmeta files.) Failed merges: r? @ghost
This commit is contained in:
commit
8a44125f55
77 changed files with 568 additions and 355 deletions
|
@ -911,7 +911,7 @@ impl<G: ?Sized + Generator> Generator for Pin<Box<G>> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "futures_api", issue = "50547")]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl<F: ?Sized + Future + Unpin> Future for Box<F> {
|
||||
type Output = F::Output;
|
||||
|
||||
|
|
|
@ -85,7 +85,6 @@
|
|||
#![feature(fmt_internals)]
|
||||
#![feature(fn_traits)]
|
||||
#![feature(fundamental)]
|
||||
#![feature(futures_api)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(libc)]
|
||||
#![feature(needs_allocator)]
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#![unstable(feature = "futures_api",
|
||||
reason = "futures in libcore are unstable",
|
||||
issue = "50547")]
|
||||
#![stable(feature = "futures_api", since = "1.36.0")]
|
||||
|
||||
use crate::marker::Unpin;
|
||||
use crate::ops;
|
||||
|
@ -26,8 +24,10 @@ use crate::task::{Context, Poll};
|
|||
/// `await!` the value.
|
||||
#[doc(spotlight)]
|
||||
#[must_use = "futures do nothing unless polled"]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub trait Future {
|
||||
/// The type of value produced on completion.
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
type Output;
|
||||
|
||||
/// Attempt to resolve the future to a final value, registering
|
||||
|
@ -92,9 +92,11 @@ pub trait Future {
|
|||
/// [`Context`]: ../task/struct.Context.html
|
||||
/// [`Waker`]: ../task/struct.Waker.html
|
||||
/// [`Waker::wake`]: ../task/struct.Waker.html#method.wake
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl<F: ?Sized + Future + Unpin> Future for &mut F {
|
||||
type Output = F::Output;
|
||||
|
||||
|
@ -103,6 +105,7 @@ impl<F: ?Sized + Future + Unpin> Future for &mut F {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl<P> Future for Pin<P>
|
||||
where
|
||||
P: Unpin + ops::DerefMut,
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#![unstable(feature = "futures_api",
|
||||
reason = "futures in libcore are unstable",
|
||||
issue = "50547")]
|
||||
#![stable(feature = "futures_api", since = "1.36.0")]
|
||||
|
||||
//! Asynchronous values.
|
||||
|
||||
mod future;
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub use self::future::Future;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#![unstable(feature = "futures_api",
|
||||
reason = "futures in libcore are unstable",
|
||||
issue = "50547")]
|
||||
#![stable(feature = "futures_api", since = "1.36.0")]
|
||||
|
||||
//! Types and Traits for working with asynchronous tasks.
|
||||
|
||||
mod poll;
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub use self::poll::Poll;
|
||||
|
||||
mod wake;
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub use self::wake::{Context, Waker, RawWaker, RawWakerVTable};
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#![unstable(feature = "futures_api",
|
||||
reason = "futures in libcore are unstable",
|
||||
issue = "50547")]
|
||||
#![stable(feature = "futures_api", since = "1.36.0")]
|
||||
|
||||
use crate::ops::Try;
|
||||
use crate::result::Result;
|
||||
|
@ -9,20 +7,27 @@ use crate::result::Result;
|
|||
/// scheduled to receive a wakeup instead.
|
||||
#[must_use = "this `Poll` may be a `Pending` variant, which should be handled"]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub enum Poll<T> {
|
||||
/// Represents that a value is immediately ready.
|
||||
Ready(T),
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
Ready(
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
T
|
||||
),
|
||||
|
||||
/// Represents that a value is not ready yet.
|
||||
///
|
||||
/// When a function returns `Pending`, the function *must* also
|
||||
/// ensure that the current task is scheduled to be awoken when
|
||||
/// progress can be made.
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
Pending,
|
||||
}
|
||||
|
||||
impl<T> Poll<T> {
|
||||
/// Changes the ready value of this `Poll` with the closure provided.
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub fn map<U, F>(self, f: F) -> Poll<U>
|
||||
where F: FnOnce(T) -> U
|
||||
{
|
||||
|
@ -34,6 +39,7 @@ impl<T> Poll<T> {
|
|||
|
||||
/// Returns `true` if this is `Poll::Ready`
|
||||
#[inline]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub fn is_ready(&self) -> bool {
|
||||
match *self {
|
||||
Poll::Ready(_) => true,
|
||||
|
@ -43,6 +49,7 @@ impl<T> Poll<T> {
|
|||
|
||||
/// Returns `true` if this is `Poll::Pending`
|
||||
#[inline]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub fn is_pending(&self) -> bool {
|
||||
!self.is_ready()
|
||||
}
|
||||
|
@ -50,6 +57,7 @@ impl<T> Poll<T> {
|
|||
|
||||
impl<T, E> Poll<Result<T, E>> {
|
||||
/// Changes the success value of this `Poll` with the closure provided.
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
|
||||
where F: FnOnce(T) -> U
|
||||
{
|
||||
|
@ -61,6 +69,7 @@ impl<T, E> Poll<Result<T, E>> {
|
|||
}
|
||||
|
||||
/// Changes the error value of this `Poll` with the closure provided.
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
|
||||
where F: FnOnce(E) -> U
|
||||
{
|
||||
|
@ -72,12 +81,14 @@ impl<T, E> Poll<Result<T, E>> {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl<T> From<T> for Poll<T> {
|
||||
fn from(t: T) -> Poll<T> {
|
||||
Poll::Ready(t)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl<T, E> Try for Poll<Result<T, E>> {
|
||||
type Ok = Poll<T>;
|
||||
type Error = E;
|
||||
|
@ -102,6 +113,7 @@ impl<T, E> Try for Poll<Result<T, E>> {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl<T, E> Try for Poll<Option<Result<T, E>>> {
|
||||
type Ok = Poll<Option<T>>;
|
||||
type Error = E;
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#![unstable(feature = "futures_api",
|
||||
reason = "futures in libcore are unstable",
|
||||
issue = "50547")]
|
||||
#![stable(feature = "futures_api", since = "1.36.0")]
|
||||
|
||||
use crate::fmt;
|
||||
use crate::marker::{PhantomData, Unpin};
|
||||
|
@ -13,6 +11,7 @@ use crate::marker::{PhantomData, Unpin};
|
|||
/// It consists of a data pointer and a [virtual function pointer table (vtable)][vtable] that
|
||||
/// customizes the behavior of the `RawWaker`.
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub struct RawWaker {
|
||||
/// A data pointer, which can be used to store arbitrary data as required
|
||||
/// by the executor. This could be e.g. a type-erased pointer to an `Arc`
|
||||
|
@ -37,9 +36,7 @@ impl RawWaker {
|
|||
/// from a `RawWaker`. For each operation on the `Waker`, the associated
|
||||
/// function in the `vtable` of the underlying `RawWaker` will be called.
|
||||
#[rustc_promotable]
|
||||
#[unstable(feature = "futures_api",
|
||||
reason = "futures in libcore are unstable",
|
||||
issue = "50547")]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker {
|
||||
RawWaker {
|
||||
data,
|
||||
|
@ -58,6 +55,7 @@ impl RawWaker {
|
|||
/// pointer of a properly constructed [`RawWaker`] object from inside the
|
||||
/// [`RawWaker`] implementation. Calling one of the contained functions using
|
||||
/// any other `data` pointer will cause undefined behavior.
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
#[derive(PartialEq, Copy, Clone, Debug)]
|
||||
pub struct RawWakerVTable {
|
||||
/// This function will be called when the [`RawWaker`] gets cloned, e.g. when
|
||||
|
@ -131,9 +129,14 @@ impl RawWakerVTable {
|
|||
/// resources that are associated with this instance of a [`RawWaker`] and
|
||||
/// associated task.
|
||||
#[rustc_promotable]
|
||||
#[unstable(feature = "futures_api",
|
||||
reason = "futures in libcore are unstable",
|
||||
issue = "50547")]
|
||||
#[cfg_attr(stage0, unstable(feature = "futures_api_const_fn_ptr", issue = "50547"))]
|
||||
#[cfg_attr(not(stage0), stable(feature = "futures_api", since = "1.36.0"))]
|
||||
// `rustc_allow_const_fn_ptr` is a hack that should not be used anywhere else
|
||||
// without first consulting with T-Lang.
|
||||
//
|
||||
// FIXME: remove whenever we have a stable way to accept fn pointers from const fn
|
||||
// (see https://github.com/rust-rfcs/const-eval/issues/19#issuecomment-472799062)
|
||||
#[cfg_attr(not(stage0), rustc_allow_const_fn_ptr)]
|
||||
pub const fn new(
|
||||
clone: unsafe fn(*const ()) -> RawWaker,
|
||||
wake: unsafe fn(*const ()),
|
||||
|
@ -153,6 +156,7 @@ impl RawWakerVTable {
|
|||
///
|
||||
/// Currently, `Context` only serves to provide access to a `&Waker`
|
||||
/// which can be used to wake the current task.
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub struct Context<'a> {
|
||||
waker: &'a Waker,
|
||||
// Ensure we future-proof against variance changes by forcing
|
||||
|
@ -164,6 +168,7 @@ pub struct Context<'a> {
|
|||
|
||||
impl<'a> Context<'a> {
|
||||
/// Create a new `Context` from a `&Waker`.
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
#[inline]
|
||||
pub fn from_waker(waker: &'a Waker) -> Self {
|
||||
Context {
|
||||
|
@ -173,12 +178,14 @@ impl<'a> Context<'a> {
|
|||
}
|
||||
|
||||
/// Returns a reference to the `Waker` for the current task.
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
#[inline]
|
||||
pub fn waker(&self) -> &'a Waker {
|
||||
&self.waker
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl fmt::Debug for Context<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Context")
|
||||
|
@ -195,17 +202,22 @@ impl fmt::Debug for Context<'_> {
|
|||
///
|
||||
/// Implements [`Clone`], [`Send`], and [`Sync`].
|
||||
#[repr(transparent)]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub struct Waker {
|
||||
waker: RawWaker,
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl Unpin for Waker {}
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
unsafe impl Send for Waker {}
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
unsafe impl Sync for Waker {}
|
||||
|
||||
impl Waker {
|
||||
/// Wake up the task associated with this `Waker`.
|
||||
#[inline]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub fn wake(self) {
|
||||
// The actual wakeup call is delegated through a virtual function call
|
||||
// to the implementation which is defined by the executor.
|
||||
|
@ -227,6 +239,7 @@ impl Waker {
|
|||
/// where an owned `Waker` is available. This method should be preferred to
|
||||
/// calling `waker.clone().wake()`.
|
||||
#[inline]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub fn wake_by_ref(&self) {
|
||||
// The actual wakeup call is delegated through a virtual function call
|
||||
// to the implementation which is defined by the executor.
|
||||
|
@ -243,6 +256,7 @@ impl Waker {
|
|||
///
|
||||
/// This function is primarily used for optimization purposes.
|
||||
#[inline]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub fn will_wake(&self, other: &Waker) -> bool {
|
||||
self.waker == other.waker
|
||||
}
|
||||
|
@ -253,6 +267,7 @@ impl Waker {
|
|||
/// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld.
|
||||
/// Therefore this method is unsafe.
|
||||
#[inline]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub unsafe fn from_raw(waker: RawWaker) -> Waker {
|
||||
Waker {
|
||||
waker,
|
||||
|
@ -260,6 +275,7 @@ impl Waker {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl Clone for Waker {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
|
@ -272,6 +288,7 @@ impl Clone for Waker {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl Drop for Waker {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
|
@ -282,6 +299,7 @@ impl Drop for Waker {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl fmt::Debug for Waker {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let vtable_ptr = self.waker.vtable as *const RawWakerVTable;
|
||||
|
|
|
@ -121,6 +121,7 @@ impl_stable_hash_for!(struct ::syntax::attr::Stability {
|
|||
feature,
|
||||
rustc_depr,
|
||||
promotable,
|
||||
allow_const_fn_ptr,
|
||||
const_stability
|
||||
});
|
||||
|
||||
|
|
|
@ -441,6 +441,7 @@ impl<'a, 'tcx> Index<'tcx> {
|
|||
rustc_depr: None,
|
||||
const_stability: None,
|
||||
promotable: false,
|
||||
allow_const_fn_ptr: false,
|
||||
});
|
||||
annotator.parent_stab = Some(stability);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use crate::hir::def::{CtorKind, Namespace};
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::hir::{self, HirId, InlineAsm as HirInlineAsm};
|
||||
use crate::hir::{self, InlineAsm as HirInlineAsm};
|
||||
use crate::mir::interpret::{ConstValue, InterpError, Scalar};
|
||||
use crate::mir::visit::MirVisitable;
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
|
@ -138,16 +138,20 @@ pub struct Mir<'tcx> {
|
|||
/// If this MIR was built for a constant, this will be 0.
|
||||
pub arg_count: usize,
|
||||
|
||||
/// Names and capture modes of all the closure upvars, assuming
|
||||
/// the first argument is either the closure or a reference to it.
|
||||
pub upvar_decls: Vec<UpvarDecl>,
|
||||
|
||||
/// Mark an argument local (which must be a tuple) as getting passed as
|
||||
/// its individual components at the LLVM level.
|
||||
///
|
||||
/// This is used for the "rust-call" ABI.
|
||||
pub spread_arg: Option<Local>,
|
||||
|
||||
/// Names and capture modes of all the closure upvars, assuming
|
||||
/// the first argument is either the closure or a reference to it.
|
||||
// NOTE(eddyb) This is *strictly* a temporary hack for codegen
|
||||
// debuginfo generation, and will be removed at some point.
|
||||
// Do **NOT** use it for anything else, upvar information should not be
|
||||
// in the MIR, please rely on local crate HIR or other side-channels.
|
||||
pub __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
|
||||
|
||||
/// Mark this MIR of a const context other than const functions as having converted a `&&` or
|
||||
/// `||` expression into `&` or `|` respectively. This is problematic because if we ever stop
|
||||
/// this conversion from happening and use short circuiting, we will cause the following code
|
||||
|
@ -173,7 +177,7 @@ impl<'tcx> Mir<'tcx> {
|
|||
local_decls: LocalDecls<'tcx>,
|
||||
user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
|
||||
arg_count: usize,
|
||||
upvar_decls: Vec<UpvarDecl>,
|
||||
__upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
|
||||
span: Span,
|
||||
control_flow_destroyed: Vec<(Span, String)>,
|
||||
) -> Self {
|
||||
|
@ -197,7 +201,7 @@ impl<'tcx> Mir<'tcx> {
|
|||
local_decls,
|
||||
user_type_annotations,
|
||||
arg_count,
|
||||
upvar_decls,
|
||||
__upvar_debuginfo_codegen_only_do_not_use,
|
||||
spread_arg: None,
|
||||
span,
|
||||
cache: cache::Cache::new(),
|
||||
|
@ -431,7 +435,7 @@ impl_stable_hash_for!(struct Mir<'tcx> {
|
|||
local_decls,
|
||||
user_type_annotations,
|
||||
arg_count,
|
||||
upvar_decls,
|
||||
__upvar_debuginfo_codegen_only_do_not_use,
|
||||
spread_arg,
|
||||
control_flow_destroyed,
|
||||
span,
|
||||
|
@ -983,16 +987,11 @@ impl<'tcx> LocalDecl<'tcx> {
|
|||
|
||||
/// A closure capture, with its name and mode.
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub struct UpvarDecl {
|
||||
pub struct UpvarDebuginfo {
|
||||
pub debug_name: Name,
|
||||
|
||||
/// `HirId` of the captured variable
|
||||
pub var_hir_id: ClearCrossCrate<HirId>,
|
||||
|
||||
/// If true, the capture is behind a reference.
|
||||
pub by_ref: bool,
|
||||
|
||||
pub mutability: Mutability,
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3156,7 +3155,7 @@ CloneTypeFoldableAndLiftImpls! {
|
|||
MirPhase,
|
||||
Mutability,
|
||||
SourceInfo,
|
||||
UpvarDecl,
|
||||
UpvarDebuginfo,
|
||||
FakeReadCause,
|
||||
RetagKind,
|
||||
SourceScope,
|
||||
|
@ -3178,7 +3177,7 @@ BraceStructTypeFoldableImpl! {
|
|||
local_decls,
|
||||
user_type_annotations,
|
||||
arg_count,
|
||||
upvar_decls,
|
||||
__upvar_debuginfo_codegen_only_do_not_use,
|
||||
spread_arg,
|
||||
control_flow_destroyed,
|
||||
span,
|
||||
|
|
|
@ -133,41 +133,6 @@ impl<'tcx> Place<'tcx> {
|
|||
proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
|
||||
}
|
||||
}
|
||||
|
||||
/// If this is a field projection, and the field is being projected from a closure type,
|
||||
/// then returns the index of the field being projected. Note that this closure will always
|
||||
/// be `self` in the current MIR, because that is the only time we directly access the fields
|
||||
/// of a closure type.
|
||||
pub fn is_upvar_field_projection<'cx, 'gcx>(&self, mir: &'cx Mir<'tcx>,
|
||||
tcx: &TyCtxt<'cx, 'gcx, 'tcx>) -> Option<Field> {
|
||||
let (place, by_ref) = if let Place::Projection(ref proj) = self {
|
||||
if let ProjectionElem::Deref = proj.elem {
|
||||
(&proj.base, true)
|
||||
} else {
|
||||
(self, false)
|
||||
}
|
||||
} else {
|
||||
(self, false)
|
||||
};
|
||||
|
||||
match place {
|
||||
Place::Projection(ref proj) => match proj.elem {
|
||||
ProjectionElem::Field(field, _ty) => {
|
||||
let base_ty = proj.base.ty(mir, *tcx).ty;
|
||||
|
||||
if (base_ty.is_closure() || base_ty.is_generator()) &&
|
||||
(!by_ref || mir.upvar_decls[field.index()].by_ref)
|
||||
{
|
||||
Some(field)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum RvalueInitializationState {
|
||||
|
|
|
@ -235,6 +235,8 @@ rustc_queries! {
|
|||
/// constructor function).
|
||||
query is_promotable_const_fn(_: DefId) -> bool {}
|
||||
|
||||
query const_fn_is_allowed_fn_ptr(_: DefId) -> bool {}
|
||||
|
||||
/// True if this is a foreign item (i.e., linked via `extern { ... }`).
|
||||
query is_foreign_item(_: DefId) -> bool {}
|
||||
|
||||
|
|
|
@ -95,9 +95,16 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
|
|||
}
|
||||
}
|
||||
|
||||
fn const_fn_is_allowed_fn_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
|
||||
tcx.is_const_fn(def_id) &&
|
||||
tcx.lookup_stability(def_id)
|
||||
.map(|stab| stab.allow_const_fn_ptr).unwrap_or(false)
|
||||
}
|
||||
|
||||
*providers = Providers {
|
||||
is_const_fn_raw,
|
||||
is_promotable_const_fn,
|
||||
const_fn_is_allowed_fn_ptr,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
|
|
@ -542,7 +542,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
finalize(self)
|
||||
}
|
||||
|
||||
fn debuginfo_upvar_decls_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4] {
|
||||
fn debuginfo_upvar_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4] {
|
||||
unsafe {
|
||||
[llvm::LLVMRustDIBuilderCreateOpDeref(),
|
||||
llvm::LLVMRustDIBuilderCreateOpPlusUconst(),
|
||||
|
|
|
@ -83,14 +83,16 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
|
|||
for obj in codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) {
|
||||
remove(sess, obj);
|
||||
}
|
||||
if let Some(ref obj) = codegen_results.metadata_module.object {
|
||||
remove(sess, obj);
|
||||
}
|
||||
if let Some(ref allocator) = codegen_results.allocator_module {
|
||||
if let Some(ref obj) = allocator.object {
|
||||
if let Some(ref metadata_module) = codegen_results.metadata_module {
|
||||
if let Some(ref obj) = metadata_module.object {
|
||||
remove(sess, obj);
|
||||
}
|
||||
if let Some(ref bc) = allocator.bytecode_compressed {
|
||||
}
|
||||
if let Some(ref allocator_module) = codegen_results.allocator_module {
|
||||
if let Some(ref obj) = allocator_module.object {
|
||||
remove(sess, obj);
|
||||
}
|
||||
if let Some(ref bc) = allocator_module.bytecode_compressed {
|
||||
remove(sess, bc);
|
||||
}
|
||||
}
|
||||
|
@ -1067,7 +1069,10 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
|
|||
// object file, so we link that in here.
|
||||
if crate_type == config::CrateType::Dylib ||
|
||||
crate_type == config::CrateType::ProcMacro {
|
||||
if let Some(obj) = codegen_results.metadata_module.object.as_ref() {
|
||||
let obj = codegen_results.metadata_module
|
||||
.as_ref()
|
||||
.and_then(|m| m.object.as_ref());
|
||||
if let Some(obj) = obj {
|
||||
cmd.add_object(obj);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -350,7 +350,7 @@ fn generate_lto_work<B: ExtraBackendMethods>(
|
|||
|
||||
pub struct CompiledModules {
|
||||
pub modules: Vec<CompiledModule>,
|
||||
pub metadata_module: CompiledModule,
|
||||
pub metadata_module: Option<CompiledModule>,
|
||||
pub allocator_module: Option<CompiledModule>,
|
||||
}
|
||||
|
||||
|
@ -682,8 +682,10 @@ fn produce_final_output_artifacts(sess: &Session,
|
|||
}
|
||||
|
||||
if !user_wants_bitcode {
|
||||
if let Some(ref path) = compiled_modules.metadata_module.bytecode {
|
||||
remove(sess, &path);
|
||||
if let Some(ref metadata_module) = compiled_modules.metadata_module {
|
||||
if let Some(ref path) = metadata_module.bytecode {
|
||||
remove(sess, &path);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref allocator_module) = compiled_modules.allocator_module {
|
||||
|
@ -1564,9 +1566,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
// out deterministic results.
|
||||
compiled_modules.sort_by(|a, b| a.name.cmp(&b.name));
|
||||
|
||||
let compiled_metadata_module = compiled_metadata_module
|
||||
.expect("Metadata module not compiled?");
|
||||
|
||||
Ok(CompiledModules {
|
||||
modules: compiled_modules,
|
||||
metadata_module: compiled_metadata_module,
|
||||
|
|
|
@ -25,7 +25,7 @@ use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt};
|
|||
use rustc::ty::query::Providers;
|
||||
use rustc::middle::cstore::{self, LinkagePreference};
|
||||
use rustc::util::common::{time, print_time_passes_entry};
|
||||
use rustc::session::config::{self, EntryFnType, Lto};
|
||||
use rustc::session::config::{self, CrateType, EntryFnType, Lto};
|
||||
use rustc::session::Session;
|
||||
use rustc_mir::monomorphize::item::DefPathBasedNames;
|
||||
use rustc_mir::monomorphize::Instance;
|
||||
|
@ -550,12 +550,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
});
|
||||
tcx.sess.profiler(|p| p.end_activity("codegen crate metadata"));
|
||||
|
||||
let metadata_module = ModuleCodegen {
|
||||
name: metadata_cgu_name,
|
||||
module_llvm: metadata_llvm_module,
|
||||
kind: ModuleKind::Metadata,
|
||||
};
|
||||
|
||||
// Skip crate items and just output metadata in -Z no-codegen mode.
|
||||
if tcx.sess.opts.debugging_opts.no_codegen ||
|
||||
!tcx.sess.opts.output_types.should_codegen() {
|
||||
|
@ -566,7 +560,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
rx,
|
||||
1);
|
||||
|
||||
ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
|
||||
ongoing_codegen.codegen_finished(tcx);
|
||||
|
||||
assert_and_save_dep_graph(tcx);
|
||||
|
@ -639,7 +632,24 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module);
|
||||
}
|
||||
|
||||
ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
|
||||
let needs_metadata_module = tcx.sess.crate_types.borrow().iter().any(|ct| {
|
||||
match *ct {
|
||||
CrateType::Dylib |
|
||||
CrateType::ProcMacro => true,
|
||||
CrateType::Executable |
|
||||
CrateType::Rlib |
|
||||
CrateType::Staticlib |
|
||||
CrateType::Cdylib => false,
|
||||
}
|
||||
});
|
||||
if needs_metadata_module {
|
||||
let metadata_module = ModuleCodegen {
|
||||
name: metadata_cgu_name,
|
||||
module_llvm: metadata_llvm_module,
|
||||
kind: ModuleKind::Metadata,
|
||||
};
|
||||
ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
|
||||
}
|
||||
|
||||
// We sort the codegen units by size. This way we can schedule work for LLVM
|
||||
// a bit more efficiently.
|
||||
|
|
|
@ -154,7 +154,7 @@ pub struct CodegenResults {
|
|||
pub crate_name: Symbol,
|
||||
pub modules: Vec<CompiledModule>,
|
||||
pub allocator_module: Option<CompiledModule>,
|
||||
pub metadata_module: CompiledModule,
|
||||
pub metadata_module: Option<CompiledModule>,
|
||||
pub crate_hash: Svh,
|
||||
pub metadata: rustc::middle::cstore::EncodedMetadata,
|
||||
pub windows_subsystem: Option<String>,
|
||||
|
|
|
@ -598,9 +598,10 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
tmp
|
||||
}
|
||||
};
|
||||
let upvar_debuginfo = &mir.__upvar_debuginfo_codegen_only_do_not_use;
|
||||
arg_scope.map(|scope| {
|
||||
// Is this a regular argument?
|
||||
if arg_index > 0 || mir.upvar_decls.is_empty() {
|
||||
if arg_index > 0 || upvar_debuginfo.is_empty() {
|
||||
// The Rust ABI passes indirect variables using a pointer and a manual copy, so we
|
||||
// need to insert a deref here, but the C ABI uses a pointer and a copy using the
|
||||
// byval attribute, for which LLVM always does the deref itself,
|
||||
|
@ -638,16 +639,16 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
let (def_id, upvar_substs) = match closure_layout.ty.sty {
|
||||
ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
|
||||
ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
|
||||
_ => bug!("upvar_decls with non-closure arg0 type `{}`", closure_layout.ty)
|
||||
_ => bug!("upvar debuginfo with non-closure arg0 type `{}`", closure_layout.ty)
|
||||
};
|
||||
let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
|
||||
|
||||
let extra_locals = {
|
||||
let upvars = mir.upvar_decls
|
||||
let upvars = upvar_debuginfo
|
||||
.iter()
|
||||
.zip(upvar_tys)
|
||||
.enumerate()
|
||||
.map(|(i, (decl, ty))| (i, decl.debug_name, decl.by_ref, ty));
|
||||
.map(|(i, (upvar, ty))| (i, upvar.debug_name, upvar.by_ref, ty));
|
||||
|
||||
let generator_fields = mir.generator_layout.as_ref().map(|generator_layout| {
|
||||
let (def_id, gen_substs) = match closure_layout.ty.sty {
|
||||
|
@ -656,7 +657,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
};
|
||||
let state_tys = gen_substs.state_tys(def_id, tcx);
|
||||
|
||||
let upvar_count = mir.upvar_decls.len();
|
||||
let upvar_count = upvar_debuginfo.len();
|
||||
generator_layout.fields
|
||||
.iter()
|
||||
.zip(state_tys)
|
||||
|
@ -673,7 +674,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
for (field, name, by_ref, ty) in extra_locals {
|
||||
let byte_offset_of_var_in_env = closure_layout.fields.offset(field).bytes();
|
||||
|
||||
let ops = bx.debuginfo_upvar_decls_ops_sequence(byte_offset_of_var_in_env);
|
||||
let ops = bx.debuginfo_upvar_ops_sequence(byte_offset_of_var_in_env);
|
||||
|
||||
// The environment and the capture can each be indirect.
|
||||
let mut ops = if env_ref { &ops[..] } else { &ops[1..] };
|
||||
|
|
|
@ -37,7 +37,7 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
|
|||
defining_crate: CrateNum,
|
||||
) -> Self::DIScope;
|
||||
fn debuginfo_finalize(&self);
|
||||
fn debuginfo_upvar_decls_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4];
|
||||
fn debuginfo_upvar_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4];
|
||||
}
|
||||
|
||||
pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
|
||||
|
|
|
@ -1088,7 +1088,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
| LocalKind::Temp => bug!("temporary or return pointer with a name"),
|
||||
LocalKind::Var => "local variable ",
|
||||
LocalKind::Arg
|
||||
if !self.mir.upvar_decls.is_empty()
|
||||
if !self.upvars.is_empty()
|
||||
&& local == Local::new(1) => {
|
||||
"variable captured by `move` "
|
||||
}
|
||||
|
@ -1632,11 +1632,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
match proj.elem {
|
||||
ProjectionElem::Deref => {
|
||||
let upvar_field_projection =
|
||||
place.is_upvar_field_projection(self.mir, &self.infcx.tcx);
|
||||
self.is_upvar_field_projection(place);
|
||||
if let Some(field) = upvar_field_projection {
|
||||
let var_index = field.index();
|
||||
let name = self.mir.upvar_decls[var_index].debug_name.to_string();
|
||||
if self.mir.upvar_decls[var_index].by_ref {
|
||||
let name = self.upvars[var_index].name.to_string();
|
||||
if self.upvars[var_index].by_ref {
|
||||
buf.push_str(&name);
|
||||
} else {
|
||||
buf.push_str(&format!("*{}", &name));
|
||||
|
@ -1694,10 +1694,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
autoderef = true;
|
||||
|
||||
let upvar_field_projection =
|
||||
place.is_upvar_field_projection(self.mir, &self.infcx.tcx);
|
||||
self.is_upvar_field_projection(place);
|
||||
if let Some(field) = upvar_field_projection {
|
||||
let var_index = field.index();
|
||||
let name = self.mir.upvar_decls[var_index].debug_name.to_string();
|
||||
let name = self.upvars[var_index].name.to_string();
|
||||
buf.push_str(&name);
|
||||
} else {
|
||||
let field_name = self.describe_field(&proj.base, field);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! This query borrow-checks the MIR to (further) ensure it is not broken.
|
||||
|
||||
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
|
||||
use rustc::hir;
|
||||
use rustc::hir::{self, HirId};
|
||||
use rustc::hir::Node;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::infer::InferCtxt;
|
||||
|
@ -27,6 +27,7 @@ use std::collections::BTreeMap;
|
|||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
|
||||
use syntax::ast::Name;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex};
|
||||
|
@ -63,6 +64,19 @@ mod used_muts;
|
|||
|
||||
pub(crate) mod nll;
|
||||
|
||||
// FIXME(eddyb) perhaps move this somewhere more centrally.
|
||||
#[derive(Debug)]
|
||||
crate struct Upvar {
|
||||
name: Name,
|
||||
|
||||
var_hir_id: HirId,
|
||||
|
||||
/// If true, the capture is behind a reference.
|
||||
by_ref: bool,
|
||||
|
||||
mutability: Mutability,
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers<'_>) {
|
||||
*providers = Providers {
|
||||
mir_borrowck,
|
||||
|
@ -126,6 +140,36 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
|||
.as_local_hir_id(def_id)
|
||||
.expect("do_mir_borrowck: non-local DefId");
|
||||
|
||||
// Gather the upvars of a closure, if any.
|
||||
let tables = tcx.typeck_tables_of(def_id);
|
||||
let upvars: Vec<_> = tables
|
||||
.upvar_list
|
||||
.get(&def_id)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|upvar_id| {
|
||||
let var_hir_id = upvar_id.var_path.hir_id;
|
||||
let var_node_id = tcx.hir().hir_to_node_id(var_hir_id);
|
||||
let capture = tables.upvar_capture(*upvar_id);
|
||||
let by_ref = match capture {
|
||||
ty::UpvarCapture::ByValue => false,
|
||||
ty::UpvarCapture::ByRef(..) => true,
|
||||
};
|
||||
let mut upvar = Upvar {
|
||||
name: tcx.hir().name(var_node_id),
|
||||
var_hir_id,
|
||||
by_ref,
|
||||
mutability: Mutability::Not,
|
||||
};
|
||||
let bm = *tables.pat_binding_modes().get(var_hir_id)
|
||||
.expect("missing binding mode");
|
||||
if bm == ty::BindByValue(hir::MutMutable) {
|
||||
upvar.mutability = Mutability::Mut;
|
||||
}
|
||||
upvar
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Replace all regions with fresh inference variables. This
|
||||
// requires first making our own copy of the MIR. This copy will
|
||||
// be modified (in place) to contain non-lexical lifetimes. It
|
||||
|
@ -168,6 +212,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
|||
def_id,
|
||||
free_regions,
|
||||
mir,
|
||||
&upvars,
|
||||
location_table,
|
||||
param_env,
|
||||
&mut flow_inits,
|
||||
|
@ -240,6 +285,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
|||
used_mut_upvars: SmallVec::new(),
|
||||
borrow_set,
|
||||
dominators,
|
||||
upvars,
|
||||
};
|
||||
|
||||
let mut state = Flows::new(
|
||||
|
@ -475,6 +521,9 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
|
|||
|
||||
/// Dominators for MIR
|
||||
dominators: Dominators<BasicBlock>,
|
||||
|
||||
/// Information about upvars not necessarily preserved in types or MIR
|
||||
upvars: Vec<Upvar>,
|
||||
}
|
||||
|
||||
// Check that:
|
||||
|
@ -1287,8 +1336,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
let propagate_closure_used_mut_place = |this: &mut Self, place: &Place<'tcx>| {
|
||||
match *place {
|
||||
Place::Projection { .. } => {
|
||||
if let Some(field) = place.is_upvar_field_projection(
|
||||
this.mir, &this.infcx.tcx) {
|
||||
if let Some(field) = this.is_upvar_field_projection(place) {
|
||||
this.used_mut_upvars.push(field);
|
||||
}
|
||||
}
|
||||
|
@ -2057,7 +2105,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
place: place @ Place::Projection(_),
|
||||
is_local_mutation_allowed: _,
|
||||
} => {
|
||||
if let Some(field) = place.is_upvar_field_projection(self.mir, &self.infcx.tcx) {
|
||||
if let Some(field) = self.is_upvar_field_projection(place) {
|
||||
self.used_mut_upvars.push(field);
|
||||
}
|
||||
}
|
||||
|
@ -2127,13 +2175,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
// Mutably borrowed data is mutable, but only if we have a
|
||||
// unique path to the `&mut`
|
||||
hir::MutMutable => {
|
||||
let mode = match place.is_upvar_field_projection(
|
||||
self.mir, &self.infcx.tcx)
|
||||
{
|
||||
let mode = match self.is_upvar_field_projection(place) {
|
||||
Some(field)
|
||||
if {
|
||||
self.mir.upvar_decls[field.index()].by_ref
|
||||
} =>
|
||||
if self.upvars[field.index()].by_ref =>
|
||||
{
|
||||
is_local_mutation_allowed
|
||||
}
|
||||
|
@ -2173,15 +2217,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
| ProjectionElem::ConstantIndex { .. }
|
||||
| ProjectionElem::Subslice { .. }
|
||||
| ProjectionElem::Downcast(..) => {
|
||||
let upvar_field_projection = place.is_upvar_field_projection(
|
||||
self.mir, &self.infcx.tcx);
|
||||
let upvar_field_projection = self.is_upvar_field_projection(place);
|
||||
if let Some(field) = upvar_field_projection {
|
||||
let decl = &self.mir.upvar_decls[field.index()];
|
||||
let upvar = &self.upvars[field.index()];
|
||||
debug!(
|
||||
"decl.mutability={:?} local_mutation_is_allowed={:?} place={:?}",
|
||||
decl, is_local_mutation_allowed, place
|
||||
"upvar.mutability={:?} local_mutation_is_allowed={:?} place={:?}",
|
||||
upvar, is_local_mutation_allowed, place
|
||||
);
|
||||
match (decl.mutability, is_local_mutation_allowed) {
|
||||
match (upvar.mutability, is_local_mutation_allowed) {
|
||||
(Mutability::Not, LocalMutationIsAllowed::No)
|
||||
| (Mutability::Not, LocalMutationIsAllowed::ExceptUpvars) => {
|
||||
Err(place)
|
||||
|
@ -2229,6 +2272,41 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// If `place` is a field projection, and the field is being projected from a closure type,
|
||||
/// then returns the index of the field being projected. Note that this closure will always
|
||||
/// be `self` in the current MIR, because that is the only time we directly access the fields
|
||||
/// of a closure type.
|
||||
pub fn is_upvar_field_projection(&self, place: &Place<'tcx>) -> Option<Field> {
|
||||
let (place, by_ref) = if let Place::Projection(ref proj) = place {
|
||||
if let ProjectionElem::Deref = proj.elem {
|
||||
(&proj.base, true)
|
||||
} else {
|
||||
(place, false)
|
||||
}
|
||||
} else {
|
||||
(place, false)
|
||||
};
|
||||
|
||||
match place {
|
||||
Place::Projection(ref proj) => match proj.elem {
|
||||
ProjectionElem::Field(field, _ty) => {
|
||||
let tcx = self.infcx.tcx;
|
||||
let base_ty = proj.base.ty(self.mir, tcx).ty;
|
||||
|
||||
if (base_ty.is_closure() || base_ty.is_generator()) &&
|
||||
(!by_ref || self.upvars[field.index()].by_ref)
|
||||
{
|
||||
Some(field)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
|
|
|
@ -256,7 +256,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
let origin = Origin::Mir;
|
||||
debug!("report: original_path={:?} span={:?}, kind={:?} \
|
||||
original_path.is_upvar_field_projection={:?}", original_path, span, kind,
|
||||
original_path.is_upvar_field_projection(self.mir, &self.infcx.tcx));
|
||||
self.is_upvar_field_projection(original_path));
|
||||
(
|
||||
match kind {
|
||||
IllegalMoveOriginKind::Static => {
|
||||
|
@ -269,8 +269,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
let ty = place.ty(self.mir, self.infcx.tcx).ty;
|
||||
let is_upvar_field_projection =
|
||||
self.prefixes(&original_path, PrefixSet::All)
|
||||
.any(|p| p.is_upvar_field_projection(self.mir, &self.infcx.tcx)
|
||||
.is_some());
|
||||
.any(|p| self.is_upvar_field_projection(p).is_some());
|
||||
debug!("report: ty={:?}", ty);
|
||||
match ty.sty {
|
||||
ty::Array(..) | ty::Slice(..) =>
|
||||
|
@ -278,7 +277,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
span, ty, None, origin
|
||||
),
|
||||
ty::Closure(def_id, closure_substs)
|
||||
if !self.mir.upvar_decls.is_empty() && is_upvar_field_projection
|
||||
if def_id == self.mir_def_id && is_upvar_field_projection
|
||||
=> {
|
||||
let closure_kind_ty =
|
||||
closure_substs.closure_kind_ty(def_id, self.infcx.tcx);
|
||||
|
@ -303,11 +302,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
span, place_description, origin);
|
||||
|
||||
for prefix in self.prefixes(&original_path, PrefixSet::All) {
|
||||
if let Some(field) = prefix.is_upvar_field_projection(
|
||||
self.mir, &self.infcx.tcx) {
|
||||
let upvar_decl = &self.mir.upvar_decls[field.index()];
|
||||
let upvar_hir_id =
|
||||
upvar_decl.var_hir_id.assert_crate_local();
|
||||
if let Some(field) = self.is_upvar_field_projection(prefix) {
|
||||
let upvar_hir_id = self.upvars[field.index()].var_hir_id;
|
||||
let upvar_span = self.infcx.tcx.hir().span_by_hir_id(
|
||||
upvar_hir_id);
|
||||
diag.span_label(upvar_span, "captured outer variable");
|
||||
|
|
|
@ -68,10 +68,10 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
));
|
||||
|
||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||
if access_place.is_upvar_field_projection(self.mir, &self.infcx.tcx).is_some() {
|
||||
if self.is_upvar_field_projection(access_place).is_some() {
|
||||
reason = ", as it is not declared as mutable".to_string();
|
||||
} else {
|
||||
let name = self.mir.upvar_decls[upvar_index.index()].debug_name;
|
||||
let name = self.upvars[upvar_index.index()].name;
|
||||
reason = format!(", as `{}` is not declared as mutable", name);
|
||||
}
|
||||
}
|
||||
|
@ -81,15 +81,14 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
elem: ProjectionElem::Deref,
|
||||
}) => {
|
||||
if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
|
||||
!self.mir.upvar_decls.is_empty() {
|
||||
!self.upvars.is_empty() {
|
||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||
debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr());
|
||||
debug_assert!(is_closure_or_generator(
|
||||
the_place_err.ty(self.mir, self.infcx.tcx).ty
|
||||
));
|
||||
|
||||
reason = if access_place.is_upvar_field_projection(self.mir,
|
||||
&self.infcx.tcx).is_some() {
|
||||
reason = if self.is_upvar_field_projection(access_place).is_some() {
|
||||
", as it is a captured variable in a `Fn` closure".to_string()
|
||||
} else {
|
||||
", as `Fn` closures cannot mutate their captured variables".to_string()
|
||||
|
@ -309,9 +308,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||
|
||||
let upvar_hir_id = self.mir.upvar_decls[upvar_index.index()]
|
||||
.var_hir_id
|
||||
.assert_crate_local();
|
||||
let upvar_hir_id = self.upvars[upvar_index.index()].var_hir_id;
|
||||
let upvar_node_id = self.infcx.tcx.hir().hir_to_node_id(upvar_hir_id);
|
||||
if let Some(Node::Binding(pat)) = self.infcx.tcx.hir().find(upvar_node_id) {
|
||||
if let hir::PatKind::Binding(
|
||||
|
@ -452,7 +449,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
base,
|
||||
elem: ProjectionElem::Deref,
|
||||
}) if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
|
||||
!self.mir.upvar_decls.is_empty() =>
|
||||
!self.upvars.is_empty() =>
|
||||
{
|
||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||
err.span_help(
|
||||
|
|
|
@ -273,11 +273,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
if mir.local_decls[local].name.is_some() {
|
||||
if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
|
||||
if let Place::Base(PlaceBase::Local(borrowed_local)) = place {
|
||||
let dropped_local_scope = mir.local_decls[local].visibility_scope;
|
||||
let borrowed_local_scope =
|
||||
mir.local_decls[*borrowed_local].visibility_scope;
|
||||
|
||||
if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope)
|
||||
if mir.local_decls[*borrowed_local].name.is_some()
|
||||
&& local != *borrowed_local
|
||||
{
|
||||
should_note_order = true;
|
||||
|
@ -298,6 +294,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
let (category, from_closure, span, region_name) =
|
||||
self.nonlexical_regioncx.free_region_constraint_info(
|
||||
self.mir,
|
||||
&self.upvars,
|
||||
self.mir_def_id,
|
||||
self.infcx,
|
||||
borrow_region_vid,
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::dataflow::move_paths::MoveData;
|
|||
use crate::dataflow::FlowAtLocation;
|
||||
use crate::dataflow::MaybeInitializedPlaces;
|
||||
use crate::transform::MirSource;
|
||||
use crate::borrow_check::Upvar;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir};
|
||||
|
@ -72,6 +73,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
|
|||
def_id: DefId,
|
||||
universal_regions: UniversalRegions<'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
location_table: &LocationTable,
|
||||
param_env: ty::ParamEnv<'gcx>,
|
||||
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'cx, 'gcx, 'tcx>>,
|
||||
|
@ -187,7 +189,8 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
|
|||
});
|
||||
|
||||
// Solve the region constraints.
|
||||
let closure_region_requirements = regioncx.solve(infcx, &mir, def_id, errors_buffer);
|
||||
let closure_region_requirements =
|
||||
regioncx.solve(infcx, &mir, upvars, def_id, errors_buffer);
|
||||
|
||||
// Dump MIR results into a file, if that is enabled. This let us
|
||||
// write unit-tests, as well as helping with debugging.
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::borrow_check::nll::type_check::Locations;
|
|||
use crate::borrow_check::nll::universal_regions::DefiningTy;
|
||||
use crate::borrow_check::nll::ConstraintDescription;
|
||||
use crate::util::borrowck_errors::{BorrowckErrors, Origin};
|
||||
use crate::borrow_check::Upvar;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||
use rustc::infer::InferCtxt;
|
||||
|
@ -237,6 +238,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
pub(super) fn report_error(
|
||||
&self,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
mir_def_id: DefId,
|
||||
fr: RegionVid,
|
||||
|
@ -273,6 +275,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
(ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(infcx, fr) => {
|
||||
self.report_fnmut_error(
|
||||
mir,
|
||||
upvars,
|
||||
infcx,
|
||||
mir_def_id,
|
||||
fr,
|
||||
|
@ -284,6 +287,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
(ConstraintCategory::Assignment, true, false)
|
||||
| (ConstraintCategory::CallArgument, true, false) => self.report_escaping_data_error(
|
||||
mir,
|
||||
upvars,
|
||||
infcx,
|
||||
mir_def_id,
|
||||
fr,
|
||||
|
@ -294,6 +298,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
),
|
||||
_ => self.report_general_error(
|
||||
mir,
|
||||
upvars,
|
||||
infcx,
|
||||
mir_def_id,
|
||||
fr,
|
||||
|
@ -353,6 +358,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
fn report_fnmut_error(
|
||||
&self,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
mir_def_id: DefId,
|
||||
_fr: RegionVid,
|
||||
|
@ -377,7 +383,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
|
||||
diag.span_label(span, message);
|
||||
|
||||
match self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, &mut 1).unwrap().source {
|
||||
match self.give_region_a_name(infcx, mir, upvars, mir_def_id, outlived_fr, &mut 1)
|
||||
.unwrap().source
|
||||
{
|
||||
RegionNameSource::NamedEarlyBoundRegion(fr_span)
|
||||
| RegionNameSource::NamedFreeRegion(fr_span)
|
||||
| RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
|
||||
|
@ -415,6 +423,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
fn report_escaping_data_error(
|
||||
&self,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
mir_def_id: DefId,
|
||||
fr: RegionVid,
|
||||
|
@ -423,9 +432,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
span: Span,
|
||||
errors_buffer: &mut Vec<Diagnostic>,
|
||||
) {
|
||||
let fr_name_and_span = self.get_var_name_and_span_for_region(infcx.tcx, mir, fr);
|
||||
let fr_name_and_span =
|
||||
self.get_var_name_and_span_for_region(infcx.tcx, mir, upvars, fr);
|
||||
let outlived_fr_name_and_span =
|
||||
self.get_var_name_and_span_for_region(infcx.tcx, mir, outlived_fr);
|
||||
self.get_var_name_and_span_for_region(infcx.tcx, mir, upvars, outlived_fr);
|
||||
|
||||
let escapes_from = match self.universal_regions.defining_ty {
|
||||
DefiningTy::Closure(..) => "closure",
|
||||
|
@ -442,6 +452,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
{
|
||||
return self.report_general_error(
|
||||
mir,
|
||||
upvars,
|
||||
infcx,
|
||||
mir_def_id,
|
||||
fr,
|
||||
|
@ -504,6 +515,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
fn report_general_error(
|
||||
&self,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
mir_def_id: DefId,
|
||||
fr: RegionVid,
|
||||
|
@ -520,10 +532,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
);
|
||||
|
||||
let counter = &mut 1;
|
||||
let fr_name = self.give_region_a_name(infcx, mir, mir_def_id, fr, counter).unwrap();
|
||||
let fr_name = self.give_region_a_name(infcx, mir, upvars, mir_def_id, fr, counter).unwrap();
|
||||
fr_name.highlight_region_name(&mut diag);
|
||||
let outlived_fr_name =
|
||||
self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, counter).unwrap();
|
||||
self.give_region_a_name(infcx, mir, upvars, mir_def_id, outlived_fr, counter).unwrap();
|
||||
outlived_fr_name.highlight_region_name(&mut diag);
|
||||
|
||||
let mir_def_name = if infcx.tcx.is_closure(mir_def_id) {
|
||||
|
@ -656,6 +668,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
crate fn free_region_constraint_info(
|
||||
&self,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
mir_def_id: DefId,
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
borrow_region: RegionVid,
|
||||
|
@ -664,7 +677,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
let (category, from_closure, span) =
|
||||
self.best_blame_constraint(mir, borrow_region, |r| r == outlived_region);
|
||||
let outlived_fr_name =
|
||||
self.give_region_a_name(infcx, mir, mir_def_id, outlived_region, &mut 1);
|
||||
self.give_region_a_name(infcx, mir, upvars, mir_def_id, outlived_region, &mut 1);
|
||||
(category, from_closure, span, outlived_fr_name)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::fmt::{self, Display};
|
|||
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
|
||||
use crate::borrow_check::nll::universal_regions::DefiningTy;
|
||||
use crate::borrow_check::nll::ToRegionVid;
|
||||
use crate::borrow_check::Upvar;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::infer::InferCtxt;
|
||||
|
@ -144,6 +145,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
&self,
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
mir_def_id: DefId,
|
||||
fr: RegionVid,
|
||||
counter: &mut usize,
|
||||
|
@ -160,7 +162,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
})
|
||||
.or_else(|| {
|
||||
self.give_name_if_anonymous_region_appears_in_upvars(
|
||||
infcx.tcx, mir, fr, counter,
|
||||
infcx.tcx, upvars, fr, counter,
|
||||
)
|
||||
})
|
||||
.or_else(|| {
|
||||
|
@ -639,13 +641,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
fn give_name_if_anonymous_region_appears_in_upvars(
|
||||
&self,
|
||||
tcx: TyCtxt<'_, '_, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
fr: RegionVid,
|
||||
counter: &mut usize,
|
||||
) -> Option<RegionName> {
|
||||
let upvar_index = self.get_upvar_index_for_region(tcx, fr)?;
|
||||
let (upvar_name, upvar_span) =
|
||||
self.get_upvar_name_and_span_for_region(tcx, mir, upvar_index);
|
||||
self.get_upvar_name_and_span_for_region(tcx, upvars, upvar_index);
|
||||
let region_name = self.synthesize_region_name(counter);
|
||||
|
||||
Some(RegionName {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
|
||||
use crate::borrow_check::nll::ToRegionVid;
|
||||
use crate::borrow_check::Upvar;
|
||||
use rustc::mir::{Local, Mir};
|
||||
use rustc::ty::{RegionVid, TyCtxt};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
|
@ -11,6 +12,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
&self,
|
||||
tcx: TyCtxt<'_, '_, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
fr: RegionVid,
|
||||
) -> Option<(Option<Symbol>, Span)> {
|
||||
debug!("get_var_name_and_span_for_region(fr={:?})", fr);
|
||||
|
@ -19,7 +21,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
debug!("get_var_name_and_span_for_region: attempting upvar");
|
||||
self.get_upvar_index_for_region(tcx, fr)
|
||||
.map(|index| {
|
||||
let (name, span) = self.get_upvar_name_and_span_for_region(tcx, mir, index);
|
||||
let (name, span) =
|
||||
self.get_upvar_name_and_span_for_region(tcx, upvars, index);
|
||||
(Some(name), span)
|
||||
})
|
||||
.or_else(|| {
|
||||
|
@ -67,10 +70,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
crate fn get_upvar_name_and_span_for_region(
|
||||
&self,
|
||||
tcx: TyCtxt<'_, '_, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
upvar_index: usize,
|
||||
) -> (Symbol, Span) {
|
||||
let upvar_hir_id = mir.upvar_decls[upvar_index].var_hir_id.assert_crate_local();
|
||||
let upvar_hir_id = upvars[upvar_index].var_hir_id;
|
||||
debug!("get_upvar_name_and_span_for_region: upvar_hir_id={:?}", upvar_hir_id);
|
||||
|
||||
let upvar_name = tcx.hir().name_by_hir_id(upvar_hir_id);
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::borrow_check::nll::constraints::{ConstraintSccIndex, ConstraintSet, O
|
|||
use crate::borrow_check::nll::region_infer::values::{
|
||||
PlaceholderIndices, RegionElement, ToElementIndex
|
||||
};
|
||||
use crate::borrow_check::Upvar;
|
||||
use crate::borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
|
||||
use crate::borrow_check::nll::type_check::Locations;
|
||||
use rustc::hir::def_id::DefId;
|
||||
|
@ -400,6 +401,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
mir_def_id: DefId,
|
||||
errors_buffer: &mut Vec<Diagnostic>,
|
||||
) -> Option<ClosureRegionRequirements<'gcx>> {
|
||||
|
@ -407,7 +409,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
infcx.tcx.sess.time_extended(),
|
||||
Some(infcx.tcx.sess),
|
||||
&format!("solve_nll_region_constraints({:?})", mir_def_id),
|
||||
|| self.solve_inner(infcx, mir, mir_def_id, errors_buffer),
|
||||
|| self.solve_inner(infcx, mir, upvars, mir_def_id, errors_buffer),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -415,6 +417,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
mir_def_id: DefId,
|
||||
errors_buffer: &mut Vec<Diagnostic>,
|
||||
) -> Option<ClosureRegionRequirements<'gcx>> {
|
||||
|
@ -442,6 +445,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
self.check_universal_regions(
|
||||
infcx,
|
||||
mir,
|
||||
upvars,
|
||||
mir_def_id,
|
||||
outlives_requirements.as_mut(),
|
||||
errors_buffer,
|
||||
|
@ -1102,6 +1106,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
&self,
|
||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
mir_def_id: DefId,
|
||||
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
|
||||
errors_buffer: &mut Vec<Diagnostic>,
|
||||
|
@ -1115,6 +1120,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
self.check_universal_region(
|
||||
infcx,
|
||||
mir,
|
||||
upvars,
|
||||
mir_def_id,
|
||||
fr,
|
||||
&mut propagated_outlives_requirements,
|
||||
|
@ -1145,6 +1151,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
&self,
|
||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
mir_def_id: DefId,
|
||||
longer_fr: RegionVid,
|
||||
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
|
||||
|
@ -1177,6 +1184,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
representative,
|
||||
infcx,
|
||||
mir,
|
||||
upvars,
|
||||
mir_def_id,
|
||||
propagated_outlives_requirements,
|
||||
errors_buffer,
|
||||
|
@ -1192,6 +1200,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
shorter_fr,
|
||||
infcx,
|
||||
mir,
|
||||
upvars,
|
||||
mir_def_id,
|
||||
propagated_outlives_requirements,
|
||||
errors_buffer,
|
||||
|
@ -1208,6 +1217,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
shorter_fr: RegionVid,
|
||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
mir_def_id: DefId,
|
||||
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
|
||||
errors_buffer: &mut Vec<Diagnostic>,
|
||||
|
@ -1265,7 +1275,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
//
|
||||
// Note: in this case, we use the unapproximated regions to report the
|
||||
// error. This gives better error messages in some cases.
|
||||
self.report_error(mir, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
|
||||
self.report_error(mir, upvars, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
|
||||
Some(ErrorReported)
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ impl<'tcx> DefiningTy<'tcx> {
|
|||
/// Returns a list of all the upvar types for this MIR. If this is
|
||||
/// not a closure or generator, there are no upvars, and hence it
|
||||
/// will be an empty list. The order of types in this list will
|
||||
/// match up with the `upvar_decls` field of `Mir`.
|
||||
/// match up with the upvar order in the HIR, typesystem, and MIR.
|
||||
pub fn upvar_tys(self, tcx: TyCtxt<'_, '_, 'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
|
||||
match self {
|
||||
DefiningTy::Closure(def_id, substs) => Either::Left(substs.upvar_tys(def_id, tcx)),
|
||||
|
|
|
@ -556,10 +556,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
);
|
||||
// Not in a closure
|
||||
debug_assert!(
|
||||
this.upvar_decls.len() > upvar_index.index(),
|
||||
this.upvar_mutbls.len() > upvar_index.index(),
|
||||
"Unexpected capture place"
|
||||
);
|
||||
this.upvar_decls[upvar_index.index()].mutability
|
||||
this.upvar_mutbls[upvar_index.index()]
|
||||
}
|
||||
_ => bug!("Unexpected capture place"),
|
||||
};
|
||||
|
|
|
@ -505,14 +505,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
UserTypeProjections::none(),
|
||||
&mut |this, mutability, name, mode, var, span, ty, user_ty| {
|
||||
if visibility_scope.is_none() {
|
||||
visibility_scope =
|
||||
Some(this.new_source_scope(scope_span, LintLevel::Inherited, None));
|
||||
// If we have lints, create a new source scope
|
||||
// that marks the lints for the locals. See the comment
|
||||
// on the `source_info` field for why this is needed.
|
||||
if lint_level.is_explicit() {
|
||||
scope = this.new_source_scope(scope_span, lint_level, None);
|
||||
}
|
||||
visibility_scope = Some(this.new_source_scope(scope_span,
|
||||
LintLevel::Inherited,
|
||||
None));
|
||||
}
|
||||
let source_info = SourceInfo { span, scope };
|
||||
let visibility_scope = visibility_scope.unwrap();
|
||||
|
|
|
@ -375,7 +375,8 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
|||
var_indices: HirIdMap<LocalsForNode>,
|
||||
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
|
||||
canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
|
||||
upvar_decls: Vec<UpvarDecl>,
|
||||
__upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
|
||||
upvar_mutbls: Vec<Mutability>,
|
||||
unit_temp: Option<Place<'tcx>>,
|
||||
|
||||
/// Cached block with the `RESUME` terminator; this is created
|
||||
|
@ -625,11 +626,12 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
|||
let fn_def_id = tcx_hir.local_def_id_from_hir_id(fn_id);
|
||||
|
||||
// Gather the upvars of a closure, if any.
|
||||
let mut upvar_mutbls = vec![];
|
||||
// In analyze_closure() in upvar.rs we gathered a list of upvars used by a
|
||||
// closure and we stored in a map called upvar_list in TypeckTables indexed
|
||||
// with the closure's DefId. Here, we run through that vec of UpvarIds for
|
||||
// the given closure and use the necessary information to create UpvarDecl.
|
||||
let upvar_decls: Vec<_> = hir_tables
|
||||
let upvar_debuginfo: Vec<_> = hir_tables
|
||||
.upvar_list
|
||||
.get(&fn_def_id)
|
||||
.into_iter()
|
||||
|
@ -642,27 +644,27 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
|||
ty::UpvarCapture::ByValue => false,
|
||||
ty::UpvarCapture::ByRef(..) => true,
|
||||
};
|
||||
let mut decl = UpvarDecl {
|
||||
let mut debuginfo = UpvarDebuginfo {
|
||||
debug_name: keywords::Invalid.name(),
|
||||
var_hir_id: ClearCrossCrate::Set(var_hir_id),
|
||||
by_ref,
|
||||
mutability: Mutability::Not,
|
||||
};
|
||||
let mut mutability = Mutability::Not;
|
||||
if let Some(Node::Binding(pat)) = tcx_hir.find(var_node_id) {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
|
||||
decl.debug_name = ident.name;
|
||||
debuginfo.debug_name = ident.name;
|
||||
if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) {
|
||||
if bm == ty::BindByValue(hir::MutMutable) {
|
||||
decl.mutability = Mutability::Mut;
|
||||
mutability = Mutability::Mut;
|
||||
} else {
|
||||
decl.mutability = Mutability::Not;
|
||||
mutability = Mutability::Not;
|
||||
}
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(pat.span, "missing binding mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
decl
|
||||
upvar_mutbls.push(mutability);
|
||||
debuginfo
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -672,7 +674,8 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
|||
safety,
|
||||
return_ty,
|
||||
return_ty_span,
|
||||
upvar_decls);
|
||||
upvar_debuginfo,
|
||||
upvar_mutbls);
|
||||
|
||||
let call_site_scope = region::Scope {
|
||||
id: body.value.hir_id.local_id,
|
||||
|
@ -734,7 +737,7 @@ fn construct_const<'a, 'gcx, 'tcx>(
|
|||
let ty = hir.tables().expr_ty_adjusted(ast_expr);
|
||||
let owner_id = tcx.hir().body_owner(body_id);
|
||||
let span = tcx.hir().span(owner_id);
|
||||
let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, ty_span,vec![]);
|
||||
let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, ty_span, vec![], vec![]);
|
||||
|
||||
let mut block = START_BLOCK;
|
||||
let expr = builder.hir.mirror(ast_expr);
|
||||
|
@ -762,7 +765,7 @@ fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
|
|||
let owner_id = hir.tcx().hir().body_owner(body_id);
|
||||
let span = hir.tcx().hir().span(owner_id);
|
||||
let ty = hir.tcx().types.err;
|
||||
let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, vec![]);
|
||||
let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, vec![], vec![]);
|
||||
let source_info = builder.source_info(span);
|
||||
builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
|
||||
builder.finish(None)
|
||||
|
@ -775,7 +778,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
safety: Safety,
|
||||
return_ty: Ty<'tcx>,
|
||||
return_span: Span,
|
||||
upvar_decls: Vec<UpvarDecl>)
|
||||
__upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
|
||||
upvar_mutbls: Vec<Mutability>)
|
||||
-> Builder<'a, 'gcx, 'tcx> {
|
||||
let lint_level = LintLevel::Explicit(hir.root_lint_level);
|
||||
let mut builder = Builder {
|
||||
|
@ -797,7 +801,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
1,
|
||||
),
|
||||
canonical_user_type_annotations: IndexVec::new(),
|
||||
upvar_decls,
|
||||
__upvar_debuginfo_codegen_only_do_not_use,
|
||||
upvar_mutbls,
|
||||
var_indices: Default::default(),
|
||||
unit_temp: None,
|
||||
cached_resume_block: None,
|
||||
|
@ -832,7 +837,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
self.local_decls,
|
||||
self.canonical_user_type_annotations,
|
||||
self.arg_count,
|
||||
self.upvar_decls,
|
||||
self.__upvar_debuginfo_codegen_only_do_not_use,
|
||||
self.fn_span,
|
||||
self.hir.control_flow_destroyed(),
|
||||
)
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::hash::Hash;
|
|||
use std::ops::RangeInclusive;
|
||||
|
||||
use syntax_pos::symbol::Symbol;
|
||||
use rustc::hir;
|
||||
use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx};
|
||||
use rustc::ty;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
@ -165,13 +166,28 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, '
|
|||
match layout.ty.sty {
|
||||
// generators and closures.
|
||||
ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
|
||||
if let Some(upvar) = self.ecx.tcx.optimized_mir(def_id).upvar_decls.get(field) {
|
||||
PathElem::ClosureVar(upvar.debug_name)
|
||||
} else {
|
||||
// Sometimes the index is beyond the number of freevars (seen
|
||||
// for a generator).
|
||||
PathElem::ClosureVar(Symbol::intern(&field.to_string()))
|
||||
let mut name = None;
|
||||
if def_id.is_local() {
|
||||
let tables = self.ecx.tcx.typeck_tables_of(def_id);
|
||||
if let Some(upvars) = tables.upvar_list.get(&def_id) {
|
||||
// Sometimes the index is beyond the number of freevars (seen
|
||||
// for a generator).
|
||||
if let Some(upvar_id) = upvars.get(field) {
|
||||
let var_hir_id = upvar_id.var_path.hir_id;
|
||||
let var_node_id = self.ecx.tcx.hir().hir_to_node_id(var_hir_id);
|
||||
if let hir::Node::Binding(pat) = self.ecx.tcx.hir().get(var_node_id) {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
|
||||
name = Some(ident.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PathElem::ClosureVar(name.unwrap_or_else(|| {
|
||||
// Fall back to showing the field index.
|
||||
Symbol::intern(&field.to_string())
|
||||
}))
|
||||
}
|
||||
|
||||
// tuples
|
||||
|
|
|
@ -490,7 +490,7 @@ fn locals_live_across_suspend_points(
|
|||
|
||||
fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
source: MirSource<'tcx>,
|
||||
upvars: Vec<Ty<'tcx>>,
|
||||
upvars: &Vec<Ty<'tcx>>,
|
||||
interior: Ty<'tcx>,
|
||||
movable: bool,
|
||||
mir: &mut Mir<'tcx>)
|
||||
|
@ -505,7 +505,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
movable);
|
||||
// Erase regions from the types passed in from typeck so we can compare them with
|
||||
// MIR types
|
||||
let allowed_upvars = tcx.erase_regions(&upvars);
|
||||
let allowed_upvars = tcx.erase_regions(upvars);
|
||||
let allowed = match interior.sty {
|
||||
ty::GeneratorWitness(s) => tcx.erase_late_bound_regions(&s),
|
||||
_ => bug!(),
|
||||
|
@ -528,7 +528,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
let upvar_len = mir.upvar_decls.len();
|
||||
let upvar_len = upvars.len();
|
||||
let dummy_local = LocalDecl::new_internal(tcx.mk_unit(), mir.span);
|
||||
|
||||
// Gather live locals and their indices replacing values in mir.local_decls with a dummy
|
||||
|
@ -917,12 +917,12 @@ impl MirPass for StateTransform {
|
|||
let (remap, layout, storage_liveness) = compute_layout(
|
||||
tcx,
|
||||
source,
|
||||
upvars,
|
||||
&upvars,
|
||||
interior,
|
||||
movable,
|
||||
mir);
|
||||
|
||||
let state_field = mir.upvar_decls.len();
|
||||
let state_field = upvars.len();
|
||||
|
||||
// Run the transformation which converts Places from Local to generator struct
|
||||
// accesses for locals in `remap`.
|
||||
|
|
|
@ -222,10 +222,10 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||
debug!("should_inline({:?})", callsite);
|
||||
let tcx = self.tcx;
|
||||
|
||||
// Don't inline closures that have captures
|
||||
// Don't inline closures that have capture debuginfo
|
||||
// FIXME: Handle closures better
|
||||
if callee_mir.upvar_decls.len() > 0 {
|
||||
debug!(" upvar decls present - not inlining");
|
||||
if callee_mir.__upvar_debuginfo_codegen_only_do_not_use.len() > 0 {
|
||||
debug!(" upvar debuginfo present - not inlining");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,13 +60,14 @@ pub fn is_min_const_fn(
|
|||
}
|
||||
|
||||
for local in &mir.local_decls {
|
||||
check_ty(tcx, local.ty, local.source_info.span)?;
|
||||
check_ty(tcx, local.ty, local.source_info.span, def_id)?;
|
||||
}
|
||||
// impl trait is gone in MIR, so check the return type manually
|
||||
check_ty(
|
||||
tcx,
|
||||
tcx.fn_sig(def_id).output().skip_binder(),
|
||||
mir.local_decls.iter().next().unwrap().source_info.span,
|
||||
def_id,
|
||||
)?;
|
||||
|
||||
for bb in mir.basic_blocks() {
|
||||
|
@ -82,6 +83,7 @@ fn check_ty(
|
|||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ty: ty::Ty<'tcx>,
|
||||
span: Span,
|
||||
fn_def_id: DefId,
|
||||
) -> McfResult {
|
||||
for ty in ty.walk() {
|
||||
match ty.sty {
|
||||
|
@ -91,7 +93,9 @@ fn check_ty(
|
|||
)),
|
||||
ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
|
||||
ty::FnPtr(..) => {
|
||||
return Err((span, "function pointers in const fn are unstable".into()))
|
||||
if !tcx.const_fn_is_allowed_fn_ptr(fn_def_id) {
|
||||
return Err((span, "function pointers in const fn are unstable".into()))
|
||||
}
|
||||
}
|
||||
ty::Dynamic(preds, _) => {
|
||||
for pred in preds.iter() {
|
||||
|
|
|
@ -461,9 +461,7 @@ fn comment(tcx: TyCtxt<'_, '_, '_>, SourceInfo { span, scope }: SourceInfo) -> S
|
|||
)
|
||||
}
|
||||
|
||||
/// Prints user-defined variables in a scope tree.
|
||||
///
|
||||
/// Returns the total number of variables printed.
|
||||
/// Prints local variables in a scope tree.
|
||||
fn write_scope_tree(
|
||||
tcx: TyCtxt<'_, '_, '_>,
|
||||
mir: &Mir<'_>,
|
||||
|
@ -474,57 +472,64 @@ fn write_scope_tree(
|
|||
) -> io::Result<()> {
|
||||
let indent = depth * INDENT.len();
|
||||
|
||||
// Local variable types (including the user's name in a comment).
|
||||
for (local, local_decl) in mir.local_decls.iter_enumerated() {
|
||||
if (1..mir.arg_count+1).contains(&local.index()) {
|
||||
// Skip over argument locals, they're printed in the signature.
|
||||
continue;
|
||||
}
|
||||
|
||||
if local_decl.source_info.scope != parent {
|
||||
// Not declared in this scope.
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut_str = if local_decl.mutability == Mutability::Mut {
|
||||
"mut "
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
let mut indented_decl = format!(
|
||||
"{0:1$}let {2}{3:?}: {4:?}",
|
||||
INDENT,
|
||||
indent,
|
||||
mut_str,
|
||||
local,
|
||||
local_decl.ty
|
||||
);
|
||||
for user_ty in local_decl.user_ty.projections() {
|
||||
write!(indented_decl, " as {:?}", user_ty).unwrap();
|
||||
}
|
||||
indented_decl.push_str(";");
|
||||
|
||||
let local_name = if local == RETURN_PLACE {
|
||||
format!(" return place")
|
||||
} else if let Some(name) = local_decl.name {
|
||||
format!(" \"{}\"", name)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
writeln!(
|
||||
w,
|
||||
"{0:1$} //{2} in {3}",
|
||||
indented_decl,
|
||||
ALIGN,
|
||||
local_name,
|
||||
comment(tcx, local_decl.source_info),
|
||||
)?;
|
||||
}
|
||||
|
||||
let children = match scope_tree.get(&parent) {
|
||||
Some(children) => children,
|
||||
Some(childs) => childs,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
for &child in children {
|
||||
let data = &mir.source_scopes[child];
|
||||
assert_eq!(data.parent_scope, Some(parent));
|
||||
assert_eq!(mir.source_scopes[child].parent_scope, Some(parent));
|
||||
writeln!(w, "{0:1$}scope {2} {{", "", indent, child.index())?;
|
||||
|
||||
// User variable types (including the user's name in a comment).
|
||||
for local in mir.vars_iter() {
|
||||
let var = &mir.local_decls[local];
|
||||
let (name, source_info) = if var.source_info.scope == child {
|
||||
(var.name.unwrap(), var.source_info)
|
||||
} else {
|
||||
// Not a variable or not declared in this scope.
|
||||
continue;
|
||||
};
|
||||
|
||||
let mut_str = if var.mutability == Mutability::Mut {
|
||||
"mut "
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
let indent = indent + INDENT.len();
|
||||
let mut indented_var = format!(
|
||||
"{0:1$}let {2}{3:?}: {4:?}",
|
||||
INDENT,
|
||||
indent,
|
||||
mut_str,
|
||||
local,
|
||||
var.ty
|
||||
);
|
||||
for user_ty in var.user_ty.projections() {
|
||||
write!(indented_var, " as {:?}", user_ty).unwrap();
|
||||
}
|
||||
indented_var.push_str(";");
|
||||
writeln!(
|
||||
w,
|
||||
"{0:1$} // \"{2}\" in {3}",
|
||||
indented_var,
|
||||
ALIGN,
|
||||
name,
|
||||
comment(tcx, source_info)
|
||||
)?;
|
||||
}
|
||||
|
||||
write_scope_tree(tcx, mir, scope_tree, w, child, depth + 1)?;
|
||||
|
||||
writeln!(w, "{0:1$}}}", "", depth * INDENT.len())?;
|
||||
}
|
||||
|
||||
|
@ -556,19 +561,8 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
// Print return place
|
||||
let indented_retptr = format!("{}let mut {:?}: {};",
|
||||
INDENT,
|
||||
RETURN_PLACE,
|
||||
mir.local_decls[RETURN_PLACE].ty);
|
||||
writeln!(w, "{0:1$} // return place",
|
||||
indented_retptr,
|
||||
ALIGN)?;
|
||||
|
||||
write_scope_tree(tcx, mir, &scope_tree, w, OUTERMOST_SOURCE_SCOPE, 1)?;
|
||||
|
||||
write_temp_decls(mir, w)?;
|
||||
|
||||
// Add an empty line before the first block is printed.
|
||||
writeln!(w, "")?;
|
||||
|
||||
|
@ -632,22 +626,6 @@ fn write_mir_sig(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_temp_decls(mir: &Mir<'_>, w: &mut dyn Write) -> io::Result<()> {
|
||||
// Compiler-introduced temporary types.
|
||||
for temp in mir.temps_iter() {
|
||||
writeln!(
|
||||
w,
|
||||
"{}let {}{:?}: {};",
|
||||
INDENT,
|
||||
if mir.local_decls[temp].mutability == Mutability::Mut {"mut "} else {""},
|
||||
temp,
|
||||
mir.local_decls[temp].ty
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_user_type_annotations(mir: &Mir<'_>, w: &mut dyn Write) -> io::Result<()> {
|
||||
if !mir.user_type_annotations.is_empty() {
|
||||
writeln!(w, "| User Type Annotations")?;
|
||||
|
|
|
@ -184,12 +184,12 @@ a.test-arrow {
|
|||
color: #ddd;
|
||||
}
|
||||
|
||||
.stab.unstable {background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
|
||||
.stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
|
||||
.stab.internal { background: #FFB9B3; border-color: #B71C1C; color: #2f2f2f; }
|
||||
.stab.deprecated { background: #F3DFFF; border-color: #7F0087; color: #2f2f2f; }
|
||||
.stab.portability { background: #C4ECFF; border-color: #7BA5DB; color: #2f2f2f; }
|
||||
|
||||
.stab > code {
|
||||
.stab.portability > code {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ a.test-arrow {
|
|||
.stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
|
||||
.stab.portability { background: #C4ECFF; border-color: #7BA5DB; }
|
||||
|
||||
.stab > code {
|
||||
.stab.portability > code {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ use core::task::{Context, Poll};
|
|||
use core::ops::{Drop, Generator, GeneratorState};
|
||||
|
||||
#[doc(inline)]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub use core::future::*;
|
||||
|
||||
/// Wrap a generator in a future.
|
||||
|
|
|
@ -263,7 +263,6 @@
|
|||
#![feature(fixed_size_array)]
|
||||
#![feature(fn_traits)]
|
||||
#![feature(fnbox)]
|
||||
#![feature(futures_api)]
|
||||
#![feature(generator_trait)]
|
||||
#![feature(hash_raw_entry)]
|
||||
#![feature(hashmap_internals)]
|
||||
|
@ -458,18 +457,15 @@ pub mod process;
|
|||
pub mod sync;
|
||||
pub mod time;
|
||||
|
||||
#[unstable(feature = "futures_api",
|
||||
reason = "futures in libcore are unstable",
|
||||
issue = "50547")]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub mod task {
|
||||
//! Types and Traits for working with asynchronous tasks.
|
||||
#[doc(inline)]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub use core::task::*;
|
||||
}
|
||||
|
||||
#[unstable(feature = "futures_api",
|
||||
reason = "futures in libcore are unstable",
|
||||
issue = "50547")]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub mod future;
|
||||
|
||||
// Platform-abstraction modules
|
||||
|
|
|
@ -319,7 +319,7 @@ impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "futures_api", issue = "50547")]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl<F: Future> Future for AssertUnwindSafe<F> {
|
||||
type Output = F::Output;
|
||||
|
||||
|
|
|
@ -114,6 +114,8 @@ pub struct Stability {
|
|||
pub const_stability: Option<Symbol>,
|
||||
/// whether the function has a `#[rustc_promotable]` attribute
|
||||
pub promotable: bool,
|
||||
/// whether the function has a `#[rustc_allow_const_fn_ptr]` attribute
|
||||
pub allow_const_fn_ptr: bool,
|
||||
}
|
||||
|
||||
/// The available stability levels.
|
||||
|
@ -178,6 +180,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||
let mut rustc_depr: Option<RustcDeprecation> = None;
|
||||
let mut rustc_const_unstable: Option<Symbol> = None;
|
||||
let mut promotable = false;
|
||||
let mut allow_const_fn_ptr = false;
|
||||
let diagnostic = &sess.span_diagnostic;
|
||||
|
||||
'outer: for attr in attrs_iter {
|
||||
|
@ -187,6 +190,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||
"unstable",
|
||||
"stable",
|
||||
"rustc_promotable",
|
||||
"rustc_allow_const_fn_ptr",
|
||||
].iter().any(|&s| attr.path == s) {
|
||||
continue // not a stability level
|
||||
}
|
||||
|
@ -198,6 +202,9 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||
if attr.path == "rustc_promotable" {
|
||||
promotable = true;
|
||||
}
|
||||
if attr.path == "rustc_allow_const_fn_ptr" {
|
||||
allow_const_fn_ptr = true;
|
||||
}
|
||||
// attributes with data
|
||||
else if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta {
|
||||
let meta = meta.as_ref().unwrap();
|
||||
|
@ -354,6 +361,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||
rustc_depr: None,
|
||||
const_stability: None,
|
||||
promotable: false,
|
||||
allow_const_fn_ptr: false,
|
||||
})
|
||||
}
|
||||
(None, _, _) => {
|
||||
|
@ -418,6 +426,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||
rustc_depr: None,
|
||||
const_stability: None,
|
||||
promotable: false,
|
||||
allow_const_fn_ptr: false,
|
||||
})
|
||||
}
|
||||
(None, _) => {
|
||||
|
@ -458,13 +467,14 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||
}
|
||||
|
||||
// Merge the const-unstable info into the stability info
|
||||
if promotable {
|
||||
if promotable || allow_const_fn_ptr {
|
||||
if let Some(ref mut stab) = stab {
|
||||
stab.promotable = true;
|
||||
stab.promotable = promotable;
|
||||
stab.allow_const_fn_ptr = allow_const_fn_ptr;
|
||||
} else {
|
||||
span_err!(diagnostic, item_sp, E0717,
|
||||
"rustc_promotable attribute must be paired with \
|
||||
either stable or unstable attribute");
|
||||
"rustc_promotable and rustc_allow_const_fn_ptr attributes \
|
||||
must be paired with either stable or unstable attribute");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1145,9 +1145,34 @@ impl<'a> Parser<'a> {
|
|||
if text.is_empty() {
|
||||
self.span_bug(sp, "found empty literal suffix in Some")
|
||||
}
|
||||
self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
|
||||
.span_label(sp, format!("invalid suffix `{}`", text))
|
||||
.emit();
|
||||
let mut err = if kind == "a tuple index" &&
|
||||
["i32", "u32", "isize", "usize"].contains(&text.to_string().as_str())
|
||||
{
|
||||
// #59553: warn instead of reject out of hand to allow the fix to percolate
|
||||
// through the ecosystem when people fix their macros
|
||||
let mut err = self.struct_span_warn(
|
||||
sp,
|
||||
&format!("suffixes on {} are invalid", kind),
|
||||
);
|
||||
err.note(&format!(
|
||||
"`{}` is *temporarily* accepted on tuple index fields as it was \
|
||||
incorrectly accepted on stable for a few releases",
|
||||
text,
|
||||
));
|
||||
err.help(
|
||||
"on proc macros, you'll want to use `syn::Index::from` or \
|
||||
`proc_macro::Literal::*_unsuffixed` for code that will desugar \
|
||||
to tuple field access",
|
||||
);
|
||||
err.note(
|
||||
"for more context, see https://github.com/rust-lang/rust/issues/60210",
|
||||
);
|
||||
err
|
||||
} else {
|
||||
self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
|
||||
};
|
||||
err.span_label(sp, format!("invalid suffix `{}`", text));
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1455,6 +1480,9 @@ impl<'a> Parser<'a> {
|
|||
fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
|
||||
self.sess.span_diagnostic.struct_span_err(sp, m)
|
||||
}
|
||||
fn struct_span_warn<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
|
||||
self.sess.span_diagnostic.struct_span_warn(sp, m)
|
||||
}
|
||||
crate fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> ! {
|
||||
self.sess.span_diagnostic.span_bug(sp, m)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![deny(unused_must_use)]
|
||||
#![feature(arbitrary_self_types, futures_api)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
|
||||
use std::iter::Iterator;
|
||||
use std::future::Future;
|
||||
|
|
|
@ -22,15 +22,14 @@ impl Drop for S {
|
|||
// END RUST SOURCE
|
||||
// START rustc.main.ElaborateDrops.before.mir
|
||||
// let mut _0: ();
|
||||
// scope 1 {
|
||||
// }
|
||||
// scope 2 {
|
||||
// let _1: std::boxed::Box<S>;
|
||||
// }
|
||||
// let mut _2: std::boxed::Box<S>;
|
||||
// let mut _3: ();
|
||||
// let mut _4: std::boxed::Box<S>;
|
||||
//
|
||||
// scope 1 {
|
||||
// let _1: std::boxed::Box<S>;
|
||||
// }
|
||||
// scope 2 {
|
||||
// }
|
||||
// bb0: {
|
||||
// StorageLive(_1);
|
||||
// StorageLive(_2);
|
||||
|
|
|
@ -29,27 +29,28 @@ impl S {
|
|||
// END RUST SOURCE
|
||||
// START rustc.main.ElaborateDrops.after.mir
|
||||
// let mut _0: ();
|
||||
// scope 1 {
|
||||
// }
|
||||
// scope 2 {
|
||||
// let _1: ();
|
||||
// }
|
||||
// let mut _2: S;
|
||||
// let mut _3: S;
|
||||
// let mut _4: S;
|
||||
// let mut _5: bool;
|
||||
// scope 1 {
|
||||
// let _1: ();
|
||||
// }
|
||||
// scope 2 {
|
||||
// }
|
||||
// ...
|
||||
// bb0: {
|
||||
// END rustc.main.ElaborateDrops.after.mir
|
||||
// START rustc.test.ElaborateDrops.after.mir
|
||||
// let mut _0: ();
|
||||
// ...
|
||||
// let mut _2: S;
|
||||
// ...
|
||||
// let _1: S;
|
||||
// ...
|
||||
// let mut _3: ();
|
||||
// let mut _4: S;
|
||||
// let mut _5: S;
|
||||
// let mut _6: bool;
|
||||
// ...
|
||||
// let _1: S;
|
||||
// ...
|
||||
// let mut _2: S;
|
||||
// ...
|
||||
// bb0: {
|
||||
// END rustc.test.ElaborateDrops.after.mir
|
||||
|
|
|
@ -17,16 +17,16 @@ fn main() {
|
|||
// START rustc.main.mir_map.0.mir
|
||||
// fn main() -> (){
|
||||
// let mut _0: ();
|
||||
// scope 1 {
|
||||
// }
|
||||
// scope 2 {
|
||||
// let _2: i32;
|
||||
// }
|
||||
// let mut _1: ();
|
||||
// let mut _3: bool;
|
||||
// let mut _4: !;
|
||||
// let mut _5: ();
|
||||
// let mut _6: &i32;
|
||||
// scope 1 {
|
||||
// let _2: i32;
|
||||
// }
|
||||
// scope 2 {
|
||||
// }
|
||||
// bb0: {
|
||||
// goto -> bb1;
|
||||
// }
|
||||
|
|
|
@ -27,10 +27,10 @@ fn main() {
|
|||
// | '_#4r | U0 | {bb2[4..=5], bb3[0..=1]}
|
||||
// END rustc.main.nll.0.mir
|
||||
// START rustc.main.nll.0.mir
|
||||
// let _6: &'_#4r usize;
|
||||
// ...
|
||||
// let _2: &'_#3r usize;
|
||||
// ...
|
||||
// let _6: &'_#4r usize;
|
||||
// ...
|
||||
// _2 = &'_#2r _1[_3];
|
||||
// ...
|
||||
// _6 = _2;
|
||||
|
|
|
@ -18,16 +18,16 @@ impl Drop for Droppy {
|
|||
// START rustc.main.EraseRegions.before.mir
|
||||
// fn main() -> () {
|
||||
// let mut _0: ();
|
||||
// scope 1 {
|
||||
// }
|
||||
// scope 2 {
|
||||
// let mut _1: Packed;
|
||||
// }
|
||||
// let mut _2: Aligned;
|
||||
// let mut _3: Droppy;
|
||||
// let mut _4: Aligned;
|
||||
// let mut _5: Droppy;
|
||||
// let mut _6: Aligned;
|
||||
// scope 1 {
|
||||
// let mut _1: Packed;
|
||||
// }
|
||||
// scope 2 {
|
||||
// }
|
||||
//
|
||||
// bb0: {
|
||||
// StorageLive(_1);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// edition:2018
|
||||
// aux-build:arc_wake.rs
|
||||
|
||||
#![feature(async_await, await_macro, futures_api)]
|
||||
#![feature(async_await, await_macro)]
|
||||
|
||||
extern crate arc_wake;
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// edition:2018
|
||||
|
||||
#![feature(futures_api)]
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::task::{
|
||||
Waker, RawWaker, RawWakerVTable,
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// aux-build:arc_wake.rs
|
||||
|
||||
#![feature(futures_api)]
|
||||
|
||||
extern crate arc_wake;
|
||||
|
||||
use std::future::Future;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// run-pass
|
||||
|
||||
#![allow(unused_variables)]
|
||||
#![feature(async_await, await_macro, futures_api)]
|
||||
#![feature(async_await, await_macro)]
|
||||
|
||||
extern crate arc_wake;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// edition:2018
|
||||
// run-pass
|
||||
|
||||
#![feature(async_await, await_macro, futures_api)]
|
||||
#![feature(async_await, await_macro)]
|
||||
|
||||
trait Foo { }
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// edition:2018
|
||||
|
||||
#![feature(async_await, futures_api)]
|
||||
#![feature(async_await)]
|
||||
|
||||
// @has async_fn/fn.foo.html '//pre[@class="rust fn"]' 'pub async fn foo() -> Option<Foo>'
|
||||
pub async fn foo() -> Option<Foo> {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// edition:2018
|
||||
|
||||
#![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)]
|
||||
#![feature(arbitrary_self_types, async_await, await_macro, pin)]
|
||||
|
||||
use std::ops::Add;
|
||||
|
||||
|
|
10
src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs
Normal file
10
src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
#![feature(rustc_attrs, staged_api)]
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
const fn error(_: fn()) {} //~ ERROR function pointers in const fn are unstable
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_allow_const_fn_ptr]
|
||||
const fn compiles(_: fn()) {}
|
||||
|
||||
fn main() {}
|
12
src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr
Normal file
12
src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error[E0723]: function pointers in const fn are unstable
|
||||
--> $DIR/allow_const_fn_ptr.rs:4:16
|
||||
|
|
||||
LL | const fn error(_: fn()) {}
|
||||
| ^
|
||||
|
|
||||
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
|
||||
= help: add #![feature(const_fn)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0723`.
|
|
@ -0,0 +1,11 @@
|
|||
#![feature(staged_api)]
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
const fn error(_: fn()) {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_allow_const_fn_ptr]
|
||||
//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved
|
||||
const fn compiles(_: fn()) {}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,12 @@
|
|||
error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
|
||||
--> $DIR/allow_const_fn_ptr_feature_gate.rs:7:3
|
||||
|
|
||||
LL | #[rustc_allow_const_fn_ptr]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
|
@ -0,0 +1,18 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(rustc_attrs, staged_api)]
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_allow_const_fn_ptr]
|
||||
const fn takes_fn_ptr(_: fn()) {}
|
||||
|
||||
const FN: fn() = || ();
|
||||
|
||||
const fn gives_fn_ptr() {
|
||||
takes_fn_ptr(FN)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
gives_fn_ptr();
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
// edition:2015
|
||||
|
||||
#![feature(futures_api, async_await)]
|
||||
#![feature(async_await)]
|
||||
|
||||
async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// edition:2015
|
||||
|
||||
#![feature(futures_api)]
|
||||
|
||||
async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||
//~^ ERROR async fn is unstable
|
||||
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
error[E0670]: `async fn` is not permitted in the 2015 edition
|
||||
--> $DIR/feature-gate-async-await-2015-edition.rs:5:1
|
||||
--> $DIR/feature-gate-async-await-2015-edition.rs:3:1
|
||||
|
|
||||
LL | async fn foo() {}
|
||||
| ^^^^^
|
||||
|
||||
error[E0422]: cannot find struct, variant or union type `async` in this scope
|
||||
--> $DIR/feature-gate-async-await-2015-edition.rs:9:13
|
||||
--> $DIR/feature-gate-async-await-2015-edition.rs:7:13
|
||||
|
|
||||
LL | let _ = async {};
|
||||
| ^^^^^ not found in this scope
|
||||
|
||||
error[E0425]: cannot find value `async` in this scope
|
||||
--> $DIR/feature-gate-async-await-2015-edition.rs:10:13
|
||||
--> $DIR/feature-gate-async-await-2015-edition.rs:8:13
|
||||
|
|
||||
LL | let _ = async || { true };
|
||||
| ^^^^^ not found in this scope
|
||||
|
||||
error[E0658]: async fn is unstable
|
||||
--> $DIR/feature-gate-async-await-2015-edition.rs:5:1
|
||||
--> $DIR/feature-gate-async-await-2015-edition.rs:3:1
|
||||
|
|
||||
LL | async fn foo() {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// edition:2018
|
||||
|
||||
#![feature(futures_api)]
|
||||
|
||||
struct S;
|
||||
|
||||
impl S {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
error[E0706]: trait fns cannot be declared `async`
|
||||
--> $DIR/feature-gate-async-await.rs:12:5
|
||||
--> $DIR/feature-gate-async-await.rs:10:5
|
||||
|
|
||||
LL | async fn foo();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0658]: async fn is unstable
|
||||
--> $DIR/feature-gate-async-await.rs:8:5
|
||||
--> $DIR/feature-gate-async-await.rs:6:5
|
||||
|
|
||||
LL | async fn foo() {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
@ -14,7 +14,7 @@ LL | async fn foo() {}
|
|||
= help: add #![feature(async_await)] to the crate attributes to enable
|
||||
|
||||
error[E0658]: async fn is unstable
|
||||
--> $DIR/feature-gate-async-await.rs:12:5
|
||||
--> $DIR/feature-gate-async-await.rs:10:5
|
||||
|
|
||||
LL | async fn foo();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
@ -23,7 +23,7 @@ LL | async fn foo();
|
|||
= help: add #![feature(async_await)] to the crate attributes to enable
|
||||
|
||||
error[E0658]: async fn is unstable
|
||||
--> $DIR/feature-gate-async-await.rs:16:1
|
||||
--> $DIR/feature-gate-async-await.rs:14:1
|
||||
|
|
||||
LL | async fn foo() {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
@ -32,7 +32,7 @@ LL | async fn foo() {}
|
|||
= help: add #![feature(async_await)] to the crate attributes to enable
|
||||
|
||||
error[E0658]: async blocks are unstable
|
||||
--> $DIR/feature-gate-async-await.rs:19:13
|
||||
--> $DIR/feature-gate-async-await.rs:17:13
|
||||
|
|
||||
LL | let _ = async {};
|
||||
| ^^^^^^^^
|
||||
|
@ -41,7 +41,7 @@ LL | let _ = async {};
|
|||
= help: add #![feature(async_await)] to the crate attributes to enable
|
||||
|
||||
error[E0658]: async closures are unstable
|
||||
--> $DIR/feature-gate-async-await.rs:20:13
|
||||
--> $DIR/feature-gate-async-await.rs:18:13
|
||||
|
|
||||
LL | let _ = async || {};
|
||||
| ^^^^^^^^^^^
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Test that impl trait does not allow creating recursive types that are
|
||||
// otherwise forbidden when using `async` and `await`.
|
||||
|
||||
#![feature(await_macro, async_await, futures_api, generators)]
|
||||
#![feature(await_macro, async_await, generators)]
|
||||
|
||||
async fn recursive_async_function() -> () { //~ ERROR
|
||||
await!(recursive_async_function());
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Test that impl trait does not allow creating recursive types that are
|
||||
// otherwise forbidden.
|
||||
|
||||
#![feature(futures_api, generators)]
|
||||
#![feature(generators)]
|
||||
|
||||
fn option(i: i32) -> impl Sized { //~ ERROR
|
||||
if i < 0 {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// compile-pass
|
||||
// edition:2018
|
||||
|
||||
#![feature(async_await, await_macro, futures_api)]
|
||||
#![feature(async_await, await_macro)]
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// compile-pass
|
||||
// edition:2018
|
||||
|
||||
#![feature(async_await, await_macro, futures_api)]
|
||||
#![feature(async_await, await_macro)]
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// compile-pass
|
||||
// edition:2018
|
||||
|
||||
#![feature(async_await, await_macro, futures_api)]
|
||||
#![feature(async_await, await_macro)]
|
||||
|
||||
struct Xyz {
|
||||
a: u64,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// compile-pass
|
||||
// edition:2018
|
||||
|
||||
#![feature(async_await, await_macro, futures_api)]
|
||||
#![feature(async_await, await_macro)]
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// edition:2018
|
||||
|
||||
#![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)]
|
||||
#![feature(async_await, await_macro)]
|
||||
|
||||
fn main() {
|
||||
let _ = async |x: u8| {};
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// compile-pass
|
||||
|
||||
#![allow(dead_code, unused)]
|
||||
#![feature(futures_api)]
|
||||
|
||||
use std::task::Poll;
|
||||
|
||||
|
|
Loading…
Reference in a new issue