mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
Reject implementing const Drop for types that are not const Destruct already
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::util::CheckRegions;
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypingMode};
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
|
||||
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
|
||||
@@ -65,6 +65,8 @@ pub(crate) fn check_drop_impl(
|
||||
adt_to_impl_args,
|
||||
)?;
|
||||
|
||||
ensure_all_fields_are_const_destruct(tcx, drop_impl_did, adt_def.did())?;
|
||||
|
||||
ensure_impl_predicates_are_implied_by_item_defn(
|
||||
tcx,
|
||||
drop_impl_did,
|
||||
@@ -173,6 +175,64 @@ fn ensure_impl_params_and_item_params_correspond<'tcx>(
|
||||
Err(err.emit())
|
||||
}
|
||||
|
||||
fn ensure_all_fields_are_const_destruct<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_def_id: LocalDefId,
|
||||
adt_def_id: DefId,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if !tcx.is_conditionally_const(impl_def_id) {
|
||||
return Ok(());
|
||||
}
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
let impl_span = tcx.def_span(impl_def_id.to_def_id());
|
||||
let env =
|
||||
ty::EarlyBinder::bind(tcx.param_env(impl_def_id)).instantiate_identity().skip_norm_wip();
|
||||
let args = ty::GenericArgs::identity_for_item(tcx, impl_def_id);
|
||||
let destruct_trait = tcx.lang_items().destruct_trait().unwrap();
|
||||
for field in tcx.adt_def(adt_def_id).all_fields() {
|
||||
let field_ty = field.ty(tcx, args);
|
||||
let cause = traits::ObligationCause::new(
|
||||
tcx.def_span(field.did),
|
||||
impl_def_id,
|
||||
ObligationCauseCode::Misc,
|
||||
);
|
||||
ocx.register_obligation(traits::Obligation::new(
|
||||
tcx,
|
||||
cause,
|
||||
env,
|
||||
ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
|
||||
trait_ref: ty::TraitRef::new(tcx, destruct_trait, [field_ty]),
|
||||
constness: ty::BoundConstness::Maybe,
|
||||
}),
|
||||
));
|
||||
}
|
||||
ocx.evaluate_obligations_error_on_ambiguity()
|
||||
.into_iter()
|
||||
.map(|error| {
|
||||
let ty::ClauseKind::HostEffect(eff) =
|
||||
error.root_obligation.predicate.expect_clause().kind().no_bound_vars().unwrap()
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
let field_ty = eff.trait_ref.self_ty();
|
||||
let diag = struct_span_code_err!(
|
||||
tcx.dcx(),
|
||||
error.root_obligation.cause.span,
|
||||
E0367,
|
||||
"`{field_ty}` does not implement `[const] Destruct`",
|
||||
)
|
||||
.with_span_note(impl_span, "required for this `Drop` impl");
|
||||
if field_ty.has_param() {
|
||||
// FIXME: suggest adding `[const] Destruct` by teaching
|
||||
// `suggest_restricting_param_bound` about const traits.
|
||||
}
|
||||
Err(diag.emit())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Confirms that all predicates defined on the `Drop` impl (`drop_impl_def_id`) are able to be
|
||||
/// proven from within `adt_def_id`'s environment. I.e. all the predicates on the impl are
|
||||
/// implied by the ADT being well formed.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_destruct)]
|
||||
//@ check-pass
|
||||
|
||||
use std::marker::Destruct;
|
||||
|
||||
@@ -11,12 +10,14 @@ fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
struct ConstDrop(NotConstDrop);
|
||||
//~^ ERROR: `NotConstDrop` does not implement `[const] Destruct`
|
||||
|
||||
impl const Drop for ConstDrop {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
struct ConstDrop2<T>(T);
|
||||
//~^ ERROR: `T` does not implement `[const] Destruct`
|
||||
|
||||
impl<T> const Drop for ConstDrop2<T> {
|
||||
fn drop(&mut self) {}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
error[E0367]: `NotConstDrop` does not implement `[const] Destruct`
|
||||
--> $DIR/drop-impl-nonconst-drop-field.rs:12:18
|
||||
|
|
||||
LL | struct ConstDrop(NotConstDrop);
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: required for this `Drop` impl
|
||||
--> $DIR/drop-impl-nonconst-drop-field.rs:15:1
|
||||
|
|
||||
LL | impl const Drop for ConstDrop {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0367]: `T` does not implement `[const] Destruct`
|
||||
--> $DIR/drop-impl-nonconst-drop-field.rs:19:22
|
||||
|
|
||||
LL | struct ConstDrop2<T>(T);
|
||||
| ^
|
||||
|
|
||||
note: required for this `Drop` impl
|
||||
--> $DIR/drop-impl-nonconst-drop-field.rs:22:1
|
||||
|
|
||||
LL | impl<T> const Drop for ConstDrop2<T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0367`.
|
||||
@@ -1,5 +1,17 @@
|
||||
error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct`
|
||||
--> $DIR/const-drop-fail.rs:19:30
|
||||
|
|
||||
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required for this `Drop` impl
|
||||
--> $DIR/const-drop-fail.rs:22:1
|
||||
|
|
||||
LL | impl const Drop for ConstImplWithDropGlue {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
|
||||
--> $DIR/const-drop-fail.rs:34:5
|
||||
--> $DIR/const-drop-fail.rs:35:5
|
||||
|
|
||||
LL | const _: () = check($exp);
|
||||
| ----- required by a bound introduced by this call
|
||||
@@ -8,13 +20,13 @@ LL | NonTrivialDrop,
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const-drop-fail.rs:25:19
|
||||
--> $DIR/const-drop-fail.rs:26:19
|
||||
|
|
||||
LL | const fn check<T: [const] Destruct>(_: T) {}
|
||||
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
|
||||
--> $DIR/const-drop-fail.rs:36:5
|
||||
--> $DIR/const-drop-fail.rs:37:5
|
||||
|
|
||||
LL | const _: () = check($exp);
|
||||
| ----- required by a bound introduced by this call
|
||||
@@ -23,11 +35,12 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const-drop-fail.rs:25:19
|
||||
--> $DIR/const-drop-fail.rs:26:19
|
||||
|
|
||||
LL | const fn check<T: [const] Destruct>(_: T) {}
|
||||
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
Some errors have detailed explanations: E0277, E0367.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct`
|
||||
--> $DIR/const-drop-fail.rs:19:30
|
||||
|
|
||||
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required for this `Drop` impl
|
||||
--> $DIR/const-drop-fail.rs:22:1
|
||||
|
|
||||
LL | impl const Drop for ConstImplWithDropGlue {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
|
||||
--> $DIR/const-drop-fail.rs:34:5
|
||||
--> $DIR/const-drop-fail.rs:35:5
|
||||
|
|
||||
LL | const _: () = check($exp);
|
||||
| ----- required by a bound introduced by this call
|
||||
@@ -8,13 +20,13 @@ LL | NonTrivialDrop,
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const-drop-fail.rs:25:19
|
||||
--> $DIR/const-drop-fail.rs:26:19
|
||||
|
|
||||
LL | const fn check<T: [const] Destruct>(_: T) {}
|
||||
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
|
||||
--> $DIR/const-drop-fail.rs:36:5
|
||||
--> $DIR/const-drop-fail.rs:37:5
|
||||
|
|
||||
LL | const _: () = check($exp);
|
||||
| ----- required by a bound introduced by this call
|
||||
@@ -23,11 +35,12 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const-drop-fail.rs:25:19
|
||||
--> $DIR/const-drop-fail.rs:26:19
|
||||
|
|
||||
LL | const fn check<T: [const] Destruct>(_: T) {}
|
||||
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
Some errors have detailed explanations: E0277, E0367.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct`
|
||||
--> $DIR/const-drop-fail.rs:19:30
|
||||
|
|
||||
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required for this `Drop` impl
|
||||
--> $DIR/const-drop-fail.rs:22:1
|
||||
|
|
||||
LL | impl const Drop for ConstImplWithDropGlue {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
|
||||
--> $DIR/const-drop-fail.rs:34:5
|
||||
--> $DIR/const-drop-fail.rs:35:5
|
||||
|
|
||||
LL | const _: () = check($exp);
|
||||
| ----- required by a bound introduced by this call
|
||||
@@ -8,13 +20,13 @@ LL | NonTrivialDrop,
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const-drop-fail.rs:25:19
|
||||
--> $DIR/const-drop-fail.rs:26:19
|
||||
|
|
||||
LL | const fn check<T: [const] Destruct>(_: T) {}
|
||||
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
|
||||
--> $DIR/const-drop-fail.rs:36:5
|
||||
--> $DIR/const-drop-fail.rs:37:5
|
||||
|
|
||||
LL | const _: () = check($exp);
|
||||
| ----- required by a bound introduced by this call
|
||||
@@ -23,11 +35,12 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const-drop-fail.rs:25:19
|
||||
--> $DIR/const-drop-fail.rs:26:19
|
||||
|
|
||||
LL | const fn check<T: [const] Destruct>(_: T) {}
|
||||
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
Some errors have detailed explanations: E0277, E0367.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct`
|
||||
--> $DIR/const-drop-fail.rs:19:30
|
||||
|
|
||||
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required for this `Drop` impl
|
||||
--> $DIR/const-drop-fail.rs:22:1
|
||||
|
|
||||
LL | impl const Drop for ConstImplWithDropGlue {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
|
||||
--> $DIR/const-drop-fail.rs:34:5
|
||||
--> $DIR/const-drop-fail.rs:35:5
|
||||
|
|
||||
LL | const _: () = check($exp);
|
||||
| ----- required by a bound introduced by this call
|
||||
@@ -8,13 +20,13 @@ LL | NonTrivialDrop,
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const-drop-fail.rs:25:19
|
||||
--> $DIR/const-drop-fail.rs:26:19
|
||||
|
|
||||
LL | const fn check<T: [const] Destruct>(_: T) {}
|
||||
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
|
||||
--> $DIR/const-drop-fail.rs:36:5
|
||||
--> $DIR/const-drop-fail.rs:37:5
|
||||
|
|
||||
LL | const _: () = check($exp);
|
||||
| ----- required by a bound introduced by this call
|
||||
@@ -23,11 +35,12 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const-drop-fail.rs:25:19
|
||||
--> $DIR/const-drop-fail.rs:26:19
|
||||
|
|
||||
LL | const fn check<T: [const] Destruct>(_: T) {}
|
||||
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
Some errors have detailed explanations: E0277, E0367.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
||||
@@ -17,6 +17,7 @@ fn drop(&mut self) {
|
||||
}
|
||||
|
||||
struct ConstImplWithDropGlue(NonTrivialDrop);
|
||||
//~^ ERROR: `NonTrivialDrop` does not implement `[const] Destruct`
|
||||
|
||||
impl const Drop for ConstImplWithDropGlue {
|
||||
fn drop(&mut self) {}
|
||||
|
||||
@@ -19,7 +19,7 @@ const trait Foo {}
|
||||
impl Foo for () {}
|
||||
|
||||
struct Conditional<T: Foo>(T);
|
||||
impl<T> const Drop for Conditional<T> where T: [const] Foo {
|
||||
impl<T> const Drop for Conditional<T> where T: [const] Foo + [const] Destruct {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user