about summary refs log tree commit diff
path: root/compiler/rustc_mir/src/const_eval/eval_queries.rs
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2021-01-24 12:50:30 +0100
committerRalf Jung <post@ralfj.de>2021-01-24 13:34:34 +0100
commit48f9dbfd59356f865f81ce674eefdbab2d7c3cbb (patch)
tree32f1a61dd64449d8ae99b6e16f948f080a1e837a /compiler/rustc_mir/src/const_eval/eval_queries.rs
parent4d0dd02ee07bddad9136f95c9f7846ebf3eb3fc5 (diff)
downloadrust-48f9dbfd59356f865f81ce674eefdbab2d7c3cbb.tar.gz
rust-48f9dbfd59356f865f81ce674eefdbab2d7c3cbb.zip
clean up some const error reporting around promoteds
Diffstat (limited to 'compiler/rustc_mir/src/const_eval/eval_queries.rs')
-rw-r--r--compiler/rustc_mir/src/const_eval/eval_queries.rs102
1 files changed, 28 insertions, 74 deletions
diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs
index df163f65628..252f5e7ef2f 100644
--- a/compiler/rustc_mir/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs
@@ -298,6 +298,8 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
         tcx.def_span(def.did),
         key.param_env,
         CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
+        // Statics (and promoteds inside statics) may access other statics, because unlike consts
+        // they do not have to behave "as if" they were evaluated at runtime.
         MemoryExtra { can_access_statics: is_static },
     );
 
@@ -305,83 +307,35 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
     match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) {
         Err(error) => {
             let err = ConstEvalErr::new(&ecx, error, None);
-            // errors in statics are always emitted as fatal errors
-            if is_static {
-                // Ensure that if the above error was either `TooGeneric` or `Reported`
-                // an error must be reported.
-                let v = err.report_as_error(
-                    ecx.tcx.at(ecx.cur_span()),
-                    "could not evaluate static initializer",
-                );
-
-                // If this is `Reveal:All`, then we need to make sure an error is reported but if
-                // this is `Reveal::UserFacing`, then it's expected that we could get a
-                // `TooGeneric` error. When we fall back to `Reveal::All`, then it will either
-                // succeed or we'll report this error then.
-                if key.param_env.reveal() == Reveal::All {
-                    tcx.sess.delay_span_bug(
-                        err.span,
-                        &format!("static eval failure did not emit an error: {:#?}", v),
-                    );
-                }
-
-                Err(v)
-            } else if let Some(def) = def.as_local() {
-                // constant defined in this crate, we can figure out a lint level!
-                match tcx.def_kind(def.did.to_def_id()) {
-                    // constants never produce a hard error at the definition site. Anything else is
-                    // a backwards compatibility hazard (and will break old versions of winapi for
-                    // sure)
-                    //
-                    // note that validation may still cause a hard error on this very same constant,
-                    // because any code that existed before validation could not have failed
-                    // validation thus preventing such a hard error from being a backwards
-                    // compatibility hazard
-                    DefKind::Const | DefKind::AssocConst => {
-                        let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
-                        Err(err.report_as_lint(
-                            tcx.at(tcx.def_span(def.did)),
-                            "any use of this value will cause an error",
-                            hir_id,
-                            Some(err.span),
-                        ))
-                    }
-                    // promoting runtime code is only allowed to error if it references broken
-                    // constants any other kind of error will be reported to the user as a
-                    // deny-by-default lint
-                    _ => {
-                        if let Some(p) = cid.promoted {
-                            let span = tcx.promoted_mir_opt_const_arg(def.to_global())[p].span;
-                            if let err_inval!(ReferencedConstant) = err.error {
-                                Err(err.report_as_error(
-                                    tcx.at(span),
-                                    "evaluation of constant expression failed",
-                                ))
-                            } else {
-                                Err(err.report_as_lint(
-                                    tcx.at(span),
-                                    "reaching this expression at runtime will panic or abort",
-                                    tcx.hir().local_def_id_to_hir_id(def.did),
-                                    Some(err.span),
-                                ))
-                            }
-                        // anything else (array lengths, enum initializers, constant patterns) are
-                        // reported as hard errors
-                        } else {
-                            Err(err.report_as_error(
-                                ecx.tcx.at(ecx.cur_span()),
-                                "evaluation of constant value failed",
-                            ))
-                        }
-                    }
-                }
+            // Some CTFE errors raise just a lint, not a hard error; see
+            // <https://github.com/rust-lang/rust/issues/71800>.
+            let emit_as_lint = if let Some(def) = def.as_local() {
+                // (Associated) consts only emit a lint, since they might be unused.
+                matches!(tcx.def_kind(def.did.to_def_id()), DefKind::Const | DefKind::AssocConst)
             } else {
-                // use of broken constant from other crate
-                Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), "could not evaluate constant"))
+                // use of broken constant from other crate: always an error
+                false
+            };
+            if emit_as_lint {
+                let hir_id = tcx.hir().local_def_id_to_hir_id(def.as_local().unwrap().did);
+                Err(err.report_as_lint(
+                    tcx.at(tcx.def_span(def.did)),
+                    "any use of this value will cause an error",
+                    hir_id,
+                    Some(err.span),
+                ))
+            } else {
+                let msg = if is_static {
+                    "could not evaluate static initializer"
+                } else {
+                    "evaluation of constant value failed"
+                };
+                Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), msg))
             }
         }
         Ok(mplace) => {
-            // Since evaluation had no errors, valiate the resulting constant:
+            // Since evaluation had no errors, validate the resulting constant.
+            // This is a separate `try` block to provide more targeted error reporting.
             let validation = try {
                 let mut ref_tracking = RefTracking::new(mplace);
                 let mut inner = false;
@@ -399,7 +353,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
                 }
             };
             if let Err(error) = validation {
-                // Validation failed, report an error
+                // Validation failed, report an error. This is always a hard error.
                 let err = ConstEvalErr::new(&ecx, error, None);
                 Err(err.struct_error(
                     ecx.tcx,