about summary refs log tree commit diff
path: root/compiler/rustc_middle/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-09-18 19:41:21 +0000
committerbors <bors@rust-lang.org>2023-09-18 19:41:21 +0000
commitcebb9cfd4f0052fbb5e98f9b6f3a61dae8fd96a7 (patch)
tree8cab476d937833d4744831c22fd1d5493e857455 /compiler/rustc_middle/src
parentb1575cb72ef40459666f802af8636faf8428e3eb (diff)
parent9ac8b363e3227fdc08634ce445b7787aa0fa6bba (diff)
downloadrust-cebb9cfd4f0052fbb5e98f9b6f3a61dae8fd96a7.tar.gz
rust-cebb9cfd4f0052fbb5e98f9b6f3a61dae8fd96a7.zip
Auto merge of #115748 - RalfJung:post-mono, r=oli-obk
move required_consts check to general post-mono-check function

This factors some code that is common between the interpreter and the codegen backends into shared helper functions. Also as a side-effect the interpreter now uses the same `eval` functions as everyone else to get the evaluated MIR constants.

Also this is in preparation for another post-mono check that will be needed for (the current hackfix for) https://github.com/rust-lang/rust/issues/115709: ensuring that all locals are dynamically sized.

I didn't expect this to change diagnostics, but it's just cycle errors that change.

r? `@oli-obk`
Diffstat (limited to 'compiler/rustc_middle/src')
-rw-r--r--compiler/rustc_middle/src/error.rs7
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs62
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs18
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs32
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs4
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs6
6 files changed, 105 insertions, 24 deletions
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index b346cd45391..3c553657087 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -144,5 +144,12 @@ pub struct UnsupportedFnAbi {
     pub abi: &'static str,
 }
 
+#[derive(Diagnostic)]
+#[diag(middle_erroneous_constant)]
+pub struct ErroneousConstant {
+    #[primary_span]
+    pub span: Span,
+}
+
 /// Used by `rustc_const_eval`
 pub use crate::fluent_generated::middle_adjust_for_foreign_abi_error;
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 2194ef81cec..eb4614745d5 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -1,8 +1,9 @@
 use super::{AllocId, AllocRange, ConstAlloc, Pointer, Scalar};
 
+use crate::error;
 use crate::mir::interpret::ConstValue;
 use crate::query::TyCtxtAt;
-use crate::ty::{layout, tls, Ty, ValTree};
+use crate::ty::{layout, tls, Ty, TyCtxt, ValTree};
 
 use rustc_data_structures::sync::Lock;
 use rustc_errors::{
@@ -11,7 +12,7 @@ use rustc_errors::{
 };
 use rustc_macros::HashStable;
 use rustc_session::CtfeBacktrace;
-use rustc_span::def_id::DefId;
+use rustc_span::{def_id::DefId, Span, DUMMY_SP};
 use rustc_target::abi::{call, Align, Size, VariantIdx, WrappingRange};
 
 use std::borrow::Cow;
@@ -21,16 +22,51 @@ use std::{any::Any, backtrace::Backtrace, fmt};
 pub enum ErrorHandled {
     /// Already reported an error for this evaluation, and the compilation is
     /// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
-    Reported(ReportedErrorInfo),
+    Reported(ReportedErrorInfo, Span),
     /// Don't emit an error, the evaluation failed because the MIR was generic
     /// and the args didn't fully monomorphize it.
-    TooGeneric,
+    TooGeneric(Span),
 }
 
 impl From<ErrorGuaranteed> for ErrorHandled {
     #[inline]
     fn from(error: ErrorGuaranteed) -> ErrorHandled {
-        ErrorHandled::Reported(error.into())
+        ErrorHandled::Reported(error.into(), DUMMY_SP)
+    }
+}
+
+impl ErrorHandled {
+    pub fn with_span(self, span: Span) -> Self {
+        match self {
+            ErrorHandled::Reported(err, _span) => ErrorHandled::Reported(err, span),
+            ErrorHandled::TooGeneric(_span) => ErrorHandled::TooGeneric(span),
+        }
+    }
+
+    pub fn emit_err(&self, tcx: TyCtxt<'_>) -> ErrorGuaranteed {
+        match self {
+            &ErrorHandled::Reported(err, span) => {
+                if !err.is_tainted_by_errors && !span.is_dummy() {
+                    tcx.sess.emit_err(error::ErroneousConstant { span });
+                }
+                err.error
+            }
+            &ErrorHandled::TooGeneric(span) => tcx.sess.delay_span_bug(
+                span,
+                "encountered TooGeneric error when monomorphic data was expected",
+            ),
+        }
+    }
+
+    pub fn emit_note(&self, tcx: TyCtxt<'_>) {
+        match self {
+            &ErrorHandled::Reported(err, span) => {
+                if !err.is_tainted_by_errors && !span.is_dummy() {
+                    tcx.sess.emit_note(error::ErroneousConstant { span });
+                }
+            }
+            &ErrorHandled::TooGeneric(_) => {}
+        }
     }
 }
 
@@ -45,12 +81,6 @@ impl ReportedErrorInfo {
     pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo {
         ReportedErrorInfo { is_tainted_by_errors: true, error }
     }
-
-    /// Returns true if evaluation failed because MIR was tainted by errors.
-    #[inline]
-    pub fn is_tainted_by_errors(self) -> bool {
-        self.is_tainted_by_errors
-    }
 }
 
 impl From<ErrorGuaranteed> for ReportedErrorInfo {
@@ -162,6 +192,16 @@ impl From<ErrorGuaranteed> for InterpErrorInfo<'_> {
     }
 }
 
