Explicitly reject negative and reservation drop impls

This commit is contained in:
Michael Goulet 2023-04-26 18:22:32 +00:00
parent 6ce22733b9
commit bd146c72ac
10 changed files with 74 additions and 28 deletions

View file

@ -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

View file

@ -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::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 @@
/// 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() {

View file

@ -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,
},
}

View file

@ -360,16 +360,16 @@ pub fn calculate_dtor(
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")

View file

@ -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
}
}

View file

@ -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`.

View file

@ -0,0 +1,7 @@
#![feature(negative_impls)]
struct NonDrop;
impl !Drop for NonDrop {}
//~^ ERROR negative `Drop` impls are not supported
fn main() {}

View file

@ -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

View file

@ -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() {}

View file

@ -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