Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/pat.rs')
-rw-r--r--crates/hir-ty/src/infer/pat.rs345
1 files changed, 171 insertions, 174 deletions
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index 18288b718f..8019844b5d 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -8,35 +8,35 @@ use hir_def::{
hir::{Binding, BindingAnnotation, BindingId, Expr, ExprId, Literal, Pat, PatId},
};
use hir_expand::name::Name;
+use rustc_ast_ir::Mutability;
+use rustc_type_ir::inherent::{GenericArg as _, GenericArgs as _, IntoKind, SliceLike, Ty as _};
use stdx::TupleExt;
use crate::{
- DeclContext, DeclOrigin, InferenceDiagnostic, Interner, Mutability, Scalar, Substitution, Ty,
- TyBuilder, TyExt, TyKind,
+ DeclContext, DeclOrigin, InferenceDiagnostic,
consteval::{self, try_const_usize, usize_const},
infer::{
- BindingMode, Expectation, InferenceContext, TypeMismatch, coerce::CoerceNever,
- expr::ExprIsRead,
+ AllowTwoPhase, BindingMode, Expectation, InferenceContext, TypeMismatch,
+ coerce::CoerceNever, expr::ExprIsRead,
},
- lower::lower_to_chalk_mutability,
- primitive::UintTy,
- static_lifetime,
+ lower::lower_mutability,
+ next_solver::{GenericArgs, Ty, TyKind},
};
-impl InferenceContext<'_> {
+impl<'db> InferenceContext<'_, 'db> {
/// Infers type for tuple struct pattern or its corresponding assignee expression.
///
/// Ellipses found in the original pattern or expression must be filtered out.
pub(super) fn infer_tuple_struct_pat_like(
&mut self,
path: Option<&Path>,
- expected: &Ty,
+ expected: Ty<'db>,
default_bm: BindingMode,
id: PatId,
ellipsis: Option<u32>,
subs: &[PatId],
decl: Option<DeclContext>,
- ) -> Ty {
+ ) -> Ty<'db> {
let (ty, def) = self.resolve_variant(id.into(), path, true);
let var_data = def.map(|it| it.fields(self.db));
if let Some(variant) = def {
@@ -54,7 +54,7 @@ impl InferenceContext<'_> {
}
}
- self.unify(&ty, expected);
+ self.unify(ty, expected);
match def {
_ if subs.is_empty() => {}
@@ -83,24 +83,24 @@ impl InferenceContext<'_> {
{
// FIXME(DIAGNOSE): private tuple field
}
- let f = field_types[local_id].clone();
+ let f = field_types[local_id];
let expected_ty = match substs {
- Some(substs) => f.substitute(Interner, substs),
- None => f.substitute(Interner, &Substitution::empty(Interner)),
+ Some(substs) => f.instantiate(self.interner(), substs),
+ None => f.instantiate(self.interner(), &[]),
};
- self.normalize_associated_types_in(expected_ty)
+ self.process_remote_user_written_ty(expected_ty)
}
None => self.err_ty(),
}
};
- self.infer_pat(subpat, &expected_ty, default_bm, decl);
+ self.infer_pat(subpat, expected_ty, default_bm, decl);
}
}
None => {
let err_ty = self.err_ty();
for &inner in subs {
- self.infer_pat(inner, &err_ty, default_bm, decl);
+ self.infer_pat(inner, err_ty, default_bm, decl);
}
}
}
@@ -112,18 +112,18 @@ impl InferenceContext<'_> {
pub(super) fn infer_record_pat_like(
&mut self,
path: Option<&Path>,
- expected: &Ty,
+ expected: Ty<'db>,
default_bm: BindingMode,
id: PatId,
subs: impl ExactSizeIterator<Item = (Name, PatId)>,
decl: Option<DeclContext>,
- ) -> Ty {
+ ) -> Ty<'db> {
let (ty, def) = self.resolve_variant(id.into(), path, false);
if let Some(variant) = def {
self.write_variant_resolution(id.into(), variant);
}
- self.unify(&ty, expected);
+ self.unify(ty, expected);
match def {
_ if subs.len() == 0 => {}
@@ -147,12 +147,12 @@ impl InferenceContext<'_> {
variant: def,
});
}
- let f = field_types[local_id].clone();
+ let f = field_types[local_id];
let expected_ty = match substs {
- Some(substs) => f.substitute(Interner, substs),
- None => f.substitute(Interner, &Substitution::empty(Interner)),
+ Some(substs) => f.instantiate(self.interner(), substs),
+ None => f.instantiate(self.interner(), &[]),
};
- self.normalize_associated_types_in(expected_ty)
+ self.process_remote_user_written_ty(expected_ty)
}
None => {
self.push_diagnostic(InferenceDiagnostic::NoSuchField {
@@ -165,13 +165,13 @@ impl InferenceContext<'_> {
}
};
- self.infer_pat(inner, &expected_ty, default_bm, decl);
+ self.infer_pat(inner, expected_ty, default_bm, decl);
}
}
None => {
let err_ty = self.err_ty();
for (_, inner) in subs {
- self.infer_pat(inner, &err_ty, default_bm, decl);
+ self.infer_pat(inner, err_ty, default_bm, decl);
}
}
}
@@ -184,16 +184,16 @@ impl InferenceContext<'_> {
/// Ellipses found in the original pattern or expression must be filtered out.
pub(super) fn infer_tuple_pat_like(
&mut self,
- expected: &Ty,
+ expected: Ty<'db>,
default_bm: BindingMode,
ellipsis: Option<u32>,
subs: &[PatId],
decl: Option<DeclContext>,
- ) -> Ty {
- let expected = self.resolve_ty_shallow(expected);
- let expectations = match expected.as_tuple() {
- Some(parameters) => parameters.as_slice(Interner),
- _ => &[],
+ ) -> Ty<'db> {
+ let expected = self.table.structurally_resolve_type(expected);
+ let expectations = match expected.kind() {
+ TyKind::Tuple(parameters) => parameters,
+ _ => self.types.empty_tys,
};
let ((pre, post), n_uncovered_patterns) = match ellipsis {
@@ -202,10 +202,8 @@ impl InferenceContext<'_> {
}
None => ((subs, &[][..]), 0),
};
- let mut expectations_iter = expectations
- .iter()
- .map(|a| a.assert_ty_ref(Interner).clone())
- .chain(repeat_with(|| self.table.new_type_var()));
+ let mut expectations_iter =
+ expectations.iter().chain(repeat_with(|| self.table.next_ty_var()));
let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + subs.len());
@@ -213,32 +211,36 @@ impl InferenceContext<'_> {
// Process pre
for (ty, pat) in inner_tys.iter_mut().zip(pre) {
- *ty = self.infer_pat(*pat, ty, default_bm, decl);
+ *ty = self.infer_pat(*pat, *ty, default_bm, decl);
}
// Process post
for (ty, pat) in inner_tys.iter_mut().skip(pre.len() + n_uncovered_patterns).zip(post) {
- *ty = self.infer_pat(*pat, ty, default_bm, decl);
+ *ty = self.infer_pat(*pat, *ty, default_bm, decl);
}
- TyKind::Tuple(inner_tys.len(), Substitution::from_iter(Interner, inner_tys))
- .intern(Interner)
+ Ty::new_tup_from_iter(self.interner(), inner_tys.into_iter())
}
/// The resolver needs to be updated to the surrounding expression when inside assignment
/// (because there, `Pat::Path` can refer to a variable).
- pub(super) fn infer_top_pat(&mut self, pat: PatId, expected: &Ty, decl: Option<DeclContext>) {
+ pub(super) fn infer_top_pat(
+ &mut self,
+ pat: PatId,
+ expected: Ty<'db>,
+ decl: Option<DeclContext>,
+ ) {
self.infer_pat(pat, expected, BindingMode::default(), decl);
}
fn infer_pat(
&mut self,
pat: PatId,
- expected: &Ty,
+ expected: Ty<'db>,
mut default_bm: BindingMode,
decl: Option<DeclContext>,
- ) -> Ty {
- let mut expected = self.resolve_ty_shallow(expected);
+ ) -> Ty<'db> {
+ let mut expected = self.table.structurally_resolve_type(expected);
if matches!(&self.body[pat], Pat::Ref { .. }) || self.inside_assignment {
cov_mark::hit!(match_ergonomics_ref);
@@ -249,9 +251,9 @@ impl InferenceContext<'_> {
default_bm = BindingMode::Move;
} else if self.is_non_ref_pat(self.body, pat) {
let mut pat_adjustments = Vec::new();
- while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
- pat_adjustments.push(expected.clone());
- expected = self.resolve_ty_shallow(inner);
+ while let TyKind::Ref(_lifetime, inner, mutability) = expected.kind() {
+ pat_adjustments.push(expected);
+ expected = self.table.try_structurally_resolve_type(inner);
default_bm = match default_bm {
BindingMode::Move => BindingMode::Ref(mutability),
BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not),
@@ -271,25 +273,21 @@ impl InferenceContext<'_> {
let ty = match &self.body[pat] {
Pat::Tuple { args, ellipsis } => {
- self.infer_tuple_pat_like(&expected, default_bm, *ellipsis, args, decl)
+ self.infer_tuple_pat_like(expected, default_bm, *ellipsis, args, decl)
}
Pat::Or(pats) => {
for pat in pats.iter() {
- self.infer_pat(*pat, &expected, default_bm, decl);
+ self.infer_pat(*pat, expected, default_bm, decl);
}
- expected.clone()
+ expected
+ }
+ &Pat::Ref { pat, mutability } => {
+ self.infer_ref_pat(pat, lower_mutability(mutability), expected, default_bm, decl)
}
- &Pat::Ref { pat, mutability } => self.infer_ref_pat(
- pat,
- lower_to_chalk_mutability(mutability),
- &expected,
- default_bm,
- decl,
- ),
Pat::TupleStruct { path: p, args: subpats, ellipsis } => self
.infer_tuple_struct_pat_like(
p.as_deref(),
- &expected,
+ expected,
default_bm,
pat,
*ellipsis,
@@ -298,30 +296,26 @@ impl InferenceContext<'_> {
),
Pat::Record { path: p, args: fields, ellipsis: _ } => {
let subs = fields.iter().map(|f| (f.name.clone(), f.pat));
- self.infer_record_pat_like(p.as_deref(), &expected, default_bm, pat, subs, decl)
+ self.infer_record_pat_like(p.as_deref(), expected, default_bm, pat, subs, decl)
}
Pat::Path(path) => {
let ty = self.infer_path(path, pat.into()).unwrap_or_else(|| self.err_ty());
- let ty_inserted_vars = self.insert_type_vars_shallow(ty.clone());
- match self.table.coerce(&expected, &ty_inserted_vars, CoerceNever::Yes) {
- Ok((adjustments, coerced_ty)) => {
- if !adjustments.is_empty() {
- self.result
- .pat_adjustments
- .entry(pat)
- .or_default()
- .extend(adjustments.into_iter().map(|adjust| adjust.target));
- }
+ let ty_inserted_vars = self.insert_type_vars_shallow(ty);
+ match self.coerce(
+ pat.into(),
+ expected,
+ ty_inserted_vars,
+ AllowTwoPhase::No,
+ CoerceNever::Yes,
+ ) {
+ Ok(coerced_ty) => {
self.write_pat_ty(pat, coerced_ty);
return self.pat_ty_after_adjustment(pat);
}
Err(_) => {
self.result.type_mismatches.insert(
pat.into(),
- TypeMismatch {
- expected: expected.clone(),
- actual: ty_inserted_vars.clone(),
- },
+ TypeMismatch { expected, actual: ty_inserted_vars },
);
self.write_pat_ty(pat, ty);
// We return `expected` to prevent cascading errors. I guess an alternative is to
@@ -331,75 +325,77 @@ impl InferenceContext<'_> {
}
}
Pat::Bind { id, subpat } => {
- return self.infer_bind_pat(pat, *id, default_bm, *subpat, &expected, decl);
+ return self.infer_bind_pat(pat, *id, default_bm, *subpat, expected, decl);
}
Pat::Slice { prefix, slice, suffix } => {
- self.infer_slice_pat(&expected, prefix, slice, suffix, default_bm, decl)
+ self.infer_slice_pat(expected, prefix, *slice, suffix, default_bm, decl)
}
- Pat::Wild => expected.clone(),
+ Pat::Wild => expected,
Pat::Range { .. } => {
// FIXME: do some checks here.
- expected.clone()
+ expected
}
&Pat::Lit(expr) => {
// Don't emit type mismatches again, the expression lowering already did that.
- let ty = self.infer_lit_pat(expr, &expected);
+ let ty = self.infer_lit_pat(expr, expected);
self.write_pat_ty(pat, ty);
return self.pat_ty_after_adjustment(pat);
}
Pat::Box { inner } => match self.resolve_boxed_box() {
Some(box_adt) => {
let (inner_ty, alloc_ty) = match expected.as_adt() {
- Some((adt, subst)) if adt == box_adt => (
- subst.at(Interner, 0).assert_ty_ref(Interner).clone(),
- subst.as_slice(Interner).get(1).and_then(|a| a.ty(Interner).cloned()),
- ),
- _ => (self.result.standard_types.unknown.clone(), None),
+ Some((adt, subst)) if adt == box_adt => {
+ (subst.type_at(0), subst.as_slice().get(1).and_then(|a| a.as_type()))
+ }
+ _ => (self.types.error, None),
};
- let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm, decl);
- let mut b = TyBuilder::adt(self.db, box_adt).push(inner_ty);
-
- if let Some(alloc_ty) = alloc_ty {
- b = b.push(alloc_ty);
- }
- b.fill_with_defaults(self.db, || self.table.new_type_var()).build()
+ let inner_ty = self.infer_pat(*inner, inner_ty, default_bm, decl);
+ Ty::new_adt(
+ self.interner(),
+ box_adt,
+ GenericArgs::fill_with_defaults(
+ self.interner(),
+ box_adt.into(),
+ std::iter::once(inner_ty.into()).chain(alloc_ty.map(Into::into)),
+ |_, id, _| self.table.next_var_for_param(id),
+ ),
+ )
}
None => self.err_ty(),
},
Pat::ConstBlock(expr) => {
let old_inside_assign = std::mem::replace(&mut self.inside_assignment, false);
- let result = self.infer_expr(
- *expr,
- &Expectation::has_type(expected.clone()),
- ExprIsRead::Yes,
- );
+ let result =
+ self.infer_expr(*expr, &Expectation::has_type(expected), ExprIsRead::Yes);
self.inside_assignment = old_inside_assign;
result
}
Pat::Expr(expr) => {
let old_inside_assign = std::mem::replace(&mut self.inside_assignment, false);
// LHS of assignment doesn't constitute reads.
- let result = self.infer_expr_coerce(
- *expr,
- &Expectation::has_type(expected.clone()),
- ExprIsRead::No,
- );
+ let result =
+ self.infer_expr_coerce(*expr, &Expectation::has_type(expected), ExprIsRead::No);
// We are returning early to avoid the unifiability check below.
let lhs_ty = self.insert_type_vars_shallow(result);
- let ty = match self.coerce(None, &expected, &lhs_ty, CoerceNever::Yes) {
+ let ty = match self.coerce(
+ pat.into(),
+ expected,
+ lhs_ty,
+ AllowTwoPhase::No,
+ CoerceNever::Yes,
+ ) {
Ok(ty) => ty,
Err(_) => {
- self.result.type_mismatches.insert(
- pat.into(),
- TypeMismatch { expected: expected.clone(), actual: lhs_ty.clone() },
- );
+ self.result
+ .type_mismatches
+ .insert(pat.into(), TypeMismatch { expected, actual: lhs_ty });
// `rhs_ty` is returned so no further type mismatches are
// reported because of this mismatch.
expected
}
};
- self.write_pat_ty(pat, ty.clone());
+ self.write_pat_ty(pat, ty);
self.inside_assignment = old_inside_assign;
return ty;
}
@@ -408,46 +404,43 @@ impl InferenceContext<'_> {
// use a new type variable if we got error type here
let ty = self.insert_type_vars_shallow(ty);
// FIXME: This never check is odd, but required with out we do inference right now
- if !expected.is_never() && !self.unify(&ty, &expected) {
- self.result
- .type_mismatches
- .insert(pat.into(), TypeMismatch { expected, actual: ty.clone() });
+ if !expected.is_never() && !self.unify(ty, expected) {
+ self.result.type_mismatches.insert(pat.into(), TypeMismatch { expected, actual: ty });
}
self.write_pat_ty(pat, ty);
self.pat_ty_after_adjustment(pat)
}
- fn pat_ty_after_adjustment(&self, pat: PatId) -> Ty {
- self.result
+ fn pat_ty_after_adjustment(&self, pat: PatId) -> Ty<'db> {
+ *self
+ .result
.pat_adjustments
.get(&pat)
.and_then(|it| it.first())
.unwrap_or(&self.result.type_of_pat[pat])
- .clone()
}
fn infer_ref_pat(
&mut self,
inner_pat: PatId,
mutability: Mutability,
- expected: &Ty,
+ expected: Ty<'db>,
default_bm: BindingMode,
decl: Option<DeclContext>,
- ) -> Ty {
- let (expectation_type, expectation_lt) = match expected.as_reference() {
- Some((inner_ty, lifetime, _exp_mut)) => (inner_ty.clone(), lifetime),
- None => {
- let inner_ty = self.table.new_type_var();
- let inner_lt = self.table.new_lifetime_var();
- let ref_ty =
- TyKind::Ref(mutability, inner_lt.clone(), inner_ty.clone()).intern(Interner);
+ ) -> Ty<'db> {
+ let (expectation_type, expectation_lt) = match expected.kind() {
+ TyKind::Ref(lifetime, inner_ty, _exp_mut) => (inner_ty, lifetime),
+ _ => {
+ let inner_ty = self.table.next_ty_var();
+ let inner_lt = self.table.next_region_var();
+ let ref_ty = Ty::new_ref(self.interner(), inner_lt, inner_ty, mutability);
// Unification failure will be reported by the caller.
- self.unify(&ref_ty, expected);
+ self.unify(ref_ty, expected);
(inner_ty, inner_lt)
}
};
- let subty = self.infer_pat(inner_pat, &expectation_type, default_bm, decl);
- TyKind::Ref(mutability, expectation_lt, subty).intern(Interner)
+ let subty = self.infer_pat(inner_pat, expectation_type, default_bm, decl);
+ Ty::new_ref(self.interner(), expectation_lt, subty, mutability)
}
fn infer_bind_pat(
@@ -456,9 +449,9 @@ impl InferenceContext<'_> {
binding: BindingId,
default_bm: BindingMode,
subpat: Option<PatId>,
- expected: &Ty,
+ expected: Ty<'db>,
decl: Option<DeclContext>,
- ) -> Ty {
+ ) -> Ty<'db> {
let Binding { mode, .. } = self.body[binding];
let mode = if mode == BindingAnnotation::Unannotated {
default_bm
@@ -469,91 +462,95 @@ impl InferenceContext<'_> {
let inner_ty = match subpat {
Some(subpat) => self.infer_pat(subpat, expected, default_bm, decl),
- None => expected.clone(),
+ None => expected,
};
let inner_ty = self.insert_type_vars_shallow(inner_ty);
let bound_ty = match mode {
BindingMode::Ref(mutability) => {
- let inner_lt = self.table.new_lifetime_var();
- TyKind::Ref(mutability, inner_lt, inner_ty.clone()).intern(Interner)
+ let inner_lt = self.table.next_region_var();
+ Ty::new_ref(self.interner(), inner_lt, inner_ty, mutability)
}
- BindingMode::Move => inner_ty.clone(),
+ BindingMode::Move => inner_ty,
};
- self.write_pat_ty(pat, inner_ty.clone());
+ self.write_pat_ty(pat, inner_ty);
self.write_binding_ty(binding, bound_ty);
inner_ty
}
fn infer_slice_pat(
&mut self,
- expected: &Ty,
+ expected: Ty<'db>,
prefix: &[PatId],
- slice: &Option<PatId>,
+ slice: Option<PatId>,
suffix: &[PatId],
default_bm: BindingMode,
decl: Option<DeclContext>,
- ) -> Ty {
- let expected = self.resolve_ty_shallow(expected);
+ ) -> Ty<'db> {
+ let expected = self.table.structurally_resolve_type(expected);
// If `expected` is an infer ty, we try to equate it to an array if the given pattern
// allows it. See issue #16609
- if self.pat_is_irrefutable(decl) && expected.is_ty_var() {
- if let Some(resolved_array_ty) =
+ if self.pat_is_irrefutable(decl)
+ && expected.is_ty_var()
+ && let Some(resolved_array_ty) =
self.try_resolve_slice_ty_to_array_ty(prefix, suffix, slice)
- {
- self.unify(&expected, &resolved_array_ty);
- }
+ {
+ self.unify(expected, resolved_array_ty);
}
- let expected = self.resolve_ty_shallow(&expected);
- let elem_ty = match expected.kind(Interner) {
- TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
+ let expected = self.table.try_structurally_resolve_type(expected);
+ let elem_ty = match expected.kind() {
+ TyKind::Array(st, _) | TyKind::Slice(st) => st,
_ => self.err_ty(),
};
for &pat_id in prefix.iter().chain(suffix.iter()) {
- self.infer_pat(pat_id, &elem_ty, default_bm, decl);
+ self.infer_pat(pat_id, elem_ty, default_bm, decl);
}
- if let &Some(slice_pat_id) = slice {
- let rest_pat_ty = match expected.kind(Interner) {
+ if let Some(slice_pat_id) = slice {
+ let rest_pat_ty = match expected.kind() {
TyKind::Array(_, length) => {
let len = try_const_usize(self.db, length);
let len =
len.and_then(|len| len.checked_sub((prefix.len() + suffix.len()) as u128));
- TyKind::Array(elem_ty.clone(), usize_const(self.db, len, self.resolver.krate()))
+ Ty::new_array_with_const_len(
+ self.interner(),
+ elem_ty,
+ usize_const(self.db, len, self.resolver.krate()),
+ )
}
- _ => TyKind::Slice(elem_ty.clone()),
- }
- .intern(Interner);
- self.infer_pat(slice_pat_id, &rest_pat_ty, default_bm, decl);
+ _ => Ty::new_slice(self.interner(), elem_ty),
+ };
+ self.infer_pat(slice_pat_id, rest_pat_ty, default_bm, decl);
}
- match expected.kind(Interner) {
- TyKind::Array(_, const_) => TyKind::Array(elem_ty, const_.clone()),
- _ => TyKind::Slice(elem_ty),
+ match expected.kind() {
+ TyKind::Array(_, const_) => {
+ Ty::new_array_with_const_len(self.interner(), elem_ty, const_)
+ }
+ _ => Ty::new_slice(self.interner(), elem_ty),
}
- .intern(Interner)
}
- fn infer_lit_pat(&mut self, expr: ExprId, expected: &Ty) -> Ty {
+ fn infer_lit_pat(&mut self, expr: ExprId, expected: Ty<'db>) -> Ty<'db> {
// Like slice patterns, byte string patterns can denote both `&[u8; N]` and `&[u8]`.
- if let Expr::Literal(Literal::ByteString(_)) = self.body[expr] {
- if let Some((inner, ..)) = expected.as_reference() {
- let inner = self.resolve_ty_shallow(inner);
- if matches!(inner.kind(Interner), TyKind::Slice(_)) {
- let elem_ty = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner);
- let slice_ty = TyKind::Slice(elem_ty).intern(Interner);
- let ty =
- TyKind::Ref(Mutability::Not, static_lifetime(), slice_ty).intern(Interner);
- self.write_expr_ty(expr, ty.clone());
- return ty;
- }
+ if let Expr::Literal(Literal::ByteString(_)) = self.body[expr]
+ && let TyKind::Ref(_, inner, _) = expected.kind()
+ {
+ let inner = self.table.try_structurally_resolve_type(inner);
+ if matches!(inner.kind(), TyKind::Slice(_)) {
+ let elem_ty = self.types.u8;
+ let slice_ty = Ty::new_slice(self.interner(), elem_ty);
+ let ty =
+ Ty::new_ref(self.interner(), self.types.re_static, slice_ty, Mutability::Not);
+ self.write_expr_ty(expr, ty);
+ return ty;
}
}
- self.infer_expr(expr, &Expectation::has_type(expected.clone()), ExprIsRead::Yes)
+ self.infer_expr(expr, &Expectation::has_type(expected), ExprIsRead::Yes)
}
fn is_non_ref_pat(&mut self, body: &hir_def::expr_store::Body, pat: PatId) -> bool {
@@ -587,17 +584,17 @@ impl InferenceContext<'_> {
&mut self,
before: &[PatId],
suffix: &[PatId],
- slice: &Option<PatId>,
- ) -> Option<Ty> {
- if !slice.is_none() {
+ slice: Option<PatId>,
+ ) -> Option<Ty<'db>> {
+ if slice.is_some() {
return None;
}
let len = before.len() + suffix.len();
let size = consteval::usize_const(self.db, Some(len as u128), self.owner.krate(self.db));
- let elem_ty = self.table.new_type_var();
- let array_ty = TyKind::Array(elem_ty, size).intern(Interner);
+ let elem_ty = self.table.next_ty_var();
+ let array_ty = Ty::new_array_with_const_len(self.interner(), elem_ty, size);
Some(array_ty)
}