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 {
   |
```
This commit is contained in:
Esteban Küber 2025-07-19 00:40:03 +00:00
parent 528137f972
commit a08bdffb21
28 changed files with 291 additions and 8 deletions

View file

@ -1,9 +1,10 @@
//! Concrete error types for all operations which may be invalid in a certain const context.
use hir::{ConstContext, LangItem};
use rustc_errors::Diag;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
@ -352,13 +353,58 @@ fn build_error_for_const_call<'tcx>(
non_or_conditionally,
})
}
_ => ccx.dcx().create_err(errors::NonConstFnCall {
span,
def_descr: ccx.tcx.def_descr(callee),
def_path_str: ccx.tcx.def_path_str_with_args(callee, args),
kind: ccx.const_kind(),
non_or_conditionally,
}),
_ => {
let def_descr = ccx.tcx.def_descr(callee);
let mut err = ccx.dcx().create_err(errors::NonConstFnCall {
span,
def_descr,
def_path_str: ccx.tcx.def_path_str_with_args(callee, args),
kind: ccx.const_kind(),
non_or_conditionally,
});
let def_kind = ccx.tcx.def_kind(callee);
if let DefKind::AssocTy | DefKind::AssocConst | DefKind::AssocFn = def_kind {
let parent = ccx.tcx.parent(callee);
if let DefKind::Trait = ccx.tcx.def_kind(parent)
&& !ccx.tcx.is_const_trait(parent)
{
let assoc_span = ccx.tcx.def_span(callee);
let assoc_name = ccx.tcx.item_name(callee);
let mut span: MultiSpan = ccx.tcx.def_span(parent).into();
span.push_span_label(assoc_span, format!("this {def_descr} is not const"));
let trait_descr = ccx.tcx.def_descr(parent);
let trait_span = ccx.tcx.def_span(parent);
let trait_name = ccx.tcx.item_name(parent);
span.push_span_label(trait_span, format!("this {trait_descr} is not const"));
err.span_note(
span,
format!(
"{def_descr} `{assoc_name}` is not const because {trait_descr} \
`{trait_name}` is not const",
),
);
let indentation = ccx
.tcx
.sess
.source_map()
.indentation_before(trait_span)
.unwrap_or_default();
err.span_suggestion_verbose(
trait_span.shrink_to_lo(),
format!("consider making trait `{trait_name}` const"),
format!("#[const_trait]\n{indentation}"),
Applicability::MachineApplicable,
);
}
} else if ccx.tcx.constness(callee) != hir::Constness::Const {
let name = ccx.tcx.item_name(callee);
err.span_note(
ccx.tcx.def_span(callee),
format!("{def_descr} `{name}` is not const"),
);
}
err
}
};
err.note(format!(

View file

@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `non_const_fn` in constants
LL | global_asm!("/* {} */", const non_const_fn(0));
| ^^^^^^^^^^^^^^^
|
note: function `non_const_fn` is not const
--> $DIR/non-const.rs:8:1
|
LL | fn non_const_fn(x: i32) -> i32 { x }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 1 previous error

View file

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

View file

@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `f` in constants
LL | let _ = [0; f(2)];
| ^^^^
|
note: function `f` is not const
--> $DIR/const-call.rs:1:1
|
LL | fn f(x: usize) -> usize {
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 1 previous error

View file

@ -21,6 +21,8 @@ error[E0015]: cannot call non-const function `_print` in constant functions
LL | println!("{:?}", 0);
| ^^^^^^^^^^^^^^^^^^^
|
note: function `_print` is not const
--> $SRC_DIR/std/src/io/stdio.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `regular_in_block` in constant func
LL | regular_in_block();
| ^^^^^^^^^^^^^^^^^^
|
note: function `regular_in_block` is not const
--> $DIR/const-extern-fn-call-extern-fn.rs:2:5
|
LL | fn regular_in_block();
| ^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
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
LL | regular();
| ^^^^^^^^^
|
note: function `regular` is not const
--> $DIR/const-extern-fn-call-extern-fn.rs:12:1
|
LL | extern "C" fn regular() {}
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors

View file

@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `random` in constant functions
LL | random()
| ^^^^^^^^
|
note: function `random` is not const
--> $DIR/const-fn-not-safe-for-const.rs:5:1
|
LL | fn random() -> u32 {
| ^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 1 previous error

View file

@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `non_const` in constants
LL | pub const Q: i32 = match non_const() {
| ^^^^^^^^^^^
|
note: function `non_const` is not const
--> $DIR/issue-46843.rs:6:1
|
LL | fn non_const() -> Thing {
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 1 previous error

View file

@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `Y::foo` in statics
LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: function `foo` is not const
--> $DIR/issue-16538.rs:6:5
|
LL | pub fn foo(value: *const X) -> *const X {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

View file

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

View file

@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `xyz` in constants
LL | const NUM: u8 = xyz();
| ^^^^^
|
note: function `xyz` is not const
--> $DIR/issue-43105.rs:1:1
|
LL | fn xyz() -> u8 { 42 }
| ^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 1 previous error

View file

@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `bar` in statics
LL | static foo: Foo = bar();
| ^^^^^
|
note: function `bar` is not const
--> $DIR/mir_check_nonconst.rs:4:1
|
LL | fn bar() -> Foo {
| ^^^^^^^^^^^^^^^
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

View file

@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `create_some` in constants
LL | const FOO: Option<u8> = create_some();
| ^^^^^^^^^^^^^
|
note: function `create_some` is not const
--> $DIR/E0015.rs:1:1
|
LL | fn create_some() -> Option<u8> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 1 previous error

View file

@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `not_const` in constant functions
LL | become not_const();
| ^^^^^^^^^^^
|
note: function `not_const` is not const
--> $DIR/constck.rs:18:1
|
LL | fn not_const() {}
| ^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const function `not_const` in constant functions
@ -12,6 +17,11 @@ error[E0015]: cannot call non-const function `not_const` in constant functions
LL | become yes_const(not_const());
| ^^^^^^^^^^^
|
note: function `not_const` is not const
--> $DIR/constck.rs:18:1
|
LL | fn not_const() {}
| ^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors

View file

@ -4,7 +4,19 @@ error[E0015]: cannot call non-const associated function `<Dim3 as Dim>::dim` in
LL | let array: [usize; Dim3::dim()]
| ^^^^^^^^^^^
|
note: associated function `dim` is not const because trait `Dim` is not const
--> $DIR/issue-39559-2.rs:1:1
|
LL | trait Dim {
| ^^^^^^^^^ this trait is not const
LL | fn dim() -> usize;
| ------------------ this associated function is not const
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
help: consider making trait `Dim` const
|
LL + #[const_trait]
LL | trait Dim {
|
error[E0015]: cannot call non-const associated function `<Dim3 as Dim>::dim` in constants
--> $DIR/issue-39559-2.rs:16:15
@ -12,7 +24,19 @@ error[E0015]: cannot call non-const associated function `<Dim3 as Dim>::dim` in
LL | = [0; Dim3::dim()];
| ^^^^^^^^^^^
|
note: associated function `dim` is not const because trait `Dim` is not const
--> $DIR/issue-39559-2.rs:1:1
|
LL | trait Dim {
| ^^^^^^^^^ this trait is not const
LL | fn dim() -> usize;
| ------------------ this associated function is not const
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
help: consider making trait `Dim` const
|
LL + #[const_trait]
LL | trait Dim {
|
error: aborting due to 2 previous errors

View file

@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `foo` in statics
LL | static a: [isize; 2] = [foo(); 2];
| ^^^^^
|
note: function `foo` is not const
--> $DIR/static-vec-repeat-not-constant.rs:1:1
|
LL | fn foo() -> isize { 23 }
| ^^^^^^^^^^^^^^^^^
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

View file

@ -35,6 +35,13 @@ error[E0015]: cannot call non-const method `<str as ToString>::to_string` in sta
LL | field2: SafeEnum::Variant4("str".to_string()),
| ^^^^^^^^^^^
|
note: method `to_string` is not const because trait `ToString` is not const
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
= note: this trait is not const
::: $SRC_DIR/alloc/src/string.rs:LL:COL
|
= note: this method is not const
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`

View file

@ -4,6 +4,11 @@ error[E0015]: cannot call non-const function `non_const` in constant functions
LL | fn foo() { non_const() }
| ^^^^^^^^^^^
|
note: function `non_const` is not const
--> $DIR/const-check-fns-in-const-impl.rs:11:1
|
LL | fn non_const() {}
| ^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 1 previous error

View file

@ -13,7 +13,19 @@ error[E0015]: cannot call non-const method `<() as Trait>::foo` in constant func
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 {
|
error: aborting due to 2 previous errors

View file

@ -4,6 +4,8 @@ error[E0015]: cannot call non-const function `_print` in constant functions
LL | println!("lul");
| ^^^^^^^^^^^^^^^
|
note: function `_print` is not const
--> $SRC_DIR/std/src/io/stdio.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -4,7 +4,19 @@ error[E0015]: cannot call non-const associated function `<T as A>::assoc` in con
LL | T::assoc()
| ^^^^^^^^^^
|
note: associated function `assoc` is not const because trait `A` is not const
--> $DIR/issue-88155.rs:3:1
|
LL | pub trait A {
| ^^^^^^^^^^^ this trait is not const
LL | fn assoc() -> bool;
| ------------------- this associated function is not const
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider making trait `A` const
|
LL + #[const_trait]
LL | pub trait A {
|
error: aborting due to 1 previous error

View file

@ -51,7 +51,19 @@ error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
LL | x.a();
| ^^^
|
note: method `a` is not const because trait `Foo` is not const
--> $DIR/super-traits-fail-2.rs:6:1
|
LL | trait Foo {
| ^^^^^^^^^ this trait is not const
LL | fn a(&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 `Foo` const
|
LL + #[const_trait]
LL | trait Foo {
|
error: aborting due to 5 previous errors

View file

@ -63,7 +63,19 @@ error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
LL | x.a();
| ^^^
|
note: method `a` is not const because trait `Foo` is not const
--> $DIR/super-traits-fail-2.rs:6:1
|
LL | trait Foo {
| ^^^^^^^^^ this trait is not const
LL | fn a(&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 `Foo` const
|
LL + #[const_trait]
LL | trait Foo {
|
error: aborting due to 6 previous errors

View file

@ -94,7 +94,19 @@ error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
LL | x.a();
| ^^^
|
note: method `a` is not const because trait `Foo` is not const
--> $DIR/super-traits-fail-3.rs:17:1
|
LL | trait Foo {
| ^^^^^^^^^ this trait is not const
LL | fn a(&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 `Foo` const
|
LL + #[const_trait]
LL | trait Foo {
|
error: aborting due to 9 previous errors

View file

@ -94,7 +94,19 @@ error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
LL | x.a();
| ^^^
|
note: method `a` is not const because trait `Foo` is not const
--> $DIR/super-traits-fail-3.rs:17:1
|
LL | trait Foo {
| ^^^^^^^^^ this trait is not const
LL | fn a(&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 `Foo` const
|
LL + #[const_trait]
LL | trait Foo {
|
error: aborting due to 9 previous errors

View file

@ -74,7 +74,19 @@ error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
LL | x.a();
| ^^^
|
note: method `a` is not const because trait `Foo` is not const
--> $DIR/super-traits-fail-3.rs:17:1
|
LL | trait Foo {
| ^^^^^^^^^ this trait is not const
LL | fn a(&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 `Foo` const
|
LL + #[const_trait]
LL | trait Foo {
|
error: aborting due to 7 previous errors

View file

@ -63,7 +63,19 @@ error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
LL | x.a();
| ^^^
|
note: method `a` is not const because trait `Foo` is not const
--> $DIR/super-traits-fail-3.rs:17:1
|
LL | trait Foo {
| ^^^^^^^^^ this trait is not const
LL | fn a(&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 `Foo` const
|
LL + #[const_trait]
LL | trait Foo {
|
error: aborting due to 6 previous errors

View file

@ -671,6 +671,11 @@ error[E0015]: cannot call non-const function `map::<u8>` in constants
LL | const _: Option<_> = map(value);
| ^^^^^^^^^^
|
note: function `map` is not const
--> $DIR/typeck_type_placeholder_item.rs:222:1
|
LL | fn map<T>(_: fn() -> Option<&'static T>) -> Option<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const method `<std::ops::Range<i32> as Iterator>::filter::<{closure@$DIR/typeck_type_placeholder_item.rs:240:29: 240:32}>` in constants
@ -679,6 +684,13 @@ error[E0015]: cannot call non-const method `<std::ops::Range<i32> as Iterator>::
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
| ^^^^^^^^^^^^^^^^^^^^^^
|
note: method `filter` is not const because trait `Iterator` is not const
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
= note: this trait is not const
::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
= note: this method is not const
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const method `<Filter<std::ops::Range<i32>, {closure@$DIR/typeck_type_placeholder_item.rs:240:29: 240:32}> as Iterator>::map::<i32, {closure@$DIR/typeck_type_placeholder_item.rs:240:49: 240:52}>` in constants
@ -687,6 +699,13 @@ error[E0015]: cannot call non-const method `<Filter<std::ops::Range<i32>, {closu
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
| ^^^^^^^^^^^^^^
|
note: method `map` is not const because trait `Iterator` is not const
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
= note: this trait is not const
::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
= note: this method is not const
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 83 previous errors