From 8b147624ff906a11134d2e18be071c6cb8ec4beb Mon Sep 17 00:00:00 2001 From: Jade Date: Wed, 12 May 2021 04:39:48 -0700 Subject: Add lowering of array lengths in types Now e.g. ```rust fn a(b: [u8; 2]) { } ``` will know about the length of b. --- crates/hir_ty/src/infer/expr.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'crates/hir_ty/src/infer') diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 2178ffd07..5e9420752 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -8,6 +8,7 @@ use hir_def::{ expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, path::{GenericArg, GenericArgs}, resolver::resolver_for_expr, + type_ref::ConstScalar, AssocContainerId, FieldId, Lookup, }; use hir_expand::name::{name, Name}; @@ -15,9 +16,7 @@ use stdx::always; use syntax::ast::RangeOp; use crate::{ - autoderef, - consts::ConstScalar, - dummy_usize_const, + autoderef, dummy_usize_const, lower::lower_to_chalk_mutability, mapping::from_chalk, method_resolution, op, @@ -737,7 +736,8 @@ impl<'a> InferenceContext<'a> { TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner), ), ); - // FIXME: support length for Repeat array expressions + // 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 } }; -- cgit v1.2.3 From 73023c0299d4adeada026648c3684621f129e038 Mon Sep 17 00:00:00 2001 From: Jade Date: Wed, 12 May 2021 05:44:01 -0700 Subject: Support length for ByteStrings I am not confident that my added byte string parsing is right. --- crates/hir_ty/src/infer/expr.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'crates/hir_ty/src/infer') diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 5e9420752..46e4777a4 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -16,7 +16,7 @@ use stdx::always; use syntax::ast::RangeOp; use crate::{ - autoderef, dummy_usize_const, + autoderef, lower::lower_to_chalk_mutability, mapping::from_chalk, method_resolution, op, @@ -24,8 +24,9 @@ use crate::{ static_lifetime, to_chalk_trait_id, traits::FnTrait, utils::{generics, Generics}, - AdtId, Binders, CallableDefId, ConstValue, FnPointer, FnSig, FnSubst, InEnvironment, Interner, - ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, + AdtId, Binders, CallableDefId, ConcreteConst, ConstValue, FnPointer, FnSig, FnSubst, + InEnvironment, Interner, ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, + TyBuilder, TyExt, TyKind, }; use super::{ @@ -758,11 +759,18 @@ impl<'a> InferenceContext<'a> { TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(&Interner)) .intern(&Interner) } - Literal::ByteString(..) => { + Literal::ByteString(bs) => { let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); - let array_type = - TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner); + let len = ConstData { + ty: TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner), + value: ConstValue::Concrete(ConcreteConst { + interned: ConstScalar::Usize(bs.len() as u64), + }), + } + .intern(&Interner); + + let array_type = TyKind::Array(byte_type, len).intern(&Interner); TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner) } Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner), -- cgit v1.2.3 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_ty/src/infer/expr.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'crates/hir_ty/src/infer') 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), }), }; -- cgit v1.2.3 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/infer/expr.rs | 41 ++++++++--------------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) (limited to 'crates/hir_ty/src/infer') diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 0b36ac861..04fc2f12b 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -1,18 +1,13 @@ //! Type inference for expressions. -use std::{ - convert::TryInto, - iter::{repeat, repeat_with}, -}; +use std::iter::{repeat, repeat_with}; use std::{mem, sync::Arc}; -use chalk_ir::{cast::Cast, fold::Shift, ConstData, Mutability, TyVariableKind}; +use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind}; use hir_def::{ - builtin_type::BuiltinUint, expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, path::{GenericArg, GenericArgs}, resolver::resolver_for_expr, - type_ref::ConstScalar, AssocContainerId, FieldId, Lookup, }; use hir_expand::name::{name, Name}; @@ -21,6 +16,7 @@ use syntax::ast::RangeOp; use crate::{ autoderef, + consteval::{self, ExprEval}, lower::lower_to_chalk_mutability, mapping::from_chalk, method_resolution, op, @@ -28,9 +24,8 @@ use crate::{ static_lifetime, to_chalk_trait_id, traits::FnTrait, utils::{generics, Generics}, - AdtId, Binders, CallableDefId, ConcreteConst, ConstValue, FnPointer, FnSig, FnSubst, - InEnvironment, Interner, ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, - TyBuilder, TyExt, TyKind, + AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner, + ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, }; use super::{ @@ -743,25 +738,11 @@ impl<'a> InferenceContext<'a> { ); 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, - } + repeat_expr.eval_usize() } }; - 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)) - .unwrap_or(ConstScalar::Unknown), - }), - }; - TyKind::Array(elem_ty, cd.intern(&Interner)).intern(&Interner) + TyKind::Array(elem_ty, consteval::usize_const(len)).intern(&Interner) } Expr::Literal(lit) => match lit { Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), @@ -772,13 +753,7 @@ impl<'a> InferenceContext<'a> { Literal::ByteString(bs) => { let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); - let len = ConstData { - ty: TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner), - value: ConstValue::Concrete(ConcreteConst { - interned: ConstScalar::Usize(bs.len() as u64), - }), - } - .intern(&Interner); + let len = consteval::usize_const(Some(bs.len() as u64)); let array_type = TyKind::Array(byte_type, len).intern(&Interner); TyKind::Ref(Mutability::Not, static_lifetime(), array_type).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/infer/expr.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'crates/hir_ty/src/infer') diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 04fc2f12b..b6b5a1b75 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -15,8 +15,7 @@ use stdx::always; use syntax::ast::RangeOp; use crate::{ - autoderef, - consteval::{self, ExprEval}, + autoderef, consteval, lower::lower_to_chalk_mutability, mapping::from_chalk, method_resolution, op, @@ -738,7 +737,7 @@ impl<'a> InferenceContext<'a> { ); let repeat_expr = &self.body.exprs[*repeat]; - repeat_expr.eval_usize() + consteval::eval_usize(repeat_expr) } }; -- cgit v1.2.3