Skip to content

Commit 0a798a0

Browse files
authored
Merge pull request #21060 from ChayimFriedman2/adjust-last
fix: Fix some inference of patterns
2 parents 9cee3bc + ddf4636 commit 0a798a0

File tree

7 files changed

+95
-44
lines changed

7 files changed

+95
-44
lines changed

crates/hir-ty/src/infer.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,6 @@ struct InternedStandardTypes<'db> {
759759
re_erased: Region<'db>,
760760

761761
empty_args: GenericArgs<'db>,
762-
empty_tys: Tys<'db>,
763762
}
764763

765764
impl<'db> InternedStandardTypes<'db> {
@@ -795,7 +794,6 @@ impl<'db> InternedStandardTypes<'db> {
795794
re_erased: Region::new_erased(interner),
796795

797796
empty_args: GenericArgs::new_from_iter(interner, []),
798-
empty_tys: Tys::new_from_iter(interner, []),
799797
}
800798
}
801799
}
@@ -1475,15 +1473,30 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
14751473
self.resolve_associated_type_with_params(inner_ty, assoc_ty, &[])
14761474
}
14771475

1478-
fn demand_eqtype(&mut self, expected: Ty<'db>, actual: Ty<'db>) {
1476+
fn demand_eqtype(
1477+
&mut self,
1478+
id: ExprOrPatId,
1479+
expected: Ty<'db>,
1480+
actual: Ty<'db>,
1481+
) -> Result<(), ()> {
1482+
let result = self.demand_eqtype_fixme_no_diag(expected, actual);
1483+
if result.is_err() {
1484+
self.result.type_mismatches.insert(id, TypeMismatch { expected, actual });
1485+
}
1486+
result
1487+
}
1488+
1489+
fn demand_eqtype_fixme_no_diag(
1490+
&mut self,
1491+
expected: Ty<'db>,
1492+
actual: Ty<'db>,
1493+
) -> Result<(), ()> {
14791494
let result = self
14801495
.table
14811496
.at(&ObligationCause::new())
14821497
.eq(expected, actual)
14831498
.map(|infer_ok| self.table.register_infer_ok(infer_ok));
1484-
if let Err(_err) = result {
1485-
// FIXME: Emit diagnostic.
1486-
}
1499+
result.map_err(drop)
14871500
}
14881501

14891502
fn demand_suptype(&mut self, expected: Ty<'db>, actual: Ty<'db>) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ impl<'db> InferenceContext<'_, 'db> {
160160
};
161161
debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
162162

163-
self.demand_eqtype(ty, fallback);
163+
_ = self.demand_eqtype_fixme_no_diag(ty, fallback);
164164
true
165165
}
166166

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
108108
{
109109
let builtin_return_ty =
110110
self.enforce_builtin_binop_types(lhs_ty, rhs_ty, category);
111-
self.demand_eqtype(builtin_return_ty, return_ty);
111+
_ = self.demand_eqtype(expr.into(), builtin_return_ty, return_ty);
112112
builtin_return_ty
113113
} else {
114114
return_ty

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl<'db> InferenceContext<'_, 'db> {
109109

110110
let expected =
111111
EarlyBinder::bind(ty.ty).instantiate(interner, opaque_type_key.args);
112-
self.demand_eqtype(expected, hidden_type.ty);
112+
_ = self.demand_eqtype_fixme_no_diag(expected, hidden_type.ty);
113113
}
114114

115115
self.result.type_of_opaque.insert(def_id, ty.ty);

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

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Type inference for patterns.
22
3-
use std::iter::repeat_with;
3+
use std::{cmp, iter};
44

55
use hir_def::{
66
HasModule,
@@ -19,7 +19,7 @@ use crate::{
1919
AllowTwoPhase, BindingMode, Expectation, InferenceContext, TypeMismatch, expr::ExprIsRead,
2020
},
2121
lower::lower_mutability,
22-
next_solver::{GenericArgs, Ty, TyKind},
22+
next_solver::{GenericArgs, Ty, TyKind, Tys, infer::traits::ObligationCause},
2323
};
2424

2525
impl<'db> InferenceContext<'_, 'db> {
@@ -183,42 +183,61 @@ impl<'db> InferenceContext<'_, 'db> {
183183
/// Ellipses found in the original pattern or expression must be filtered out.
184184
pub(super) fn infer_tuple_pat_like(
185185
&mut self,
186+
pat: PatId,
186187
expected: Ty<'db>,
187188
default_bm: BindingMode,
188189
ellipsis: Option<u32>,
189-
subs: &[PatId],
190+
elements: &[PatId],
190191
decl: Option<DeclContext>,
191192
) -> Ty<'db> {
192-
let expected = self.table.structurally_resolve_type(expected);
193-
let expectations = match expected.kind() {
194-
TyKind::Tuple(parameters) => parameters,
195-
_ => self.types.empty_tys,
196-
};
193+
let mut expected_len = elements.len();
194+
if ellipsis.is_some() {
195+
// Require known type only when `..` is present.
196+
if let TyKind::Tuple(tys) = self.table.structurally_resolve_type(expected).kind() {
197+
expected_len = tys.len();
198+
}
199+
}
200+
let max_len = cmp::max(expected_len, elements.len());
197201

198-
let ((pre, post), n_uncovered_patterns) = match ellipsis {
199-
Some(idx) => {
200-
(subs.split_at(idx as usize), expectations.len().saturating_sub(subs.len()))
202+
let element_tys_iter = (0..max_len).map(|_| self.table.next_ty_var());
203+
let element_tys = Tys::new_from_iter(self.interner(), element_tys_iter);
204+
let pat_ty = Ty::new(self.interner(), TyKind::Tuple(element_tys));
205+
if self.demand_eqtype(pat.into(), expected, pat_ty).is_err()
206+
&& let TyKind::Tuple(expected) = expected.kind()
207+
{
208+
// Equate expected type with the infer vars, for better diagnostics.
209+
for (expected, elem_ty) in iter::zip(expected, element_tys) {
210+
_ = self
211+
.table
212+
.at(&ObligationCause::dummy())
213+
.eq(expected, elem_ty)
214+
.map(|infer_ok| self.table.register_infer_ok(infer_ok));
201215
}
202-
None => ((subs, &[][..]), 0),
216+
}
217+
let (before_ellipsis, after_ellipsis) = match ellipsis {
218+
Some(ellipsis) => {
219+
let element_tys = element_tys.as_slice();
220+
// Don't check patterns twice.
221+
let from_end_start = cmp::max(
222+
element_tys.len().saturating_sub(elements.len() - ellipsis as usize),
223+
ellipsis as usize,
224+
);
225+
(
226+
element_tys.get(..ellipsis as usize).unwrap_or(element_tys),
227+
element_tys.get(from_end_start..).unwrap_or_default(),
228+
)
229+
}
230+
None => (element_tys.as_slice(), &[][..]),
203231
};
204-
let mut expectations_iter =
205-
expectations.iter().chain(repeat_with(|| self.table.next_ty_var()));
206-
207-
let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + subs.len());
208-
209-
inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns + subs.len()));
210-
211-
// Process pre
212-
for (ty, pat) in inner_tys.iter_mut().zip(pre) {
213-
*ty = self.infer_pat(*pat, *ty, default_bm, decl);
232+
for (&elem, &elem_ty) in iter::zip(elements, before_ellipsis.iter().chain(after_ellipsis)) {
233+
self.infer_pat(elem, elem_ty, default_bm, decl);
214234
}
215-
216-
// Process post
217-
for (ty, pat) in inner_tys.iter_mut().skip(pre.len() + n_uncovered_patterns).zip(post) {
218-
*ty = self.infer_pat(*pat, *ty, default_bm, decl);
235+
if let Some(uncovered) = elements.get(element_tys.len()..) {
236+
for &elem in uncovered {
237+
self.infer_pat(elem, self.types.error, default_bm, decl);
238+
}
219239
}
220-
221-
Ty::new_tup_from_iter(self.interner(), inner_tys.into_iter())
240+
pat_ty
222241
}
223242

224243
/// The resolver needs to be updated to the surrounding expression when inside assignment
@@ -272,7 +291,7 @@ impl<'db> InferenceContext<'_, 'db> {
272291

273292
let ty = match &self.body[pat] {
274293
Pat::Tuple { args, ellipsis } => {
275-
self.infer_tuple_pat_like(expected, default_bm, *ellipsis, args, decl)
294+
self.infer_tuple_pat_like(pat, expected, default_bm, *ellipsis, args, decl)
276295
}
277296
Pat::Or(pats) => {
278297
for pat in pats.iter() {
@@ -356,7 +375,7 @@ impl<'db> InferenceContext<'_, 'db> {
356375
GenericArgs::fill_with_defaults(
357376
self.interner(),
358377
box_adt.into(),
359-
std::iter::once(inner_ty.into()).chain(alloc_ty.map(Into::into)),
378+
iter::once(inner_ty.into()).chain(alloc_ty.map(Into::into)),
360379
|_, id, _| self.table.next_var_for_param(id),
361380
),
362381
)
@@ -416,7 +435,7 @@ impl<'db> InferenceContext<'_, 'db> {
416435
.result
417436
.pat_adjustments
418437
.get(&pat)
419-
.and_then(|it| it.first())
438+
.and_then(|it| it.last())
420439
.unwrap_or(&self.result.type_of_pat[pat])
421440
}
422441

@@ -469,9 +488,9 @@ impl<'db> InferenceContext<'_, 'db> {
469488
let bound_ty = match mode {
470489
BindingMode::Ref(mutability) => {
471490
let inner_lt = self.table.next_region_var();
472-
Ty::new_ref(self.interner(), inner_lt, inner_ty, mutability)
491+
Ty::new_ref(self.interner(), inner_lt, expected, mutability)
473492
}
474-
BindingMode::Move => inner_ty,
493+
BindingMode::Move => expected,
475494
};
476495
self.write_pat_ty(pat, inner_ty);
477496
self.write_binding_ty(binding, bound_ty);

crates/hir-ty/src/tests/coercion.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -833,11 +833,11 @@ struct V<T> { t: T }
833833
fn main() {
834834
let a: V<&dyn Tr>;
835835
(a,) = V { t: &S };
836-
//^^^^expected V<&'? S>, got (V<&'? (dyn Tr + 'static)>,)
836+
//^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,)
837837
838838
let mut a: V<&dyn Tr> = V { t: &S };
839839
(a,) = V { t: &S };
840-
//^^^^expected V<&'? S>, got (V<&'? (dyn Tr + 'static)>,)
840+
//^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,)
841841
}
842842
"#,
843843
);

crates/hir-ty/src/tests/patterns.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,3 +1259,22 @@ fn main() {
12591259
"#,
12601260
);
12611261
}
1262+
1263+
#[test]
1264+
fn destructuring_assign_ref() {
1265+
check_no_mismatches(
1266+
r#"
1267+
struct Foo;
1268+
1269+
fn foo() -> (&'static Foo, u32) {
1270+
(&Foo, 0)
1271+
}
1272+
1273+
fn bar() {
1274+
let ext: &Foo;
1275+
let v;
1276+
(ext, v) = foo();
1277+
}
1278+
"#,
1279+
);
1280+
}

0 commit comments

Comments
 (0)