Skip to content

Commit 78317f7

Browse files
committed
Point at non-const trait when using them in const context
Point at trait and associated item when that associated item is used in a const context. Suggest making the trait `#[const_trait]`. ``` error[E0015]: cannot call non-const method `<() as Trait>::foo` in constant functions --> $DIR/inline-incorrect-early-bound-in-ctfe.rs:26:8 | LL | ().foo(); | ^^^^^ | note: method `foo` is not const because trait `Trait` is not const --> $DIR/inline-incorrect-early-bound-in-ctfe.rs:13:1 | LL | trait Trait { | ^^^^^^^^^^^ this trait is not const LL | fn foo(self); | ------------- this method is not const = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider making trait `Trait` const | LL + #[const_trait] LL | trait Trait { | ```
1 parent 50d1168 commit 78317f7

28 files changed

+291
-8
lines changed

compiler/rustc_const_eval/src/check_consts/ops.rs

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
//! Concrete error types for all operations which may be invalid in a certain const context.
22
33
use hir::{ConstContext, LangItem};
4-
use rustc_errors::Diag;
54
use rustc_errors::codes::*;
5+
use rustc_errors::{Applicability, Diag, MultiSpan};
66
use rustc_hir as hir;
7+
use rustc_hir::def::DefKind;
78
use rustc_hir::def_id::DefId;
89
use rustc_infer::infer::TyCtxtInferExt;
910
use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
@@ -355,13 +356,58 @@ fn build_error_for_const_call<'tcx>(
355356
non_or_conditionally,
356357
})
357358
}
358-
_ => ccx.dcx().create_err(errors::NonConstFnCall {
359-
span,
360-
def_descr: ccx.tcx.def_descr(callee),
361-
def_path_str: ccx.tcx.def_path_str_with_args(callee, args),
362-
kind: ccx.const_kind(),
363-
non_or_conditionally,
364-
}),
359+
_ => {
360+
let def_descr = ccx.tcx.def_descr(callee);
361+
let mut err = ccx.dcx().create_err(errors::NonConstFnCall {
362+
span,
363+
def_descr,
364+
def_path_str: ccx.tcx.def_path_str_with_args(callee, args),
365+
kind: ccx.const_kind(),
366+
non_or_conditionally,
367+
});
368+
let def_kind = ccx.tcx.def_kind(callee);
369+
if let DefKind::AssocTy | DefKind::AssocConst | DefKind::AssocFn = def_kind {
370+
let parent = ccx.tcx.parent(callee);
371+
if let DefKind::Trait = ccx.tcx.def_kind(parent)
372+
&& !ccx.tcx.is_const_trait(parent)
373+
{
374+
let assoc_span = ccx.tcx.def_span(callee);
375+
let assoc_name = ccx.tcx.item_name(callee);
376+
let mut span: MultiSpan = ccx.tcx.def_span(parent).into();
377+
span.push_span_label(assoc_span, format!("this {def_descr} is not const"));
378+
let trait_descr = ccx.tcx.def_descr(parent);
379+
let trait_span = ccx.tcx.def_span(parent);
380+
let trait_name = ccx.tcx.item_name(parent);
381+
span.push_span_label(trait_span, format!("this {trait_descr} is not const"));
382+
err.span_note(
383+
span,
384+
format!(
385+
"{def_descr} `{assoc_name}` is not const because {trait_descr} \
386+
`{trait_name}` is not const",
387+
),
388+
);
389+
let indentation = ccx
390+
.tcx
391+
.sess
392+
.source_map()
393+
.indentation_before(trait_span)
394+
.unwrap_or_default();
395+
err.span_suggestion_verbose(
396+
trait_span.shrink_to_lo(),
397+
format!("consider making trait `{trait_name}` const"),
398+
format!("#[const_trait]\n{indentation}"),
399+
Applicability::MachineApplicable,
400+
);
401+
}
402+
} else if ccx.tcx.constness(callee) != hir::Constness::Const {
403+
let name = ccx.tcx.item_name(callee);
404+
err.span_note(
405+
ccx.tcx.def_span(callee),
406+
format!("{def_descr} `{name}` is not const"),
407+
);
408+
}
409+
err
410+
}
365411
};
366412

