Handle Fn family trait call errror
This commit is contained in:
parent
6d6314f878
commit
d3acb9d00e
10 changed files with 57 additions and 13 deletions
|
@ -196,8 +196,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
.map(|n| format!("`{}`", n))
|
.map(|n| format!("`{}`", n))
|
||||||
.unwrap_or_else(|| "value".to_owned());
|
.unwrap_or_else(|| "value".to_owned());
|
||||||
match kind {
|
match kind {
|
||||||
CallKind::FnCall(once_did)
|
CallKind::FnCall { fn_trait_id, .. }
|
||||||
if Some(once_did) == self.infcx.tcx.lang_items().fn_once_trait() =>
|
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
|
||||||
{
|
{
|
||||||
err.span_label(
|
err.span_label(
|
||||||
fn_call_span,
|
fn_call_span,
|
||||||
|
|
|
@ -8,7 +8,9 @@ use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
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_middle::ty::{Binder, BoundConstness, ImplPolarity, TraitRef};
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
@ -155,7 +157,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
||||||
CallKind::Normal { desugaring: Some((kind, self_ty)), .. } => {
|
CallKind::Normal { desugaring: Some((kind, self_ty)), .. } => {
|
||||||
macro_rules! error {
|
macro_rules! error {
|
||||||
($fmt:literal) => {
|
($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))
|
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, .. } => {
|
CallKind::Operator { trait_id, self_ty, .. } => {
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
tcx.sess,
|
tcx.sess,
|
||||||
|
|
|
@ -44,7 +44,7 @@ pub enum CallKind<'tcx> {
|
||||||
is_option_or_result: bool,
|
is_option_or_result: bool,
|
||||||
},
|
},
|
||||||
/// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)`
|
/// 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`)
|
/// 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> },
|
Operator { self_arg: Option<Ident>, trait_id: DefId, self_ty: Ty<'tcx> },
|
||||||
DerefCoercion {
|
DerefCoercion {
|
||||||
|
@ -85,7 +85,7 @@ pub fn call_kind<'tcx>(
|
||||||
// an FnOnce call, an operator (e.g. `<<`), or a
|
// an FnOnce call, an operator (e.g. `<<`), or a
|
||||||
// deref coercion.
|
// deref coercion.
|
||||||
let kind = if let Some(&trait_id) = fn_call {
|
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 {
|
} else if let Some(&trait_id) = operator {
|
||||||
Some(CallKind::Operator { self_arg, trait_id, self_ty: method_substs.type_at(0) })
|
Some(CallKind::Operator { self_arg, trait_id, self_ty: method_substs.type_at(0) })
|
||||||
} else if is_deref {
|
} else if is_deref {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
const X: u8 =
|
const X: u8 =
|
||||||
|| -> u8 { 5 }()
|
|| -> u8 { 5 }()
|
||||||
//~^ ERROR cannot call non-const fn
|
//~^ ERROR cannot call non-const closure
|
||||||
;
|
;
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -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
|
--> $DIR/issue-28113.rs:4:5
|
||||||
|
|
|
|
||||||
LL | || -> u8 { 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
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![feature(const_fn_fn_ptr_basics)]
|
#![feature(const_fn_fn_ptr_basics)]
|
||||||
|
|
||||||
const fn foo() { (||{})() }
|
const fn foo() { (||{})() }
|
||||||
//~^ ERROR cannot call non-const fn
|
//~^ ERROR cannot call non-const closure
|
||||||
|
|
||||||
const fn bad(input: fn()) {
|
const fn bad(input: fn()) {
|
||||||
input()
|
input()
|
||||||
|
|
|
@ -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
|
--> $DIR/issue-56164.rs:3:18
|
||||||
|
|
|
|
||||||
LL | const fn foo() { (||{})() }
|
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
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
|
|
||||||
error: function pointers are not allowed in const fn
|
error: function pointers are not allowed in const fn
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// in the length part of an array.
|
// in the length part of an array.
|
||||||
|
|
||||||
struct Bug {
|
struct Bug {
|
||||||
a: [(); (|| { 0 })()] //~ ERROR cannot call non-const fn
|
a: [(); (|| { 0 })()] //~ ERROR cannot call non-const closure
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -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
|
--> $DIR/issue-68542-closure-in-array-len.rs:6:13
|
||||||
|
|
|
|
||||||
LL | a: [(); (|| { 0 })()]
|
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
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
|
@ -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
|
--> $DIR/unstable-const-fn-in-libcore.rs:24:26
|
||||||
|
|
|
|
||||||
LL | Opt::None => f(),
|
LL | Opt::None => f(),
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
= 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
|
error[E0493]: destructors cannot be evaluated at compile-time
|
||||||
--> $DIR/unstable-const-fn-in-libcore.rs:19:53
|
--> $DIR/unstable-const-fn-in-libcore.rs:19:53
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue