Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/consts.rs')
-rw-r--r--crates/hir-ty/src/next_solver/consts.rs219
1 files changed, 37 insertions, 182 deletions
diff --git a/crates/hir-ty/src/next_solver/consts.rs b/crates/hir-ty/src/next_solver/consts.rs
index 9643f1ba4c..fa90e3d8a0 100644
--- a/crates/hir-ty/src/next_solver/consts.rs
+++ b/crates/hir-ty/src/next_solver/consts.rs
@@ -1,5 +1,7 @@
//! Things related to consts in the next-trait-solver.
+mod valtree;
+
use std::hash::Hash;
use hir_def::ConstParamId;
@@ -9,17 +11,19 @@ use rustc_ast_ir::visit::VisitorResult;
use rustc_type_ir::{
BoundVar, BoundVarIndexKind, ConstVid, DebruijnIndex, FlagComputation, Flags,
GenericTypeVisitable, InferConst, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable,
- TypeVisitable, TypeVisitableExt, WithCachedTypeInfo,
- inherent::{IntoKind, ParamEnv as _, PlaceholderLike, SliceLike},
- relate::Relate,
+ TypeVisitable, WithCachedTypeInfo, inherent::IntoKind, relate::Relate,
};
use crate::{
- MemoryMap,
- next_solver::{ClauseKind, ParamEnv, impl_stored_interned},
+ ParamEnvAndCrate,
+ next_solver::{
+ AllocationData, impl_foldable_for_interned_slice, impl_stored_interned, interned_slice,
+ },
};
-use super::{BoundVarKind, DbInterner, ErrorGuaranteed, GenericArgs, Placeholder, Ty};
+use super::{DbInterner, ErrorGuaranteed, GenericArgs, Ty};
+
+pub use self::valtree::*;
pub type ConstKind<'db> = rustc_type_ir::ConstKind<DbInterner<'db>>;
pub type UnevaluatedConst<'db> = rustc_type_ir::UnevaluatedConst<DbInterner<'db>>;
@@ -71,26 +75,33 @@ impl<'db> Const<'db> {
Const::new(interner, ConstKind::Param(param))
}
- pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderConst) -> Self {
+ pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderConst<'db>) -> Self {
Const::new(interner, ConstKind::Placeholder(placeholder))
}
- pub fn new_bound(interner: DbInterner<'db>, index: DebruijnIndex, bound: BoundConst) -> Self {
+ pub fn new_bound(
+ interner: DbInterner<'db>,
+ index: DebruijnIndex,
+ bound: BoundConst<'db>,
+ ) -> Self {
Const::new(interner, ConstKind::Bound(BoundVarIndexKind::Bound(index), bound))
}
- pub fn new_valtree(
+ pub fn new_valtree(interner: DbInterner<'db>, ty: Ty<'db>, kind: ValTreeKind<'db>) -> Self {
+ Const::new(interner, ConstKind::Value(ValueConst { ty, value: ValTree::new(kind) }))
+ }
+
+ pub fn new_from_allocation(
interner: DbInterner<'db>,
- ty: Ty<'db>,
- memory: Box<[u8]>,
- memory_map: MemoryMap<'db>,
+ allocation: &AllocationData<'db>,
+ param_env: ParamEnvAndCrate<'db>,
) -> Self {
- Const::new(
+ allocation_to_const(
interner,
- ConstKind::Value(ValueConst {
- ty,
- value: Valtree::new(ConstBytes { memory, memory_map }),
- }),
+ allocation.ty,
+ &allocation.memory,
+ &allocation.memory_map,
+ param_env,
)
}
@@ -120,7 +131,7 @@ impl<'db> std::fmt::Debug for Const<'db> {
}
}
-pub type PlaceholderConst = Placeholder<BoundConst>;
+pub type PlaceholderConst<'db> = rustc_type_ir::PlaceholderConst<DbInterner<'db>>;
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub struct ParamConst {
@@ -135,126 +146,6 @@ impl std::fmt::Debug for ParamConst {
}
}
-impl ParamConst {
- pub fn find_const_ty_from_env<'db>(self, env: ParamEnv<'db>) -> Ty<'db> {
- let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
- // `ConstArgHasType` are never desugared to be higher ranked.
- match clause.kind().skip_binder() {
- ClauseKind::ConstArgHasType(param_ct, ty) => {
- assert!(!(param_ct, ty).has_escaping_bound_vars());
-
- match param_ct.kind() {
- ConstKind::Param(param_ct) if param_ct.index == self.index => Some(ty),
- _ => None,
- }
- }
- _ => None,
- }
- });
-
- // N.B. it may be tempting to fix ICEs by making this function return
- // `Option<Ty<'db>>` instead of `Ty<'db>`; however, this is generally
- // considered to be a bandaid solution, since it hides more important
- // underlying issues with how we construct generics and predicates of
- // items. It's advised to fix the underlying issue rather than trying
- // to modify this function.
- let ty = candidates.next().unwrap_or_else(|| {
- panic!("cannot find `{self:?}` in param-env: {env:#?}");
- });
- assert!(
- candidates.next().is_none(),
- "did not expect duplicate `ConstParamHasTy` for `{self:?}` in param-env: {env:#?}"
- );
- ty
- }
-}
-
-/// A type-level constant value.
-///
-/// Represents a typed, fully evaluated constant.
-#[derive(
- Debug, Copy, Clone, Eq, PartialEq, Hash, TypeFoldable, TypeVisitable, GenericTypeVisitable,
-)]
-pub struct ValueConst<'db> {
- pub ty: Ty<'db>,
- // FIXME: Should we ignore this for TypeVisitable, TypeFoldable?
- #[type_visitable(ignore)]
- #[type_foldable(identity)]
- pub value: Valtree<'db>,
-}
-
-impl<'db> ValueConst<'db> {
- pub fn new(ty: Ty<'db>, bytes: ConstBytes<'db>) -> Self {
- let value = Valtree::new(bytes);
- ValueConst { ty, value }
- }
-}
-
-impl<'db> rustc_type_ir::inherent::ValueConst<DbInterner<'db>> for ValueConst<'db> {
- fn ty(self) -> Ty<'db> {
- self.ty
- }
-
- fn valtree(self) -> Valtree<'db> {
- self.value
- }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, GenericTypeVisitable)]
-pub struct ConstBytes<'db> {
- pub memory: Box<[u8]>,
- pub memory_map: MemoryMap<'db>,
-}
-
-impl Hash for ConstBytes<'_> {
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
- self.memory.hash(state)
- }
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub struct Valtree<'db> {
- interned: InternedRef<'db, ValtreeInterned>,
-}
-
-impl<'db, V: super::WorldExposer> GenericTypeVisitable<V> for Valtree<'db> {
- fn generic_visit_with(&self, visitor: &mut V) {
- if visitor.on_interned(self.interned).is_continue() {
- self.inner().generic_visit_with(visitor);
- }
- }
-}
-
-#[derive(Debug, PartialEq, Eq, Hash, GenericTypeVisitable)]
-pub(super) struct ValtreeInterned(ConstBytes<'static>);
-
-impl_internable!(gc; ValtreeInterned);
-
-const _: () = {
- const fn is_copy<T: Copy>() {}
- is_copy::<Valtree<'static>>();
-};
-
-impl<'db> Valtree<'db> {
- #[inline]
- pub fn new(bytes: ConstBytes<'db>) -> Self {
- let bytes = unsafe { std::mem::transmute::<ConstBytes<'db>, ConstBytes<'static>>(bytes) };
- Self { interned: Interned::new_gc(ValtreeInterned(bytes)) }
- }
-
- #[inline]
- pub fn inner(&self) -> &ConstBytes<'db> {
- let inner = &self.interned.0;
- unsafe { std::mem::transmute::<&ConstBytes<'static>, &ConstBytes<'db>>(inner) }
- }
-}
-
-impl std::fmt::Debug for Valtree<'_> {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- self.interned.fmt(f)
- }
-}
-
#[derive(
Copy, Clone, Debug, Hash, PartialEq, Eq, TypeVisitable, TypeFoldable, GenericTypeVisitable,
)]
@@ -388,25 +279,22 @@ impl<'db> rustc_type_ir::inherent::Const<DbInterner<'db>> for Const<'db> {
Const::new(interner, ConstKind::Infer(InferConst::Var(var)))
}
- fn new_bound(interner: DbInterner<'db>, debruijn: DebruijnIndex, var: BoundConst) -> Self {
+ fn new_bound(interner: DbInterner<'db>, debruijn: DebruijnIndex, var: BoundConst<'db>) -> Self {
Const::new(interner, ConstKind::Bound(BoundVarIndexKind::Bound(debruijn), var))
}
fn new_anon_bound(interner: DbInterner<'db>, debruijn: DebruijnIndex, var: BoundVar) -> Self {
Const::new(
interner,
- ConstKind::Bound(BoundVarIndexKind::Bound(debruijn), BoundConst { var }),
+ ConstKind::Bound(BoundVarIndexKind::Bound(debruijn), BoundConst::new(var)),
)
}
fn new_canonical_bound(interner: DbInterner<'db>, var: BoundVar) -> Self {
- Const::new(interner, ConstKind::Bound(BoundVarIndexKind::Canonical, BoundConst { var }))
+ Const::new(interner, ConstKind::Bound(BoundVarIndexKind::Canonical, BoundConst::new(var)))
}
- fn new_placeholder(
- interner: DbInterner<'db>,
- param: <DbInterner<'db> as rustc_type_ir::Interner>::PlaceholderConst,
- ) -> Self {
+ fn new_placeholder(interner: DbInterner<'db>, param: PlaceholderConst<'db>) -> Self {
Const::new(interner, ConstKind::Placeholder(param))
}
@@ -426,43 +314,7 @@ impl<'db> rustc_type_ir::inherent::Const<DbInterner<'db>> for Const<'db> {
}
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct BoundConst {
- pub var: BoundVar,
-}
-
-impl<'db> rustc_type_ir::inherent::BoundVarLike<DbInterner<'db>> for BoundConst {
- fn var(self) -> BoundVar {
- self.var
- }
-
- fn assert_eq(self, var: BoundVarKind) {
- var.expect_const()
- }
-}
-
-impl<'db> PlaceholderLike<DbInterner<'db>> for PlaceholderConst {
- type Bound = BoundConst;
-
- fn universe(self) -> rustc_type_ir::UniverseIndex {
- self.universe
- }
-
- fn var(self) -> rustc_type_ir::BoundVar {
- self.bound.var
- }
-
- fn with_updated_universe(self, ui: rustc_type_ir::UniverseIndex) -> Self {
- Placeholder { universe: ui, bound: self.bound }
- }
-
- fn new(ui: rustc_type_ir::UniverseIndex, var: BoundConst) -> Self {
- Placeholder { universe: ui, bound: var }
- }
- fn new_anon(ui: rustc_type_ir::UniverseIndex, var: rustc_type_ir::BoundVar) -> Self {
- Placeholder { universe: ui, bound: BoundConst { var } }
- }
-}
+pub type BoundConst<'db> = rustc_type_ir::BoundConst<DbInterner<'db>>;
impl<'db> Relate<DbInterner<'db>> for ExprConst {
fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
@@ -483,3 +335,6 @@ impl<'db> rustc_type_ir::inherent::ExprConst<DbInterner<'db>> for ExprConst {
GenericArgs::default()
}
}
+
+interned_slice!(ConstsStorage, Consts, StoredConsts, consts, Const<'db>, Const<'static>);
+impl_foldable_for_interned_slice!(Consts);