From 9308e4cf45656313c67e57e602f92dc2ea26ce26 Mon Sep 17 00:00:00 2001 From: Devin Jeanpierre Date: Thu, 8 Sep 2022 03:12:18 +0000 Subject: [PATCH 1/8] Add the `#[manually_drop]` attribute. This attribute is equivalent to `#[lang = "manually_drop"]`, and the behavior of both are extended to allow the type to define `Drop`, in which case, that will still be run. Only the field drop glue is suppressed. This PR should essentially fully implement #100344. Some additional notes: `#[manually_drop]` means "do not destroy the fields automatically during destruction". `ManuallyDrop`, is (or could be) "just" `#[manually_drop] struct ManuallyDrop(T);`. The intent is, per the MCP, to allow customization of the drop order, without making the interface for initializing or accessing the fields of the struct clumsier than a normal Rust type. It also -- and people did seem excited about this part -- lifts `ManuallyDrop` from being a special language supported feature to just another user of `#[manually_drop]`. There is the question of how this interacts with "insignificant" drop. I had trouble understanding the comments, but insignificant drop appears to just be a static analysis tool, and not something that changes behavior. (For example, it's used to detect if a language change will reorder drops in a meaningful way -- meaning, reorder the significant drops, not the insignificant ones.) Since it's unlikely to be used for `#[manually_drop]` types, I don't think it matters a whole lot. And where a destructor is defined, it would seem to make sense for `#[manually_drop]` types to match exactly the behavior of `union`, since they both have the shared property that field drop glue is suppressed. I looked for all locations that queried for `is_manually_drop` in any form, and found two difficult cases which are hardcoded for `ManuallyDrop` in particular. The first is a clippy lint for redundant clones. I don't understand why it special-cases `ManuallyDrop`, and it's almost certainly wrong for it to special-case `#[manually_drop]` types in general. However, without understanding the original rationale, I have trouble figuring the right fix. Perhaps it should simply be deleted altogether. The second is unions -- specifically, the logic for disabling `DerefMut`. `my_union.x.y = z` will automatically dereference `my_union.x` if it implements `DerefMut`, unless it is `ManuallyDrop`, in which case it will not. This is because `ManuallyDrop` is a pointer back to its content, and so this will automatically call `drop` on a probably uninitialized field, and is unsafe. This is true of `ManuallyDrop`, but not necessarily any other `#[manually_drop]` type. I believe the correct fix would, instead, be a way to mark and detect types which are a smart pointer whose pointee is within `self`. See, for example, this playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=76fb22a6214ce453538fc18ec35a839d But that needs to wait for a separate RFC. For now, we apply exactly the same restriction for `ManuallyDrop` and for any other `#[manually_drop]` type, even though it may be confusing. 1. Delete `#[lang = "manually_drop"]`. I'm not sure if anything special needs to be done here other than replacing it with `#[manually_drop]` -- is there a compatibility guarantee that must be upheld? 2. (Optional) Fix the redundant clone check to correctly handle `#[manually_drop]` structs that aren't `ManuallyDrop`. 3. When there is more experience with the feature (e.g. in Crubit) create a full RFC based on the MCP, and go through the remainder of the stabilization process. (Also, do things like generalize the union error messages to not specifically mention `ManuallyDrop`, but also mention `#[manually_drop]`. For as long as the feature is unstable, the error messages would be confusing if they referenced it...) --- compiler/rustc_feature/src/active.rs | 2 + compiler/rustc_feature/src/builtin_attrs.rs | 4 + .../rustc_hir_analysis/src/check/check.rs | 6 +- compiler/rustc_hir_typeck/src/place_op.rs | 8 +- compiler/rustc_middle/src/ty/adt.rs | 2 +- .../rustc_mir_dataflow/src/elaborate_drops.rs | 3 +- compiler/rustc_passes/src/check_attr.rs | 13 +++ compiler/rustc_passes/src/errors.rs | 7 ++ compiler/rustc_span/src/symbol.rs | 1 + .../src/traits/query/dropck_outlives.rs | 5 +- compiler/rustc_ty_utils/src/needs_drop.rs | 8 +- .../language-features/manually-drop-attr.md | 36 +++++++++ .../feature-gate-manually_drop_attr.rs | 5 ++ .../feature-gate-manually_drop_attr.stderr | 12 +++ .../manually_drop-bad-item.rs | 8 ++ .../manually_drop-bad-item.stderr | 17 ++++ .../manually_drop-destructor.rs | 81 +++++++++++++++++++ .../manually_drop-dropck.rs | 38 +++++++++ .../manually_drop-dropck.stderr | 17 ++++ .../manually_drop-in-union.rs | 18 +++++ .../manually_drop-in-union.stderr | 15 ++++ .../manually_drop-nodestructor.rs | 59 ++++++++++++++ .../clippy_lints/src/redundant_clone.rs | 1 + tests/ui/union/union-deref.mirunsafeck.stderr | 12 +-- tests/ui/union/union-deref.rs | 12 +-- .../ui/union/union-deref.thirunsafeck.stderr | 12 +-- 26 files changed, 372 insertions(+), 30 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/manually-drop-attr.md create mode 100644 src/test/ui/manually_drop_attr/feature-gate-manually_drop_attr.rs create mode 100644 src/test/ui/manually_drop_attr/feature-gate-manually_drop_attr.stderr create mode 100644 src/test/ui/manually_drop_attr/manually_drop-bad-item.rs create mode 100644 src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr create mode 100644 src/test/ui/manually_drop_attr/manually_drop-destructor.rs create mode 100644 src/test/ui/manually_drop_attr/manually_drop-dropck.rs create mode 100644 src/test/ui/manually_drop_attr/manually_drop-dropck.stderr create mode 100644 src/test/ui/manually_drop_attr/manually_drop-in-union.rs create mode 100644 src/test/ui/manually_drop_attr/manually_drop-in-union.stderr create mode 100644 src/test/ui/manually_drop_attr/manually_drop-nodestructor.rs diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 323f5a368fc09..0466cbd803226 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -442,6 +442,8 @@ declare_features! ( (active, lint_reasons, "1.31.0", Some(54503), None), /// Give access to additional metadata about declarative macro meta-variables. (active, macro_metavar_expr, "1.61.0", Some(83527), None), + /// Allows `#[manually_drop]` on type definitions. + (active, manually_drop_attr, "1.64.0", Some(100344), None), /// Allows `#[marker]` on certain traits allowing overlapping implementations. (active, marker_trait_attr, "1.30.0", Some(29864), None), /// A minimal, sound subset of specialization intended to be used by the diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index af56a0b245987..6a57ae91318dc 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -480,6 +480,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ deprecated_safe, Normal, template!(List: r#"since = "version", note = "...""#), ErrorFollowing, experimental!(deprecated_safe), ), + // lang-team MCP 135 + gated!( + manually_drop, Normal, template!(Word), WarnFollowing, manually_drop_attr, experimental!(manually_drop), + ), // `#[collapse_debuginfo]` gated!( diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 47eace961be55..45327cc7e8050 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -112,8 +112,10 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b allowed_union_field(*elem, tcx, param_env) } _ => { - // Fallback case: allow `ManuallyDrop` and things that are `Copy`. - ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop()) + // Fallback case: if there is no destructor (including field drop glue), because it is + // `Copy` or is `#[manually_drop]` with no `Drop`, then allow it. + ty.ty_adt_def() + .is_some_and(|adt_def| adt_def.is_manually_drop() && !adt_def.has_dtor(tcx)) || ty.is_copy_modulo_regions(tcx, param_env) } } diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index ae0df5aa8f1cf..f0d8fc6c732f5 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -330,12 +330,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514). // This helps avoid accidental drops. + // + // FIXME: This is not correct for `#[manually_drop]` in general, only when the struct is + // a smart pointer whose pointee is at the same address, and whose pointee implements `Drop`. + // Instead of checking for `#[manually_drop]`, this should likely be a more restricted check + // for such types, or else union really should special-case and only permit `ManuallyDrop`, and + // not `#[manually_drop]` types in general. if inside_union && source.ty_adt_def().map_or(false, |adt| adt.is_manually_drop()) { let mut err = self.tcx.sess.struct_span_err( expr.span, - "not automatically applying `DerefMut` on `ManuallyDrop` union field", + "not automatically applying `DerefMut` on manually dropped union field", ); err.help( "writing to this reference calls the destructor for the old value", diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 099a784511827..8799b6b03e887 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -241,7 +241,7 @@ impl AdtDefData { if Some(did) == tcx.lang_items().owned_box() { flags |= AdtFlags::IS_BOX; } - if Some(did) == tcx.lang_items().manually_drop() { + if Some(did) == tcx.lang_items().manually_drop() || tcx.has_attr(did, sym::manually_drop) { flags |= AdtFlags::IS_MANUALLY_DROP; } if Some(did) == tcx.lang_items().unsafe_cell_type() { diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 7836ae2e7b76f..e3757e88a12c9 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -443,8 +443,7 @@ where }); } - let skip_contents = - adt.is_union() || Some(adt.did()) == self.tcx().lang_items().manually_drop(); + let skip_contents = adt.is_union() || adt.is_manually_drop(); let contents_drop = if skip_contents { (self.succ, self.unwind) } else { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 238ec9ca30f70..3aba5b1e4b6d2 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -193,6 +193,7 @@ impl CheckAttrVisitor<'_> { sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target), sym::deprecated => self.check_deprecated(hir_id, attr, span, target), sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target), + sym::manually_drop => self.check_manually_drop(hir_id, attr, span, target), sym::path => self.check_generic_attr(hir_id, attr, target, Target::Mod), sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target), sym::macro_export => self.check_macro_export(hir_id, attr, target), @@ -2091,6 +2092,17 @@ impl CheckAttrVisitor<'_> { } } + fn check_manually_drop(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { + if !matches!(target, Target::Struct | Target::Enum) { + self.tcx.emit_spanned_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::ManuallyDropShouldBeAppliedToStructEnum { defn_span: span }, + ); + } + } + fn check_plugin_registrar(&self, hir_id: HirId, attr: &Attribute, target: Target) { if target != Target::Fn { self.tcx.emit_spanned_lint( @@ -2370,6 +2382,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { sym::rustc_main, sym::unix_sigpipe, sym::derive, + sym::manually_drop, sym::test, sym::test_case, sym::global_allocator, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 68b098e3457b7..58ed983862b50 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -639,6 +639,13 @@ pub struct MacroUse { pub name: Symbol, } +#[derive(LintDiagnostic)] +#[diag(passes_should_be_applied_to_struct_enum)] +pub struct ManuallyDropShouldBeAppliedToStructEnum { + #[label] + pub defn_span: Span, +} + #[derive(LintDiagnostic)] #[diag(passes_macro_export)] pub struct MacroExport; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f1119214be44d..0637660b106e8 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -902,6 +902,7 @@ symbols! { main, managed_boxes, manually_drop, + manually_drop_attr, map, marker, marker_trait_attr, diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 455b53bfb7d8f..f33b2f493855a 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -49,8 +49,9 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { } ty::Adt(def, _) => { - if Some(def.did()) == tcx.lang_items().manually_drop() { - // `ManuallyDrop` never has a dtor. + if def.is_manually_drop() && !def.has_dtor(tcx) { + // A `#[manually_drop]` type without a Drop impl (e.g. `ManuallyDrop`) + // does not run any code at all when dropped. true } else { // Other types might. Moreover, PhantomData doesn't diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index cd1475391a4d9..3b744083707e0 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -219,10 +219,7 @@ fn drop_tys_helper<'tcx>( } let adt_components = move |adt_def: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>| { - if adt_def.is_manually_drop() { - debug!("drop_tys_helper: `{:?}` is manually drop", adt_def); - Ok(Vec::new()) - } else if let Some(dtor_info) = adt_has_dtor(adt_def) { + if let Some(dtor_info) = adt_has_dtor(adt_def) { match dtor_info { DtorType::Significant => { debug!("drop_tys_helper: `{:?}` implements `Drop`", adt_def); @@ -237,6 +234,9 @@ fn drop_tys_helper<'tcx>( Ok(substs.types().collect()) } } + } else if adt_def.is_manually_drop() { + debug!("drop_tys_helper: `{:?}` is manually drop", adt_def); + Ok(Vec::new()) } else if adt_def.is_union() { debug!("drop_tys_helper: `{:?}` is a union", adt_def); Ok(Vec::new()) diff --git a/src/doc/unstable-book/src/language-features/manually-drop-attr.md b/src/doc/unstable-book/src/language-features/manually-drop-attr.md new file mode 100644 index 0000000000000..602240d8d3569 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/manually-drop-attr.md @@ -0,0 +1,36 @@ +# `manually_drop_attr` + +The tracking issue for this feature is: [#100344] + +[#100344]: https://github.com/rust-lang/rust/issues/100344 + +The `manually_drop_attr` feature enables the `#[manually_drop]` attribute, which disables the drop glue for the type it is applied to. + +For example, `std::mem::ManuallyDrop` is implemented as follows: + +```rs +#[manually_drop] +struct ManuallyDrop(T); +``` + +But you can also use the attribute to change the order in which fields are dropped, by overriding `Drop`: + +```rs +/// This struct changes the order in which `x` and `y` are dropped from the default. +#[manually_drop] +struct MyStruct { + x: String, + y: String, +} + +impl Drop for MyStruct { + fn drop(&mut self) { + unsafe { + std::ptr::drop_in_place(&mut self.y); + std::ptr::drop_in_place(&mut self.x); + } + } +} +``` + +This can be useful in combination with `repr(C)`, to decouple the layout from the destruction order. See MCP [#135](https://github.com/rust-lang/lang-team/issues/135). diff --git a/src/test/ui/manually_drop_attr/feature-gate-manually_drop_attr.rs b/src/test/ui/manually_drop_attr/feature-gate-manually_drop_attr.rs new file mode 100644 index 0000000000000..835921ac6af9b --- /dev/null +++ b/src/test/ui/manually_drop_attr/feature-gate-manually_drop_attr.rs @@ -0,0 +1,5 @@ +#[manually_drop] +//~^ ERROR the `#[manually_drop]` attribute is an experimental feature +struct Foo {} + +fn main() {} diff --git a/src/test/ui/manually_drop_attr/feature-gate-manually_drop_attr.stderr b/src/test/ui/manually_drop_attr/feature-gate-manually_drop_attr.stderr new file mode 100644 index 0000000000000..e105179cb2743 --- /dev/null +++ b/src/test/ui/manually_drop_attr/feature-gate-manually_drop_attr.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[manually_drop]` attribute is an experimental feature + --> $DIR/feature-gate-manually_drop_attr.rs:1:1 + | +LL | #[manually_drop] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #100344 for more information + = help: add `#![feature(manually_drop_attr)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/manually_drop_attr/manually_drop-bad-item.rs b/src/test/ui/manually_drop_attr/manually_drop-bad-item.rs new file mode 100644 index 0000000000000..57ce6433a063b --- /dev/null +++ b/src/test/ui/manually_drop_attr/manually_drop-bad-item.rs @@ -0,0 +1,8 @@ +#![feature(manually_drop_attr)] +#![forbid(unused_attributes)] + +#[manually_drop] +//~^ ERROR attribute should be applied to a struct or enum +fn foo() {} + +fn main() {} diff --git a/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr b/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr new file mode 100644 index 0000000000000..0fc702dbda6d3 --- /dev/null +++ b/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr @@ -0,0 +1,17 @@ +error: attribute should be applied to a struct or enum + --> $DIR/manually_drop-bad-item.rs:4:1 + | +LL | #[manually_drop] + | ^^^^^^^^^^^^^^^^ +LL | +LL | fn foo() {} + | ----------- not a struct or enum + | +note: the lint level is defined here + --> $DIR/manually_drop-bad-item.rs:2:11 + | +LL | #![forbid(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/manually_drop_attr/manually_drop-destructor.rs b/src/test/ui/manually_drop_attr/manually_drop-destructor.rs new file mode 100644 index 0000000000000..33721673b5f49 --- /dev/null +++ b/src/test/ui/manually_drop_attr/manually_drop-destructor.rs @@ -0,0 +1,81 @@ +//! A test of `#[manually_drop]` on a type that *does* have a `Drop` impl. +//! +//! The mirror image of `manually_drop-nodestructor.rs` +#![feature(manually_drop_attr)] +// run-pass +extern crate core; +use core::cell::Cell; + +struct DropCounter<'a>(&'a Cell); +impl<'a> Drop for DropCounter<'a> { + fn drop(&mut self) { + self.0.set(self.0.get() + 1); + } +} + +#[manually_drop] +struct ManuallyDropped<'a> { + field_1: DropCounter<'a>, + field_2: DropCounter<'a>, +} + +impl<'a> Drop for ManuallyDropped<'a> { + fn drop(&mut self) { + // just do a LITTLE dropping. + unsafe { + core::ptr::drop_in_place(&mut self.field_1) + } + } +} + +#[manually_drop] +enum ManuallyDroppedEnum<'a> { + A(DropCounter<'a>, DropCounter<'a>), +} + +impl<'a> Drop for ManuallyDroppedEnum<'a> { + fn drop(&mut self) { + // just do a LITTLE dropping. + let ManuallyDroppedEnum::A(a, _) = self; + unsafe { + core::ptr::drop_in_place(a); + } + } +} + +/// Dropping a `#[manually_drop]` struct does not implicitly drop its fields. +/// +/// (Though it does run `Drop`, which can choose to drop them explicitly.) +fn test_destruction() { + let counter = Cell::new(0); + core::mem::drop(ManuallyDropped { + field_1: DropCounter(&counter), + field_2: DropCounter(&counter), + }); + // We only run the drop specifically requested in the Drop impl. + assert_eq!(counter.get(), 1); + assert!(core::mem::needs_drop::()); + + core::mem::drop(ManuallyDroppedEnum::A(DropCounter(&counter), DropCounter(&counter))); + assert_eq!(counter.get(), 2); + assert!(core::mem::needs_drop::()); + +} + +/// Assignment does still drop the fields. +fn test_assignment() { + let counter = Cell::new(0); + let mut manually_dropped = ManuallyDropped { + field_1: DropCounter(&counter), + field_2: DropCounter(&counter), + }; + assert_eq!(counter.get(), 0); + manually_dropped.field_1 = DropCounter(&counter); + manually_dropped.field_2 = DropCounter(&counter); + assert_eq!(counter.get(), 2); +} + +fn main() { + test_destruction(); + test_assignment(); +} diff --git a/src/test/ui/manually_drop_attr/manually_drop-dropck.rs b/src/test/ui/manually_drop_attr/manually_drop-dropck.rs new file mode 100644 index 0000000000000..95a108735564c --- /dev/null +++ b/src/test/ui/manually_drop_attr/manually_drop-dropck.rs @@ -0,0 +1,38 @@ +//! The drop checker only complains about a `#[manually_drop]` type if it _itself_ defines `Drop`. + +// FIXME: this does test dropck, does it also test needs_drop? + +#![feature(manually_drop_attr)] + + +// For example, this is absolutely fine: + +#[manually_drop] +struct ManuallyDrop(T); + +fn drop_out_of_order_ok(x: T) { + let mut manually_dropped = ManuallyDrop(None); + // x will be dropped before manually_dropped. + let x = x; + // ... but this is still fine, because it doesn't have logic on Drop. + manually_dropped.0 = Some(&x); +} + +// ... but this is not: + +#[manually_drop] +struct ManuallyDropWithDestructor(T); +impl Drop for ManuallyDropWithDestructor { + fn drop(&mut self) { + // maybe we read self.0 here! + } +} + +fn drop_out_of_order_not_ok(x: T) { + let mut manually_dropped_bad = ManuallyDropWithDestructor(None); + let x = x; + manually_dropped_bad.0 = Some(&x); + //~^ ERROR `x` does not live long enough +} + +fn main() {} diff --git a/src/test/ui/manually_drop_attr/manually_drop-dropck.stderr b/src/test/ui/manually_drop_attr/manually_drop-dropck.stderr new file mode 100644 index 0000000000000..39bd679cf207f --- /dev/null +++ b/src/test/ui/manually_drop_attr/manually_drop-dropck.stderr @@ -0,0 +1,17 @@ +error[E0597]: `x` does not live long enough + --> $DIR/manually_drop-dropck.rs:34:35 + | +LL | manually_dropped_bad.0 = Some(&x); + | ^^ borrowed value does not live long enough +LL | +LL | } + | - + | | + | `x` dropped here while still borrowed + | borrow might be used here, when `manually_dropped_bad` is dropped and runs the `Drop` code for type `ManuallyDropWithDestructor` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/manually_drop_attr/manually_drop-in-union.rs b/src/test/ui/manually_drop_attr/manually_drop-in-union.rs new file mode 100644 index 0000000000000..cd48d89c6ec37 --- /dev/null +++ b/src/test/ui/manually_drop_attr/manually_drop-in-union.rs @@ -0,0 +1,18 @@ +//! A `#[manually_drop]` type with a destructor is still not allowed inside a union! +#![feature(manually_drop_attr)] + +extern crate core; + +#[manually_drop] +struct ManuallyDropHasDrop; + +impl Drop for ManuallyDropHasDrop { + fn drop(&mut self) {} +} + +union MyUnion { + x: ManuallyDropHasDrop, + //~^ ERROR: unions cannot contain fields that may need dropping +} + +fn main() {} diff --git a/src/test/ui/manually_drop_attr/manually_drop-in-union.stderr b/src/test/ui/manually_drop_attr/manually_drop-in-union.stderr new file mode 100644 index 0000000000000..7c2ac50dee17e --- /dev/null +++ b/src/test/ui/manually_drop_attr/manually_drop-in-union.stderr @@ -0,0 +1,15 @@ +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/manually_drop-in-union.rs:14:5 + | +LL | x: ManuallyDropHasDrop, + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + | +LL | x: std::mem::ManuallyDrop, + | +++++++++++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0740`. diff --git a/src/test/ui/manually_drop_attr/manually_drop-nodestructor.rs b/src/test/ui/manually_drop_attr/manually_drop-nodestructor.rs new file mode 100644 index 0000000000000..e5af4e7e1b50a --- /dev/null +++ b/src/test/ui/manually_drop_attr/manually_drop-nodestructor.rs @@ -0,0 +1,59 @@ +//! A test of `#[manually_drop]` on a type that *doesn't* have a `Drop` impl. +//! +//! The mirror image of `manually_drop-destructor.rs` + +#![feature(manually_drop_attr)] +// run-pass +extern crate core; +use core::cell::Cell; + +struct DropCounter<'a>(&'a Cell); +impl<'a> Drop for DropCounter<'a> { + fn drop(&mut self) { + self.0.set(self.0.get() + 1); + } +} + +#[manually_drop] +struct ManuallyDropped<'a> { + field_1: DropCounter<'a>, + field_2: DropCounter<'a>, +} + +#[manually_drop] +enum ManuallyDroppedEnum<'a> { + A(DropCounter<'a>, DropCounter<'a>), +} + +/// Dropping a `#[manually_drop]` struct does not implicitly drop its fields. +fn test_destruction() { + let counter = Cell::new(0); + core::mem::drop(ManuallyDropped { + field_1: DropCounter(&counter), + field_2: DropCounter(&counter), + }); + assert_eq!(counter.get(), 0); + assert!(!core::mem::needs_drop::()); + + core::mem::drop(ManuallyDroppedEnum::A(DropCounter(&counter), DropCounter(&counter))); + assert_eq!(counter.get(), 0); + assert!(!core::mem::needs_drop::()); +} + +/// Assignment does still drop the fields. +fn test_assignment() { + let counter = Cell::new(0); + let mut manually_dropped = ManuallyDropped { + field_1: DropCounter(&counter), + field_2: DropCounter(&counter), + }; + assert_eq!(counter.get(), 0); + manually_dropped.field_1 = DropCounter(&counter); + manually_dropped.field_2 = DropCounter(&counter); + assert_eq!(counter.get(), 2); +} + +fn main() { + test_destruction(); + test_assignment(); +} diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index 944a33cc3e53f..81b6c26361783 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -112,6 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { } if let ty::Adt(def, _) = arg_ty.kind() { + // FIXME: This is not correct with `#[manually_drop]`, as that is just like any other type. if def.is_manually_drop() { continue; } diff --git a/tests/ui/union/union-deref.mirunsafeck.stderr b/tests/ui/union/union-deref.mirunsafeck.stderr index be5e60ab88a59..ce3571deb1c8b 100644 --- a/tests/ui/union/union-deref.mirunsafeck.stderr +++ b/tests/ui/union/union-deref.mirunsafeck.stderr @@ -1,4 +1,4 @@ -error: not automatically applying `DerefMut` on `ManuallyDrop` union field +error: not automatically applying `DerefMut` on manually dropped union field --> $DIR/union-deref.rs:16:14 | LL | unsafe { u.f.0 = Vec::new() }; @@ -7,7 +7,7 @@ LL | unsafe { u.f.0 = Vec::new() }; = help: writing to this reference calls the destructor for the old value = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor -error: not automatically applying `DerefMut` on `ManuallyDrop` union field +error: not automatically applying `DerefMut` on manually dropped union field --> $DIR/union-deref.rs:18:19 | LL | unsafe { &mut u.f.0 }; @@ -16,7 +16,7 @@ LL | unsafe { &mut u.f.0 }; = help: writing to this reference calls the destructor for the old value = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor -error: not automatically applying `DerefMut` on `ManuallyDrop` union field +error: not automatically applying `DerefMut` on manually dropped union field --> $DIR/union-deref.rs:20:14 | LL | unsafe { u.f.0.push(0) }; @@ -25,7 +25,7 @@ LL | unsafe { u.f.0.push(0) }; = help: writing to this reference calls the destructor for the old value = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor -error: not automatically applying `DerefMut` on `ManuallyDrop` union field +error: not automatically applying `DerefMut` on manually dropped union field --> $DIR/union-deref.rs:24:14 | LL | unsafe { u.f.0.0 = Vec::new() }; @@ -34,7 +34,7 @@ LL | unsafe { u.f.0.0 = Vec::new() }; = help: writing to this reference calls the destructor for the old value = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor -error: not automatically applying `DerefMut` on `ManuallyDrop` union field +error: not automatically applying `DerefMut` on manually dropped union field --> $DIR/union-deref.rs:26:19 | LL | unsafe { &mut u.f.0.0 }; @@ -43,7 +43,7 @@ LL | unsafe { &mut u.f.0.0 }; = help: writing to this reference calls the destructor for the old value = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor -error: not automatically applying `DerefMut` on `ManuallyDrop` union field +error: not automatically applying `DerefMut` on manually dropped union field --> $DIR/union-deref.rs:28:14 | LL | unsafe { u.f.0.0.push(0) }; diff --git a/tests/ui/union/union-deref.rs b/tests/ui/union/union-deref.rs index 5aa28d93f96ed..b8afc9793d921 100644 --- a/tests/ui/union/union-deref.rs +++ b/tests/ui/union/union-deref.rs @@ -13,17 +13,17 @@ union U2 { x:(), f: (ManuallyDrop<(T,)>,) } fn main() { let mut u : U1> = U1 { x: () }; unsafe { (*u.f).0 = Vec::new() }; // explicit deref, this compiles - unsafe { u.f.0 = Vec::new() }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field + unsafe { u.f.0 = Vec::new() }; //~ERROR not automatically applying `DerefMut` on manually dropped union field unsafe { &mut (*u.f).0 }; // explicit deref, this compiles - unsafe { &mut u.f.0 }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field + unsafe { &mut u.f.0 }; //~ERROR not automatically applying `DerefMut` on manually dropped union field unsafe { (*u.f).0.push(0) }; // explicit deref, this compiles - unsafe { u.f.0.push(0) }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field + unsafe { u.f.0.push(0) }; //~ERROR not automatically applying `DerefMut` on manually dropped union field let mut u : U2> = U2 { x: () }; unsafe { (*u.f.0).0 = Vec::new() }; // explicit deref, this compiles - unsafe { u.f.0.0 = Vec::new() }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field + unsafe { u.f.0.0 = Vec::new() }; //~ERROR not automatically applying `DerefMut` on manually dropped union field unsafe { &mut (*u.f.0).0 }; // explicit deref, this compiles - unsafe { &mut u.f.0.0 }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field + unsafe { &mut u.f.0.0 }; //~ERROR not automatically applying `DerefMut` on manually dropped union field unsafe { (*u.f.0).0.push(0) }; // explicit deref, this compiles - unsafe { u.f.0.0.push(0) }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field + unsafe { u.f.0.0.push(0) }; //~ERROR not automatically applying `DerefMut` on manually dropped union field } diff --git a/tests/ui/union/union-deref.thirunsafeck.stderr b/tests/ui/union/union-deref.thirunsafeck.stderr index be5e60ab88a59..ce3571deb1c8b 100644 --- a/tests/ui/union/union-deref.thirunsafeck.stderr +++ b/tests/ui/union/union-deref.thirunsafeck.stderr @@ -1,4 +1,4 @@ -error: not automatically applying `DerefMut` on `ManuallyDrop` union field +error: not automatically applying `DerefMut` on manually dropped union field --> $DIR/union-deref.rs:16:14 | LL | unsafe { u.f.0 = Vec::new() }; @@ -7,7 +7,7 @@ LL | unsafe { u.f.0 = Vec::new() }; = help: writing to this reference calls the destructor for the old value = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor -error: not automatically applying `DerefMut` on `ManuallyDrop` union field +error: not automatically applying `DerefMut` on manually dropped union field --> $DIR/union-deref.rs:18:19 | LL | unsafe { &mut u.f.0 }; @@ -16,7 +16,7 @@ LL | unsafe { &mut u.f.0 }; = help: writing to this reference calls the destructor for the old value = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor -error: not automatically applying `DerefMut` on `ManuallyDrop` union field +error: not automatically applying `DerefMut` on manually dropped union field --> $DIR/union-deref.rs:20:14 | LL | unsafe { u.f.0.push(0) }; @@ -25,7 +25,7 @@ LL | unsafe { u.f.0.push(0) }; = help: writing to this reference calls the destructor for the old value = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor -error: not automatically applying `DerefMut` on `ManuallyDrop` union field +error: not automatically applying `DerefMut` on manually dropped union field --> $DIR/union-deref.rs:24:14 | LL | unsafe { u.f.0.0 = Vec::new() }; @@ -34,7 +34,7 @@ LL | unsafe { u.f.0.0 = Vec::new() }; = help: writing to this reference calls the destructor for the old value = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor -error: not automatically applying `DerefMut` on `ManuallyDrop` union field +error: not automatically applying `DerefMut` on manually dropped union field --> $DIR/union-deref.rs:26:19 | LL | unsafe { &mut u.f.0.0 }; @@ -43,7 +43,7 @@ LL | unsafe { &mut u.f.0.0 }; = help: writing to this reference calls the destructor for the old value = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor -error: not automatically applying `DerefMut` on `ManuallyDrop` union field +error: not automatically applying `DerefMut` on manually dropped union field --> $DIR/union-deref.rs:28:14 | LL | unsafe { u.f.0.0.push(0) }; From fb064e3147f8e40c567f0780deaf3e3d65d7b416 Mon Sep 17 00:00:00 2001 From: Devin Jeanpierre Date: Mon, 14 Nov 2022 10:34:43 -0800 Subject: [PATCH 2/8] Replace manually_drop lang item with attribute. Co-authored-by: lcnr --- compiler/rustc_middle/src/ty/adt.rs | 2 +- library/core/src/lib.rs | 1 + library/core/src/mem/manually_drop.rs | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 8799b6b03e887..ce4d4743df698 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -241,7 +241,7 @@ impl AdtDefData { if Some(did) == tcx.lang_items().owned_box() { flags |= AdtFlags::IS_BOX; } - if Some(did) == tcx.lang_items().manually_drop() || tcx.has_attr(did, sym::manually_drop) { + if tcx.has_attr(did, sym::manually_drop) { flags |= AdtFlags::IS_MANUALLY_DROP; } if Some(did) == tcx.lang_items().unsafe_cell_type() { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index dc0702c467a4e..5784e30b253ed 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -214,6 +214,7 @@ #![feature(lang_items)] #![feature(link_llvm_intrinsics)] #![feature(macro_metavar_expr)] +#![cfg_attr(not(bootstrap), feature(manually_drop_attr))] #![feature(min_specialization)] #![feature(must_not_suspend)] #![feature(negative_impls)] diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 3d719afe49e4a..f5a9ad20c0aa0 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -44,7 +44,8 @@ use crate::ptr; /// [`mem::zeroed`]: crate::mem::zeroed /// [`MaybeUninit`]: crate::mem::MaybeUninit #[stable(feature = "manually_drop", since = "1.20.0")] -#[lang = "manually_drop"] +#[cfg_attr(bootstrap, lang = "manually_drop")] +#[cfg_attr(not(bootstrap), manually_drop)] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] pub struct ManuallyDrop { From 8090b3129863a68bbbd039c717626361303c301f Mon Sep 17 00:00:00 2001 From: Devin Jeanpierre Date: Mon, 14 Nov 2022 12:32:20 -0800 Subject: [PATCH 3/8] Improve error message for `#![manually_drop]` --- compiler/rustc_passes/src/check_attr.rs | 1 - .../manually_drop-bad-item.rs | 3 +++ .../manually_drop-bad-item.stderr | 21 +++++++++++++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3aba5b1e4b6d2..b086705c10019 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2382,7 +2382,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { sym::rustc_main, sym::unix_sigpipe, sym::derive, - sym::manually_drop, sym::test, sym::test_case, sym::global_allocator, diff --git a/src/test/ui/manually_drop_attr/manually_drop-bad-item.rs b/src/test/ui/manually_drop_attr/manually_drop-bad-item.rs index 57ce6433a063b..d52d7deda1d9e 100644 --- a/src/test/ui/manually_drop_attr/manually_drop-bad-item.rs +++ b/src/test/ui/manually_drop_attr/manually_drop-bad-item.rs @@ -1,5 +1,8 @@ #![feature(manually_drop_attr)] #![forbid(unused_attributes)] +#![manually_drop] +//~^ ERROR `manually_drop` attribute cannot be used at crate level +//~^^ ERROR attribute should be applied to a struct or enum #[manually_drop] //~^ ERROR attribute should be applied to a struct or enum diff --git a/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr b/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr index 0fc702dbda6d3..481cc51cde439 100644 --- a/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr +++ b/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr @@ -1,5 +1,5 @@ error: attribute should be applied to a struct or enum - --> $DIR/manually_drop-bad-item.rs:4:1 + --> $DIR/manually_drop-bad-item.rs:7:1 | LL | #[manually_drop] | ^^^^^^^^^^^^^^^^ @@ -13,5 +13,22 @@ note: the lint level is defined here LL | #![forbid(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: attribute should be applied to a struct or enum + --> $DIR/manually_drop-bad-item.rs:3:1 + | +LL | #![manually_drop] + | ^^^^^^^^^^^^^^^^^ + +error: `manually_drop` attribute cannot be used at crate level + --> $DIR/manually_drop-bad-item.rs:3:1 + | +LL | #![manually_drop] + | ^^^^^^^^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[manually_drop] + | + +error: aborting due to 3 previous errors From 8b0f5f8f6c989b93d9e0a5ee58217ffb59383401 Mon Sep 17 00:00:00 2001 From: Devin Jeanpierre Date: Tue, 15 Nov 2022 13:48:35 -0800 Subject: [PATCH 4/8] Fix bad-item tests, which I apparently forgot to do --- .../manually_drop_attr/manually_drop-bad-item.rs | 3 +-- .../manually_drop-bad-item.stderr | 15 ++------------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/test/ui/manually_drop_attr/manually_drop-bad-item.rs b/src/test/ui/manually_drop_attr/manually_drop-bad-item.rs index d52d7deda1d9e..502fc2862cf0e 100644 --- a/src/test/ui/manually_drop_attr/manually_drop-bad-item.rs +++ b/src/test/ui/manually_drop_attr/manually_drop-bad-item.rs @@ -1,8 +1,7 @@ #![feature(manually_drop_attr)] #![forbid(unused_attributes)] #![manually_drop] -//~^ ERROR `manually_drop` attribute cannot be used at crate level -//~^^ ERROR attribute should be applied to a struct or enum +//~^ ERROR attribute should be applied to a struct or enum #[manually_drop] //~^ ERROR attribute should be applied to a struct or enum diff --git a/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr b/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr index 481cc51cde439..ed4085934f5d5 100644 --- a/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr +++ b/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr @@ -1,5 +1,5 @@ error: attribute should be applied to a struct or enum - --> $DIR/manually_drop-bad-item.rs:7:1 + --> $DIR/manually_drop-bad-item.rs:6:1 | LL | #[manually_drop] | ^^^^^^^^^^^^^^^^ @@ -19,16 +19,5 @@ error: attribute should be applied to a struct or enum LL | #![manually_drop] | ^^^^^^^^^^^^^^^^^ -error: `manually_drop` attribute cannot be used at crate level - --> $DIR/manually_drop-bad-item.rs:3:1 - | -LL | #![manually_drop] - | ^^^^^^^^^^^^^^^^^ - | -help: perhaps you meant to use an outer attribute - | -LL | #[manually_drop] - | - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors From 89f4a86828bd75210960493f47c8190acee57ae7 Mon Sep 17 00:00:00 2001 From: Devin Jeanpierre Date: Tue, 15 Nov 2022 13:49:20 -0800 Subject: [PATCH 5/8] Add an enum variant per review comment --- .../manually_drop_attr/manually_drop-destructor.rs | 12 +++++++----- .../manually_drop_attr/manually_drop-nodestructor.rs | 7 ++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/test/ui/manually_drop_attr/manually_drop-destructor.rs b/src/test/ui/manually_drop_attr/manually_drop-destructor.rs index 33721673b5f49..a9138ebb70224 100644 --- a/src/test/ui/manually_drop_attr/manually_drop-destructor.rs +++ b/src/test/ui/manually_drop_attr/manually_drop-destructor.rs @@ -30,15 +30,17 @@ impl<'a> Drop for ManuallyDropped<'a> { #[manually_drop] enum ManuallyDroppedEnum<'a> { - A(DropCounter<'a>, DropCounter<'a>), + _A, + B(DropCounter<'a>, DropCounter<'a>), } impl<'a> Drop for ManuallyDroppedEnum<'a> { fn drop(&mut self) { // just do a LITTLE dropping. - let ManuallyDroppedEnum::A(a, _) = self; - unsafe { - core::ptr::drop_in_place(a); + if let ManuallyDroppedEnum::B(a, _) = self { + unsafe { + core::ptr::drop_in_place(a); + } } } } @@ -56,7 +58,7 @@ fn test_destruction() { assert_eq!(counter.get(), 1); assert!(core::mem::needs_drop::()); - core::mem::drop(ManuallyDroppedEnum::A(DropCounter(&counter), DropCounter(&counter))); + core::mem::drop(ManuallyDroppedEnum::B(DropCounter(&counter), DropCounter(&counter))); assert_eq!(counter.get(), 2); assert!(core::mem::needs_drop::()); diff --git a/src/test/ui/manually_drop_attr/manually_drop-nodestructor.rs b/src/test/ui/manually_drop_attr/manually_drop-nodestructor.rs index e5af4e7e1b50a..da0597f398455 100644 --- a/src/test/ui/manually_drop_attr/manually_drop-nodestructor.rs +++ b/src/test/ui/manually_drop_attr/manually_drop-nodestructor.rs @@ -22,10 +22,11 @@ struct ManuallyDropped<'a> { #[manually_drop] enum ManuallyDroppedEnum<'a> { - A(DropCounter<'a>, DropCounter<'a>), + _A, + B(DropCounter<'a>, DropCounter<'a>), } -/// Dropping a `#[manually_drop]` struct does not implicitly drop its fields. +/// Dropping a `#[manually_drop]` type does not implicitly drop its fields. fn test_destruction() { let counter = Cell::new(0); core::mem::drop(ManuallyDropped { @@ -35,7 +36,7 @@ fn test_destruction() { assert_eq!(counter.get(), 0); assert!(!core::mem::needs_drop::()); - core::mem::drop(ManuallyDroppedEnum::A(DropCounter(&counter), DropCounter(&counter))); + core::mem::drop(ManuallyDroppedEnum::B(DropCounter(&counter), DropCounter(&counter))); assert_eq!(counter.get(), 0); assert!(!core::mem::needs_drop::()); } From 8a23f4c737c5cfb893b7a25b683cafabe971a3e0 Mon Sep 17 00:00:00 2001 From: Devin Jeanpierre Date: Wed, 16 Nov 2022 14:54:00 -0800 Subject: [PATCH 6/8] Fix test. ... honestly, I'd thought I'd fixed this and tested before, this was my bad. All it took was `./x.py test src/test/ui --bless` :( --- src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr b/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr index ed4085934f5d5..890d45325ca57 100644 --- a/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr +++ b/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr @@ -17,7 +17,7 @@ error: attribute should be applied to a struct or enum --> $DIR/manually_drop-bad-item.rs:3:1 | LL | #![manually_drop] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ not a struct or enum error: aborting due to 2 previous errors From 8e01e2a0bb17dfb5c60575e9f2ab078b80ba2678 Mon Sep 17 00:00:00 2001 From: Devin Jeanpierre Date: Mon, 6 Feb 2023 14:26:45 -0800 Subject: [PATCH 7/8] Ah. Move tests into tests dir, and `--bless` them. --- .../ui/manually_drop_attr/feature-gate-manually_drop_attr.rs | 0 .../ui/manually_drop_attr/feature-gate-manually_drop_attr.stderr | 0 .../ui/manually_drop_attr/manually_drop-bad-item.rs | 0 .../ui/manually_drop_attr/manually_drop-bad-item.stderr | 0 .../ui/manually_drop_attr/manually_drop-destructor.rs | 0 {src/test => tests}/ui/manually_drop_attr/manually_drop-dropck.rs | 0 .../ui/manually_drop_attr/manually_drop-dropck.stderr | 0 .../ui/manually_drop_attr/manually_drop-in-union.rs | 0 .../ui/manually_drop_attr/manually_drop-in-union.stderr | 0 .../ui/manually_drop_attr/manually_drop-nodestructor.rs | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename {src/test => tests}/ui/manually_drop_attr/feature-gate-manually_drop_attr.rs (100%) rename {src/test => tests}/ui/manually_drop_attr/feature-gate-manually_drop_attr.stderr (100%) rename {src/test => tests}/ui/manually_drop_attr/manually_drop-bad-item.rs (100%) rename {src/test => tests}/ui/manually_drop_attr/manually_drop-bad-item.stderr (100%) rename {src/test => tests}/ui/manually_drop_attr/manually_drop-destructor.rs (100%) rename {src/test => tests}/ui/manually_drop_attr/manually_drop-dropck.rs (100%) rename {src/test => tests}/ui/manually_drop_attr/manually_drop-dropck.stderr (100%) rename {src/test => tests}/ui/manually_drop_attr/manually_drop-in-union.rs (100%) rename {src/test => tests}/ui/manually_drop_attr/manually_drop-in-union.stderr (100%) rename {src/test => tests}/ui/manually_drop_attr/manually_drop-nodestructor.rs (100%) diff --git a/src/test/ui/manually_drop_attr/feature-gate-manually_drop_attr.rs b/tests/ui/manually_drop_attr/feature-gate-manually_drop_attr.rs similarity index 100% rename from src/test/ui/manually_drop_attr/feature-gate-manually_drop_attr.rs rename to tests/ui/manually_drop_attr/feature-gate-manually_drop_attr.rs diff --git a/src/test/ui/manually_drop_attr/feature-gate-manually_drop_attr.stderr b/tests/ui/manually_drop_attr/feature-gate-manually_drop_attr.stderr similarity index 100% rename from src/test/ui/manually_drop_attr/feature-gate-manually_drop_attr.stderr rename to tests/ui/manually_drop_attr/feature-gate-manually_drop_attr.stderr diff --git a/src/test/ui/manually_drop_attr/manually_drop-bad-item.rs b/tests/ui/manually_drop_attr/manually_drop-bad-item.rs similarity index 100% rename from src/test/ui/manually_drop_attr/manually_drop-bad-item.rs rename to tests/ui/manually_drop_attr/manually_drop-bad-item.rs diff --git a/src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr b/tests/ui/manually_drop_attr/manually_drop-bad-item.stderr similarity index 100% rename from src/test/ui/manually_drop_attr/manually_drop-bad-item.stderr rename to tests/ui/manually_drop_attr/manually_drop-bad-item.stderr diff --git a/src/test/ui/manually_drop_attr/manually_drop-destructor.rs b/tests/ui/manually_drop_attr/manually_drop-destructor.rs similarity index 100% rename from src/test/ui/manually_drop_attr/manually_drop-destructor.rs rename to tests/ui/manually_drop_attr/manually_drop-destructor.rs diff --git a/src/test/ui/manually_drop_attr/manually_drop-dropck.rs b/tests/ui/manually_drop_attr/manually_drop-dropck.rs similarity index 100% rename from src/test/ui/manually_drop_attr/manually_drop-dropck.rs rename to tests/ui/manually_drop_attr/manually_drop-dropck.rs diff --git a/src/test/ui/manually_drop_attr/manually_drop-dropck.stderr b/tests/ui/manually_drop_attr/manually_drop-dropck.stderr similarity index 100% rename from src/test/ui/manually_drop_attr/manually_drop-dropck.stderr rename to tests/ui/manually_drop_attr/manually_drop-dropck.stderr diff --git a/src/test/ui/manually_drop_attr/manually_drop-in-union.rs b/tests/ui/manually_drop_attr/manually_drop-in-union.rs similarity index 100% rename from src/test/ui/manually_drop_attr/manually_drop-in-union.rs rename to tests/ui/manually_drop_attr/manually_drop-in-union.rs diff --git a/src/test/ui/manually_drop_attr/manually_drop-in-union.stderr b/tests/ui/manually_drop_attr/manually_drop-in-union.stderr similarity index 100% rename from src/test/ui/manually_drop_attr/manually_drop-in-union.stderr rename to tests/ui/manually_drop_attr/manually_drop-in-union.stderr diff --git a/src/test/ui/manually_drop_attr/manually_drop-nodestructor.rs b/tests/ui/manually_drop_attr/manually_drop-nodestructor.rs similarity index 100% rename from src/test/ui/manually_drop_attr/manually_drop-nodestructor.rs rename to tests/ui/manually_drop_attr/manually_drop-nodestructor.rs From 3468fac8d23ea394b8f9e4146118f9f625f8f3c0 Mon Sep 17 00:00:00 2001 From: Devin Jeanpierre Date: Tue, 7 Feb 2023 12:57:04 -0800 Subject: [PATCH 8/8] ... actually run git add... --- tests/ui/manually_drop_attr/manually_drop-dropck.stderr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ui/manually_drop_attr/manually_drop-dropck.stderr b/tests/ui/manually_drop_attr/manually_drop-dropck.stderr index 39bd679cf207f..52063baca6d08 100644 --- a/tests/ui/manually_drop_attr/manually_drop-dropck.stderr +++ b/tests/ui/manually_drop_attr/manually_drop-dropck.stderr @@ -1,6 +1,8 @@ error[E0597]: `x` does not live long enough --> $DIR/manually_drop-dropck.rs:34:35 | +LL | let x = x; + | - binding `x` declared here LL | manually_dropped_bad.0 = Some(&x); | ^^ borrowed value does not live long enough LL |