Skip to content

Commit ba8fb09

Browse files
committed
Handle Fn family trait call errror
1 parent f9f7d13 commit ba8fb09

File tree

10 files changed

+57
-13
lines changed

10 files changed

+57
-13
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
196196
.map(|n| format!("`{}`", n))
197197
.unwrap_or_else(|| "value".to_owned());
198198
match kind {
199-
CallKind::FnCall(once_did)
200-
if Some(once_did) == self.infcx.tcx.lang_items().fn_once_trait() =>
199+
CallKind::FnCall { fn_trait_id, .. }
200+
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
201201
{
202202
err.span_label(
203203
fn_call_span,

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

+39-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
88
use rustc_middle::mir;
99
use rustc_middle::ty::print::with_no_trimmed_paths;
1010
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
11-
use rustc_middle::ty::{suggest_constraining_type_param, Adt, Param, TraitPredicate, Ty};
11+
use rustc_middle::ty::{
12+
suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, TraitPredicate, Ty,
13+
};
1214
use rustc_middle::ty::{Binder, BoundConstness, ImplPolarity, TraitRef};
1315
use rustc_session::parse::feature_err;
1416
use rustc_span::symbol::sym;
@@ -155,7 +157,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
155157
CallKind::Normal { desugaring: Some((kind, self_ty)), .. } => {
156158
macro_rules! error {
157159
($fmt:literal) => {
158-
struct_span_err!(tcx.sess, span, E0015, $fmt, self_ty, ccx.const_kind(),)
160+
struct_span_err!(tcx.sess, span, E0015, $fmt, self_ty, ccx.const_kind())
159161
};
160162
}
161163

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

177179
diag_trait(err, self_ty, kind.trait_def_id(tcx))
178180
}
181+
CallKind::FnCall { fn_trait_id, self_ty } => {
182+
let mut err = struct_span_err!(
183+
tcx.sess,
184+
span,
185+
E0015,
186+
"cannot call non-const closure in {}s",
187+
ccx.const_kind(),
188+
);
189+
190+
match self_ty.kind() {
191+
FnDef(def_id, ..) => {
192+
let span = tcx.sess.source_map().guess_head_span(tcx.def_span(*def_id));
193+
if ccx.tcx.is_const_fn_raw(*def_id) {
194+
span_bug!(span, "calling const FnDef errored when it shouldn't");
195+
}
196+
197+
err.span_note(span, "function defined here, but it is not `const`");
198+
}
199+
FnPtr(..) => {
200+
err.note(&format!(
201+
"function pointers need an RFC before allowed to be called in {}s",
202+
ccx.const_kind()
203+
));
204+
}
205+
Closure(..) => {
206+
err.note(&format!(
207+
"closures need an RFC before allowed to be called in {}s",
208+
ccx.const_kind()
209+
));
210+
}
211+
_ => {}
212+
}
213+
214+
diag_trait(err, self_ty, fn_trait_id)
215+
}
179216
CallKind::Operator { trait_id, self_ty, .. } => {
180217
let mut err = struct_span_err!(
181218
tcx.sess,

compiler/rustc_const_eval/src/util/call_kind.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub enum CallKind<'tcx> {
4444
is_option_or_result: bool,
4545
},
4646
/// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)`
47-
FnCall(DefId),
47+
FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> },
4848
/// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`)
4949
Operator { self_arg: Option<Ident>, trait_id: DefId, self_ty: Ty<'tcx> },
5050
DerefCoercion {
@@ -85,7 +85,7 @@ pub fn call_kind<'tcx>(
8585
// an FnOnce call, an operator (e.g. `<<`), or a
8686
// deref coercion.
8787
let kind = if let Some(&trait_id) = fn_call {
88-
Some(CallKind::FnCall(trait_id))
88+
Some(CallKind::FnCall { fn_trait_id: trait_id, self_ty: method_substs.type_at(0) })
8989
} else if let Some(&trait_id) = operator {
9090
Some(CallKind::Operator { self_arg, trait_id, self_ty: method_substs.type_at(0) })
9191
} else if is_deref {

src/test/ui/consts/issue-28113.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

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

88
fn main() {}

src/test/ui/consts/issue-28113.stderr

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
error[E0015]: cannot call non-const fn `<[closure@$DIR/issue-28113.rs:4:5: 4:19] as Fn<()>>::call` in constants
1+
error[E0015]: cannot call non-const closure in constants
22
--> $DIR/issue-28113.rs:4:5
33
|
44
LL | || -> u8 { 5 }()
55
| ^^^^^^^^^^^^^^^^
66
|
7+
= note: closures need an RFC before allowed to be called in constants
78
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
89

910
error: aborting due to previous error

src/test/ui/consts/issue-56164.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![feature(const_fn_fn_ptr_basics)]
22

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

66
const fn bad(input: fn()) {
77
input()

src/test/ui/consts/issue-56164.stderr

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
error[E0015]: cannot call non-const fn `<[closure@$DIR/issue-56164.rs:3:18: 3:24] as Fn<()>>::call` in constant functions
1+
error[E0015]: cannot call non-const closure in constant functions
22
--> $DIR/issue-56164.rs:3:18
33
|
44
LL | const fn foo() { (||{})() }
55
| ^^^^^^^^
66
|
7+
= note: closures need an RFC before allowed to be called in constant functions
78
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
89

910
error: function pointers are not allowed in const fn

src/test/ui/consts/issue-68542-closure-in-array-len.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// in the length part of an array.
44

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

99
fn main() {}

src/test/ui/consts/issue-68542-closure-in-array-len.stderr

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
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
1+
error[E0015]: cannot call non-const closure in constants
22
--> $DIR/issue-68542-closure-in-array-len.rs:6:13
33
|
44
LL | a: [(); (|| { 0 })()]
55
| ^^^^^^^^^^^^
66
|
7+
= note: closures need an RFC before allowed to be called in constants
78
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
89

910
error: aborting due to previous error

src/test/ui/consts/unstable-const-fn-in-libcore.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
error[E0015]: cannot call non-const fn `<F as FnOnce<()>>::call_once` in constant functions
1+
error[E0015]: cannot call non-const closure in constant functions
22
--> $DIR/unstable-const-fn-in-libcore.rs:24:26
33
|
44
LL | Opt::None => f(),
55
| ^^^
66
|
77
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
8+
help: consider further restricting this bound
9+
|
10+
LL | const fn unwrap_or_else<F: FnOnce() -> T + ~const std::ops::FnOnce<()>>(self, f: F) -> T {
11+
| +++++++++++++++++++++++++++++
812

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

0 commit comments

Comments
 (0)