Skip to content

Commit 6fe4e51

Browse files
committed
Add support for lengths in array repeats, if they are literals
Now we will get the type of `[0u8; 4]`.
1 parent 41389e6 commit 6fe4e51

File tree

4 files changed

+22
-11
lines changed

4 files changed

+22
-11
lines changed

crates/hir_def/src/body/lower.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -996,16 +996,17 @@ impl From<ast::BinOp> for BinaryOp {
996996
impl From<ast::LiteralKind> for Literal {
997997
fn from(ast_lit_kind: ast::LiteralKind) -> Self {
998998
match ast_lit_kind {
999+
// FIXME: these should have actual values filled in, but unsure on perf impact
9991000
LiteralKind::IntNumber(lit) => {
10001001
if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
10011002
return Literal::Float(Default::default(), builtin);
10021003
} else if let builtin @ Some(_) =
10031004
lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it))
10041005
{
1005-
Literal::Int(Default::default(), builtin)
1006+
Literal::Int(lit.value().unwrap_or(0) as i128, builtin)
10061007
} else {
10071008
let builtin = lit.suffix().and_then(|it| BuiltinUint::from_suffix(&it));
1008-
Literal::Uint(Default::default(), builtin)
1009+
Literal::Uint(lit.value().unwrap_or(0), builtin)
10091010
}
10101011
}
10111012
LiteralKind::FloatNumber(lit) => {

crates/hir_def/src/expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ pub enum Literal {
4343
ByteString(Vec<u8>),
4444
Char(char),
4545
Bool(bool),
46-
Int(u64, Option<BuiltinInt>),
47-
Uint(u64, Option<BuiltinUint>),
46+
Int(i128, Option<BuiltinInt>),
47+
Uint(u128, Option<BuiltinUint>),
4848
Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq
4949
}
5050

crates/hir_ty/src/infer/expr.rs

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
//! Type inference for expressions.
22
3-
use std::iter::{repeat, repeat_with};
3+
use std::{
4+
convert::TryInto,
5+
iter::{repeat, repeat_with},
6+
};
47
use std::{mem, sync::Arc};
58

69
use chalk_ir::{cast::Cast, fold::Shift, ConstData, Mutability, TyVariableKind};
710
use hir_def::{
11+
builtin_type::BuiltinUint,
812
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
913
path::{GenericArg, GenericArgs},
1014
resolver::resolver_for_expr,
@@ -724,7 +728,7 @@ impl<'a> InferenceContext<'a> {
724728
for expr in items.iter() {
725729
self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone()));
726730
}
727-
Some(items.len())
731+
Some(items.len() as u64)
728732
}
729733
Array::Repeat { initializer, repeat } => {
730734
self.infer_expr_coerce(
@@ -737,17 +741,23 @@ impl<'a> InferenceContext<'a> {
737741
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
738742
),
739743
);
740-
// FIXME: we don't know the length here because hir Exprs don't actually
741-
// get the value out of the AST, even though it is there.
742-
None
744+
745+
let repeat_expr = &self.body.exprs[*repeat];
746+
match repeat_expr {
747+
Expr::Literal(Literal::Uint(v, None))
748+
| Expr::Literal(Literal::Uint(v, Some(BuiltinUint::Usize))) => {
749+
(*v).try_into().ok()
750+
}
751+
_ => None,
752+
}
743753
}
744754
};
745755

746756
let cd = ConstData {
747757
ty: TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
748758
value: ConstValue::Concrete(chalk_ir::ConcreteConst {
749759
interned: len
750-
.map(|len| ConstScalar::Usize(len as u64))
760+
.map(|len| ConstScalar::Usize(len))
751761
.unwrap_or(ConstScalar::Unknown),
752762
}),
753763
};

crates/hir_ty/src/tests/coercion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ fn coerce_places() {
9393
340..345 '[arr]': [&[u8]; 1]
9494
341..344 'arr': &[u8; 1]
9595
355..356 'f': [&[u8]; 2]
96-
370..378 '[arr; 2]': [&[u8]; _]
96+
370..378 '[arr; 2]': [&[u8]; 2]
9797
371..374 'arr': &[u8; 1]
9898
376..377 '2': usize
9999
388..389 'g': (&[u8], &[u8])

0 commit comments

Comments
 (0)