Skip to content

Commit 2c639cc

Browse files
Rollup merge of #155676 - oli-obk:const-drop-non-const-destruct, r=fee1-dead
Reject implementing const Drop for types that are not const `Destruct` already fixes #155618 While there is no soundness or otherwise issue currently, this PR ensures that people get what they expect. It seems wrong to allow implementing `const Drop`, but then the type still can't be dropped at compile-time. r? @fee1-dead
2 parents 0e9c586 + 7dcedaf commit 2c639cc

9 files changed

Lines changed: 198 additions & 26 deletions

compiler/rustc_hir_analysis/src/check/always_applicable.rs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
1111
use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
1212
use rustc_middle::span_bug;
1313
use rustc_middle::ty::util::CheckRegions;
14-
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypingMode};
14+
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
1515
use rustc_trait_selection::regions::InferCtxtRegionExt;
1616
use rustc_trait_selection::traits::{self, ObligationCtxt};
1717

@@ -65,6 +65,8 @@ pub(crate) fn check_drop_impl(
6565
adt_to_impl_args,
6666
)?;
6767

68+
ensure_all_fields_are_const_destruct(tcx, drop_impl_did, adt_def.did())?;
69+
6870
ensure_impl_predicates_are_implied_by_item_defn(
6971
tcx,
7072
drop_impl_did,
@@ -173,6 +175,64 @@ fn ensure_impl_params_and_item_params_correspond<'tcx>(
173175
Err(err.emit())
174176
}
175177

