Skip to content

Commit e0ff091

Browse files
Rollup merge of rust-lang#155013 - jakubadamw:issue-103270, r=oli-obk
Suggest the `[const] Destruct` bound for type parameters in const functions when missing When a const function drops a value whose type is a type parameter without a `[const] Destruct` bound, suggest adding it so that the destructor can be evaluated at compile-time. Closes rust-lang#103270. Example: ```rust const fn f(_x: impl std::fmt::Debug) {} ``` Before: ``` error[E0493]: destructor of `impl std::fmt::Debug` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:1:11 | LL | const fn f(_x: impl std::fmt::Debug) {} | ^^ - value is dropped here | | | the destructor for this type cannot be evaluated in constant functions ``` After: ``` error[E0493]: destructor of `impl std::fmt::Debug` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:1:11 | LL | const fn f(_x: impl std::fmt::Debug) {} | ^^ - value is dropped here | | | the destructor for this type cannot be evaluated in constant functions | help: consider restricting opaque type `impl std::fmt::Debug` with unstable trait `Destruct` | LL | const fn f(_x: impl std::fmt::Debug + [const] Destruct) {} | ++++++++++++++++++ ``` No new tests as the existing ones had their results updated with the new suggestion.
2 parents f83cdee + 2f961b8 commit e0ff091

10 files changed

Lines changed: 105 additions & 1 deletion

File tree

‎compiler/rustc_const_eval/src/check_consts/ops.rs‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> {
594594
}
595595

596596
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
597-
if self.needs_non_const_drop {
597+
let mut err = if self.needs_non_const_drop {
598598
ccx.dcx().create_err(diagnostics::LiveDrop {
599599
span,
600600
dropped_ty: self.dropped_ty,
@@ -611,7 +611,30 @@ impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> {
611611
},
612612
sym::const_destruct,
613613
)
614+
};
615+
616+
// If the dropped type is a type parameter, suggest adding a `[const] Destruct` bound.
617+
// The suggestion is only offered on nightly, since `[const]` bounds are unstable.
618+
if let Param(param_ty) = self.dropped_ty.kind()
619+
&& ccx.tcx.sess.is_nightly_build()
620+
{
621+
let tcx = ccx.tcx;
622+
let caller = ccx.def_id();
623+
if let Some(generics) = tcx.hir_node_by_def_id(caller).generics() {
624+
let destruct_def_id = tcx.lang_items().destruct_trait();
625+
suggest_constraining_type_param(
626+
tcx,
627+
generics,
628+
&mut err,
629+
param_ty.name.as_str(),
630+
"[const] Destruct",
631+
destruct_def_id,
632+
None,
633+
);
634+
}
614635
}
636+
637+
err
615638
}
616639
}
617640

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0493]: destructor of `T` cannot be evaluated at compile-time
2+
--> const-drop.rs:1:24
3+
|
4+
LL | const fn const_drop<T>(_: T) {}
5+
| ^ - value is dropped here
6+
| |
7+
| the destructor for this type cannot be evaluated in constant functions
8+
|
9+
help: consider restricting type parameter `T` with unstable trait `Destruct`
10+
|
11+
LL | const fn const_drop<T: [const] Destruct>(_: T) {}
12+
| ++++++++++++++++++
13+
14+
error: aborting due to 1 previous error
15+
16+
For more information about this error, try `rustc --explain E0493`.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0493]: destructor of `T` cannot be evaluated at compile-time
2+
--> const-drop.rs:1:24
3+
|
4+
1 | const fn const_drop<T>(_: T) {}
5+
| ^ - value is dropped here
6+
| |
7+
| the destructor for this type cannot be evaluated in constant functions
8+
9+
error: aborting due to 1 previous error
10+
11+
For more information about this error, try `rustc --explain E0493`.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const fn const_drop<T>(_: T) {}
2+
3+
fn main() {}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//@ needs-target-std
2+
//
3+
// Test that the suggestion to constrain a type parameter that is dropped in a const
4+
// function with a `[const] Destruct` bound is only offered on nightly, since the bound
5+
// requires an unstable feature.
6+
7+
use run_make_support::{diff, rustc};
8+
9+
fn main() {
10+
let out = rustc()
11+
.input("const-drop.rs")
12+
.env("RUSTC_BOOTSTRAP", "-1")
13+
.run_fail()
14+
.assert_stderr_not_contains("consider restricting type parameter `T`")
15+
.stderr_utf8();
16+
diff().expected_file("const-drop-stable.stderr").actual_text("(rustc)", &out).run();
17+
let out = rustc()
18+
.input("const-drop.rs")
19+
.ui_testing()
20+
.run_fail()
21+
.assert_stderr_contains(
22+
"consider restricting type parameter `T` with unstable trait `Destruct`",
23+
)
24+
.stderr_utf8();
25+
diff().expected_file("const-drop-nightly.stderr").actual_text("(rustc)", &out).run();
26+
}

