]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir_ty/src/infer/expr.rs
Add lowering of array lengths in types
[rust.git] / crates / hir_ty / src / infer / expr.rs
index cbbfa8b5c3a25fcf5eddcdc418aa94c6a128e773..5e942075249ab2f4ec9bfa9d6f55917c6ff64ec0 100644 (file)
@@ -3,11 +3,12 @@
 use std::iter::{repeat, repeat_with};
 use std::{mem, sync::Arc};
 
-use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind};
+use chalk_ir::{cast::Cast, fold::Shift, ConstData, Mutability, TyVariableKind};
 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};
 use crate::{
     autoderef, dummy_usize_const,
     lower::lower_to_chalk_mutability,
+    mapping::from_chalk,
     method_resolution, op,
     primitive::{self, UintTy},
     static_lifetime, to_chalk_trait_id,
-    traits::{chalk::from_chalk, FnTrait},
+    traits::FnTrait,
     utils::{generics, Generics},
-    AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
+    AdtId, Binders, CallableDefId, ConstValue, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
     ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
 };
 
@@ -462,7 +464,11 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                     };
                     match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) {
                         TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| {
-                            substs.interned().get(idx).map(|a| a.assert_ty_ref(&Interner)).cloned()
+                            substs
+                                .as_slice(&Interner)
+                                .get(idx)
+                                .map(|a| a.assert_ty_ref(&Interner))
+                                .cloned()
                         }),
                         TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
                             let local_id = self.db.struct_data(*s).variant_data.field(name)?;
@@ -712,11 +718,12 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                     _ => self.table.new_type_var(),
                 };
 
-                match array {
+                let len = match array {
                     Array::ElementList(items) => {
                         for expr in items.iter() {
                             self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone()));
                         }
+                        Some(items.len())
                     }
                     Array::Repeat { initializer, repeat } => {
                         self.infer_expr_coerce(
@@ -729,10 +736,21 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                                 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
                     }
-                }
+                };
 
-                TyKind::Array(elem_ty, dummy_usize_const()).intern(&Interner)
+                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))
+                            .unwrap_or(ConstScalar::Unknown),
+                    }),
+                };
+                TyKind::Array(elem_ty, cd.intern(&Interner)).intern(&Interner)
             }
             Expr::Literal(lit) => match lit {
                 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
@@ -742,6 +760,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                 }
                 Literal::ByteString(..) => {
                     let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
+
                     let array_type =
                         TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner);
                     TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner)
@@ -804,7 +823,7 @@ fn infer_block(
                     let ty = self.resolve_ty_as_possible(ty);
                     self.infer_pat(*pat, &ty, BindingMode::default());
                 }
-                Statement::Expr(expr) => {
+                Statement::Expr { expr, .. } => {
                     self.infer_expr(*expr, &Expectation::none());
                 }
             }