From e666589e63fd4de16baa5f1ebda4ab07aa5a5437 Mon Sep 17 00:00:00 2001 From: Jade Date: Wed, 12 May 2021 05:59:35 -0700 Subject: Add support for lengths in array repeats, if they are literals Now we will get the type of `[0u8; 4]`. --- crates/hir_def/src/body/lower.rs | 5 +++-- crates/hir_def/src/expr.rs | 4 ++-- crates/hir_ty/src/infer/expr.rs | 22 ++++++++++++++++------ crates/hir_ty/src/tests/coercion.rs | 2 +- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index b00dcbdf0..2a7e0205f 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs @@ -1006,16 +1006,17 @@ impl From for BinaryOp { impl From 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) => { diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs index 0c3b41080..2ba619d23 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs @@ -43,8 +43,8 @@ pub enum Literal { ByteString(Vec), Char(char), Bool(bool), - Int(u64, Option), - Uint(u64, Option), + Int(i128, Option), + Uint(u128, Option), Float(u64, Option), // FIXME: f64 is not Eq } diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 46e4777a4..0b36ac861 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -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, @@ -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( @@ -737,9 +741,15 @@ 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, + } } }; @@ -747,7 +757,7 @@ impl<'a> InferenceContext<'a> { 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), }), }; diff --git a/crates/hir_ty/src/tests/coercion.rs b/crates/hir_ty/src/tests/coercion.rs index c2afaf6ec..190471069 100644 --- a/crates/hir_ty/src/tests/coercion.rs +++ b/crates/hir_ty/src/tests/coercion.rs @@ -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]) -- cgit v1.2.3