about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDeadbeef <ent3rm4n@gmail.com>2021-12-29 17:05:54 +0800
committerDeadbeef <ent3rm4n@gmail.com>2022-02-12 19:24:43 +1100
commitd3acb9d00e64d68d8c91c9d9925b92cd79b33379 (patch)
tree44891fbd41e701febd1ffab7efb41a9a3891d870
parent6d6314f878bf489e15293498ecb4af082c8d53d8 (diff)
downloadrust-d3acb9d00e64d68d8c91c9d9925b92cd79b33379.tar.gz
rust-d3acb9d00e64d68d8c91c9d9925b92cd79b33379.zip
Handle Fn family trait call errror
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs41
-rw-r--r--compiler/rustc_const_eval/src/util/call_kind.rs4
-rw-r--r--src/test/ui/consts/issue-28113.rs2
-rw-r--r--src/test/ui/consts/issue-28113.stderr3
-rw-r--r--src/test/ui/consts/issue-56164.rs2
-rw-r--r--src/test/ui/consts/issue-56164.stderr3
-rw-r--r--src/test/ui/consts/issue-68542-closure-in-array-len.rs2
-rw-r--r--src/test/ui/consts/issue-68542-closure-in-array-len.stderr3
-rw-r--r--src/test/ui/consts/unstable-const-fn-in-libcore.stderr6
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 @@ 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,
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_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,
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<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 {
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 `<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