1
Fork 0

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`
This commit is contained in:
bors 2023-09-18 19:41:21 +00:00
commit cebb9cfd4f
76 changed files with 385 additions and 361 deletions

View file

@ -4,7 +4,7 @@ use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, IntoDiagnostic, IntoDi
use rustc_middle::mir::AssertKind;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::{layout::LayoutError, ConstInt};
use rustc_span::{ErrorGuaranteed, Span, Symbol};
use rustc_span::{ErrorGuaranteed, Span, Symbol, DUMMY_SP};
use super::InterpCx;
use crate::errors::{self, FrameNote, ReportErrorExt};
@ -134,11 +134,11 @@ where
// Don't emit a new diagnostic for these errors, they are already reported elsewhere or
// should remain silent.
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
ErrorHandled::TooGeneric
ErrorHandled::TooGeneric(span.unwrap_or(DUMMY_SP))
}
err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar),
err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span.unwrap_or(DUMMY_SP)),
err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
ErrorHandled::Reported(guar.into())
ErrorHandled::Reported(guar.into(), span.unwrap_or(DUMMY_SP))
}
// Report remaining errors.
_ => {
@ -152,7 +152,7 @@ where
// Use *our* span to label the interp error
err.span_label(our_span, msg);
ErrorHandled::Reported(err.emit().into())
ErrorHandled::Reported(err.emit().into(), span)
}
}
}

View file

@ -212,7 +212,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
key.param_env = key.param_env.with_user_facing();
match tcx.eval_to_const_value_raw(key) {
// try again with reveal all as requested
Err(ErrorHandled::TooGeneric) => {}
Err(ErrorHandled::TooGeneric(_)) => {}
// deduplicate calls
other => return other,
}
@ -259,7 +259,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
key.param_env = key.param_env.with_user_facing();
match tcx.eval_to_allocation_raw(key) {
// try again with reveal all as requested
Err(ErrorHandled::TooGeneric) => {}
Err(ErrorHandled::TooGeneric(_)) => {}
// deduplicate calls
other => return other,
}

View file

@ -239,13 +239,6 @@ pub struct LongRunningWarn {
pub item_span: Span,
}
#[derive(Diagnostic)]
#[diag(const_eval_erroneous_constant)]
pub(crate) struct ErroneousConstUsed {
#[primary_span]
pub span: Span,
}
#[derive(Subdiagnostic)]
#[note(const_eval_non_const_impl)]
pub(crate) struct NonConstImplNote {

View file

@ -7,7 +7,7 @@ use hir::CRATE_HIR_ID;
use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
use rustc_index::IndexVec;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{ErrorHandled, InterpError, InvalidMetaKind, ReportedErrorInfo};
use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{
self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers,
@ -21,10 +21,10 @@ use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayou
use super::{
AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace,
MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, PointerArithmetic,
MemPlaceMeta, Memory, MemoryKind, OpTy, Operand, Place, PlaceTy, Pointer, PointerArithmetic,
Projectable, Provenance, Scalar, StackPopJump,
};
use crate::errors::{self, ErroneousConstUsed};
use crate::errors;
use crate::util;
use crate::{fluent_generated as fluent, ReportErrorExt};
@ -556,7 +556,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
>(
&self,
value: T,
) -> Result<T, InterpError<'tcx>> {
) -> Result<T, ErrorHandled> {
self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value)
}
@ -566,7 +566,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
&self,
frame: &Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>,
value: T,
) -> Result<T, InterpError<'tcx>> {
) -> Result<T, ErrorHandled> {
frame
.instance
.try_subst_mir_and_normalize_erasing_regions(
@ -574,7 +574,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.param_env,
ty::EarlyBinder::bind(value),
)
.map_err(|_| err_inval!(TooGeneric))
.map_err(|_| ErrorHandled::TooGeneric(self.cur_span()))
}
/// The `args` are assumed to already be in our interpreter "universe" (param_env).
@ -750,11 +750,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
if M::POST_MONO_CHECKS {
for ct in &body.required_consts {
let span = ct.span;
let ct = self.subst_from_current_frame_and_normalize_erasing_regions(ct.literal)?;
self.eval_mir_constant(&ct, Some(span), None)?;
}
// `ctfe_query` does some error message decoration that we want to be in effect here.
self.ctfe_query(None, |tcx| {
body.post_mono_checks(*tcx, self.param_env, |c| {
self.subst_from_current_frame_and_normalize_erasing_regions(c)
})
})?;
}
// done
@ -1059,28 +1060,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
&self,
span: Option<Span>,
query: impl FnOnce(TyCtxtAt<'tcx>) -> Result<T, ErrorHandled>,
) -> InterpResult<'tcx, T> {
) -> Result<T, ErrorHandled> {
// Use a precise span for better cycle errors.
query(self.tcx.at(span.unwrap_or_else(|| self.cur_span()))).map_err(|err| {
match err {
ErrorHandled::Reported(err) => {
if !err.is_tainted_by_errors() && let Some(span) = span {
// To make it easier to figure out where this error comes from, also add a note at the current location.
self.tcx.sess.emit_note(ErroneousConstUsed { span });
}
err_inval!(AlreadyReported(err))
}
ErrorHandled::TooGeneric => err_inval!(TooGeneric),
}
.into()
err.emit_note(*self.tcx);
err
})
}
pub fn eval_global(
&self,
gid: GlobalId<'tcx>,
span: Option<Span>,
instance: ty::Instance<'tcx>,
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
let gid = GlobalId { instance, promoted: None };
// For statics we pick `ParamEnv::reveal_all`, because statics don't have generics
// and thus don't care about the parameter environment. While we could just use
// `self.param_env`, that would mean we invoke the query to evaluate the static
@ -1091,10 +1083,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} else {
self.param_env
};
let val = self.ctfe_query(span, |tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?;
let val = self.ctfe_query(None, |tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?;
self.raw_const_to_mplace(val)
}
pub fn eval_mir_constant(
&self,
val: &mir::ConstantKind<'tcx>,
span: Option<Span>,
layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
let const_val = self.ctfe_query(span, |tcx| val.eval(*tcx, self.param_env, span))?;
self.const_val_to_op(const_val, val.ty(), layout)
}
#[must_use]
pub fn dump_place(
&self,

View file

@ -8,15 +8,14 @@ use either::{Either, Left, Right};
use rustc_hir::def::Namespace;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
use rustc_middle::ty::{ConstInt, Ty, ValTree};
use rustc_middle::ty::{ConstInt, Ty};
use rustc_middle::{mir, ty};
use rustc_span::Span;
use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size};
use super::{
alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, Frame, GlobalId,
InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, PlaceTy, Pointer,
Projectable, Provenance, Scalar,
alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, Frame, InterpCx,
InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, PlaceTy, Pointer, Projectable,
Provenance, Scalar,
};
/// An `Immediate` represents a single immediate self-contained Rust value.
@ -701,54 +700,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok(op)
}
fn eval_ty_constant(
&self,
val: ty::Const<'tcx>,
span: Option<Span>,
) -> InterpResult<'tcx, ValTree<'tcx>> {
Ok(match val.kind() {
ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(..) => {
throw_inval!(TooGeneric)
}
// FIXME(generic_const_exprs): `ConstKind::Expr` should be able to be evaluated
ty::ConstKind::Expr(_) => throw_inval!(TooGeneric),
ty::ConstKind::Error(reported) => {
throw_inval!(AlreadyReported(reported.into()))
}
ty::ConstKind::Unevaluated(uv) => {
let instance = self.resolve(uv.def, uv.args)?;
let cid = GlobalId { instance, promoted: None };
self.ctfe_query(span, |tcx| tcx.eval_to_valtree(self.param_env.and(cid)))?
.unwrap_or_else(|| bug!("unable to create ValTree for {uv:?}"))
}
ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => {
span_bug!(self.cur_span(), "unexpected ConstKind in ctfe: {val:?}")
}
ty::ConstKind::Value(valtree) => valtree,
})
}
pub fn eval_mir_constant(
&self,
val: &mir::ConstantKind<'tcx>,
span: Option<Span>,
layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
match *val {
mir::ConstantKind::Ty(ct) => {
let ty = ct.ty();
let valtree = self.eval_ty_constant(ct, span)?;
let const_val = self.tcx.valtree_to_const_val((ty, valtree));
self.const_val_to_op(const_val, ty, layout)
}
mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout),
mir::ConstantKind::Unevaluated(uv, _) => {
let instance = self.resolve(uv.def, uv.args)?;
Ok(self.eval_global(GlobalId { instance, promoted: uv.promoted }, span)?.into())
}
}
}
pub(crate) fn const_val_to_op(
&self,
val_val: ConstValue<'tcx>,