From 7e08f80b34608e4aac2fcce1d9e85735b02034fe Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 4 Jun 2024 00:39:35 +0100 Subject: [PATCH] Split smir `Const` into `TyConst` and `MirConst` --- .../rustc_smir/src/rustc_internal/internal.rs | 44 ++++----- compiler/rustc_smir/src/rustc_internal/mod.rs | 3 +- compiler/rustc_smir/src/rustc_smir/context.rs | 59 +++++++++--- .../rustc_smir/src/rustc_smir/convert/mir.rs | 20 ++-- .../rustc_smir/src/rustc_smir/convert/mod.rs | 2 + .../rustc_smir/src/rustc_smir/convert/ty.rs | 74 +++++++++++---- compiler/rustc_smir/src/rustc_smir/mod.rs | 13 ++- compiler/stable_mir/src/compiler_interface.rs | 22 +++-- compiler/stable_mir/src/mir/body.rs | 10 +- compiler/stable_mir/src/mir/pretty.rs | 16 ++-- compiler/stable_mir/src/mir/visit.rs | 25 +++-- compiler/stable_mir/src/ty.rs | 95 +++++++++++++------ compiler/stable_mir/src/visitor.rs | 30 +++++- .../ui-fulldeps/stable-mir/check_transform.rs | 6 +- 14 files changed, 285 insertions(+), 134 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 6ec710f97d16a..edfd48ed43b1a 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -5,17 +5,17 @@ // Prefer importing stable_mir over internal rustc constructs to make this file more readable. use crate::rustc_smir::Tables; -use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy, TyCtxt}; +use rustc_middle::ty::{self as rustc_ty, Const as InternalConst, Ty as InternalTy, TyCtxt}; use rustc_span::Symbol; use stable_mir::abi::Layout; use stable_mir::mir::alloc::AllocId; use stable_mir::mir::mono::{Instance, MonoItem, StaticDef}; use stable_mir::mir::{BinOp, Mutability, Place, ProjectionElem, Safety, UnOp}; use stable_mir::ty::{ - Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const, - DynKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig, - GenericArgKind, GenericArgs, IndexedVal, IntTy, Movability, Pattern, Region, RigidTy, Span, - TermKind, TraitRef, Ty, UintTy, VariantDef, VariantIdx, + Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, DynKind, + ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig, + GenericArgKind, GenericArgs, IndexedVal, IntTy, MirConst, Movability, Pattern, Region, RigidTy, + Span, TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx, }; use stable_mir::{CrateItem, CrateNum, DefId}; @@ -55,7 +55,7 @@ impl RustcInternal for GenericArgKind { let arg: rustc_ty::GenericArg<'tcx> = match self { GenericArgKind::Lifetime(reg) => reg.internal(tables, tcx).into(), GenericArgKind::Type(ty) => ty.internal(tables, tcx).into(), - GenericArgKind::Const(cnst) => ty_const(cnst, tables, tcx).into(), + GenericArgKind::Const(cnst) => cnst.internal(tables, tcx).into(), }; tcx.lift(arg).unwrap() } @@ -76,13 +76,20 @@ impl RustcInternal for Ty { } } +impl RustcInternal for TyConst { + type T<'tcx> = InternalConst<'tcx>; + fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { + tcx.lift(tables.ty_consts[self.id]).unwrap() + } +} + impl RustcInternal for Pattern { type T<'tcx> = rustc_ty::Pattern<'tcx>; fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { tcx.mk_pat(match self { Pattern::Range { start, end, include_end } => rustc_ty::PatternKind::Range { - start: start.as_ref().map(|c| ty_const(c, tables, tcx)), - end: end.as_ref().map(|c| ty_const(c, tables, tcx)), + start: start.as_ref().map(|c| c.internal(tables, tcx)), + end: end.as_ref().map(|c| c.internal(tables, tcx)), include_end: *include_end, }, }) @@ -101,7 +108,7 @@ impl RustcInternal for RigidTy { RigidTy::Float(float_ty) => rustc_ty::TyKind::Float(float_ty.internal(tables, tcx)), RigidTy::Never => rustc_ty::TyKind::Never, RigidTy::Array(ty, cnst) => { - rustc_ty::TyKind::Array(ty.internal(tables, tcx), ty_const(cnst, tables, tcx)) + rustc_ty::TyKind::Array(ty.internal(tables, tcx), cnst.internal(tables, tcx)) } RigidTy::Pat(ty, pat) => { rustc_ty::TyKind::Pat(ty.internal(tables, tcx), pat.internal(tables, tcx)) @@ -239,23 +246,10 @@ impl RustcInternal for VariantDef { } } -fn ty_const<'tcx>( - constant: &Const, - tables: &mut Tables<'_>, - tcx: TyCtxt<'tcx>, -) -> rustc_ty::Const<'tcx> { - match constant.internal(tables, tcx) { - rustc_middle::mir::Const::Ty(c) => c, - cnst => { - panic!("Trying to convert constant `{constant:?}` to type constant, but found {cnst:?}") - } - } -} - -impl RustcInternal for Const { +impl RustcInternal for MirConst { type T<'tcx> = rustc_middle::mir::Const<'tcx>; fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { - let constant = tables.constants[self.id]; + let constant = tables.mir_consts[self.id]; match constant { rustc_middle::mir::Const::Ty(ty) => rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap()), rustc_middle::mir::Const::Unevaluated(uneval, ty) => { @@ -392,7 +386,7 @@ impl RustcInternal for TermKind { fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { match self { TermKind::Type(ty) => ty.internal(tables, tcx).into(), - TermKind::Const(const_) => ty_const(const_, tables, tcx).into(), + TermKind::Const(cnst) => cnst.internal(tables, tcx).into(), } } } diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 6e870728bafc4..810ffc142a09f 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -214,7 +214,8 @@ where spans: IndexMap::default(), types: IndexMap::default(), instances: IndexMap::default(), - constants: IndexMap::default(), + ty_consts: IndexMap::default(), + mir_consts: IndexMap::default(), layouts: IndexMap::default(), })); stable_mir::compiler_interface::run(&tables, || init(&tables, f)) diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index fa7b2a30ba6cf..9822ed79e2bd9 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -6,7 +6,6 @@ #![allow(rustc::usage_of_qualified_ty)] use rustc_abi::HasDataLayout; -use rustc_middle::ty; use rustc_middle::ty::layout::{ FnAbiOf, FnAbiOfHelpers, HasParamEnv, HasTyCtxt, LayoutOf, LayoutOfHelpers, }; @@ -14,6 +13,7 @@ use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; use rustc_middle::ty::{ GenericPredicates, Instance, List, ParamEnv, ScalarInt, TyCtxt, TypeVisitableExt, ValTree, }; +use rustc_middle::{mir, ty}; use rustc_span::def_id::LOCAL_CRATE; use stable_mir::abi::{FnAbi, Layout, LayoutShape}; use stable_mir::compiler_interface::Context; @@ -22,9 +22,9 @@ use stable_mir::mir::mono::{InstanceDef, StaticDef}; use stable_mir::mir::{BinOp, Body, Place, UnOp}; use stable_mir::target::{MachineInfo, MachineSize}; use stable_mir::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef, - ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind, - UintTy, VariantDef, + AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef, + ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, Ty, + TyConst, TyKind, UintTy, VariantDef, }; use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol}; use std::cell::RefCell; @@ -360,7 +360,15 @@ impl<'tcx> Context for TablesWrapper<'tcx> { def.internal(&mut *tables, tcx).fields.iter().map(|f| f.stable(&mut *tables)).collect() } - fn eval_target_usize(&self, cnst: &Const) -> Result { + fn eval_target_usize(&self, cnst: &MirConst) -> Result { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let mir_const = cnst.internal(&mut *tables, tcx); + mir_const + .try_eval_target_usize(tables.tcx, ParamEnv::empty()) + .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) + } + fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; let mir_const = cnst.internal(&mut *tables, tcx); @@ -369,7 +377,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) } - fn try_new_const_zst(&self, ty: Ty) -> Result { + fn try_new_const_zst(&self, ty: Ty) -> Result { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; let ty_internal = ty.internal(&mut *tables, tcx); @@ -390,25 +398,45 @@ impl<'tcx> Context for TablesWrapper<'tcx> { ))); } - Ok(ty::Const::zero_sized(tables.tcx, ty_internal).stable(&mut *tables)) + Ok(mir::Const::Ty(ty::Const::zero_sized(tables.tcx, ty_internal)).stable(&mut *tables)) } - fn new_const_str(&self, value: &str) -> Const { + fn new_const_str(&self, value: &str) -> MirConst { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; let ty = ty::Ty::new_static_str(tcx); let bytes = value.as_bytes(); let val_tree = ty::ValTree::from_raw_bytes(tcx, bytes); - ty::Const::new_value(tcx, val_tree, ty).stable(&mut *tables) + let ct = ty::Const::new_value(tcx, val_tree, ty); + super::convert::mir_const_from_ty_const(&mut *tables, ct, ty) } - fn new_const_bool(&self, value: bool) -> Const { + fn new_const_bool(&self, value: bool) -> MirConst { let mut tables = self.0.borrow_mut(); - ty::Const::from_bool(tables.tcx, value).stable(&mut *tables) + let ct = ty::Const::from_bool(tables.tcx, value); + let ty = tables.tcx.types.bool; + super::convert::mir_const_from_ty_const(&mut *tables, ct, ty) } - fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result { + fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx)); + let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size; + + // We don't use Const::from_bits since it doesn't have any error checking. + let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| { + Error::new(format!("Value overflow: cannot convert `{value}` to `{ty}`.")) + })?; + let ct = ty::Const::new_value(tables.tcx, ValTree::from_scalar_int(scalar), ty); + Ok(super::convert::mir_const_from_ty_const(&mut *tables, ct, ty)) + } + fn try_new_ty_const_uint( + &self, + value: u128, + uint_ty: UintTy, + ) -> Result { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx)); @@ -453,7 +481,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { .stable(&mut *tables) } - fn const_pretty(&self, cnst: &stable_mir::ty::Const) -> String { + fn mir_const_pretty(&self, cnst: &stable_mir::ty::MirConst) -> String { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; cnst.internal(&mut *tables, tcx).to_string() @@ -474,6 +502,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> { tables.types[ty].kind().stable(&mut *tables) } + fn ty_const_pretty(&self, ct: stable_mir::ty::TyConstId) -> String { + let tables = self.0.borrow_mut(); + tables.ty_consts[ct].to_string() + } + fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index a1a5c09ef0af4..1c87293209c68 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -6,7 +6,7 @@ use rustc_middle::mir::interpret::alloc_range; use rustc_middle::mir::mono::MonoItem; use stable_mir::mir::alloc::GlobalAlloc; use stable_mir::mir::{ConstOperand, Statement, UserTypeProjection, VarDebugInfoFragment}; -use stable_mir::ty::{Allocation, Const, ConstantKind}; +use stable_mir::ty::{Allocation, ConstantKind, MirConst}; use stable_mir::{opaque, Error}; use crate::rustc_smir::{alloc, Stable, Tables}; @@ -724,11 +724,16 @@ impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> { } impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> { - type T = stable_mir::ty::Const; + type T = stable_mir::ty::MirConst; fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + let id = tables.intern_mir_const(tables.tcx.lift(*self).unwrap()); match *self { - mir::Const::Ty(c) => c.stable(tables), + mir::Const::Ty(c) => MirConst::new( + stable_mir::ty::ConstantKind::Ty(c.stable(tables)), + c.ty().stable(tables), + id, + ), mir::Const::Unevaluated(unev_const, ty) => { let kind = stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { @@ -737,21 +742,18 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> { promoted: unev_const.promoted.map(|u| u.as_u32()), }); let ty = ty.stable(tables); - let id = tables.intern_const(tables.tcx.lift(*self).unwrap()); - Const::new(kind, ty, id) + MirConst::new(kind, ty, id) } mir::Const::Val(mir::ConstValue::ZeroSized, ty) => { let ty = ty.stable(tables); - let id = tables.intern_const(tables.tcx.lift(*self).unwrap()); - Const::new(ConstantKind::ZeroSized, ty, id) + MirConst::new(ConstantKind::ZeroSized, ty, id) } mir::Const::Val(val, ty) => { let ty = tables.tcx.lift(ty).unwrap(); let val = tables.tcx.lift(val).unwrap(); let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables)); let ty = ty.stable(tables); - let id = tables.intern_const(tables.tcx.lift(*self).unwrap()); - Const::new(kind, ty, id) + MirConst::new(kind, ty, id) } } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs index 736378a530f0a..50687935473a7 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs @@ -9,6 +9,8 @@ mod error; mod mir; mod ty; +pub use ty::mir_const_from_ty_const; + impl<'tcx> Stable<'tcx> for rustc_hir::Safety { type T = stable_mir::mir::Safety; fn stable(&self, _: &mut Tables<'_>) -> Self::T { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 66708def00f19..1f3356f579fe6 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -3,8 +3,7 @@ use rustc_middle::ty::Ty; use rustc_middle::{mir, ty}; use stable_mir::ty::{ - AdtKind, Const, ConstantKind, FloatTy, GenericArgs, GenericParamDef, IntTy, Region, RigidTy, - TyKind, UintTy, + AdtKind, FloatTy, GenericArgs, GenericParamDef, IntTy, Region, RigidTy, TyKind, UintTy, }; use crate::rustc_smir::{alloc, Stable, Tables}; @@ -410,8 +409,50 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { } } +pub fn mir_const_from_ty_const<'tcx>( + tables: &mut Tables<'tcx>, + ty_const: ty::Const<'tcx>, + ty: Ty<'tcx>, +) -> stable_mir::ty::MirConst { + let kind = match ty_const.kind() { + ty::Value(val) => { + let val = match val { + ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar), + ty::ValTree::Branch(branch) => { + ty::ValTree::Branch(tables.tcx.lift(branch).unwrap()) + } + }; + let ty = tables.tcx.lift(ty).unwrap(); + let const_val = tables.tcx.valtree_to_const_val((ty, val)); + if matches!(const_val, mir::ConstValue::ZeroSized) { + stable_mir::ty::ConstantKind::ZeroSized + } else { + stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation( + ty, const_val, tables, + )) + } + } + ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)), + ty::ErrorCt(_) => unreachable!(), + ty::InferCt(_) => unreachable!(), + ty::BoundCt(_, _) => unimplemented!(), + ty::PlaceholderCt(_) => unimplemented!(), + ty::Unevaluated(uv) => { + stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { + def: tables.const_def(uv.def), + args: uv.args.stable(tables), + promoted: None, + }) + } + ty::ExprCt(_) => unimplemented!(), + }; + let stable_ty = tables.intern_ty(ty); + let id = tables.intern_mir_const(mir::Const::Ty(ty_const)); + stable_mir::ty::MirConst::new(kind, stable_ty, id) +} + impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { - type T = stable_mir::ty::Const; + type T = stable_mir::ty::TyConst; fn stable(&self, tables: &mut Tables<'_>) -> Self::T { let kind = match self.kind() { @@ -425,30 +466,27 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { let ty = tables.tcx.lift(self.ty()).unwrap(); let const_val = tables.tcx.valtree_to_const_val((ty, val)); if matches!(const_val, mir::ConstValue::ZeroSized) { - ConstantKind::ZeroSized + stable_mir::ty::TyConstKind::ZSTValue(ty.stable(tables)) } else { - stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation( - ty, const_val, tables, - )) + stable_mir::ty::TyConstKind::Value( + ty.stable(tables), + alloc::new_allocation(ty, const_val, tables), + ) } } - ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)), + ty::ParamCt(param) => stable_mir::ty::TyConstKind::Param(param.stable(tables)), + ty::Unevaluated(uv) => stable_mir::ty::TyConstKind::Unevaluated( + tables.const_def(uv.def), + uv.args.stable(tables), + ), ty::ErrorCt(_) => unreachable!(), ty::InferCt(_) => unreachable!(), ty::BoundCt(_, _) => unimplemented!(), ty::PlaceholderCt(_) => unimplemented!(), - ty::Unevaluated(uv) => { - stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { - def: tables.const_def(uv.def), - args: uv.args.stable(tables), - promoted: None, - }) - } ty::ExprCt(_) => unimplemented!(), }; - let ty = self.ty().stable(tables); - let id = tables.intern_const(mir::Const::Ty(tables.tcx.lift(*self).unwrap())); - Const::new(kind, ty, id) + let id = tables.intern_ty_const(tables.tcx.lift(*self).unwrap()); + stable_mir::ty::TyConst::new(kind, id) } } diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index aba7e7dc9c21d..d13e780332632 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; use stable_mir::abi::Layout; use stable_mir::mir::mono::InstanceDef; -use stable_mir::ty::{ConstId, Span}; +use stable_mir::ty::{MirConstId, Span, TyConstId}; use stable_mir::{CtorKind, ItemKind}; use std::ops::RangeInclusive; use tracing::debug; @@ -33,7 +33,8 @@ pub struct Tables<'tcx> { pub(crate) spans: IndexMap, pub(crate) types: IndexMap, stable_mir::ty::Ty>, pub(crate) instances: IndexMap, InstanceDef>, - pub(crate) constants: IndexMap, ConstId>, + pub(crate) ty_consts: IndexMap, TyConstId>, + pub(crate) mir_consts: IndexMap, MirConstId>, pub(crate) layouts: IndexMap, Layout>, } @@ -42,8 +43,12 @@ impl<'tcx> Tables<'tcx> { self.types.create_or_fetch(ty) } - pub(crate) fn intern_const(&mut self, constant: mir::Const<'tcx>) -> ConstId { - self.constants.create_or_fetch(constant) + pub(crate) fn intern_ty_const(&mut self, ct: ty::Const<'tcx>) -> TyConstId { + self.ty_consts.create_or_fetch(ct) + } + + pub(crate) fn intern_mir_const(&mut self, constant: mir::Const<'tcx>) -> MirConstId { + self.mir_consts.create_or_fetch(constant) } pub(crate) fn has_body(&self, instance: Instance<'tcx>) -> bool { diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index 858ce5301d84c..085dfd9ea8909 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -11,10 +11,10 @@ use crate::mir::mono::{Instance, InstanceDef, StaticDef}; use crate::mir::{BinOp, Body, Place, UnOp}; use crate::target::MachineInfo; use crate::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef, + AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics, - ImplDef, ImplTrait, IntrinsicDef, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty, - TyKind, UintTy, VariantDef, + ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl, + TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, }; use crate::{ mir, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind, @@ -109,19 +109,21 @@ pub trait Context { fn variant_fields(&self, def: VariantDef) -> Vec; /// Evaluate constant as a target usize. - fn eval_target_usize(&self, cnst: &Const) -> Result; + fn eval_target_usize(&self, cnst: &MirConst) -> Result; + fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result; /// Create a new zero-sized constant. - fn try_new_const_zst(&self, ty: Ty) -> Result; + fn try_new_const_zst(&self, ty: Ty) -> Result; /// Create a new constant that represents the given string value. - fn new_const_str(&self, value: &str) -> Const; + fn new_const_str(&self, value: &str) -> MirConst; /// Create a new constant that represents the given boolean value. - fn new_const_bool(&self, value: bool) -> Const; + fn new_const_bool(&self, value: bool) -> MirConst; /// Create a new constant that represents the given value. - fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result; + fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result; + fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result; /// Create a new type from the given kind. fn new_rigid_ty(&self, kind: RigidTy) -> Ty; @@ -136,11 +138,13 @@ pub trait Context { fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty; /// Returns literal value of a const as a string. - fn const_pretty(&self, cnst: &Const) -> String; + fn mir_const_pretty(&self, cnst: &MirConst) -> String; /// `Span` of an item fn span_of_an_item(&self, def_id: DefId) -> Span; + fn ty_const_pretty(&self, ct: TyConstId) -> String; + /// Obtain the representation of a type. fn ty_pretty(&self, ty: Ty) -> String; diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 4c779ae96a81b..43e4682dc1008 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -1,8 +1,8 @@ use crate::compiler_interface::with; use crate::mir::pretty::function_body; use crate::ty::{ - AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind, - VariantIdx, + AdtDef, ClosureDef, CoroutineDef, GenericArgs, MirConst, Movability, Region, RigidTy, Ty, + TyConst, TyKind, VariantIdx, }; use crate::{Error, Opaque, Span, Symbol}; use std::io; @@ -524,7 +524,7 @@ pub enum Rvalue { /// Corresponds to source code like `[x; 32]`. /// /// [#74836]: /~https://github.com/rust-lang/rust/issues/74836 - Repeat(Operand, Const), + Repeat(Operand, TyConst), /// Transmutes a `*mut u8` into shallow-initialized `Box`. /// @@ -718,7 +718,7 @@ pub enum VarDebugInfoContents { pub struct ConstOperand { pub span: Span, pub user_ty: Option, - pub const_: Const, + pub const_: MirConst, } // In MIR ProjectionElem is parameterized on the second Field argument and the Index argument. This @@ -833,7 +833,7 @@ type UserTypeAnnotationIndex = usize; pub struct Constant { pub span: Span, pub user_ty: Option, - pub literal: Const, + pub literal: MirConst, } /// The possible branch sites of a [TerminatorKind::SwitchInt]. diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 580dc1a2b88fc..2fb180b84c7c3 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -1,5 +1,5 @@ use crate::mir::{Operand, Place, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents}; -use crate::ty::{Const, IndexedVal, Ty}; +use crate::ty::{IndexedVal, MirConst, Ty, TyConst}; use crate::{with, Body, Mutability}; use fmt::{Display, Formatter}; use std::fmt::Debug; @@ -46,7 +46,7 @@ pub(crate) fn function_body(writer: &mut W, body: &Body, name: &str) - VarDebugInfoContents::Place(place) => { format!("{place:?}") } - VarDebugInfoContents::Const(constant) => pretty_const(&constant.const_), + VarDebugInfoContents::Const(constant) => pretty_mir_const(&constant.const_), }; writeln!(writer, " debug {} => {};", info.name, content) })?; @@ -310,12 +310,16 @@ fn pretty_operand(operand: &Operand) -> String { Operand::Move(mv) => { format!("move {:?}", mv) } - Operand::Constant(cnst) => pretty_const(&cnst.literal), + Operand::Constant(cnst) => pretty_mir_const(&cnst.literal), } } -fn pretty_const(literal: &Const) -> String { - with(|cx| cx.const_pretty(literal)) +fn pretty_mir_const(literal: &MirConst) -> String { + with(|cx| cx.mir_const_pretty(literal)) +} + +fn pretty_ty_const(ct: &TyConst) -> String { + with(|cx| cx.ty_const_pretty(ct.id)) } fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { @@ -359,7 +363,7 @@ fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { write!(writer, "{kind}{:?}", place) } Rvalue::Repeat(op, cnst) => { - write!(writer, "{} \" \" {}", &pretty_operand(op), cnst.ty()) + write!(writer, "{} \" \" {}", &pretty_operand(op), &pretty_ty_const(cnst)) } Rvalue::ShallowInitBox(_, _) => Ok(()), Rvalue::ThreadLocalRef(item) => { diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index 24296e9e8778b..10f30083dc2d9 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -36,7 +36,7 @@ //! variant argument) that does not require visiting. use crate::mir::*; -use crate::ty::{Const, GenericArgs, Region, Ty}; +use crate::ty::{GenericArgs, MirConst, Region, Ty, TyConst}; use crate::{Error, Opaque, Span}; pub trait MirVisitor { @@ -112,8 +112,13 @@ pub trait MirVisitor { self.super_constant(constant, location) } - fn visit_const(&mut self, constant: &Const, location: Location) { - self.super_const(constant, location) + fn visit_mir_const(&mut self, constant: &MirConst, location: Location) { + self.super_mir_const(constant, location) + } + + fn visit_ty_const(&mut self, constant: &TyConst, location: Location) { + let _ = location; + self.super_ty_const(constant) } fn visit_region(&mut self, region: &Region, location: Location) { @@ -339,7 +344,7 @@ pub trait MirVisitor { } Rvalue::Repeat(op, constant) => { self.visit_operand(op, location); - self.visit_const(constant, location); + self.visit_ty_const(constant, location); } Rvalue::ShallowInitBox(op, ty) => { self.visit_ty(ty, location); @@ -378,14 +383,18 @@ pub trait MirVisitor { fn super_constant(&mut self, constant: &Constant, location: Location) { let Constant { span, user_ty: _, literal } = constant; self.visit_span(span); - self.visit_const(literal, location); + self.visit_mir_const(literal, location); } - fn super_const(&mut self, constant: &Const, location: Location) { - let Const { kind: _, ty, id: _ } = constant; + fn super_mir_const(&mut self, constant: &MirConst, location: Location) { + let MirConst { kind: _, ty, id: _ } = constant; self.visit_ty(ty, location); } + fn super_ty_const(&mut self, constant: &TyConst) { + let _ = constant; + } + fn super_region(&mut self, region: &Region) { let _ = region; } @@ -407,7 +416,7 @@ pub trait MirVisitor { self.visit_place(place, PlaceContext::NON_USE, location); } VarDebugInfoContents::Const(constant) => { - self.visit_const(&constant.const_, location); + self.visit_mir_const(&constant.const_, location); } } } diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 50bf0a5d74ef3..bcbe87f7303b3 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -28,11 +28,11 @@ impl Ty { /// Create a new array type. pub fn try_new_array(elem_ty: Ty, size: u64) -> Result { - Ok(Ty::from_rigid_kind(RigidTy::Array(elem_ty, Const::try_from_target_usize(size)?))) + Ok(Ty::from_rigid_kind(RigidTy::Array(elem_ty, TyConst::try_from_target_usize(size)?))) } /// Create a new array type from Const length. - pub fn new_array_with_const_len(elem_ty: Ty, len: Const) -> Ty { + pub fn new_array_with_const_len(elem_ty: Ty, len: TyConst) -> Ty { Ty::from_rigid_kind(RigidTy::Array(elem_ty, len)) } @@ -101,24 +101,66 @@ impl Ty { /// Represents a pattern in the type system #[derive(Clone, Debug, Eq, PartialEq)] pub enum Pattern { - Range { start: Option, end: Option, include_end: bool }, + Range { start: Option, end: Option, include_end: bool }, } -/// Represents a constant in MIR or from the Type system. +/// Represents a constant in the type system #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Const { +pub struct TyConst { + pub(crate) kind: TyConstKind, + pub id: TyConstId, +} + +impl TyConst { + pub fn new(kind: TyConstKind, id: TyConstId) -> TyConst { + Self { kind, id } + } + + /// Retrieve the constant kind. + pub fn kind(&self) -> &TyConstKind { + &self.kind + } + + /// Creates an interned usize constant. + fn try_from_target_usize(val: u64) -> Result { + with(|cx| cx.try_new_ty_const_uint(val.into(), UintTy::Usize)) + } + + /// Try to evaluate to a target `usize`. + pub fn eval_target_usize(&self) -> Result { + with(|cx| cx.eval_target_usize_ty(self)) + } +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum TyConstKind { + Param(ParamConst), + Bound(DebruijnIndex, BoundVar), + Unevaluated(ConstDef, GenericArgs), + + // FIXME: These should be a valtree + Value(Ty, Allocation), + ZSTValue(Ty), +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct TyConstId(usize); + +/// Represents a constant in MIR +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct MirConst { /// The constant kind. pub(crate) kind: ConstantKind, /// The constant type. pub(crate) ty: Ty, /// Used for internal tracking of the internal constant. - pub id: ConstId, + pub id: MirConstId, } -impl Const { +impl MirConst { /// Build a constant. Note that this should only be used by the compiler. - pub fn new(kind: ConstantKind, ty: Ty, id: ConstId) -> Const { - Const { kind, ty, id } + pub fn new(kind: ConstantKind, ty: Ty, id: MirConstId) -> MirConst { + MirConst { kind, ty, id } } /// Retrieve the constant kind. @@ -131,11 +173,6 @@ impl Const { self.ty } - /// Creates an interned usize constant. - fn try_from_target_usize(val: u64) -> Result { - with(|cx| cx.try_new_const_uint(val.into(), UintTy::Usize)) - } - /// Try to evaluate to a target `usize`. pub fn eval_target_usize(&self) -> Result { with(|cx| cx.eval_target_usize(self)) @@ -143,7 +180,7 @@ impl Const { /// Create a constant that represents a new zero-sized constant of type T. /// Fails if the type is not a ZST or if it doesn't have a known size. - pub fn try_new_zero_sized(ty: Ty) -> Result { + pub fn try_new_zero_sized(ty: Ty) -> Result { with(|cx| cx.try_new_const_zst(ty)) } @@ -152,23 +189,23 @@ impl Const { /// Note that there is no guarantee today about duplication of the same constant. /// I.e.: Calling this function multiple times with the same argument may or may not return /// the same allocation. - pub fn from_str(value: &str) -> Const { + pub fn from_str(value: &str) -> MirConst { with(|cx| cx.new_const_str(value)) } /// Build a new constant that represents the given boolean value. - pub fn from_bool(value: bool) -> Const { + pub fn from_bool(value: bool) -> MirConst { with(|cx| cx.new_const_bool(value)) } /// Build a new constant that represents the given unsigned integer. - pub fn try_from_uint(value: u128, uint_ty: UintTy) -> Result { + pub fn try_from_uint(value: u128, uint_ty: UintTy) -> Result { with(|cx| cx.try_new_const_uint(value, uint_ty)) } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct ConstId(usize); +pub struct MirConstId(usize); type Ident = Opaque; @@ -484,7 +521,7 @@ pub enum RigidTy { Adt(AdtDef, GenericArgs), Foreign(ForeignDef), Str, - Array(Ty, Const), + Array(Ty, TyConst), Pat(Ty, Pattern), Slice(Ty), RawPtr(Ty, Mutability), @@ -866,7 +903,7 @@ impl std::ops::Index for GenericArgs { } impl std::ops::Index for GenericArgs { - type Output = Const; + type Output = TyConst; fn index(&self, index: ParamConst) -> &Self::Output { self.0[index.index as usize].expect_const() @@ -877,7 +914,7 @@ impl std::ops::Index for GenericArgs { pub enum GenericArgKind { Lifetime(Region), Type(Ty), - Const(Const), + Const(TyConst), } impl GenericArgKind { @@ -894,7 +931,7 @@ impl GenericArgKind { /// Panic if this generic argument is not a const, otherwise /// return the const. #[track_caller] - pub fn expect_const(&self) -> &Const { + pub fn expect_const(&self) -> &TyConst { match self { GenericArgKind::Const(c) => c, _ => panic!("{self:?}"), @@ -913,7 +950,7 @@ impl GenericArgKind { #[derive(Clone, Debug, Eq, PartialEq)] pub enum TermKind { Type(Ty), - Const(Const), + Const(TyConst), } #[derive(Clone, Debug, Eq, PartialEq)] @@ -1202,6 +1239,7 @@ impl Allocation { #[derive(Clone, Debug, Eq, PartialEq)] pub enum ConstantKind { + Ty(TyConst), Allocated(Allocation), Unevaluated(UnevaluatedConst), Param(ParamConst), @@ -1335,7 +1373,7 @@ pub enum PredicateKind { ObjectSafe(TraitDef), SubType(SubtypePredicate), Coerce(CoercePredicate), - ConstEquate(Const, Const), + ConstEquate(TyConst, TyConst), Ambiguous, AliasRelate(TermKind, TermKind, AliasRelationDirection), } @@ -1346,9 +1384,9 @@ pub enum ClauseKind { RegionOutlives(RegionOutlivesPredicate), TypeOutlives(TypeOutlivesPredicate), Projection(ProjectionPredicate), - ConstArgHasType(Const, Ty), + ConstArgHasType(TyConst, Ty), WellFormed(GenericArgKind), - ConstEvaluatable(Const), + ConstEvaluatable(TyConst), } #[derive(Clone, Debug, Eq, PartialEq)] @@ -1426,7 +1464,8 @@ macro_rules! index_impl { }; } -index_impl!(ConstId); +index_impl!(TyConstId); +index_impl!(MirConstId); index_impl!(Ty); index_impl!(Span); diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs index 2d7159f87fec3..fc1da8fafe486 100644 --- a/compiler/stable_mir/src/visitor.rs +++ b/compiler/stable_mir/src/visitor.rs @@ -1,10 +1,10 @@ use std::ops::ControlFlow; -use crate::Opaque; +use crate::{ty::TyConst, Opaque}; use super::ty::{ - Allocation, Binder, Const, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, - Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst, + Allocation, Binder, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, + MirConst, Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst, }; pub trait Visitor: Sized { @@ -12,7 +12,7 @@ pub trait Visitor: Sized { fn visit_ty(&mut self, ty: &Ty) -> ControlFlow { ty.super_visit(self) } - fn visit_const(&mut self, c: &Const) -> ControlFlow { + fn visit_const(&mut self, c: &TyConst) -> ControlFlow { c.super_visit(self) } fn visit_reg(&mut self, reg: &Region) -> ControlFlow { @@ -42,12 +42,32 @@ impl Visitable for Ty { } } -impl Visitable for Const { +impl Visitable for TyConst { fn visit(&self, visitor: &mut V) -> ControlFlow { visitor.visit_const(self) } + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + match &self.kind { + crate::ty::TyConstKind::Param(_) => {} + crate::ty::TyConstKind::Bound(_, _) => {} + crate::ty::TyConstKind::Unevaluated(_, args) => args.visit(visitor)?, + crate::ty::TyConstKind::Value(ty, alloc) => { + alloc.visit(visitor)?; + ty.visit(visitor)?; + } + crate::ty::TyConstKind::ZSTValue(ty) => ty.visit(visitor)?, + } + ControlFlow::Continue(()) + } +} + +impl Visitable for MirConst { + fn visit(&self, visitor: &mut V) -> ControlFlow { + self.super_visit(visitor) + } fn super_visit(&self, visitor: &mut V) -> ControlFlow { match &self.kind() { + super::ty::ConstantKind::Ty(ct) => ct.visit(visitor)?, super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor)?, super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor)?, super::ty::ConstantKind::Param(_) | super::ty::ConstantKind::ZeroSized => {} diff --git a/tests/ui-fulldeps/stable-mir/check_transform.rs b/tests/ui-fulldeps/stable-mir/check_transform.rs index 6345ee24f7893..b203e76e54f45 100644 --- a/tests/ui-fulldeps/stable-mir/check_transform.rs +++ b/tests/ui-fulldeps/stable-mir/check_transform.rs @@ -22,7 +22,7 @@ use rustc_smir::rustc_internal; use stable_mir::mir::alloc::GlobalAlloc; use stable_mir::mir::mono::Instance; use stable_mir::mir::{Body, Constant, Operand, Rvalue, StatementKind, TerminatorKind}; -use stable_mir::ty::{Const, ConstantKind}; +use stable_mir::ty::{ConstantKind, MirConst}; use stable_mir::{CrateDef, CrateItems, ItemKind}; use std::convert::TryFrom; use std::io::Write; @@ -77,7 +77,7 @@ fn check_msg(body: &Body, expected: &str) { }; assert_eq!(alloc.provenance.ptrs.len(), 1); - let alloc_prov_id = alloc.provenance.ptrs[0].1 .0; + let alloc_prov_id = alloc.provenance.ptrs[0].1.0; let GlobalAlloc::Memory(val) = GlobalAlloc::from(alloc_prov_id) else { unreachable!() }; @@ -95,7 +95,7 @@ fn change_panic_msg(mut body: Body, new_msg: &str) -> Body { for bb in &mut body.blocks { match &mut bb.terminator.kind { TerminatorKind::Call { args, .. } => { - let new_const = Const::from_str(new_msg); + let new_const = MirConst::from_str(new_msg); args[0] = Operand::Constant(Constant { literal: new_const, span: bb.terminator.span,