mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2026-03-21 20:34:07 +00:00
Merge pull request #21388 from Veykril/push-uyrsywszqotk
Remove unnecessary `ConstLiteralRef` enum
This commit is contained in:
@@ -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)),
|
||||
|
||||
@@ -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('_'),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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(),
|
||||
)
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user