+impl From<ErrorHandled> for InterpErrorInfo<'_> {
+    fn from(err: ErrorHandled) -> Self {
+        InterpError::InvalidProgram(match err {
+            ErrorHandled::Reported(r, _span) => InvalidProgramInfo::AlreadyReported(r),
+            ErrorHandled::TooGeneric(_span) => InvalidProgramInfo::TooGeneric,
+        })
+        .into()
+    }
+}
+
 impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
     fn from(kind: InterpError<'tcx>) -> Self {
         InterpErrorInfo(Box::new(InterpErrorInfoInner {
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index fc659ce18a4..fbf6403eabe 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -61,8 +61,10 @@ impl<'tcx> TyCtxt<'tcx> {
                 let cid = GlobalId { instance, promoted: ct.promoted };
                 self.const_eval_global_id(param_env, cid, span)
             }
-            Ok(None) => Err(ErrorHandled::TooGeneric),
-            Err(err) => Err(ErrorHandled::Reported(err.into())),
+            // For errors during resolution, we deliberately do not point at the usage site of the constant,
+            // since for these errors the place the constant is used shouldn't matter.
+            Ok(None) => Err(ErrorHandled::TooGeneric(DUMMY_SP)),
+            Err(err) => Err(ErrorHandled::Reported(err.into(), DUMMY_SP)),
         }
     }
 
@@ -117,8 +119,10 @@ impl<'tcx> TyCtxt<'tcx> {
                     }
                 })
             }
-            Ok(None) => Err(ErrorHandled::TooGeneric),
-            Err(err) => Err(ErrorHandled::Reported(err.into())),
+            // For errors during resolution, we deliberately do not point at the usage site of the constant,
+            // since for these errors the place the constant is used shouldn't matter.
+            Ok(None) => Err(ErrorHandled::TooGeneric(DUMMY_SP)),
+            Err(err) => Err(ErrorHandled::Reported(err.into(), DUMMY_SP)),
         }
     }
 
