Skip to content

Commit bd146c7

Browse files
Explicitly reject negative and reservation drop impls
1 parent 6ce2273 commit bd146c7

File tree

10 files changed

+74
-28
lines changed

10 files changed

+74
-28
lines changed

compiler/rustc_hir_analysis/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,7 @@ hir_analysis_const_specialize = cannot specialize on const impl with non-const i
276276
hir_analysis_static_specialize = cannot specialize on `'static` lifetime
277277
278278
hir_analysis_missing_tilde_const = missing `~const` qualifier for specialization
279+
280+
hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
281+
282+
hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported

compiler/rustc_hir_analysis/src/check/dropck.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
// FIXME(@lcnr): Move this module out of `rustc_hir_analysis`.
22
//
33
// We don't do any drop checking during hir typeck.
4-
use crate::hir::def_id::{DefId, LocalDefId};
54
use rustc_errors::{struct_span_err, ErrorGuaranteed};
65
use rustc_middle::ty::error::TypeError;
76
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
87
use rustc_middle::ty::subst::SubstsRef;
98
use rustc_middle::ty::util::IgnoreRegions;
109
use rustc_middle::ty::{self, Predicate, Ty, TyCtxt};
1110

11+
use crate::errors;
12+
use crate::hir::def_id::{DefId, LocalDefId};
13+
1214
/// This function confirms that the `Drop` implementation identified by
1315
/// `drop_impl_did` is not any more specialized than the type it is
1416
/// attached to (Issue #8142).
@@ -27,6 +29,19 @@ use rustc_middle::ty::{self, Predicate, Ty, TyCtxt};
2729
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
2830
///
2931
pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorGuaranteed> {
32+
match tcx.impl_polarity(drop_impl_did) {
33+
ty::ImplPolarity::Positive => {}
34+
ty::ImplPolarity::Negative => {
35+
return Err(tcx.sess.emit_err(errors::DropImplPolarity::Negative {
36+
span: tcx.def_span(drop_impl_did),
37+
}));
38+
}
39+
ty::ImplPolarity::Reservation => {
40+
return Err(tcx.sess.emit_err(errors::DropImplPolarity::Reservation {
41+
span: tcx.def_span(drop_impl_did),
42+
}));
43+
}
44+
}
3045
let dtor_self_type = tcx.type_of(drop_impl_did).subst_identity();
3146
let dtor_predicates = tcx.predicates_of(drop_impl_did);
3247
match dtor_self_type.kind() {

compiler/rustc_hir_analysis/src/errors.rs

+14
Original file line numberDiff line numberDiff line change
@@ -815,3 +815,17 @@ pub(crate) struct MissingTildeConst {
815815
#[primary_span]
816816
pub span: Span,
817817
}
818+
819+
#[derive(Diagnostic)]
820+
pub(crate) enum DropImplPolarity {
821+
#[diag(hir_analysis_drop_impl_negative)]
822+
Negative {
823+
#[primary_span]
824+
span: Span,
825+
},
826+
#[diag(hir_analysis_drop_impl_reservation)]
827+
Reservation {
828+
#[primary_span]
829+
span: Span,
830+
},
831+
}

compiler/rustc_middle/src/ty/util.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -360,16 +360,16 @@ impl<'tcx> TyCtxt<'tcx> {
360360
let ty = self.type_of(adt_did).subst_identity();
361361
let mut dtor_candidate = None;
362362
self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
363-
let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
364-
self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function");
365-
return;
366-
};
367-
368363
if validate(self, impl_did).is_err() {
369364
// Already `ErrorGuaranteed`, no need to delay a span bug here.
370365
return;
371366
}
372367

368+
let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
369+
self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function");
370+
return;
371+
};
372+
373373
if let Some((old_item_id, _)) = dtor_candidate {
374374
self.sess
375375
.struct_span_err(self.def_span(item_id), "multiple drop impls found")

tests/ui/consts/const-block-const-bound.rs

-6
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,9 @@ impl Drop for UnconstDrop {
1111
fn drop(&mut self) {}
1212
}
1313

14-
struct NonDrop;
15-
16-
impl !Drop for NonDrop {}
17-
1814
fn main() {
1915
const {
2016
f(UnconstDrop);
2117
//~^ ERROR can't drop
22-
f(NonDrop);
23-
//~^ ERROR can't drop
2418
}
2519
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: can't drop `UnconstDrop` in const contexts
2-
--> $DIR/const-block-const-bound.rs:20:9
2+
--> $DIR/const-block-const-bound.rs:16:9
33
|
44
LL | f(UnconstDrop);
55
| ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `UnconstDrop`
@@ -12,20 +12,6 @@ LL | &f(UnconstDrop);
1212
LL | &mut f(UnconstDrop);
1313
| ++++
1414

15-
error[E0277]: can't drop `NonDrop` in const contexts
16-
--> $DIR/const-block-const-bound.rs:22:9
17-
|
18-
LL | f(NonDrop);
19-
| ^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonDrop`
20-
|
21-
= note: the trait bound `NonDrop: ~const Destruct` is not satisfied
22-
help: consider borrowing here
23-
|
24-
LL | &f(NonDrop);
25-
| +
26-
LL | &mut f(NonDrop);
27-
| ++++
28-
29-
error: aborting due to 2 previous errors
15+
error: aborting due to previous error
3016

3117
For more information about this error, try `rustc --explain E0277`.

tests/ui/dropck/negative.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![feature(negative_impls)]
2+
3+
struct NonDrop;
4+
impl !Drop for NonDrop {}
5+
//~^ ERROR negative `Drop` impls are not supported
6+
7+
fn main() {}

tests/ui/dropck/negative.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: negative `Drop` impls are not supported
2+
--> $DIR/negative.rs:4:1
3+
|
4+
LL | impl !Drop for NonDrop {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+

tests/ui/dropck/reservation.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![feature(rustc_attrs)]
2+
3+
struct ReservedDrop;
4+
#[rustc_reservation_impl = "message"]
5+
impl Drop for ReservedDrop {
6+
//~^ ERROR reservation `Drop` impls are not supported
7+
fn drop(&mut self) {}
8+
}
9+
10+
fn main() {}

tests/ui/dropck/reservation.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: reservation `Drop` impls are not supported
2+
--> $DIR/reservation.rs:5:1
3+
|
4+
LL | impl Drop for ReservedDrop {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+

0 commit comments

Comments
 (0)