178+
fn ensure_all_fields_are_const_destruct<'tcx>(
179+
tcx: TyCtxt<'tcx>,
180+
impl_def_id: LocalDefId,
181+
adt_def_id: DefId,
182+
) -> Result<(), ErrorGuaranteed> {
183+
if !tcx.is_conditionally_const(impl_def_id) {
184+
return Ok(());
185+
}
186+
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
187+
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
188+
189+
let impl_span = tcx.def_span(impl_def_id.to_def_id());
190+
let env =
191+
ty::EarlyBinder::bind(tcx.param_env(impl_def_id)).instantiate_identity().skip_norm_wip();
192+
let args = ty::GenericArgs::identity_for_item(tcx, impl_def_id);
193+
let destruct_trait = tcx.lang_items().destruct_trait().unwrap();
194+
for field in tcx.adt_def(adt_def_id).all_fields() {
195+
let field_ty = field.ty(tcx, args);
196+
let cause = traits::ObligationCause::new(
197+
tcx.def_span(field.did),
198+
impl_def_id,
199+
ObligationCauseCode::Misc,
200+
);
201+
ocx.register_obligation(traits::Obligation::new(
202+
tcx,
203+
cause,
204+
env,
205+
ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
206+
trait_ref: ty::TraitRef::new(tcx, destruct_trait, [field_ty]),
207+
constness: ty::BoundConstness::Maybe,
208+
}),
209+
));
210+
}
211+
ocx.evaluate_obligations_error_on_ambiguity()
212+
.into_iter()
213+
.map(|error| {
214+
let ty::ClauseKind::HostEffect(eff) =
215+
error.root_obligation.predicate.expect_clause().kind().no_bound_vars().unwrap()
216+
else {
217+
unreachable!()
218+
};
219+
let field_ty = eff.trait_ref.self_ty();
220+
let diag = struct_span_code_err!(
221+
tcx.dcx(),
222+
error.root_obligation.cause.span,
223+
E0367,
224+
"`{field_ty}` does not implement `[const] Destruct`",
225+
)
226+
.with_span_note(impl_span, "required for this `Drop` impl");
227+
if field_ty.has_param() {
228+
// FIXME: suggest adding `[const] Destruct` by teaching
229+
// `suggest_restricting_param_bound` about const traits.
230+
}
231+
Err(diag.emit())
232+
})
233+
.collect()
234+
}
235+
176236
/// Confirms that all predicates defined on the `Drop` impl (`drop_impl_def_id`) are able to be
177237
/// proven from within `adt_def_id`'s environment. I.e. all the predicates on the impl are
178238
/// implied by the ADT being well formed.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#![feature(const_trait_impl)]
2+
#![feature(const_destruct)]
3+
4+
use std::marker::Destruct;
5+
6+
struct NotConstDrop;
7+
8+
impl Drop for NotConstDrop {
9+
fn drop(&mut self) {}
10+
}
11+
12+
struct ConstDrop(NotConstDrop);
13+
//~^ ERROR: `NotConstDrop` does not implement `[const] Destruct`
14+
15+
impl const Drop for ConstDrop {
16+
fn drop(&mut self) {}
17+
}
18+
19+
struct ConstDrop2<T>(T);
20+
//~^ ERROR: `T` does not implement `[const] Destruct`
21+
22+
impl<T> const Drop for ConstDrop2<T> {
23+
fn drop(&mut self) {}
24+
}
25+
26+
struct ConstDrop3<T>(T);
27+
28+
impl<T: [const] Destruct> const Drop for ConstDrop3<T> {
29+
fn drop(&mut self) {}
30+
}
31+
32+
fn main() {}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0367]: `NotConstDrop` does not implement `[const] Destruct`
2+
--> $DIR/drop-impl-nonconst-drop-field.rs:12:18
3+
|
4+
LL | struct ConstDrop(NotConstDrop);
5+
| ^^^^^^^^^^^^
6+
|
7+
note: required for this `Drop` impl
8+
--> $DIR/drop-impl-nonconst-drop-field.rs:15:1
9+
|
10+
LL | impl const Drop for ConstDrop {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error[E0367]: `T` does not implement `[const] Destruct`
14+
--> $DIR/drop-impl-nonconst-drop-field.rs:19:22
15+
|
16+
LL | struct ConstDrop2<T>(T);
17+
| ^
18+
|
19+
note: required for this `Drop` impl
20+
--> $DIR/drop-impl-nonconst-drop-field.rs:22:1
21+
|
22+
LL | impl<T> const Drop for ConstDrop2<T> {
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error: aborting due to 2 previous errors
26+
27+
For more information about this error, try `rustc --explain E0367`.
Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
1+
error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct`
2+
--> $DIR/const-drop-fail.rs:19:30
3+
|
4+
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
5+
| ^^^^^^^^^^^^^^
6+
|
7+
note: required for this `Drop` impl
8+
--> $DIR/const-drop-fail.rs:22:1
9+
|
10+
LL | impl const Drop for ConstImplWithDropGlue {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
113
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
2-
--> $DIR/const-drop-fail.rs:34:5
14+
--> $DIR/const-drop-fail.rs:35:5
315
|
416
LL | const _: () = check($exp);
517
| ----- required by a bound introduced by this call
@@ -8,13 +20,13 @@ LL | NonTrivialDrop,
820
| ^^^^^^^^^^^^^^
921
|
1022
note: required by a bound in `check`
11-
--> $DIR/const-drop-fail.rs:25:19
23+
--> $DIR/const-drop-fail.rs:26:19
1224
|
1325
LL | const fn check<T: [const] Destruct>(_: T) {}
1426
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
1527

1628
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
17-
--> $DIR/const-drop-fail.rs:36:5
29+
--> $DIR/const-drop-fail.rs:37:5
1830
|
1931
LL | const _: () = check($exp);
2032
| ----- required by a bound introduced by this call
@@ -23,11 +35,12 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
2335
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2436
|
2537
note: required by a bound in `check`
26-
--> $DIR/const-drop-fail.rs:25:19
38+
--> $DIR/const-drop-fail.rs:26:19
2739
|
2840
LL | const fn check<T: [const] Destruct>(_: T) {}
2941
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
3042

31-
error: aborting due to 2 previous errors
43+
error: aborting due to 3 previous errors
3244

33-
For more information about this error, try `rustc --explain E0277`.
45+
Some errors have detailed explanations: E0277, E0367.
46+
For more information about an error, try `rustc --explain E0277`.
Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
1+
error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct`
2+
--> $DIR/const-drop-fail.rs:19:30
3+
|
4+
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
5+
| ^^^^^^^^^^^^^^
6+
|
7+
note: required for this `Drop` impl
8+
--> $DIR/const-drop-fail.rs:22:1
9+
|
10+
LL | impl const Drop for ConstImplWithDropGlue {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
113
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
2-
--> $DIR/const-drop-fail.rs:34:5
14+
--> $DIR/const-drop-fail.rs:35:5
315
|
416
LL | const _: () = check($exp);
517
| ----- required by a bound introduced by this call
@@ -8,13 +20,13 @@ LL | NonTrivialDrop,
820
| ^^^^^^^^^^^^^^
921
|
1022
note: required by a bound in `check`
11-
--> $DIR/const-drop-fail.rs:25:19
23+
--> $DIR/const-drop-fail.rs:26:19
1224
|
1325
LL | const fn check<T: [const] Destruct>(_: T) {}
1426
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
1527

1628
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
17-
--> $DIR/const-drop-fail.rs:36:5
29+
--> $DIR/const-drop-fail.rs:37:5
1830
|
1931
LL | const _: () = check($exp);
2032
| ----- required by a bound introduced by this call
@@ -23,11 +35,12 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
2335
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2436
|
2537
note: required by a bound in `check`
26-
--> $DIR/const-drop-fail.rs:25:19
38+
--> $DIR/const-drop-fail.rs:26:19
2739
|
2840
LL | const fn check<T: [const] Destruct>(_: T) {}
2941
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
3042

31-
error: aborting due to 2 previous errors
43+
error: aborting due to 3 previous errors
3244

33-
For more information about this error, try `rustc --explain E0277`.
45+
Some errors have detailed explanations: E0277, E0367.
46+
For more information about an error, try `rustc --explain E0277`.
Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
1+
error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct`
2+
--> $DIR/const-drop-fail.rs:19:30
3+
|
4+
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
5+
| ^^^^^^^^^^^^^^
6+
|
7+
note: required for this `Drop` impl
8+
--> $DIR/const-drop-fail.rs:22:1
9+
|
10+
LL | impl const Drop for ConstImplWithDropGlue {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
113
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
2-
--> $DIR/const-drop-fail.rs:34:5
14+
--> $DIR/const-drop-fail.rs:35:5
315
|
416
LL | const _: () = check($exp);
517
| ----- required by a bound introduced by this call
@@ -8,13 +20,13 @@ LL | NonTrivialDrop,
820
| ^^^^^^^^^^^^^^
921
|
1022
note: required by a bound in `check`
11-
--> $DIR/const-drop-fail.rs:25:19
23+
--> $DIR/const-drop-fail.rs:26:19
1224
|
1325
LL | const fn check<T: [const] Destruct>(_: T) {}
1426
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
1527

1628
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
17-
--> $DIR/const-drop-fail.rs:36:5
29+
--> $DIR/const-drop-fail.rs:37:5
1830
|
1931
LL | const _: () = check($exp);
2032
| ----- required by a bound introduced by this call
@@ -23,11 +35,12 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
2335
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2436
|
2537
note: required by a bound in `check`
26-
--> $DIR/const-drop-fail.rs:25:19
38+
--> $DIR/const-drop-fail.rs:26:19
2739
|
2840
LL | const fn check<T: [const] Destruct>(_: T) {}
2941
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
3042

31-
error: aborting due to 2 previous errors
43+
error: aborting due to 3 previous errors
3244

33-
For more information about this error, try `rustc --explain E0277`.
45+
Some errors have detailed explanations: E0277, E0367.
46+
For more information about an error, try `rustc --explain E0277`.
Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
1+
error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct`
2+
--> $DIR/const-drop-fail.rs:19:30
3+
|
4+
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
5+
| ^^^^^^^^^^^^^^
6+
|
7+
note: required for this `Drop` impl
8+
--> $DIR/const-drop-fail.rs:22:1
9+
|
10+
LL | impl const Drop for ConstImplWithDropGlue {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
113
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
2-
--> $DIR/const-drop-fail.rs:34:5
14+
--> $DIR/const-drop-fail.rs:35:5
315
|
416
LL | const _: () = check($exp);
517
| ----- required by a bound introduced by this call
@@ -8,13 +20,13 @@ LL | NonTrivialDrop,
820
| ^^^^^^^^^^^^^^
921
|
1022
note: required by a bound in `check`
11-
--> $DIR/const-drop-fail.rs:25:19
23+
--> $DIR/const-drop-fail.rs:26:19
1224
|
1325
LL | const fn check<T: [const] Destruct>(_: T) {}
1426
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
1527

1628
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
17-
--> $DIR/const-drop-fail.rs:36:5
29+
--> $DIR/const-drop-fail.rs:37:5
1830
|
1931
LL | const _: () = check($exp);
2032
| ----- required by a bound introduced by this call
@@ -23,11 +35,12 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
2335
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2436
|
2537
note: required by a bound in `check`
26-
--> $DIR/const-drop-fail.rs:25:19
38+
--> $DIR/const-drop-fail.rs:26:19
2739
|
2840
LL | const fn check<T: [const] Destruct>(_: T) {}
2941
| ^^^^^^^^^^^^^^^^ required by this bound in `check`
3042

31-
error: aborting due to 2 previous errors
43+
error: aborting due to 3 previous errors
3244

33-
For more information about this error, try `rustc --explain E0277`.
45+
Some errors have detailed explanations: E0277, E0367.
46+
For more information about an error, try `rustc --explain E0277`.

tests/ui/traits/const-traits/const-drop-fail.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ impl Drop for NonTrivialDrop {
1717
}
1818

1919
struct ConstImplWithDropGlue(NonTrivialDrop);
20+
//~^ ERROR: `NonTrivialDrop` does not implement `[const] Destruct`
2021

2122
impl const Drop for ConstImplWithDropGlue {
2223
fn drop(&mut self) {}

tests/ui/traits/const-traits/minicore-drop-fail.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const trait Foo {}
1919
impl Foo for () {}
2020

2121
struct Conditional<T: Foo>(T);
22-
impl<T> const Drop for Conditional<T> where T: [const] Foo {
22+
impl<T> const Drop for Conditional<T> where T: [const] Foo + [const] Destruct {
2323
fn drop(&mut self) {}
2424
}
2525

0 commit comments

Comments
 (0)