diff --git a/Cargo.lock b/Cargo.lock index 1948e6c2e5ef6..25ebd213e5273 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2465,6 +2465,7 @@ dependencies = [ "ctrlc", "env_logger", "getrandom", + "jemalloc-sys", "lazy_static", "libc", "libffi", @@ -2474,7 +2475,6 @@ dependencies = [ "rand", "regex", "rustc_version", - "serde", "smallvec", "ui_test", ] diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index fd94e7e9341d4..f4e3086f2b589 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -106,7 +106,8 @@ ast_lowering_misplaced_double_dot = .note = only allowed in tuple, tuple struct, and slice patterns ast_lowering_misplaced_impl_trait = - `impl Trait` only allowed in function and inherent method argument and return types, not in {$position} + `impl Trait` is not allowed in {$position} + .note = `impl Trait` is only allowed in arguments and return types of functions and methods ast_lowering_misplaced_relax_trait_bound = `?Trait` bounds are only permitted at the point where a type parameter is declared diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 710690d0d86a4..faa22eece380b 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -90,6 +90,7 @@ pub enum AssocTyParenthesesSub { #[derive(Diagnostic)] #[diag(ast_lowering_misplaced_impl_trait, code = "E0562")] +#[note] pub struct MisplacedImplTrait<'a> { #[primary_span] pub span: Span, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c618953461cf6..d8de447e5b4cd 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -12,6 +12,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::PredicateOrigin; use rustc_index::{Idx, IndexSlice, IndexVec}; +use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{kw, sym, Ident}; @@ -182,7 +183,8 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs) } ItemKind::Static(box ast::StaticItem { ty: t, mutability: m, expr: e }) => { - let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); + let (ty, body_id) = + self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy); hir::ItemKind::Static(ty, *m, body_id) } ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => { @@ -191,7 +193,9 @@ impl<'hir> LoweringContext<'_, 'hir> { Const::No, id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - |this| this.lower_const_item(ty, span, expr.as_deref()), + |this| { + this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy) + }, ); hir::ItemKind::Const(ty, generics, body_id) } @@ -448,8 +452,9 @@ impl<'hir> LoweringContext<'_, 'hir> { ty: &Ty, span: Span, body: Option<&Expr>, + impl_trait_position: ImplTraitPosition, ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { - let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); + let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(impl_trait_position)); (ty, self.lower_const_body(span, body)) } @@ -572,23 +577,25 @@ impl<'hir> LoweringContext<'_, 'hir> { // This is used to track which lifetimes have already been defined, // and which need to be replicated when lowering an async fn. - match parent_hir.node().expect_item().kind { + let generics = match parent_hir.node().expect_item().kind { hir::ItemKind::Impl(impl_) => { self.is_in_trait_impl = impl_.of_trait.is_some(); + &impl_.generics } - hir::ItemKind::Trait(_, _, generics, _, _) if self.tcx.features().effects => { - self.host_param_id = generics - .params - .iter() - .find(|param| { - matches!( - param.kind, - hir::GenericParamKind::Const { is_host_effect: true, .. } - ) - }) - .map(|param| param.def_id); + hir::ItemKind::Trait(_, _, generics, _, _) => generics, + kind => { + span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr()) } - _ => {} + }; + + if self.tcx.features().effects { + self.host_param_id = generics + .params + .iter() + .find(|param| { + matches!(param.kind, hir::GenericParamKind::Const { is_host_effect: true, .. }) + }) + .map(|param| param.def_id); } match ctxt { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index fb59770d48a2b..dc23b1dce7bf5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -304,8 +304,6 @@ enum ImplTraitPosition { ClosureParam, PointerParam, FnTraitParam, - TraitParam, - ImplParam, ExternFnReturn, ClosureReturn, PointerReturn, @@ -324,29 +322,27 @@ impl std::fmt::Display for ImplTraitPosition { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let name = match self { ImplTraitPosition::Path => "paths", - ImplTraitPosition::Variable => "variable bindings", + ImplTraitPosition::Variable => "the type of variable bindings", ImplTraitPosition::Trait => "traits", ImplTraitPosition::AsyncBlock => "async blocks", ImplTraitPosition::Bound => "bounds", ImplTraitPosition::Generic => "generics", - ImplTraitPosition::ExternFnParam => "`extern fn` params", - ImplTraitPosition::ClosureParam => "closure params", - ImplTraitPosition::PointerParam => "`fn` pointer params", - ImplTraitPosition::FnTraitParam => "`Fn` trait params", - ImplTraitPosition::TraitParam => "trait method params", - ImplTraitPosition::ImplParam => "`impl` method params", + ImplTraitPosition::ExternFnParam => "`extern fn` parameters", + ImplTraitPosition::ClosureParam => "closure parameters", + ImplTraitPosition::PointerParam => "`fn` pointer parameters", + ImplTraitPosition::FnTraitParam => "the parameters of `Fn` trait bounds", ImplTraitPosition::ExternFnReturn => "`extern fn` return types", ImplTraitPosition::ClosureReturn => "closure return types", ImplTraitPosition::PointerReturn => "`fn` pointer return types", - ImplTraitPosition::FnTraitReturn => "`Fn` trait return types", + ImplTraitPosition::FnTraitReturn => "the return type of `Fn` trait bounds", ImplTraitPosition::GenericDefault => "generic parameter defaults", ImplTraitPosition::ConstTy => "const types", ImplTraitPosition::StaticTy => "static types", ImplTraitPosition::AssocTy => "associated types", ImplTraitPosition::FieldTy => "field types", - ImplTraitPosition::Cast => "cast types", + ImplTraitPosition::Cast => "cast expression types", ImplTraitPosition::ImplSelf => "impl headers", - ImplTraitPosition::OffsetOf => "`offset_of!` params", + ImplTraitPosition::OffsetOf => "`offset_of!` parameters", }; write!(f, "{name}") @@ -364,19 +360,6 @@ enum FnDeclKind { Impl, } -impl FnDeclKind { - fn param_impl_trait_allowed(&self) -> bool { - matches!(self, FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait) - } - - fn return_impl_trait_allowed(&self) -> bool { - match self { - FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => true, - _ => false, - } - } -} - #[derive(Copy, Clone)] enum AstOwner<'a> { NonOwner, @@ -1842,19 +1825,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { inputs = &inputs[..inputs.len() - 1]; } let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { - let itctx = if kind.param_impl_trait_allowed() { - ImplTraitContext::Universal - } else { - ImplTraitContext::Disallowed(match kind { - FnDeclKind::Fn | FnDeclKind::Inherent => { - unreachable!("fn should allow APIT") - } - FnDeclKind::ExternFn => ImplTraitPosition::ExternFnParam, - FnDeclKind::Closure => ImplTraitPosition::ClosureParam, - FnDeclKind::Pointer => ImplTraitPosition::PointerParam, - FnDeclKind::Trait => ImplTraitPosition::TraitParam, - FnDeclKind::Impl => ImplTraitPosition::ImplParam, - }) + let itctx = match kind { + FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => { + ImplTraitContext::Universal + } + FnDeclKind::ExternFn => { + ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnParam) + } + FnDeclKind::Closure => { + ImplTraitContext::Disallowed(ImplTraitPosition::ClosureParam) + } + FnDeclKind::Pointer => { + ImplTraitContext::Disallowed(ImplTraitPosition::PointerParam) + } }; self.lower_ty_direct(¶m.ty, &itctx) })); @@ -1866,26 +1849,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } None => match &decl.output { FnRetTy::Ty(ty) => { - let context = if kind.return_impl_trait_allowed() { - let fn_def_id = self.local_def_id(fn_node_id); - ImplTraitContext::ReturnPositionOpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + let itctx = match kind { + FnDeclKind::Fn + | FnDeclKind::Inherent + | FnDeclKind::Trait + | FnDeclKind::Impl => ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(self.local_def_id(fn_node_id)), fn_kind: kind, + }, + FnDeclKind::ExternFn => { + ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnReturn) + } + FnDeclKind::Closure => { + ImplTraitContext::Disallowed(ImplTraitPosition::ClosureReturn) + } + FnDeclKind::Pointer => { + ImplTraitContext::Disallowed(ImplTraitPosition::PointerReturn) } - } else { - ImplTraitContext::Disallowed(match kind { - FnDeclKind::Fn - | FnDeclKind::Inherent - | FnDeclKind::Trait - | FnDeclKind::Impl => { - unreachable!("fn should allow return-position impl trait in traits") - } - FnDeclKind::ExternFn => ImplTraitPosition::ExternFnReturn, - FnDeclKind::Closure => ImplTraitPosition::ClosureReturn, - FnDeclKind::Pointer => ImplTraitPosition::PointerReturn, - }) }; - hir::FnRetTy::Return(self.lower_ty(ty, &context)) + hir::FnRetTy::Return(self.lower_ty(ty, &itctx)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)), }, diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 69d54f0640780..561f8ef36ffde 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -899,25 +899,37 @@ marker_impls! { {T: ?Sized} &mut T, } -/// Types that can be safely moved after being pinned. -/// -/// Rust itself has no notion of immovable types, and considers moves (e.g., -/// through assignment or [`mem::replace`]) to always be safe. -/// -/// The [`Pin`][Pin] type is used instead to prevent moves through the type -/// system. Pointers `P` wrapped in the [`Pin>`][Pin] wrapper can't be -/// moved out of. See the [`pin` module] documentation for more information on -/// pinning. -/// -/// Implementing the `Unpin` trait for `T` lifts the restrictions of pinning off -/// the type, which then allows moving `T` out of [`Pin>`][Pin] with -/// functions such as [`mem::replace`]. -/// -/// `Unpin` has no consequence at all for non-pinned data. In particular, -/// [`mem::replace`] happily moves `!Unpin` data (it works for any `&mut T`, not -/// just when `T: Unpin`). However, you cannot use [`mem::replace`] on data -/// wrapped inside a [`Pin>`][Pin] because you cannot get the `&mut T` you -/// need for that, and *that* is what makes this system work. +/// Types that do not require any pinning guarantees. +/// +/// For information on what "pinning" is, see the [`pin` module] documentation. +/// +/// Implementing the `Unpin` trait for `T` expresses the fact that `T` is pinning-agnostic: +/// it shall not expose nor rely on any pinning guarantees. This, in turn, means that a +/// `Pin`-wrapped pointer to such a type can feature a *fully unrestricted* API. +/// In other words, if `T: Unpin`, a value of type `T` will *not* be bound by the invariants +/// which pinning otherwise offers, even when "pinned" by a [`Pin`] pointing at it. +/// When a value of type `T` is pointed at by a [`Pin`], [`Pin`] will not restrict access +/// to the pointee value like it normally would, thus allowing the user to do anything that they +/// normally could with a non-[`Pin`]-wrapped `Ptr` to that value. +/// +/// The idea of this trait is to alleviate the reduced ergonomics of APIs that require the use +/// of [`Pin`] for soundness for some types, but which also want to be used by other types that +/// don't care about pinning. The prime example of such an API is [`Future::poll`]. There are many +/// [`Future`] types that don't care about pinning. These futures can implement `Unpin` and +/// therefore get around the pinning related restrictions in the API, while still allowing the +/// subset of [`Future`]s which *do* require pinning to be implemented soundly. +/// +/// For more discussion on the consequences of [`Unpin`] within the wider scope of the pinning +/// system, see the [section about `Unpin`] in the [`pin` module]. +/// +/// `Unpin` has no consequence at all for non-pinned data. In particular, [`mem::replace`] happily +/// moves `!Unpin` data, which would be immovable when pinned ([`mem::replace`] works for any +/// `&mut T`, not just when `T: Unpin`). +/// +/// *However*, you cannot use [`mem::replace`] on `!Unpin` data which is *pinned* by being wrapped +/// inside a [`Pin`] pointing at it. This is because you cannot (safely) use a +/// [`Pin`] to get an `&mut T` to its pointee value, which you would need to call +/// [`mem::replace`], and *that* is what makes this system work. /// /// So this, for example, can only be done on types implementing `Unpin`: /// @@ -935,11 +947,22 @@ marker_impls! { /// mem::replace(&mut *pinned_string, "other".to_string()); /// ``` /// -/// This trait is automatically implemented for almost every type. -/// -/// [`mem::replace`]: crate::mem::replace -/// [Pin]: crate::pin::Pin -/// [`pin` module]: crate::pin +/// This trait is automatically implemented for almost every type. The compiler is free +/// to take the conservative stance of marking types as [`Unpin`] so long as all of the types that +/// compose its fields are also [`Unpin`]. This is because if a type implements [`Unpin`], then it +/// is unsound for that type's implementation to rely on pinning-related guarantees for soundness, +/// *even* when viewed through a "pinning" pointer! It is the responsibility of the implementor of +/// a type that relies upon pinning for soundness to ensure that type is *not* marked as [`Unpin`] +/// by adding [`PhantomPinned`] field. For more details, see the [`pin` module] docs. +/// +/// [`mem::replace`]: crate::mem::replace "mem replace" +/// [`Future`]: crate::future::Future "Future" +/// [`Future::poll`]: crate::future::Future::poll "Future poll" +/// [`Pin`]: crate::pin::Pin "Pin" +/// [`Pin`]: crate::pin::Pin "Pin" +/// [`pin` module]: crate::pin "pin module" +/// [section about `Unpin`]: crate::pin#unpin "pin module docs about unpin" +/// [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe" #[stable(feature = "pin", since = "1.33.0")] #[diagnostic::on_unimplemented( note = "consider using the `pin!` macro\nconsider using `Box::pin` if you need to access the pinned value outside of the current scope", diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 7d8c881eab809..bb6c81a486a59 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1,188 +1,616 @@ -//! Types that pin data to its location in memory. -//! -//! It is sometimes useful to have objects that are guaranteed not to move, -//! in the sense that their placement in memory does not change, and can thus be relied upon. -//! A prime example of such a scenario would be building self-referential structs, -//! as moving an object with pointers to itself will invalidate them, which could cause undefined -//! behavior. -//! -//! At a high level, a [Pin]\

ensures that the pointee of any pointer type -//! `P` has a stable location in memory, meaning it cannot be moved elsewhere -//! and its memory cannot be deallocated until it gets dropped. We say that the -//! pointee is "pinned". Things get more subtle when discussing types that -//! combine pinned with non-pinned data; [see below](#projections-and-structural-pinning) -//! for more details. -//! -//! By default, all types in Rust are movable. Rust allows passing all types by-value, -//! and common smart-pointer types such as [Box]\ and [&mut] T allow -//! replacing and moving the values they contain: you can move out of a [Box]\, -//! or you can use [`mem::swap`]. [Pin]\

wraps a pointer type `P`, so -//! [Pin]<[Box]\> functions much like a regular [Box]\: -//! when a [Pin]<[Box]\> gets dropped, so do its contents, and the memory gets -//! deallocated. Similarly, [Pin]<[&mut] T> is a lot like [&mut] T. -//! However, [Pin]\

does not let clients actually obtain a [Box]\ -//! or [&mut] T to pinned data, which implies that you cannot use operations such -//! as [`mem::swap`]: +//! Types that pin data to a location in memory. +//! +//! It is sometimes useful to be able to rely upon a certain value not being able to *move*, +//! in the sense that its address in memory cannot change. This is useful especially when there +//! are one or more [*pointers*][pointer] pointing at that value. The ability to rely on this +//! guarantee that the value a [pointer] is pointing at (its **pointee**) will +//! +//! 1. Not be *moved* out of its memory location +//! 2. More generally, remain *valid* at that same memory location +//! +//! is called "pinning." We would say that a value which satisfies these guarantees has been +//! "pinned," in that it has been permanently (until the end of its lifespan) attached to its +//! location in memory, as though pinned to a pinboard. Pinning a value is an incredibly useful +//! building block for [`unsafe`] code to be able to reason about whether a raw pointer to the +//! pinned value is still valid. [As we'll see later][drop-guarantee], this is necessarily from the +//! time the value is first pinned until the end of its lifespan. This concept of "pinning" is +//! necessary to implement safe interfaces on top of things like self-referential types and +//! intrusive data structures which cannot currently be modeled in fully safe Rust using only +//! borrow-checked [references][reference]. +//! +//! "Pinning" allows us to put a *value* which exists at some location in memory into a state where +//! safe code cannot *move* that value to a different location in memory or otherwise invalidate it +//! at its current location (unless it implements [`Unpin`], which we will +//! [talk about below][self#unpin]). Anything that wants to interact with the pinned value in a way +//! that has the potential to violate these guarantees must promise that it will not actually +//! violate them, using the [`unsafe`] keyword to mark that such a promise is upheld by the user +//! and not the compiler. In this way, we can allow other [`unsafe`] code to rely on any pointers +//! that point to the pinned value to be valid to dereference while it is pinned. +//! +//! Note that as long as you don't use [`unsafe`], it's impossible to create or misuse a pinned +//! value in a way that is unsound. See the documentation of [`Pin`] for more +//! information on the practicalities of how to pin a value and how to use that pinned value from a +//! user's perspective without using [`unsafe`]. +//! +//! The rest of this documentation is intended to be the source of truth for users of [`Pin`] +//! that are implementing the [`unsafe`] pieces of an interface that relies on pinning for validity; +//! users of [`Pin`] in safe code do not need to read it in detail. +//! +//! There are several sections to this documentation: +//! +//! * [What is "*moving*"?][what-is-moving] +//! * [What is "pinning"?][what-is-pinning] +//! * [Address sensitivity, AKA "when do we need pinning?"][address-sensitive-values] +//! * [Examples of types with address-sensitive states][address-sensitive-examples] +//! * [Self-referential struct][self-ref] +//! * [Intrusive, doubly-linked list][linked-list] +//! * [Subtle details and the `Drop` guarantee][subtle-details] +//! +//! # What is "*moving*"? +//! [what-is-moving]: self#what-is-moving +//! +//! When we say a value is *moved*, we mean that the compiler copies, byte-for-byte, the +//! value from one location to another. In a purely mechanical sense, this is identical to +//! [`Copy`]ing a value from one place in memory to another. In Rust, "move" carries with it the +//! semantics of ownership transfer from one variable to another, which is the key difference +//! between a [`Copy`] and a move. For the purposes of this module's documentation, however, when +//! we write *move* in italics, we mean *specifically* that the value has *moved* in the mechanical +//! sense of being located at a new place in memory. +//! +//! All values in Rust are trivially *moveable*. This means that the address at which a value is +//! located is not necessarily stable in between borrows. The compiler is allowed to *move* a value +//! to a new address without running any code to notify that value that its address +//! has changed. Although the compiler will not insert memory *moves* where no semantic move has +//! occurred, there are many places where a value *may* be moved. For example, when doing +//! assignment or passing a value into a function. +//! +//! ``` +//! #[derive(Default)] +//! struct AddrTracker(Option); +//! +//! impl AddrTracker { +//! // If we haven't checked the addr of self yet, store the current +//! // address. If we have, confirm that the current address is the same +//! // as it was last time, or else panic. +//! fn check_for_move(&mut self) { +//! let current_addr = self as *mut Self as usize; +//! match self.0 { +//! None => self.0 = Some(current_addr), +//! Some(prev_addr) => assert_eq!(prev_addr, current_addr), +//! } +//! } +//! } +//! +//! // Create a tracker and store the initial address +//! let mut tracker = AddrTracker::default(); +//! tracker.check_for_move(); +//! +//! // Here we shadow the variable. This carries a semantic move, and may therefore also +//! // come with a mechanical memory *move* +//! let mut tracker = tracker; +//! +//! // May panic! +//! // tracker.check_for_move(); +//! ``` +//! +//! In this sense, Rust does not guarantee that `check_for_move()` will never panic, because the +//! compiler is permitted to *move* `tracker` in many situations. +//! +//! Common smart-pointer types such as [`Box`] and [`&mut T`] also allow *moving* the underlying +//! *value* they point at: you can move out of a [`Box`], or you can use [`mem::replace`] to +//! move a `T` out of a [`&mut T`]. Therefore, putting a value (such as `tracker` above) behind a +//! pointer isn't enough on its own to ensure that its address does not change. +//! +//! # What is "pinning"? +//! [what-is-pinning]: self#what-is-pinning +//! +//! We say that a value has been *pinned* when it has been put into a state where it is guaranteed +//! to remain *located at the same place in memory* from the time it is pinned until its +//! [`drop`] is called. +//! +//! ## Address-sensitive values, AKA "when we need pinning" +//! [address-sensitive-values]: self#address-sensitive-values-aka-when-we-need-pinning +//! +//! Most values in Rust are entirely okay with being *moved* around at-will. +//! Types for which it is *always* the case that *any* value of that type can be +//! *moved* at-will should implement [`Unpin`], which we will discuss more [below][self#unpin]. +//! +//! [`Pin`] is specifically targeted at allowing the implementation of *safe interfaces* around +//! types which have some state during which they become "address-sensitive." A value in such an +//! "address-sensitive" state is *not* okay with being *moved* around at-will. Such a value must +//! stay *un-moved* and valid during the address-sensitive portion of its lifespan because some +//! interface is relying on those invariants to be true in order for its implementation to be sound. +//! +//! As a motivating example of a type which may become address-sensitive, consider a type which +//! contains a pointer to another piece of its own data, *i.e.* a "self-referential" type. In order +//! for such a type to be implemented soundly, the pointer which points into `self`'s data must be +//! proven valid whenever it is accessed. But if that value is *moved*, the pointer will still +//! point to the old address where the value was located and not into the new location of `self`, +//! thus becoming invalid. A key example of such self-referential types are the state machines +//! generated by the compiler to implement [`Future`] for `async fn`s. +//! +//! Such types that have an *address-sensitive* state usually follow a lifecycle +//! that looks something like so: +//! +//! 1. A value is created which can be freely moved around. +//! * e.g. calling an async function which returns a state machine implementing [`Future`] +//! 2. An operation causes the value to depend on its own address not changing +//! * e.g. calling [`poll`] for the first time on the produced [`Future`] +//! 3. Further pieces of the safe interface of the type use internal [`unsafe`] operations which +//! assume that the address of the value is stable +//! * e.g. subsequent calls to [`poll`] +//! 4. Before the value is invalidated (e.g. deallocated), it is *dropped*, giving it a chance to +//! notify anything with pointers to itself that those pointers will be invalidated +//! * e.g. [`drop`]ping the [`Future`] [^pin-drop-future] +//! +//! There are two possible ways to ensure the invariants required for 2. and 3. above (which +//! apply to any address-sensitive type, not just self-referrential types) do not get broken. +//! +//! 1. Have the value detect when it is moved and update all the pointers that point to itself. +//! 2. Guarantee that the address of the value does not change (and that memory is not re-used +//! for anything else) during the time that the pointers to it are expected to be valid to +//! dereference. +//! +//! Since, as we discussed, Rust can move values without notifying them that they have moved, the +//! first option is ruled out. +//! +//! In order to implement the second option, we must in some way enforce its key invariant, +//! *i.e.* prevent the value from being *moved* or otherwise invalidated (you may notice this +//! sounds an awful lot like the definition of *pinning* a value). There a few ways one might be +//! able to enforce this invariant in Rust: +//! +//! 1. Offer a wholly `unsafe` API to interact with the object, thus requiring every caller to +//! uphold the invariant themselves +//! 2. Store the value that must not be moved behind a carefully managed pointer internal to +//! the object +//! 3. Leverage the type system to encode and enforce this invariant by presenting a restricted +//! API surface to interact with *any* object that requires these invariants +//! +//! The first option is quite obviously undesirable, as the [`unsafe`]ty of the interface will +//! become viral throughout all code that interacts with the object. +//! +//! The second option is a viable solution to the problem for some use cases, in particular +//! for self-referrential types. Under this model, any type that has an address sensitive state +//! would ultimately store its data in something like a [`Box`], carefully manage internal +//! access to that data to ensure no *moves* or other invalidation occurs, and finally +//! provide a safe interface on top. +//! +//! There are a couple of linked disadvantages to using this model. The most significant is that +//! each individual object must assume it is *on its own* to ensure +//! that its data does not become *moved* or otherwise invalidated. Since there is no shared +//! contract between values of different types, an object cannot assume that others interacting +//! with it will properly respect the invariants around interacting with its data and must +//! therefore protect it from everyone. Because of this, *composition* of address-sensitive types +//! requires at least a level of pointer indirection each time a new object is added to the mix +//! (and, practically, a heap allocation). +//! +//! Although there were other reason as well, this issue of expensive composition is the key thing +//! that drove Rust towards adopting a different model. It is particularly a problem +//! when one considers, for exapmle, the implications of composing together the [`Future`]s which +//! will eventaully make up an asynchronous task (including address-sensitive `async fn` state +//! machines). It is plausible that there could be many layers of [`Future`]s composed together, +//! including multiple layers of `async fn`s handling different parts of a task. It was deemed +//! unacceptable to force indirection and allocation for each layer of composition in this case. +//! +//! [`Pin`] is an implementation of the third option. It allows us to solve the issues +//! discussed with the second option by building a *shared contractual language* around the +//! guarantees of "pinning" data. +//! +//! [^pin-drop-future]: Futures themselves do not ever need to notify other bits of code that +//! they are being dropped, however data structures like stack-based intrusive linked lists do. +//! +//! ## Using [`Pin`] to pin values +//! +//! In order to pin a value, we wrap a *pointer to that value* (of some type `Ptr`) in a +//! [`Pin`]. [`Pin`] can wrap any pointer type, forming a promise that the **pointee** +//! will not be *moved* or [otherwise invalidated][subtle-details]. +//! +//! We call such a [`Pin`]-wrapped pointer a **pinning pointer,** (or pinning reference, or pinning +//! `Box`, etc.) because its existence is the thing that is conceptually pinning the underlying +//! pointee in place: it is the metaphorical "pin" securing the data in place on the pinboard +//! (in memory). +//! +//! Notice that the thing wrapped by [`Pin`] is not the value which we want to pin itself, but +//! rather a pointer to that value! A [`Pin`] does not pin the `Ptr`; instead, it pins the +//! pointer's ***pointee** value*. +//! +//! ### Pinning as a library contract +//! +//! Pinning does not require nor make use of any compiler "magic"[^noalias], only a specific +//! contract between the [`unsafe`] parts of a library API and its users. +//! +//! It is important to stress this point as a user of the [`unsafe`] parts of the [`Pin`] API. +//! Practically, this means that performing the mechanics of "pinning" a value by creating a +//! [`Pin`] to it *does not* actually change the way the compiler behaves towards the +//! inner value! It is possible to use incorrect [`unsafe`] code to create a [`Pin`] to a +//! value which does not actually satisfy the invariants that a pinned value must satisfy, and in +//! this way lead to undefined behavior even in (from that point) fully safe code. Similarly, using +//! [`unsafe`], one may get access to a bare [`&mut T`] from a [`Pin`] and +//! use that to invalidly *move* the pinned value out. It is the job of the user of the +//! [`unsafe`] parts of the [`Pin`] API to ensure these invariants are not violated. +//! +//! This differs from e.g. [`UnsafeCell`] which changes the semantics of a program's compiled +//! output. A [`Pin`] is a handle to a value which we have promised we will not move out of, +//! but Rust still considers all values themselves to be fundamentally moveable through, *e.g.* +//! assignment or [`mem::replace`]. +//! +//! [^noalias]: There is a bit of nuance here that is still being decided about what the aliasing +//! semantics of `Pin<&mut T>` should be, but this is true as of today. +//! +//! ### How [`Pin`] prevents misuse in safe code +//! +//! In order to accomplish the goal of pinning the pointee value, [`Pin`] restricts access to +//! the wrapped `Ptr` type in safe code. Specifically, [`Pin`] disallows the ability to access +//! the wrapped pointer in ways that would allow the user to *move* the underlying pointee value or +//! otherwise re-use that memory for something else without using [`unsafe`]. For example, a +//! [`Pin<&mut T>`] makes it impossible to obtain the wrapped [&mut] T safely because +//! through that [&mut] T it would be possible to *move* the underlying value out of +//! the pointer with [`mem::replace`], etc. +//! +//! As discussed above, this promise must be upheld manually by [`unsafe`] code which interacts +//! with the [`Pin`] so that other [`unsafe`] code can rely on the pointee value being +//! *un-moved* and valid. Interfaces that operate on values which are in an address-sensitive state +//! accept an argument like [Pin]<[&mut] T> or [Pin]<[Box]\> to +//! indicate this contract to the caller. +//! +//! [As discussed below][drop-guarantee], opting in to using pinning guarantees in the interface +//! of an address-sensitive type has consequences for the implementation of some safe traits on +//! that type as well. +//! +//! ## Interaction between [`Deref`] and [`Pin`] +//! +//! Since [`Pin`] can wrap any pointer type, it uses [`Deref`] and [`DerefMut`] in +//! order to identify the type of the pinned pointee data and provide (restricted) access to it. +//! +//! A [`Pin`] where [`Ptr: Deref`][Deref] is a "`Ptr`-style pinning pointer" to a pinned +//! [`Ptr::Target`][Target] – so, a [Pin]<[Box]\> is an owned, pinning pointer to a +//! pinned `T`, and a [Pin]<[Rc]\> is a reference-counted, pinning pointer to a +//! pinned `T`. +//! +//! [`Pin`] also uses the [`::Target`][Target] type information to modify the +//! interface it is allowed to provide for interacting with that data (for example, when a +//! pinning pointer points at pinned data which implements [`Unpin`], as +//! [discussed below][self#unpin]). +//! +//! [`Pin`] requires that implementations of [`Deref`] and [`DerefMut`] on `Ptr` return a +//! pointer to the pinned data directly and do not *move* out of the `self` parameter during their +//! implementation of [`DerefMut::deref_mut`]. It is unsound for [`unsafe`] code to wrap pointer +//! types with such "malicious" implementations of [`Deref`]; see [`Pin::new_unchecked`] for +//! details. +//! +//! ## Fixing `AddrTracker` +//! +//! The guarantee of a stable address is necessary to make our `AddrTracker` example work. When +//! `check_for_move` sees a [Pin]<&mut AddrTracker>, it can safely assume that value +//! will exist at that same address until said value goes out of scope, and thus multiple calls +//! to it *cannot* panic. //! //! ``` +//! use std::marker::PhantomPinned; //! use std::pin::Pin; -//! fn swap_pins(x: Pin<&mut T>, y: Pin<&mut T>) { -//! // `mem::swap` needs `&mut T`, but we cannot get it. -//! // We are stuck, we cannot swap the contents of these references. -//! // We could use `Pin::get_unchecked_mut`, but that is unsafe for a reason: -//! // we are not allowed to use it for moving things out of the `Pin`. +//! use std::pin::pin; +//! +//! #[derive(Default)] +//! struct AddrTracker { +//! prev_addr: Option, +//! // remove auto-implemented `Unpin` bound to mark this type as having some +//! // address-sensitive state. This is essential for our expected pinning +//! // guarantees to work, and is discussed more below. +//! _pin: PhantomPinned, +//! } +//! +//! impl AddrTracker { +//! fn check_for_move(self: Pin<&mut Self>) { +//! let current_addr = &*self as *const Self as usize; +//! match self.prev_addr { +//! None => { +//! // SAFETY: we do not move out of self +//! let self_data_mut = unsafe { self.get_unchecked_mut() }; +//! self_data_mut.prev_addr = Some(current_addr); +//! }, +//! Some(prev_addr) => assert_eq!(prev_addr, current_addr), +//! } +//! } //! } +//! +//! // 1. Create the value, not yet in an address-sensitive state +//! let tracker = AddrTracker::default(); +//! +//! // 2. Pin the value by putting it behind a pinning pointer, thus putting +//! // it into an address-sensitive state +//! let mut ptr_to_pinned_tracker: Pin<&mut AddrTracker> = pin!(tracker); +//! ptr_to_pinned_tracker.as_mut().check_for_move(); +//! +//! // Trying to access `tracker` or pass `ptr_to_pinned_tracker` to anything that requires +//! // mutable access to a non-pinned version of it will no longer compile +//! +//! // 3. We can now assume that the tracker value will never be moved, thus +//! // this will never panic! +//! ptr_to_pinned_tracker.as_mut().check_for_move(); //! ``` //! -//! It is worth reiterating that [Pin]\

does *not* change the fact that a Rust -//! compiler considers all types movable. [`mem::swap`] remains callable for any `T`. Instead, -//! [Pin]\

prevents certain *values* (pointed to by pointers wrapped in -//! [Pin]\

) from being moved by making it impossible to call methods that require -//! [&mut] T on them (like [`mem::swap`]). -//! -//! [Pin]\

can be used to wrap any pointer type `P`, and as such it interacts with -//! [`Deref`] and [`DerefMut`]. A [Pin]\

where P: [Deref] should be -//! considered as a "`P`-style pointer" to a pinned P::[Target] – so, a -//! [Pin]<[Box]\> is an owned pointer to a pinned `T`, and a -//! [Pin]<[Rc]\> is a reference-counted pointer to a pinned `T`. -//! For correctness, [Pin]\

relies on the implementations of [`Deref`] and -//! [`DerefMut`] not to move out of their `self` parameter, and only ever to -//! return a pointer to pinned data when they are called on a pinned pointer. -//! -//! # `Unpin` -//! -//! Many types are always freely movable, even when pinned, because they do not -//! rely on having a stable address. This includes all the basic types (like -//! [`bool`], [`i32`], and references) as well as types consisting solely of these -//! types. Types that do not care about pinning implement the [`Unpin`] -//! auto-trait, which cancels the effect of [Pin]\

. For T: [Unpin], -//! [Pin]<[Box]\> and [Box]\ function identically, as do -//! [Pin]<[&mut] T> and [&mut] T. -//! -//! Note that pinning and [`Unpin`] only affect the pointed-to type P::[Target], -//! not the pointer type `P` itself that got wrapped in [Pin]\

. For example, -//! whether or not [Box]\ is [`Unpin`] has no effect on the behavior of -//! [Pin]<[Box]\> (here, `T` is the pointed-to type). -//! -//! # Example: self-referential struct -//! -//! Before we go into more details to explain the guarantees and choices -//! associated with [Pin]\

, we discuss some examples for how it might be used. -//! Feel free to [skip to where the theoretical discussion continues](#drop-guarantee). +//! Note that this invariant is enforced by simply making it impossible to call code that would +//! perform a move on the pinned value. This is the case since the only way to access that pinned +//! value is through the pinning [Pin]<[&mut] T>>, which in turn restricts our access. +//! +//! ## [`Unpin`] +//! +//! The vast majority of Rust types have no address-sensitive states. These types +//! implement the [`Unpin`] auto-trait, which cancels the restrictive effects of +//! [`Pin`] when the *pointee* type `T` is [`Unpin`]. When [`T: Unpin`][Unpin], +//! [Pin]<[Box]\> functions identically to a non-pinning [`Box`]; similarly, +//! [Pin]<[&mut] T> would impose no additional restrictions above a regular +//! [`&mut T`]. +//! +//! The idea of this trait is to alleviate the reduced ergonomics of APIs that require the use +//! of [`Pin`] for soundness for some types, but which also want to be used by other types that +//! don't care about pinning. The prime example of such an API is [`Future::poll`]. There are many +//! [`Future`] types that don't care about pinning. These futures can implement [`Unpin`] and +//! therefore get around the pinning related restrictions in the API, while still allowing the +//! subset of [`Future`]s which *do* require pinning to be implemented soundly. +//! +//! Note that the interaction between a [`Pin`] and [`Unpin`] is through the type of the +//! **pointee** value, [`::Target`][Target]. Whether the `Ptr` type itself +//! implements [`Unpin`] does not affect the behavior of a [`Pin`]. For example, whether or not +//! [`Box`] is [`Unpin`] has no effect on the behavior of [Pin]<[Box]\>, because +//! `T` is the type of the pointee value, not [`Box`]. So, whether `T` implements [`Unpin`] is +//! the thing that will affect the behavior of the [Pin]<[Box]\>. +//! +//! Builtin types that are [`Unpin`] include all of the primitive types, like [`bool`], [`i32`], +//! and [`f32`], references ([&]T and [&mut] T), etc., as well as many +//! core and standard library types like [`Box`], [`String`], and more. +//! These types are marked [`Unpin`] because they do not have an ddress-sensitive state like the +//! ones we discussed above. If they did have such a state, those parts of their interface would be +//! unsound without being expressed through pinning, and they would then need to not +//! implement [`Unpin`]. +//! +//! The compiler is free to take the conservative stance of marking types as [`Unpin`] so long as +//! all of the types that compose its fields are also [`Unpin`]. This is because if a type +//! implements [`Unpin`], then it is unsound for that type's implementation to rely on +//! pinning-related guarantees for soundness, *even* when viewed through a "pinning" pointer! It is +//! the responsibility of the implementor of a type that relies upon pinning for soundness to +//! ensure that type is *not* marked as [`Unpin`] by adding [`PhantomPinned`] field. This is +//! exactly what we did with our `AddrTracker` example above. Without doing this, you *must not* +//! rely on pinning-related guarantees to apply to your type! +//! +//! If need to truly pin a value of a foreign or built-in type that implements [`Unpin`], you'll +//! need to create your own wrapper type around the [`Unpin`] type you want to pin and then +//! opts-out of [`Unpin`] using [`PhantomPinned`]. +//! +//! Exposing access to the inner field which you want to remain pinned must then be carefully +//! considered as well! Remember, exposing a method that gives access to a +//! [Pin]<[&mut] InnerT>> where `InnerT: [Unpin]` would allow safe code to trivially +//! move the inner value out of that pinning pointer, which is precisely what you're seeking to +//! prevent! Exposing a field of a pinned value through a pinning pointer is called "projecting" +//! a pin, and the more general case of deciding in which cases a pin should be able to be +//! projected or not is called "structural pinning." We will go into more detail about this +//! [below][structural-pinning]. +//! +//! # Examples of address-sensitive types +//! [address-sensitive-examples]: #examples-of-address-sensitive-types +//! +//! ## A self-referential struct +//! [self-ref]: #a-self-referential-struct +//! [`Unmovable`]: #a-self-referential-struct +//! +//! Self-referential structs are the simplest kind of address-sensitive type. +//! +//! It is often useful for a struct to hold a pointer back into itself, which +//! allows the program to efficiently track subsections of the struct. +//! Below, the `slice` field is a pointer into the `data` field, which +//! we could imagine being used to track a sliding window of `data` in parser +//! code. +//! +//! As mentioned before, this pattern is also used extensively by compiler-generated +//! [`Future`]s. //! //! ```rust //! use std::pin::Pin; //! use std::marker::PhantomPinned; //! use std::ptr::NonNull; //! -//! // This is a self-referential struct because the slice field points to the data field. -//! // We cannot inform the compiler about that with a normal reference, -//! // as this pattern cannot be described with the usual borrowing rules. -//! // Instead we use a raw pointer, though one which is known not to be null, -//! // as we know it's pointing at the string. +//! /// This is a self-referential struct because `self.slice` points into `self.data`. //! struct Unmovable { -//! data: String, -//! slice: NonNull, +//! /// Backing buffer. +//! data: [u8; 64], +//! /// Points at `self.data` which we know is itself non-null. Raw pointer because we can't do +//! /// this with a normal reference. +//! slice: NonNull<[u8]>, +//! /// Suppress `Unpin` so that this cannot be moved out of a `Pin` once constructed. //! _pin: PhantomPinned, //! } //! //! impl Unmovable { -//! // To ensure the data doesn't move when the function returns, -//! // we place it in the heap where it will stay for the lifetime of the object, -//! // and the only way to access it would be through a pointer to it. -//! fn new(data: String) -> Pin> { +//! /// Create a new `Unmovable`. +//! /// +//! /// To ensure the data doesn't move we place it on the heap behind a pinning Box. +//! /// Note that the data is pinned, but the `Pin>` which is pinning it can +//! /// itself still be moved. This is important because it means we can return the pinning +//! /// pointer from the function, which is itself a kind of move! +//! fn new() -> Pin> { //! let res = Unmovable { -//! data, -//! // we only create the pointer once the data is in place -//! // otherwise it will have already moved before we even started -//! slice: NonNull::dangling(), +//! data: [0; 64], +//! // We only create the pointer once the data is in place +//! // otherwise it will have already moved before we even started. +//! slice: NonNull::from(&[]), //! _pin: PhantomPinned, //! }; -//! let mut boxed = Box::pin(res); +//! // First we put the data in a box, which will be its final resting place +//! let mut boxed = Box::new(res); //! -//! let slice = NonNull::from(&boxed.data); -//! // we know this is safe because modifying a field doesn't move the whole struct -//! unsafe { -//! let mut_ref: Pin<&mut Self> = Pin::as_mut(&mut boxed); -//! Pin::get_unchecked_mut(mut_ref).slice = slice; -//! } -//! boxed +//! // Then we make the slice field point to the proper part of that boxed data. +//! // From now on we need to make sure we don't move the boxed data. +//! boxed.slice = NonNull::from(&boxed.data); +//! +//! // To do that, we pin the data in place by pointing to it with a pinning +//! // (`Pin`-wrapped) pointer. +//! // +//! // `Box::into_pin` makes existing `Box` pin the data in-place without moving it, +//! // so we can safely do this now *after* inserting the slice pointer above, but we have +//! // to take care that we haven't performed any other semantic moves of `res` in between. +//! let pin = Box::into_pin(boxed); +//! +//! // Now we can return the pinned (through a pinning Box) data +//! pin //! } //! } //! -//! let unmoved = Unmovable::new("hello".to_string()); -//! // The pointer should point to the correct location, -//! // so long as the struct hasn't moved. +//! let unmovable: Pin> = Unmovable::new(); +//! +//! // The inner pointee `Unmovable` struct will now never be allowed to move. //! // Meanwhile, we are free to move the pointer around. //! # #[allow(unused_mut)] -//! let mut still_unmoved = unmoved; +//! let mut still_unmoved = unmovable; //! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data)); //! -//! // Since our type doesn't implement Unpin, this will fail to compile: -//! // let mut new_unmoved = Unmovable::new("world".to_string()); +//! // We cannot mutably dereference a `Pin` unless the pointee is `Unpin` or we use unsafe. +//! // Since our type doesn't implement `Unpin`, this will fail to compile. +//! // let mut new_unmoved = Unmovable::new(); //! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved); //! ``` //! -//! # Example: intrusive doubly-linked list +//! ## An intrusive, doubly-linked list +//! [linked-list]: #an-intrusive-doubly-linked-list +//! +//! In an intrusive doubly-linked list, the collection itself does not own the memory in which +//! each of its elements is stored. Instead, each client is free to allocate space for elements it +//! adds to the list in whichever manner it likes, including on the stack! Elements can live on a +//! stack frame that lives shorter than the collection does provided the elements that live in a +//! given stack frame are removed from the list before going out of scope. +//! +//! To make such an intrusive data structure work, every element stores pointers to its predecessor +//! and successor within its own data, rather than having the list structure itself managing those +//! pointers. It is in this sense that the structure is "intrusive": the details of how an +//! element is stored within the larger structure "intrudes" on the implementation of the element +//! type itself! +//! +//! The full implementation details of such a data structure are outside the scope of this +//! documentation, but we will discuss how [`Pin`] can help to do so. +//! +//! Using such an intrusive pattern, elements may only be added when they are pinned. If we think +//! about the consequences of adding non-pinned values to such a list, this becomes clear: +//! +//! *Moving* or otherwise invalidating an element's data would invalidate the pointers back to it +//! which are stored in the elements ahead and behind it. Thus, in order to soundly dereference +//! the pointers stored to the next and previous elements, we must satisfy the guarantee that +//! nothing has invalidated those pointers (which point to data that we do not own). +//! +//! Moreover, the [`Drop`][Drop] implementation of each element must in some way notify its +//! predecessor and successor elements that it should be removed from the list before it is fully +//! destroyed, otherwise the pointers back to it would again become invalidated. //! -//! In an intrusive doubly-linked list, the collection does not actually allocate -//! the memory for the elements itself. Allocation is controlled by the clients, -//! and elements can live on a stack frame that lives shorter than the collection does. +//! Crucially, this means we have to be able to rely on [`drop`] always being called before an +//! element is invalidated. If an element could be deallocated or otherwise invalidated without +//! calling [`drop`], the pointers to it stored in its neighboring elements would +//! become invalid, which would break the data structure. //! -//! To make this work, every element has pointers to its predecessor and successor in -//! the list. Elements can only be added when they are pinned, because moving the elements -//! around would invalidate the pointers. Moreover, the [`Drop`][Drop] implementation of a linked -//! list element will patch the pointers of its predecessor and successor to remove itself -//! from the list. +//! Therefore, pinning data also comes with [the "`Drop` guarantee"][drop-guarantee]. //! -//! Crucially, we have to be able to rely on [`drop`] being called. If an element -//! could be deallocated or otherwise invalidated without calling [`drop`], the pointers into it -//! from its neighboring elements would become invalid, which would break the data structure. +//! # Subtle details and the `Drop` guarantee +//! [subtle-details]: self#subtle-details-and-the-drop-guarantee +//! [drop-guarantee]: self#subtle-details-and-the-drop-guarantee //! -//! Therefore, pinning also comes with a [`drop`]-related guarantee. +//! The purpose of pinning is not *just* to prevent a value from being *moved*, but more +//! generally to be able to rely on the pinned value *remaining valid **at a specific place*** in +//! memory. //! -//! # `Drop` guarantee +//! To do so, pinning a value adds an *additional* invariant that must be upheld in order for use +//! of the pinned data to be valid, on top of the ones that must be upheld for a non-pinned value +//! of the same type to be valid: //! -//! The purpose of pinning is to be able to rely on the placement of some data in memory. -//! To make this work, not just moving the data is restricted; deallocating, repurposing, or -//! otherwise invalidating the memory used to store the data is restricted, too. -//! Concretely, for pinned data you have to maintain the invariant -//! that *its memory will not get invalidated or repurposed from the moment it gets pinned until -//! when [`drop`] is called*. Only once [`drop`] returns or panics, the memory may be reused. +//! From the moment a value is pinned by constructing a [`Pin`]ning pointer to it, that value +//! must *remain, **valid***, at that same address in memory, *until its [`drop`] handler is +//! called.* //! -//! Memory can be "invalidated" by deallocation, but also by -//! replacing a [Some]\(v) by [`None`], or calling [`Vec::set_len`] to "kill" some -//! elements off of a vector. It can be repurposed by using [`ptr::write`] to overwrite it without -//! calling the destructor first. None of this is allowed for pinned data without calling [`drop`]. +//! There is some subtlety to this which we have not yet talked about in detail. The invariant +//! described above means that, yes, //! -//! This is exactly the kind of guarantee that the intrusive linked list from the previous -//! section needs to function correctly. +//! 1. The value must not be moved out of its location in memory //! -//! Notice that this guarantee does *not* mean that memory does not leak! It is still -//! completely okay to not ever call [`drop`] on a pinned element (e.g., you can still -//! call [`mem::forget`] on a [Pin]<[Box]\>). In the example of the doubly-linked -//! list, that element would just stay in the list. However you must not free or reuse the storage -//! *without calling [`drop`]*. +//! but it also implies that, //! -//! # `Drop` implementation +//! 2. The memory location that stores the value must not get invalidated or otherwise repurposed +//! during the lifespan of the pinned value until its [`drop`] returns or panics +//! +//! This point is subtle but required for intrusive data structures to be implemented soundly. +//! +//! ## `Drop` guarantee +//! +//! There needs to be a way for a pinned value to notify any code that is relying on its pinned +//! status that it is about to be destroyed. In this way, the dependent code can remove the +//! pinned value's address from its data structures or otherwise change its behavior with the +//! knowledge that it can no longer rely on that value existing at the location it was pinned to. +//! +//! Thus, in any situation where we may want to overwrite a pinned value, that value's [`drop`] must +//! be called beforehand (unless the pinned value implements [`Unpin`], in which case we can ignore +//! all of [`Pin`]'s guarantees, as usual). +//! +//! The most common storage-reuse situations occur when a value on the stack is destroyed as part +//! of a function return and when heap storage is freed. In both cases, [`drop`] gets run for us +//! by Rust when using standard safe code. However, for manual heap allocations or otherwise +//! custom-allocated storage, [`unsafe`] code must make sure to call [`ptr::drop_in_place`] before +//! deallocating and re-using said storage. +//! +//! In addition, storage "re-use"/invalidation can happen even if no storage is (de-)allocated. +//! For example, if we had an [`Option`] which contained a `Some(v)` where `v` is pinned, then `v` +//! would be invalidated by setting that option to `None`. +//! +//! Similarly, if a [`Vec`] was used to store pinned values and [`Vec::set_len`] was used to +//! manually "kill" some elements of a vector, all of the items "killed" would become invalidated, +//! which would be *undefined behavior* if those items were pinned. +//! +//! Both of these cases are somewhat contrived, but it is crucial to remember that [`Pin`]ned data +//! *must* be [`drop`]ped before it is invalidated; not just to prevent memory leaks, but as a +//! matter of soundness. As a corollary, the following code can *never* be made safe: +//! +//! ```rust +//! # use std::mem::ManuallyDrop; +//! # use std::pin::Pin; +//! # struct Type; +//! // Pin something inside a `ManuallyDrop`. This is fine on its own. +//! let mut pin: Pin>> = Box::pin(ManuallyDrop::new(Type)); +//! +//! // However, creating a pinning mutable reference to the type *inside* +//! // the `ManuallyDrop` is not! +//! let inner: Pin<&mut Type> = unsafe { +//! Pin::map_unchecked_mut(pin.as_mut(), |x| &mut **x) +//! }; +//! ``` //! -//! If your type uses pinning (such as the two examples above), you have to be careful -//! when implementing [`Drop`][Drop]. The [`drop`] function takes [&mut] self, but this -//! is called *even if your type was previously pinned*! It is as if the -//! compiler automatically called [`Pin::get_unchecked_mut`]. +//! Because [`mem::ManuallyDrop`] inhibits the destructor of `Type`, it won't get run when the +//! [Box]<[ManuallyDrop]\> is dropped, thus violating the drop guarantee of the +//! [Pin]<[&mut] Type>>. //! -//! This can never cause a problem in safe code because implementing a type that -//! relies on pinning requires unsafe code, but be aware that deciding to make -//! use of pinning in your type (for example by implementing some operation on -//! [Pin]<[&]Self> or [Pin]<[&mut] Self>) has consequences for your +//! Of course, *leaking* memory in such a way that its underlying storage will never get invalidated +//! or re-used is still fine: [`mem::forget`]ing a [`Box`] prevents its storage from ever getting +//! re-used, so the [`drop`] guarantee is still satisfied. +//! +//! # Implementing an address-sensitive type. +//! +//! This section goes into detail on important considerations for implementing your own +//! address-sensitive types, which are different from merely using [`Pin`] in a generic +//! way. +//! +//! ## Implementing [`Drop`] for types with address-sensitive states +//! [drop-impl]: self#implementing-drop-for-types-with-address-sensitive-states +//! +//! The [`drop`] function takes [`&mut self`], but this is called *even if that `self` has been +//! pinned*! Implementing [`Drop`] for a type with address-sensitive states, because if `self` was +//! indeed in an address-sensitive state before [`drop`] was called, it is as if the compiler +//! automatically called [`Pin::get_unchecked_mut`]. +//! +//! This can never cause a problem in purely safe code because creating a pinning pointer to +//! a type which has an address-sensitive (thus does not implement `Unpin`) requires `unsafe`, +//! but it is important to note that choosing to take advantage of pinning-related guarantees +//! to justify validity in the implementation of your type has consequences for that type's //! [`Drop`][Drop] implementation as well: if an element of your type could have been pinned, -//! you must treat [`Drop`][Drop] as implicitly taking [Pin]<[&mut] Self>. +//! you must treat [`Drop`][Drop] as implicitly taking self: [Pin]<[&mut] Self>. //! -//! For example, you could implement [`Drop`][Drop] as follows: +//! You should implement [`Drop`] as follows: //! //! ```rust,no_run //! # use std::pin::Pin; -//! # struct Type { } +//! # struct Type; //! impl Drop for Type { //! fn drop(&mut self) { //! // `new_unchecked` is okay because we know this value is never used @@ -195,72 +623,157 @@ //! } //! ``` //! -//! The function `inner_drop` has the type that [`drop`] *should* have, so this makes sure that -//! you do not accidentally use `self`/`this` in a way that is in conflict with pinning. +//! The function `inner_drop` has the signature that [`drop`] *should* have in this situation. +//! This makes sure that you do not accidentally use `self`/`this` in a way that is in conflict +//! with pinning's invariants. //! -//! Moreover, if your type is `#[repr(packed)]`, the compiler will automatically +//! Moreover, if your type is [`#[repr(packed)]`][packed], the compiler will automatically //! move fields around to be able to drop them. It might even do //! that for fields that happen to be sufficiently aligned. As a consequence, you cannot use -//! pinning with a `#[repr(packed)]` type. -//! -//! # Projections and Structural Pinning -//! -//! When working with pinned structs, the question arises how one can access the -//! fields of that struct in a method that takes just [Pin]<[&mut] Struct>. -//! The usual approach is to write helper methods (so called *projections*) -//! that turn [Pin]<[&mut] Struct> into a reference to the field, but what type should -//! that reference have? Is it [Pin]<[&mut] Field> or [&mut] Field? -//! The same question arises with the fields of an `enum`, and also when considering -//! container/wrapper types such as [Vec]\, [Box]\, -//! or [RefCell]\. (This question applies to both mutable and shared references, -//! we just use the more common case of mutable references here for illustration.) -//! -//! It turns out that it is actually up to the author of the data structure to decide whether -//! the pinned projection for a particular field turns [Pin]<[&mut] Struct> -//! into [Pin]<[&mut] Field> or [&mut] Field. There are some -//! constraints though, and the most important constraint is *consistency*: -//! every field can be *either* projected to a pinned reference, *or* have -//! pinning removed as part of the projection. If both are done for the same field, -//! that will likely be unsound! -//! -//! As the author of a data structure you get to decide for each field whether pinning +//! pinning with a [`#[repr(packed)]`][packed] type. +//! +//! ### Implementing [`Drop`] for pointer types which will be used as [`Pin`]ning pointers +//! +//! It should further be noted that creating a pinning pointer of some type `Ptr` *also* carries +//! with it implications on the way that `Ptr` type must implement [`Drop`] +//! (as well as [`Deref`] and [`DerefMut`])! When implementing a pointer type that may be used as +//! a pinning pointer, you must also take the same care described above not to *move* out of or +//! otherwise invalidate the pointee during [`Drop`], [`Deref`], or [`DerefMut`] +//! implementations. +//! +//! ## "Assigning" pinned data +//! +//! Although in general it is not valid to swap data or assign through a [`Pin`] for the same +//! reason that reusing a pinned object's memory is invalid, it is possible to do validly when +//! implemented with special care for the needs of the exact data structure which is being +//! modified. For example, the assigning function must know how to update all uses of the pinned +//! address (and any other invariants necessary to satisfy validity for that type). For +//! [`Unmovable`] (from the example above), we could write an assignment function like so: +//! +//! ``` +//! # use std::pin::Pin; +//! # use std::marker::PhantomPinned; +//! # use std::ptr::NonNull; +//! # struct Unmovable { +//! # data: [u8; 64], +//! # slice: NonNull<[u8]>, +//! # _pin: PhantomPinned, +//! # } +//! # +//! impl Unmovable { +//! // Copies the contents of `src` into `self`, fixing up the self-pointer +//! // in the process. +//! fn assign(self: Pin<&mut Self>, src: Pin<&mut Self>) { +//! unsafe { +//! let unpinned_self = Pin::into_inner_unchecked(self); +//! let unpinned_src = Pin::into_inner_unchecked(src); +//! *unpinned_self = Self { +//! data: unpinned_src.data, +//! slice: NonNull::from(&mut []), +//! _pin: PhantomPinned, +//! }; +//! +//! let data_ptr = unpinned_src.data.as_ptr() as *const u8; +//! let slice_ptr = unpinned_src.slice.as_ptr() as *const u8; +//! let offset = slice_ptr.offset_from(data_ptr) as usize; +//! let len = (*unpinned_src.slice.as_ptr()).len(); +//! +//! unpinned_self.slice = NonNull::from(&mut unpinned_self.data[offset..offset+len]); +//! } +//! } +//! } +//! ``` +//! +//! Even though we can't have the compiler do the assignment for us, it's possible to write +//! such specialized functions for types that might need it. +//! +//! Note that it _is_ possible to assign generically through a [`Pin`] by way of [`Pin::set()`]. +//! This does not violate any guarantees, since it will run [`drop`] on the pointee value before +//! assigning the new value. Thus, the [`drop`] implementation still has a chance to perform the +//! necessary notifications to dependent values before the memory location of the original pinned +//! value is overwritten. +//! +//! ## Projections and Structural Pinning +//! [structural-pinning]: self#projections-and-structural-pinning +//! +//! With ordinary structs, it is natural that we want to add *projection* methods that allow +//! borrowing one or more of the inner fields of a struct when the caller has access to a +//! borrow of the whole struct: +//! +//! ``` +//! # struct Field; +//! struct Struct { +//! field: Field, +//! // ... +//! } +//! +//! impl Struct { +//! fn field(&mut self) -> &mut Field { &mut self.field } +//! } +//! ``` +//! +//! When working with address-sensitive types, it's not obvious what the signature of these +//! functions should be. If `field` takes self: [Pin]<[&mut Struct][&mut]>, should it +//! return [`&mut Field`] or [Pin]<[`&mut Field`]>? This question also arises with +//! `enum`s and wrapper types like [`Vec`], [`Box`], and [`RefCell`]. (This question +//! applies just as well to shared references, but we'll examine the more common case of mutable +//! references for illustration) +//! +//! It turns out that it's up to the author of `Struct` to decide which type the "projection" +//! should produce. The choice must be *consistent* though: if a pin is projected to a field +//! in one place, then it should very likely not be exposed elsewhere without projecting the +//! pin. +//! +//! As the author of a data structure, you get to decide for each field whether pinning //! "propagates" to this field or not. Pinning that propagates is also called "structural", //! because it follows the structure of the type. -//! In the following subsections, we describe the considerations that have to be made -//! for either choice. //! -//! ## Pinning *is not* structural for `field` +//! This choice depends on what guarantees you need from the field for your [`unsafe`] code to work. +//! If the field is itself address-sensitive, or participates in the parent struct's address +//! sensitivity, it will need to be structurally pinned. +//! +//! A useful test is if [`unsafe`] code that consumes [Pin]\<[&mut Struct][&mut]> +//! also needs to take note of the address of the field itself, it may be evidence that that field +//! is structurally pinned. Unfortunately, there are no hard-and-fast rules. //! -//! It may seem counter-intuitive that the field of a pinned struct might not be pinned, -//! but that is actually the easiest choice: if a [Pin]<[&mut] Field> is never created, -//! nothing can go wrong! So, if you decide that some field does not have structural pinning, -//! all you have to ensure is that you never create a pinned reference to that field. +//! ### Choosing pinning *not to be* structural for `field`... +//! +//! While counter-intuitive, it's often the easier choice: if you do not expose a +//! [Pin]<[&mut] Field>, you do not need to be careful about other code +//! moving out of that field, you just have to ensure is that you never create pinning +//! reference to that field. This does of course also mean that if you decide a field does not +//! have structural pinning, you must not write [`unsafe`] code that assumes (invalidly) that the +//! field *is* structurally pinned! //! //! Fields without structural pinning may have a projection method that turns -//! [Pin]<[&mut] Struct> into [&mut] Field: +//! [Pin]<[&mut] Struct> into [`&mut Field`]: //! //! ```rust,no_run //! # use std::pin::Pin; //! # type Field = i32; //! # struct Struct { field: Field } //! impl Struct { -//! fn pin_get_field(self: Pin<&mut Self>) -> &mut Field { -//! // This is okay because `field` is never considered pinned. +//! fn field(self: Pin<&mut Self>) -> &mut Field { +//! // This is okay because `field` is never considered pinned, therefore we do not +//! // need to uphold any pinning guarantees for this field in particular. Of course, +//! // we must not elsewhere assume this field *is* pinned if we choose to expose +//! // such a method! //! unsafe { &mut self.get_unchecked_mut().field } //! } //! } //! ``` //! -//! You may also impl [Unpin] for Struct *even if* the type of `field` -//! is not [`Unpin`]. What that type thinks about pinning is not relevant -//! when no [Pin]<[&mut] Field> is ever created. +//! You may also in this situation impl [Unpin] for Struct {} *even if* the type of +//! `field` is not [`Unpin`]. Since we have explicitly chosen not to care about pinning guarantees +//! for `field`, the way `field`'s type interacts with pinning is no longer relevant in the +//! context of its use in `Struct`. //! -//! ## Pinning *is* structural for `field` +//! ### Choosing pinning *to be* structural for `field`... //! //! The other option is to decide that pinning is "structural" for `field`, //! meaning that if the struct is pinned then so is the field. //! -//! This allows writing a projection that creates a [Pin]<[&mut] Field>, thus +//! This allows writing a projection that creates a [Pin]<[`&mut Field`]>, thus //! witnessing that the field is pinned: //! //! ```rust,no_run @@ -268,108 +781,117 @@ //! # type Field = i32; //! # struct Struct { field: Field } //! impl Struct { -//! fn pin_get_field(self: Pin<&mut Self>) -> Pin<&mut Field> { +//! fn field(self: Pin<&mut Self>) -> Pin<&mut Field> { //! // This is okay because `field` is pinned when `self` is. //! unsafe { self.map_unchecked_mut(|s| &mut s.field) } //! } //! } //! ``` //! -//! However, structural pinning comes with a few extra requirements: -//! -//! 1. The struct must only be [`Unpin`] if all the structural fields are -//! [`Unpin`]. This is the default, but [`Unpin`] is a safe trait, so as the author of -//! the struct it is your responsibility *not* to add something like -//! impl\ [Unpin] for Struct\. (Notice that adding a projection operation -//! requires unsafe code, so the fact that [`Unpin`] is a safe trait does not break -//! the principle that you only have to worry about any of this if you use [`unsafe`].) -//! 2. The destructor of the struct must not move structural fields out of its argument. This -//! is the exact point that was raised in the [previous section][drop-impl]: [`drop`] takes -//! [&mut] self, but the struct (and hence its fields) might have been pinned -//! before. You have to guarantee that you do not move a field inside your [`Drop`][Drop] -//! implementation. In particular, as explained previously, this means that your struct -//! must *not* be `#[repr(packed)]`. -//! See that section for how to write [`drop`] in a way that the compiler can help you -//! not accidentally break pinning. -//! 3. You must make sure that you uphold the [`Drop` guarantee][drop-guarantee]: -//! once your struct is pinned, the memory that contains the -//! content is not overwritten or deallocated without calling the content's destructors. -//! This can be tricky, as witnessed by [VecDeque]\: the destructor of -//! [VecDeque]\ can fail to call [`drop`] on all elements if one of the -//! destructors panics. This violates the [`Drop`][Drop] guarantee, because it can lead to -//! elements being deallocated without their destructor being called. -//! ([VecDeque]\ has no pinning projections, so this -//! does not cause unsoundness.) -//! 4. You must not offer any other operations that could lead to data being moved out of +//! Structural pinning comes with a few extra requirements: +//! +//! 1. *Structural [`Unpin`].* A struct can be [`Unpin`] only if all of its +//! structurally-pinned fields are, too. This is [`Unpin`]'s behavior by default. +//! However, as a libray author, it is your responsibility not to write something like +//! impl\ [Unpin] for Struct\ {} and then offer a method that provides +//! structural pinning to an inner field of `T`, which may not be [`Unpin`]! (Adding *any* +//! projection operation requires unsafe code, so the fact that [`Unpin`] is a safe trait does +//! not break the principle that you only have to worry about any of this if you use +//! [`unsafe`]) +//! +//! 2. *Pinned Destruction.* As discussed [above][drop-impl], [`drop`] takes +//! [`&mut self`], but the struct (and hence its fields) might have been pinned +//! before. The destructor must be written as if its argument was +//! self: [Pin]\<[`&mut Self`]>, instead. +//! +//! As a consequence, the struct *must not* be [`#[repr(packed)]`][packed]. +//! +//! 3. *Structural Notice of Destruction.* You must uphold the the +//! [`Drop` guarantee][drop-guarantee]: once your struct is pinned, the struct's storage cannot +//! be re-used without calling the structurally-pinned fields' destructors, as well. +//! +//! This can be tricky, as witnessed by [`VecDeque`]: the destructor of [`VecDeque`] +//! can fail to call [`drop`] on all elements if one of the destructors panics. This violates +//! the [`Drop` guarantee][drop-guarantee], because it can lead to elements being deallocated +//! without their destructor being called. +//! +//! [`VecDeque`] has no pinning projections, so its destructor is sound. If it wanted +//! to provide such structural pinning, its destructor would need to abort the process if any +//! of the destructors panicked. +//! +//! 4. You must not offer any other operations that could lead to data being *moved* out of //! the structural fields when your type is pinned. For example, if the struct contains an -//! [Option]\ and there is a [`take`][Option::take]-like operation with type -//! fn([Pin]<[&mut] Struct\>) -> [Option]\, -//! that operation can be used to move a `T` out of a pinned `Struct` – which means -//! pinning cannot be structural for the field holding this data. +//! [`Option`] and there is a [`take`][Option::take]-like operation with type +//! fn([Pin]<[&mut Struct\][&mut]>) -> [`Option`], +//! then that operation can be used to move a `T` out of a pinned `Struct` – which +//! means pinning cannot be structural for the field holding this data. //! //! For a more complex example of moving data out of a pinned type, -//! imagine if [RefCell]\ had a method -//! fn get_pin_mut(self: [Pin]<[&mut] Self>) -> [Pin]<[&mut] T>. +//! imagine if [`RefCell`] had a method +//! fn get_pin_mut(self: [Pin]<[`&mut Self`]>) -> [Pin]<[`&mut T`]>. //! Then we could do the following: //! ```compile_fail +//! # use std::cell::RefCell; +//! # use std::pin::Pin; //! fn exploit_ref_cell(rc: Pin<&mut RefCell>) { -//! { let p = rc.as_mut().get_pin_mut(); } // Here we get pinned access to the `T`. -//! let rc_shr: &RefCell = rc.into_ref().get_ref(); -//! let b = rc_shr.borrow_mut(); -//! let content = &mut *b; // And here we have `&mut T` to the same data. +//! // Here we get pinned access to the `T`. +//! let _: Pin<&mut T> = rc.as_mut().get_pin_mut(); +//! +//! // And here we have `&mut T` to the same data. +//! let shared: &RefCell = rc.into_ref().get_ref(); +//! let borrow = shared.borrow_mut(); +//! let content = &mut *borrow; //! } //! ``` -//! This is catastrophic, it means we can first pin the content of the -//! [RefCell]\ (using [RefCell]::get_pin_mut) and then move that +//! This is catastrophic: it means we can first pin the content of the +//! [`RefCell`] (using [RefCell]::get_pin_mut) and then move that //! content using the mutable reference we got later. //! -//! ## Examples +//! ### Structural Pinning examples //! -//! For a type like [Vec]\, both possibilities (structural pinning or not) make -//! sense. A [Vec]\ with structural pinning could have `get_pin`/`get_pin_mut` -//! methods to get pinned references to elements. However, it could *not* allow calling -//! [`pop`][Vec::pop] on a pinned [Vec]\ because that would move the (structurally +//! For a type like [`Vec`], both possibilities (structural pinning or not) make +//! sense. A [`Vec`] with structural pinning could have `get_pin`/`get_pin_mut` +//! methods to get pinning references to elements. However, it could *not* allow calling +//! [`pop`][Vec::pop] on a pinned [`Vec`] because that would move the (structurally //! pinned) contents! Nor could it allow [`push`][Vec::push], which might reallocate and thus also //! move the contents. //! -//! A [Vec]\ without structural pinning could -//! impl\ [Unpin] for [Vec]\, because the contents are never pinned -//! and the [Vec]\ itself is fine with being moved as well. +//! A [`Vec`] without structural pinning could +//! impl\ [Unpin] for [`Vec`], because the contents are never pinned +//! and the [`Vec`] itself is fine with being moved as well. //! At that point pinning just has no effect on the vector at all. //! //! In the standard library, pointer types generally do not have structural pinning, -//! and thus they do not offer pinning projections. This is why [Box]\: [Unpin] +//! and thus they do not offer pinning projections. This is why [`Box`]: [Unpin] //! holds for all `T`. It makes sense to do this for pointer types, because moving the -//! [Box]\ does not actually move the `T`: the [Box]\ can be freely -//! movable (aka [`Unpin`]) even if the `T` is not. In fact, even [Pin]<[Box]\> and -//! [Pin]<[&mut] T> are always [`Unpin`] themselves, for the same reason: +//! [`Box`] does not actually move the `T`: the [`Box`] can be freely +//! movable (aka [`Unpin`]) even if the `T` is not. In fact, even [Pin]<[`Box`]> and +//! [Pin]<[`&mut T`]> are always [`Unpin`] themselves, for the same reason: //! their contents (the `T`) are pinned, but the pointers themselves can be moved without moving -//! the pinned data. For both [Box]\ and [Pin]<[Box]\>, +//! the pinned data. For both [`Box`] and [Pin]<[`Box`]>, //! whether the content is pinned is entirely independent of whether the //! pointer is pinned, meaning pinning is *not* structural. //! //! When implementing a [`Future`] combinator, you will usually need structural pinning -//! for the nested futures, as you need to get pinned references to them to call [`poll`]. -//! But if your combinator contains any other data that does not need to be pinned, +//! for the nested futures, as you need to get pinning ([`Pin`]-wrapped) references to them to +//! call [`poll`]. But if your combinator contains any other data that does not need to be pinned, //! you can make those fields not structural and hence freely access them with a -//! mutable reference even when you just have [Pin]<[&mut] Self> (such as in your own -//! [`poll`] implementation). +//! mutable reference even when you just have [Pin]<[`&mut Self`]> +//! (such as in your own [`poll`] implementation). //! +//! [`&mut T`]: &mut +//! [`&mut self`]: &mut +//! [`&mut Self`]: &mut +//! [`&mut Field`]: &mut //! [Deref]: crate::ops::Deref "ops::Deref" //! [`Deref`]: crate::ops::Deref "ops::Deref" //! [Target]: crate::ops::Deref::Target "ops::Deref::Target" //! [`DerefMut`]: crate::ops::DerefMut "ops::DerefMut" //! [`mem::swap`]: crate::mem::swap "mem::swap" //! [`mem::forget`]: crate::mem::forget "mem::forget" -//! [Vec]: ../../std/vec/struct.Vec.html "Vec" -//! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len "Vec::set_len" -//! [Box]: ../../std/boxed/struct.Box.html "Box" -//! [Vec::pop]: ../../std/vec/struct.Vec.html#method.pop "Vec::pop" -//! [Vec::push]: ../../std/vec/struct.Vec.html#method.push "Vec::push" -//! [Rc]: ../../std/rc/struct.Rc.html "rc::Rc" +//! [ManuallyDrop]: crate::mem::ManuallyDrop "ManuallyDrop" //! [RefCell]: crate::cell::RefCell "cell::RefCell" //! [`drop`]: Drop::drop -//! [VecDeque]: ../../std/collections/struct.VecDeque.html "collections::VecDeque" //! [`ptr::write`]: crate::ptr::write "ptr::write" //! [`Future`]: crate::future::Future "future::Future" //! [drop-impl]: #drop-implementation @@ -378,6 +900,23 @@ //! [&]: reference "shared reference" //! [&mut]: reference "mutable reference" //! [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe" +//! [packed]: https://doc.rust-lang.org/nomicon/other-reprs.html#reprpacked +//! [`std::alloc`]: ../../std/alloc/index.html +//! [`Box`]: ../../std/boxed/struct.Box.html +//! [Box]: ../../std/boxed/struct.Box.html "Box" +//! [`Box`]: ../../std/boxed/struct.Box.html "Box" +//! [`Rc`]: ../../std/rc/struct.Rc.html +//! [Rc]: ../../std/rc/struct.Rc.html "rc::Rc" +//! [`Vec`]: ../../std/vec/struct.Vec.html +//! [Vec]: ../../std/vec/struct.Vec.html "Vec" +//! [`Vec`]: ../../std/vec/struct.Vec.html "Vec" +//! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len "Vec::set_len" +//! [Vec::pop]: ../../std/vec/struct.Vec.html#method.pop "Vec::pop" +//! [Vec::push]: ../../std/vec/struct.Vec.html#method.push "Vec::push" +//! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len +//! [`VecDeque`]: ../../std/collections/struct.VecDeque.html +//! [VecDeque]: ../../std/collections/struct.VecDeque.html "collections::VecDeque" +//! [`String`]: ../../std/string/struct.String.html "String" #![stable(feature = "pin", since = "1.33.0")] @@ -386,17 +925,159 @@ use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver}; -/// A pinned pointer. +#[allow(unused_imports)] +use crate::{ + cell::{RefCell, UnsafeCell}, + future::Future, + marker::PhantomPinned, + mem, ptr, +}; + +/// A pointer which pins its pointee in place. +/// +/// [`Pin`] is a wrapper around some kind of pointer `Ptr` which makes that pointer "pin" its +/// pointee value in place, thus preventing the value referenced by that pointer from being moved +/// or otherwise invalidated at that place in memory unless it implements [`Unpin`]. +/// +/// *See the [`pin` module] documentation for a more thorough exploration of pinning.* +/// +/// ## Pinning values with [`Pin`] +/// +/// In order to pin a value, we wrap a *pointer to that value* (of some type `Ptr`) in a +/// [`Pin`]. [`Pin`] can wrap any pointer type, forming a promise that the **pointee** +/// will not be *moved* or [otherwise invalidated][subtle-details]. If the pointee value's type +/// implements [`Unpin`], we are free to disregard these requirements entirely and can wrap any +/// pointer to that value in [`Pin`] directly via [`Pin::new`]. If the pointee value's type does +/// not implement [`Unpin`], then Rust will not let us use the [`Pin::new`] function directly and +/// we'll need to construct a [`Pin`]-wrapped pointer in one of the more specialized manners +/// discussed below. +/// +/// We call such a [`Pin`]-wrapped pointer a **pinning pointer** (or pinning ref, or pinning +/// [`Box`], etc.) because its existince is the thing that is pinning the underlying pointee in +/// place: it is the metaphorical "pin" securing the data in place on the pinboard (in memory). +/// +/// It is important to stress that the thing in the [`Pin`] is not the value which we want to pin +/// itself, but rather a pointer to that value! A [`Pin`] does not pin the `Ptr` but rather +/// the pointer's ***pointee** value*. +/// +/// The most common set of types which require pinning related guarantees for soundness are the +/// compiler-generated state machines that implement [`Future`] for the return value of +/// `async fn`s. These compiler-generated [`Future`]s may contain self-referrential pointers, one +/// of the most common use cases for [`Pin`]. More details on this point are provided in the +/// [`pin` module] docs, but suffice it to say they require the guarantees provided by pinning to +/// be implemented soundly. +/// +/// This requirement for the implementation of `async fn`s means that the [`Future`] trait +/// requires all calls to [`poll`] to use a self: [Pin]\<&mut Self> parameter instead +/// of the usual `&mut self`. Therefore, when manually polling a future, you will need to pin it +/// first. +/// +/// You may notice that `async fn`-sourced [`Future`]s are only a small percentage of all +/// [`Future`]s that exist, yet we had to modify the signature of [`poll`] for all [`Future`]s +/// to accommodate them. This is unfortunate, but there is a way that the language attempts to +/// alleviate the extra friction that this API choice incurs: the [`Unpin`] trait. +/// +/// The vast majority of Rust types have no reason to ever care about being pinned. These +/// types implement the [`Unpin`] trait, which entirely opts all values of that type out of +/// pinning-related guarantees. For values of these types, pinning a value by pointing to it with a +/// [`Pin`] will have no actual effect. +/// +/// The reason this distinction exists is exactly to allow APIs like [`Future::poll`] to take a +/// [`Pin`] as an argument for all types while only forcing [`Future`] types that actually +/// care about pinning guarantees pay the ergonomics cost. For the majority of [`Future`] types +/// that don't have a reason to care about being pinned and therefore implement [`Unpin`], the +/// [Pin]\<&mut Self> will act exactly like a regular `&mut Self`, allowing direct +/// access to the underlying value. Only types that *don't* implement [`Unpin`] will be restricted. +/// +/// ### Pinning a value of a type that implements [`Unpin`] +/// +/// If the type of the value you need to "pin" implements [`Unpin`], you can trivially wrap any +/// pointer to that value in a [`Pin`] by calling [`Pin::new`]. +/// +/// ``` +/// use std::pin::Pin; +/// +/// // Create a value of a type that implements `Unpin` +/// let mut unpin_future = std::future::ready(5); +/// +/// // Pin it by creating a pinning mutable reference to it (ready to be `poll`ed!) +/// let my_pinned_unpin_future: Pin<&mut _> = Pin::new(&mut unpin_future); +/// ``` +/// +/// ### Pinning a value inside a [`Box`] +/// +/// The simplest and most flexible way to pin a value that does not implement [`Unpin`] is to put +/// that value inside a [`Box`] and then turn that [`Box`] into a "pinning [`Box`]" by wrapping it +/// in a [`Pin`]. You can do both of these in a single step using [`Box::pin`]. Let's see an +/// example of using this flow to pin a [`Future`] returned from calling an `async fn`, a common +/// use case as described above. +/// +/// ``` +/// use std::pin::Pin; +/// +/// async fn add_one(x: u32) -> u32 { +/// x + 1 +/// } +/// +/// // Call the async function to get a future back +/// let fut = add_one(42); +/// +/// // Pin the future inside a pinning box +/// let pinned_fut: Pin> = Box::pin(fut); +/// ``` +/// +/// If you have a value which is already boxed, for example a [`Box`][Box], you can pin +/// that value in-place at its current memory address using [`Box::into_pin`]. +/// +/// ``` +/// use std::pin::Pin; +/// use std::future::Future; +/// +/// async fn add_one(x: u32) -> u32 { +/// x + 1 +/// } +/// +/// fn boxed_add_one(x: u32) -> Box> { +/// Box::new(add_one(x)) +/// } +/// +/// let boxed_fut = boxed_add_one(42); +/// +/// // Pin the future inside the existing box +/// let pinned_fut: Pin> = Box::into_pin(boxed_fut); +/// ``` /// -/// This is a wrapper around a kind of pointer which makes that pointer "pin" its -/// value in place, preventing the value referenced by that pointer from being moved -/// unless it implements [`Unpin`]. +/// There are similar pinning methods offered on the other standard library smart pointer types +/// as well, like [`Rc`] and [`Arc`]. /// -/// `Pin

` is guaranteed to have the same memory layout and ABI as `P`. +/// ### Pinning a value on the stack using [`pin!`] /// -/// *See the [`pin` module] documentation for an explanation of pinning.* +/// There are some situations where it is desirable or even required (for example, in a `#[no_std]` +/// context where you don't have access to the standard library or allocation in general) to +/// pin a value which does not implement [`Unpin`] to its location on the stack. Doing so is +/// possible using the [`pin!`] macro. See its documentation for more. /// -/// [`pin` module]: self +/// ## Layout and ABI +/// +/// [`Pin`] is guaranteed to have the same memory layout and ABI[^noalias] as `Ptr`. +/// +/// [^noalias]: There is a bit of nuance here that is still being decided about whether the +/// aliasing semantics of `Pin<&mut T>` should be different than `&mut T`, but this is true as of +/// today. +/// +/// [`pin!`]: crate::pin::pin "pin!" +/// [`Future`]: crate::future::Future "Future" +/// [`poll`]: crate::future::Future::poll "Future::poll" +/// [`Future::poll`]: crate::future::Future::poll "Future::poll" +/// [`pin` module]: self "pin module" +/// [`Rc`]: ../../std/rc/struct.Rc.html "Rc" +/// [`Arc`]: ../../std/sync/struct.Arc.html "Arc" +/// [Box]: ../../std/boxed/struct.Box.html "Box" +/// [`Box`]: ../../std/boxed/struct.Box.html "Box" +/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin "Box::pin" +/// [`Box::into_pin`]: ../../std/boxed/struct.Box.html#method.into_pin "Box::into_pin" +/// [subtle-details]: self#subtle-details-and-the-drop-guarantee "pin subtle details" +/// [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe" // // Note: the `Clone` derive below causes unsoundness as it's possible to implement // `Clone` for mutable references. @@ -406,7 +1087,7 @@ use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver}; #[fundamental] #[repr(transparent)] #[derive(Copy, Clone)] -pub struct Pin

{ +pub struct Pin { // FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to: // - deter downstream users from accessing it (which would be unsound!), // - let the `pin!` macro access it (such a macro requires using struct @@ -414,7 +1095,7 @@ pub struct Pin

{ // Long-term, `unsafe` fields or macro hygiene are expected to offer more robust alternatives. #[unstable(feature = "unsafe_pin_internals", issue = "none")] #[doc(hidden)] - pub pointer: P, + pub pointer: Ptr, } // The following implementations aren't derived in order to avoid soundness @@ -424,68 +1105,68 @@ pub struct Pin

{ // See for more details. #[stable(feature = "pin_trait_impls", since = "1.41.0")] -impl PartialEq> for Pin

+impl PartialEq> for Pin where - P::Target: PartialEq, + Ptr::Target: PartialEq, { fn eq(&self, other: &Pin) -> bool { - P::Target::eq(self, other) + Ptr::Target::eq(self, other) } fn ne(&self, other: &Pin) -> bool { - P::Target::ne(self, other) + Ptr::Target::ne(self, other) } } #[stable(feature = "pin_trait_impls", since = "1.41.0")] -impl> Eq for Pin

{} +impl> Eq for Pin {} #[stable(feature = "pin_trait_impls", since = "1.41.0")] -impl PartialOrd> for Pin

+impl PartialOrd> for Pin where - P::Target: PartialOrd, + Ptr::Target: PartialOrd, { fn partial_cmp(&self, other: &Pin) -> Option { - P::Target::partial_cmp(self, other) + Ptr::Target::partial_cmp(self, other) } fn lt(&self, other: &Pin) -> bool { - P::Target::lt(self, other) + Ptr::Target::lt(self, other) } fn le(&self, other: &Pin) -> bool { - P::Target::le(self, other) + Ptr::Target::le(self, other) } fn gt(&self, other: &Pin) -> bool { - P::Target::gt(self, other) + Ptr::Target::gt(self, other) } fn ge(&self, other: &Pin) -> bool { - P::Target::ge(self, other) + Ptr::Target::ge(self, other) } } #[stable(feature = "pin_trait_impls", since = "1.41.0")] -impl> Ord for Pin

{ +impl> Ord for Pin { fn cmp(&self, other: &Self) -> cmp::Ordering { - P::Target::cmp(self, other) + Ptr::Target::cmp(self, other) } } #[stable(feature = "pin_trait_impls", since = "1.41.0")] -impl> Hash for Pin

{ +impl> Hash for Pin { fn hash(&self, state: &mut H) { - P::Target::hash(self, state); + Ptr::Target::hash(self, state); } } -impl> Pin

{ - /// Construct a new `Pin

` around a pointer to some data of a type that +impl> Pin { + /// Construct a new `Pin` around a pointer to some data of a type that /// implements [`Unpin`]. /// /// Unlike `Pin::new_unchecked`, this method is safe because the pointer - /// `P` dereferences to an [`Unpin`] type, which cancels the pinning guarantees. + /// `Ptr` dereferences to an [`Unpin`] type, which cancels the pinning guarantees. /// /// # Examples /// @@ -493,22 +1174,25 @@ impl> Pin

{ /// use std::pin::Pin; /// /// let mut val: u8 = 5; - /// // We can pin the value, since it doesn't care about being moved + /// + /// // Since `val` doesn't care about being moved, we can safely create a "facade" `Pin` + /// // which will allow `val` to participate in `Pin`-bound apis without checking that + /// // pinning guarantees are actually upheld. /// let mut pinned: Pin<&mut u8> = Pin::new(&mut val); /// ``` #[inline(always)] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] #[stable(feature = "pin", since = "1.33.0")] - pub const fn new(pointer: P) -> Pin

{ + pub const fn new(pointer: Ptr) -> Pin { // SAFETY: the value pointed to is `Unpin`, and so has no requirements // around pinning. unsafe { Pin::new_unchecked(pointer) } } - /// Unwraps this `Pin

` returning the underlying pointer. + /// Unwraps this `Pin`, returning the underlying pointer. /// - /// This requires that the data inside this `Pin` implements [`Unpin`] so that we - /// can ignore the pinning invariants when unwrapping it. + /// Doing this operation safely requires that the data pointed at by this pinning pointer + /// implemts [`Unpin`] so that we can ignore the pinning invariants when unwrapping it. /// /// # Examples /// @@ -517,46 +1201,54 @@ impl> Pin

{ /// /// let mut val: u8 = 5; /// let pinned: Pin<&mut u8> = Pin::new(&mut val); - /// // Unwrap the pin to get a reference to the value + /// + /// // Unwrap the pin to get the underlying mutable reference to the value. We can do + /// // this because `val` doesn't care about being moved, so the `Pin` was just + /// // a "facade" anyway. /// let r = Pin::into_inner(pinned); /// assert_eq!(*r, 5); /// ``` #[inline(always)] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] #[stable(feature = "pin_into_inner", since = "1.39.0")] - pub const fn into_inner(pin: Pin

) -> P { + pub const fn into_inner(pin: Pin) -> Ptr { pin.pointer } } -impl Pin

{ - /// Construct a new `Pin

` around a reference to some data of a type that - /// may or may not implement `Unpin`. +impl Pin { + /// Construct a new `Pin` around a reference to some data of a type that + /// may or may not implement [`Unpin`]. /// - /// If `pointer` dereferences to an `Unpin` type, `Pin::new` should be used + /// If `pointer` dereferences to an [`Unpin`] type, [`Pin::new`] should be used /// instead. /// /// # Safety /// /// This constructor is unsafe because we cannot guarantee that the data - /// pointed to by `pointer` is pinned, meaning that the data will not be moved or - /// its storage invalidated until it gets dropped. If the constructed `Pin

` does - /// not guarantee that the data `P` points to is pinned, that is a violation of - /// the API contract and may lead to undefined behavior in later (safe) operations. + /// pointed to by `pointer` is pinned. At its core, pinning a value means making the + /// guarantee that the value's data will not be moved nor have its storage invalidated until + /// it gets dropped. For a more thorough explanation of pinning, see the [`pin` module docs]. + /// + /// If the caller that is constructing this `Pin` does not ensure that the data `Ptr` + /// points to is pinned, that is a violation of the API contract and may lead to undefined + /// behavior in later (even safe) operations. /// - /// By using this method, you are making a promise about the `P::Deref` and - /// `P::DerefMut` implementations, if they exist. Most importantly, they + /// By using this method, you are also making a promise about the [`Deref`] and + /// [`DerefMut`] implementations of `Ptr`, if they exist. Most importantly, they /// must not move out of their `self` arguments: `Pin::as_mut` and `Pin::as_ref` - /// will call `DerefMut::deref_mut` and `Deref::deref` *on the pinned pointer* + /// will call `DerefMut::deref_mut` and `Deref::deref` *on the pointer type `Ptr`* /// and expect these methods to uphold the pinning invariants. - /// Moreover, by calling this method you promise that the reference `P` + /// Moreover, by calling this method you promise that the reference `Ptr` /// dereferences to will not be moved out of again; in particular, it - /// must not be possible to obtain a `&mut P::Target` and then + /// must not be possible to obtain a `&mut Ptr::Target` and then /// move out of that reference (using, for example [`mem::swap`]). /// /// For example, calling `Pin::new_unchecked` on an `&'a mut T` is unsafe because /// while you are able to pin it for the given lifetime `'a`, you have no control - /// over whether it is kept pinned once `'a` ends: + /// over whether it is kept pinned once `'a` ends, and therefore cannot uphold the + /// guarantee that a value, once pinned, remains pinned until it is dropped: + /// /// ``` /// use std::mem; /// use std::pin::Pin; @@ -583,12 +1275,14 @@ impl Pin

{ /// use std::pin::Pin; /// /// fn move_pinned_rc(mut x: Rc) { - /// let pinned = unsafe { Pin::new_unchecked(Rc::clone(&x)) }; + /// // This should mean the pointee can never move again. + /// let pin = unsafe { Pin::new_unchecked(Rc::clone(&x)) }; /// { - /// let p: Pin<&T> = pinned.as_ref(); - /// // This should mean the pointee can never move again. + /// let p: Pin<&T> = pin.as_ref(); + /// // ... /// } - /// drop(pinned); + /// drop(pin); + /// /// let content = Rc::get_mut(&mut x).unwrap(); // Potential UB down the road ⚠️ /// // Now, if `x` was the only reference, we have a mutable reference to /// // data that we pinned above, which we could use to move it as we have @@ -649,15 +1343,16 @@ impl Pin

{ /// ``` /// /// [`mem::swap`]: crate::mem::swap + /// [`pin` module docs]: self #[lang = "new_unchecked"] #[inline(always)] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] #[stable(feature = "pin", since = "1.33.0")] - pub const unsafe fn new_unchecked(pointer: P) -> Pin

{ + pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin { Pin { pointer } } - /// Gets a pinned shared reference from this pinned pointer. + /// Gets a shared reference to the pinned value this [`Pin`] points to. /// /// This is a generic method to go from `&Pin>` to `Pin<&T>`. /// It is safe because, as part of the contract of `Pin::new_unchecked`, @@ -666,34 +1361,39 @@ impl Pin

{ /// ruled out by the contract of `Pin::new_unchecked`. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub fn as_ref(&self) -> Pin<&P::Target> { + pub fn as_ref(&self) -> Pin<&Ptr::Target> { // SAFETY: see documentation on this function unsafe { Pin::new_unchecked(&*self.pointer) } } - /// Unwraps this `Pin

` returning the underlying pointer. + /// Unwraps this `Pin`, returning the underlying `Ptr`. /// /// # Safety /// /// This function is unsafe. You must guarantee that you will continue to - /// treat the pointer `P` as pinned after you call this function, so that + /// treat the pointer `Ptr` as pinned after you call this function, so that /// the invariants on the `Pin` type can be upheld. If the code using the - /// resulting `P` does not continue to maintain the pinning invariants that + /// resulting `Ptr` does not continue to maintain the pinning invariants that /// is a violation of the API contract and may lead to undefined behavior in /// later (safe) operations. /// + /// Note that you must be able to guarantee that the data pointed to by `Ptr` + /// will be treated as pinned all the way until its `drop` handler is complete! + /// + /// *For more information, see the [`pin` module docs][self]* + /// /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used /// instead. #[inline(always)] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] #[stable(feature = "pin_into_inner", since = "1.39.0")] - pub const unsafe fn into_inner_unchecked(pin: Pin

) -> P { + pub const unsafe fn into_inner_unchecked(pin: Pin) -> Ptr { pin.pointer } } -impl Pin

{ - /// Gets a pinned mutable reference from this pinned pointer. +impl Pin { + /// Gets a mutable reference to the pinned value this `Pin` points to. /// /// This is a generic method to go from `&mut Pin>` to `Pin<&mut T>`. /// It is safe because, as part of the contract of `Pin::new_unchecked`, @@ -701,7 +1401,8 @@ impl Pin

{ /// "Malicious" implementations of `Pointer::DerefMut` are likewise /// ruled out by the contract of `Pin::new_unchecked`. /// - /// This method is useful when doing multiple calls to functions that consume the pinned type. + /// This method is useful when doing multiple calls to functions that consume the + /// pinning pointer. /// /// # Example /// @@ -723,15 +1424,17 @@ impl Pin

{ /// ``` #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub fn as_mut(&mut self) -> Pin<&mut P::Target> { + pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> { // SAFETY: see documentation on this function unsafe { Pin::new_unchecked(&mut *self.pointer) } } - /// Assigns a new value to the memory behind the pinned reference. + /// Assigns a new value to the memory location pointed to by the `Pin`. /// - /// This overwrites pinned data, but that is okay: its destructor gets - /// run before being overwritten, so no pinning guarantee is violated. + /// This overwrites pinned data, but that is okay: the original pinned value's destructor gets + /// run before being overwritten and the new value is also a valid value of the same type, so + /// no pinning invariant is violated. See [the `pin` module documentation][subtle-details] + /// for more information on how this upholds the pinning invariants. /// /// # Example /// @@ -741,14 +1444,16 @@ impl Pin

{ /// let mut val: u8 = 5; /// let mut pinned: Pin<&mut u8> = Pin::new(&mut val); /// println!("{}", pinned); // 5 - /// pinned.as_mut().set(10); + /// pinned.set(10); /// println!("{}", pinned); // 10 /// ``` + /// + /// [subtle-details]: self#subtle-details-and-the-drop-guarantee #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub fn set(&mut self, value: P::Target) + pub fn set(&mut self, value: Ptr::Target) where - P::Target: Sized, + Ptr::Target: Sized, { *(self.pointer) = value; } @@ -790,15 +1495,15 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// It may seem like there is an issue here with interior mutability: in fact, /// it *is* possible to move a `T` out of a `&RefCell`. However, this is /// not a problem as long as there does not also exist a `Pin<&T>` pointing - /// to the same data, and `RefCell` does not let you create a pinned reference - /// to its contents. See the discussion on ["pinning projections"] for further - /// details. + /// to the inner `T` inside the `RefCell`, and `RefCell` does not let you get a + /// `Pin<&T>` pointer to its contents. See the discussion on ["pinning projections"] + /// for further details. /// /// Note: `Pin` also implements `Deref` to the target, which can be used /// to access the inner value. However, `Deref` only provides a reference /// that lives for as long as the borrow of the `Pin`, not the lifetime of - /// the `Pin` itself. This method allows turning the `Pin` into a reference - /// with the same lifetime as the original `Pin`. + /// the reference contained in the `Pin`. This method allows turning the `Pin` into a reference + /// with the same lifetime as the reference it wraps. /// /// ["pinning projections"]: self#projections-and-structural-pinning #[inline(always)] @@ -891,9 +1596,9 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { } impl Pin<&'static T> { - /// Get a pinned reference from a static reference. + /// Get a pinning reference from a `&'static` reference. /// - /// This is safe, because `T` is borrowed for the `'static` lifetime, which + /// This is safe because `T` is borrowed immutably for the `'static` lifetime, which /// never ends. #[stable(feature = "pin_static_ref", since = "1.61.0")] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] @@ -904,49 +1609,50 @@ impl Pin<&'static T> { } } -impl<'a, P: DerefMut> Pin<&'a mut Pin

> { - /// Gets a pinned mutable reference from this nested pinned pointer. +impl<'a, Ptr: DerefMut> Pin<&'a mut Pin> { + /// Gets `Pin<&mut T>` to the underlying pinned value from this nested `Pin`-pointer. /// /// This is a generic method to go from `Pin<&mut Pin>>` to `Pin<&mut T>`. It is /// safe because the existence of a `Pin>` ensures that the pointee, `T`, cannot /// move in the future, and this method does not enable the pointee to move. "Malicious" - /// implementations of `P::DerefMut` are likewise ruled out by the contract of + /// implementations of `Ptr::DerefMut` are likewise ruled out by the contract of /// `Pin::new_unchecked`. #[unstable(feature = "pin_deref_mut", issue = "86918")] #[must_use = "`self` will be dropped if the result is not used"] #[inline(always)] - pub fn as_deref_mut(self) -> Pin<&'a mut P::Target> { + pub fn as_deref_mut(self) -> Pin<&'a mut Ptr::Target> { // SAFETY: What we're asserting here is that going from // - // Pin<&mut Pin

> + // Pin<&mut Pin> // // to // - // Pin<&mut P::Target> + // Pin<&mut Ptr::Target> // // is safe. // // We need to ensure that two things hold for that to be the case: // - // 1) Once we give out a `Pin<&mut P::Target>`, an `&mut P::Target` will not be given out. - // 2) By giving out a `Pin<&mut P::Target>`, we do not risk of violating `Pin<&mut Pin

>` + // 1) Once we give out a `Pin<&mut Ptr::Target>`, an `&mut Ptr::Target` will not be given out. + // 2) By giving out a `Pin<&mut Ptr::Target>`, we do not risk of violating + // `Pin<&mut Pin>` // - // The existence of `Pin

` is sufficient to guarantee #1: since we already have a - // `Pin

`, it must already uphold the pinning guarantees, which must mean that - // `Pin<&mut P::Target>` does as well, since `Pin::as_mut` is safe. We do not have to rely - // on the fact that P is _also_ pinned. + // The existence of `Pin` is sufficient to guarantee #1: since we already have a + // `Pin`, it must already uphold the pinning guarantees, which must mean that + // `Pin<&mut Ptr::Target>` does as well, since `Pin::as_mut` is safe. We do not have to rely + // on the fact that `Ptr` is _also_ pinned. // - // For #2, we need to ensure that code given a `Pin<&mut P::Target>` cannot cause the - // `Pin

` to move? That is not possible, since `Pin<&mut P::Target>` no longer retains - // any access to the `P` itself, much less the `Pin

`. + // For #2, we need to ensure that code given a `Pin<&mut Ptr::Target>` cannot cause the + // `Pin` to move? That is not possible, since `Pin<&mut Ptr::Target>` no longer retains + // any access to the `Ptr` itself, much less the `Pin`. unsafe { self.get_unchecked_mut() }.as_mut() } } impl Pin<&'static mut T> { - /// Get a pinned mutable reference from a static mutable reference. + /// Get a pinning mutable reference from a static mutable reference. /// - /// This is safe, because `T` is borrowed for the `'static` lifetime, which + /// This is safe because `T` is borrowed for the `'static` lifetime, which /// never ends. #[stable(feature = "pin_static_ref", since = "1.61.0")] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] @@ -958,39 +1664,39 @@ impl Pin<&'static mut T> { } #[stable(feature = "pin", since = "1.33.0")] -impl Deref for Pin

{ - type Target = P::Target; - fn deref(&self) -> &P::Target { +impl Deref for Pin { + type Target = Ptr::Target; + fn deref(&self) -> &Ptr::Target { Pin::get_ref(Pin::as_ref(self)) } } #[stable(feature = "pin", since = "1.33.0")] -impl> DerefMut for Pin

{ - fn deref_mut(&mut self) -> &mut P::Target { +impl> DerefMut for Pin { + fn deref_mut(&mut self) -> &mut Ptr::Target { Pin::get_mut(Pin::as_mut(self)) } } #[unstable(feature = "receiver_trait", issue = "none")] -impl Receiver for Pin

{} +impl Receiver for Pin {} #[stable(feature = "pin", since = "1.33.0")] -impl fmt::Debug for Pin

{ +impl fmt::Debug for Pin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.pointer, f) } } #[stable(feature = "pin", since = "1.33.0")] -impl fmt::Display for Pin

{ +impl fmt::Display for Pin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.pointer, f) } } #[stable(feature = "pin", since = "1.33.0")] -impl fmt::Pointer for Pin

{ +impl fmt::Pointer for Pin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Pointer::fmt(&self.pointer, f) } @@ -1002,10 +1708,10 @@ impl fmt::Pointer for Pin

{ // for other reasons, though, so we just need to take care not to allow such // impls to land in std. #[stable(feature = "pin", since = "1.33.0")] -impl CoerceUnsized> for Pin

where P: CoerceUnsized {} +impl CoerceUnsized> for Pin where Ptr: CoerceUnsized {} #[stable(feature = "pin", since = "1.33.0")] -impl DispatchFromDyn> for Pin

where P: DispatchFromDyn {} +impl DispatchFromDyn> for Pin where Ptr: DispatchFromDyn {} /// Constructs a [Pin]<[&mut] T>, by pinning a `value: T` locally. /// diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 62370206956c6..6cd22a9151897 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -30,18 +30,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] name = "annotate-snippets" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3b9d411ecbaf79885c6df4d75fff75858d5995ff25385657a28af47e82f9c36" +checksum = "ccaf7e9dfbb6ab22c82e473cd1a8a7bd313c19a5b7e40970f3d89ef5a5c9e81e" dependencies = [ "unicode-width", "yansi-term", @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "autocfg" @@ -91,15 +91,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "bstr" -version = "1.6.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" +checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" dependencies = [ "memchr", "regex-automata", @@ -117,9 +117,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" +checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" dependencies = [ "serde", ] @@ -180,9 +180,9 @@ dependencies = [ [[package]] name = "color-spantrace" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" dependencies = [ "once_cell", "owo-colors", @@ -192,11 +192,10 @@ dependencies = [ [[package]] name = "colored" -version = "2.0.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" dependencies = [ - "is-terminal", "lazy_static", "windows-sys 0.48.0", ] @@ -222,18 +221,18 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2" dependencies = [ "cfg-if", "crossbeam-utils", @@ -241,9 +240,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" dependencies = [ "cfg-if", ] @@ -260,12 +259,12 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" +checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" dependencies = [ "nix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -276,9 +275,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "env_logger" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" dependencies = [ "humantime", "is-terminal", @@ -289,30 +288,19 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.4" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] name = "eyre" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799" dependencies = [ "indenter", "once_cell", @@ -336,9 +324,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "libc", @@ -347,9 +335,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "hermit-abi" @@ -402,20 +390,30 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ "hermit-abi", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "jemalloc-sys" +version = "0.5.4+5.3.0-patched" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2" +dependencies = [ + "cc", + "libc", +] [[package]] name = "lazy_static" @@ -431,9 +429,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.148" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libffi" @@ -466,15 +464,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.8" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -488,9 +486,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "measureme" -version = "10.1.1" +version = "10.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1930d162935fecd56fc4e0f6729eb3483bac1264542eb4ea31570b86a434b6bc" +checksum = "45e381dcdad44c3c435f8052b08c5c4a1449c48ab56f312345eae12d7a693dbe" dependencies = [ "log", "memmap2", @@ -502,9 +500,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" @@ -533,6 +531,7 @@ dependencies = [ "ctrlc", "env_logger", "getrandom", + "jemalloc-sys", "lazy_static", "libc", "libffi", @@ -542,7 +541,6 @@ dependencies = [ "rand", "regex", "rustc_version", - "serde", "smallvec", "ui_test", ] @@ -553,7 +551,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "cfg-if", "libc", ] @@ -566,18 +564,18 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "owo-colors" @@ -596,27 +594,25 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.11.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ - "instant", "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" -version = "0.8.6" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", - "instant", "libc", - "redox_syscall 0.2.16", + "redox_syscall", "smallvec", - "winapi", + "windows-targets 0.48.5", ] [[package]] @@ -636,9 +632,9 @@ checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "portable-atomic" -version = "1.4.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" [[package]] name = "ppv-lite86" @@ -658,18 +654,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -706,27 +702,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.9.6" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", @@ -736,9 +723,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -747,9 +734,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rustc-demangle" @@ -786,22 +773,22 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.19" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "scopeguard" @@ -811,27 +798,27 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.19" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.188" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", @@ -840,9 +827,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "itoa", "ryu", @@ -860,15 +847,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "syn" -version = "2.0.37" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -877,40 +864,40 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", + "redox_syscall", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", @@ -929,20 +916,19 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -960,9 +946,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "sharded-slab", "thread_local", @@ -1081,6 +1067,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -1111,6 +1106,21 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -1123,6 +1133,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -1135,6 +1151,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -1147,6 +1169,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -1159,6 +1187,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -1171,6 +1205,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -1183,6 +1223,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -1195,6 +1241,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "yansi-term" version = "0.1.2" diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index f8e507a11b022..df987bd3ac60f 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -24,10 +24,15 @@ log = "0.4" rand = "0.8" smallvec = "1.7" aes = { version = "0.8.3", features = ["hazmat"] } - measureme = "10.0.0" ctrlc = "3.2.5" +# Copied from `compiler/rustc/Cargo.toml`. +# But only for Unix, it fails on Windows. +[target.'cfg(unix)'.dependencies.jemalloc-sys] +version = "0.5.0" +features = ['unprefixed_malloc_on_supported_platforms'] + [target.'cfg(unix)'.dependencies] libc = "0.2" @@ -39,11 +44,8 @@ libloading = "0.8" colored = "2" ui_test = "0.21.1" rustc_version = "0.4" -# Features chosen to match those required by env_logger, to avoid rebuilds -regex = { version = "1.5.5", default-features = false, features = ["perf", "std"] } +regex = "1.5.5" lazy_static = "1.4.0" -# Require a version of serde without intransparent unreproducible binary blobs. -serde = { version = "1.0.185", features = ["derive"] } [package.metadata.rust-analyzer] # This crate uses #[feature(rustc_private)]. diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock index 8f442b3de13a1..6e3a8dbaa1d4b 100644 --- a/src/tools/miri/cargo-miri/Cargo.lock +++ b/src/tools/miri/cargo-miri/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "bitflags" @@ -16,9 +16,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "camino" @@ -44,18 +44,18 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" +checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" dependencies = [ "serde", ] [[package]] name = "cargo_metadata" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb9ac64500cc83ce4b9f8dafa78186aa008c8dea77a09b94cd307fd0cd5022a8" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", "cargo-platform", @@ -65,15 +65,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -98,28 +89,17 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "errno" -version = "0.3.4" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] @@ -130,9 +110,9 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "libc", @@ -141,21 +121,32 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "libc" -version = "0.2.148" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] [[package]] name = "linux-raw-sys" -version = "0.4.8" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "option-ext" @@ -165,48 +156,39 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] @@ -238,46 +220,46 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.19" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "semver" -version = "1.0.19" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.188" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", @@ -286,9 +268,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "itoa", "ryu", @@ -297,9 +279,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.37" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -308,31 +290,31 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", + "redox_syscall", "rustix", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", @@ -357,7 +339,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -366,13 +357,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -381,38 +387,80 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/src/tools/miri/miri-script/Cargo.lock b/src/tools/miri/miri-script/Cargo.lock index ea306ed838a1c..04615f3d8c165 100644 --- a/src/tools/miri/miri-script/Cargo.lock +++ b/src/tools/miri/miri-script/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "bitflags" @@ -16,18 +16,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" - -[[package]] -name = "cc" -version = "1.0.83" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "cfg-if" @@ -53,7 +44,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -70,30 +61,19 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "errno" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "libc", @@ -102,11 +82,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -120,15 +100,26 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.148" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] [[package]] name = "linux-raw-sys" -version = "0.4.8" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "miri-script" @@ -148,9 +139,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "option-ext" @@ -166,39 +157,39 @@ checksum = "a6e819bbd49d5939f682638fa54826bf1650abddcd65d000923de8ad63cc7d15" [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ "getrandom", - "redox_syscall", + "libredox", "thiserror", ] @@ -213,15 +204,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.19" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -235,9 +226,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.19" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "shell-words" @@ -247,9 +238,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "syn" -version = "2.0.37" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -258,18 +249,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", @@ -347,7 +338,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -356,13 +356,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -371,42 +386,84 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "xshell" version = "0.2.5" diff --git a/src/tools/miri/miri-script/src/util.rs b/src/tools/miri/miri-script/src/util.rs index c9bc55848dfb5..420ecdab63c9b 100644 --- a/src/tools/miri/miri-script/src/util.rs +++ b/src/tools/miri/miri-script/src/util.rs @@ -111,9 +111,11 @@ impl MiriEnv { ) -> Result<()> { let MiriEnv { toolchain, cargo_extra_flags, .. } = self; let quiet_flag = if quiet { Some("--quiet") } else { None }; + // We build the tests as well, (a) to avoid having rebuilds when building the tests later + // and (b) to have more parallelism during the build of Miri and its tests. let mut cmd = cmd!( self.sh, - "cargo +{toolchain} build {cargo_extra_flags...} --manifest-path {manifest_path} {quiet_flag...} {args...}" + "cargo +{toolchain} build --bins --tests {cargo_extra_flags...} --manifest-path {manifest_path} {quiet_flag...} {args...}" ); cmd.set_quiet(quiet); cmd.run()?; diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 5298ff36f2141..548e12ffdeafb 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -2271c26e4a8e062bb00d709d0ccb5846e0c341b9 +5bcd86d89b2b7b6a490f7e075dd4eb346deb5f98 diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index ad6a5a669f006..d07753d34dff8 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -293,13 +293,51 @@ fn run_compiler( } /// Parses a comma separated list of `T` from the given string: -/// /// `,,,...` fn parse_comma_list(input: &str) -> Result, T::Err> { input.split(',').map(str::parse::).collect() } +#[cfg(unix)] +fn jemalloc_magic() { + // These magic runes are copied from + // . + // See there for further comments. + use std::os::raw::{c_int, c_void}; + + #[used] + static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc; + #[used] + static _F2: unsafe extern "C" fn(*mut *mut c_void, usize, usize) -> c_int = + jemalloc_sys::posix_memalign; + #[used] + static _F3: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::aligned_alloc; + #[used] + static _F4: unsafe extern "C" fn(usize) -> *mut c_void = jemalloc_sys::malloc; + #[used] + static _F5: unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void = jemalloc_sys::realloc; + #[used] + static _F6: unsafe extern "C" fn(*mut c_void) = jemalloc_sys::free; + + // On OSX, jemalloc doesn't directly override malloc/free, but instead + // registers itself with the allocator's zone APIs in a ctor. However, + // the linker doesn't seem to consider ctors as "used" when statically + // linking, so we need to explicitly depend on the function. + #[cfg(target_os = "macos")] + { + extern "C" { + fn _rjem_je_zone_register(); + } + + #[used] + static _F7: unsafe extern "C" fn() = _rjem_je_zone_register; + } +} + fn main() { + #[cfg(unix)] + jemalloc_magic(); + let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); // Snapshot a copy of the environment before `rustc` starts messing with it. diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index 778a544544b54..4b47cc0cb824d 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -612,7 +612,7 @@ impl<'tcx> Tree { is_foreign: rel_pos.is_foreign(), access_cause, access_range, - transition_range: perms_range.clone(), + transition_range: perms_range, span, }); } diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index cc81ef6e6c916..a1db7bf74f281 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -145,17 +145,30 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "fabsf32" => { let [f] = check_arg_count(args)?; let f = this.read_scalar(f)?.to_f32()?; - // Can be implemented in soft-floats. // This is a "bitwise" operation, so there's no NaN non-determinism. this.write_scalar(Scalar::from_f32(f.abs()), dest)?; } "fabsf64" => { let [f] = check_arg_count(args)?; let f = this.read_scalar(f)?.to_f64()?; - // Can be implemented in soft-floats. // This is a "bitwise" operation, so there's no NaN non-determinism. this.write_scalar(Scalar::from_f64(f.abs()), dest)?; } + "floorf32" | "ceilf32" | "truncf32" | "roundf32" | "rintf32" => { + let [f] = check_arg_count(args)?; + let f = this.read_scalar(f)?.to_f32()?; + let mode = match intrinsic_name { + "floorf32" => Round::TowardNegative, + "ceilf32" => Round::TowardPositive, + "truncf32" => Round::TowardZero, + "roundf32" => Round::NearestTiesToAway, + "rintf32" => Round::NearestTiesToEven, + _ => bug!(), + }; + let res = f.round_to_integral(mode).value; + let res = this.adjust_nan(res, &[f]); + this.write_scalar(res, dest)?; + } #[rustfmt::skip] | "sinf32" | "cosf32" @@ -165,11 +178,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { | "logf32" | "log10f32" | "log2f32" - | "floorf32" - | "ceilf32" - | "truncf32" - | "roundf32" - | "rintf32" => { let [f] = check_arg_count(args)?; let f = this.read_scalar(f)?.to_f32()?; @@ -184,11 +192,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "logf32" => f_host.ln(), "log10f32" => f_host.log10(), "log2f32" => f_host.log2(), - "floorf32" => f_host.floor(), - "ceilf32" => f_host.ceil(), - "truncf32" => f_host.trunc(), - "roundf32" => f_host.round(), - "rintf32" => f_host.round_ties_even(), _ => bug!(), }; let res = res.to_soft(); @@ -196,6 +199,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(res, dest)?; } + "floorf64" | "ceilf64" | "truncf64" | "roundf64" | "rintf64" => { + let [f] = check_arg_count(args)?; + let f = this.read_scalar(f)?.to_f64()?; + let mode = match intrinsic_name { + "floorf64" => Round::TowardNegative, + "ceilf64" => Round::TowardPositive, + "truncf64" => Round::TowardZero, + "roundf64" => Round::NearestTiesToAway, + "rintf64" => Round::NearestTiesToEven, + _ => bug!(), + }; + let res = f.round_to_integral(mode).value; + let res = this.adjust_nan(res, &[f]); + this.write_scalar(res, dest)?; + } #[rustfmt::skip] | "sinf64" | "cosf64" @@ -205,11 +223,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { | "logf64" | "log10f64" | "log2f64" - | "floorf64" - | "ceilf64" - | "truncf64" - | "roundf64" - | "rintf64" => { let [f] = check_arg_count(args)?; let f = this.read_scalar(f)?.to_f64()?; @@ -224,11 +237,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "logf64" => f_host.ln(), "log10f64" => f_host.log10(), "log2f64" => f_host.log2(), - "floorf64" => f_host.floor(), - "ceilf64" => f_host.ceil(), - "truncf64" => f_host.trunc(), - "roundf64" => f_host.round(), - "rintf64" => f_host.round_ties_even(), _ => bug!(), }; let res = res.to_soft(); diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index aa3b25e338a7f..9d9db7b049857 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "js-sys", @@ -119,9 +119,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "hermit-abi" @@ -131,18 +131,18 @@ checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" dependencies = [ "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.148" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "linux-raw-sys" @@ -152,9 +152,9 @@ checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -168,9 +168,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "miniz_oxide" @@ -183,9 +183,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -197,7 +197,7 @@ name = "miri-test-deps" version = "0.1.0" dependencies = [ "getrandom 0.1.16", - "getrandom 0.2.10", + "getrandom 0.2.11", "libc", "num_cpus", "page_size", @@ -219,18 +219,18 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "page_size" @@ -254,13 +254,13 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", "windows-targets 0.48.5", ] @@ -279,18 +279,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -322,16 +322,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", + "getrandom 0.2.11", ] [[package]] @@ -351,15 +342,15 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -379,15 +370,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys 0.48.0", @@ -395,9 +386,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.37" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -406,22 +397,22 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", + "redox_syscall", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio" -version = "1.32.0" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ "backtrace", "bytes", @@ -438,9 +429,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", @@ -467,9 +458,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -477,9 +468,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" dependencies = [ "bumpalo", "log", @@ -492,9 +483,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -502,9 +493,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", @@ -515,9 +506,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "winapi" diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs index 401927f5f6c9f..4468eb299f3d7 100644 --- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs +++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs @@ -3,7 +3,12 @@ // Some targets treat arrays and structs very differently. We would probably catch that on those // targets since we check the `PassMode`; here we ensure that we catch it on *all* targets // (in particular, on x86-64 the pass mode is `Indirect` for both of these). -struct S(#[allow(dead_code)] i32, #[allow(dead_code)] i32, #[allow(dead_code)] i32, #[allow(dead_code)] i32); +struct S( + #[allow(dead_code)] i32, + #[allow(dead_code)] i32, + #[allow(dead_code)] i32, + #[allow(dead_code)] i32, +); type A = [i32; 4]; fn main() { diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index 70c64485fe937..5f2d4489f4ac1 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -1,8 +1,18 @@ #![feature(stmt_expr_attributes)] #![feature(round_ties_even)] +#![feature(float_gamma)] #![allow(arithmetic_overflow)] + use std::fmt::Debug; use std::hint::black_box; +use std::{f32, f64}; + +macro_rules! assert_approx_eq { + ($a:expr, $b:expr) => {{ + let (a, b) = (&$a, &$b); + assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); + }}; +} fn main() { basic(); @@ -11,6 +21,8 @@ fn main() { ops(); nan_casts(); rounding(); + mul_add(); + libm(); } // Helper function to avoid promotion so that this tests "run-time" casts, not CTFE. @@ -148,8 +160,6 @@ fn basic() { assert_ne!({ 5.0_f32 / 0.0 }, { -5.0_f32 / 0.0 }); assert!((5.0_f64 / 0.0).is_infinite()); assert_ne!({ 5.0_f64 / 0.0 }, { 5.0_f64 / -0.0 }); - assert!((-5.0_f32).sqrt().is_nan()); - assert!((-5.0_f64).sqrt().is_nan()); assert_ne!(f32::NAN, f32::NAN); assert_ne!(f64::NAN, f64::NAN); // negative zero @@ -178,6 +188,9 @@ fn basic() { assert!((black_box(1.0f64) % -1.0).is_sign_positive()); assert!((black_box(-1.0f64) % 1.0).is_sign_negative()); assert!((black_box(-1.0f64) % -1.0).is_sign_negative()); + + assert_eq!((-1.0f32).abs(), 1.0f32); + assert_eq!(34.2f64.abs(), 34.2f64); } /// Many of these test values are taken from @@ -592,4 +605,150 @@ fn rounding() { assert_eq((-1.3f64).round_ties_even(), -1.0f64); assert_eq((-1.5f64).round_ties_even(), -2.0f64); assert_eq((-1.7f64).round_ties_even(), -2.0f64); + + assert_eq!(3.8f32.floor(), 3.0f32); + assert_eq!((-1.1f64).floor(), -2.0f64); + + assert_eq!((-2.3f32).ceil(), -2.0f32); + assert_eq!(3.8f64.ceil(), 4.0f64); + + assert_eq!(0.1f32.trunc(), 0.0f32); + assert_eq!((-0.1f64).trunc(), 0.0f64); + + assert_eq!(3.3_f32.round(), 3.0); + assert_eq!(2.5_f32.round(), 3.0); + assert_eq!(3.9_f64.round(), 4.0); + assert_eq!(2.5_f64.round(), 3.0); +} + +fn mul_add() { + assert_eq!(3.0f32.mul_add(2.0f32, 5.0f32), 11.0); + assert_eq!(0.0f32.mul_add(-2.0, f32::consts::E), f32::consts::E); + assert_eq!(3.0f64.mul_add(2.0, 5.0), 11.0); + assert_eq!(0.0f64.mul_add(-2.0f64, f64::consts::E), f64::consts::E); + assert_eq!((-3.2f32).mul_add(2.4, f32::NEG_INFINITY), f32::NEG_INFINITY); + assert_eq!((-3.2f64).mul_add(2.4, f64::NEG_INFINITY), f64::NEG_INFINITY); + + let f = f32::mul_add( + -0.000000000000000000000000000000000000014728589, + 0.0000037105144, + 0.000000000000000000000000000000000000000000055, + ); + assert_eq!(f.to_bits(), f32::to_bits(-0.0)); +} + +pub fn libm() { + fn ldexp(a: f64, b: i32) -> f64 { + extern "C" { + fn ldexp(x: f64, n: i32) -> f64; + } + unsafe { ldexp(a, b) } + } + + assert_approx_eq!(64f32.sqrt(), 8f32); + assert_approx_eq!(64f64.sqrt(), 8f64); + assert!((-5.0_f32).sqrt().is_nan()); + assert!((-5.0_f64).sqrt().is_nan()); + + assert_approx_eq!(25f32.powi(-2), 0.0016f32); + assert_approx_eq!(23.2f64.powi(2), 538.24f64); + + assert_approx_eq!(25f32.powf(-2f32), 0.0016f32); + assert_approx_eq!(400f64.powf(0.5f64), 20f64); + + assert_approx_eq!(1f32.exp(), f32::consts::E); + assert_approx_eq!(1f64.exp(), f64::consts::E); + + assert_approx_eq!(1f32.exp_m1(), f32::consts::E - 1.0); + assert_approx_eq!(1f64.exp_m1(), f64::consts::E - 1.0); + + assert_approx_eq!(10f32.exp2(), 1024f32); + assert_approx_eq!(50f64.exp2(), 1125899906842624f64); + + assert_approx_eq!(f32::consts::E.ln(), 1f32); + assert_approx_eq!(1f64.ln(), 0f64); + + assert_approx_eq!(0f32.ln_1p(), 0f32); + assert_approx_eq!(0f64.ln_1p(), 0f64); + + assert_approx_eq!(10f32.log10(), 1f32); + assert_approx_eq!(f64::consts::E.log10(), f64::consts::LOG10_E); + + assert_approx_eq!(8f32.log2(), 3f32); + assert_approx_eq!(f64::consts::E.log2(), f64::consts::LOG2_E); + + #[allow(deprecated)] + { + assert_approx_eq!(5.0f32.abs_sub(3.0), 2.0); + assert_approx_eq!(3.0f64.abs_sub(5.0), 0.0); + } + + assert_approx_eq!(27.0f32.cbrt(), 3.0f32); + assert_approx_eq!(27.0f64.cbrt(), 3.0f64); + + assert_approx_eq!(3.0f32.hypot(4.0f32), 5.0f32); + assert_approx_eq!(3.0f64.hypot(4.0f64), 5.0f64); + + assert_eq!(ldexp(0.65f64, 3i32), 5.2f64); + assert_eq!(ldexp(1.42, 0xFFFF), f64::INFINITY); + assert_eq!(ldexp(1.42, -0xFFFF), 0f64); + + // Trigonometric functions. + + assert_approx_eq!(0f32.sin(), 0f32); + assert_approx_eq!((f64::consts::PI / 2f64).sin(), 1f64); + assert_approx_eq!(f32::consts::FRAC_PI_6.sin(), 0.5); + assert_approx_eq!(f64::consts::FRAC_PI_6.sin(), 0.5); + assert_approx_eq!(f32::consts::FRAC_PI_4.sin().asin(), f32::consts::FRAC_PI_4); + assert_approx_eq!(f64::consts::FRAC_PI_4.sin().asin(), f64::consts::FRAC_PI_4); + + assert_approx_eq!(1.0f32.sinh(), 1.1752012f32); + assert_approx_eq!(1.0f64.sinh(), 1.1752012f64); + assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32); + assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64); + + assert_approx_eq!(0f32.cos(), 1f32); + assert_approx_eq!((f64::consts::PI * 2f64).cos(), 1f64); + assert_approx_eq!(f32::consts::FRAC_PI_3.cos(), 0.5); + assert_approx_eq!(f64::consts::FRAC_PI_3.cos(), 0.5); + assert_approx_eq!(f32::consts::FRAC_PI_4.cos().acos(), f32::consts::FRAC_PI_4); + assert_approx_eq!(f64::consts::FRAC_PI_4.cos().acos(), f64::consts::FRAC_PI_4); + + assert_approx_eq!(1.0f32.cosh(), 1.54308f32); + assert_approx_eq!(1.0f64.cosh(), 1.54308f64); + assert_approx_eq!(2.0f32.acosh(), 1.31695789692481670862504634730796844f32); + assert_approx_eq!(3.0f64.acosh(), 1.76274717403908605046521864995958461f64); + + assert_approx_eq!(1.0f32.tan(), 1.557408f32); + assert_approx_eq!(1.0f64.tan(), 1.557408f64); + assert_approx_eq!(1.0_f32, 1.0_f32.tan().atan()); + assert_approx_eq!(1.0_f64, 1.0_f64.tan().atan()); + assert_approx_eq!(1.0f32.atan2(2.0f32), 0.46364761f32); + assert_approx_eq!(1.0f32.atan2(2.0f32), 0.46364761f32); + + assert_approx_eq!( + 1.0f32.tanh(), + (1.0 - f32::consts::E.powi(-2)) / (1.0 + f32::consts::E.powi(-2)) + ); + assert_approx_eq!( + 1.0f64.tanh(), + (1.0 - f64::consts::E.powi(-2)) / (1.0 + f64::consts::E.powi(-2)) + ); + assert_approx_eq!(0.5f32.atanh(), 0.54930614433405484569762261846126285f32); + assert_approx_eq!(0.5f64.atanh(), 0.54930614433405484569762261846126285f64); + + assert_approx_eq!(5.0f32.gamma(), 24.0); + assert_approx_eq!(5.0f64.gamma(), 24.0); + assert_approx_eq!((-0.5f32).gamma(), (-2.0) * f32::consts::PI.sqrt()); + assert_approx_eq!((-0.5f64).gamma(), (-2.0) * f64::consts::PI.sqrt()); + + assert_eq!(2.0f32.ln_gamma(), (0.0, 1)); + assert_eq!(2.0f64.ln_gamma(), (0.0, 1)); + // Gamma(-0.5) = -2*sqrt(π) + let (val, sign) = (-0.5f32).ln_gamma(); + assert_approx_eq!(val, (2.0 * f32::consts::PI.sqrt()).ln()); + assert_eq!(sign, -1); + let (val, sign) = (-0.5f64).ln_gamma(); + assert_approx_eq!(val, (2.0 * f64::consts::PI.sqrt()).ln()); + assert_eq!(sign, -1); } diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs index 207ce70fb20e3..4bfd12245ef1c 100644 --- a/src/tools/miri/tests/pass/float_nan.rs +++ b/src/tools/miri/tests/pass/float_nan.rs @@ -264,6 +264,10 @@ fn test_f32() { HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), || F32::from(f32::min(nan, nan)), ); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(nan.floor()), + ); check_all_outcomes( HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), || F32::from(nan.sin()), @@ -376,6 +380,10 @@ fn test_f64() { HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), || F64::from(f64::min(nan, nan)), ); + check_all_outcomes( + HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), + || F64::from(nan.floor()), + ); check_all_outcomes( HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), || F64::from(nan.sin()), diff --git a/src/tools/miri/tests/pass/intrinsics-math.rs b/src/tools/miri/tests/pass/intrinsics-math.rs deleted file mode 100644 index 589864f4f4ba7..0000000000000 --- a/src/tools/miri/tests/pass/intrinsics-math.rs +++ /dev/null @@ -1,156 +0,0 @@ -#![feature(float_gamma)] -use std::{f32, f64}; - -macro_rules! assert_approx_eq { - ($a:expr, $b:expr) => {{ - let (a, b) = (&$a, &$b); - assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); - }}; -} - -fn ldexp(a: f64, b: i32) -> f64 { - extern "C" { - fn ldexp(x: f64, n: i32) -> f64; - } - unsafe { ldexp(a, b) } -} - -pub fn main() { - mul_add(); - - assert_approx_eq!(64f32.sqrt(), 8f32); - assert_approx_eq!(64f64.sqrt(), 8f64); - - assert_approx_eq!(25f32.powi(-2), 0.0016f32); - assert_approx_eq!(23.2f64.powi(2), 538.24f64); - - assert_approx_eq!(25f32.powf(-2f32), 0.0016f32); - assert_approx_eq!(400f64.powf(0.5f64), 20f64); - - assert_approx_eq!(1f32.exp(), f32::consts::E); - assert_approx_eq!(1f64.exp(), f64::consts::E); - - assert_approx_eq!(1f32.exp_m1(), f32::consts::E - 1.0); - assert_approx_eq!(1f64.exp_m1(), f64::consts::E - 1.0); - - assert_approx_eq!(10f32.exp2(), 1024f32); - assert_approx_eq!(50f64.exp2(), 1125899906842624f64); - - assert_approx_eq!(f32::consts::E.ln(), 1f32); - assert_approx_eq!(1f64.ln(), 0f64); - - assert_approx_eq!(0f32.ln_1p(), 0f32); - assert_approx_eq!(0f64.ln_1p(), 0f64); - - assert_approx_eq!(10f32.log10(), 1f32); - assert_approx_eq!(f64::consts::E.log10(), f64::consts::LOG10_E); - - assert_approx_eq!(8f32.log2(), 3f32); - assert_approx_eq!(f64::consts::E.log2(), f64::consts::LOG2_E); - - assert_approx_eq!((-1.0f32).abs(), 1.0f32); - assert_approx_eq!(34.2f64.abs(), 34.2f64); - - #[allow(deprecated)] - { - assert_approx_eq!(5.0f32.abs_sub(3.0), 2.0); - assert_approx_eq!(3.0f64.abs_sub(5.0), 0.0); - } - - assert_approx_eq!(3.8f32.floor(), 3.0f32); - assert_approx_eq!((-1.1f64).floor(), -2.0f64); - - assert_approx_eq!((-2.3f32).ceil(), -2.0f32); - assert_approx_eq!(3.8f64.ceil(), 4.0f64); - - assert_approx_eq!(0.1f32.trunc(), 0.0f32); - assert_approx_eq!((-0.1f64).trunc(), 0.0f64); - - assert_approx_eq!(27.0f32.cbrt(), 3.0f32); - assert_approx_eq!(27.0f64.cbrt(), 3.0f64); - - assert_approx_eq!(3.0f32.hypot(4.0f32), 5.0f32); - assert_approx_eq!(3.0f64.hypot(4.0f64), 5.0f64); - - assert_eq!(3.3_f32.round(), 3.0); - assert_eq!(3.3_f64.round(), 3.0); - - assert_eq!(ldexp(0.65f64, 3i32), 5.2f64); - assert_eq!(ldexp(1.42, 0xFFFF), f64::INFINITY); - assert_eq!(ldexp(1.42, -0xFFFF), 0f64); - - // Trigonometric functions. - - assert_approx_eq!(0f32.sin(), 0f32); - assert_approx_eq!((f64::consts::PI / 2f64).sin(), 1f64); - assert_approx_eq!(f32::consts::FRAC_PI_6.sin(), 0.5); - assert_approx_eq!(f64::consts::FRAC_PI_6.sin(), 0.5); - assert_approx_eq!(f32::consts::FRAC_PI_4.sin().asin(), f32::consts::FRAC_PI_4); - assert_approx_eq!(f64::consts::FRAC_PI_4.sin().asin(), f64::consts::FRAC_PI_4); - - assert_approx_eq!(1.0f32.sinh(), 1.1752012f32); - assert_approx_eq!(1.0f64.sinh(), 1.1752012f64); - assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32); - assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64); - - assert_approx_eq!(0f32.cos(), 1f32); - assert_approx_eq!((f64::consts::PI * 2f64).cos(), 1f64); - assert_approx_eq!(f32::consts::FRAC_PI_3.cos(), 0.5); - assert_approx_eq!(f64::consts::FRAC_PI_3.cos(), 0.5); - assert_approx_eq!(f32::consts::FRAC_PI_4.cos().acos(), f32::consts::FRAC_PI_4); - assert_approx_eq!(f64::consts::FRAC_PI_4.cos().acos(), f64::consts::FRAC_PI_4); - - assert_approx_eq!(1.0f32.cosh(), 1.54308f32); - assert_approx_eq!(1.0f64.cosh(), 1.54308f64); - assert_approx_eq!(2.0f32.acosh(), 1.31695789692481670862504634730796844f32); - assert_approx_eq!(3.0f64.acosh(), 1.76274717403908605046521864995958461f64); - - assert_approx_eq!(1.0f32.tan(), 1.557408f32); - assert_approx_eq!(1.0f64.tan(), 1.557408f64); - assert_approx_eq!(1.0_f32, 1.0_f32.tan().atan()); - assert_approx_eq!(1.0_f64, 1.0_f64.tan().atan()); - assert_approx_eq!(1.0f32.atan2(2.0f32), 0.46364761f32); - assert_approx_eq!(1.0f32.atan2(2.0f32), 0.46364761f32); - - assert_approx_eq!( - 1.0f32.tanh(), - (1.0 - f32::consts::E.powi(-2)) / (1.0 + f32::consts::E.powi(-2)) - ); - assert_approx_eq!( - 1.0f64.tanh(), - (1.0 - f64::consts::E.powi(-2)) / (1.0 + f64::consts::E.powi(-2)) - ); - assert_approx_eq!(0.5f32.atanh(), 0.54930614433405484569762261846126285f32); - assert_approx_eq!(0.5f64.atanh(), 0.54930614433405484569762261846126285f64); - - assert_approx_eq!(5.0f32.gamma(), 24.0); - assert_approx_eq!(5.0f64.gamma(), 24.0); - assert_approx_eq!((-0.5f32).gamma(), (-2.0) * f32::consts::PI.sqrt()); - assert_approx_eq!((-0.5f64).gamma(), (-2.0) * f64::consts::PI.sqrt()); - - assert_eq!(2.0f32.ln_gamma(), (0.0, 1)); - assert_eq!(2.0f64.ln_gamma(), (0.0, 1)); - // Gamma(-0.5) = -2*sqrt(π) - let (val, sign) = (-0.5f32).ln_gamma(); - assert_approx_eq!(val, (2.0 * f32::consts::PI.sqrt()).ln()); - assert_eq!(sign, -1); - let (val, sign) = (-0.5f64).ln_gamma(); - assert_approx_eq!(val, (2.0 * f64::consts::PI.sqrt()).ln()); - assert_eq!(sign, -1); -} - -fn mul_add() { - assert_approx_eq!(3.0f32.mul_add(2.0f32, 5.0f32), 11.0); - assert_eq!(0.0f32.mul_add(-2.0, f32::consts::E), f32::consts::E); - assert_approx_eq!(3.0f64.mul_add(2.0, 5.0), 11.0); - assert_eq!(0.0f64.mul_add(-2.0f64, f64::consts::E), f64::consts::E); - assert_eq!((-3.2f32).mul_add(2.4, f32::NEG_INFINITY), f32::NEG_INFINITY); - assert_eq!((-3.2f64).mul_add(2.4, f64::NEG_INFINITY), f64::NEG_INFINITY); - - let f = f32::mul_add( - -0.000000000000000000000000000000000000014728589, - 0.0000037105144, - 0.000000000000000000000000000000000000000000055, - ); - assert_eq!(f.to_bits(), f32::to_bits(-0.0)); -} diff --git a/src/tools/miri/tests/pass/stacked-borrows/non_scalar_field_retagging.rs b/src/tools/miri/tests/pass/stacked-borrows/non_scalar_field_retagging.rs index 06c0b683810af..92d8f3237d013 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/non_scalar_field_retagging.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/non_scalar_field_retagging.rs @@ -1,6 +1,10 @@ //@compile-flags: -Zmiri-retag-fields=scalar -struct Newtype<'a>(#[allow(dead_code)] &'a mut i32, #[allow(dead_code)] i32, #[allow(dead_code)] i32); +struct Newtype<'a>( + #[allow(dead_code)] &'a mut i32, + #[allow(dead_code)] i32, + #[allow(dead_code)] i32, +); fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) { dealloc(); diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr index aeedf6b194978..e1461fec296e0 100644 --- a/tests/ui/associated-consts/issue-105330.stderr +++ b/tests/ui/associated-consts/issue-105330.stderr @@ -33,11 +33,13 @@ LL | fn main>() { = note: see issue #92827 for more information = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers +error[E0562]: `impl Trait` is not allowed in impl headers --> $DIR/issue-105330.rs:6:27 | LL | impl TraitWAssocConst for impl Demo { | ^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0131]: `main` function is not allowed to have generic parameters --> $DIR/issue-105330.rs:15:8 diff --git a/tests/ui/async-await/pin-needed-to-poll-2.stderr b/tests/ui/async-await/pin-needed-to-poll-2.stderr index 9c1ad32cc2ce9..8eb671531e792 100644 --- a/tests/ui/async-await/pin-needed-to-poll-2.stderr +++ b/tests/ui/async-await/pin-needed-to-poll-2.stderr @@ -13,7 +13,7 @@ note: required because it appears within the type `Sleep` | LL | struct Sleep(std::marker::PhantomPinned); | ^^^^^ -note: required by a bound in `Pin::

::new` +note: required by a bound in `Pin::::new` --> $SRC_DIR/core/src/pin.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.stderr b/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.stderr index f5cb3e2b5f807..48fc84618823e 100644 --- a/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.stderr +++ b/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.stderr @@ -1,4 +1,4 @@ -error[E0133]: call to unsafe function `Pin::

::new_unchecked` is unsafe and requires unsafe function or block +error[E0133]: call to unsafe function `Pin::::new_unchecked` is unsafe and requires unsafe function or block --> $DIR/coerce-unsafe-closure-to-unsafe-fn-ptr.rs:2:31 | LL | let _: unsafe fn() = || { ::std::pin::Pin::new_unchecked(&0_u8); }; diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs index 152c7a8de66a1..073599edad7b9 100644 --- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -54,20 +54,20 @@ fn _rpit_dyn() -> Box> { Box::new(S1) } const _cdef: impl Tr1 = S1; //~^ ERROR associated type bounds are unstable -//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~| ERROR `impl Trait` is not allowed in const types // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. // const _cdef_dyn: &dyn Tr1 = &S1; static _sdef: impl Tr1 = S1; //~^ ERROR associated type bounds are unstable -//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~| ERROR `impl Trait` is not allowed in static types // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. // static _sdef_dyn: &dyn Tr1 = &S1; fn main() { let _: impl Tr1 = S1; //~^ ERROR associated type bounds are unstable - //~| ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~| ERROR `impl Trait` is not allowed in the type of variable bindings // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. // let _: &dyn Tr1 = &S1; } diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr index f2bceda9bea71..4a643d31259f2 100644 --- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -115,23 +115,29 @@ LL | let _: impl Tr1 = S1; = note: see issue #52662 for more information = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types +error[E0562]: `impl Trait` is not allowed in const types --> $DIR/feature-gate-associated_type_bounds.rs:55:14 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types +error[E0562]: `impl Trait` is not allowed in static types --> $DIR/feature-gate-associated_type_bounds.rs:61:15 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings +error[E0562]: `impl Trait` is not allowed in the type of variable bindings --> $DIR/feature-gate-associated_type_bounds.rs:68:12 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0277]: the trait bound `<::A as Iterator>::Item: Copy` is not satisfied --> $DIR/feature-gate-associated_type_bounds.rs:12:28 diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs index 1b9530fa82f38..c75eabd6ac83e 100644 --- a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs +++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs @@ -1,6 +1,6 @@ fn f() -> impl Fn() -> impl Sized { || () } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return +//~^ ERROR `impl Trait` is not allowed in the return type of `Fn` trait bounds fn g() -> &'static dyn Fn() -> impl Sized { &|| () } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return +//~^ ERROR `impl Trait` is not allowed in the return type of `Fn` trait bounds fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr index f0c0cd040e03c..dacf1ca4c37c5 100644 --- a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr +++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr @@ -1,18 +1,20 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types +error[E0562]: `impl Trait` is not allowed in the return type of `Fn` trait bounds --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:1:24 | LL | fn f() -> impl Fn() -> impl Sized { || () } | ^^^^^^^^^^ | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods = note: see issue #99697 for more information = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types +error[E0562]: `impl Trait` is not allowed in the return type of `Fn` trait bounds --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32 | LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () } | ^^^^^^^^^^ | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods = note: see issue #99697 for more information = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable diff --git a/tests/ui/impl-trait/issues/issue-54600.rs b/tests/ui/impl-trait/issues/issue-54600.rs index ccf2767012e6d..62bfd7cd96881 100644 --- a/tests/ui/impl-trait/issues/issue-54600.rs +++ b/tests/ui/impl-trait/issues/issue-54600.rs @@ -2,6 +2,6 @@ use std::fmt::Debug; fn main() { let x: Option = Some(44_u32); - //~^ `impl Trait` only allowed in function and inherent method argument and return types + //~^ `impl Trait` is not allowed in the type of variable bindings println!("{:?}", x); } diff --git a/tests/ui/impl-trait/issues/issue-54600.stderr b/tests/ui/impl-trait/issues/issue-54600.stderr index 946ad74b87228..c75c0fa0f055d 100644 --- a/tests/ui/impl-trait/issues/issue-54600.stderr +++ b/tests/ui/impl-trait/issues/issue-54600.stderr @@ -1,8 +1,10 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings +error[E0562]: `impl Trait` is not allowed in the type of variable bindings --> $DIR/issue-54600.rs:4:19 | LL | let x: Option = Some(44_u32); | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-54840.rs b/tests/ui/impl-trait/issues/issue-54840.rs index 910d23f1d9386..65257d2f7f1db 100644 --- a/tests/ui/impl-trait/issues/issue-54840.rs +++ b/tests/ui/impl-trait/issues/issue-54840.rs @@ -3,5 +3,5 @@ use std::ops::Add; fn main() { let i: i32 = 0; let j: &impl Add = &i; - //~^ `impl Trait` only allowed in function and inherent method argument and return types + //~^ `impl Trait` is not allowed in the type of variable bindings } diff --git a/tests/ui/impl-trait/issues/issue-54840.stderr b/tests/ui/impl-trait/issues/issue-54840.stderr index c4ab79f110dde..de75256d5a939 100644 --- a/tests/ui/impl-trait/issues/issue-54840.stderr +++ b/tests/ui/impl-trait/issues/issue-54840.stderr @@ -1,8 +1,10 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings +error[E0562]: `impl Trait` is not allowed in the type of variable bindings --> $DIR/issue-54840.rs:5:13 | LL | let j: &impl Add = &i; | ^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-58504.rs b/tests/ui/impl-trait/issues/issue-58504.rs index 03b51ae92d189..4f7a35e81b80b 100644 --- a/tests/ui/impl-trait/issues/issue-58504.rs +++ b/tests/ui/impl-trait/issues/issue-58504.rs @@ -8,5 +8,5 @@ fn mk_gen() -> impl Coroutine { fn main() { let gens: [impl Coroutine;2] = [ mk_gen(), mk_gen() ]; - //~^ `impl Trait` only allowed in function and inherent method argument and return types + //~^ `impl Trait` is not allowed in the type of variable bindings } diff --git a/tests/ui/impl-trait/issues/issue-58504.stderr b/tests/ui/impl-trait/issues/issue-58504.stderr index e67e48728ed09..8231732bba1c2 100644 --- a/tests/ui/impl-trait/issues/issue-58504.stderr +++ b/tests/ui/impl-trait/issues/issue-58504.stderr @@ -1,8 +1,10 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings +error[E0562]: `impl Trait` is not allowed in the type of variable bindings --> $DIR/issue-58504.rs:10:16 | LL | let gens: [impl Coroutine;2] = [ mk_gen(), mk_gen() ]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-58956.rs b/tests/ui/impl-trait/issues/issue-58956.rs index 5d5566860c0fc..a59de2379d8fa 100644 --- a/tests/ui/impl-trait/issues/issue-58956.rs +++ b/tests/ui/impl-trait/issues/issue-58956.rs @@ -5,9 +5,9 @@ impl Lam for B {} pub struct Wrap(T); const _A: impl Lam = { - //~^ `impl Trait` only allowed in function and inherent method argument and return types + //~^ `impl Trait` is not allowed in const types let x: Wrap = Wrap(B); - //~^ `impl Trait` only allowed in function and inherent method argument and return types + //~^ `impl Trait` is not allowed in the type of variable bindings x.0 }; diff --git a/tests/ui/impl-trait/issues/issue-58956.stderr b/tests/ui/impl-trait/issues/issue-58956.stderr index 5ee33352afa2a..0c81c69def3aa 100644 --- a/tests/ui/impl-trait/issues/issue-58956.stderr +++ b/tests/ui/impl-trait/issues/issue-58956.stderr @@ -1,14 +1,18 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types +error[E0562]: `impl Trait` is not allowed in const types --> $DIR/issue-58956.rs:7:11 | LL | const _A: impl Lam = { | ^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings +error[E0562]: `impl Trait` is not allowed in the type of variable bindings --> $DIR/issue-58956.rs:9:17 | LL | let x: Wrap = Wrap(B); | ^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/issues/issue-70971.rs b/tests/ui/impl-trait/issues/issue-70971.rs index c24259a71eb22..2f2c2e8f441a8 100644 --- a/tests/ui/impl-trait/issues/issue-70971.rs +++ b/tests/ui/impl-trait/issues/issue-70971.rs @@ -1,4 +1,4 @@ fn main() { let x : (impl Copy,) = (true,); - //~^ `impl Trait` only allowed in function and inherent method argument and return types + //~^ `impl Trait` is not allowed in the type of variable bindings } diff --git a/tests/ui/impl-trait/issues/issue-70971.stderr b/tests/ui/impl-trait/issues/issue-70971.stderr index fcc67291e4d2b..28c463cea8504 100644 --- a/tests/ui/impl-trait/issues/issue-70971.stderr +++ b/tests/ui/impl-trait/issues/issue-70971.stderr @@ -1,8 +1,10 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings +error[E0562]: `impl Trait` is not allowed in the type of variable bindings --> $DIR/issue-70971.rs:2:14 | LL | let x : (impl Copy,) = (true,); | ^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-79099.rs b/tests/ui/impl-trait/issues/issue-79099.rs index 22c66491ce988..757e61fb631ea 100644 --- a/tests/ui/impl-trait/issues/issue-79099.rs +++ b/tests/ui/impl-trait/issues/issue-79099.rs @@ -1,7 +1,7 @@ struct Bug { V1: [(); { let f: impl core::future::Future = async { 1 }; - //~^ `impl Trait` only allowed in function and inherent method argument and return types + //~^ `impl Trait` is not allowed in the type of variable bindings //~| expected identifier 1 }], diff --git a/tests/ui/impl-trait/issues/issue-79099.stderr b/tests/ui/impl-trait/issues/issue-79099.stderr index 82fc03c61b3b3..6c26d5bd1b742 100644 --- a/tests/ui/impl-trait/issues/issue-79099.stderr +++ b/tests/ui/impl-trait/issues/issue-79099.stderr @@ -9,11 +9,13 @@ LL | let f: impl core::future::Future = async { 1 }; = help: pass `--edition 2021` to `rustc` = note: for more on editions, read https://doc.rust-lang.org/edition-guide -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings +error[E0562]: `impl Trait` is not allowed in the type of variable bindings --> $DIR/issue-79099.rs:3:16 | LL | let f: impl core::future::Future = async { 1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs index 3224145bffeb4..771b29f3c7e18 100644 --- a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs +++ b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs @@ -1,8 +1,8 @@ struct Foo(T); -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in generic parameter defaults type Result = std::result::Result; -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in generic parameter defaults // should not cause ICE fn x() -> Foo { diff --git a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr index 56be4577d51a0..07d6c5b6b1c88 100644 --- a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr +++ b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr @@ -1,14 +1,18 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults +error[E0562]: `impl Trait` is not allowed in generic parameter defaults --> $DIR/issue-83929-impl-trait-in-generic-default.rs:1:16 | LL | struct Foo(T); | ^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults +error[E0562]: `impl Trait` is not allowed in generic parameter defaults --> $DIR/issue-83929-impl-trait-in-generic-default.rs:4:20 | LL | type Result = std::result::Result; | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/issues/issue-84919.rs b/tests/ui/impl-trait/issues/issue-84919.rs index 77d27d7c06b6c..0f911ba23ae20 100644 --- a/tests/ui/impl-trait/issues/issue-84919.rs +++ b/tests/ui/impl-trait/issues/issue-84919.rs @@ -3,7 +3,7 @@ impl Trait for () {} fn foo<'a: 'a>() { let _x: impl Trait = (); - //~^ `impl Trait` only allowed in function and inherent method argument and return types + //~^ `impl Trait` is not allowed in the type of variable bindings } fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-84919.stderr b/tests/ui/impl-trait/issues/issue-84919.stderr index 963865efa69f7..02d2ce28fb3ed 100644 --- a/tests/ui/impl-trait/issues/issue-84919.stderr +++ b/tests/ui/impl-trait/issues/issue-84919.stderr @@ -1,8 +1,10 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings +error[E0562]: `impl Trait` is not allowed in the type of variable bindings --> $DIR/issue-84919.rs:5:13 | LL | let _x: impl Trait = (); | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-86642.rs b/tests/ui/impl-trait/issues/issue-86642.rs index 49f8944ac4af0..74be8779d4458 100644 --- a/tests/ui/impl-trait/issues/issue-86642.rs +++ b/tests/ui/impl-trait/issues/issue-86642.rs @@ -1,5 +1,5 @@ static x: impl Fn(&str) -> Result<&str, ()> = move |source| { - //~^ `impl Trait` only allowed in function and inherent method argument and return types + //~^ `impl Trait` is not allowed in static types let res = (move |source| Ok(source))(source); let res = res.or((move |source| Ok(source))(source)); res diff --git a/tests/ui/impl-trait/issues/issue-86642.stderr b/tests/ui/impl-trait/issues/issue-86642.stderr index 3ad18a13290a2..19fd5bc0c1ca4 100644 --- a/tests/ui/impl-trait/issues/issue-86642.stderr +++ b/tests/ui/impl-trait/issues/issue-86642.stderr @@ -1,8 +1,10 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types +error[E0562]: `impl Trait` is not allowed in static types --> $DIR/issue-86642.rs:1:11 | LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-87295.rs b/tests/ui/impl-trait/issues/issue-87295.rs index eb44020ac0e72..a765e14884b09 100644 --- a/tests/ui/impl-trait/issues/issue-87295.rs +++ b/tests/ui/impl-trait/issues/issue-87295.rs @@ -14,5 +14,5 @@ impl Struct { fn main() { let _do_not_waste: Struct> = Struct::new(()); - //~^ `impl Trait` only allowed in function and inherent method argument and return types + //~^ `impl Trait` is not allowed in the type of variable bindings } diff --git a/tests/ui/impl-trait/issues/issue-87295.stderr b/tests/ui/impl-trait/issues/issue-87295.stderr index e9a635f244bcb..78274a056ec68 100644 --- a/tests/ui/impl-trait/issues/issue-87295.stderr +++ b/tests/ui/impl-trait/issues/issue-87295.stderr @@ -1,8 +1,10 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings +error[E0562]: `impl Trait` is not allowed in the type of variable bindings --> $DIR/issue-87295.rs:16:31 | LL | let _do_not_waste: Struct> = Struct::new(()); | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/nested_impl_trait.rs b/tests/ui/impl-trait/nested_impl_trait.rs index c036b9e367a17..760102794c34e 100644 --- a/tests/ui/impl-trait/nested_impl_trait.rs +++ b/tests/ui/impl-trait/nested_impl_trait.rs @@ -9,7 +9,7 @@ fn bad_in_ret_position(x: impl Into) -> impl Into { x } fn bad_in_fn_syntax(x: fn() -> impl Into) {} //~^ ERROR nested `impl Trait` is not allowed -//~| `impl Trait` only allowed in function and inherent method argument and return types +//~| `impl Trait` is not allowed in `fn` pointer fn bad_in_arg_position(_: impl Into) { } //~^ ERROR nested `impl Trait` is not allowed diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr index f1cafd958b05e..31c3e0c901365 100644 --- a/tests/ui/impl-trait/nested_impl_trait.stderr +++ b/tests/ui/impl-trait/nested_impl_trait.stderr @@ -34,11 +34,13 @@ LL | fn bad(x: impl Into) -> impl Into { x } | | nested `impl Trait` here | outer `impl Trait` -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types +error[E0562]: `impl Trait` is not allowed in `fn` pointer return types --> $DIR/nested_impl_trait.rs:10:32 | LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0277]: the trait bound `impl Debug: From>` is not satisfied --> $DIR/nested_impl_trait.rs:6:46 diff --git a/tests/ui/impl-trait/where-allowed.rs b/tests/ui/impl-trait/where-allowed.rs index 158dc5ab9745d..5ce63db684f3e 100644 --- a/tests/ui/impl-trait/where-allowed.rs +++ b/tests/ui/impl-trait/where-allowed.rs @@ -16,47 +16,47 @@ fn in_adt_in_parameters(_: Vec) { panic!() } // Disallowed fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in `fn` pointer // Disallowed fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in `fn` pointer // Disallowed fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in `fn` pointer // Disallowed fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in `fn` pointer // Disallowed fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in the parameters of `Fn` trait bounds // Disallowed fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in the return type of `Fn` trait bounds // Disallowed fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in the parameters of `Fn` trait bounds // Allowed fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } // Disallowed fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in the parameters of `Fn` trait bounds //~^^ ERROR nested `impl Trait` is not allowed // Disallowed fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in the return type of `Fn` trait bounds // Disallowed fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in the parameters of `Fn` trait bounds //~| ERROR nested `impl Trait` is not allowed // Allowed @@ -64,11 +64,11 @@ fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() // Disallowed fn in_Fn_parameter_in_generics (_: F) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in the parameters of `Fn` trait bounds // Disallowed fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in the return type of `Fn` trait bounds // Allowed @@ -81,22 +81,22 @@ fn in_impl_Trait_in_return() -> impl IntoIterator { // Disallowed struct InBraceStructField { x: impl Debug } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in field types // Disallowed struct InAdtInBraceStructField { x: Vec } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in field types // Disallowed struct InTupleStructField(impl Debug); -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in field types // Disallowed enum InEnum { InBraceVariant { x: impl Debug }, - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in field types InTupleVariant(impl Debug), - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in field types } // Allowed @@ -136,10 +136,10 @@ impl DummyType { // Disallowed extern "C" { fn in_foreign_parameters(_: impl Debug); - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in `extern fn` fn in_foreign_return() -> impl Debug; - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in `extern fn` } // Allowed @@ -155,97 +155,97 @@ type InTypeAlias = impl Debug; //~^ ERROR `impl Trait` in type aliases is unstable type InReturnInTypeAlias = fn() -> impl Debug; -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in `fn` pointer //~| ERROR `impl Trait` in type aliases is unstable // Disallowed in impl headers impl PartialEq for () { - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in traits } // Disallowed in impl headers impl PartialEq<()> for impl Debug { - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in impl headers } // Disallowed in inherent impls impl impl Debug { - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in impl headers } // Disallowed in inherent impls struct InInherentImplAdt { t: T } impl InInherentImplAdt { - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in impl headers } // Disallowed in where clauses fn in_fn_where_clause() where impl Debug: Debug -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in bounds { } // Disallowed in where clauses fn in_adt_in_fn_where_clause() where Vec: Debug -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in bounds { } // Disallowed fn in_trait_parameter_in_fn_where_clause() where T: PartialEq -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in bounds { } // Disallowed fn in_Fn_parameter_in_fn_where_clause() where T: Fn(impl Debug) -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in the parameters of `Fn` trait bounds { } // Disallowed fn in_Fn_return_in_fn_where_clause() where T: Fn() -> impl Debug -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in the return type of `Fn` trait bounds { } // Disallowed struct InStructGenericParamDefault(T); -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in generic parameter defaults // Disallowed enum InEnumGenericParamDefault { Variant(T) } -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in generic parameter defaults // Disallowed trait InTraitGenericParamDefault {} -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in generic parameter defaults // Disallowed type InTypeAliasGenericParamDefault = T; -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in generic parameter defaults // Disallowed impl T {} //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions //~| WARNING this was previously accepted by the compiler but is being phased out -//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~| ERROR `impl Trait` is not allowed in generic parameter defaults //~| ERROR no nominal type found // Disallowed fn in_method_generic_param_default(_: T) {} //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions //~| WARNING this was previously accepted by the compiler but is being phased out -//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~| ERROR `impl Trait` is not allowed in generic parameter defaults fn main() { let _in_local_variable: impl Fn() = || {}; - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in the type of variable bindings let _in_return_in_local_variable = || -> impl Fn() { || {} }; - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in closure return types } diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index 2d8895030f2fe..5e8a8637d0480 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -43,227 +43,301 @@ LL | type InReturnInTypeAlias = fn() -> impl Debug; = note: see issue #63063 for more information = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer params +error[E0562]: `impl Trait` is not allowed in `fn` pointer parameters --> $DIR/where-allowed.rs:18:40 | LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types +error[E0562]: `impl Trait` is not allowed in `fn` pointer return types --> $DIR/where-allowed.rs:22:42 | LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer params +error[E0562]: `impl Trait` is not allowed in `fn` pointer parameters --> $DIR/where-allowed.rs:26:38 | LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types +error[E0562]: `impl Trait` is not allowed in `fn` pointer return types --> $DIR/where-allowed.rs:30:40 | LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params +error[E0562]: `impl Trait` is not allowed in the parameters of `Fn` trait bounds --> $DIR/where-allowed.rs:34:49 | LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types +error[E0562]: `impl Trait` is not allowed in the return type of `Fn` trait bounds --> $DIR/where-allowed.rs:38:51 | LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params +error[E0562]: `impl Trait` is not allowed in the parameters of `Fn` trait bounds --> $DIR/where-allowed.rs:42:55 | LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params +error[E0562]: `impl Trait` is not allowed in the parameters of `Fn` trait bounds --> $DIR/where-allowed.rs:49:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types +error[E0562]: `impl Trait` is not allowed in the return type of `Fn` trait bounds --> $DIR/where-allowed.rs:54:53 | LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params +error[E0562]: `impl Trait` is not allowed in the parameters of `Fn` trait bounds --> $DIR/where-allowed.rs:58:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params +error[E0562]: `impl Trait` is not allowed in the parameters of `Fn` trait bounds --> $DIR/where-allowed.rs:66:38 | LL | fn in_Fn_parameter_in_generics (_: F) { panic!() } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types +error[E0562]: `impl Trait` is not allowed in the return type of `Fn` trait bounds --> $DIR/where-allowed.rs:70:40 | LL | fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types +error[E0562]: `impl Trait` is not allowed in field types --> $DIR/where-allowed.rs:83:32 | LL | struct InBraceStructField { x: impl Debug } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types +error[E0562]: `impl Trait` is not allowed in field types --> $DIR/where-allowed.rs:87:41 | LL | struct InAdtInBraceStructField { x: Vec } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types +error[E0562]: `impl Trait` is not allowed in field types --> $DIR/where-allowed.rs:91:27 | LL | struct InTupleStructField(impl Debug); | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types +error[E0562]: `impl Trait` is not allowed in field types --> $DIR/where-allowed.rs:96:25 | LL | InBraceVariant { x: impl Debug }, | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types +error[E0562]: `impl Trait` is not allowed in field types --> $DIR/where-allowed.rs:98:20 | LL | InTupleVariant(impl Debug), | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `extern fn` params +error[E0562]: `impl Trait` is not allowed in `extern fn` parameters --> $DIR/where-allowed.rs:138:33 | LL | fn in_foreign_parameters(_: impl Debug); | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `extern fn` return types +error[E0562]: `impl Trait` is not allowed in `extern fn` return types --> $DIR/where-allowed.rs:141:31 | LL | fn in_foreign_return() -> impl Debug; | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types +error[E0562]: `impl Trait` is not allowed in `fn` pointer return types --> $DIR/where-allowed.rs:157:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in traits +error[E0562]: `impl Trait` is not allowed in traits --> $DIR/where-allowed.rs:162:16 | LL | impl PartialEq for () { | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers +error[E0562]: `impl Trait` is not allowed in impl headers --> $DIR/where-allowed.rs:167:24 | LL | impl PartialEq<()> for impl Debug { | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers +error[E0562]: `impl Trait` is not allowed in impl headers --> $DIR/where-allowed.rs:172:6 | LL | impl impl Debug { | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers +error[E0562]: `impl Trait` is not allowed in impl headers --> $DIR/where-allowed.rs:178:24 | LL | impl InInherentImplAdt { | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in bounds +error[E0562]: `impl Trait` is not allowed in bounds --> $DIR/where-allowed.rs:184:11 | LL | where impl Debug: Debug | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in bounds +error[E0562]: `impl Trait` is not allowed in bounds --> $DIR/where-allowed.rs:191:15 | LL | where Vec: Debug | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in bounds +error[E0562]: `impl Trait` is not allowed in bounds --> $DIR/where-allowed.rs:198:24 | LL | where T: PartialEq | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params +error[E0562]: `impl Trait` is not allowed in the parameters of `Fn` trait bounds --> $DIR/where-allowed.rs:205:17 | LL | where T: Fn(impl Debug) | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types +error[E0562]: `impl Trait` is not allowed in the return type of `Fn` trait bounds --> $DIR/where-allowed.rs:212:22 | LL | where T: Fn() -> impl Debug | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults +error[E0562]: `impl Trait` is not allowed in generic parameter defaults --> $DIR/where-allowed.rs:218:40 | LL | struct InStructGenericParamDefault(T); | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults +error[E0562]: `impl Trait` is not allowed in generic parameter defaults --> $DIR/where-allowed.rs:222:36 | LL | enum InEnumGenericParamDefault { Variant(T) } | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults +error[E0562]: `impl Trait` is not allowed in generic parameter defaults --> $DIR/where-allowed.rs:226:38 | LL | trait InTraitGenericParamDefault {} | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults +error[E0562]: `impl Trait` is not allowed in generic parameter defaults --> $DIR/where-allowed.rs:230:41 | LL | type InTypeAliasGenericParamDefault = T; | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults +error[E0562]: `impl Trait` is not allowed in generic parameter defaults --> $DIR/where-allowed.rs:234:11 | LL | impl T {} | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults +error[E0562]: `impl Trait` is not allowed in generic parameter defaults --> $DIR/where-allowed.rs:241:40 | LL | fn in_method_generic_param_default(_: T) {} | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings +error[E0562]: `impl Trait` is not allowed in the type of variable bindings --> $DIR/where-allowed.rs:247:29 | LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in closure return types +error[E0562]: `impl Trait` is not allowed in closure return types --> $DIR/where-allowed.rs:249:46 | LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; | ^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions --> $DIR/where-allowed.rs:234:7 diff --git a/tests/ui/issues/issue-47715.rs b/tests/ui/issues/issue-47715.rs index 0a770593bc9ce..bf2b03351b29a 100644 --- a/tests/ui/issues/issue-47715.rs +++ b/tests/ui/issues/issue-47715.rs @@ -7,22 +7,22 @@ trait Iterable { } struct Container> { - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in generics field: T } enum Enum> { - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in generics A(T), } union Union + Copy> { - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in generics x: T, } type Type> = T; -//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR `impl Trait` is not allowed in generics fn main() { } diff --git a/tests/ui/issues/issue-47715.stderr b/tests/ui/issues/issue-47715.stderr index 2ded98781c643..8ed9ff4395216 100644 --- a/tests/ui/issues/issue-47715.stderr +++ b/tests/ui/issues/issue-47715.stderr @@ -1,26 +1,34 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics +error[E0562]: `impl Trait` is not allowed in generics --> $DIR/issue-47715.rs:9:37 | LL | struct Container> { | ^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics +error[E0562]: `impl Trait` is not allowed in generics --> $DIR/issue-47715.rs:14:30 | LL | enum Enum> { | ^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics +error[E0562]: `impl Trait` is not allowed in generics --> $DIR/issue-47715.rs:19:32 | LL | union Union + Copy> { | ^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics +error[E0562]: `impl Trait` is not allowed in generics --> $DIR/issue-47715.rs:24:30 | LL | type Type> = T; | ^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 4 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr index ddedf8f1d8d27..d0ca1b19ad17d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr @@ -1,27 +1,30 @@ -error[E0277]: can't compare `impl PartialEq + Destruct + Copy` with `impl PartialEq + Destruct + Copy` - --> $DIR/const-impl-trait.rs:28:17 +error[E0277]: can't compare `()` with `()` + --> $DIR/const-impl-trait.rs:35:17 | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `impl PartialEq + Destruct + Copy == impl PartialEq + Destruct + Copy` +LL | assert!(cmp(&())); + | --- ^^^ no implementation for `() == ()` + | | + | required by a bound introduced by this call | - = help: the trait `~const PartialEq` is not implemented for `impl PartialEq + Destruct + Copy` -note: required by a bound in `Foo::{opaque#0}` - --> $DIR/const-impl-trait.rs:24:22 + = help: the trait `const PartialEq` is not implemented for `()` + = help: the trait `PartialEq` is implemented for `()` +note: required by a bound in `cmp` + --> $DIR/const-impl-trait.rs:12:23 | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}` +LL | const fn cmp(a: &impl ~const PartialEq) -> bool { + | ^^^^^^^^^^^^^^^^ required by this bound in `cmp` -error[E0277]: can't drop `impl PartialEq + Destruct + Copy` - --> $DIR/const-impl-trait.rs:28:17 +error[E0277]: can't compare `&impl ~const PartialEq` with `&impl ~const PartialEq` + --> $DIR/const-impl-trait.rs:13:7 | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `impl PartialEq + Destruct + Copy` +LL | a == a + | ^^ no implementation for `&impl ~const PartialEq == &impl ~const PartialEq` | -note: required by a bound in `Foo::{opaque#0}` - --> $DIR/const-impl-trait.rs:24:41 + = help: the trait `~const PartialEq<&impl ~const PartialEq>` is not implemented for `&impl ~const PartialEq` +help: consider dereferencing both sides of the expression | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}` +LL | *a == *a + | + + error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.rs new file mode 100644 index 0000000000000..a848b6d2fc9f2 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-assoc-fn-in-trait-impl.rs @@ -0,0 +1,29 @@ +// Regression test for issue #119700. +// check-pass + +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Main { + fn compute() -> u32; +} + +impl const Main for () { + fn compute() -> u32 { + T::generate() + } +} + +#[const_trait] +trait Aux { + fn generate() -> u32; +} + +impl const Aux for () { + fn generate() -> u32 { 1024 } +} + +fn main() { + const _: u32 = <()>::compute::<()>(); + let _ = <()>::compute::<()>(); +} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.rs similarity index 100% rename from tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs rename to tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-inherent-assoc-const-fn.rs diff --git a/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr index ec985b254b340..1811cd6753ffe 100644 --- a/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr +++ b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr @@ -6,7 +6,7 @@ LL | Pin::new(S).x(); | | | required by a bound introduced by this call | -note: required by a bound in `Pin::

::new` +note: required by a bound in `Pin::::new` --> $SRC_DIR/core/src/pin.rs:LL:COL help: consider borrowing here | diff --git a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr index 7c81825e57649..60ab392f55de8 100644 --- a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -52,7 +52,7 @@ LL | Pin::new(x) | = note: consider using the `pin!` macro consider using `Box::pin` if you need to access the pinned value outside of the current scope -note: required by a bound in `Pin::

::new` +note: required by a bound in `Pin::::new` --> $SRC_DIR/core/src/pin.rs:LL:COL error[E0277]: `dyn Future + Send` cannot be unpinned @@ -65,7 +65,7 @@ LL | Pin::new(Box::new(x)) | = note: consider using the `pin!` macro consider using `Box::pin` if you need to access the pinned value outside of the current scope -note: required by a bound in `Pin::

::new` +note: required by a bound in `Pin::::new` --> $SRC_DIR/core/src/pin.rs:LL:COL error[E0308]: mismatched types diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs index 9796823a72440..46c2c22cac1c9 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs @@ -4,7 +4,7 @@ // FIXME: this is ruled out for now but should work type Foo = fn() -> impl Send; -//~^ ERROR: `impl Trait` only allowed in function and inherent method argument and return types +//~^ ERROR: `impl Trait` is not allowed in `fn` pointer return types fn make_foo() -> Foo { || 15 diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr index 5641ff301649f..0f73c14247046 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr @@ -1,8 +1,10 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types +error[E0562]: `impl Trait` is not allowed in `fn` pointer return types --> $DIR/type-alias-impl-trait-fn-type.rs:6:20 | LL | type Foo = fn() -> impl Send; | ^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 1 previous error diff --git a/tests/ui/typeck/issue-104513-ice.rs b/tests/ui/typeck/issue-104513-ice.rs index 4968d3f51fe80..aaeee9cef48ac 100644 --- a/tests/ui/typeck/issue-104513-ice.rs +++ b/tests/ui/typeck/issue-104513-ice.rs @@ -1,6 +1,6 @@ struct S; fn f() { let _: S = S; //~ ERROR cannot find trait `Oops` in this scope - //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types + //~^ ERROR `impl Trait` is not allowed in the type of variable bindings } fn main() {} diff --git a/tests/ui/typeck/issue-104513-ice.stderr b/tests/ui/typeck/issue-104513-ice.stderr index 56c6b33615462..37d38a76a4034 100644 --- a/tests/ui/typeck/issue-104513-ice.stderr +++ b/tests/ui/typeck/issue-104513-ice.stderr @@ -4,11 +4,13 @@ error[E0405]: cannot find trait `Oops` in this scope LL | let _: S = S; | ^^^^ not found in this scope -error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings +error[E0562]: `impl Trait` is not allowed in the type of variable bindings --> $DIR/issue-104513-ice.rs:3:14 | LL | let _: S = S; | ^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 2 previous errors