diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index ffa4176cc7969..d877ac6ac5c79 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -80,6 +80,7 @@ #![feature(box_into_raw_non_null)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(cfg_sanitize)] #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] #![feature(const_generic_impls_guard)] diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 4a0cf2984edd9..d9b54fb0b177a 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -40,6 +40,23 @@ mod tests; /// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. const MAX_REFCOUNT: usize = (isize::MAX) as usize; +#[cfg(not(sanitize = "thread"))] +macro_rules! acquire { + ($x:expr) => { + atomic::fence(Acquire) + }; +} + +// ThreadSanitizer does not support memory fences. To avoid false positive +// reports in Arc / Weak implementation use atomic loads for synchronization +// instead. +#[cfg(sanitize = "thread")] +macro_rules! acquire { + ($x:expr) => { + $x.load(Acquire) + }; +} + /// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically /// Reference Counted'. /// @@ -402,7 +419,7 @@ impl Arc { return Err(this); } - atomic::fence(Acquire); + acquire!(this.inner().strong); unsafe { let elem = ptr::read(&this.ptr.as_ref().data); @@ -739,7 +756,7 @@ impl Arc { ptr::drop_in_place(&mut self.ptr.as_mut().data); if self.inner().weak.fetch_sub(1, Release) == 1 { - atomic::fence(Acquire); + acquire!(self.inner().weak); Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) } } @@ -1243,7 +1260,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { // // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) // [2]: (https://github.com/rust-lang/rust/pull/41714) - atomic::fence(Acquire); + acquire!(self.inner().strong); unsafe { self.drop_slow(); @@ -1701,7 +1718,7 @@ impl Drop for Weak { let inner = if let Some(inner) = self.inner() { inner } else { return }; if inner.weak.fetch_sub(1, Release) == 1 { - atomic::fence(Acquire); + acquire!(inner.weak); unsafe { Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) } } } diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 8ffad82b69d7c..adee8cea442b4 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -1,5 +1,5 @@ use crate::fmt; -use crate::hash::{Hash, Hasher}; +use crate::hash::Hash; /// An unbounded range (`..`). /// @@ -330,7 +330,7 @@ impl> RangeTo { /// assert_eq!(arr[1..=3], [ 1,2,3 ]); // RangeInclusive /// ``` #[doc(alias = "..=")] -#[derive(Clone)] // not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[stable(feature = "inclusive_range", since = "1.26.0")] pub struct RangeInclusive { // Note that the fields here are not public to allow changing the @@ -350,26 +350,6 @@ pub struct RangeInclusive { pub(crate) exhausted: bool, } -#[stable(feature = "inclusive_range", since = "1.26.0")] -impl PartialEq for RangeInclusive { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.start == other.start && self.end == other.end && self.exhausted == other.exhausted - } -} - -#[stable(feature = "inclusive_range", since = "1.26.0")] -impl Eq for RangeInclusive {} - -#[stable(feature = "inclusive_range", since = "1.26.0")] -impl Hash for RangeInclusive { - fn hash(&self, state: &mut H) { - self.start.hash(state); - self.end.hash(state); - self.exhausted.hash(state); - } -} - impl RangeInclusive { /// Creates a new inclusive range. Equivalent to writing `start..=end`. /// diff --git a/src/libcore/tests/mem.rs b/src/libcore/tests/mem.rs index 8337ab103419f..59588d97787b7 100644 --- a/src/libcore/tests/mem.rs +++ b/src/libcore/tests/mem.rs @@ -129,21 +129,3 @@ fn test_discriminant_send_sync() { is_send_sync::>(); is_send_sync::>(); } - -#[test] -fn test_const_forget() { - const _: () = forget(0i32); - const _: () = forget(Vec::>>::new()); - - // Writing this function signature without const-forget - // triggers compiler errors: - // 1) That we use a non-const fn inside a const fn - // 2) without the forget, it complains about the destructor of Box - const fn const_forget_box(x: Box) { - forget(x); - } - - // Call the forget_box at runtime, - // as we can't const-construct a box yet. - const_forget_box(Box::new(0i32)); -} diff --git a/src/librustc/ty/query/caches.rs b/src/librustc/ty/query/caches.rs index efc2804bd4d59..a11b3bcba3ed3 100644 --- a/src/librustc/ty/query/caches.rs +++ b/src/librustc/ty/query/caches.rs @@ -1,5 +1,4 @@ use crate::dep_graph::DepNodeIndex; -use crate::ty::query::config::QueryAccessors; use crate::ty::query::plumbing::{QueryLookup, QueryState, QueryStateShard}; use crate::ty::TyCtxt; @@ -7,39 +6,43 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sharded::Sharded; use std::default::Default; use std::hash::Hash; +use std::marker::PhantomData; pub(crate) trait CacheSelector { - type Cache: QueryCache; + type Cache: QueryCache; } -pub(crate) trait QueryCache: Default { +pub(crate) trait QueryCache: Default { + type Key; + type Value; type Sharded: Default; /// Checks if the query is already computed and in the cache. /// It returns the shard index and a lock guard to the shard, /// which will be used if the query is not in the cache and we need /// to compute it. - fn lookup<'tcx, R, GetCache, OnHit, OnMiss, Q>( + fn lookup<'tcx, R, GetCache, OnHit, OnMiss>( &self, - state: &'tcx QueryState<'tcx, Q>, + state: &'tcx QueryState<'tcx, Self>, get_cache: GetCache, - key: K, + key: Self::Key, // `on_hit` can be called while holding a lock to the query state shard. on_hit: OnHit, on_miss: OnMiss, ) -> R where - Q: QueryAccessors<'tcx>, - GetCache: for<'a> Fn(&'a mut QueryStateShard<'tcx, Q>) -> &'a mut Self::Sharded, - OnHit: FnOnce(&V, DepNodeIndex) -> R, - OnMiss: FnOnce(K, QueryLookup<'tcx, Q>) -> R; + GetCache: for<'a> Fn( + &'a mut QueryStateShard<'tcx, Self::Key, Self::Sharded>, + ) -> &'a mut Self::Sharded, + OnHit: FnOnce(&Self::Value, DepNodeIndex) -> R, + OnMiss: FnOnce(Self::Key, QueryLookup<'tcx, Self::Key, Self::Sharded>) -> R; fn complete( &self, tcx: TyCtxt<'tcx>, lock_sharded_storage: &mut Self::Sharded, - key: K, - value: V, + key: Self::Key, + value: Self::Value, index: DepNodeIndex, ); @@ -47,36 +50,45 @@ pub(crate) trait QueryCache: Default { &self, shards: &Sharded, get_shard: impl Fn(&mut L) -> &mut Self::Sharded, - f: impl for<'a> FnOnce(Box + 'a>) -> R, + f: impl for<'a> FnOnce( + Box + 'a>, + ) -> R, ) -> R; } pub struct DefaultCacheSelector; impl CacheSelector for DefaultCacheSelector { - type Cache = DefaultCache; + type Cache = DefaultCache; } -#[derive(Default)] -pub struct DefaultCache; +pub struct DefaultCache(PhantomData<(K, V)>); + +impl Default for DefaultCache { + fn default() -> Self { + DefaultCache(PhantomData) + } +} -impl QueryCache for DefaultCache { +impl QueryCache for DefaultCache { + type Key = K; + type Value = V; type Sharded = FxHashMap; #[inline(always)] - fn lookup<'tcx, R, GetCache, OnHit, OnMiss, Q>( + fn lookup<'tcx, R, GetCache, OnHit, OnMiss>( &self, - state: &'tcx QueryState<'tcx, Q>, + state: &'tcx QueryState<'tcx, Self>, get_cache: GetCache, key: K, on_hit: OnHit, on_miss: OnMiss, ) -> R where - Q: QueryAccessors<'tcx>, - GetCache: for<'a> Fn(&'a mut QueryStateShard<'tcx, Q>) -> &'a mut Self::Sharded, + GetCache: + for<'a> Fn(&'a mut QueryStateShard<'tcx, K, Self::Sharded>) -> &'a mut Self::Sharded, OnHit: FnOnce(&V, DepNodeIndex) -> R, - OnMiss: FnOnce(K, QueryLookup<'tcx, Q>) -> R, + OnMiss: FnOnce(K, QueryLookup<'tcx, K, Self::Sharded>) -> R, { let mut lookup = state.get_lookup(&key); let lock = &mut *lookup.lock; diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 178c2362def6e..72a0fdf156726 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -2,7 +2,7 @@ use crate::dep_graph::SerializedDepNodeIndex; use crate::dep_graph::{DepKind, DepNode}; use crate::ty::query::caches::QueryCache; use crate::ty::query::plumbing::CycleError; -use crate::ty::query::{Query, QueryState}; +use crate::ty::query::QueryState; use crate::ty::TyCtxt; use rustc_data_structures::profiling::ProfileCategory; use rustc_hir::def_id::DefId; @@ -28,18 +28,15 @@ pub trait QueryConfig<'tcx> { pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> { const ANON: bool; const EVAL_ALWAYS: bool; + const DEP_KIND: DepKind; - type Cache: QueryCache; - - fn query(key: Self::Key) -> Query<'tcx>; + type Cache: QueryCache; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state<'a>(tcx: TyCtxt<'tcx>) -> &'a QueryState<'tcx, Self>; + fn query_state<'a>(tcx: TyCtxt<'tcx>) -> &'a QueryState<'tcx, Self::Cache>; fn to_dep_node(tcx: TyCtxt<'tcx>, key: &Self::Key) -> DepNode; - fn dep_kind() -> DepKind; - // Don't use this method to compute query results, instead use the methods on TyCtxt fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value; @@ -62,10 +59,7 @@ pub(crate) trait QueryDescription<'tcx>: QueryAccessors<'tcx> { } } -impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M -where - >::Cache: QueryCache>::Value>, -{ +impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M { default fn describe(tcx: TyCtxt<'_>, def_id: DefId) -> Cow<'static, str> { if !tcx.sess.verbose() { format!("processing `{}`", tcx.def_path_str(def_id)).into() diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 7ac8358c78a61..0407bad0bb501 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -57,13 +57,12 @@ use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use std::borrow::Cow; use std::collections::BTreeMap; -use std::convert::TryFrom; use std::ops::Deref; use std::sync::Arc; #[macro_use] mod plumbing; -pub use self::plumbing::CycleError; +pub(crate) use self::plumbing::CycleError; use self::plumbing::*; mod stats; diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index acf67f52dceaa..0bfcae5fa2e66 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -2,10 +2,10 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. -use crate::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex}; +use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex}; use crate::ty::query::caches::QueryCache; -use crate::ty::query::config::{QueryAccessors, QueryDescription}; -use crate::ty::query::job::{QueryInfo, QueryJob, QueryJobId, QueryShardJobId}; +use crate::ty::query::config::QueryDescription; +use crate::ty::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryShardJobId}; use crate::ty::query::Query; use crate::ty::tls; use crate::ty::{self, TyCtxt}; @@ -20,6 +20,8 @@ use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, FatalError, H use rustc_span::source_map::DUMMY_SP; use rustc_span::Span; use std::collections::hash_map::Entry; +use std::convert::TryFrom; +use std::fmt::Debug; use std::hash::{Hash, Hasher}; use std::mem; use std::num::NonZeroU32; @@ -27,37 +29,38 @@ use std::ptr; #[cfg(debug_assertions)] use std::sync::atomic::{AtomicUsize, Ordering}; -pub(crate) struct QueryStateShard<'tcx, D: QueryAccessors<'tcx> + ?Sized> { - pub(super) cache: <>::Cache as QueryCache>::Sharded, - pub(super) active: FxHashMap>, +pub(crate) struct QueryStateShard<'tcx, K, C> { + cache: C, + active: FxHashMap>, /// Used to generate unique ids for active jobs. - pub(super) jobs: u32, + jobs: u32, } -impl<'tcx, Q: QueryAccessors<'tcx>> QueryStateShard<'tcx, Q> { - fn get_cache( - &mut self, - ) -> &mut <>::Cache as QueryCache>::Sharded { +impl<'tcx, K, C> QueryStateShard<'tcx, K, C> { + fn get_cache(&mut self) -> &mut C { &mut self.cache } } -impl<'tcx, Q: QueryAccessors<'tcx>> Default for QueryStateShard<'tcx, Q> { - fn default() -> QueryStateShard<'tcx, Q> { +impl<'tcx, K, C: Default> Default for QueryStateShard<'tcx, K, C> { + fn default() -> QueryStateShard<'tcx, K, C> { QueryStateShard { cache: Default::default(), active: Default::default(), jobs: 0 } } } -pub(crate) struct QueryState<'tcx, D: QueryAccessors<'tcx> + ?Sized> { - pub(super) cache: D::Cache, - pub(super) shards: Sharded>, +pub(crate) struct QueryState<'tcx, C: QueryCache> { + cache: C, + shards: Sharded>, #[cfg(debug_assertions)] pub(super) cache_hits: AtomicUsize, } -impl<'tcx, Q: QueryAccessors<'tcx>> QueryState<'tcx, Q> { - pub(super) fn get_lookup(&'tcx self, key: &K) -> QueryLookup<'tcx, Q> { +impl<'tcx, C: QueryCache> QueryState<'tcx, C> { + pub(super) fn get_lookup( + &'tcx self, + key: &K2, + ) -> QueryLookup<'tcx, C::Key, C::Sharded> { // We compute the key's hash once and then use it for both the // shard lookup and the hashmap lookup. This relies on the fact // that both of them use `FxHasher`. @@ -72,7 +75,7 @@ impl<'tcx, Q: QueryAccessors<'tcx>> QueryState<'tcx, Q> { } /// Indicates the state of a query for a given key in a query map. -pub(super) enum QueryResult<'tcx> { +enum QueryResult<'tcx> { /// An already executing query. The query job can be used to await for its completion. Started(QueryJob<'tcx>), @@ -81,25 +84,54 @@ pub(super) enum QueryResult<'tcx> { Poisoned, } -impl<'tcx, M: QueryAccessors<'tcx>> QueryState<'tcx, M> { - pub fn iter_results( +impl<'tcx, C: QueryCache> QueryState<'tcx, C> { + pub(super) fn iter_results( &self, f: impl for<'a> FnOnce( - Box + 'a>, + Box + 'a>, ) -> R, ) -> R { self.cache.iter(&self.shards, |shard| &mut shard.cache, f) } - pub fn all_inactive(&self) -> bool { + pub(super) fn all_inactive(&self) -> bool { let shards = self.shards.lock_shards(); shards.iter().all(|shard| shard.active.is_empty()) } + + pub(super) fn try_collect_active_jobs( + &self, + kind: DepKind, + make_query: fn(C::Key) -> Query<'tcx>, + jobs: &mut FxHashMap>, + ) -> Option<()> + where + C::Key: Clone, + { + // We use try_lock_shards here since we are called from the + // deadlock handler, and this shouldn't be locked. + let shards = self.shards.try_lock_shards()?; + let shards = shards.iter().enumerate(); + jobs.extend(shards.flat_map(|(shard_id, shard)| { + shard.active.iter().filter_map(move |(k, v)| { + if let QueryResult::Started(ref job) = *v { + let id = + QueryJobId { job: job.id, shard: u16::try_from(shard_id).unwrap(), kind }; + let info = QueryInfo { span: job.span, query: make_query(k.clone()) }; + Some((id, QueryJobInfo { info, job: job.clone() })) + } else { + None + } + }) + })); + + Some(()) + } } -impl<'tcx, M: QueryAccessors<'tcx>> Default for QueryState<'tcx, M> { - fn default() -> QueryState<'tcx, M> { +impl<'tcx, C: QueryCache> Default for QueryState<'tcx, C> { + fn default() -> QueryState<'tcx, C> { QueryState { - cache: M::Cache::default(), + cache: C::default(), shards: Default::default(), #[cfg(debug_assertions)] cache_hits: AtomicUsize::new(0), @@ -108,21 +140,31 @@ impl<'tcx, M: QueryAccessors<'tcx>> Default for QueryState<'tcx, M> { } /// Values used when checking a query cache which can be reused on a cache-miss to execute the query. -pub(crate) struct QueryLookup<'tcx, Q: QueryAccessors<'tcx>> { +pub(crate) struct QueryLookup<'tcx, K, C> { pub(super) key_hash: u64, - pub(super) shard: usize, - pub(super) lock: LockGuard<'tcx, QueryStateShard<'tcx, Q>>, + shard: usize, + pub(super) lock: LockGuard<'tcx, QueryStateShard<'tcx, K, C>>, } /// A type representing the responsibility to execute the job in the `job` field. /// This will poison the relevant query if dropped. -pub(super) struct JobOwner<'tcx, Q: QueryDescription<'tcx>> { - tcx: TyCtxt<'tcx>, - key: Q::Key, +struct JobOwner<'tcx, C> +where + C: QueryCache, + C::Key: Eq + Hash + Clone + Debug, + C::Value: Clone, +{ + state: &'tcx QueryState<'tcx, C>, + key: C::Key, id: QueryJobId, } -impl<'tcx, Q: QueryDescription<'tcx>> JobOwner<'tcx, Q> { +impl<'tcx, C: QueryCache> JobOwner<'tcx, C> +where + C: QueryCache, + C::Key: Eq + Hash + Clone + Debug, + C::Value: Clone, +{ /// Either gets a `JobOwner` corresponding the query, allowing us to /// start executing the query, or returns with the result of the query. /// This function assumes that `try_get_cached` is already called and returned `lookup`. @@ -132,12 +174,15 @@ impl<'tcx, Q: QueryDescription<'tcx>> JobOwner<'tcx, Q> { /// This function is inlined because that results in a noticeable speed-up /// for some compile-time benchmarks. #[inline(always)] - pub(super) fn try_start( + fn try_start( tcx: TyCtxt<'tcx>, span: Span, - key: &Q::Key, - mut lookup: QueryLookup<'tcx, Q>, - ) -> TryGetJob<'tcx, Q> { + key: &C::Key, + mut lookup: QueryLookup<'tcx, C::Key, C::Sharded>, + ) -> TryGetJob<'tcx, C> + where + Q: QueryDescription<'tcx, Key = C::Key, Value = C::Value, Cache = C>, + { let lock = &mut *lookup.lock; let (latch, mut _query_blocked_prof_timer) = match lock.active.entry((*key).clone()) { @@ -154,7 +199,7 @@ impl<'tcx, Q: QueryDescription<'tcx>> JobOwner<'tcx, Q> { }; // Create the id of the job we're waiting for - let id = QueryJobId::new(job.id, lookup.shard, Q::dep_kind()); + let id = QueryJobId::new(job.id, lookup.shard, Q::DEP_KIND); (job.latch(id), _query_blocked_prof_timer) } @@ -169,13 +214,14 @@ impl<'tcx, Q: QueryDescription<'tcx>> JobOwner<'tcx, Q> { lock.jobs = id; let id = QueryShardJobId(NonZeroU32::new(id).unwrap()); - let global_id = QueryJobId::new(id, lookup.shard, Q::dep_kind()); + let global_id = QueryJobId::new(id, lookup.shard, Q::DEP_KIND); let job = tls::with_related_context(tcx, |icx| QueryJob::new(id, span, icx.query)); entry.insert(QueryResult::Started(job)); - let owner = JobOwner { tcx, id: global_id, key: (*key).clone() }; + let owner = + JobOwner { state: Q::query_state(tcx), id: global_id, key: (*key).clone() }; return TryGetJob::NotYetStarted(owner); } }; @@ -198,7 +244,8 @@ impl<'tcx, Q: QueryDescription<'tcx>> JobOwner<'tcx, Q> { return TryGetJob::Cycle(Q::handle_cycle_error(tcx, cycle)); } - let cached = tcx.try_get_cached::( + let cached = tcx.try_get_cached( + Q::query_state(tcx), (*key).clone(), |value, index| (value.clone(), index), |_, _| panic!("value must be in cache after waiting"), @@ -215,16 +262,15 @@ impl<'tcx, Q: QueryDescription<'tcx>> JobOwner<'tcx, Q> { /// Completes the query by updating the query cache with the `result`, /// signals the waiter and forgets the JobOwner, so it won't poison the query #[inline(always)] - pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) { + fn complete(self, tcx: TyCtxt<'tcx>, result: &C::Value, dep_node_index: DepNodeIndex) { // We can move out of `self` here because we `mem::forget` it below let key = unsafe { ptr::read(&self.key) }; - let tcx = self.tcx; + let state = self.state; // Forget ourself so our destructor won't poison the query mem::forget(self); let job = { - let state = Q::query_state(tcx); let result = result.clone(); let mut lock = state.shards.get_shard_by_value(&key).lock(); let job = match lock.active.remove(&key).unwrap() { @@ -249,12 +295,16 @@ where (result, diagnostics.into_inner()) } -impl<'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'tcx, Q> { +impl<'tcx, C: QueryCache> Drop for JobOwner<'tcx, C> +where + C::Key: Eq + Hash + Clone + Debug, + C::Value: Clone, +{ #[inline(never)] #[cold] fn drop(&mut self) { // Poison the query so jobs waiting on it panic. - let state = Q::query_state(self.tcx); + let state = self.state; let shard = state.shards.get_shard_by_value(&self.key); let job = { let mut shard = shard.lock(); @@ -272,25 +322,29 @@ impl<'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'tcx, Q> { } #[derive(Clone)] -pub struct CycleError<'tcx> { +pub(crate) struct CycleError<'tcx> { /// The query and related span that uses the cycle. pub(super) usage: Option<(Span, Query<'tcx>)>, pub(super) cycle: Vec>, } /// The result of `try_start`. -pub(super) enum TryGetJob<'tcx, D: QueryDescription<'tcx>> { +enum TryGetJob<'tcx, C: QueryCache> +where + C::Key: Eq + Hash + Clone + Debug, + C::Value: Clone, +{ /// The query is not yet started. Contains a guard to the cache eventually used to start it. - NotYetStarted(JobOwner<'tcx, D>), + NotYetStarted(JobOwner<'tcx, C>), /// The query was already completed. /// Returns the result of the query and its dep-node index /// if it succeeded or a cycle error if it failed. #[cfg(parallel_compiler)] - JobCompleted((D::Value, DepNodeIndex)), + JobCompleted((C::Value, DepNodeIndex)), /// Trying to execute the query resulted in a cycle. - Cycle(D::Value), + Cycle(C::Value), } impl<'tcx> TyCtxt<'tcx> { @@ -298,7 +352,7 @@ impl<'tcx> TyCtxt<'tcx> { /// new query job while it executes. It returns the diagnostics /// captured during execution and the actual result. #[inline(always)] - pub(super) fn start_query( + fn start_query( self, token: QueryJobId, diagnostics: Option<&Lock>>, @@ -419,23 +473,22 @@ impl<'tcx> TyCtxt<'tcx> { /// which will be used if the query is not in the cache and we need /// to compute it. #[inline(always)] - fn try_get_cached( + fn try_get_cached( self, - key: Q::Key, + state: &'tcx QueryState<'tcx, C>, + key: C::Key, // `on_hit` can be called while holding a lock to the query cache on_hit: OnHit, on_miss: OnMiss, ) -> R where - Q: QueryDescription<'tcx> + 'tcx, - OnHit: FnOnce(&Q::Value, DepNodeIndex) -> R, - OnMiss: FnOnce(Q::Key, QueryLookup<'tcx, Q>) -> R, + C: QueryCache, + OnHit: FnOnce(&C::Value, DepNodeIndex) -> R, + OnMiss: FnOnce(C::Key, QueryLookup<'tcx, C::Key, C::Sharded>) -> R, { - let state = Q::query_state(self); - state.cache.lookup( state, - QueryStateShard::::get_cache, + QueryStateShard::::get_cache, key, |value, index| { if unlikely!(self.prof.enabled()) { @@ -459,7 +512,8 @@ impl<'tcx> TyCtxt<'tcx> { ) -> Q::Value { debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span); - self.try_get_cached::( + self.try_get_cached( + Q::query_state(self), key, |value, index| { self.dep_graph.read_index(index); @@ -470,13 +524,13 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline(always)] - pub(super) fn try_execute_query>( + fn try_execute_query + 'tcx>( self, span: Span, key: Q::Key, - lookup: QueryLookup<'tcx, Q>, + lookup: QueryLookup<'tcx, Q::Key, ::Sharded>, ) -> Q::Value { - let job = match JobOwner::try_start(self, span, &key, lookup) { + let job = match JobOwner::try_start::(self, span, &key, lookup) { TryGetJob::NotYetStarted(job) => job, TryGetJob::Cycle(result) => return result, #[cfg(parallel_compiler)] @@ -498,7 +552,7 @@ impl<'tcx> TyCtxt<'tcx> { let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { self.start_query(job.id, diagnostics, |tcx| { - tcx.dep_graph.with_anon_task(Q::dep_kind(), || Q::compute(tcx, key)) + tcx.dep_graph.with_anon_task(Q::DEP_KIND, || Q::compute(tcx, key)) }) }); @@ -512,7 +566,7 @@ impl<'tcx> TyCtxt<'tcx> { .store_diagnostics_for_anon_node(dep_node_index, diagnostics); } - job.complete(&result, dep_node_index); + job.complete(self, &result, dep_node_index); return result; } @@ -538,7 +592,7 @@ impl<'tcx> TyCtxt<'tcx> { }) }); if let Some((result, dep_node_index)) = loaded { - job.complete(&result, dep_node_index); + job.complete(self, &result, dep_node_index); return result; } } @@ -634,10 +688,10 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline(always)] - fn force_query_with_job>( + fn force_query_with_job + 'tcx>( self, key: Q::Key, - job: JobOwner<'tcx, Q>, + job: JobOwner<'tcx, Q::Cache>, dep_node: DepNode, ) -> (Q::Value, DepNodeIndex) { // If the following assertion triggers, it can have two reasons: @@ -680,7 +734,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - job.complete(&result, dep_node_index); + job.complete(self, &result, dep_node_index); (result, dep_node_index) } @@ -729,13 +783,14 @@ impl<'tcx> TyCtxt<'tcx> { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. - self.try_get_cached::( + self.try_get_cached( + Q::query_state(self), key, |_, _| { // Cache hit, do nothing }, |key, lookup| { - let job = match JobOwner::try_start(self, span, &key, lookup) { + let job = match JobOwner::try_start::(self, span, &key, lookup) { TryGetJob::NotYetStarted(job) => job, TryGetJob::Cycle(_) => return, #[cfg(parallel_compiler)] @@ -842,55 +897,6 @@ macro_rules! define_queries_inner { input: ($(([$($modifiers)*] [$($attr)*] [$name]))*) } - impl<$tcx> Queries<$tcx> { - pub fn new( - providers: IndexVec>, - fallback_extern_providers: Providers<$tcx>, - on_disk_cache: OnDiskCache<'tcx>, - ) -> Self { - Queries { - providers, - fallback_extern_providers: Box::new(fallback_extern_providers), - on_disk_cache, - $($name: Default::default()),* - } - } - - pub fn try_collect_active_jobs( - &self - ) -> Option>> { - let mut jobs = FxHashMap::default(); - - $( - // We use try_lock_shards here since we are called from the - // deadlock handler, and this shouldn't be locked. - let shards = self.$name.shards.try_lock_shards()?; - let shards = shards.iter().enumerate(); - jobs.extend(shards.flat_map(|(shard_id, shard)| { - shard.active.iter().filter_map(move |(k, v)| { - if let QueryResult::Started(ref job) = *v { - let id = QueryJobId { - job: job.id, - shard: u16::try_from(shard_id).unwrap(), - kind: - as QueryAccessors<'tcx>>::dep_kind(), - }; - let info = QueryInfo { - span: job.span, - query: queries::$name::query(k.clone()) - }; - Some((id, QueryJobInfo { info, job: job.clone() })) - } else { - None - } - }) - })); - )* - - Some(jobs) - } - } - #[allow(nonstandard_style)] #[derive(Clone, Debug)] pub enum Query<$tcx> { @@ -951,16 +957,6 @@ macro_rules! define_queries_inner { })* } - // This module and the functions in it exist only to provide a - // predictable symbol name prefix for query providers. This is helpful - // for analyzing queries in profilers. - pub(super) mod __query_compute { - $(#[inline(never)] - pub fn $name R, R>(f: F) -> R { - f() - })* - } - $(impl<$tcx> QueryConfig<$tcx> for queries::$name<$tcx> { type Key = $K; type Value = $V; @@ -971,16 +967,12 @@ macro_rules! define_queries_inner { impl<$tcx> QueryAccessors<$tcx> for queries::$name<$tcx> { const ANON: bool = is_anon!([$($modifiers)*]); const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]); + const DEP_KIND: dep_graph::DepKind = dep_graph::DepKind::$node; type Cache = query_storage!([$($modifiers)*][$K, $V]); #[inline(always)] - fn query(key: Self::Key) -> Query<'tcx> { - Query::$name(key) - } - - #[inline(always)] - fn query_state<'a>(tcx: TyCtxt<$tcx>) -> &'a QueryState<$tcx, Self> { + fn query_state<'a>(tcx: TyCtxt<$tcx>) -> &'a QueryState<$tcx, Self::Cache> { &tcx.queries.$name } @@ -990,23 +982,16 @@ macro_rules! define_queries_inner { DepConstructor::$node(tcx, *key) } - #[inline(always)] - fn dep_kind() -> dep_graph::DepKind { - dep_graph::DepKind::$node - } - #[inline] fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value { - __query_compute::$name(move || { - let provider = tcx.queries.providers.get(key.query_crate()) - // HACK(eddyb) it's possible crates may be loaded after - // the query engine is created, and because crate loading - // is not yet integrated with the query engine, such crates - // would be missing appropriate entries in `providers`. - .unwrap_or(&tcx.queries.fallback_extern_providers) - .$name; - provider(tcx, key) - }) + let provider = tcx.queries.providers.get(key.query_crate()) + // HACK(eddyb) it's possible crates may be loaded after + // the query engine is created, and because crate loading + // is not yet integrated with the query engine, such crates + // would be missing appropriate entries in `providers`. + .unwrap_or(&tcx.queries.fallback_extern_providers) + .$name; + provider(tcx, key) } fn hash_result( @@ -1139,7 +1124,41 @@ macro_rules! define_queries_struct { providers: IndexVec>, fallback_extern_providers: Box>, - $($(#[$attr])* $name: QueryState<$tcx, queries::$name<$tcx>>,)* + $($(#[$attr])* $name: QueryState< + $tcx, + as QueryAccessors<'tcx>>::Cache, + >,)* + } + + impl<$tcx> Queries<$tcx> { + pub(crate) fn new( + providers: IndexVec>, + fallback_extern_providers: Providers<$tcx>, + on_disk_cache: OnDiskCache<'tcx>, + ) -> Self { + Queries { + providers, + fallback_extern_providers: Box::new(fallback_extern_providers), + on_disk_cache, + $($name: Default::default()),* + } + } + + pub(crate) fn try_collect_active_jobs( + &self + ) -> Option>> { + let mut jobs = FxHashMap::default(); + + $( + self.$name.try_collect_active_jobs( + as QueryAccessors<'tcx>>::DEP_KIND, + Query::$name, + &mut jobs, + )?; + )* + + Some(jobs) + } } }; } diff --git a/src/librustc/ty/query/profiling_support.rs b/src/librustc/ty/query/profiling_support.rs index 99ada34d59ebe..58ace917786cf 100644 --- a/src/librustc/ty/query/profiling_support.rs +++ b/src/librustc/ty/query/profiling_support.rs @@ -1,6 +1,6 @@ use crate::hir::map::definitions::DefPathData; use crate::ty::context::TyCtxt; -use crate::ty::query::config::QueryAccessors; +use crate::ty::query::caches::QueryCache; use crate::ty::query::plumbing::QueryState; use measureme::{StringComponent, StringId}; use rustc_data_structures::fx::FxHashMap; @@ -157,13 +157,14 @@ where /// Allocate the self-profiling query strings for a single query cache. This /// method is called from `alloc_self_profile_query_strings` which knows all /// the queries via macro magic. -pub(super) fn alloc_self_profile_query_strings_for_query_cache<'tcx, Q>( +pub(super) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( tcx: TyCtxt<'tcx>, query_name: &'static str, - query_state: &QueryState<'tcx, Q>, + query_state: &QueryState<'tcx, C>, string_cache: &mut QueryKeyStringCache, ) where - Q: QueryAccessors<'tcx>, + C: QueryCache, + C::Key: Debug + Clone, { tcx.prof.with_profiler(|profiler| { let event_id_builder = profiler.event_id_builder(); diff --git a/src/librustc/ty/query/stats.rs b/src/librustc/ty/query/stats.rs index d257320d4eaf6..527bb46c90888 100644 --- a/src/librustc/ty/query/stats.rs +++ b/src/librustc/ty/query/stats.rs @@ -1,3 +1,4 @@ +use crate::ty::query::caches::QueryCache; use crate::ty::query::config::QueryAccessors; use crate::ty::query::plumbing::QueryState; use crate::ty::query::queries; @@ -37,20 +38,17 @@ struct QueryStats { local_def_id_keys: Option, } -fn stats<'tcx, Q: QueryAccessors<'tcx>>( - name: &'static str, - map: &QueryState<'tcx, Q>, -) -> QueryStats { +fn stats<'tcx, C: QueryCache>(name: &'static str, map: &QueryState<'tcx, C>) -> QueryStats { let mut stats = QueryStats { name, #[cfg(debug_assertions)] cache_hits: map.cache_hits.load(Ordering::Relaxed), #[cfg(not(debug_assertions))] cache_hits: 0, - key_size: mem::size_of::(), - key_type: type_name::(), - value_size: mem::size_of::(), - value_type: type_name::(), + key_size: mem::size_of::(), + key_type: type_name::(), + value_size: mem::size_of::(), + value_type: type_name::(), entry_count: map.iter_results(|results| results.count()), local_def_id_keys: None, }; @@ -125,7 +123,9 @@ macro_rules! print_stats { let mut queries = Vec::new(); $($( - queries.push(stats::>( + queries.push(stats::< + as QueryAccessors<'_>>::Cache, + >( stringify!($name), &tcx.queries.$name, )); diff --git a/src/librustc_error_codes/error_codes/E0439.md b/src/librustc_error_codes/error_codes/E0439.md index e6da2117ac5f2..3e663df866caa 100644 --- a/src/librustc_error_codes/error_codes/E0439.md +++ b/src/librustc_error_codes/error_codes/E0439.md @@ -1,5 +1,6 @@ -The length of the platform-intrinsic function `simd_shuffle` -wasn't specified. Erroneous code example: +The length of the platform-intrinsic function `simd_shuffle` wasn't specified. + +Erroneous code example: ```compile_fail,E0439 #![feature(platform_intrinsics)] diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index 821c4d68c7e8a..873ebcf4d2452 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -144,7 +144,8 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> { let arguments = implicit_argument.into_iter().chain(explicit_arguments); let (yield_ty, return_ty) = if body.generator_kind.is_some() { - let gen_sig = match ty.kind { + let gen_ty = tcx.body_tables(body_id).node_type(id); + let gen_sig = match gen_ty.kind { ty::Generator(gen_def_id, gen_substs, ..) => { gen_substs.as_generator().sig(gen_def_id, tcx) } diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 51bf1f4843972..bc843fccc4c71 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -133,7 +133,7 @@ impl RegionExt for Region { /// that it corresponds to. /// /// FIXME. This struct gets converted to a `ResolveLifetimes` for -/// actual use. It has the same data, but indexed by `DefIndex`. This +/// actual use. It has the same data, but indexed by `LocalDefId`. This /// is silly. #[derive(Default)] struct NamedRegionMap { diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index 41c205bc11b35..dd261393e55db 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -188,12 +188,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { Node::Field(field) => icx.to_ty(&field.ty), Node::Expr(&Expr { kind: ExprKind::Closure(.., gen), .. }) => { - if gen.is_some() { - return tcx.typeck_tables_of(def_id).node_type(hir_id); - } - let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_closure(def_id, substs) + if let Some(movability) = gen { + tcx.mk_generator(def_id, substs, movability) + } else { + tcx.mk_closure(def_id, substs) + } } Node::AnonConst(_) => { diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr index afb8f146192cc..46a132da309bb 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -18,22 +18,6 @@ LL | | break 0u8; LL | | }; | |_________- enclosing `async` block -error[E0308]: mismatched types - --> $DIR/async-block-control-flow-static-semantics.rs:13:43 - | -LL | fn return_targets_async_block_not_fn() -> u8 { - | --------------------------------- ^^ expected `u8`, found `()` - | | - | implicitly returns `()` as its body has no tail or `return` expression - -error[E0271]: type mismatch resolving `::Output == ()` - --> $DIR/async-block-control-flow-static-semantics.rs:18:39 - | -LL | let _: &dyn Future = █ - | ^^^^^^ expected `()`, found `u8` - | - = note: required for the cast to the object type `dyn std::future::Future` - error[E0308]: mismatched types --> $DIR/async-block-control-flow-static-semantics.rs:22:58 | @@ -55,6 +39,22 @@ LL | let _: &dyn Future = █ | = note: required for the cast to the object type `dyn std::future::Future` +error[E0308]: mismatched types + --> $DIR/async-block-control-flow-static-semantics.rs:13:43 + | +LL | fn return_targets_async_block_not_fn() -> u8 { + | --------------------------------- ^^ expected `u8`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error[E0271]: type mismatch resolving `::Output == ()` + --> $DIR/async-block-control-flow-static-semantics.rs:18:39 + | +LL | let _: &dyn Future = █ + | ^^^^^^ expected `()`, found `u8` + | + = note: required for the cast to the object type `dyn std::future::Future` + error[E0308]: mismatched types --> $DIR/async-block-control-flow-static-semantics.rs:48:44 | diff --git a/src/test/ui/async-await/async-error-span.rs b/src/test/ui/async-await/async-error-span.rs index 28132c9789c67..cf10ebfeca939 100644 --- a/src/test/ui/async-await/async-error-span.rs +++ b/src/test/ui/async-await/async-error-span.rs @@ -5,6 +5,7 @@ use std::future::Future; fn get_future() -> impl Future { +//~^ ERROR the trait bound `(): std::future::Future` is not satisfied panic!() } diff --git a/src/test/ui/async-await/async-error-span.stderr b/src/test/ui/async-await/async-error-span.stderr index b551b99587dd9..4054e739c483d 100644 --- a/src/test/ui/async-await/async-error-span.stderr +++ b/src/test/ui/async-await/async-error-span.stderr @@ -1,15 +1,27 @@ +error[E0277]: the trait bound `(): std::future::Future` is not satisfied + --> $DIR/async-error-span.rs:7:20 + | +LL | fn get_future() -> impl Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `()` +LL | +LL | panic!() + | -------- this returned value is of type `!` + | + = note: the return type of a function must have a statically known size + error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/async-error-span.rs:12:9 + --> $DIR/async-error-span.rs:13:9 | LL | let a; | ^ cannot infer type | note: the type is part of the `async fn` body because of this `await` - --> $DIR/async-error-span.rs:13:5 + --> $DIR/async-error-span.rs:14:5 | LL | get_future().await; | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0698`. +Some errors have detailed explanations: E0277, E0698. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs index 22bcbb1064dd7..cebff3be6b059 100644 --- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs +++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs @@ -62,6 +62,7 @@ fn foo10() -> Result<(), ()> { fn foo11() -> Result<(), ()> { let _ = await bar()?; //~ ERROR `await` is only allowed inside `async` functions and blocks //~^ ERROR incorrect use of `await` + //~| ERROR the `?` operator can only be applied to values that implement `std::ops::Try` Ok(()) } fn foo12() -> Result<(), ()> { diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr index 92cef80c19360..61f2570b2ff93 100644 --- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr +++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -71,49 +71,49 @@ LL | let _ = await bar()?; | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:68:14 + --> $DIR/incorrect-syntax-suggestions.rs:69:14 | LL | let _ = (await bar())?; | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:73:24 + --> $DIR/incorrect-syntax-suggestions.rs:74:24 | LL | let _ = bar().await(); | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:78:24 + --> $DIR/incorrect-syntax-suggestions.rs:79:24 | LL | let _ = bar().await()?; | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:106:13 + --> $DIR/incorrect-syntax-suggestions.rs:107:13 | LL | let _ = await!(bar()); | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:110:13 + --> $DIR/incorrect-syntax-suggestions.rs:111:13 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:115:17 + --> $DIR/incorrect-syntax-suggestions.rs:116:17 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:123:17 + --> $DIR/incorrect-syntax-suggestions.rs:124:17 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: expected expression, found `=>` - --> $DIR/incorrect-syntax-suggestions.rs:131:25 + --> $DIR/incorrect-syntax-suggestions.rs:132:25 | LL | match await { await => () } | ----- ^^ expected expression @@ -121,13 +121,13 @@ LL | match await { await => () } | while parsing this incorrect await expression error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:131:11 + --> $DIR/incorrect-syntax-suggestions.rs:132:11 | LL | match await { await => () } | ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await` error: expected one of `.`, `?`, `{`, or an operator, found `}` - --> $DIR/incorrect-syntax-suggestions.rs:134:1 + --> $DIR/incorrect-syntax-suggestions.rs:135:1 | LL | match await { await => () } | ----- - expected one of `.`, `?`, `{`, or an operator @@ -162,7 +162,7 @@ LL | let _ = await bar()?; | ^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:68:14 + --> $DIR/incorrect-syntax-suggestions.rs:69:14 | LL | fn foo12() -> Result<(), ()> { | ----- this is not `async` @@ -170,7 +170,7 @@ LL | let _ = (await bar())?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:73:13 + --> $DIR/incorrect-syntax-suggestions.rs:74:13 | LL | fn foo13() -> Result<(), ()> { | ----- this is not `async` @@ -178,7 +178,7 @@ LL | let _ = bar().await(); | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:78:13 + --> $DIR/incorrect-syntax-suggestions.rs:79:13 | LL | fn foo14() -> Result<(), ()> { | ----- this is not `async` @@ -186,7 +186,7 @@ LL | let _ = bar().await()?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:83:13 + --> $DIR/incorrect-syntax-suggestions.rs:84:13 | LL | fn foo15() -> Result<(), ()> { | ----- this is not `async` @@ -194,7 +194,7 @@ LL | let _ = bar().await; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:87:13 + --> $DIR/incorrect-syntax-suggestions.rs:88:13 | LL | fn foo16() -> Result<(), ()> { | ----- this is not `async` @@ -202,7 +202,7 @@ LL | let _ = bar().await?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:92:17 + --> $DIR/incorrect-syntax-suggestions.rs:93:17 | LL | fn foo() -> Result<(), ()> { | --- this is not `async` @@ -210,7 +210,7 @@ LL | let _ = bar().await?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:99:17 + --> $DIR/incorrect-syntax-suggestions.rs:100:17 | LL | let foo = || { | -- this is not `async` @@ -218,7 +218,7 @@ LL | let _ = bar().await?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:115:17 + --> $DIR/incorrect-syntax-suggestions.rs:116:17 | LL | fn foo() -> Result<(), ()> { | --- this is not `async` @@ -226,7 +226,7 @@ LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:123:17 + --> $DIR/incorrect-syntax-suggestions.rs:124:17 | LL | let foo = || { | -- this is not `async` @@ -242,7 +242,16 @@ LL | let _ = await bar()?; = help: the trait `std::ops::Try` is not implemented for `impl std::future::Future` = note: required by `std::ops::Try::into_result` -error: aborting due to 35 previous errors +error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` + --> $DIR/incorrect-syntax-suggestions.rs:63:19 + | +LL | let _ = await bar()?; + | ^^^^^^ the `?` operator cannot be applied to type `impl std::future::Future` + | + = help: the trait `std::ops::Try` is not implemented for `impl std::future::Future` + = note: required by `std::ops::Try::into_result` + +error: aborting due to 36 previous errors Some errors have detailed explanations: E0277, E0728. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issue-67651.rs b/src/test/ui/async-await/issue-67651.rs new file mode 100644 index 0000000000000..bd96a3b709bae --- /dev/null +++ b/src/test/ui/async-await/issue-67651.rs @@ -0,0 +1,20 @@ +// edition:2018 + +trait From { + fn from(); +} + +impl From for () { + fn from() {} +} + +impl From for () { +//~^ ERROR conflicting implementations of trait + fn from() {} +} + +fn bar() -> impl core::future::Future { + async move { From::from() } +} + +fn main() {} diff --git a/src/test/ui/async-await/issue-67651.stderr b/src/test/ui/async-await/issue-67651.stderr new file mode 100644 index 0000000000000..99857c215eb8f --- /dev/null +++ b/src/test/ui/async-await/issue-67651.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `From` for type `()`: + --> $DIR/issue-67651.rs:11:1 + | +LL | impl From for () { + | ---------------- first implementation here +... +LL | impl From for () { + | ^^^^^^^^^^^^^^^^ conflicting implementation for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/async-await/issues/issue-63388-2.nll.stderr b/src/test/ui/async-await/issues/issue-63388-2.nll.stderr deleted file mode 100644 index 6edb9e63d480a..0000000000000 --- a/src/test/ui/async-await/issues/issue-63388-2.nll.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0106]: missing lifetime specifier - --> $DIR/issue-63388-2.rs:12:10 - | -LL | foo: &dyn Foo, bar: &'a dyn Foo - | -------- ----------- -LL | ) -> &dyn Foo - | ^ help: consider using the named lifetime: `&'a` - | - = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/async-await/issues/issue-63388-2.rs b/src/test/ui/async-await/issues/issue-63388-2.rs index 73e7f25f97d0d..458bc9faeaf27 100644 --- a/src/test/ui/async-await/issues/issue-63388-2.rs +++ b/src/test/ui/async-await/issues/issue-63388-2.rs @@ -8,7 +8,7 @@ trait Foo {} impl Xyz { async fn do_sth<'a>( - foo: &dyn Foo, bar: &'a dyn Foo //~ ERROR cannot infer + foo: &dyn Foo, bar: &'a dyn Foo ) -> &dyn Foo //~ ERROR missing lifetime specifier { foo diff --git a/src/test/ui/async-await/issues/issue-63388-2.stderr b/src/test/ui/async-await/issues/issue-63388-2.stderr index 9f51ced9c3f49..6edb9e63d480a 100644 --- a/src/test/ui/async-await/issues/issue-63388-2.stderr +++ b/src/test/ui/async-await/issues/issue-63388-2.stderr @@ -8,21 +8,6 @@ LL | ) -> &dyn Foo | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar` -error: cannot infer an appropriate lifetime - --> $DIR/issue-63388-2.rs:11:9 - | -LL | foo: &dyn Foo, bar: &'a dyn Foo - | ^^^ ...but this borrow... -... -LL | foo - | --- this return type evaluates to the `'static` lifetime... - | -note: ...can't outlive the lifetime `'_` as defined on the method body at 11:14 - --> $DIR/issue-63388-2.rs:11:14 - | -LL | foo: &dyn Foo, bar: &'a dyn Foo - | ^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/async-await/issues/issue-65159.rs b/src/test/ui/async-await/issues/issue-65159.rs index b5fee061f277e..2f80435046bdf 100644 --- a/src/test/ui/async-await/issues/issue-65159.rs +++ b/src/test/ui/async-await/issues/issue-65159.rs @@ -5,6 +5,7 @@ async fn copy() -> Result<()> //~ ERROR wrong number of type arguments { Ok(()) + //~^ type annotations needed } fn main() { } diff --git a/src/test/ui/async-await/issues/issue-65159.stderr b/src/test/ui/async-await/issues/issue-65159.stderr index 56d2c38b302e9..04cfa5249982e 100644 --- a/src/test/ui/async-await/issues/issue-65159.stderr +++ b/src/test/ui/async-await/issues/issue-65159.stderr @@ -4,6 +4,13 @@ error[E0107]: wrong number of type arguments: expected 2, found 1 LL | async fn copy() -> Result<()> | ^^^^^^^^^^ expected 2 type arguments -error: aborting due to previous error +error[E0282]: type annotations needed + --> $DIR/issue-65159.rs:7:5 + | +LL | Ok(()) + | ^^ cannot infer type for type parameter `E` declared on the enum `Result` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0107, E0282. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs index b12d7bccecead..05960c0c7f636 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs @@ -9,6 +9,9 @@ impl Trait<'_, '_> for T { } async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> { //~^ ERROR ambiguous lifetime bound //~| ERROR ambiguous lifetime bound + //~| ERROR ambiguous lifetime bound + //~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds + //~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds (a, b) } diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr index f9a1b4b3394c1..c69595a3f4d01 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr @@ -14,5 +14,42 @@ LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<' | = help: add #![feature(member_constraints)] to the crate attributes to enable -error: aborting due to 2 previous errors +error: ambiguous lifetime bound in `impl Trait` + --> $DIR/ret-impl-trait-no-fg.rs:9:64 + | +LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> { + | ^^^^^^^^^^^^^^^^^^ the elided lifetimes here do not outlive one another + | + = help: add #![feature(member_constraints)] to the crate attributes to enable + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ret-impl-trait-no-fg.rs:9:1 + | +LL | / async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> { +LL | | +LL | | +LL | | +... | +LL | | (a, b) +LL | | } + | |_^ + | + = note: hidden type `(&u8, &u8)` captures lifetime '_#4r + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ret-impl-trait-no-fg.rs:9:1 + | +LL | / async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> { +LL | | +LL | | +LL | | +... | +LL | | (a, b) +LL | | } + | |_^ + | + = note: hidden type `(&u8, &u8)` captures lifetime '_#5r + +error: aborting due to 5 previous errors +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/consts/const_forget.rs b/src/test/ui/consts/const_forget.rs new file mode 100644 index 0000000000000..2dcb72a5a09cb --- /dev/null +++ b/src/test/ui/consts/const_forget.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(const_forget)] + +use std::mem::forget; + +const _: () = forget(0i32); +const _: () = forget(Vec::>>::new()); + +// Writing this function signature without const-forget +// triggers compiler errors: +// 1) That we use a non-const fn inside a const fn +// 2) without the forget, it complains about the destructor of Box +// +// FIXME: this method cannot be called in const-eval yet, as Box isn't +// const constructable +#[allow(unused)] +const fn const_forget_box(b: Box) { + forget(b); +} + +fn main() {} diff --git a/src/test/ui/self/elision/ref-self-async.nll.stderr b/src/test/ui/self/elision/ref-self-async.nll.stderr deleted file mode 100644 index 541e49543221e..0000000000000 --- a/src/test/ui/self/elision/ref-self-async.nll.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: `Wrap<&Struct, Struct>` cannot be used as the type of `self` without the `arbitrary_self_types` feature - --> $DIR/ref-self-async.rs:47:39 - | -LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #44874 for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/self/elision/ref-self-async.rs b/src/test/ui/self/elision/ref-self-async.rs index 6a98b79cb3bba..0fbbd95c975d6 100644 --- a/src/test/ui/self/elision/ref-self-async.rs +++ b/src/test/ui/self/elision/ref-self-async.rs @@ -1,6 +1,7 @@ // edition:2018 #![allow(non_snake_case)] +#![feature(arbitrary_self_types)] use std::marker::PhantomData; use std::ops::Deref; diff --git a/src/test/ui/self/elision/ref-self-async.stderr b/src/test/ui/self/elision/ref-self-async.stderr index b73290b024f8f..bda958241b67b 100644 --- a/src/test/ui/self/elision/ref-self-async.stderr +++ b/src/test/ui/self/elision/ref-self-async.stderr @@ -1,5 +1,5 @@ error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:22:9 + --> $DIR/ref-self-async.rs:23:9 | LL | async fn ref_self(&self, f: &u32) -> &u32 { | ----- ---- @@ -9,7 +9,7 @@ LL | f | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:28:9 + --> $DIR/ref-self-async.rs:29:9 | LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { | ----- ---- @@ -19,7 +19,7 @@ LL | f | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:32:9 + --> $DIR/ref-self-async.rs:33:9 | LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { | ----- ---- @@ -29,7 +29,7 @@ LL | f | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:36:9 + --> $DIR/ref-self-async.rs:37:9 | LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { | ----- ---- @@ -39,7 +39,7 @@ LL | f | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:40:9 + --> $DIR/ref-self-async.rs:41:9 | LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | ----- ---- @@ -49,7 +49,7 @@ LL | f | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:44:9 + --> $DIR/ref-self-async.rs:45:9 | LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { | ----- ---- @@ -59,7 +59,7 @@ LL | f | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:48:9 + --> $DIR/ref-self-async.rs:49:9 | LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { | ----- ---