diff options
author | Jade <[email protected]> | 2021-05-11 13:06:33 +0100 |
---|---|---|
committer | Jade <[email protected]> | 2021-05-11 13:25:19 +0100 |
commit | dc63fea427280ff278bf89a8b9c78df606009910 (patch) | |
tree | 5fb6eae3df58a7c5bc3bc5a1220dd9a5d6d3ea86 /crates/hir_ty/src/infer | |
parent | 77f0c92fd8311bccc001ddaf9eb72662d35e9836 (diff) |
Add basic support for array lengths in types
This recognizes `let a = [1u8, 2, 3]` as having type `[u8; 3]` instead
of the previous `[u8; _]`. Byte strings and `[0u8; 2]` kinds of range
array declarations are unsupported as before.
I don't know why a bunch of our rustc tests had single quotes inside
strings un-escaped by `UPDATE_EXPECT=1 cargo t`, but I don't think it's
bad? Maybe something in a nightly?
Diffstat (limited to 'crates/hir_ty/src/infer')
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 50497eecb..9aec8a236 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use std::iter::{repeat, repeat_with}; | 3 | use std::iter::{repeat, repeat_with}; |
4 | use std::{mem, sync::Arc}; | 4 | use std::{mem, sync::Arc}; |
5 | 5 | ||
6 | use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind}; | 6 | use chalk_ir::{cast::Cast, fold::Shift, ConstData, Mutability, TyVariableKind}; |
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, | 8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, |
9 | path::{GenericArg, GenericArgs}, | 9 | path::{GenericArg, GenericArgs}, |
@@ -15,7 +15,9 @@ use stdx::always; | |||
15 | use syntax::ast::RangeOp; | 15 | use syntax::ast::RangeOp; |
16 | 16 | ||
17 | use crate::{ | 17 | use crate::{ |
18 | autoderef, dummy_usize_const, | 18 | autoderef, |
19 | consts::ConstScalar, | ||
20 | dummy_usize_const, | ||
19 | lower::lower_to_chalk_mutability, | 21 | lower::lower_to_chalk_mutability, |
20 | mapping::from_chalk, | 22 | mapping::from_chalk, |
21 | method_resolution, op, | 23 | method_resolution, op, |
@@ -23,7 +25,7 @@ use crate::{ | |||
23 | static_lifetime, to_chalk_trait_id, | 25 | static_lifetime, to_chalk_trait_id, |
24 | traits::FnTrait, | 26 | traits::FnTrait, |
25 | utils::{generics, Generics}, | 27 | utils::{generics, Generics}, |
26 | AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner, | 28 | AdtId, Binders, CallableDefId, ConstValue, FnPointer, FnSig, FnSubst, InEnvironment, Interner, |
27 | ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, | 29 | ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, |
28 | }; | 30 | }; |
29 | 31 | ||
@@ -717,11 +719,12 @@ impl<'a> InferenceContext<'a> { | |||
717 | _ => self.table.new_type_var(), | 719 | _ => self.table.new_type_var(), |
718 | }; | 720 | }; |
719 | 721 | ||
720 | match array { | 722 | let len = match array { |
721 | Array::ElementList(items) => { | 723 | Array::ElementList(items) => { |
722 | for expr in items.iter() { | 724 | for expr in items.iter() { |
723 | self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone())); | 725 | self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone())); |
724 | } | 726 | } |
727 | Some(items.len()) | ||
725 | } | 728 | } |
726 | Array::Repeat { initializer, repeat } => { | 729 | Array::Repeat { initializer, repeat } => { |
727 | self.infer_expr_coerce( | 730 | self.infer_expr_coerce( |
@@ -734,10 +737,20 @@ impl<'a> InferenceContext<'a> { | |||
734 | TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner), | 737 | TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner), |
735 | ), | 738 | ), |
736 | ); | 739 | ); |
740 | // FIXME: support length for Repeat array expressions | ||
741 | None | ||
737 | } | 742 | } |
738 | } | 743 | }; |
739 | 744 | ||
740 | TyKind::Array(elem_ty, dummy_usize_const()).intern(&Interner) | 745 | let cd = ConstData { |
746 | ty: TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner), | ||
747 | value: ConstValue::Concrete(chalk_ir::ConcreteConst { | ||
748 | interned: len | ||
749 | .map(|len| ConstScalar::Usize(len)) | ||
750 | .unwrap_or(ConstScalar::Unknown), | ||
751 | }), | ||
752 | }; | ||
753 | TyKind::Array(elem_ty, cd.intern(&Interner)).intern(&Interner) | ||
741 | } | 754 | } |
742 | Expr::Literal(lit) => match lit { | 755 | Expr::Literal(lit) => match lit { |
743 | Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), | 756 | Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), |
@@ -747,6 +760,7 @@ impl<'a> InferenceContext<'a> { | |||
747 | } | 760 | } |
748 | Literal::ByteString(..) => { | 761 | Literal::ByteString(..) => { |
749 | let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); | 762 | let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); |
763 | |||
750 | let array_type = | 764 | let array_type = |
751 | TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner); | 765 | TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner); |
752 | TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner) | 766 | TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner) |