Skip to content

Commit ec273c3

Browse files
committed
Split pattern inference into more functions
1 parent fc2b395 commit ec273c3

File tree

6 files changed

+234
-172
lines changed

6 files changed

+234
-172
lines changed

crates/hir-def/src/resolver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub enum ResolveValueResult {
8585
Partial(TypeNs, usize),
8686
}
8787

88-
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
88+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
8989
pub enum ValueNs {
9090
ImplSelf(ImplId),
9191
LocalBinding(PatId),

crates/hir-ty/src/infer.rs

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -144,44 +144,6 @@ impl Default for BindingMode {
144144
}
145145
}
146146

147-
/// Used to generalize patterns and assignee expressions.
148-
trait PatLike: Into<ExprOrPatId> + Copy {
149-
type BindingMode: Copy;
150-
151-
fn infer(
152-
this: &mut InferenceContext<'_>,
153-
id: Self,
154-
expected_ty: &Ty,
155-
default_bm: Self::BindingMode,
156-
) -> Ty;
157-
}
158-
159-
impl PatLike for ExprId {
160-
type BindingMode = ();
161-
162-
fn infer(
163-
this: &mut InferenceContext<'_>,
164-
id: Self,
165-
expected_ty: &Ty,
166-
_: Self::BindingMode,
167-
) -> Ty {
168-
this.infer_assignee_expr(id, expected_ty)
169-
}
170-
}
171-
172-
impl PatLike for PatId {
173-
type BindingMode = BindingMode;
174-
175-
fn infer(
176-
this: &mut InferenceContext<'_>,
177-
id: Self,
178-
expected_ty: &Ty,
179-
default_bm: Self::BindingMode,
180-
) -> Ty {
181-
this.infer_pat(id, expected_ty, default_bm)
182-
}
183-
}
184-
185147
#[derive(Debug)]
186148
pub(crate) struct InferOk<T> {
187149
value: T,
@@ -581,7 +543,7 @@ impl<'a> InferenceContext<'a> {
581543
let ty = self.insert_type_vars(ty);
582544
let ty = self.normalize_associated_types_in(ty);
583545

584-
self.infer_pat(*pat, &ty, BindingMode::default());
546+
self.infer_top_pat(*pat, &ty);
585547
}
586548
let error_ty = &TypeRef::Error;
587549
let return_ty = if data.has_async_kw() {

crates/hir-ty/src/infer/expr.rs

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ use syntax::ast::RangeOp;
2525
use crate::{
2626
autoderef::{self, Autoderef},
2727
consteval,
28-
infer::{coerce::CoerceMany, find_continuable, BreakableKind},
28+
infer::{
29+
coerce::CoerceMany, find_continuable, pat::contains_explicit_ref_binding, BreakableKind,
30+
},
2931
lower::{
3032
const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, ParamLoweringMode,
3133
},
@@ -39,8 +41,8 @@ use crate::{
3941
};
4042

4143
use super::{
42-
coerce::auto_deref_adjust_steps, find_breakable, BindingMode, BreakableContext, Diverges,
43-
Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch,
44+
coerce::auto_deref_adjust_steps, find_breakable, BreakableContext, Diverges, Expectation,
45+
InferenceContext, InferenceDiagnostic, TypeMismatch,
4446
};
4547

4648
impl<'a> InferenceContext<'a> {
@@ -111,7 +113,7 @@ impl<'a> InferenceContext<'a> {
111113
}
112114
&Expr::Let { pat, expr } => {
113115
let input_ty = self.infer_expr(expr, &Expectation::none());
114-
self.infer_pat(pat, &input_ty, BindingMode::default());
116+
self.infer_top_pat(pat, &input_ty);
115117
self.result.standard_types.bool_.clone()
116118
}
117119
Expr::Block { statements, tail, label, id: _ } => {
@@ -223,7 +225,7 @@ impl<'a> InferenceContext<'a> {
223225
let pat_ty =
224226
self.resolve_associated_type(into_iter_ty, self.resolve_iterator_item());
225227

226-
self.infer_pat(pat, &pat_ty, BindingMode::default());
228+
self.infer_top_pat(pat, &pat_ty);
227229
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
228230
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
229231
});
@@ -298,7 +300,7 @@ impl<'a> InferenceContext<'a> {
298300

299301
// Now go through the argument patterns
300302
for (arg_pat, arg_ty) in args.iter().zip(sig_tys) {
301-
self.infer_pat(*arg_pat, &arg_ty, BindingMode::default());
303+
self.infer_top_pat(*arg_pat, &arg_ty);
302304
}
303305

304306
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
@@ -395,7 +397,8 @@ impl<'a> InferenceContext<'a> {
395397

396398
for arm in arms.iter() {
397399
self.diverges = Diverges::Maybe;
398-
let _pat_ty = self.infer_pat(arm.pat, &input_ty, BindingMode::default());
400+
let input_ty = self.resolve_ty_shallow(&input_ty);
401+
let _pat_ty = self.infer_top_pat(arm.pat, &input_ty);
399402
if let Some(guard_expr) = arm.guard {
400403
self.infer_expr(
401404
guard_expr,
@@ -1142,27 +1145,33 @@ impl<'a> InferenceContext<'a> {
11421145
let decl_ty = type_ref
11431146
.as_ref()
11441147
.map(|tr| self.make_ty(tr))
1145-
.unwrap_or_else(|| self.err_ty());
1146-
1147-
// Always use the declared type when specified
1148-
let mut ty = decl_ty.clone();
1148+
.unwrap_or_else(|| self.table.new_type_var());
11491149

1150-
if let Some(expr) = initializer {
1151-
let actual_ty =
1152-
self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty.clone()));
1153-
if decl_ty.is_unknown() {
1154-
ty = actual_ty;
1150+
let ty = if let Some(expr) = initializer {
1151+
let ty = if contains_explicit_ref_binding(&self.body, *pat) {
1152+
self.infer_expr(*expr, &Expectation::has_type(decl_ty.clone()))
1153+
} else {
1154+
self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty.clone()))
1155+
};
1156+
if type_ref.is_some() {
1157+
decl_ty
1158+
} else {
1159+
ty
11551160
}
1156-
}
1161+
} else {
1162+
decl_ty
1163+
};
1164+
1165+
self.infer_top_pat(*pat, &ty);
11571166

11581167
if let Some(expr) = else_branch {
1168+
let previous_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
11591169
self.infer_expr_coerce(
11601170
*expr,
11611171
&Expectation::HasType(self.result.standard_types.never.clone()),
11621172
);
1173+
self.diverges = previous_diverges;
11631174
}
1164-
1165-
self.infer_pat(*pat, &ty, BindingMode::default());
11661175
}
11671176
Statement::Expr { expr, .. } => {
11681177
self.infer_expr(*expr, &Expectation::none());

0 commit comments

Comments
 (0)