Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #21388 from Veykril/push-uyrsywszqotk
Remove unnecessary `ConstLiteralRef` enum
Lukas Wirth 4 months ago
parent 913fdb2 · parent 8ecf6fc · commit e19dfc8
-rw-r--r--crates/hir-def/src/expr_store/lower.rs1
-rw-r--r--crates/hir-def/src/hir/type_ref.rs58
-rw-r--r--crates/hir-ty/src/consteval.rs127
-rw-r--r--crates/hir-ty/src/lower.rs24
-rw-r--r--crates/hir-ty/src/next_solver/ty.rs18
5 files changed, 130 insertions, 98 deletions
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index af274f1a48..d3774ded39 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -2319,7 +2319,6 @@ impl<'db> ExprCollector<'db> {
ast::Pat::SlicePat(p) => {
let SlicePatComponents { prefix, slice, suffix } = p.components();
- // FIXME properly handle `RestPat`
Pat::Slice {
prefix: prefix.into_iter().map(|p| self.collect_pat(p, binding_list)).collect(),
slice: slice.map(|p| self.collect_pat(p, binding_list)),
diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs
index ad8535413d..b64199fa26 100644
--- a/crates/hir-def/src/hir/type_ref.rs
+++ b/crates/hir-def/src/hir/type_ref.rs
@@ -1,8 +1,6 @@
//! HIR for references to types. Paths in these are not yet resolved. They can
//! be directly created from an ast::TypeRef, without further queries.
-use std::fmt::Write;
-
use hir_expand::name::Name;
use intern::Symbol;
use la_arena::Idx;
@@ -10,12 +8,11 @@ use thin_vec::ThinVec;
use crate::{
LifetimeParamId, TypeParamId,
- builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
expr_store::{
ExpressionStore,
path::{GenericArg, Path},
},
- hir::{ExprId, Literal},
+ hir::ExprId,
};
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
@@ -275,56 +272,3 @@ impl TypeBound {
pub struct ConstRef {
pub expr: ExprId,
}
-
-/// A literal constant value
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum LiteralConstRef {
- Int(i128),
- UInt(u128),
- Bool(bool),
- Char(char),
-
- /// 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 LiteralConstRef {
- pub fn builtin_type(&self) -> BuiltinType {
- match self {
- LiteralConstRef::UInt(_) | LiteralConstRef::Unknown => {
- BuiltinType::Uint(BuiltinUint::U128)
- }
- LiteralConstRef::Int(_) => BuiltinType::Int(BuiltinInt::I128),
- LiteralConstRef::Char(_) => BuiltinType::Char,
- LiteralConstRef::Bool(_) => BuiltinType::Bool,
- }
- }
-}
-
-impl From<Literal> for LiteralConstRef {
- fn from(literal: Literal) -> Self {
- match literal {
- Literal::Char(c) => Self::Char(c),
- Literal::Bool(flag) => Self::Bool(flag),
- Literal::Int(num, _) => Self::Int(num),
- Literal::Uint(num, _) => Self::UInt(num),
- _ => Self::Unknown,
- }
- }
-}
-
-impl std::fmt::Display for LiteralConstRef {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
- match self {
- LiteralConstRef::Int(num) => num.fmt(f),
- LiteralConstRef::UInt(num) => num.fmt(f),
- LiteralConstRef::Bool(flag) => flag.fmt(f),
- LiteralConstRef::Char(c) => write!(f, "'{c}'"),
- LiteralConstRef::Unknown => f.write_char('_'),
- }
- }
-}
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index f11240e0f7..5bc2446fdd 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -7,9 +7,9 @@ use base_db::Crate;
use hir_def::{
ConstId, EnumVariantId, GeneralConstId, HasModule, StaticId,
attrs::AttrFlags,
+ builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
expr_store::Body,
- hir::{Expr, ExprId},
- type_ref::LiteralConstRef,
+ hir::{Expr, ExprId, Literal},
};
use hir_expand::Lookup;
use rustc_type_ir::inherent::IntoKind;
@@ -23,7 +23,7 @@ use crate::{
mir::{MirEvalError, MirLowerError},
next_solver::{
Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
- ParamEnv, StoredConst, StoredGenericArgs, Ty, ValueConst,
+ StoredConst, StoredGenericArgs, Ty, ValueConst,
},
traits::StoredParamEnvAndCrate,
};
@@ -81,47 +81,122 @@ impl From<MirEvalError> for ConstEvalError {
/// Interns a constant scalar with the given type
pub fn intern_const_ref<'a>(
db: &'a dyn HirDatabase,
- value: &LiteralConstRef,
+ value: &Literal,
ty: Ty<'a>,
- krate: Crate,
+ _krate: Crate,
) -> Const<'a> {
let interner = DbInterner::new_no_crate(db);
- let layout = db
- .layout_of_ty(ty.store(), ParamEnvAndCrate { param_env: ParamEnv::empty(), krate }.store());
let kind = match value {
- LiteralConstRef::Int(i) => {
- // FIXME: We should handle failure of layout better.
- let size = layout.map(|it| it.size.bytes_usize()).unwrap_or(16);
+ &Literal::Uint(i, builtin_ty)
+ if builtin_ty.is_none() || ty.as_builtin() == builtin_ty.map(BuiltinType::Uint) =>
+ {
+ let memory = match ty.as_builtin() {
+ Some(BuiltinType::Uint(builtin_uint)) => match builtin_uint {
+ BuiltinUint::U8 => Box::new([i as u8]) as Box<[u8]>,
+ BuiltinUint::U16 => Box::new((i as u16).to_le_bytes()),
+ BuiltinUint::U32 => Box::new((i as u32).to_le_bytes()),
+ BuiltinUint::U64 => Box::new((i as u64).to_le_bytes()),
+ BuiltinUint::U128 => Box::new((i).to_le_bytes()),
+ BuiltinUint::Usize => Box::new((i as usize).to_le_bytes()),
+ },
+ _ => return Const::new(interner, rustc_type_ir::ConstKind::Error(ErrorGuaranteed)),
+ };
rustc_type_ir::ConstKind::Value(ValueConst::new(
ty,
- ConstBytes {
- memory: i.to_le_bytes()[0..size].into(),
- memory_map: MemoryMap::default(),
+ ConstBytes { memory, memory_map: MemoryMap::default() },
+ ))
+ }
+ &Literal::Int(i, None)
+ if ty
+ .as_builtin()
+ .is_some_and(|builtin_ty| matches!(builtin_ty, BuiltinType::Uint(_))) =>
+ {
+ let memory = match ty.as_builtin() {
+ Some(BuiltinType::Uint(builtin_uint)) => match builtin_uint {
+ BuiltinUint::U8 => Box::new([i as u8]) as Box<[u8]>,
+ BuiltinUint::U16 => Box::new((i as u16).to_le_bytes()),
+ BuiltinUint::U32 => Box::new((i as u32).to_le_bytes()),
+ BuiltinUint::U64 => Box::new((i as u64).to_le_bytes()),
+ BuiltinUint::U128 => Box::new((i as u128).to_le_bytes()),
+ BuiltinUint::Usize => Box::new((i as usize).to_le_bytes()),
},
+ _ => return Const::new(interner, rustc_type_ir::ConstKind::Error(ErrorGuaranteed)),
+ };
+ rustc_type_ir::ConstKind::Value(ValueConst::new(
+ ty,
+ ConstBytes { memory, memory_map: MemoryMap::default() },
))
}
- LiteralConstRef::UInt(i) => {
- let size = layout.map(|it| it.size.bytes_usize()).unwrap_or(16);
+ &Literal::Int(i, builtin_ty)
+ if builtin_ty.is_none() || ty.as_builtin() == builtin_ty.map(BuiltinType::Int) =>
+ {
+ let memory = match ty.as_builtin() {
+ Some(BuiltinType::Int(builtin_int)) => match builtin_int {
+ BuiltinInt::I8 => Box::new([i as u8]) as Box<[u8]>,
+ BuiltinInt::I16 => Box::new((i as i16).to_le_bytes()),
+ BuiltinInt::I32 => Box::new((i as i32).to_le_bytes()),
+ BuiltinInt::I64 => Box::new((i as i64).to_le_bytes()),
+ BuiltinInt::I128 => Box::new((i).to_le_bytes()),
+ BuiltinInt::Isize => Box::new((i as isize).to_le_bytes()),
+ },
+ _ => return Const::new(interner, rustc_type_ir::ConstKind::Error(ErrorGuaranteed)),
+ };
rustc_type_ir::ConstKind::Value(ValueConst::new(
ty,
- ConstBytes {
- memory: i.to_le_bytes()[0..size].into(),
- memory_map: MemoryMap::default(),
+ ConstBytes { memory, memory_map: MemoryMap::default() },
+ ))
+ }
+ Literal::Float(float_type_wrapper, builtin_float)
+ if builtin_float.is_none()
+ || ty.as_builtin() == builtin_float.map(BuiltinType::Float) =>
+ {
+ let memory = match ty.as_builtin().unwrap() {
+ BuiltinType::Float(builtin_float) => match builtin_float {
+ // FIXME:
+ hir_def::builtin_type::BuiltinFloat::F16 => Box::new([0u8; 2]) as Box<[u8]>,
+ hir_def::builtin_type::BuiltinFloat::F32 => {
+ Box::new(float_type_wrapper.to_f32().to_le_bytes())
+ }
+ hir_def::builtin_type::BuiltinFloat::F64 => {
+ Box::new(float_type_wrapper.to_f64().to_le_bytes())
+ }
+ // FIXME:
+ hir_def::builtin_type::BuiltinFloat::F128 => Box::new([0; 16]),
},
+ _ => unreachable!(),
+ };
+ rustc_type_ir::ConstKind::Value(ValueConst::new(
+ ty,
+ ConstBytes { memory, memory_map: MemoryMap::default() },
))
}
- LiteralConstRef::Bool(b) => rustc_type_ir::ConstKind::Value(ValueConst::new(
+ Literal::Bool(b) if ty.is_bool() => rustc_type_ir::ConstKind::Value(ValueConst::new(
ty,
ConstBytes { memory: Box::new([*b as u8]), memory_map: MemoryMap::default() },
)),
- LiteralConstRef::Char(c) => rustc_type_ir::ConstKind::Value(ValueConst::new(
+ Literal::Char(c) if ty.is_char() => rustc_type_ir::ConstKind::Value(ValueConst::new(
ty,
ConstBytes {
memory: (*c as u32).to_le_bytes().into(),
memory_map: MemoryMap::default(),
},
)),
- LiteralConstRef::Unknown => rustc_type_ir::ConstKind::Error(ErrorGuaranteed),
+ Literal::String(symbol) if ty.is_str() => rustc_type_ir::ConstKind::Value(ValueConst::new(
+ ty,
+ ConstBytes {
+ memory: symbol.as_str().as_bytes().into(),
+ memory_map: MemoryMap::default(),
+ },
+ )),
+ Literal::ByteString(items) if ty.as_slice().is_some_and(|ty| ty.is_u8()) => {
+ rustc_type_ir::ConstKind::Value(ValueConst::new(
+ ty,
+ ConstBytes { memory: items.clone(), memory_map: MemoryMap::default() },
+ ))
+ }
+ // FIXME
+ Literal::CString(_items) => rustc_type_ir::ConstKind::Error(ErrorGuaranteed),
+ _ => rustc_type_ir::ConstKind::Error(ErrorGuaranteed),
};
Const::new(interner, kind)
}
@@ -130,7 +205,15 @@ pub fn intern_const_ref<'a>(
pub fn usize_const<'db>(db: &'db dyn HirDatabase, value: Option<u128>, krate: Crate) -> Const<'db> {
intern_const_ref(
db,
- &value.map_or(LiteralConstRef::Unknown, LiteralConstRef::UInt),
+ &match value {
+ Some(value) => Literal::Uint(value, Some(BuiltinUint::Usize)),
+ None => {
+ return Const::new(
+ DbInterner::new_no_crate(db),
+ rustc_type_ir::ConstKind::Error(ErrorGuaranteed),
+ );
+ }
+ },
Ty::new_uint(DbInterner::new_no_crate(db), rustc_type_ir::UintTy::Usize),
krate,
)
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index e45ef113a0..46ec554e0a 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -27,8 +27,8 @@ use hir_def::{
resolver::{HasResolver, LifetimeNs, Resolver, TypeNs, ValueNs},
signatures::{FunctionSignature, TraitFlags, TypeAliasFlags},
type_ref::{
- ConstRef, LifetimeRefId, LiteralConstRef, PathId, TraitBoundModifier,
- TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId,
+ ConstRef, LifetimeRefId, PathId, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound,
+ TypeRef, TypeRefId,
},
};
use hir_expand::name::Name;
@@ -281,21 +281,9 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
hir_def::hir::Expr::Path(path) => {
self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type))
}
- hir_def::hir::Expr::Literal(literal) => intern_const_ref(
- self.db,
- &match *literal {
- hir_def::hir::Literal::Float(_, _)
- | hir_def::hir::Literal::String(_)
- | hir_def::hir::Literal::ByteString(_)
- | hir_def::hir::Literal::CString(_) => LiteralConstRef::Unknown,
- hir_def::hir::Literal::Char(c) => LiteralConstRef::Char(c),
- hir_def::hir::Literal::Bool(b) => LiteralConstRef::Bool(b),
- hir_def::hir::Literal::Int(val, _) => LiteralConstRef::Int(val),
- hir_def::hir::Literal::Uint(val, _) => LiteralConstRef::UInt(val),
- },
- const_type,
- self.resolver.krate(),
- ),
+ hir_def::hir::Expr::Literal(literal) => {
+ intern_const_ref(self.db, literal, const_type, self.resolver.krate())
+ }
hir_def::hir::Expr::UnaryOp { expr: inner_expr, op: hir_def::hir::UnaryOp::Neg } => {
if let hir_def::hir::Expr::Literal(literal) = &self.store[*inner_expr] {
// Only handle negation for signed integers and floats
@@ -304,7 +292,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
if let Some(negated_literal) = literal.clone().negate() {
intern_const_ref(
self.db,
- &negated_literal.into(),
+ &negated_literal,
const_type,
self.resolver.krate(),
)
diff --git a/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs
index 030ba37015..66a24d3949 100644
--- a/crates/hir-ty/src/next_solver/ty.rs
+++ b/crates/hir-ty/src/next_solver/ty.rs
@@ -383,6 +383,11 @@ impl<'db> Ty<'db> {
matches!(self.kind(), TyKind::Bool)
}
+ #[inline]
+ pub fn is_char(self) -> bool {
+ matches!(self.kind(), TyKind::Char)
+ }
+
/// A scalar type is one that denotes an atomic datum, with no sub-components.
/// (A RawPtr is scalar because it represents a non-managed pointer, so its
/// contents are abstract to rustc.)
@@ -423,6 +428,11 @@ impl<'db> Ty<'db> {
}
#[inline]
+ pub fn is_u8(self) -> bool {
+ matches!(self.kind(), TyKind::Uint(UintTy::U8))
+ }
+
+ #[inline]
pub fn is_raw_ptr(self) -> bool {
matches!(self.kind(), TyKind::RawPtr(..))
}
@@ -457,6 +467,14 @@ impl<'db> Ty<'db> {
}
#[inline]
+ pub fn as_slice(self) -> Option<Ty<'db>> {
+ match self.kind() {
+ TyKind::Slice(ty) => Some(ty),
+ _ => None,
+ }
+ }
+
+ #[inline]
pub fn ty_vid(self) -> Option<TyVid> {
match self.kind() {
TyKind::Infer(rustc_type_ir::TyVar(vid)) => Some(vid),