Explicitly reject negative and reservation drop impls
This commit is contained in:
parent
6ce22733b9
commit
bd146c72ac
10 changed files with 74 additions and 28 deletions
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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`.
|
||||
|
|
7
tests/ui/dropck/negative.rs
Normal file
7
tests/ui/dropck/negative.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
#![feature(negative_impls)]
|
||||
|
||||
struct NonDrop;
|
||||
impl !Drop for NonDrop {}
|
||||
//~^ ERROR negative `Drop` impls are not supported
|
||||
|
||||
fn main() {}
|
8
tests/ui/dropck/negative.stderr
Normal file
8
tests/ui/dropck/negative.stderr
Normal 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
|
||||
|
10
tests/ui/dropck/reservation.rs
Normal file
10
tests/ui/dropck/reservation.rs
Normal 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() {}
|
8
tests/ui/dropck/reservation.stderr
Normal file
8
tests/ui/dropck/reservation.stderr
Normal 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
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue