about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-04-26 18:22:32 +0000
committerMichael Goulet <michael@errs.io>2023-04-27 17:02:17 +0000
commitbd146c72ac2faf6bbf189ad92d06e0bcd6cc92fc (patch)
tree3dd93051ad801fdc2d4a61ee2944480f7c401772
parent6ce22733b973355573efd1e6294e585460e90e17 (diff)
downloadrust-bd146c72ac2faf6bbf189ad92d06e0bcd6cc92fc.tar.gz
rust-bd146c72ac2faf6bbf189ad92d06e0bcd6cc92fc.zip
Explicitly reject negative and reservation drop impls
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl4
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs17
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs14
-rw-r--r--compiler/rustc_middle/src/ty/util.rs10
-rw-r--r--tests/ui/consts/const-block-const-bound.rs6
-rw-r--r--tests/ui/consts/const-block-const-bound.stderr18
-rw-r--r--tests/ui/dropck/negative.rs7
-rw-r--r--tests/ui/dropck/negative.stderr8
-rw-r--r--tests/ui/dropck/reservation.rs10
-rw-r--r--tests/ui/dropck/reservation.stderr8
10 files changed, 74 insertions, 28 deletions
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 5d45d09797b..4c4af9b6908 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -276,3 +276,7 @@ hir_analysis_const_specialize = cannot specialize on const impl with non-const i
 hir_analysis_static_specialize = cannot specialize on `'static` lifetime
 
 hir_analysis_missing_tilde_const = missing `~const` qualifier for specialization
+
+hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
+
+hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 111bf5e5455..703e389a838 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -1,7 +1,6 @@
 // FIXME(@lcnr): Move this module out of `rustc_hir_analysis`.
 //
 // We don't do any drop checking during hir typeck.
-use crate::hir::def_id::{DefId, LocalDefId};
 use rustc_errors::{struct_span_err, ErrorGuaranteed};
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
@@ -9,6 +8,9 @@ use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::util::IgnoreRegions;
 use rustc_middle::ty::{self, Predicate, Ty, TyCtxt};
 
+use crate::errors;
+use crate::hir::def_id::{DefId, LocalDefId};
+
 /// This function confirms that the `Drop` implementation identified by
 /// `drop_impl_did` is not any more specialized than the type it is
 /// attached to (Issue #8142).
