Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explicitly reject negative and reservation drop impls #110859

Merged
merged 1 commit into from
May 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
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 @@ -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,
},
}
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