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 | 88 |
1 files changed, 51 insertions, 37 deletions
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index c59c919c51..a03e891114 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -327,7 +327,7 @@ impl<'db> InferenceContext<'_, 'db> { let ty = match expr { Expr::Missing => self.err_ty(), &Expr::If { condition, then_branch, else_branch } => { - let expected = &expected.adjust_for_branches(&mut self.table); + let expected = &expected.adjust_for_branches(&mut self.table, tgt_expr.into()); self.infer_expr_coerce_never( condition, &Expectation::HasType(self.types.types.bool), @@ -346,14 +346,20 @@ impl<'db> InferenceContext<'_, 'db> { expected.coercion_target_type(&mut self.table, then_branch.into()), &coercion_sites, ); - coerce.coerce(self, &ObligationCause::new(), then_branch, then_ty, ExprIsRead::Yes); + coerce.coerce( + self, + &ObligationCause::new(then_branch), + then_branch, + then_ty, + ExprIsRead::Yes, + ); match else_branch { Some(else_branch) => { let else_ty = self.infer_expr_inner(else_branch, expected, ExprIsRead::Yes); let else_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); coerce.coerce( self, - &ObligationCause::new(), + &ObligationCause::new(else_branch), else_branch, else_ty, ExprIsRead::Yes, @@ -364,7 +370,7 @@ impl<'db> InferenceContext<'_, 'db> { coerce.coerce_forced_unit( self, tgt_expr, - &ObligationCause::new(), + &ObligationCause::new(tgt_expr), true, ExprIsRead::Yes, ); @@ -461,7 +467,7 @@ impl<'db> InferenceContext<'_, 'db> { self.infer_top_pat(arm.pat, input_ty, PatOrigin::MatchArm); } - let expected = expected.adjust_for_branches(&mut self.table); + let expected = expected.adjust_for_branches(&mut self.table, tgt_expr.into()); let result_ty = match &expected { // We don't coerce to `()` so that if the match expression is a // statement it's branches can have any consistent type. @@ -485,7 +491,7 @@ impl<'db> InferenceContext<'_, 'db> { all_arms_diverge &= self.diverges; coerce.coerce( self, - &ObligationCause::new(), + &ObligationCause::new(arm.expr), arm.expr, arm_ty, ExprIsRead::Yes, @@ -536,10 +542,11 @@ impl<'db> InferenceContext<'_, 'db> { match find_breakable(&mut self.breakables, label) { Some(ctxt) => match ctxt.coerce.take() { Some(mut coerce) => { + let expr = expr.unwrap_or(tgt_expr); coerce.coerce( self, - &ObligationCause::new(), - expr.unwrap_or(tgt_expr), + &ObligationCause::new(expr), + expr, val_ty, ExprIsRead::Yes, ); @@ -598,7 +605,7 @@ impl<'db> InferenceContext<'_, 'db> { self.infer_record_expr(tgt_expr, expected, path, fields, *spread) } Expr::Field { expr, name } => self.infer_field_access(tgt_expr, *expr, name, expected), - Expr::Await { expr } => self.infer_await_expr(*expr), + Expr::Await { expr } => self.infer_await_expr(tgt_expr, *expr), Expr::Cast { expr, type_ref } => { let cast_ty = self.make_body_ty(*type_ref); let expr_ty = @@ -751,7 +758,7 @@ impl<'db> InferenceContext<'_, 'db> { Expr::Tuple { exprs, .. } => { let mut tys = match expected .only_has_type(&mut self.table) - .map(|t| self.table.try_structurally_resolve_type(t).kind()) + .map(|t| self.table.try_structurally_resolve_type(tgt_expr.into(), t).kind()) { Some(TyKind::Tuple(substs)) => substs .iter() @@ -964,14 +971,14 @@ impl<'db> InferenceContext<'_, 'db> { ty } - fn infer_await_expr(&mut self, awaitee: ExprId) -> Ty<'db> { + fn infer_await_expr(&mut self, expr: ExprId, awaitee: ExprId) -> Ty<'db> { let awaitee_ty = self.infer_expr_no_expect(awaitee, ExprIsRead::Yes); let (Some(into_future), Some(into_future_output)) = (self.lang_items.IntoFuture, self.lang_items.IntoFutureOutput) else { return self.types.types.error; }; - self.table.register_bound(awaitee_ty, into_future, ObligationCause::new()); + self.table.register_bound(awaitee_ty, into_future, ObligationCause::new(expr)); // Do not eagerly normalize. Ty::new_projection(self.interner(), into_future_output.into(), [awaitee_ty]) } @@ -1002,7 +1009,7 @@ impl<'db> InferenceContext<'_, 'db> { self.check_record_expr_fields(adt_ty, expected, expr, variant, fields, base_expr); - self.require_type_is_sized(adt_ty); + self.require_type_is_sized(adt_ty, expr.into()); adt_ty } @@ -1017,12 +1024,12 @@ impl<'db> InferenceContext<'_, 'db> { ) { let interner = self.interner(); - let adt_ty = self.table.try_structurally_resolve_type(adt_ty); + let adt_ty = self.table.try_structurally_resolve_type(expr.into(), adt_ty); let adt_ty_hint = expected.only_has_type(&mut self.table).and_then(|expected| { self.infcx() .fudge_inference_if_ok(|| { let mut ocx = ObligationCtxt::new(self.infcx()); - ocx.sup(&ObligationCause::new(), self.table.param_env, expected, adt_ty)?; + ocx.sup(&ObligationCause::new(expr), self.table.param_env, expected, adt_ty)?; if !ocx.try_evaluate_obligations().is_empty() { return Err(TypeError::Mismatch); } @@ -1084,7 +1091,7 @@ impl<'db> InferenceContext<'_, 'db> { // Check that the expected field type is WF. Otherwise, we emit no use-site error // in the case of coercions for non-WF fields, which leads to incorrect error // tainting. See issue #126272. - self.table.register_wf_obligation(field_type.into(), ObligationCause::new()); + self.table.register_wf_obligation(field_type.into(), ObligationCause::new(field.expr)); // Make sure to give a type to the field even if there's // an error, so we can continue type-checking. @@ -1131,7 +1138,7 @@ impl<'db> InferenceContext<'_, 'db> { if remaining_fields.remove(&field.name).is_some() { let target_ty = variant_field_tys[field_idx].get().instantiate(interner, args); - let cause = ObligationCause::new(); + let cause = ObligationCause::new(expr); match self.table.at(&cause).sup(target_ty, fru_ty) { Ok(InferOk { obligations, value: () }) => { self.table.register_predicates(obligations) @@ -1337,7 +1344,7 @@ impl<'db> InferenceContext<'_, 'db> { ) -> Ty<'db> { let elem_ty = match expected .to_option(&mut self.table) - .map(|t| self.table.try_structurally_resolve_type(t).kind()) + .map(|t| self.table.try_structurally_resolve_type(expr.into(), t).kind()) { Some(TyKind::Array(st, _) | TyKind::Slice(st)) => st, _ => self.table.next_ty_var(expr.into()), @@ -1356,7 +1363,7 @@ impl<'db> InferenceContext<'_, 'db> { let cur_elem_ty = self.infer_expr_inner(expr, &expected, ExprIsRead::Yes); coerce.coerce( self, - &ObligationCause::new(), + &ObligationCause::new(expr), expr, cur_elem_ty, ExprIsRead::Yes, @@ -1402,7 +1409,13 @@ impl<'db> InferenceContext<'_, 'db> { let return_expr_ty = self.infer_expr_inner(expr, &Expectation::HasType(ret_ty), ExprIsRead::Yes); let mut coerce_many = self.return_coercion.take().unwrap(); - coerce_many.coerce(self, &ObligationCause::new(), expr, return_expr_ty, ExprIsRead::Yes); + coerce_many.coerce( + self, + &ObligationCause::new(expr), + expr, + return_expr_ty, + ExprIsRead::Yes, + ); self.return_coercion = Some(coerce_many); } @@ -1416,7 +1429,7 @@ impl<'db> InferenceContext<'_, 'db> { coerce.coerce_forced_unit( self, ret, - &ObligationCause::new(), + &ObligationCause::new(ret), true, ExprIsRead::Yes, ); @@ -1600,11 +1613,12 @@ impl<'db> InferenceContext<'_, 'db> { fn lookup_field( &mut self, + field_expr: ExprId, receiver_ty: Ty<'db>, name: &Name, ) -> Option<(Ty<'db>, Either<FieldId, TupleFieldId>, Vec<Adjustment>, bool)> { let interner = self.interner(); - let mut autoderef = self.table.autoderef_with_tracking(receiver_ty); + let mut autoderef = self.table.autoderef_with_tracking(receiver_ty, field_expr.into()); let mut private_field = None; let res = autoderef.by_ref().find_map(|(derefed_ty, _)| { let (field_id, parameters) = match derefed_ty.kind() { @@ -1692,7 +1706,7 @@ impl<'db> InferenceContext<'_, 'db> { return self.err_ty(); } - match self.lookup_field(receiver_ty, name) { + match self.lookup_field(tgt_expr, receiver_ty, name) { Some((ty, field_id, adjustments, is_public)) => { self.write_expr_adj(receiver, adjustments.into_boxed_slice()); self.result.field_resolutions.insert(tgt_expr, field_id); @@ -1761,7 +1775,7 @@ impl<'db> InferenceContext<'_, 'db> { CallableDefId::StructId(it) => it.into(), CallableDefId::EnumVariantId(it) => it.loc(self.db).parent.into(), }; - self.add_required_obligations_for_value_path(def_id, args); + self.add_required_obligations_for_value_path(tgt_expr.into(), def_id, args); } self.check_call_arguments( @@ -1787,7 +1801,7 @@ impl<'db> InferenceContext<'_, 'db> { expected: &Expectation<'db>, ) -> Ty<'db> { let receiver_ty = self.infer_expr_inner(receiver, &Expectation::none(), ExprIsRead::Yes); - let receiver_ty = self.table.try_structurally_resolve_type(receiver_ty); + let receiver_ty = self.table.try_structurally_resolve_type(receiver.into(), receiver_ty); let resolved = self.lookup_method_including_private( receiver_ty, @@ -1809,15 +1823,15 @@ impl<'db> InferenceContext<'_, 'db> { // Failed to resolve, report diagnostic and try to resolve as call to field access or // assoc function Err(_) => { - let field_with_same_name_exists = match self.lookup_field(receiver_ty, method_name) - { - Some((ty, field_id, adjustments, _public)) => { - self.write_expr_adj(receiver, adjustments.into_boxed_slice()); - self.result.field_resolutions.insert(tgt_expr, field_id); - Some(ty) - } - None => None, - }; + let field_with_same_name_exists = + match self.lookup_field(tgt_expr, receiver_ty, method_name) { + Some((ty, field_id, adjustments, _public)) => { + self.write_expr_adj(receiver, adjustments.into_boxed_slice()); + self.result.field_resolutions.insert(tgt_expr, field_id); + Some(ty) + } + None => None, + }; let assoc_func_with_same_name = self.with_method_resolution(tgt_expr.into(), receiver.into(), |ctx| { @@ -1961,13 +1975,13 @@ impl<'db> InferenceContext<'_, 'db> { // return type (likely containing type variables if the function // is polymorphic) and the expected return type. // No argument expectations are produced if unification fails. - let origin = ObligationCause::new(); + let origin = ObligationCause::new(call_expr); ocx.sup(&origin, self.table.param_env, expected_output, formal_output)?; for &ty in &formal_input_tys { ocx.register_obligation(Obligation::new( self.interner(), - ObligationCause::new(), + ObligationCause::new(call_expr), self.table.param_env, ClauseKind::WellFormed(ty.into()), )); @@ -2088,7 +2102,7 @@ impl<'db> InferenceContext<'_, 'db> { let formal_ty_error = this .table .infer_ctxt - .at(&ObligationCause::new(), this.table.param_env) + .at(&ObligationCause::new(provided_arg), this.table.param_env) .eq(formal_input_ty, coerced_ty); // If neither check failed, the types are compatible |