aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/consteval.rs
diff options
context:
space:
mode:
authorJade <[email protected]>2021-05-14 08:59:30 +0100
committerJade <[email protected]>2021-05-14 09:39:28 +0100
commit78d6b88f211cc9faf88815ce7fb1a91546cfce15 (patch)
tree6b54a10d2eeee6fc03d63015e4b7c9838b4b02b9 /crates/hir_ty/src/consteval.rs
parent32c600664e5a599bbe3f0254274211474b89914a (diff)
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)
Diffstat (limited to 'crates/hir_ty/src/consteval.rs')
-rw-r--r--crates/hir_ty/src/consteval.rs64
1 files changed, 64 insertions, 0 deletions
diff --git a/crates/hir_ty/src/consteval.rs b/crates/hir_ty/src/consteval.rs
new file mode 100644
index 000000000..a4a430f30
--- /dev/null
+++ b/crates/hir_ty/src/consteval.rs
@@ -0,0 +1,64 @@
1//! Constant evaluation details
2
3use std::convert::TryInto;
4
5use hir_def::{
6 builtin_type::BuiltinUint,
7 expr::{Expr, Literal},
8 type_ref::ConstScalar,
9};
10
11use crate::{Const, ConstData, ConstValue, Interner, TyKind};
12
13/// Extension trait for [`Const`]
14pub trait ConstExtension {
15 /// Is a [`Const`] unknown?
16 fn is_unknown(&self) -> bool;
17}
18
19impl ConstExtension for Const {
20 fn is_unknown(&self) -> bool {
21 match self.data(&Interner).value {
22 // interned Unknown
23 chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
24 interned: ConstScalar::Unknown,
25 }) => true,
26
27 // interned concrete anything else
28 chalk_ir::ConstValue::Concrete(..) => false,
29
30 _ => {
31 log::error!("is_unknown was called on a non-concrete constant value! {:?}", self);
32 true
33 }
34 }
35 }
36}
37
38/// Extension trait for [`Expr`]
39pub trait ExprEval {
40 /// Attempts to evaluate the expression as a target usize.
41 fn eval_usize(&self) -> Option<u64>;
42}
43
44impl ExprEval for Expr {
45 // FIXME: support more than just evaluating literals
46 fn eval_usize(&self) -> Option<u64> {
47 match self {
48 Expr::Literal(Literal::Uint(v, None))
49 | Expr::Literal(Literal::Uint(v, Some(BuiltinUint::Usize))) => (*v).try_into().ok(),
50 _ => None,
51 }
52 }
53}
54
55/// Interns a possibly-unknown target usize
56pub fn usize_const(value: Option<u64>) -> Const {
57 ConstData {
58 ty: TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize)).intern(&Interner),
59 value: ConstValue::Concrete(chalk_ir::ConcreteConst {
60 interned: value.map(|value| ConstScalar::Usize(value)).unwrap_or(ConstScalar::Unknown),
61 }),
62 }
63 .intern(&Interner)
64}