Merge pull request #21388 from Veykril/push-uyrsywszqotk

Remove unnecessary `ConstLiteralRef` enum
This commit is contained in:
Lukas Wirth
2026-01-02 12:30:33 +00:00
committed by GitHub
5 changed files with 132 additions and 100 deletions

View File

@@ -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)),

View File

@@ -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('_'),
}
}
}

View File

@@ -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() },
))
}
LiteralConstRef::UInt(i) => {
let size = layout.map(|it| it.size.bytes_usize()).unwrap_or(16);
&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: i.to_le_bytes()[0..size].into(),
memory_map: MemoryMap::default(),
},
ConstBytes { memory, memory_map: MemoryMap::default() },
))
}
LiteralConstRef::Bool(b) => rustc_type_ir::ConstKind::Value(ValueConst::new(
&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, 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() },
))
}
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,
)

View File

@@ -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(),
)

View File

@@ -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.)
@@ -422,6 +427,11 @@ impl<'db> Ty<'db> {
matches!(self.kind(), TyKind::Tuple(tys) if tys.is_empty())
}
#[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(..))
@@ -456,6 +466,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() {