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.rs | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs index 3cd7461cf3..ac209adef8 100644 --- a/crates/hir-ty/src/infer/pat.rs +++ b/crates/hir-ty/src/infer/pat.rs @@ -26,7 +26,7 @@ use span::Edition; use tracing::{debug, instrument, trace}; use crate::{ - BindingMode, InferenceDiagnostic, + BindingMode, InferenceDiagnostic, Span, infer::{ AllowTwoPhase, ByRef, Expectation, InferenceContext, PatAdjust, PatAdjustment, TypeMismatch, expr::ExprIsRead, @@ -446,7 +446,8 @@ impl<'a, 'db> InferenceContext<'a, 'db> { pat_info, ) } - Pat::Missing | Pat::Wild => expected, + Pat::Missing => self.types.types.error, + Pat::Wild | Pat::Rest => expected, // We allow any type here; we ensure that the type is uninhabited during match checking. // Pat::Never => expected, Pat::Path(_) => { @@ -658,8 +659,8 @@ impl<'a, 'db> InferenceContext<'a, 'db> { Pat::Ref { .. } // No need to do anything on a missing pattern. | Pat::Missing - // A `_` pattern works with any expected type, so there's no need to do anything. - | Pat::Wild + // A `_`/`..` pattern works with any expected type, so there's no need to do anything. + | Pat::Wild | Pat::Rest // Bindings also work with whatever the expected type is, // and moreover if we peel references off, that will give us the wrong binding type. // Also, we can have a subpattern `binding @ pat`. @@ -928,7 +929,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` // is required. However, we use equality, which is stronger. // See (note_1) for an explanation. - self.new_ref_ty(mutbl, expected) + self.new_ref_ty(pat.into(), mutbl, expected) } // Otherwise, the type of x is the expected type `T`. ByRef::No => expected, // As above, `T <: typeof(x)` is required, but we use equality, see (note_1). @@ -1110,7 +1111,9 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; } let max_len = cmp::max(expected_len, elements.len()); - let element_tys_iter = (0..max_len).map(|_| self.table.next_ty_var()); + let element_tys_iter = (0..max_len).map(|i| { + self.table.next_ty_var(elements.get(i).copied().map(Span::PatId).unwrap_or(Span::Dummy)) + }); let element_tys = Tys::new_from_iter(interner, element_tys_iter); let pat_ty = Ty::new(interner, TyKind::Tuple(element_tys)); if self.demand_eqtype(pat.into(), expected, pat_ty).is_err() { @@ -1249,7 +1252,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; .map(|()| { // Here, `demand::subtype` is good enough, but I don't // think any errors can be introduced by using `demand::eqtype`. - let inner_ty = self.table.next_ty_var(); + let inner_ty = self.table.next_ty_var(inner.into()); let box_ty = Ty::new_box(interner, inner_ty); _ = self.demand_eqtype(pat.into(), expected, box_ty); (box_ty, inner_ty) @@ -1472,8 +1475,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; (expected, r_ty) } _ => { - let inner_ty = self.table.next_ty_var(); - let ref_ty = self.new_ref_ty(pat_mutbl, inner_ty); + let inner_ty = self.table.next_ty_var(inner.into()); + let ref_ty = self.new_ref_ty(inner.into(), pat_mutbl, inner_ty); debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty); _ = self.demand_eqtype(pat.into(), expected, ref_ty); @@ -1492,8 +1495,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; } /// Create a reference or pinned reference type with a fresh region variable. - fn new_ref_ty(&self, mutbl: Mutability, ty: Ty<'db>) -> Ty<'db> { - let region = self.table.next_region_var(); + fn new_ref_ty(&self, span: Span, mutbl: Mutability, ty: Ty<'db>) -> Ty<'db> { + let region = self.table.next_region_var(span); Ty::new_ref(self.interner(), region, ty, mutbl) } @@ -1501,6 +1504,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; &self, before: &[PatId], slice: Option<PatId>, + pat: PatId, ) -> Option<Ty<'db>> { if slice.is_some() { return None; @@ -1508,7 +1512,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; let interner = self.interner(); let len = before.len(); - let inner_ty = self.table.next_ty_var(); + let inner_ty = self.table.next_ty_var(pat.into()); Some(Ty::new_array(interner, inner_ty, len.try_into().unwrap())) } @@ -1576,7 +1580,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; // to an array if the given pattern allows it. See issue #76342 if self.pat_is_irrefutable(pat_info.pat_origin) && expected.is_ty_var() - && let Some(resolved_arr_ty) = self.try_resolve_slice_ty_to_array_ty(before, slice) + && let Some(resolved_arr_ty) = self.try_resolve_slice_ty_to_array_ty(before, slice, pat) { debug!(?resolved_arr_ty); let _ = self.demand_eqtype(pat.into(), expected, resolved_arr_ty); |