mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 13:25:09 +00:00
Add more tests, refactor array lengths/consteval work
Fix #2922: add unknown length as a condition for a type having unknown. Incorporate reviews: * Extract some of the const evaluation workings into functions * Add fixmes on the hacks * Add tests for impls on specific array lengths (these work!!! 😁) * Add tests for const generics (indeed we don't support it yet)
This commit is contained in:
parent
32c600664e
commit
78d6b88f21
8 changed files with 223 additions and 35 deletions
64
crates/hir_ty/src/consteval.rs
Normal file
64
crates/hir_ty/src/consteval.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
//! Constant evaluation details
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
use hir_def::{
|
||||
builtin_type::BuiltinUint,
|
||||
expr::{Expr, Literal},
|
||||
type_ref::ConstScalar,
|
||||
};
|
||||
|
||||
use crate::{Const, ConstData, ConstValue, Interner, TyKind};
|
||||
|
||||
/// Extension trait for [`Const`]
|
||||
pub trait ConstExtension {
|
||||
/// Is a [`Const`] unknown?
|
||||
fn is_unknown(&self) -> bool;
|
||||
}
|
||||
|
||||
impl ConstExtension for Const {
|
||||
fn is_unknown(&self) -> bool {
|
||||
match self.data(&Interner).value {
|
||||
// interned Unknown
|
||||
chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
|
||||
interned: ConstScalar::Unknown,
|
||||
}) => true,
|
||||
|
||||
// interned concrete anything else
|
||||
chalk_ir::ConstValue::Concrete(..) => false,
|
||||
|
||||
_ => {
|
||||
log::error!("is_unknown was called on a non-concrete constant value! {:?}", self);
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension trait for [`Expr`]
|
||||
pub trait ExprEval {
|
||||
/// Attempts to evaluate the expression as a target usize.
|
||||
fn eval_usize(&self) -> Option<u64>;
|
||||
}
|
||||
|
||||
impl ExprEval for Expr {
|
||||
// FIXME: support more than just evaluating literals
|
||||
fn eval_usize(&self) -> Option<u64> {
|
||||
match self {
|
||||
Expr::Literal(Literal::Uint(v, None))
|
||||
| Expr::Literal(Literal::Uint(v, Some(BuiltinUint::Usize))) => (*v).try_into().ok(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Interns a possibly-unknown target usize
|
||||
pub fn usize_const(value: Option<u64>) -> Const {
|
||||
ConstData {
|
||||
ty: TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize)).intern(&Interner),
|
||||
value: ConstValue::Concrete(chalk_ir::ConcreteConst {
|
||||
interned: value.map(|value| ConstScalar::Usize(value)).unwrap_or(ConstScalar::Unknown),
|
||||
}),
|
||||
}
|
||||
.intern(&Interner)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue