Auto merge of #83207 - oli-obk:valtree2, r=lcnr
normalize mir::Constant differently from ty::Const in preparation for valtrees Valtrees are unable to represent many kind of constant values (this is on purpose). For constants that are used at runtime, we do not need a valtree representation and can thus use a different form of evaluation. In order to make this explicit and less fragile, I added a `fold_constant` method to `TypeFolder` and implemented it for normalization. Normalization can now, when it wants to eagerly evaluate a constant, normalize `mir::Constant` directly into a `mir::ConstantKind::Val` instead of relying on the `ty::Const` evaluation. In the future we can get rid of the `ty::Const` in there entirely and add our own `Unevaluated` variant to `mir::ConstantKind`. This would allow us to remove the `promoted` field from `ty::ConstKind::Unevaluated`, as promoteds can never occur in the type system. cc `@rust-lang/wg-const-eval` r? `@lcnr`
This commit is contained in:
commit
0978a9eb99
41 changed files with 183 additions and 55 deletions
|
@ -2392,7 +2392,8 @@ pub struct Constant<'tcx> {
|
|||
pub literal: ConstantKind<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)]
|
||||
#[derive(Lift)]
|
||||
pub enum ConstantKind<'tcx> {
|
||||
/// This constant came from the type system
|
||||
Ty(&'tcx ty::Const<'tcx>),
|
||||
|
@ -2691,7 +2692,13 @@ impl<'tcx> Display for Constant<'tcx> {
|
|||
ty::FnDef(..) => {}
|
||||
_ => write!(fmt, "const ")?,
|
||||
}
|
||||
match self.literal {
|
||||
Display::fmt(&self.literal, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Display for ConstantKind<'tcx> {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
ConstantKind::Ty(c) => pretty_print_const(c, fmt, true),
|
||||
ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true),
|
||||
}
|
||||
|
|
|
@ -348,6 +348,11 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
|
||||
#[inline(always)]
|
||||
fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
|
||||
folder.fold_mir_const(self)
|
||||
}
|
||||
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
|
||||
match self {
|
||||
ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)),
|
||||
|
|
|
@ -1486,6 +1486,13 @@ rustc_queries! {
|
|||
desc { "normalizing `{}`", goal.value }
|
||||
}
|
||||
|
||||
/// Do not call this query directly: invoke `normalize_erasing_regions` instead.
|
||||
query normalize_mir_const_after_erasing_regions(
|
||||
goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
|
||||
) -> mir::ConstantKind<'tcx> {
|
||||
desc { "normalizing `{}`", goal.value }
|
||||
}
|
||||
|
||||
query implied_outlives_bounds(
|
||||
goal: CanonicalTyGoal<'tcx>
|
||||
) -> Result<
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::mir;
|
||||
use crate::ty::fold::{TypeFoldable, TypeFolder};
|
||||
use crate::ty::{self, Ty, TyCtxt, TypeFlags};
|
||||
|
||||
|
@ -65,4 +66,8 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> {
|
|||
_ => self.tcx.lifetimes.re_erased,
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
|
||||
c.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
//!
|
||||
//! These methods return true to indicate that the visitor has found what it is
|
||||
//! looking for, and does not need to visit anything else.
|
||||
use crate::mir;
|
||||
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
@ -180,6 +181,10 @@ pub trait TypeFolder<'tcx>: Sized {
|
|||
fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||
c.super_fold_with(self)
|
||||
}
|
||||
|
||||
fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
|
||||
bug!("most type folders should not be folding MIR datastructures: {:?}", c)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TypeVisitor<'tcx>: Sized {
|
||||
|
|
|
@ -483,6 +483,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
if let Some(substs) = self.substs_for_mir_body() { v.subst(tcx, substs) } else { *v }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn subst_mir_and_normalize_erasing_regions<T>(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//! `normalize_generic_arg_after_erasing_regions` query for each type
|
||||
//! or constant found within. (This underlying query is what is cached.)
|
||||
|
||||
use crate::mir;
|
||||
use crate::ty::fold::{TypeFoldable, TypeFolder};
|
||||
use crate::ty::subst::{Subst, SubstsRef};
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
|
@ -101,4 +102,10 @@ impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> {
|
|||
let arg = self.param_env.and(c.into());
|
||||
self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_const()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
|
||||
let arg = self.param_env.and(c);
|
||||
self.tcx.normalize_mir_const_after_erasing_regions(arg)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Type substitutions.
|
||||
|
||||
use crate::mir;
|
||||
use crate::ty::codec::{TyDecoder, TyEncoder};
|
||||
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
use crate::ty::sty::{ClosureSubsts, GeneratorSubsts};
|
||||
|
@ -506,6 +507,11 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
|
|||
c.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
|
||||
c.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue