Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/lib.rs')
| -rw-r--r-- | crates/hir-ty/src/lib.rs | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 59a5ef8c14..9c63d67ab1 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -13,6 +13,7 @@ mod builder; mod chalk_db; mod chalk_ext; pub mod consteval; +pub mod mir; mod infer; mod inhabitedness; mod interner; @@ -34,7 +35,7 @@ mod tests; #[cfg(test)] mod test_db; -use std::sync::Arc; +use std::{collections::HashMap, hash::Hash, sync::Arc}; use chalk_ir::{ fold::{Shift, TypeFoldable}, @@ -42,10 +43,11 @@ use chalk_ir::{ visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, NoSolution, TyData, }; +use either::Either; use hir_def::{expr::ExprId, type_ref::Rawness, TypeOrConstParamId}; use hir_expand::name; -use itertools::Either; use la_arena::{Arena, Idx}; +use mir::MirEvalError; use rustc_hash::FxHashSet; use traits::FnTrait; use utils::Generics; @@ -145,6 +147,49 @@ pub type ConstrainedSubst = chalk_ir::ConstrainedSubst<Interner>; pub type Guidance = chalk_solve::Guidance<Interner>; pub type WhereClause = chalk_ir::WhereClause<Interner>; +/// A constant can have reference to other things. Memory map job is holding +/// the neccessary bits of memory of the const eval session to keep the constant +/// meaningful. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct MemoryMap(pub HashMap<usize, Vec<u8>>); + +impl MemoryMap { + fn insert(&mut self, addr: usize, x: Vec<u8>) { + self.0.insert(addr, x); + } + + /// This functions convert each address by a function `f` which gets the byte intervals and assign an address + /// to them. It is useful when you want to load a constant with a memory map in a new memory. You can pass an + /// allocator function as `f` and it will return a mapping of old addresses to new addresses. + fn transform_addresses( + &self, + mut f: impl FnMut(&[u8]) -> Result<usize, MirEvalError>, + ) -> Result<HashMap<usize, usize>, MirEvalError> { + self.0.iter().map(|x| Ok((*x.0, f(x.1)?))).collect() + } +} + +/// A concrete constant value +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ConstScalar { + Bytes(Vec<u8>, MemoryMap), + /// Case of an unknown value that rustc might know but we don't + // FIXME: this is a hack to get around chalk not being able to represent unevaluatable + // constants + // https://github.com/rust-lang/rust-analyzer/pull/8813#issuecomment-840679177 + // https://rust-lang.zulipchat.com/#narrow/stream/144729-wg-traits/topic/Handling.20non.20evaluatable.20constants'.20equality/near/238386348 + Unknown, +} + +impl Hash for ConstScalar { + fn hash<H: std::hash::Hasher>(&self, state: &mut H) { + core::mem::discriminant(self).hash(state); + if let ConstScalar::Bytes(b, _) = self { + b.hash(state) + } + } +} + /// Return an index of a parameter in the generic type parameter list by it's id. pub fn param_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<usize> { generics(db.upcast(), id.parent).param_idx(id) |