diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index 557dfe09853ba..bdfe7bfb8f1fb 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -283,3 +283,12 @@ impl NoArgsAttributeParser for RustcPreserveUbChecksParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks; } + +pub(crate) struct RustcNoImplicitBoundsParser; + +impl NoArgsAttributeParser for RustcNoImplicitBoundsParser { + const PATH: &[Symbol] = &[sym::rustc_no_implicit_bounds]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index afbb70654f4d0..573e14786abf4 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -281,6 +281,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 361e98454e836..38b73a07a6891 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -121,6 +121,11 @@ fn mir_borrowck( let (input_body, _) = tcx.mir_promoted(def); debug!("run query mir_borrowck: {}", tcx.def_path_str(def)); + // We should eagerly check stalled coroutine obligations from HIR typeck. + // Not doing so leads to silent normalization failures later, which will + // fail to register opaque types in the next solver. + tcx.check_coroutine_obligations(def)?; + let input_body: &Body<'_> = &input_body.borrow(); if let Some(guar) = input_body.tainted_by_errors { debug!("Skipping borrowck because of tainted body"); diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index ef790fe76b74f..869e3f43ea710 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1177,6 +1177,9 @@ pub enum AttributeKind { /// Represents `#[rustc_no_implicit_autorefs]` RustcNoImplicitAutorefs, + /// Represents `#[rustc_no_implicit_bounds]` + RustcNoImplicitBounds, + /// Represents `#[rustc_non_const_trait_method]`. RustcNonConstTraitMethod, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index cba7679d2df31..001448b3e72e5 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -137,6 +137,7 @@ impl AttributeKind { RustcMustImplementOneOf { .. } => No, RustcNeverReturnsNullPointer => Yes, RustcNoImplicitAutorefs => Yes, + RustcNoImplicitBounds => No, RustcNonConstTraitMethod => No, // should be reported via other queries like `constness` RustcNounwind => No, RustcObjcClass { .. } => No, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index a1c3af5f999d4..85e96e200c2e1 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -4,15 +4,16 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; -use rustc_hir::PolyTraitRef; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; +use rustc_hir::{PolyTraitRef, find_attr}; use rustc_middle::bug; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, }; -use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; +use rustc_span::{ErrorGuaranteed, Ident, Span, kw}; use rustc_trait_selection::traits; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -170,7 +171,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); // Skip adding any default bounds if `#![rustc_no_implicit_bounds]` - if tcx.has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) { + if find_attr!(tcx.get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNoImplicitBounds) { return; } @@ -284,7 +285,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { context: ImpliedBoundsContext<'tcx>, ) -> bool { let collected = collect_bounds(hir_bounds, context, trait_def_id); - !self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any() + !find_attr!(self.tcx().get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNoImplicitBounds) + && !collected.any() } fn reject_duplicate_relaxed_bounds(&self, relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>) { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 42ef66847858a..e474f106433df 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1116,18 +1116,14 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { { tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id); } - if tcx.is_coroutine(def_id.to_def_id()) { - tcx.ensure_ok().mir_coroutine_witnesses(def_id); - let _ = tcx.ensure_ok().check_coroutine_obligations( - tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(), + if tcx.is_coroutine(def_id.to_def_id()) + && (!tcx.is_async_drop_in_place_coroutine(def_id.to_def_id())) + { + // Eagerly check the unsubstituted layout for cycles. + tcx.ensure_ok().layout_of( + ty::TypingEnv::post_analysis(tcx, def_id.to_def_id()) + .as_query_input(tcx.type_of(def_id).instantiate_identity()), ); - if !tcx.is_async_drop_in_place_coroutine(def_id.to_def_id()) { - // Eagerly check the unsubstituted layout for cycles. - tcx.ensure_ok().layout_of( - ty::TypingEnv::post_analysis(tcx, def_id.to_def_id()) - .as_query_input(tcx.type_of(def_id).instantiate_identity()), - ); - } } }); }); diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs index fa9995898ac20..a06f927928205 100644 --- a/compiler/rustc_middle/src/ty/context/tls.rs +++ b/compiler/rustc_middle/src/ty/context/tls.rs @@ -16,8 +16,7 @@ pub struct ImplicitCtxt<'a, 'tcx> { /// The current `TyCtxt`. pub tcx: TyCtxt<'tcx>, - /// The current query job, if any. This is updated by `JobOwner::start` in - /// `ty::query::plumbing` when executing a query. + /// The current query job, if any. pub query: Option, /// Used to prevent queries from calling too deeply. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index dd0de90d575b5..2dcfbaaef5794 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -330,6 +330,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcMir(_) | AttributeKind::RustcNeverReturnsNullPointer | AttributeKind::RustcNoImplicitAutorefs + | AttributeKind::RustcNoImplicitBounds | AttributeKind::RustcNonConstTraitMethod | AttributeKind::RustcNounwind | AttributeKind::RustcObjcClass { .. } @@ -413,7 +414,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // crate-level attrs, are checked below | sym::feature | sym::register_tool - | sym::rustc_no_implicit_bounds | sym::test_runner, .. ] => {} diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index ba442d8a0081d..88604c91d0259 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -83,14 +83,18 @@ pub(crate) fn gather_active_jobs_inner<'tcx, K: Copy>( Some(()) } -/// A type representing the responsibility to execute the job in the `job` field. -/// This will poison the relevant query if dropped. -struct JobOwner<'tcx, K> +/// Guard object representing the responsibility to execute a query job and +/// mark it as completed. +/// +/// This will poison the relevant query key if it is dropped without calling +/// [`Self::complete`]. +struct ActiveJobGuard<'tcx, K> where K: Eq + Hash + Copy, { state: &'tcx QueryState<'tcx, K>, key: K, + key_hash: u64, } #[cold] @@ -137,20 +141,19 @@ fn handle_cycle_error<'tcx, C: QueryCache, const FLAGS: QueryFlags>( } } -impl<'tcx, K> JobOwner<'tcx, K> +impl<'tcx, K> ActiveJobGuard<'tcx, K> where K: Eq + Hash + Copy, { /// 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 - fn complete(self, cache: &C, key_hash: u64, result: C::Value, dep_node_index: DepNodeIndex) + /// signals the waiter, and forgets the guard so it won't poison the query. + fn complete(self, cache: &C, result: C::Value, dep_node_index: DepNodeIndex) where C: QueryCache, { - let key = self.key; - let state = self.state; - - // Forget ourself so our destructor won't poison the query + // Forget ourself so our destructor won't poison the query. + // (Extract fields by value first to make sure we don't leak anything.) + let Self { state, key, key_hash }: Self = self; mem::forget(self); // Mark as complete before we remove the job from the active state @@ -174,7 +177,7 @@ where } } -impl<'tcx, K> Drop for JobOwner<'tcx, K> +impl<'tcx, K> Drop for ActiveJobGuard<'tcx, K> where K: Eq + Hash + Copy, { @@ -182,11 +185,10 @@ where #[cold] fn drop(&mut self) { // Poison the query so jobs waiting on it panic. - let state = self.state; + let Self { state, key, key_hash } = *self; let job = { - let key_hash = sharded::make_hash(&self.key); let mut shard = state.active.lock_shard_by_hash(key_hash); - match shard.find_entry(key_hash, equivalent_key(&self.key)) { + match shard.find_entry(key_hash, equivalent_key(&key)) { Err(_) => panic!(), Ok(occupied) => { let ((key, value), vacant) = occupied.remove(); @@ -342,11 +344,13 @@ fn execute_job<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>( id: QueryJobId, dep_node: Option, ) -> (C::Value, Option) { - // Use `JobOwner` so the query will be poisoned if executing it panics. - let job_owner = JobOwner { state, key }; + // Set up a guard object that will automatically poison the query if a + // panic occurs while executing the query (or any intermediate plumbing). + let job_guard = ActiveJobGuard { state, key, key_hash }; debug_assert_eq!(qcx.tcx.dep_graph.is_fully_enabled(), INCR); + // Delegate to another function to actually execute the query job. let (result, dep_node_index) = if INCR { execute_job_incr(query, qcx, qcx.tcx.dep_graph.data().unwrap(), key, dep_node, id) } else { @@ -388,7 +392,9 @@ fn execute_job<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>( } } } - job_owner.complete(cache, key_hash, result, dep_node_index); + + // Tell the guard to perform completion bookkeeping, and also to not poison the query. + job_guard.complete(cache, result, dep_node_index); (result, Some(dep_node_index)) } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 661ea4ab6a27f..a9e7c49515c7f 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -689,6 +689,30 @@ impl, U> CoerceUnsized> for Cell {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U> DispatchFromDyn> for Cell {} +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[Cell; N]> for Cell<[T; N]> { + #[inline] + fn as_ref(&self) -> &[Cell; N] { + self.as_array_of_cells() + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[Cell]> for Cell<[T; N]> { + #[inline] + fn as_ref(&self) -> &[Cell] { + &*self.as_array_of_cells() + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[Cell]> for Cell<[T]> { + #[inline] + fn as_ref(&self) -> &[Cell] { + self.as_slice_of_cells() + } +} + impl Cell<[T]> { /// Returns a `&[Cell]` from a `&Cell<[T]>` /// diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 320eb97f83a43..5941477201933 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1532,6 +1532,56 @@ impl MaybeUninit<[T; N]> { } } +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl From<[MaybeUninit; N]> for MaybeUninit<[T; N]> { + #[inline] + fn from(arr: [MaybeUninit; N]) -> Self { + arr.transpose() + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[MaybeUninit; N]> for MaybeUninit<[T; N]> { + #[inline] + fn as_ref(&self) -> &[MaybeUninit; N] { + // SAFETY: T and MaybeUninit have the same layout + unsafe { &*ptr::from_ref(self).cast() } + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[MaybeUninit]> for MaybeUninit<[T; N]> { + #[inline] + fn as_ref(&self) -> &[MaybeUninit] { + &*AsRef::<[MaybeUninit; N]>::as_ref(self) + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsMut<[MaybeUninit; N]> for MaybeUninit<[T; N]> { + #[inline] + fn as_mut(&mut self) -> &mut [MaybeUninit; N] { + // SAFETY: T and MaybeUninit have the same layout + unsafe { &mut *ptr::from_mut(self).cast() } + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsMut<[MaybeUninit]> for MaybeUninit<[T; N]> { + #[inline] + fn as_mut(&mut self) -> &mut [MaybeUninit] { + &mut *AsMut::<[MaybeUninit; N]>::as_mut(self) + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl From> for [MaybeUninit; N] { + #[inline] + fn from(arr: MaybeUninit<[T; N]>) -> Self { + arr.transpose() + } +} + impl [MaybeUninit; N] { /// Transposes a `[MaybeUninit; N]` into a `MaybeUninit<[T; N]>`. /// diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index a289b0d6df401..ac096afb38af0 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2175,7 +2175,7 @@ unsafe impl Sync for ChunksExactMut<'_, T> where T: Sync {} /// /// [`array_windows`]: slice::array_windows /// [slices]: slice -#[derive(Debug, Clone, Copy)] +#[derive(Debug)] #[stable(feature = "array_windows", since = "1.94.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ArrayWindows<'a, T: 'a, const N: usize> { @@ -2189,6 +2189,14 @@ impl<'a, T: 'a, const N: usize> ArrayWindows<'a, T, N> { } } +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "array_windows", since = "1.94.0")] +impl Clone for ArrayWindows<'_, T, N> { + fn clone(&self) -> Self { + Self { v: self.v } + } +} + #[stable(feature = "array_windows", since = "1.94.0")] impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> { type Item = &'a [T; N]; @@ -2224,6 +2232,14 @@ impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> { fn last(self) -> Option { self.v.last_chunk() } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + // SAFETY: since the caller guarantees that `idx` is in bounds, + // which means that `idx` cannot overflow an `isize`, and the + // "slice" created by `cast_array` is a subslice of `self.v` + // thus is guaranteed to be valid for the lifetime `'a` of `self.v`. + unsafe { &*self.v.as_ptr().add(idx).cast_array() } + } } #[stable(feature = "array_windows", since = "1.94.0")] @@ -2252,6 +2268,22 @@ impl ExactSizeIterator for ArrayWindows<'_, T, N> { } } +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ArrayWindows<'_, T, N> {} + +#[stable(feature = "array_windows", since = "1.94.0")] +impl FusedIterator for ArrayWindows<'_, T, N> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for ArrayWindows<'_, T, N> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccessNoCoerce for ArrayWindows<'_, T, N> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + /// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a /// time), starting at the end of the slice. /// diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 8f4a79b389f62..02a408802b6fa 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -121,7 +121,7 @@ macro_rules! define_client_side { } } } -with_api!(self, define_client_side); +with_api!(define_client_side, TokenStream, Span, Symbol); struct Bridge<'a> { /// Reusable buffer (only `clear`-ed, never shrunk), primarily @@ -129,7 +129,7 @@ struct Bridge<'a> { cached_buffer: Buffer, /// Server-side function that the client uses to make requests. - dispatch: closure::Closure<'a, Buffer, Buffer>, + dispatch: closure::Closure<'a>, /// Provided globals for this macro expansion. globals: ExpnGlobals, diff --git a/library/proc_macro/src/bridge/closure.rs b/library/proc_macro/src/bridge/closure.rs index e5133907854b2..88c4dd6630b15 100644 --- a/library/proc_macro/src/bridge/closure.rs +++ b/library/proc_macro/src/bridge/closure.rs @@ -1,10 +1,12 @@ -//! Closure type (equivalent to `&mut dyn FnMut(A) -> R`) that's `repr(C)`. +//! Closure type (equivalent to `&mut dyn FnMut(Buffer) -> Buffer`) that's `repr(C)`. use std::marker::PhantomData; +use super::Buffer; + #[repr(C)] -pub(super) struct Closure<'a, A, R> { - call: unsafe extern "C" fn(*mut Env, A) -> R, +pub(super) struct Closure<'a> { + call: extern "C" fn(*mut Env, Buffer) -> Buffer, env: *mut Env, // Prevent Send and Sync impls. // @@ -14,17 +16,17 @@ pub(super) struct Closure<'a, A, R> { struct Env; -impl<'a, A, R, F: FnMut(A) -> R> From<&'a mut F> for Closure<'a, A, R> { +impl<'a, F: FnMut(Buffer) -> Buffer> From<&'a mut F> for Closure<'a> { fn from(f: &'a mut F) -> Self { - unsafe extern "C" fn call R>(env: *mut Env, arg: A) -> R { + extern "C" fn call Buffer>(env: *mut Env, arg: Buffer) -> Buffer { unsafe { (*(env as *mut _ as *mut F))(arg) } } - Closure { call: call::, env: f as *mut _ as *mut Env, _marker: PhantomData } + Closure { call: call::, env: f as *mut _ as *mut Env, _marker: PhantomData } } } -impl<'a, A, R> Closure<'a, A, R> { - pub(super) fn call(&mut self, arg: A) -> R { - unsafe { (self.call)(self.env, arg) } +impl<'a> Closure<'a> { + pub(super) fn call(&mut self, arg: Buffer) -> Buffer { + (self.call)(self.env, arg) } } diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 244ab7d81b022..6a9027046af00 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -18,71 +18,67 @@ use crate::{Delimiter, Level}; /// Higher-order macro describing the server RPC API, allowing automatic /// generation of type-safe Rust APIs, both client-side and server-side. /// -/// `with_api!(MySelf, my_macro)` expands to: +/// `with_api!(my_macro, MyTokenStream, MySpan, MySymbol)` expands to: /// ```rust,ignore (pseudo-code) /// my_macro! { -/// fn lit_character(ch: char) -> MySelf::Literal; -/// fn lit_span(lit: &MySelf::Literal) -> MySelf::Span; -/// fn lit_set_span(lit: &mut MySelf::Literal, span: MySelf::Span); +/// fn ts_clone(stream: &MyTokenStream) -> MyTokenStream; +/// fn span_debug(span: &MySpan) -> String; /// // ... /// } /// ``` /// -/// The first argument serves to customize the argument/return types, -/// to enable several different usecases: -/// -/// If `MySelf` is just `Self`, then the types are only valid inside -/// a trait or a trait impl, where the trait has associated types -/// for each of the API types. If non-associated types are desired, -/// a module name (`self` in practice) can be used instead of `Self`. +/// The second (`TokenStream`), third (`Span`) and fourth (`Symbol`) +/// argument serve to customize the argument/return types that need +/// special handling, to enable several different representations of +/// these types. macro_rules! with_api { - ($S:ident, $m:ident) => { + ($m:ident, $TokenStream: path, $Span: path, $Symbol: path) => { $m! { fn injected_env_var(var: &str) -> Option; fn track_env_var(var: &str, value: Option<&str>); fn track_path(path: &str); - fn literal_from_str(s: &str) -> Result, ()>; - fn emit_diagnostic(diagnostic: Diagnostic<$S::Span>); - - fn ts_drop(stream: $S::TokenStream); - fn ts_clone(stream: &$S::TokenStream) -> $S::TokenStream; - fn ts_is_empty(stream: &$S::TokenStream) -> bool; - fn ts_expand_expr(stream: &$S::TokenStream) -> Result<$S::TokenStream, ()>; - fn ts_from_str(src: &str) -> $S::TokenStream; - fn ts_to_string(stream: &$S::TokenStream) -> String; + fn literal_from_str(s: &str) -> Result, ()>; + fn emit_diagnostic(diagnostic: Diagnostic<$Span>); + + fn ts_drop(stream: $TokenStream); + fn ts_clone(stream: &$TokenStream) -> $TokenStream; + fn ts_is_empty(stream: &$TokenStream) -> bool; + fn ts_expand_expr(stream: &$TokenStream) -> Result<$TokenStream, ()>; + fn ts_from_str(src: &str) -> $TokenStream; + fn ts_to_string(stream: &$TokenStream) -> String; fn ts_from_token_tree( - tree: TokenTree<$S::TokenStream, $S::Span, $S::Symbol>, - ) -> $S::TokenStream; + tree: TokenTree<$TokenStream, $Span, $Symbol>, + ) -> $TokenStream; fn ts_concat_trees( - base: Option<$S::TokenStream>, - trees: Vec>, - ) -> $S::TokenStream; + base: Option<$TokenStream>, + trees: Vec>, + ) -> $TokenStream; fn ts_concat_streams( - base: Option<$S::TokenStream>, - streams: Vec<$S::TokenStream>, - ) -> $S::TokenStream; + base: Option<$TokenStream>, + streams: Vec<$TokenStream>, + ) -> $TokenStream; fn ts_into_trees( - stream: $S::TokenStream - ) -> Vec>; - - fn span_debug(span: $S::Span) -> String; - fn span_parent(span: $S::Span) -> Option<$S::Span>; - fn span_source(span: $S::Span) -> $S::Span; - fn span_byte_range(span: $S::Span) -> Range; - fn span_start(span: $S::Span) -> $S::Span; - fn span_end(span: $S::Span) -> $S::Span; - fn span_line(span: $S::Span) -> usize; - fn span_column(span: $S::Span) -> usize; - fn span_file(span: $S::Span) -> String; - fn span_local_file(span: $S::Span) -> Option; - fn span_join(span: $S::Span, other: $S::Span) -> Option<$S::Span>; - fn span_subspan(span: $S::Span, start: Bound, end: Bound) -> Option<$S::Span>; - fn span_resolved_at(span: $S::Span, at: $S::Span) -> $S::Span; - fn span_source_text(span: $S::Span) -> Option; - fn span_save_span(span: $S::Span) -> usize; - fn span_recover_proc_macro_span(id: usize) -> $S::Span; - - fn symbol_normalize_and_validate_ident(string: &str) -> Result<$S::Symbol, ()>; + stream: $TokenStream + ) -> Vec>; + + fn span_debug(span: $Span) -> String; + fn span_parent(span: $Span) -> Option<$Span>; + fn span_source(span: $Span) -> $Span; + fn span_byte_range(span: $Span) -> Range; + fn span_start(span: $Span) -> $Span; + fn span_end(span: $Span) -> $Span; + fn span_line(span: $Span) -> usize; + fn span_column(span: $Span) -> usize; + fn span_file(span: $Span) -> String; + fn span_local_file(span: $Span) -> Option; + fn span_join(span: $Span, other: $Span) -> Option<$Span>; + fn span_subspan(span: $Span, start: Bound, end: Bound) -> Option<$Span>; + fn span_resolved_at(span: $Span, at: $Span) -> $Span; + fn span_source_text(span: $Span) -> Option; + fn span_save_span(span: $Span) -> usize; + fn span_recover_proc_macro_span(id: usize) -> $Span; + + fn symbol_normalize_and_validate_ident(string: &str) -> Result<$Symbol, ()>; } }; } @@ -126,7 +122,7 @@ pub struct BridgeConfig<'a> { input: Buffer, /// Server-side function that the client uses to make requests. - dispatch: closure::Closure<'a, Buffer, Buffer>, + dispatch: closure::Closure<'a>, /// If 'true', always invoke the default panic hook force_show_panics: bool, @@ -146,7 +142,7 @@ macro_rules! declare_tags { rpc_encode_decode!(enum ApiTags { $($method),* }); } } -with_api!(self, declare_tags); +with_api!(declare_tags, __, __, __); /// Helper to wrap associated types to allow trait impl dispatch. /// That is, normally a pair of impls for `T::Foo` and `T::Bar` @@ -173,7 +169,7 @@ impl Mark for Marked { self.value } } -impl<'a, T, M> Mark for &'a Marked { +impl<'a, T> Mark for &'a Marked { type Unmarked = &'a T; fn mark(_: Self::Unmarked) -> Self { unreachable!() @@ -220,6 +216,8 @@ mark_noop! { Delimiter, LitKind, Level, + Bound, + Range, } rpc_encode_decode!( @@ -318,7 +316,7 @@ macro_rules! compound_traits { }; } -compound_traits!( +rpc_encode_decode!( enum Bound { Included(x), Excluded(x), @@ -390,7 +388,7 @@ pub struct Literal { pub span: Span, } -compound_traits!(struct Literal { kind, symbol, suffix, span }); +compound_traits!(struct Literal { kind, symbol, suffix, span }); #[derive(Clone)] pub enum TokenTree { @@ -434,6 +432,6 @@ compound_traits!( struct ExpnGlobals { def_site, call_site, mixed_site } ); -compound_traits!( +rpc_encode_decode!( struct Range { start, end } ); diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs index 63329c8c02601..7fee8654bc788 100644 --- a/library/proc_macro/src/bridge/rpc.rs +++ b/library/proc_macro/src/bridge/rpc.rs @@ -52,45 +52,37 @@ macro_rules! rpc_encode_decode { } }; (enum $name:ident $(<$($T:ident),+>)? { $($variant:ident $(($field:ident))*),* $(,)? }) => { - impl),+)?> Encode for $name $(<$($T),+>)? { - fn encode(self, w: &mut Buffer, s: &mut S) { - // HACK(eddyb): `Tag` enum duplicated between the - // two impls as there's no other place to stash it. - #[allow(non_camel_case_types)] - #[repr(u8)] - enum Tag { $($variant),* } - - match self { - $($name::$variant $(($field))* => { - (Tag::$variant as u8).encode(w, s); - $($field.encode(w, s);)* - })* + #[allow(non_upper_case_globals, non_camel_case_types)] + const _: () = { + #[repr(u8)] enum Tag { $($variant),* } + + $(const $variant: u8 = Tag::$variant as u8;)* + + impl),+)?> Encode for $name $(<$($T),+>)? { + fn encode(self, w: &mut Buffer, s: &mut S) { + match self { + $($name::$variant $(($field))* => { + $variant.encode(w, s); + $($field.encode(w, s);)* + })* + } } } - } - impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S> - for $name $(<$($T),+>)? - { - fn decode(r: &mut &'a [u8], s: &mut S) -> Self { - // HACK(eddyb): `Tag` enum duplicated between the - // two impls as there's no other place to stash it. - #[allow(non_upper_case_globals, non_camel_case_types)] - mod tag { - #[repr(u8)] enum Tag { $($variant),* } - - $(pub(crate) const $variant: u8 = Tag::$variant as u8;)* - } - - match u8::decode(r, s) { - $(tag::$variant => { - $(let $field = Decode::decode(r, s);)* - $name::$variant $(($field))* - })* - _ => unreachable!(), + impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S> + for $name $(<$($T),+>)? + { + fn decode(r: &mut &'a [u8], s: &mut S) -> Self { + match u8::decode(r, s) { + $($variant => { + $(let $field = Decode::decode(r, s);)* + $name::$variant $(($field))* + })* + _ => unreachable!(), + } } } - } + }; } } diff --git a/library/proc_macro/src/bridge/selfless_reify.rs b/library/proc_macro/src/bridge/selfless_reify.rs index a53550e0b9e0c..1a9951af8c9f1 100644 --- a/library/proc_macro/src/bridge/selfless_reify.rs +++ b/library/proc_macro/src/bridge/selfless_reify.rs @@ -38,47 +38,27 @@ use std::mem; -// FIXME(eddyb) this could be `trait` impls except for the `const fn` requirement. -macro_rules! define_reify_functions { - ($( - fn $name:ident $(<$($param:ident),*>)? - for $(extern $abi:tt)? fn($($arg:ident: $arg_ty:ty),*) -> $ret_ty:ty; - )+) => { - $(pub(super) const fn $name< - $($($param,)*)? - F: Fn($($arg_ty),*) -> $ret_ty + Copy - >(f: F) -> $(extern $abi)? fn($($arg_ty),*) -> $ret_ty { - // FIXME(eddyb) describe the `F` type (e.g. via `type_name::`) once panic - // formatting becomes possible in `const fn`. - const { assert!(size_of::() == 0, "selfless_reify: closure must be zero-sized"); } - - $(extern $abi)? fn wrapper< - $($($param,)*)? - F: Fn($($arg_ty),*) -> $ret_ty + Copy - >($($arg: $arg_ty),*) -> $ret_ty { - let f = unsafe { - // SAFETY: `F` satisfies all criteria for "out of thin air" - // reconstructability (see module-level doc comment). - mem::MaybeUninit::::uninit().assume_init() - }; - f($($arg),*) - } - let _f_proof = f; - wrapper::< - $($($param,)*)? - F - > - })+ +pub(super) const fn reify_to_extern_c_fn_hrt_bridge< + R, + F: Fn(super::BridgeConfig<'_>) -> R + Copy, +>( + f: F, +) -> extern "C" fn(super::BridgeConfig<'_>) -> R { + // FIXME(eddyb) describe the `F` type (e.g. via `type_name::`) once panic + // formatting becomes possible in `const fn`. + const { + assert!(size_of::() == 0, "selfless_reify: closure must be zero-sized"); } -} - -define_reify_functions! { - fn _reify_to_extern_c_fn_unary for extern "C" fn(arg: A) -> R; - - // HACK(eddyb) this abstraction is used with `for<'a> fn(BridgeConfig<'a>) - // -> T` but that doesn't work with just `reify_to_extern_c_fn_unary` - // because of the `fn` pointer type being "higher-ranked" (i.e. the - // `for<'a>` binder). - // FIXME(eddyb) try to remove the lifetime from `BridgeConfig`, that'd help. - fn reify_to_extern_c_fn_hrt_bridge for extern "C" fn(bridge: super::BridgeConfig<'_>) -> R; + extern "C" fn wrapper) -> R + Copy>( + bridge: super::BridgeConfig<'_>, + ) -> R { + let f = unsafe { + // SAFETY: `F` satisfies all criteria for "out of thin air" + // reconstructability (see module-level doc comment). + mem::conjure_zst::() + }; + f(bridge) + } + let _f_proof = f; + wrapper:: } diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index 073ddb554994c..a3c6a232264e0 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -58,12 +58,12 @@ struct Dispatcher { server: S, } -macro_rules! define_server_dispatcher_impl { +macro_rules! define_server { ( $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)* ) => { pub trait Server { - type TokenStream: 'static + Clone; + type TokenStream: 'static + Clone + Default; type Span: 'static + Copy + Eq + Hash; type Symbol: 'static; @@ -77,22 +77,20 @@ macro_rules! define_server_dispatcher_impl { $(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?;)* } + } +} +with_api!(define_server, Self::TokenStream, Self::Span, Self::Symbol); +macro_rules! define_dispatcher { + ( + $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)* + ) => { // FIXME(eddyb) `pub` only for `ExecutionStrategy` below. pub trait DispatcherTrait { - // HACK(eddyb) these are here to allow `Self::$name` to work below. - type TokenStream; - type Span; - type Symbol; - fn dispatch(&mut self, buf: Buffer) -> Buffer; } impl DispatcherTrait for Dispatcher { - type TokenStream = MarkedTokenStream; - type Span = MarkedSpan; - type Symbol = MarkedSymbol; - fn dispatch(&mut self, mut buf: Buffer) -> Buffer { let Dispatcher { handle_store, server } = self; @@ -127,7 +125,7 @@ macro_rules! define_server_dispatcher_impl { } } } -with_api!(Self, define_server_dispatcher_impl); +with_api!(define_dispatcher, MarkedTokenStream, MarkedSpan, MarkedSymbol); pub trait ExecutionStrategy { fn run_bridge_and_client( @@ -312,7 +310,6 @@ impl client::Client { ) -> Result where S: Server, - S::TokenStream: Default, { let client::Client { handle_counters, run, _marker } = *self; run_server( @@ -338,7 +335,6 @@ impl client::Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream ) -> Result where S: Server, - S::TokenStream: Default, { let client::Client { handle_counters, run, _marker } = *self; run_server( diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 49b6f2ae41f89..e2f39c015bdd7 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -27,6 +27,7 @@ #![feature(restricted_std)] #![feature(rustc_attrs)] #![feature(extend_one)] +#![feature(mem_conjure_zst)] #![recursion_limit = "256"] #![allow(internal_features)] #![deny(ffi_unwind_calls)] diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 25bd7005b9942..14b41a427f1e0 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -19,6 +19,20 @@ //! matter the platform or filesystem. An exception to this is made for Windows //! drive letters. //! +//! ## Path normalization +//! +//! Several methods in this module perform basic path normalization by disregarding +//! repeated separators, non-leading `.` components, and trailing separators. These include: +//! - Methods for iteration, such as [`Path::components`] and [`Path::iter`] +//! - Methods for inspection, such as [`Path::has_root`] +//! - Comparisons using [`PartialEq`], [`PartialOrd`], and [`Ord`] +//! +//! [`Path::join`] and [`PathBuf::push`] also disregard trailing slashes. +//! +// FIXME(normalize_lexically): mention normalize_lexically once stable +//! These methods **do not** resolve `..` components or symlinks. For full normalization +//! including `..` resolution, use [`Path::canonicalize`] (which does access the filesystem). +//! //! ## Simple usage //! //! Path manipulation includes both parsing components from slices and building diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index c71a350ffd305..54c0f2ec74309 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -949,7 +949,9 @@ impl TargetCfgs { // actually be changed with `-C` flags. for config in query_rustc_output( config, - &["--print=cfg", "--target", &config.target], + // `-Zunstable-options` is necessary when compiletest is running with custom targets + // (such as synthetic targets used to bless mir-opt tests). + &["-Zunstable-options", "--print=cfg", "--target", &config.target], Default::default(), ) .trim() diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 1804490a5f12c..742790a50fce8 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1670,6 +1670,11 @@ impl<'test> TestCx<'test> { if self.props.force_host { &*self.config.host } else { &*self.config.target }; compiler.arg(&format!("--target={}", target)); + if target.ends_with(".json") { + // `-Zunstable-options` is necessary when compiletest is running with custom targets + // (such as synthetic targets used to bless mir-opt tests). + compiler.arg("-Zunstable-options"); + } } self.set_revision_flags(&mut compiler); diff --git a/tests/crashes/137916.rs b/tests/crashes/137916.rs deleted file mode 100644 index b25e7b200d959..0000000000000 --- a/tests/crashes/137916.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #137916 -//@ edition: 2021 -use std::ptr::null; - -async fn a() -> Box { - Box::new(async { - let non_send = null::<()>(); - &non_send; - async {}.await - }) -} - -fn main() {} diff --git a/tests/crashes/138274.rs b/tests/crashes/138274.rs deleted file mode 100644 index d657b27e46f3e..0000000000000 --- a/tests/crashes/138274.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: #138274 -//@ edition: 2021 -//@ compile-flags: --crate-type=lib -trait Trait {} - -fn foo() -> Box { - todo!() -} - -fn fetch() { - async { - let fut = async { - let _x = foo(); - async {}.await; - }; - let _: Box = Box::new(fut); - }; -} diff --git a/tests/ui/async-await/issue-70818.rs b/tests/ui/async-await/issue-70818.rs index c11332fe7d847..af9f33d9050b0 100644 --- a/tests/ui/async-await/issue-70818.rs +++ b/tests/ui/async-await/issue-70818.rs @@ -2,9 +2,8 @@ use std::future::Future; fn foo(ty: T, ty1: U) -> impl Future + Send { - //~^ ERROR future cannot be sent between threads safely + //~^ ERROR: future cannot be sent between threads safely async { (ty, ty1) } - //~^ ERROR future cannot be sent between threads safely } fn main() {} diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr index 07fd20cdd77ea..8de6a825042bb 100644 --- a/tests/ui/async-await/issue-70818.stderr +++ b/tests/ui/async-await/issue-70818.stderr @@ -1,24 +1,3 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-70818.rs:6:5 - | -LL | async { (ty, ty1) } - | ^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` - | -note: captured value is not `Send` - --> $DIR/issue-70818.rs:6:18 - | -LL | async { (ty, ty1) } - | ^^^ has type `U` which is not `Send` -note: required by a bound in an opaque type - --> $DIR/issue-70818.rs:4:69 - | -LL | fn foo(ty: T, ty1: U) -> impl Future + Send { - | ^^^^ -help: consider restricting type parameter `U` with trait `Send` - | -LL | fn foo(ty: T, ty1: U) -> impl Future + Send { - | +++++++++++++++++++ - error: future cannot be sent between threads safely --> $DIR/issue-70818.rs:4:38 | @@ -35,5 +14,5 @@ help: consider restricting type parameter `U` with trait `Send` LL | fn foo(ty: T, ty1: U) -> impl Future + Send { | +++++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs index 2851637ae78fd..27826f79dcd96 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.rs +++ b/tests/ui/async-await/issue-70935-complex-spans.rs @@ -15,7 +15,6 @@ async fn baz(_c: impl FnMut() -> T) where T: Future { fn foo(x: NotSync) -> impl Future + Send { //~^ ERROR `*mut ()` cannot be shared between threads safely async move { - //~^ ERROR `*mut ()` cannot be shared between threads safely baz(|| async { foo(x.clone()); }).await; diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr index 31d15c4592177..b9180c620b0dc 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.stderr @@ -1,46 +1,3 @@ -error[E0277]: `*mut ()` cannot be shared between threads safely - --> $DIR/issue-70935-complex-spans.rs:17:5 - | -LL | / async move { -LL | | -LL | | baz(|| async { -LL | | foo(x.clone()); -LL | | }).await; -LL | | } - | |_____^ `*mut ()` cannot be shared between threads safely - | - = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()` -note: required because it appears within the type `PhantomData<*mut ()>` - --> $SRC_DIR/core/src/marker.rs:LL:COL -note: required because it appears within the type `NotSync` - --> $DIR/issue-70935-complex-spans.rs:9:8 - | -LL | struct NotSync(PhantomData<*mut ()>); - | ^^^^^^^ - = note: required for `&NotSync` to implement `Send` -note: required because it's used within this closure - --> $DIR/issue-70935-complex-spans.rs:19:13 - | -LL | baz(|| async { - | ^^ -note: required because it's used within this `async` fn body - --> $DIR/issue-70935-complex-spans.rs:12:67 - | -LL | async fn baz(_c: impl FnMut() -> T) where T: Future { - | ___________________________________________________________________^ -LL | | } - | |_^ -note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:17:5 - | -LL | async move { - | ^^^^^^^^^^ -note: required by a bound in an opaque type - --> $DIR/issue-70935-complex-spans.rs:15:37 - | -LL | fn foo(x: NotSync) -> impl Future + Send { - | ^^^^ - error[E0277]: `*mut ()` cannot be shared between threads safely --> $DIR/issue-70935-complex-spans.rs:15:23 | @@ -57,7 +14,7 @@ LL | struct NotSync(PhantomData<*mut ()>); | ^^^^^^^ = note: required for `&NotSync` to implement `Send` note: required because it's used within this closure - --> $DIR/issue-70935-complex-spans.rs:19:13 + --> $DIR/issue-70935-complex-spans.rs:18:13 | LL | baz(|| async { | ^^ @@ -74,6 +31,6 @@ note: required because it's used within this `async` block LL | async move { | ^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/issue-105084.rs b/tests/ui/coroutine/issue-105084.rs index cddee49901757..4e9f6ee3a5958 100644 --- a/tests/ui/coroutine/issue-105084.rs +++ b/tests/ui/coroutine/issue-105084.rs @@ -36,7 +36,6 @@ fn main() { // one inside `g` and one inside `h`. // Proceed and drop `t` in `g`. Pin::new(&mut g).resume(()); - //~^ ERROR borrow of moved value: `g` // Proceed and drop `t` in `h` -> double free! Pin::new(&mut h).resume(()); diff --git a/tests/ui/coroutine/issue-105084.stderr b/tests/ui/coroutine/issue-105084.stderr index 23c1fdc545922..a69d20e607a42 100644 --- a/tests/ui/coroutine/issue-105084.stderr +++ b/tests/ui/coroutine/issue-105084.stderr @@ -1,27 +1,3 @@ -error[E0382]: borrow of moved value: `g` - --> $DIR/issue-105084.rs:38:14 - | -LL | let mut g = #[coroutine] - | ----- move occurs because `g` has type `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`, which does not implement the `Copy` trait -... -LL | let mut h = copy(g); - | - value moved here -... -LL | Pin::new(&mut g).resume(()); - | ^^^^^^ value borrowed here after move - | -note: consider changing this parameter type in function `copy` to borrow instead if owning the value isn't necessary - --> $DIR/issue-105084.rs:10:21 - | -LL | fn copy(x: T) -> T { - | ---- ^ this parameter takes ownership of the value - | | - | in this function -help: consider cloning the value if the performance cost is acceptable - | -LL | let mut h = copy(g.clone()); - | ++++++++ - error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}` --> $DIR/issue-105084.rs:32:17 | @@ -45,7 +21,6 @@ note: required by a bound in `copy` LL | fn copy(x: T) -> T { | ^^^^ required by this bound in `copy` -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0382. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/stalled-coroutine-obligations.rs b/tests/ui/coroutine/stalled-coroutine-obligations.rs new file mode 100644 index 0000000000000..89af3c9a583c2 --- /dev/null +++ b/tests/ui/coroutine/stalled-coroutine-obligations.rs @@ -0,0 +1,32 @@ +//@ edition: 2021 + +// Regression tests for #137916 and #138274 +// We now check stalled coroutine obligations eagerly at the start of `mir_borrowck`. +// So these unsatisfied bounds are caught before causing ICEs. +use std::ptr::null; + +async fn a() -> Box { + Box::new(async { + //~^ ERROR: future cannot be sent between threads safely + let non_send = null::<()>(); + &non_send; + async {}.await + }) +} + + +trait Trait {} +fn foo() -> Box { todo!() } + +fn fetch() { + async { + let fut = async { + let _x = foo(); + async {}.await; + }; + let _: Box = Box::new(fut); + //~^ ERROR: future cannot be sent between threads safely + }; +} + +fn main() {} diff --git a/tests/ui/coroutine/stalled-coroutine-obligations.stderr b/tests/ui/coroutine/stalled-coroutine-obligations.stderr new file mode 100644 index 0000000000000..cbf395dd6cfb3 --- /dev/null +++ b/tests/ui/coroutine/stalled-coroutine-obligations.stderr @@ -0,0 +1,40 @@ +error: future cannot be sent between threads safely + --> $DIR/stalled-coroutine-obligations.rs:9:5 + | +LL | / Box::new(async { +LL | | +LL | | let non_send = null::<()>(); +LL | | &non_send; +LL | | async {}.await +LL | | }) + | |______^ future created by async block is not `Send` + | + = help: within `{async block@$DIR/stalled-coroutine-obligations.rs:9:14: 9:19}`, the trait `Send` is not implemented for `*const ()` +note: future is not `Send` as this value is used across an await + --> $DIR/stalled-coroutine-obligations.rs:13:18 + | +LL | let non_send = null::<()>(); + | -------- has type `*const ()` which is not `Send` +LL | &non_send; +LL | async {}.await + | ^^^^^ await occurs here, with `non_send` maybe used later + = note: required for the cast from `Box<{async block@$DIR/stalled-coroutine-obligations.rs:9:14: 9:19}>` to `Box` + +error: future cannot be sent between threads safely + --> $DIR/stalled-coroutine-obligations.rs:27:32 + | +LL | let _: Box = Box::new(fut); + | ^^^^^^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `Send` is not implemented for `dyn Trait` +note: future is not `Send` as this value is used across an await + --> $DIR/stalled-coroutine-obligations.rs:25:22 + | +LL | let _x = foo(); + | -- has type `Box` which is not `Send` +LL | async {}.await; + | ^^^^^ await occurs here, with `_x` maybe used later + = note: required for the cast from `Box<{async block@$DIR/stalled-coroutine-obligations.rs:23:19: 23:24}>` to `Box` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.stderr b/tests/ui/suggestions/issue-71394-no-from-impl.stderr index 9e068c311ae05..b8a240f7f07c5 100644 --- a/tests/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/tests/ui/suggestions/issue-71394-no-from-impl.stderr @@ -13,7 +13,7 @@ LL | let _: &[i8] = data.into(); `[T; 6]` implements `From<(T, T, T, T, T, T)>` `[T; 7]` implements `From<(T, T, T, T, T, T, T)>` `[T; 8]` implements `From<(T, T, T, T, T, T, T, T)>` - and 6 others + and 7 others = note: required for `&[u8]` to implement `Into<&[i8]>` error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/stalled-coroutine-obligations.rs b/tests/ui/traits/next-solver/stalled-coroutine-obligations.rs new file mode 100644 index 0000000000000..7c789af9e4ccd --- /dev/null +++ b/tests/ui/traits/next-solver/stalled-coroutine-obligations.rs @@ -0,0 +1,50 @@ +//@ edition: 2024 +//@ compile-flags: -Znext-solver --diagnostic-width=300 + +// Previously we check stalled coroutine obligations after borrowck pass. +// And we wrongly assume that these obligations hold in borrowck which leads to +// silent normalization failures. +// In the next solver, we register opaques types via `NormalizesTo` goals. +// So these failures also cause those opaques types not registered in storage. +// +// Regression test for #151322 and #151323. + +#![feature(type_alias_impl_trait)] +#![feature(negative_impls)] +#![feature(auto_traits)] + +fn stalled_copy_clone() { + type T = impl Copy; + let foo: T = async {}; + //~^ ERROR: the trait bound + + type U = impl Clone; + let bar: U = async {}; + //~^ ERROR: the trait bound +} + +auto trait Valid {} +struct False; +impl !Valid for False {} + +fn stalled_auto_traits() { + type T = impl Valid; + let a = False; + let foo: T = async { a }; + //~^ ERROR: the trait bound `False: Valid` is not satisfied +} + + +trait Trait { + fn stalled_send(&self, b: *mut ()) -> impl Future + Send { + //~^ ERROR: type mismatch resolving + //~| ERROR: type mismatch resolving + async move { + //~^ ERROR: type mismatch resolving + b + } + } +} + + +fn main() {} diff --git a/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr b/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr new file mode 100644 index 0000000000000..6afa406bf367e --- /dev/null +++ b/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr @@ -0,0 +1,62 @@ +error[E0277]: the trait bound `{async block@$DIR/stalled-coroutine-obligations.rs:18:18: 18:23}: Copy` is not satisfied + --> $DIR/stalled-coroutine-obligations.rs:18:14 + | +LL | let foo: T = async {}; + | ^ the trait `Copy` is not implemented for `{async block@$DIR/stalled-coroutine-obligations.rs:18:18: 18:23}` + +error[E0277]: the trait bound `{async block@$DIR/stalled-coroutine-obligations.rs:22:18: 22:23}: Clone` is not satisfied + --> $DIR/stalled-coroutine-obligations.rs:22:14 + | +LL | let bar: U = async {}; + | ^ the trait `Clone` is not implemented for `{async block@$DIR/stalled-coroutine-obligations.rs:22:18: 22:23}` + +error[E0277]: the trait bound `False: Valid` is not satisfied in `{async block@$DIR/stalled-coroutine-obligations.rs:33:18: 33:23}` + --> $DIR/stalled-coroutine-obligations.rs:33:14 + | +LL | let foo: T = async { a }; + | ^ ----- within this `{async block@$DIR/stalled-coroutine-obligations.rs:33:18: 33:23}` + | | + | unsatisfied trait bound + | +help: within `{async block@$DIR/stalled-coroutine-obligations.rs:33:18: 33:23}`, the trait `Valid` is not implemented for `False` + --> $DIR/stalled-coroutine-obligations.rs:27:1 + | +LL | struct False; + | ^^^^^^^^^^^^ +note: captured value does not implement `Valid` + --> $DIR/stalled-coroutine-obligations.rs:33:26 + | +LL | let foo: T = async { a }; + | ^ has type `False` which does not implement `Valid` + +error[E0271]: type mismatch resolving `impl Future + Send == {async block@$DIR/stalled-coroutine-obligations.rs:42:9: 42:19}` + --> $DIR/stalled-coroutine-obligations.rs:39:5 + | +LL | fn stalled_send(&self, b: *mut ()) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `impl Future + Send == {async block@$DIR/stalled-coroutine-obligations.rs:42:9: 42:19}` + --> $DIR/stalled-coroutine-obligations.rs:42:9 + | +LL | / async move { +LL | | +LL | | b +LL | | } + | |_________^ types differ + +error[E0271]: type mismatch resolving `{async block@$DIR/stalled-coroutine-obligations.rs:42:9: 42:19} <: impl Future + Send` + --> $DIR/stalled-coroutine-obligations.rs:39:62 + | +LL | fn stalled_send(&self, b: *mut ()) -> impl Future + Send { + | ______________________________________________________________^ +LL | | +LL | | +LL | | async move { +... | +LL | | } + | |_____^ types differ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`.