Skip to content

Provide additional context to errors involving const traits #144194

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 65 additions & 12 deletions compiler/rustc_const_eval/src/check_consts/ops.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! 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_id::DefId;
use rustc_infer::infer::TyCtxtInferExt;
Expand All @@ -11,8 +11,8 @@ use rustc_middle::mir::CallSource;
use rustc_middle::span_bug;
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
use rustc_middle::ty::{
self, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef, Param, TraitRef, Ty,
suggest_constraining_type_param,
self, AssocItemContainer, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef, Param,
TraitRef, Ty, suggest_constraining_type_param,
};
use rustc_session::parse::add_feature_diagnostics;
use rustc_span::{BytePos, Pos, Span, Symbol, sym};
Expand Down Expand Up @@ -355,18 +355,71 @@ 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,
});
if let Some(item) = ccx.tcx.opt_associated_item(callee) {
if let AssocItemContainer::Trait = item.container
&& let parent = item.container_id(ccx.tcx)
&& !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",
),
);
if parent.is_local() && ccx.tcx.sess.is_nightly_build() {
if !ccx.tcx.features().const_trait_impl() {
err.help(
"add `#![feature(const_trait_impl)]` to the crate attributes to \
enable `#[const_trait]`",
);
}
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::MaybeIncorrect,
);
} else if !ccx.tcx.sess.is_nightly_build() {
err.help("const traits are not yet supported on stable Rust");
}
}
} 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!(
"calls in {}s are limited to constant functions, \
tuple structs and tuple variants",
"calls in {}s are limited to constant functions, tuple structs and tuple variants",
ccx.const_kind(),
));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,34 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
)) {
diag.downgrade_to_delayed_bug();
}
for candidate in self.find_similar_impl_candidates(trait_ref) {
let CandidateSimilarity::Exact { .. } = candidate.similarity else { continue };
let impl_did = candidate.impl_def_id;
let trait_did = candidate.trait_ref.def_id;
let impl_span = self.tcx.def_span(impl_did);
let trait_name = self.tcx.item_name(trait_did);

if self.tcx.is_const_trait(trait_did) && !self.tcx.is_const_trait_impl(impl_did) {
if let Some(impl_did) = impl_did.as_local()
&& let item = self.tcx.hir_expect_item(impl_did)
&& let hir::ItemKind::Impl(item) = item.kind
&& let Some(of_trait) = item.of_trait
{
// trait is const, impl is local and not const
diag.span_suggestion_verbose(
of_trait.path.span.shrink_to_lo(),
format!("make the `impl` of trait `{trait_name}` `const`"),
"const ".to_string(),
Applicability::MachineApplicable,
);
} else {
diag.span_note(
impl_span,
format!("trait `{trait_name}` is implemented but not `const`"),
);
}
}
}
diag
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,20 @@ 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
--> const-super-trait.rs:3:1
|
LL | trait Foo {
| ^^^^^^^^^ this trait is not const
LL | fn a(&self);
| ------------ this method is not const
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable `#[const_trait]`
= 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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,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
--> const-super-trait.rs:3: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 4 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
10 | x.a();
| ^^^
|
note: method `a` is not const because trait `Foo` is not const
--> const-super-trait.rs:3:1
|
3 | trait Foo {
| ^^^^^^^^^ this trait is not const
4 | fn a(&self);
| ------------ this method is not const
= help: const traits are not yet supported on stable Rust
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants

error: aborting due to 6 previous errors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
10 | x.a();
| ^^^
|
note: method `a` is not const because trait `Foo` is not const
--> const-super-trait.rs:3:1
|
3 | trait Foo {
| ^^^^^^^^^ this trait is not const
4 | fn a(&self);
| ------------ this method is not const
= help: const traits are not yet supported on stable Rust
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants

error: aborting due to 5 previous errors
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/asm/non-const.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/borrowck/issue-64453.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/consts/const-call.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/consts/const-eval/format.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/consts/const-fn-not-safe-for-const.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/consts/control-flow/issue-46843.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/consts/issue-16538.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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(|| ...)`

Expand Down
15 changes: 15 additions & 0 deletions tests/ui/consts/issue-32829-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(|| ...)`

Expand All @@ -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(|| ...)`

Expand Down
5 changes: 5 additions & 0 deletions tests/ui/consts/issue-43105.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/consts/mir_check_nonconst.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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(|| ...)`

Expand Down
5 changes: 5 additions & 0 deletions tests/ui/error-codes/E0015.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading