Skip to content

Commit c229a83

Browse files
committed
Auto merge of #14222 - Veykril:pat-mismatch-diags, r=Veykril
Show pattern mismatch diagnostics
2 parents 3b857e1 + 522823f commit c229a83

File tree

12 files changed

+354
-242
lines changed

12 files changed

+354
-242
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-expand/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,15 @@ impl<T> InFile<Option<T>> {
771771
}
772772
}
773773

774+
impl<L, R> InFile<Either<L, R>> {
775+
pub fn transpose(self) -> Either<InFile<L>, InFile<R>> {
776+
match self.value {
777+
Either::Left(l) => Either::Left(InFile::new(self.file_id, l)),
778+
Either::Right(r) => Either::Right(InFile::new(self.file_id, r)),
779+
}
780+
}
781+
}
782+
774783
impl<'a> InFile<&'a SyntaxNode> {
775784
pub fn ancestors_with_macros(
776785
self,

crates/hir-ty/src/infer.rs

Lines changed: 4 additions & 45 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,
@@ -389,18 +351,15 @@ impl InferenceResult {
389351
pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch> {
390352
self.type_mismatches.get(&pat.into())
391353
}
354+
pub fn type_mismatches(&self) -> impl Iterator<Item = (ExprOrPatId, &TypeMismatch)> {
355+
self.type_mismatches.iter().map(|(expr_or_pat, mismatch)| (*expr_or_pat, mismatch))
356+
}
392357
pub fn expr_type_mismatches(&self) -> impl Iterator<Item = (ExprId, &TypeMismatch)> {
393358
self.type_mismatches.iter().filter_map(|(expr_or_pat, mismatch)| match *expr_or_pat {
394359
ExprOrPatId::ExprId(expr) => Some((expr, mismatch)),
395360
_ => None,
396361
})
397362
}
398-
pub fn pat_type_mismatches(&self) -> impl Iterator<Item = (PatId, &TypeMismatch)> {
399-
self.type_mismatches.iter().filter_map(|(expr_or_pat, mismatch)| match *expr_or_pat {
400-
ExprOrPatId::PatId(pat) => Some((pat, mismatch)),
401-
_ => None,
402-
})
403-
}
404363
}
405364

406365
impl Index<ExprId> for InferenceResult {
@@ -584,7 +543,7 @@ impl<'a> InferenceContext<'a> {
584543
let ty = self.insert_type_vars(ty);
585544
let ty = self.normalize_associated_types_in(ty);
586545

587-
self.infer_pat(*pat, &ty, BindingMode::default());
546+
self.infer_top_pat(*pat, &ty);
588547
}
589548
let error_ty = &TypeRef::Error;
590549
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+
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)