‎tests/ui/consts/min_const_fn/min_const_fn.stderr‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {}
7373
| ^^ - value is dropped here
7474
| |
7575
| the destructor for this type cannot be evaluated in constant functions
76+
|
77+
help: consider restricting opaque type `impl std::fmt::Debug` with unstable trait `Destruct`
78+
|
79+
LL | const fn no_apit(_x: impl std::fmt::Debug + [const] Destruct) {}
80+
| ++++++++++++++++++
7681

7782
error: aborting due to 9 previous errors
7883

‎tests/ui/consts/unstable-const-fn-in-libcore.stderr‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ LL | const fn unwrap_or_else<F: [const] FnOnce() -> T>(self, f: F) -> T {
66
...
77
LL | }
88
| - value is dropped here
9+
|
10+
help: consider further restricting type parameter `F` with unstable trait `Destruct`
11+
|
12+
LL | const fn unwrap_or_else<F: [const] FnOnce() -> T + [const] Destruct>(self, f: F) -> T {
13+
| ++++++++++++++++++
914

1015
error[E0493]: destructor of `Opt<T>` cannot be evaluated at compile-time
1116
--> $DIR/unstable-const-fn-in-libcore.rs:19:55

‎tests/ui/self/arbitrary-self-from-method-substs-ice.stderr‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ LL | const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
1515
...
1616
LL | }
1717
| - value is dropped here
18+
|
19+
help: consider further restricting type parameter `R` with unstable trait `Destruct`
20+
|
21+
LL | const fn get<R: Deref<Target = Self> + [const] Destruct>(self: R) -> u32 {
22+
| ++++++++++++++++++
1823

1924
error[E0801]: invalid generic `self` parameter type: `R`
2025
--> $DIR/arbitrary-self-from-method-substs-ice.rs:10:49

‎tests/ui/static/static-drop-scope.stderr‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ LL | const fn const_drop<T>(_: T) {}
3737
| ^ - value is dropped here
3838
| |
3939
| the destructor for this type cannot be evaluated in constant functions
40+
|
41+
help: consider restricting type parameter `T` with unstable trait `Destruct`
42+
|
43+
LL | const fn const_drop<T: [const] Destruct>(_: T) {}
44+
| ++++++++++++++++++
4045

4146
error[E0493]: destructor of `(T, ())` cannot be evaluated at compile-time
4247
--> $DIR/static-drop-scope.rs:17:5

‎tests/ui/traits/const-traits/minicore-drop-fail.stderr‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ LL | const fn drop_arbitrary<T>(_: T) {
3030
LL |
3131
LL | }
3232
| - value is dropped here
33+
|
34+
help: consider restricting type parameter `T` with trait `Destruct`
35+
|
36+
LL | const fn drop_arbitrary<T: [const] Destruct>(_: T) {
37+
| ++++++++++++++++++
3338

3439
error: aborting due to 4 previous errors
3540

0 commit comments

Comments
 (0)