Skip to content

Commit

Permalink
Rollup merge of #110859 - compiler-errors:no-negative-drop-impls, r=o…
Browse files Browse the repository at this point in the history
…li-obk

Explicitly reject negative and reservation drop impls

Fixes #110858

It doesn't really make sense for a type to have a `!Drop` impl. Or at least, I don't want us to implicitly assign a meaning to it by the way the compiler *currently* handles it (incompletely), and rather I would like to see a PR (or an RFC...) assign a meaning to `!Drop` if we actually wanted one for it.
  • Loading branch information
matthiaskrgr authored May 4, 2023
2 parents 129195f + bd146c7 commit 6fca1a9
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 28 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -280,3 +280,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
17 changes: 16 additions & 1 deletion compiler/rustc_hir_analysis/src/check/dropck.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
// 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};
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).
Expand All @@ -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() {
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -823,3 +823,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,
},
}
10 changes: 5 additions & 5 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
6 changes: 0 additions & 6 deletions tests/ui/consts/const-block-const-bound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
18 changes: 2 additions & 16 deletions tests/ui/consts/const-block-const-bound.stderr
Original file line number Diff line number Diff line change
@@ -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`
Expand All @@ -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`.
7 changes: 7 additions & 0 deletions tests/ui/dropck/negative.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#![feature(negative_impls)]

struct NonDrop;
impl !Drop for NonDrop {}
//~^ ERROR negative `Drop` impls are not supported

fn main() {}
8 changes: 8 additions & 0 deletions tests/ui/dropck/negative.stderr
Original file line number Diff line number Diff line change
@@ -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

10 changes: 10 additions & 0 deletions tests/ui/dropck/reservation.rs
Original file line number Diff line number Diff line change
@@ -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() {}
8 changes: 8 additions & 0 deletions tests/ui/dropck/reservation.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 6fca1a9

Please sign in to comment.