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 | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs index a7b82dad4f..97165b9f07 100644 --- a/crates/hir-ty/src/infer/pat.rs +++ b/crates/hir-ty/src/infer/pat.rs @@ -309,7 +309,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { Pat::TupleStruct { path, .. } => Some(self.resolve_tuple_struct_pat(pat_id, path)), _ => None, }; - let adjust_mode = self.calc_adjust_mode(pat, opt_path_res); + let adjust_mode = self.calc_adjust_mode(pat_id, pat, opt_path_res); let ty = self.infer_pat_inner(pat_id, opt_path_res, adjust_mode, expected, pat_info); let ty = self.insert_type_vars_shallow(ty); self.write_pat_ty(pat_id, ty); @@ -321,6 +321,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { { let infer_ok = self.register_deref_mut_bounds_if_needed( pat_id, + pat_id, derefed_tys.iter().filter_map(|adjust| match adjust.kind { PatAdjust::OverloadedDeref => Some(adjust.source.as_ref()), PatAdjust::BuiltinDeref => None, @@ -393,7 +394,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { let expected = if let AdjustMode::Peel { .. } = adjust_mode && pat_info.pat_origin.default_binding_modes() { - self.table.try_structurally_resolve_type(expected) + self.table.try_structurally_resolve_type(pat.into(), expected) } else { expected }; @@ -432,7 +433,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { // The scrutinee is a smart pointer; implicitly dereference it. This adds a // requirement that `expected: DerefPure`. - let inner_ty = self.deref_pat_target(expected); + let inner_ty = self.deref_pat_target(pat, expected); // Once we've checked `pat`, we'll add a `DerefMut` bound if it contains any // `ref mut` bindings. See `Self::register_deref_mut_bounds_if_needed`. @@ -604,6 +605,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { /// When the pattern contains a path, `opt_path_res` must be `Some(path_res)`. fn calc_adjust_mode( &mut self, + pat_id: PatId, pat: &Pat, opt_path_res: Option<Result<ResolvedPat<'db>, ()>>, ) -> AdjustMode { @@ -640,7 +642,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { let mut peeled_ty = lit_ty; let mut pat_ref_layers = 0; while let TyKind::Ref(_, inner_ty, mutbl) = - self.table.try_structurally_resolve_type(peeled_ty).kind() + self.table.try_structurally_resolve_type(pat_id.into(), peeled_ty).kind() { // We rely on references at the head of constants being immutable. debug_assert!(mutbl.is_not()); @@ -763,7 +765,10 @@ impl<'a, 'db> InferenceContext<'a, 'db> { match expected.kind() { // Allow `b"...": &[u8]` TyKind::Ref(_, inner_ty, _) - if self.table.try_structurally_resolve_type(inner_ty).is_slice() => + if self + .table + .try_structurally_resolve_type(expr.into(), inner_ty) + .is_slice() => { trace!(?expr, "polymorphic byte string lit"); pat_ty = self.types.types.static_u8_slice; @@ -788,7 +793,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { // string literal patterns to have type `str`. This is accounted for when lowering to MIR. if self.features.deref_patterns && matches!(literal, Literal::String(_)) - && self.table.try_structurally_resolve_type(expected).is_str() + && self.table.try_structurally_resolve_type(expr.into(), expected).is_str() { pat_ty = self.types.types.str; } @@ -825,7 +830,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { // be peeled to `str` while ty here is still `&str`, if we don't // err early here, a rather confusing unification error will be // emitted instead). - let ty = self.table.try_structurally_resolve_type(ty); + let ty = self.table.try_structurally_resolve_type(expr.into(), ty); let fail = !(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error()); Some((fail, ty, expr)) @@ -1118,7 +1123,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; let pat_ty = Ty::new(interner, TyKind::Tuple(element_tys)); if self.demand_eqtype(pat.into(), expected, pat_ty).is_err() { let expected = if let TyKind::Tuple(tys) = - self.table.try_structurally_resolve_type(expected).kind() + self.table.try_structurally_resolve_type(Span::Dummy, expected).kind() { for (expected_var, found) in iter::zip(element_tys, tys) { // Constrain the infer var so that the type mismatch error message, which contains it, @@ -1265,15 +1270,21 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; box_ty } - fn _infer_deref_pat(&mut self, inner: PatId, expected: Ty<'db>, pat_info: PatInfo) -> Ty<'db> { - let target_ty = self.deref_pat_target(expected); + fn _infer_deref_pat( + &mut self, + pat: PatId, + inner: PatId, + expected: Ty<'db>, + pat_info: PatInfo, + ) -> Ty<'db> { + let target_ty = self.deref_pat_target(pat, expected); self.infer_pat(inner, target_ty, pat_info); - let infer_ok = self.register_deref_mut_bounds_if_needed(inner, [expected]); + let infer_ok = self.register_deref_mut_bounds_if_needed(pat, inner, [expected]); self.table.register_infer_ok(infer_ok); expected } - fn deref_pat_target(&mut self, source_ty: Ty<'db>) -> Ty<'db> { + fn deref_pat_target(&mut self, pat: PatId, source_ty: Ty<'db>) -> Ty<'db> { let (Some(deref_pure), Some(deref_target)) = (self.lang_items.DerefPure, self.lang_items.DerefTarget) else { @@ -1281,10 +1292,10 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; }; // Register a `DerefPure` bound, which is required by all `deref!()` pats. let interner = self.interner(); - self.table.register_bound(source_ty, deref_pure, ObligationCause::new()); + self.table.register_bound(source_ty, deref_pure, ObligationCause::new(pat)); // The expected type for the deref pat's inner pattern is `<expected as Deref>::Target`. let target_ty = Ty::new_projection(interner, deref_target.into(), [source_ty]); - self.table.try_structurally_resolve_type(target_ty) + self.table.try_structurally_resolve_type(pat.into(), target_ty) } /// Check if the interior of a deref pattern (either explicit or implicit) has any `ref mut` @@ -1293,6 +1304,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; /// account for `ref mut` binding modes inherited from implicitly dereferencing `&mut` refs. fn register_deref_mut_bounds_if_needed( &self, + pat: PatId, inner: PatId, derefed_tys: impl IntoIterator<Item = Ty<'db>>, ) -> InferOk<'db, ()> { @@ -1303,7 +1315,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; for mutably_derefed_ty in derefed_tys { infer_ok.obligations.push(Obligation::new( interner, - ObligationCause::new(), + ObligationCause::new(pat), self.table.param_env, TraitRef::new(interner, deref_mut.into(), [mutably_derefed_ty]), )); @@ -1350,7 +1362,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(); } - expected = self.table.try_structurally_resolve_type(expected); + expected = self.table.try_structurally_resolve_type(pat.into(), expected); // Determine whether we're consuming an inherited reference and resetting the default // binding mode, based on edition and enabled experimental features. if let ByRef::Yes(inh_mut) = pat_info.binding_mode { @@ -1574,7 +1586,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"; expected: Ty<'db>, pat_info: PatInfo, ) -> Ty<'db> { - let expected = self.table.try_structurally_resolve_type(expected); + let expected = self.table.try_structurally_resolve_type(pat.into(), expected); // If the pattern is irrefutable and `expected` is an infer ty, we try to equate it // to an array if the given pattern allows it. See issue #76342 |