@@ -143,7 +147,8 @@ impl<'tcx> TyCtxt<'tcx> {
         // improve caching of queries.
         let inputs = self.erase_regions(param_env.and(cid));
         if let Some(span) = span {
-            self.at(span).eval_to_const_value_raw(inputs)
+            // The query doesn't know where it is being invoked, so we need to fix the span.
+            self.at(span).eval_to_const_value_raw(inputs).map_err(|e| e.with_span(span))
         } else {
             self.eval_to_const_value_raw(inputs)
         }
@@ -162,7 +167,8 @@ impl<'tcx> TyCtxt<'tcx> {
         let inputs = self.erase_regions(param_env.and(cid));
         debug!(?inputs);
         if let Some(span) = span {
-            self.at(span).eval_to_valtree(inputs)
+            // The query doesn't know where it is being invoked, so we need to fix the span.
+            self.at(span).eval_to_valtree(inputs).map_err(|e| e.with_span(span))
         } else {
             self.eval_to_valtree(inputs)
         }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 5e749776992..b8032733868 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -565,6 +565,34 @@ impl<'tcx> Body<'tcx> {
     pub fn is_custom_mir(&self) -> bool {
         self.injection_phase.is_some()
     }
+
+    /// *Must* be called once the full substitution for this body is known, to ensure that the body
+    /// is indeed fit for code generation or consumption more generally.
+    ///
+    /// Sadly there's no nice way to represent an "arbitrary normalizer", so we take one for
+    /// constants specifically. (`Option<GenericArgsRef>` could be used for that, but the fact
+    /// that `Instance::args_for_mir_body` is private and instead instance exposes normalization
+    /// functions makes it seem like exposing the generic args is not the intended strategy.)
+    ///
+    /// Also sadly, CTFE doesn't even know whether it runs on MIR that is already polymorphic or still monomorphic,
+    /// so we cannot just immediately ICE on TooGeneric.
+    ///
+    /// Returns Ok(()) if everything went fine, and `Err` if a problem occurred and got reported.
+    pub fn post_mono_checks(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        normalize_const: impl Fn(ConstantKind<'tcx>) -> Result<ConstantKind<'tcx>, ErrorHandled>,
+    ) -> Result<(), ErrorHandled> {
+        // For now, the only thing we have to check is is to ensure that all the constants used in
+        // the body successfully evaluate.
+        for &const_ in &self.required_consts {
+            let c = normalize_const(const_.literal)?;
+            c.eval(tcx, param_env, Some(const_.span))?;
+        }
+
+        Ok(())
+    }
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
@@ -2397,10 +2425,10 @@ impl<'tcx> ConstantKind<'tcx> {
     pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
         match self.eval(tcx, param_env, None) {
             Ok(val) => Self::Val(val, self.ty()),
-            Err(ErrorHandled::Reported(guar)) => {
+            Err(ErrorHandled::Reported(guar, _span)) => {
                 Self::Ty(ty::Const::new_error(tcx, guar.into(), self.ty()))
             }
-            Err(ErrorHandled::TooGeneric) => self,
+            Err(ErrorHandled::TooGeneric(_span)) => self,
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index b4c6e0d970a..219927f5ab4 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -478,8 +478,8 @@ impl<'tcx> AdtDef<'tcx> {
             }
             Err(err) => {
                 let msg = match err {
-                    ErrorHandled::Reported(_) => "enum discriminant evaluation failed",
-                    ErrorHandled::TooGeneric => "enum discriminant depends on generics",
+                    ErrorHandled::Reported(..) => "enum discriminant evaluation failed",
+                    ErrorHandled::TooGeneric(..) => "enum discriminant depends on generics",
                 };
                 tcx.sess.delay_span_bug(tcx.def_span(expr_did), msg);
                 None
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 629f9f8cd7d..ba871d6478b 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -300,7 +300,7 @@ impl<'tcx> Const<'tcx> {
             | ConstKind::Infer(_)
             | ConstKind::Bound(_, _)
             | ConstKind::Placeholder(_)
-            | ConstKind::Expr(_) => Err(ErrorHandled::TooGeneric),
+            | ConstKind::Expr(_) => Err(ErrorHandled::TooGeneric(span.unwrap_or(DUMMY_SP))),
         }
     }
 
@@ -309,8 +309,8 @@ impl<'tcx> Const<'tcx> {
     pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
         match self.eval(tcx, param_env, None) {
             Ok(val) => Self::new_value(tcx, val, self.ty()),
-            Err(ErrorHandled::Reported(r)) => Self::new_error(tcx, r.into(), self.ty()),
-            Err(ErrorHandled::TooGeneric) => self,
+            Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into(), self.ty()),
+            Err(ErrorHandled::TooGeneric(_span)) => self,
         }
     }