Skip to content
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

More informative error message for E0015 #90532

Merged
merged 8 commits into from
Feb 13, 2022
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Handle Fn family trait call errror
fee1-dead committed Feb 12, 2022

Verified

This commit was signed with the committer’s verified signature.
commit d3acb9d00e64d68d8c91c9d9925b92cd79b33379
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
@@ -196,8 +196,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.map(|n| format!("`{}`", n))
.unwrap_or_else(|| "value".to_owned());
match kind {
CallKind::FnCall(once_did)
if Some(once_did) == self.infcx.tcx.lang_items().fn_once_trait() =>
CallKind::FnCall { fn_trait_id, .. }
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
{
err.span_label(
fn_call_span,
41 changes: 39 additions & 2 deletions compiler/rustc_const_eval/src/transform/check_consts/ops.rs
Original file line number Diff line number Diff line change
@@ -8,7 +8,9 @@ use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
use rustc_middle::mir;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{suggest_constraining_type_param, Adt, Param, TraitPredicate, Ty};
use rustc_middle::ty::{
suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, TraitPredicate, Ty,
};
use rustc_middle::ty::{Binder, BoundConstness, ImplPolarity, TraitRef};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
@@ -155,7 +157,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
CallKind::Normal { desugaring: Some((kind, self_ty)), .. } => {
macro_rules! error {
($fmt:literal) => {
struct_span_err!(tcx.sess, span, E0015, $fmt, self_ty, ccx.const_kind(),)
struct_span_err!(tcx.sess, span, E0015, $fmt, self_ty, ccx.const_kind())
};
}

@@ -176,6 +178,41 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {

diag_trait(err, self_ty, kind.trait_def_id(tcx))
}
CallKind::FnCall { fn_trait_id, self_ty } => {
let mut err = struct_span_err!(
tcx.sess,
span,
E0015,
"cannot call non-const closure in {}s",
ccx.const_kind(),
);

match self_ty.kind() {
FnDef(def_id, ..) => {
let span = tcx.sess.source_map().guess_head_span(tcx.def_span(*def_id));
if ccx.tcx.is_const_fn_raw(*def_id) {
span_bug!(span, "calling const FnDef errored when it shouldn't");
}

err.span_note(span, "function defined here, but it is not `const`");
}
FnPtr(..) => {
err.note(&format!(
"function pointers need an RFC before allowed to be called in {}s",
ccx.const_kind()
));
}
Closure(..) => {
err.note(&format!(
"closures need an RFC before allowed to be called in {}s",
ccx.const_kind()
));
}
_ => {}
}

diag_trait(err, self_ty, fn_trait_id)
}
CallKind::Operator { trait_id, self_ty, .. } => {
let mut err = struct_span_err!(
tcx.sess,
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/util/call_kind.rs
Original file line number Diff line number Diff line change
@@ -44,7 +44,7 @@ pub enum CallKind<'tcx> {
is_option_or_result: bool,
},
/// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)`
FnCall(DefId),
FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> },
/// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`)
Operator { self_arg: Option<Ident>, trait_id: DefId, self_ty: Ty<'tcx> },
DerefCoercion {
@@ -85,7 +85,7 @@ pub fn call_kind<'tcx>(
// an FnOnce call, an operator (e.g. `<<`), or a
// deref coercion.
let kind = if let Some(&trait_id) = fn_call {
Some(CallKind::FnCall(trait_id))
Some(CallKind::FnCall { fn_trait_id: trait_id, self_ty: method_substs.type_at(0) })
} else if let Some(&trait_id) = operator {
Some(CallKind::Operator { self_arg, trait_id, self_ty: method_substs.type_at(0) })
} else if is_deref {
2 changes: 1 addition & 1 deletion src/test/ui/consts/issue-28113.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@

const X: u8 =
|| -> u8 { 5 }()
//~^ ERROR cannot call non-const fn
//~^ ERROR cannot call non-const closure
;

fn main() {}
3 changes: 2 additions & 1 deletion src/test/ui/consts/issue-28113.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
error[E0015]: cannot call non-const fn `<[closure@$DIR/issue-28113.rs:4:5: 4:19] as Fn<()>>::call` in constants
error[E0015]: cannot call non-const closure in constants
--> $DIR/issue-28113.rs:4:5
|
LL | || -> u8 { 5 }()
| ^^^^^^^^^^^^^^^^
|
= note: closures need an RFC before allowed to be called in constants
= note: calls in constants are limited to constant functions, tuple structs and tuple variants

error: aborting due to previous error
2 changes: 1 addition & 1 deletion src/test/ui/consts/issue-56164.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![feature(const_fn_fn_ptr_basics)]

const fn foo() { (||{})() }
//~^ ERROR cannot call non-const fn
//~^ ERROR cannot call non-const closure

const fn bad(input: fn()) {
input()
3 changes: 2 additions & 1 deletion src/test/ui/consts/issue-56164.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
error[E0015]: cannot call non-const fn `<[closure@$DIR/issue-56164.rs:3:18: 3:24] as Fn<()>>::call` in constant functions
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/issue-56164.rs:3:18
|
LL | const fn foo() { (||{})() }
| ^^^^^^^^
|
= note: closures need an RFC before allowed to be called in constant functions
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants

error: function pointers are not allowed in const fn
2 changes: 1 addition & 1 deletion src/test/ui/consts/issue-68542-closure-in-array-len.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
// in the length part of an array.

struct Bug {
a: [(); (|| { 0 })()] //~ ERROR cannot call non-const fn
a: [(); (|| { 0 })()] //~ ERROR cannot call non-const closure
}

fn main() {}
3 changes: 2 additions & 1 deletion src/test/ui/consts/issue-68542-closure-in-array-len.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
error[E0015]: cannot call non-const fn `<[closure@$DIR/issue-68542-closure-in-array-len.rs:6:13: 6:23] as Fn<()>>::call` in constants
error[E0015]: cannot call non-const closure in constants
--> $DIR/issue-68542-closure-in-array-len.rs:6:13
|
LL | a: [(); (|| { 0 })()]
| ^^^^^^^^^^^^
|
= note: closures need an RFC before allowed to be called in constants
= note: calls in constants are limited to constant functions, tuple structs and tuple variants

error: aborting due to previous error
6 changes: 5 additions & 1 deletion src/test/ui/consts/unstable-const-fn-in-libcore.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
error[E0015]: cannot call non-const fn `<F as FnOnce<()>>::call_once` in constant functions
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/unstable-const-fn-in-libcore.rs:24:26
|
LL | Opt::None => f(),
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn unwrap_or_else<F: FnOnce() -> T + ~const std::ops::FnOnce<()>>(self, f: F) -> T {
| +++++++++++++++++++++++++++++

error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/unstable-const-fn-in-libcore.rs:19:53