diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 52b54655d1ca1..c2bfb3033195e 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3867,6 +3867,19 @@ pub struct Fn { pub eii_impls: ThinVec, } +impl Fn { + pub fn is_pin_drop_sugar(&self) -> bool { + self.ident.name == sym::drop + && self + .sig + .decl + .inputs + .first() + .and_then(|param| param.to_self()) + .is_some_and(|eself| matches!(eself.node, SelfKind::Pinned(None, Mutability::Mut))) + } +} + #[derive(Clone, Encodable, Decodable, Debug, Walkable)] pub struct EiiImpl { pub node_id: NodeId, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 249f8e579eee9..545e4e8750ca6 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1192,6 +1192,52 @@ impl<'hir> LoweringContext<'_, 'hir> { }) } + fn resolve_pin_drop_sugar_impl_item( + &self, + i: &AssocItem, + ident: Ident, + span: Span, + ) -> (Ident, Result) { + let trait_item_def_id = self + .get_partial_res(i.id) + .and_then(|r| r.expect_full_res().opt_def_id()) + .ok_or_else(|| { + self.dcx().span_delayed_bug(span, "could not resolve trait item being implemented") + }); + + let is_pin_drop_sugar = match &i.kind { + AssocItemKind::Fn(fn_kind) => fn_kind.is_pin_drop_sugar(), + _ => false, + }; + let def_id = match trait_item_def_id { + Ok(def_id) => def_id, + Err(guar) => return (ident, Err(guar)), + }; + if !is_pin_drop_sugar { + return (ident, Ok(def_id)); + } + + let is_drop_pin_drop = self + .tcx + .lang_items() + .drop_trait() + .is_some_and(|drop_trait| self.tcx.parent(def_id) == drop_trait); + if is_drop_pin_drop { + // Associated item collection still derives the impl item's name from HIR. + return (Ident::new(sym::pin_drop, ident.span), Ok(def_id)); + } + + let guar = self + .dcx() + .struct_span_err( + i.span, + "method `drop` with `&pin mut self` is only supported for the `Drop` trait", + ) + .with_span_label(i.span, "not a `Drop::pin_drop` implementation") + .emit(); + (ident, Err(guar)) + } + fn lower_impl_item( &mut self, i: &AssocItem, @@ -1309,26 +1355,19 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let span = self.lower_span(i.span); + let (effective_ident, impl_kind) = if is_in_trait_impl { + let (effective_ident, trait_item_def_id) = + self.resolve_pin_drop_sugar_impl_item(i, ident, span); + (effective_ident, ImplItemImplKind::Trait { defaultness, trait_item_def_id }) + } else { + (ident, ImplItemImplKind::Inherent { vis_span: self.lower_span(i.vis.span) }) + }; + let item = hir::ImplItem { owner_id: hir_id.expect_owner(), - ident: self.lower_ident(ident), + ident: self.lower_ident(effective_ident), generics, - impl_kind: if is_in_trait_impl { - ImplItemImplKind::Trait { - defaultness, - trait_item_def_id: self - .get_partial_res(i.id) - .and_then(|r| r.expect_full_res().opt_def_id()) - .ok_or_else(|| { - self.dcx().span_delayed_bug( - span, - "could not resolve trait item being implemented", - ) - }), - } - } else { - ImplItemImplKind::Inherent { vis_span: self.lower_span(i.vis.span) } - }, + impl_kind, kind, span, has_delayed_lints: !self.delayed_lints.is_empty(), diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index e8bd3abdc621e..8af45ff8bf3d0 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3591,6 +3591,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.check_trait_item( item.id, *ident, + *ident, &item.kind, ValueNS, item.span, @@ -3635,7 +3636,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); self.resolve_define_opaques(define_opaque); } - AssocItemKind::Fn(Fn { ident, generics, define_opaque, .. }) => { + AssocItemKind::Fn(fn_kind @ Fn { ident, generics, define_opaque, .. }) => { debug!("resolve_implementation AssocItemKind::Fn"); // We also need a new scope for the impl item type parameters. self.with_generic_param_rib( @@ -3645,10 +3646,16 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { LifetimeBinderKind::Function, generics.span, |this| { + let effective_ident = if is_in_trait_impl && fn_kind.is_pin_drop_sugar() { + Ident::new(sym::pin_drop, ident.span) + } else { + *ident + }; // If this is a trait impl, ensure the method // exists in trait this.check_trait_item( item.id, + effective_ident, *ident, &item.kind, ValueNS, @@ -3680,6 +3687,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.check_trait_item( item.id, *ident, + *ident, &item.kind, TypeNS, item.span, @@ -3705,6 +3713,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.check_trait_item( item.id, delegation.ident, + delegation.ident, &item.kind, ValueNS, item.span, @@ -3729,6 +3738,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { &mut self, id: NodeId, mut ident: Ident, + mut reported_ident: Ident, kind: &AssocItemKind, ns: Namespace, span: Span, @@ -3742,6 +3752,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { return; }; ident.span.normalize_to_macros_2_0_and_adjust(module.expansion); + reported_ident.span.normalize_to_macros_2_0_and_adjust(module.expansion); let key = BindingKey::new(IdentKey::new(ident), ns); let mut decl = self.r.resolution(module, key).and_then(|r| r.best_decl()); debug!(?decl); @@ -3777,10 +3788,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let Some(decl) = decl else { // We could not find the method: report an error. - let candidate = self.find_similarly_named_assoc_item(ident.name, kind); + let candidate = self.find_similarly_named_assoc_item(reported_ident.name, kind); let path = &self.current_trait_ref.as_ref().unwrap().1.path; let path_names = path_names_to_string(path); - self.report_error(span, err(ident, path_names, candidate)); + self.report_error(span, err(reported_ident, path_names, candidate)); feed_visibility(self, module.def_id()); return; }; diff --git a/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs b/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs index 7fd7504622c89..e69797c0aa063 100644 --- a/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs +++ b/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs @@ -17,6 +17,14 @@ impl Drop for Foo { //~^ ERROR use of unstable library feature `pin_ergonomics` [E0658] } +struct Sugar; + +impl Drop for Sugar { + //~^ ERROR not all trait items implemented, missing: `drop` + fn drop(&pin mut self) {} //~ ERROR pinned reference syntax is experimental + //~^ ERROR use of unstable library feature `pin_ergonomics` [E0658] +} + fn foo(mut x: Pin<&mut Foo>) { Foo::foo_sugar(x.as_mut()); Foo::foo_sugar_const(x.as_ref()); diff --git a/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr b/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr index e1919666adbda..c4db06d499450 100644 --- a/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr +++ b/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr @@ -29,7 +29,17 @@ LL | fn pin_drop(&pin mut self) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:23:14 + --> $DIR/feature-gate-pin_ergonomics.rs:24:14 + | +LL | fn drop(&pin mut self) {} + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:31:14 | LL | let _y: &pin mut Foo = x; | ^^^ @@ -39,7 +49,7 @@ LL | let _y: &pin mut Foo = x; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:27:14 + --> $DIR/feature-gate-pin_ergonomics.rs:35:14 | LL | let _y: &pin const Foo = x; | ^^^ @@ -49,7 +59,7 @@ LL | let _y: &pin const Foo = x; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:30:18 + --> $DIR/feature-gate-pin_ergonomics.rs:38:18 | LL | fn foo_sugar(_: &pin mut Foo) {} | ^^^ @@ -59,7 +69,7 @@ LL | fn foo_sugar(_: &pin mut Foo) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:42:18 + --> $DIR/feature-gate-pin_ergonomics.rs:50:18 | LL | fn baz_sugar(_: &pin const Foo) {} | ^^^ @@ -69,7 +79,7 @@ LL | fn baz_sugar(_: &pin const Foo) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:45:31 + --> $DIR/feature-gate-pin_ergonomics.rs:53:31 | LL | let mut x: Pin<&mut _> = &pin mut Foo; | ^^^ @@ -79,7 +89,7 @@ LL | let mut x: Pin<&mut _> = &pin mut Foo; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:50:23 + --> $DIR/feature-gate-pin_ergonomics.rs:58:23 | LL | let x: Pin<&_> = &pin const Foo; | ^^^ @@ -89,7 +99,7 @@ LL | let x: Pin<&_> = &pin const Foo; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:57:6 + --> $DIR/feature-gate-pin_ergonomics.rs:65:6 | LL | &pin mut x: &pin mut i32, | ^^^ @@ -99,7 +109,7 @@ LL | &pin mut x: &pin mut i32, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:57:18 + --> $DIR/feature-gate-pin_ergonomics.rs:65:18 | LL | &pin mut x: &pin mut i32, | ^^^ @@ -109,7 +119,7 @@ LL | &pin mut x: &pin mut i32, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:60:6 + --> $DIR/feature-gate-pin_ergonomics.rs:68:6 | LL | &pin const y: &'a pin const i32, | ^^^ @@ -119,7 +129,7 @@ LL | &pin const y: &'a pin const i32, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:60:23 + --> $DIR/feature-gate-pin_ergonomics.rs:68:23 | LL | &pin const y: &'a pin const i32, | ^^^ @@ -129,7 +139,7 @@ LL | &pin const y: &'a pin const i32, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:63:9 + --> $DIR/feature-gate-pin_ergonomics.rs:71:9 | LL | ref pin mut z: i32, | ^^^ @@ -139,7 +149,7 @@ LL | ref pin mut z: i32, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:64:9 + --> $DIR/feature-gate-pin_ergonomics.rs:72:9 | LL | ref pin const w: i32, | ^^^ @@ -149,7 +159,7 @@ LL | ref pin const w: i32, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:76:23 + --> $DIR/feature-gate-pin_ergonomics.rs:84:23 | LL | fn foo_sugar(&pin mut self) {} | ^^^ @@ -159,7 +169,7 @@ LL | fn foo_sugar(&pin mut self) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:77:29 + --> $DIR/feature-gate-pin_ergonomics.rs:85:29 | LL | fn foo_sugar_const(&pin const self) {} | ^^^ @@ -169,7 +179,7 @@ LL | fn foo_sugar_const(&pin const self) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:81:22 + --> $DIR/feature-gate-pin_ergonomics.rs:89:22 | LL | fn pin_drop(&pin mut self) {} | ^^^ @@ -179,7 +189,7 @@ LL | fn pin_drop(&pin mut self) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:87:18 + --> $DIR/feature-gate-pin_ergonomics.rs:95:18 | LL | let _y: &pin mut Foo = x; | ^^^ @@ -189,7 +199,7 @@ LL | let _y: &pin mut Foo = x; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:90:22 + --> $DIR/feature-gate-pin_ergonomics.rs:98:22 | LL | fn foo_sugar(_: &pin mut Foo) {} | ^^^ @@ -199,7 +209,7 @@ LL | fn foo_sugar(_: &pin mut Foo) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:102:22 + --> $DIR/feature-gate-pin_ergonomics.rs:110:22 | LL | fn baz_sugar(_: &pin const Foo) {} | ^^^ @@ -209,7 +219,7 @@ LL | fn baz_sugar(_: &pin const Foo) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:105:35 + --> $DIR/feature-gate-pin_ergonomics.rs:113:35 | LL | let mut x: Pin<&mut _> = &pin mut Foo; | ^^^ @@ -219,7 +229,7 @@ LL | let mut x: Pin<&mut _> = &pin mut Foo; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:110:27 + --> $DIR/feature-gate-pin_ergonomics.rs:118:27 | LL | let x: Pin<&_> = &pin const Foo; | ^^^ @@ -229,7 +239,7 @@ LL | let x: Pin<&_> = &pin const Foo; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:117:10 + --> $DIR/feature-gate-pin_ergonomics.rs:125:10 | LL | &pin mut x: &pin mut i32, | ^^^ @@ -239,7 +249,7 @@ LL | &pin mut x: &pin mut i32, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:117:22 + --> $DIR/feature-gate-pin_ergonomics.rs:125:22 | LL | &pin mut x: &pin mut i32, | ^^^ @@ -249,7 +259,7 @@ LL | &pin mut x: &pin mut i32, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:120:10 + --> $DIR/feature-gate-pin_ergonomics.rs:128:10 | LL | &pin const y: &'a pin const i32, | ^^^ @@ -259,7 +269,7 @@ LL | &pin const y: &'a pin const i32, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:120:27 + --> $DIR/feature-gate-pin_ergonomics.rs:128:27 | LL | &pin const y: &'a pin const i32, | ^^^ @@ -269,7 +279,7 @@ LL | &pin const y: &'a pin const i32, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:123:13 + --> $DIR/feature-gate-pin_ergonomics.rs:131:13 | LL | ref pin mut z: i32, | ^^^ @@ -279,7 +289,7 @@ LL | ref pin mut z: i32, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:124:13 + --> $DIR/feature-gate-pin_ergonomics.rs:132:13 | LL | ref pin const w: i32, | ^^^ @@ -308,6 +318,16 @@ LL | fn pin_drop(&pin mut self) {} = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: use of unstable library feature `pin_ergonomics` + --> $DIR/feature-gate-pin_ergonomics.rs:24:5 + | +LL | fn drop(&pin mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0046]: not all trait items implemented, missing: `drop` --> $DIR/feature-gate-pin_ergonomics.rs:14:1 | @@ -316,8 +336,16 @@ LL | impl Drop for Foo { | = help: implement the missing item: `fn drop(&mut self) { todo!() }` +error[E0046]: not all trait items implemented, missing: `drop` + --> $DIR/feature-gate-pin_ergonomics.rs:22:1 + | +LL | impl Drop for Sugar { + | ^^^^^^^^^^^^^^^^^^^ missing `drop` in implementation + | + = help: implement the missing item: `fn drop(&mut self) { todo!() }` + error[E0382]: use of moved value: `x` - --> $DIR/feature-gate-pin_ergonomics.rs:34:9 + --> $DIR/feature-gate-pin_ergonomics.rs:42:9 | LL | fn bar(x: Pin<&mut Foo>) { | - move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait @@ -327,7 +355,7 @@ LL | foo(x); | ^ value used here after move | note: consider changing this parameter type in function `foo` to borrow instead if owning the value isn't necessary - --> $DIR/feature-gate-pin_ergonomics.rs:20:15 + --> $DIR/feature-gate-pin_ergonomics.rs:28:15 | LL | fn foo(mut x: Pin<&mut Foo>) { | --- ^^^^^^^^^^^^^ this parameter takes ownership of the value @@ -335,7 +363,7 @@ LL | fn foo(mut x: Pin<&mut Foo>) { | in this function error[E0382]: use of moved value: `x` - --> $DIR/feature-gate-pin_ergonomics.rs:39:5 + --> $DIR/feature-gate-pin_ergonomics.rs:47:5 | LL | fn baz(mut x: Pin<&mut Foo>) { | ----- move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait @@ -354,7 +382,7 @@ help: consider reborrowing the `Pin` instead of moving it LL | x.as_mut().foo(); | +++++++++ -error: aborting due to 34 previous errors +error: aborting due to 37 previous errors Some errors have detailed explanations: E0046, E0382, E0658. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/pin-ergonomics/pinned-drop-check.rs b/tests/ui/pin-ergonomics/pinned-drop-check.rs index a8005b94dbba2..bd8d096fec547 100644 --- a/tests/ui/pin-ergonomics/pinned-drop-check.rs +++ b/tests/ui/pin-ergonomics/pinned-drop-check.rs @@ -25,11 +25,11 @@ mod pin_drop_only { struct Bar; impl Drop for Foo { - fn pin_drop(&pin mut self) {} // ok, only `pin_drop` is implemented + fn pin_drop(&pin mut self) {} // ok, non-`#[pin_v2]` can also implement `pin_drop` } impl Drop for Bar { - fn pin_drop(&pin mut self) {} // ok, non-`#[pin_v2]` can also implement `pin_drop` + fn pin_drop(&pin mut self) {} // ok, `#[pin_v2]` implements `pin_drop` } } @@ -60,16 +60,67 @@ mod neither { impl Drop for Bar {} //~ ERROR not all trait items implemented, missing one of: `drop`, `pin_drop` [E0046] } -mod drop_wrong_type { +mod drop_sugar { struct Foo; #[pin_v2] struct Bar; impl Drop for Foo { - fn drop(&pin mut self) {} //~ ERROR method `drop` has an incompatible type for trait [E0053] + fn drop(&pin mut self) {} // ok, sugar for `pin_drop` } + impl Drop for Bar { - fn drop(&pin mut self) {} + fn drop(&pin mut self) {} // ok, sugar for `pin_drop` + } +} + +mod drop_pin_const_wrong_type { + struct Foo; + #[pin_v2] + struct Bar; + + impl Drop for Foo { + fn drop(&pin const self) {} //~ ERROR method `drop` has an incompatible type for trait [E0053] + } + + impl Drop for Bar { + fn drop(&pin const self) {} + //~^ ERROR method `drop` has an incompatible type for trait [E0053] + //~| ERROR `Bar` must implement `pin_drop` + } +} + +mod drop_with_lifetime_wrong_type { + struct Foo; + #[pin_v2] + struct Bar; + + impl Drop for Foo { + fn drop<'a>(&'a pin mut self) {} + //~^ ERROR method `drop` has an incompatible type for trait [E0053] + } + + impl Drop for Bar { + fn drop<'a>(&'a pin mut self) {} + //~^ ERROR method `drop` has an incompatible type for trait [E0053] + //~| ERROR `Bar` must implement `pin_drop` + } +} + +mod drop_explicit_pin_wrong_type { + use std::pin::Pin; + + struct Foo; + #[pin_v2] + struct Bar; + + impl Drop for Foo { + fn drop(self: Pin<&mut Self>) {} + //~^ ERROR method `drop` has an incompatible type for trait [E0053] + } + + impl Drop for Bar { + fn drop(self: Pin<&mut Self>) {} //~^ ERROR method `drop` has an incompatible type for trait [E0053] //~| ERROR `Bar` must implement `pin_drop` } @@ -124,4 +175,31 @@ mod explicit_call_drop { } } +mod explicit_call_drop_sugar { + struct Foo; + + impl Drop for Foo { + fn drop(&pin mut self) { + Drop::drop(todo!()); //~ ERROR explicit use of destructor method [E0040] + Drop::pin_drop(todo!()); //~ ERROR explicit use of destructor method [E0040] + } + } +} + +mod sugar_and_pin_drop { + struct Foo; + #[pin_v2] + struct Bar; + + impl Drop for Foo { + fn drop(&pin mut self) {} + fn pin_drop(&pin mut self) {} //~ ERROR duplicate definitions with name `pin_drop` + } + + impl Drop for Bar { + fn drop(&pin mut self) {} + fn pin_drop(&pin mut self) {} //~ ERROR duplicate definitions with name `pin_drop` + } +} + fn main() {} diff --git a/tests/ui/pin-ergonomics/pinned-drop-check.stderr b/tests/ui/pin-ergonomics/pinned-drop-check.stderr index edadbcd0a0a93..3a848c66578b4 100644 --- a/tests/ui/pin-ergonomics/pinned-drop-check.stderr +++ b/tests/ui/pin-ergonomics/pinned-drop-check.stderr @@ -1,3 +1,27 @@ +error[E0201]: duplicate definitions with name `pin_drop`: + --> $DIR/pinned-drop-check.rs:196:9 + | +LL | fn drop(&pin mut self) {} + | ------------------------- previous definition here +LL | fn pin_drop(&pin mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition + | + --> $SRC_DIR/core/src/ops/drop.rs:LL:COL + | + = note: item in trait + +error[E0201]: duplicate definitions with name `pin_drop`: + --> $DIR/pinned-drop-check.rs:201:9 + | +LL | fn drop(&pin mut self) {} + | ------------------------- previous definition here +LL | fn pin_drop(&pin mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition + | + --> $SRC_DIR/core/src/ops/drop.rs:LL:COL + | + = note: item in trait + error: `Bar` must implement `pin_drop` --> $DIR/pinned-drop-check.rs:18:9 | @@ -55,56 +79,157 @@ LL | impl Drop for Bar {} | ^^^^^^^^^^^^^^^^^ missing one of `drop`, `pin_drop` in implementation error: `Bar` must implement `pin_drop` - --> $DIR/pinned-drop-check.rs:72:9 + --> $DIR/pinned-drop-check.rs:87:9 | -LL | fn drop(&pin mut self) {} - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | fn drop(&pin const self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: structurally pinned types must keep `Pin`'s safety contract note: `Bar` is marked `#[pin_v2]` here - --> $DIR/pinned-drop-check.rs:65:5 + --> $DIR/pinned-drop-check.rs:79:5 | LL | #[pin_v2] | ^^^^^^^^^ help: implement `pin_drop` instead | -LL | fn pin_drop(&pin mut self) {} - | ++++ +LL - fn drop(&pin const self) {} +LL + fn pin_drop(&pin mut self) {} + | help: remove the `#[pin_v2]` attribute if it is not intended for structurally pinning | LL - #[pin_v2] | error[E0053]: method `drop` has an incompatible type for trait - --> $DIR/pinned-drop-check.rs:69:17 + --> $DIR/pinned-drop-check.rs:83:17 | -LL | fn drop(&pin mut self) {} - | ^^^^^^^^^^^^^ expected `&mut drop_wrong_type::Foo`, found `Pin<&mut drop_wrong_type::Foo>` +LL | fn drop(&pin const self) {} + | ^^^^^^^^^^^^^^^ expected `&mut drop_pin_const_wrong_type::Foo`, found `Pin<&drop_pin_const_wrong_type::Foo>` | - = note: expected signature `fn(&mut drop_wrong_type::Foo)` - found signature `fn(Pin<&mut drop_wrong_type::Foo>)` + = note: expected signature `fn(&mut drop_pin_const_wrong_type::Foo)` + found signature `fn(Pin<&drop_pin_const_wrong_type::Foo>)` help: change the self-receiver type to match the trait | -LL - fn drop(&pin mut self) {} +LL - fn drop(&pin const self) {} LL + fn drop(&mut self) {} | error[E0053]: method `drop` has an incompatible type for trait - --> $DIR/pinned-drop-check.rs:72:17 + --> $DIR/pinned-drop-check.rs:87:17 | -LL | fn drop(&pin mut self) {} - | ^^^^^^^^^^^^^ expected `&mut drop_wrong_type::Bar`, found `Pin<&mut drop_wrong_type::Bar>` +LL | fn drop(&pin const self) {} + | ^^^^^^^^^^^^^^^ expected `&mut drop_pin_const_wrong_type::Bar`, found `Pin<&drop_pin_const_wrong_type::Bar>` + | + = note: expected signature `fn(&mut drop_pin_const_wrong_type::Bar)` + found signature `fn(Pin<&drop_pin_const_wrong_type::Bar>)` +help: change the self-receiver type to match the trait + | +LL - fn drop(&pin const self) {} +LL + fn drop(&mut self) {} + | + +error: `Bar` must implement `pin_drop` + --> $DIR/pinned-drop-check.rs:104:9 + | +LL | fn drop<'a>(&'a pin mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: structurally pinned types must keep `Pin`'s safety contract +note: `Bar` is marked `#[pin_v2]` here + --> $DIR/pinned-drop-check.rs:95:5 + | +LL | #[pin_v2] + | ^^^^^^^^^ +help: implement `pin_drop` instead + | +LL - fn drop<'a>(&'a pin mut self) {} +LL + fn pin_drop(&pin mut self) {} + | +help: remove the `#[pin_v2]` attribute if it is not intended for structurally pinning + | +LL - #[pin_v2] + | + +error[E0053]: method `drop` has an incompatible type for trait + --> $DIR/pinned-drop-check.rs:99:21 + | +LL | fn drop<'a>(&'a pin mut self) {} + | ^^^^^^^^^^^^^^^^ expected `&mut drop_with_lifetime_wrong_type::Foo`, found `Pin<&mut Foo>` + | + = note: expected signature `fn(&mut drop_with_lifetime_wrong_type::Foo)` + found signature `fn(Pin<&mut drop_with_lifetime_wrong_type::Foo>)` +help: change the self-receiver type to match the trait + | +LL - fn drop<'a>(&'a pin mut self) {} +LL + fn drop<'a>(&mut self) {} | - = note: expected signature `fn(&mut drop_wrong_type::Bar)` - found signature `fn(Pin<&mut drop_wrong_type::Bar>)` + +error[E0053]: method `drop` has an incompatible type for trait + --> $DIR/pinned-drop-check.rs:104:21 + | +LL | fn drop<'a>(&'a pin mut self) {} + | ^^^^^^^^^^^^^^^^ expected `&mut drop_with_lifetime_wrong_type::Bar`, found `Pin<&mut Bar>` + | + = note: expected signature `fn(&mut drop_with_lifetime_wrong_type::Bar)` + found signature `fn(Pin<&mut drop_with_lifetime_wrong_type::Bar>)` +help: change the self-receiver type to match the trait + | +LL - fn drop<'a>(&'a pin mut self) {} +LL + fn drop<'a>(&mut self) {} + | + +error: `Bar` must implement `pin_drop` + --> $DIR/pinned-drop-check.rs:123:9 + | +LL | fn drop(self: Pin<&mut Self>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: structurally pinned types must keep `Pin`'s safety contract +note: `Bar` is marked `#[pin_v2]` here + --> $DIR/pinned-drop-check.rs:114:5 + | +LL | #[pin_v2] + | ^^^^^^^^^ +help: implement `pin_drop` instead + | +LL - fn drop(self: Pin<&mut Self>) {} +LL + fn pin_drop(&pin mut self) {} + | +help: remove the `#[pin_v2]` attribute if it is not intended for structurally pinning + | +LL - #[pin_v2] + | + +error[E0053]: method `drop` has an incompatible type for trait + --> $DIR/pinned-drop-check.rs:118:23 + | +LL | fn drop(self: Pin<&mut Self>) {} + | ^^^^^^^^^^^^^^ expected `&mut drop_explicit_pin_wrong_type::Foo`, found `Pin<&mut Foo>` + | + = note: expected signature `fn(&mut drop_explicit_pin_wrong_type::Foo)` + found signature `fn(Pin<&mut drop_explicit_pin_wrong_type::Foo>)` help: change the self-receiver type to match the trait | -LL - fn drop(&pin mut self) {} +LL - fn drop(self: Pin<&mut Self>) {} +LL + fn drop(&mut self) {} + | + +error[E0053]: method `drop` has an incompatible type for trait + --> $DIR/pinned-drop-check.rs:123:23 + | +LL | fn drop(self: Pin<&mut Self>) {} + | ^^^^^^^^^^^^^^ expected `&mut drop_explicit_pin_wrong_type::Bar`, found `Pin<&mut Bar>` + | + = note: expected signature `fn(&mut drop_explicit_pin_wrong_type::Bar)` + found signature `fn(Pin<&mut drop_explicit_pin_wrong_type::Bar>)` +help: change the self-receiver type to match the trait + | +LL - fn drop(self: Pin<&mut Self>) {} LL + fn drop(&mut self) {} | error[E0053]: method `pin_drop` has an incompatible type for trait - --> $DIR/pinned-drop-check.rs:84:21 + --> $DIR/pinned-drop-check.rs:135:21 | LL | fn pin_drop(&mut self) {} | ^^^^^^^^^ expected `Pin<&mut pin_drop_wrong_type::Foo>`, found `&mut pin_drop_wrong_type::Foo` @@ -118,7 +243,7 @@ LL + fn pin_drop(self: Pin<&mut pin_drop_wrong_type::Foo>) {} | error[E0053]: method `pin_drop` has an incompatible type for trait - --> $DIR/pinned-drop-check.rs:88:21 + --> $DIR/pinned-drop-check.rs:139:21 | LL | fn pin_drop(&mut self) {} | ^^^^^^^^^ expected `Pin<&mut pin_drop_wrong_type::Bar>`, found `&mut pin_drop_wrong_type::Bar` @@ -132,14 +257,14 @@ LL + fn pin_drop(self: Pin<&mut pin_drop_wrong_type::Bar>) {} | error: `Bar` must implement `pin_drop` - --> $DIR/pinned-drop-check.rs:103:9 + --> $DIR/pinned-drop-check.rs:154:9 | LL | fn drop(&mut self) { | ^^^^^^^^^^^^^^^^^^ | = help: structurally pinned types must keep `Pin`'s safety contract note: `Bar` is marked `#[pin_v2]` here - --> $DIR/pinned-drop-check.rs:94:5 + --> $DIR/pinned-drop-check.rs:145:5 | LL | #[pin_v2] | ^^^^^^^^^ @@ -154,30 +279,42 @@ LL - #[pin_v2] | error[E0040]: explicit use of destructor method - --> $DIR/pinned-drop-check.rs:99:13 + --> $DIR/pinned-drop-check.rs:150:13 | LL | Drop::pin_drop(todo!()); | ^^^^^^^^^^^^^^ explicit destructor calls not allowed error[E0040]: explicit use of destructor method - --> $DIR/pinned-drop-check.rs:105:13 + --> $DIR/pinned-drop-check.rs:156:13 | LL | Drop::pin_drop(todo!()); | ^^^^^^^^^^^^^^ explicit destructor calls not allowed error[E0040]: explicit use of destructor method - --> $DIR/pinned-drop-check.rs:117:13 + --> $DIR/pinned-drop-check.rs:168:13 + | +LL | Drop::drop(todo!()); + | ^^^^^^^^^^ explicit destructor calls not allowed + +error[E0040]: explicit use of destructor method + --> $DIR/pinned-drop-check.rs:173:13 | LL | Drop::drop(todo!()); | ^^^^^^^^^^ explicit destructor calls not allowed error[E0040]: explicit use of destructor method - --> $DIR/pinned-drop-check.rs:122:13 + --> $DIR/pinned-drop-check.rs:183:13 | LL | Drop::drop(todo!()); | ^^^^^^^^^^ explicit destructor calls not allowed -error: aborting due to 15 previous errors +error[E0040]: explicit use of destructor method + --> $DIR/pinned-drop-check.rs:184:13 + | +LL | Drop::pin_drop(todo!()); + | ^^^^^^^^^^^^^^ explicit destructor calls not allowed + +error: aborting due to 25 previous errors -Some errors have detailed explanations: E0040, E0046, E0053. +Some errors have detailed explanations: E0040, E0046, E0053, E0201. For more information about an error, try `rustc --explain E0040`. diff --git a/tests/ui/pin-ergonomics/pinned-drop-sugar-no-core.rs b/tests/ui/pin-ergonomics/pinned-drop-sugar-no-core.rs new file mode 100644 index 0000000000000..d5687705defee --- /dev/null +++ b/tests/ui/pin-ergonomics/pinned-drop-sugar-no-core.rs @@ -0,0 +1,78 @@ +//@ check-pass + +#![no_std] +#![no_core] +#![no_main] +#![feature(no_core, pin_ergonomics, lang_items)] +#![allow(incomplete_features)] + +#[lang = "pointee_sized"] +trait PointeeSized {} + +#[lang = "meta_sized"] +trait MetaSized: PointeeSized {} + +#[lang = "sized"] +trait Sized: MetaSized {} + +#[lang = "copy"] +trait Copy {} + +#[lang = "legacy_receiver"] +trait LegacyReceiver: PointeeSized {} + +#[lang = "deref"] +trait Deref: PointeeSized { + #[lang = "deref_target"] + type Target: PointeeSized; + + fn deref(&self) -> &Self::Target; +} + +#[lang = "deref_mut"] +trait DerefMut: Deref + PointeeSized { + fn deref_mut(&mut self) -> &mut Self::Target; +} + +#[lang = "pin"] +struct Pin { + pointer: T, +} + +impl LegacyReceiver for &T {} +impl LegacyReceiver for &mut T {} +impl LegacyReceiver for Pin {} + +impl Deref for Pin { + type Target = Ptr::Target; + + fn deref(&self) -> &Self::Target { + &*self.pointer + } +} + +impl DerefMut for Pin { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut *self.pointer + } +} + +impl Deref for &mut T { + type Target = T; + + fn deref(&self) -> &Self::Target { + self + } +} + +struct LocalDrop; + +impl Drop for LocalDrop { + fn drop(&pin mut self) {} +} + +#[lang = "drop"] +trait Drop { + fn drop(&mut self) {} + fn pin_drop(self: Pin<&mut Self>) {} +} diff --git a/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.rs b/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.rs new file mode 100644 index 0000000000000..ace00348d1876 --- /dev/null +++ b/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.rs @@ -0,0 +1,62 @@ +//@ edition:2024 + +#![feature(pin_ergonomics)] +#![allow(incomplete_features)] + +use std::pin::Pin; + +struct S; + +trait NeedsPinDrop { + fn pin_drop(self: Pin<&mut Self>); +} + +impl NeedsPinDrop for S { + //~^ ERROR not all trait items implemented, missing: `pin_drop` [E0046] + fn drop(&pin mut self) {} + //~^ ERROR method `drop` with `&pin mut self` is only supported for the `Drop` trait +} + +trait HasDrop { + fn drop(self: Pin<&mut Self>); +} + +impl HasDrop for S { + //~^ ERROR not all trait items implemented, missing: `drop` [E0046] + fn drop(&pin mut self) {} + //~^ ERROR method `drop` is not a member of trait `HasDrop` [E0407] +} + +trait HasPinnedDropReceiver { + fn drop(self: &pin mut Self); +} + +impl HasPinnedDropReceiver for S { + //~^ ERROR not all trait items implemented, missing: `drop` [E0046] + fn drop(&pin mut self) {} + //~^ ERROR method `drop` is not a member of trait `HasPinnedDropReceiver` [E0407] +} + +struct Inherent; + +impl Inherent { + fn drop(&pin mut self) {} +} + +mod local_drop_trait { + use std::pin::Pin; + + struct S; + + trait Drop { + fn pin_drop(self: Pin<&mut Self>); + } + + impl Drop for S { + //~^ ERROR not all trait items implemented, missing: `pin_drop` [E0046] + fn drop(&pin mut self) {} + //~^ ERROR method `drop` with `&pin mut self` is only supported for the `Drop` trait + } +} + +fn main() {} diff --git a/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.stderr b/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.stderr new file mode 100644 index 0000000000000..2238abea2484d --- /dev/null +++ b/tests/ui/pin-ergonomics/pinned-drop-sugar-not-other-traits.stderr @@ -0,0 +1,70 @@ +error[E0407]: method `drop` is not a member of trait `HasDrop` + --> $DIR/pinned-drop-sugar-not-other-traits.rs:26:5 + | +LL | fn drop(&pin mut self) {} + | ^^^----^^^^^^^^^^^^^^^^^^ + | | | + | | help: there is an associated function with a similar name: `drop` + | not a member of trait `HasDrop` + +error[E0407]: method `drop` is not a member of trait `HasPinnedDropReceiver` + --> $DIR/pinned-drop-sugar-not-other-traits.rs:36:5 + | +LL | fn drop(&pin mut self) {} + | ^^^----^^^^^^^^^^^^^^^^^^ + | | | + | | help: there is an associated function with a similar name: `drop` + | not a member of trait `HasPinnedDropReceiver` + +error: method `drop` with `&pin mut self` is only supported for the `Drop` trait + --> $DIR/pinned-drop-sugar-not-other-traits.rs:16:5 + | +LL | fn drop(&pin mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a `Drop::pin_drop` implementation + +error: method `drop` with `&pin mut self` is only supported for the `Drop` trait + --> $DIR/pinned-drop-sugar-not-other-traits.rs:57:9 + | +LL | fn drop(&pin mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a `Drop::pin_drop` implementation + +error[E0046]: not all trait items implemented, missing: `pin_drop` + --> $DIR/pinned-drop-sugar-not-other-traits.rs:14:1 + | +LL | fn pin_drop(self: Pin<&mut Self>); + | ---------------------------------- `pin_drop` from trait +... +LL | impl NeedsPinDrop for S { + | ^^^^^^^^^^^^^^^^^^^^^^^ missing `pin_drop` in implementation + +error[E0046]: not all trait items implemented, missing: `drop` + --> $DIR/pinned-drop-sugar-not-other-traits.rs:24:1 + | +LL | fn drop(self: Pin<&mut Self>); + | ------------------------------ `drop` from trait +... +LL | impl HasDrop for S { + | ^^^^^^^^^^^^^^^^^^ missing `drop` in implementation + +error[E0046]: not all trait items implemented, missing: `drop` + --> $DIR/pinned-drop-sugar-not-other-traits.rs:34:1 + | +LL | fn drop(self: &pin mut Self); + | ----------------------------- `drop` from trait +... +LL | impl HasPinnedDropReceiver for S { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `drop` in implementation + +error[E0046]: not all trait items implemented, missing: `pin_drop` + --> $DIR/pinned-drop-sugar-not-other-traits.rs:55:5 + | +LL | fn pin_drop(self: Pin<&mut Self>); + | ---------------------------------- `pin_drop` from trait +... +LL | impl Drop for S { + | ^^^^^^^^^^^^^^^ missing `pin_drop` in implementation + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0046, E0407. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/pin-ergonomics/pinned-drop-sugar.rs b/tests/ui/pin-ergonomics/pinned-drop-sugar.rs new file mode 100644 index 0000000000000..11c940d2e2dff --- /dev/null +++ b/tests/ui/pin-ergonomics/pinned-drop-sugar.rs @@ -0,0 +1,31 @@ +//@ check-pass +//@ edition:2024 + +#![feature(pin_ergonomics)] +#![allow(incomplete_features)] + +struct Unpinned; + +#[pin_v2] +struct Pinned; + +struct Qualified; +struct CoreQualified; + +impl Drop for Unpinned { + fn drop(&pin mut self) {} +} + +impl Drop for Pinned { + fn drop(&pin mut self) {} +} + +impl std::ops::Drop for Qualified { + fn drop(&pin mut self) {} +} + +impl core::ops::Drop for CoreQualified { + fn drop(&pin mut self) {} +} + +fn main() {}