Skip to content

Commit

Permalink
Add support for lengths in array repeats, if they are literals
Browse files Browse the repository at this point in the history
Now we will get the type of `[0u8; 4]`.
  • Loading branch information
lf- committed May 12, 2021
1 parent 41389e6 commit 6fe4e51
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 11 deletions.
5 changes: 3 additions & 2 deletions crates/hir_def/src/body/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -996,16 +996,17 @@ impl From<ast::BinOp> for BinaryOp {
impl From<ast::LiteralKind> for Literal {
fn from(ast_lit_kind: ast::LiteralKind) -> Self {
match ast_lit_kind {
// FIXME: these should have actual values filled in, but unsure on perf impact
LiteralKind::IntNumber(lit) => {
if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
return Literal::Float(Default::default(), builtin);
} else if let builtin @ Some(_) =
lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it))
{
Literal::Int(Default::default(), builtin)
Literal::Int(lit.value().unwrap_or(0) as i128, builtin)
} else {
let builtin = lit.suffix().and_then(|it| BuiltinUint::from_suffix(&it));
Literal::Uint(Default::default(), builtin)
Literal::Uint(lit.value().unwrap_or(0), builtin)
}
}
LiteralKind::FloatNumber(lit) => {
Expand Down
4 changes: 2 additions & 2 deletions crates/hir_def/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ pub enum Literal {
ByteString(Vec<u8>),
Char(char),
Bool(bool),
Int(u64, Option<BuiltinInt>),
Uint(u64, Option<BuiltinUint>),
Int(i128, Option<BuiltinInt>),
Uint(u128, Option<BuiltinUint>),
Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq
}

Expand Down
22 changes: 16 additions & 6 deletions crates/hir_ty/src/infer/expr.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
//! Type inference for expressions.
use std::iter::{repeat, repeat_with};
use std::{
convert::TryInto,
iter::{repeat, repeat_with},
};
use std::{mem, sync::Arc};

use chalk_ir::{cast::Cast, fold::Shift, ConstData, Mutability, TyVariableKind};
use hir_def::{
builtin_type::BuiltinUint,
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
path::{GenericArg, GenericArgs},
resolver::resolver_for_expr,
Expand Down Expand Up @@ -724,7 +728,7 @@ impl<'a> InferenceContext<'a> {
for expr in items.iter() {
self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone()));
}
Some(items.len())
Some(items.len() as u64)
}
Array::Repeat { initializer, repeat } => {
self.infer_expr_coerce(
Expand All @@ -737,17 +741,23 @@ impl<'a> InferenceContext<'a> {
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
),
);
// FIXME: we don't know the length here because hir Exprs don't actually
// get the value out of the AST, even though it is there.
None

let repeat_expr = &self.body.exprs[*repeat];
match repeat_expr {
Expr::Literal(Literal::Uint(v, None))
| Expr::Literal(Literal::Uint(v, Some(BuiltinUint::Usize))) => {
(*v).try_into().ok()
}
_ => None,
}
}
};

let cd = ConstData {
ty: TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
value: ConstValue::Concrete(chalk_ir::ConcreteConst {
interned: len
.map(|len| ConstScalar::Usize(len as u64))
.map(|len| ConstScalar::Usize(len))
.unwrap_or(ConstScalar::Unknown),
}),
};
Expand Down
2 changes: 1 addition & 1 deletion crates/hir_ty/src/tests/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ fn coerce_places() {
340..345 '[arr]': [&[u8]; 1]
341..344 'arr': &[u8; 1]
355..356 'f': [&[u8]; 2]
370..378 '[arr; 2]': [&[u8]; _]
370..378 '[arr; 2]': [&[u8]; 2]
371..374 'arr': &[u8; 1]
376..377 '2': usize
388..389 'g': (&[u8], &[u8])
Expand Down

0 comments on commit 6fe4e51

Please sign in to comment.