From 78d6b88f211cc9faf88815ce7fb1a91546cfce15 Mon Sep 17 00:00:00 2001 From: Jade Date: Fri, 14 May 2021 00:59:30 -0700 Subject: Add more tests, refactor array lengths/consteval work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- crates/hir_ty/src/consteval.rs | 64 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 crates/hir_ty/src/consteval.rs (limited to 'crates/hir_ty/src/consteval.rs') 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 @@ +//! 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; +} + +impl ExprEval for Expr { + // FIXME: support more than just evaluating literals + fn eval_usize(&self) -> Option { + 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) -> 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) +} -- cgit v1.2.3 From de0ed9860d86c3b905a967b1a7b5243499d32d67 Mon Sep 17 00:00:00 2001 From: Jade Date: Sat, 15 May 2021 18:51:18 -0700 Subject: Address final feedback * rename ConstExtension->ConstExt * refactor a manual construction of a Const --- crates/hir_ty/src/consteval.rs | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'crates/hir_ty/src/consteval.rs') diff --git a/crates/hir_ty/src/consteval.rs b/crates/hir_ty/src/consteval.rs index a4a430f30..e3ceb3d62 100644 --- a/crates/hir_ty/src/consteval.rs +++ b/crates/hir_ty/src/consteval.rs @@ -11,12 +11,12 @@ use hir_def::{ use crate::{Const, ConstData, ConstValue, Interner, TyKind}; /// Extension trait for [`Const`] -pub trait ConstExtension { +pub trait ConstExt { /// Is a [`Const`] unknown? fn is_unknown(&self) -> bool; } -impl ConstExtension for Const { +impl ConstExt for Const { fn is_unknown(&self) -> bool { match self.data(&Interner).value { // interned Unknown @@ -35,20 +35,12 @@ impl ConstExtension for Const { } } -/// Extension trait for [`Expr`] -pub trait ExprEval { - /// Attempts to evaluate the expression as a target usize. - fn eval_usize(&self) -> Option; -} - -impl ExprEval for Expr { - // FIXME: support more than just evaluating literals - fn eval_usize(&self) -> Option { - match self { - Expr::Literal(Literal::Uint(v, None)) - | Expr::Literal(Literal::Uint(v, Some(BuiltinUint::Usize))) => (*v).try_into().ok(), - _ => None, - } +// FIXME: support more than just evaluating literals +pub fn eval_usize(expr: &Expr) -> Option { + match expr { + Expr::Literal(Literal::Uint(v, None)) + | Expr::Literal(Literal::Uint(v, Some(BuiltinUint::Usize))) => (*v).try_into().ok(), + _ => None, } } -- cgit v1.2.3