From d3acb9d00e64d68d8c91c9d9925b92cd79b33379 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 29 Dec 2021 17:05:54 +0800 Subject: [PATCH] Handle Fn family trait call errror --- .../src/diagnostics/conflict_errors.rs | 4 +- .../src/transform/check_consts/ops.rs | 41 ++++++++++++++++++- .../rustc_const_eval/src/util/call_kind.rs | 4 +- src/test/ui/consts/issue-28113.rs | 2 +- src/test/ui/consts/issue-28113.stderr | 3 +- src/test/ui/consts/issue-56164.rs | 2 +- src/test/ui/consts/issue-56164.stderr | 3 +- .../issue-68542-closure-in-array-len.rs | 2 +- .../issue-68542-closure-in-array-len.stderr | 3 +- .../unstable-const-fn-in-libcore.stderr | 6 ++- 10 files changed, 57 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index ff1d37bfccb..f6d21f879ff 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -196,8 +196,8 @@ pub(crate) fn report_use_of_moved_or_uninitialized( .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, diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 237201c5478..519b4c02b61 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -8,7 +8,9 @@ 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 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> DiagnosticBuilder<'tc 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 @@ macro_rules! error { 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, diff --git a/compiler/rustc_const_eval/src/util/call_kind.rs b/compiler/rustc_const_eval/src/util/call_kind.rs index fe35d942341..11bb9508a1f 100644 --- a/compiler/rustc_const_eval/src/util/call_kind.rs +++ b/compiler/rustc_const_eval/src/util/call_kind.rs @@ -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, 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 { diff --git a/src/test/ui/consts/issue-28113.rs b/src/test/ui/consts/issue-28113.rs index 1d93d454af7..f8131c9f3b7 100644 --- a/src/test/ui/consts/issue-28113.rs +++ b/src/test/ui/consts/issue-28113.rs @@ -2,7 +2,7 @@ const X: u8 = || -> u8 { 5 }() - //~^ ERROR cannot call non-const fn + //~^ ERROR cannot call non-const closure ; fn main() {} diff --git a/src/test/ui/consts/issue-28113.stderr b/src/test/ui/consts/issue-28113.stderr index 75fcc010a04..7ad1f752eb0 100644 --- a/src/test/ui/consts/issue-28113.stderr +++ b/src/test/ui/consts/issue-28113.stderr @@ -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 diff --git a/src/test/ui/consts/issue-56164.rs b/src/test/ui/consts/issue-56164.rs index af65720916c..9c673d20b2a 100644 --- a/src/test/ui/consts/issue-56164.rs +++ b/src/test/ui/consts/issue-56164.rs @@ -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() diff --git a/src/test/ui/consts/issue-56164.stderr b/src/test/ui/consts/issue-56164.stderr index af5d44d4814..62a7c7db6b8 100644 --- a/src/test/ui/consts/issue-56164.stderr +++ b/src/test/ui/consts/issue-56164.stderr @@ -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 diff --git a/src/test/ui/consts/issue-68542-closure-in-array-len.rs b/src/test/ui/consts/issue-68542-closure-in-array-len.rs index 44f44da234a..37958e7919d 100644 --- a/src/test/ui/consts/issue-68542-closure-in-array-len.rs +++ b/src/test/ui/consts/issue-68542-closure-in-array-len.rs @@ -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() {} diff --git a/src/test/ui/consts/issue-68542-closure-in-array-len.stderr b/src/test/ui/consts/issue-68542-closure-in-array-len.stderr index 3787138afc3..74fbbc680f7 100644 --- a/src/test/ui/consts/issue-68542-closure-in-array-len.stderr +++ b/src/test/ui/consts/issue-68542-closure-in-array-len.stderr @@ -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 diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr index 435141134cb..4ef25bd1334 100644 --- a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr @@ -1,10 +1,14 @@ -error[E0015]: cannot call non-const fn `>::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 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