@@ -27,6 +29,19 @@ use rustc_middle::ty::{self, Predicate, Ty, TyCtxt};
 ///    cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
 ///
 pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorGuaranteed> {
+    match tcx.impl_polarity(drop_impl_did) {
+        ty::ImplPolarity::Positive => {}
+        ty::ImplPolarity::Negative => {
+            return Err(tcx.sess.emit_err(errors::DropImplPolarity::Negative {
+                span: tcx.def_span(drop_impl_did),
+            }));
+        }
+        ty::ImplPolarity::Reservation => {
+            return Err(tcx.sess.emit_err(errors::DropImplPolarity::Reservation {
+                span: tcx.def_span(drop_impl_did),
+            }));
+        }
+    }
     let dtor_self_type = tcx.type_of(drop_impl_did).subst_identity();
     let dtor_predicates = tcx.predicates_of(drop_impl_did);
     match dtor_self_type.kind() {
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index f82169dee98..ba3039272f5 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -815,3 +815,17 @@ pub(crate) struct MissingTildeConst {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+pub(crate) enum DropImplPolarity {
+    #[diag(hir_analysis_drop_impl_negative)]
+    Negative {
+        #[primary_span]
+        span: Span,
+    },
+    #[diag(hir_analysis_drop_impl_reservation)]
+    Reservation {
+        #[primary_span]
+        span: Span,
+    },
+}
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index c77985c6bd6..e5b2d342452 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -360,16 +360,16 @@ impl<'tcx> TyCtxt<'tcx> {
         let ty = self.type_of(adt_did).subst_identity();
         let mut dtor_candidate = None;
         self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
-            let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
-                self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function");
-                return;
-            };
-
             if validate(self, impl_did).is_err() {
                 // Already `ErrorGuaranteed`, no need to delay a span bug here.
                 return;
             }
 
+            let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
+                self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function");
+                return;
+            };
+
             if let Some((old_item_id, _)) = dtor_candidate {
                 self.sess
                     .struct_span_err(self.def_span(item_id), "multiple drop impls found")
diff --git a/tests/ui/consts/const-block-const-bound.rs b/tests/ui/consts/const-block-const-bound.rs
index 42aa0216b87..3704a1a5a39 100644
--- a/tests/ui/consts/const-block-const-bound.rs
+++ b/tests/ui/consts/const-block-const-bound.rs
@@ -11,15 +11,9 @@ impl Drop for UnconstDrop {
     fn drop(&mut self) {}
 }
 
-struct NonDrop;
-
-impl !Drop for NonDrop {}
-
 fn main() {
     const {
         f(UnconstDrop);
         //~^ ERROR can't drop
-        f(NonDrop);
-        //~^ ERROR can't drop
     }
 }
diff --git a/tests/ui/consts/const-block-const-bound.stderr b/tests/ui/consts/const-block-const-bound.stderr
index fef4914fad5..caf24e7afcf 100644
--- a/tests/ui/consts/const-block-const-bound.stderr
+++ b/tests/ui/consts/const-block-const-bound.stderr
@@ -1,5 +1,5 @@
 error[E0277]: can't drop `UnconstDrop` in const contexts
-  --> $DIR/const-block-const-bound.rs:20:9
+  --> $DIR/const-block-const-bound.rs:16:9
    |
 LL |         f(UnconstDrop);
    |         ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `UnconstDrop`
@@ -12,20 +12,6 @@ LL |         &f(UnconstDrop);
 LL |         &mut f(UnconstDrop);
    |         ++++
 
-error[E0277]: can't drop `NonDrop` in const contexts
-  --> $DIR/const-block-const-bound.rs:22:9
-   |
-LL |         f(NonDrop);
-   |         ^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonDrop`
-   |
-   = note: the trait bound `NonDrop: ~const Destruct` is not satisfied
-help: consider borrowing here
-   |
-LL |         &f(NonDrop);
-   |         +
-LL |         &mut f(NonDrop);
-   |         ++++
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/dropck/negative.rs b/tests/ui/dropck/negative.rs
new file mode 100644
index 00000000000..ae63632b55e
--- /dev/null
+++ b/tests/ui/dropck/negative.rs
@@ -0,0 +1,7 @@
+#![feature(negative_impls)]
+
+struct NonDrop;
+impl !Drop for NonDrop {}
+//~^ ERROR negative `Drop` impls are not supported
+
+fn main() {}
diff --git a/tests/ui/dropck/negative.stderr b/tests/ui/dropck/negative.stderr
new file mode 100644
index 00000000000..d613e30b5ea
--- /dev/null
+++ b/tests/ui/dropck/negative.stderr
@@ -0,0 +1,8 @@
+error: negative `Drop` impls are not supported
+  --> $DIR/negative.rs:4:1
+   |
+LL | impl !Drop for NonDrop {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/dropck/reservation.rs b/tests/ui/dropck/reservation.rs
new file mode 100644
index 00000000000..f7199d4ec44
--- /dev/null
+++ b/tests/ui/dropck/reservation.rs
@@ -0,0 +1,10 @@
+#![feature(rustc_attrs)]
+
+struct ReservedDrop;
+#[rustc_reservation_impl = "message"]
+impl Drop for ReservedDrop {
+//~^ ERROR reservation `Drop` impls are not supported
+    fn drop(&mut self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/dropck/reservation.stderr b/tests/ui/dropck/reservation.stderr
new file mode 100644
index 00000000000..19325d6ed44
--- /dev/null
+++ b/tests/ui/dropck/reservation.stderr
@@ -0,0 +1,8 @@
+error: reservation `Drop` impls are not supported
+  --> $DIR/reservation.rs:5:1
+   |
+LL | impl Drop for ReservedDrop {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+