367413
err.note(format!(

tests/ui/asm/non-const.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `non_const_fn` in constants
44
LL | global_asm!("/* {} */", const non_const_fn(0));
55
| ^^^^^^^^^^^^^^^
66
|
7+
note: function `non_const_fn` is not const
8+
--> $DIR/non-const.rs:8:1
9+
|
10+
LL | fn non_const_fn(x: i32) -> i32 { x }
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
712
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
813

914
error: aborting due to 1 previous error

tests/ui/borrowck/issue-64453.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ error[E0015]: cannot call non-const function `format` in statics
44
LL | static settings_dir: String = format!("");
55
| ^^^^^^^^^^^
66
|
7+
note: function `format` is not const
8+
--> $SRC_DIR/alloc/src/fmt.rs:LL:COL
79
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
810
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
911
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)

tests/ui/consts/const-call.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `f` in constants
44
LL | let _ = [0; f(2)];
55
| ^^^^
66
|
7+
note: function `f` is not const
8+
--> $DIR/const-call.rs:1:1
9+
|
10+
LL | fn f(x: usize) -> usize {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^
712
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
813

914
error: aborting due to 1 previous error

tests/ui/consts/const-eval/format.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ error[E0015]: cannot call non-const function `_print` in constant functions
2121
LL | println!("{:?}", 0);
2222
| ^^^^^^^^^^^^^^^^^^^
2323
|
24+
note: function `_print` is not const
25+
--> $SRC_DIR/std/src/io/stdio.rs:LL:COL
2426
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
2527
= note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
2628

tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `regular_in_block` in constant func
44
LL | regular_in_block();
55
| ^^^^^^^^^^^^^^^^^^
66
|
7+
note: function `regular_in_block` is not const
8+
--> $DIR/const-extern-fn-call-extern-fn.rs:2:5
9+
|
10+
LL | fn regular_in_block();
11+
| ^^^^^^^^^^^^^^^^^^^^^^
712
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
813

914
error[E0015]: cannot call non-const function `regular` in constant functions
@@ -12,6 +17,11 @@ error[E0015]: cannot call non-const function `regular` in constant functions
1217
LL | regular();
1318
| ^^^^^^^^^
1419
|
20+
note: function `regular` is not const
21+
--> $DIR/const-extern-fn-call-extern-fn.rs:12:1
22+
|
23+
LL | extern "C" fn regular() {}
24+
| ^^^^^^^^^^^^^^^^^^^^^^^
1525
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
1626

1727
error: aborting due to 2 previous errors

tests/ui/consts/const-fn-not-safe-for-const.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `random` in constant functions
44
LL | random()
55
| ^^^^^^^^
66
|
7+
note: function `random` is not const
8+
--> $DIR/const-fn-not-safe-for-const.rs:5:1
9+
|
10+
LL | fn random() -> u32 {
11+
| ^^^^^^^^^^^^^^^^^^
712
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
813

914
error: aborting due to 1 previous error

tests/ui/consts/control-flow/issue-46843.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `non_const` in constants
44
LL | pub const Q: i32 = match non_const() {
55
| ^^^^^^^^^^^
66
|
7+
note: function `non_const` is not const
8+
--> $DIR/issue-46843.rs:6:1
9+
|
10+
LL | fn non_const() -> Thing {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^
712
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
813

914
error: aborting due to 1 previous error

tests/ui/consts/issue-16538.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `Y::foo` in statics
44
LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7+
note: function `foo` is not const
8+
--> $DIR/issue-16538.rs:6:5
9+
|
10+
LL | pub fn foo(value: *const X) -> *const X {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
712
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
813
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
914

tests/ui/consts/issue-32829-2.stderr

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `invalid` in constants
44
LL | invalid();
55
| ^^^^^^^^^
66
|
7+
note: function `invalid` is not const
8+
--> $DIR/issue-32829-2.rs:68:1
9+
|
10+
LL | fn invalid() {}
11+
| ^^^^^^^^^^^^
712
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
813

914
error[E0015]: cannot call non-const function `invalid` in statics
@@ -12,6 +17,11 @@ error[E0015]: cannot call non-const function `invalid` in statics
1217
LL | invalid();
1318
| ^^^^^^^^^
1419
|
20+
note: function `invalid` is not const
21+
--> $DIR/issue-32829-2.rs:68:1
22+
|
23+
LL | fn invalid() {}
24+
| ^^^^^^^^^^^^
1525
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
1626
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
1727

@@ -21,6 +31,11 @@ error[E0015]: cannot call non-const function `invalid` in statics
2131
LL | invalid();
2232
| ^^^^^^^^^
2333
|
34+
note: function `invalid` is not const
35+
--> $DIR/issue-32829-2.rs:68:1
36+
|
37+
LL | fn invalid() {}
38+
| ^^^^^^^^^^^^
2439
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
2540
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
2641

0 commit comments

Comments
 (0)