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/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index a274790bffcfd..24e49ff648f2f 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -120,11 +120,11 @@ impl<'a> Layout<'a> { /// Whether the layout is from a type that implements [`std::marker::PointerLike`]. /// /// Currently, that means that the type is pointer-sized, pointer-aligned, - /// and has a scalar ABI. + /// and has a initialized (non-union), scalar ABI. pub fn is_pointer_like(self, data_layout: &TargetDataLayout) -> bool { self.size() == data_layout.pointer_size && self.align().abi == data_layout.pointer_align.abi - && matches!(self.abi(), Abi::Scalar(..)) + && matches!(self.abi(), Abi::Scalar(Scalar::Initialized { .. })) } } 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/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index b4745d4883c55..99c5dce347a07 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -33,7 +33,6 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[ "tests/ui/macros/macro-expanded-include/file.txt", // testing including data with the include macros "tests/ui/macros/not-utf8.bin", // testing including data with the include macros "tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment", // more include - "tests/ui/unused-crate-deps/test.mk", // why would you use make "tests/ui/proc-macro/auxiliary/included-file.txt", // more include "tests/ui/invalid/foo.natvis.xml", // sample debugger visualizer ]; 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/dyn-star/union.rs b/tests/ui/dyn-star/union.rs new file mode 100644 index 0000000000000..ad3a85a937ae7 --- /dev/null +++ b/tests/ui/dyn-star/union.rs @@ -0,0 +1,16 @@ +#![feature(dyn_star)] +//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + +union Union { + x: usize, +} + +trait Trait {} +impl Trait for Union {} + +fn bar(_: dyn* Trait) {} + +fn main() { + bar(Union { x: 0usize }); + //~^ ERROR `Union` needs to have the same ABI as a pointer +} diff --git a/tests/ui/dyn-star/union.stderr b/tests/ui/dyn-star/union.stderr new file mode 100644 index 0000000000000..906eb4f5163e5 --- /dev/null +++ b/tests/ui/dyn-star/union.stderr @@ -0,0 +1,20 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/union.rs:1:12 + | +LL | #![feature(dyn_star)] + | ^^^^^^^^ + | + = note: see issue #102425 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: `Union` needs to have the same ABI as a pointer + --> $DIR/union.rs:14:9 + | +LL | bar(Union { x: 0usize }); + | ^^^^^^^^^^^^^^^^^^^ `Union` needs to be a pointer-like type + | + = help: the trait `PointerLike` is not implemented for `Union` + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. 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 diff --git a/tests/ui/unused-crate-deps/test.mk b/tests/ui/unused-crate-deps/test.mk deleted file mode 100644 index 0b98b4e44fb2a..0000000000000 --- a/tests/ui/unused-crate-deps/test.mk +++ /dev/null @@ -1,7 +0,0 @@ -# Everyone uses make for building Rust - -foo: bar.rlib - $(RUSTC) --crate-type bin --extern bar=bar.rlib - -%.rlib: %.rs - $(RUSTC) --crate-type lib $<