Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/expr.rs')
| -rw-r--r-- | crates/hir-ty/src/infer/expr.rs | 86 |
1 files changed, 48 insertions, 38 deletions
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index e179ca4bd3..a6c8cda404 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -27,7 +27,7 @@ use syntax::ast::RangeOp; use tracing::debug; use crate::{ - Adjust, Adjustment, CallableDefId, Rawness, consteval, + Adjust, Adjustment, CallableDefId, Rawness, Span, consteval, infer::{AllowTwoPhase, BreakableKind, coerce::CoerceMany, find_continuable, pat::PatOrigin}, lower::lower_mutability, method_resolution::{self, CandidateId, MethodCallee, MethodError}, @@ -176,7 +176,7 @@ impl<'db> InferenceContext<'_, 'db> { fn pat_guaranteed_to_constitute_read_for_never(&self, pat: PatId) -> bool { match &self.store[pat] { // Does not constitute a read. - Pat::Wild => false, + Pat::Wild | Pat::Rest => false, // This is unnecessarily restrictive when the pattern that doesn't // constitute a read is unreachable. @@ -343,7 +343,7 @@ impl<'db> InferenceContext<'_, 'db> { coercion_sites[1] = else_branch; } let mut coerce = CoerceMany::with_coercion_sites( - expected.coercion_target_type(&mut self.table), + expected.coercion_target_type(&mut self.table, then_branch.into()), &coercion_sites, ); coerce.coerce(self, &ObligationCause::new(), then_branch, then_ty, ExprIsRead::Yes); @@ -397,7 +397,7 @@ impl<'db> InferenceContext<'_, 'db> { .1 } &Expr::Loop { body, label } => { - let ty = expected.coercion_target_type(&mut self.table); + let ty = expected.coercion_target_type(&mut self.table, tgt_expr.into()); let (breaks, ()) = self.with_breakable_ctx(BreakableKind::Loop, Some(ty), label, |this| { this.infer_expr( @@ -466,7 +466,7 @@ impl<'db> InferenceContext<'_, 'db> { // We don't coerce to `()` so that if the match expression is a // statement it's branches can have any consistent type. Expectation::HasType(ty) if *ty != self.types.types.unit => *ty, - _ => self.table.next_ty_var(), + _ => self.table.next_ty_var((*expr).into()), }; let mut coerce = CoerceMany::new(result_ty); @@ -629,7 +629,7 @@ impl<'db> InferenceContext<'_, 'db> { match rawness { Rawness::RawPtr => Ty::new_ptr(self.interner(), inner_ty, mutability), Rawness::Ref => { - let lt = self.table.next_region_var(); + let lt = self.table.next_region_var(tgt_expr.into()); Ty::new_ref(self.interner(), lt, inner_ty, mutability) } } @@ -675,7 +675,7 @@ impl<'db> InferenceContext<'_, 'db> { // However, rustc lowers destructuring assignments into blocks, and blocks return `!` if they have no tail // expression and they diverge. Therefore, we have to do the same here, even though we don't lower destructuring // assignments into blocks. - self.table.new_maybe_never_var() + self.table.new_maybe_never_var(value.into()) } else { self.types.types.unit } @@ -731,7 +731,7 @@ impl<'db> InferenceContext<'_, 'db> { let idx_t = self.infer_expr_no_expect(*index, ExprIsRead::Yes); let base_t = self.structurally_resolve_type((*base).into(), base_t); - match self.lookup_indexing(tgt_expr, *base, base_t, idx_t) { + match self.lookup_indexing(tgt_expr, *base, *index, base_t, idx_t) { Some((trait_index_ty, trait_element_ty)) => { // two-phase not needed because index_ty is never mutable self.demand_coerce( @@ -755,10 +755,10 @@ impl<'db> InferenceContext<'_, 'db> { { Some(TyKind::Tuple(substs)) => substs .iter() - .chain(repeat_with(|| self.table.next_ty_var())) + .chain(repeat_with(|| self.table.next_ty_var(Span::Dummy))) .take(exprs.len()) .collect::<Vec<_>>(), - _ => (0..exprs.len()).map(|_| self.table.next_ty_var()).collect(), + _ => exprs.iter().map(|&expr| self.table.next_ty_var(expr.into())).collect(), }; for (expr, ty) in exprs.iter().zip(tys.iter_mut()) { @@ -768,7 +768,7 @@ impl<'db> InferenceContext<'_, 'db> { Ty::new_tup(self.interner(), &tys) } - Expr::Array(array) => self.infer_expr_array(array, expected), + Expr::Array(array) => self.infer_expr_array(tgt_expr, array, expected), Expr::Literal(lit) => match lit { Literal::Bool(..) => self.types.types.bool, Literal::String(..) => self.types.types.static_str_ref, @@ -1119,7 +1119,7 @@ impl<'db> InferenceContext<'_, 'db> { if self.features.type_changing_struct_update { if matches!(adt_id, AdtId::StructId(_)) { // Make some fresh generic parameters for our ADT type. - let fresh_args = self.table.fresh_args_for_item(adt_id.into()); + let fresh_args = self.table.fresh_args_for_item(expr.into(), adt_id.into()); // We do subtyping on the FRU fields first, so we can // learn exactly what types we expect the base expr // needs constrained to be compatible with the struct @@ -1266,7 +1266,7 @@ impl<'db> InferenceContext<'_, 'db> { // ...but otherwise we want to use any supertype of the // scrutinee. This is sort of a workaround, see note (*) in // `check_pat` for some details. - let scrut_ty = self.table.next_ty_var(); + let scrut_ty = self.table.next_ty_var(scrut.into()); self.infer_expr_coerce_never(scrut, &Expectation::HasType(scrut_ty), scrutinee_is_read); scrut_ty } @@ -1328,13 +1328,19 @@ impl<'db> InferenceContext<'_, 'db> { } oprnd_t } - fn infer_expr_array(&mut self, array: &Array, expected: &Expectation<'db>) -> Ty<'db> { + + fn infer_expr_array( + &mut self, + expr: ExprId, + array: &Array, + expected: &Expectation<'db>, + ) -> Ty<'db> { let elem_ty = match expected .to_option(&mut self.table) .map(|t| self.table.try_structurally_resolve_type(t).kind()) { Some(TyKind::Array(st, _) | TyKind::Slice(st)) => st, - _ => self.table.next_ty_var(), + _ => self.table.next_ty_var(expr.into()), }; let krate = self.resolver.krate(); @@ -1371,7 +1377,7 @@ impl<'db> InferenceContext<'_, 'db> { let len = match self.store[repeat] { Expr::Underscore => { self.write_expr_ty(repeat, usize); - self.table.next_const_var() + self.table.next_const_var(repeat.into()) } _ => { self.infer_expr(repeat, &Expectation::HasType(usize), ExprIsRead::Yes); @@ -1383,7 +1389,7 @@ impl<'db> InferenceContext<'_, 'db> { } }; // Try to evaluate unevaluated constant, and insert variable if is not possible. - let len = self.table.insert_const_vars_shallow(len); + let len = self.insert_const_vars_shallow(len); Ty::new_array_with_const_len(self.interner(), elem_ty, len) } @@ -1477,7 +1483,7 @@ impl<'db> InferenceContext<'_, 'db> { label: Option<LabelId>, expected: &Expectation<'db>, ) -> Ty<'db> { - let coerce_ty = expected.coercion_target_type(&mut self.table); + let coerce_ty = expected.coercion_target_type(&mut self.table, expr.into()); let g = self.resolver.update_to_inner_scope(self.db, self.owner, expr); let (break_ty, ty) = @@ -1488,7 +1494,7 @@ impl<'db> InferenceContext<'_, 'db> { let decl_ty = type_ref .as_ref() .map(|&tr| this.make_body_ty(tr)) - .unwrap_or_else(|| this.table.next_ty_var()); + .unwrap_or_else(|| this.table.next_ty_var((*pat).into())); let ty = if let Some(expr) = initializer { // If we have a subpattern that performs a read, we want to consider this @@ -1561,7 +1567,7 @@ impl<'db> InferenceContext<'_, 'db> { // `!`). if this.diverges.is_always() { // we don't even make an attempt at coercion - this.table.new_maybe_never_var() + this.table.new_maybe_never_var(expr.into()) } else if let Some(t) = expected.only_has_type(&mut this.table) { if this .coerce( @@ -1728,10 +1734,13 @@ impl<'db> InferenceContext<'_, 'db> { fn instantiate_erroneous_method(&mut self, def_id: FunctionId) -> MethodCallee<'db> { // FIXME: Using fresh infer vars for the method args isn't optimal, // we can do better by going thorough the full probe/confirm machinery. - let args = self.table.fresh_args_for_item(def_id.into()); + let args = self.table.fresh_args_for_item(Span::Dummy, def_id.into()); let sig = self.db.callable_item_signature(def_id.into()).instantiate(self.interner(), args); - let sig = - self.infcx().instantiate_binder_with_fresh_vars(BoundRegionConversionTime::FnCall, sig); + let sig = self.infcx().instantiate_binder_with_fresh_vars( + Span::Dummy, + BoundRegionConversionTime::FnCall, + sig, + ); MethodCallee { def_id, args, sig } } @@ -1810,20 +1819,21 @@ impl<'db> InferenceContext<'_, 'db> { None => None, }; - let assoc_func_with_same_name = self.with_method_resolution(|ctx| { - if !matches!( - receiver_ty.kind(), - TyKind::Infer(InferTy::TyVar(_)) | TyKind::Error(_) - ) { - ctx.probe_for_name( - method_resolution::Mode::Path, - method_name.clone(), - receiver_ty, - ) - } else { - Err(MethodError::ErrorReported) - } - }); + let assoc_func_with_same_name = + self.with_method_resolution(tgt_expr.into(), receiver.into(), |ctx| { + if !matches!( + receiver_ty.kind(), + TyKind::Infer(InferTy::TyVar(_)) | TyKind::Error(_) + ) { + ctx.probe_for_name( + method_resolution::Mode::Path, + method_name.clone(), + receiver_ty, + ) + } else { + Err(MethodError::ErrorReported) + } + }); let assoc_func_with_same_name = match assoc_func_with_same_name { Ok(method_resolution::Pick { item: CandidateId::FunctionId(def_id), .. @@ -1928,7 +1938,7 @@ impl<'db> InferenceContext<'_, 'db> { let formal_input_tys: Vec<_> = formal_input_tys .iter() .map(|&ty| { - let generalized_ty = self.table.next_ty_var(); + let generalized_ty = self.table.next_ty_var(call_expr.into()); let _ = self.demand_eqtype(call_expr.into(), ty, generalized_ty); generalized_ty }) |