diff options
Diffstat (limited to 'compiler/rustc_middle')
| -rw-r--r-- | compiler/rustc_middle/src/mir/interpret/error.rs | 27 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/interpret/queries.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/mod.rs | 35 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/adt.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/consts.rs | 6 |
5 files changed, 65 insertions, 15 deletions
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 7e3be0b5d5f..0a7296e7c78 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -11,7 +11,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 +21,25 @@ 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), + } } } @@ -162,6 +171,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..71e648bab6a 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -61,8 +61,8 @@ 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())), + Ok(None) => Err(ErrorHandled::TooGeneric(span.unwrap_or(DUMMY_SP))), + Err(err) => Err(ErrorHandled::Reported(err.into(), span.unwrap_or(DUMMY_SP))), } } @@ -117,8 +117,8 @@ impl<'tcx> TyCtxt<'tcx> { } }) } - Ok(None) => Err(ErrorHandled::TooGeneric), - Err(err) => Err(ErrorHandled::Reported(err.into())), + Ok(None) => Err(ErrorHandled::TooGeneric(span.unwrap_or(DUMMY_SP))), + Err(err) => Err(ErrorHandled::Reported(err.into(), span.unwrap_or(DUMMY_SP))), } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 8df3a79b4d4..95d27a017fe 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -565,6 +565,37 @@ 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)).map_err(|e| { + // The query results don't always have the span we want. + e.with_span(const_.span) + })?; + } + + Ok(()) + } } #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)] @@ -2397,10 +2428,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, } } |
