move required_consts check to general post-mono-check function
This commit is contained in:
parent
ccf817b9bb
commit
89ac57db4d
40 changed files with 319 additions and 257 deletions
|
@ -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 {
|
||||
|
|
|
@ -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))),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue