diff options
| author | Michael Goulet <michael@errs.io> | 2023-03-03 00:44:22 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2023-04-12 23:20:12 +0000 |
| commit | 5a71029dd3b54046fbd6144de20e320db539820f (patch) | |
| tree | fa711dff5802b38df8cd818d7b00ab49a377542e /compiler | |
| parent | 29aee6a125ac65a01932cb0ece5485e7cf8cfe87 (diff) | |
| download | rust-5a71029dd3b54046fbd6144de20e320db539820f.tar.gz rust-5a71029dd3b54046fbd6144de20e320db539820f.zip | |
Properly note source of arg mismatch
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_hir_typeck/src/demand.rs | 57 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 13 |
2 files changed, 64 insertions, 6 deletions
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index f219068b4e8..9ffee567023 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -62,7 +62,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty); if !suggested { - self.note_source_of_type_mismatch_constraint(err, expr, expected); + self.note_source_of_type_mismatch_constraint( + err, + expr, + TypeMismatchSource::Ty(expected), + ); } } @@ -222,7 +226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut Diagnostic, expr: &hir::Expr<'_>, - expected_ty: Ty<'tcx>, + source: TypeMismatchSource<'tcx>, ) -> bool { let hir = self.tcx.hir(); @@ -295,6 +299,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, }; + let expected_ty = match source { + TypeMismatchSource::Ty(expected_ty) => expected_ty, + TypeMismatchSource::Arg(call_expr, idx) => { + let hir::ExprKind::MethodCall(segment, _, args, _) = call_expr.kind else { + return false; + }; + let Some(arg_ty) = self.node_ty_opt(args[idx].hir_id) else { + return false; + }; + let possible_rcvr_ty = expr_finder.uses.iter().find_map(|binding| { + let possible_rcvr_ty = self.node_ty_opt(binding.hir_id)?; + let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger); + let method = self + .lookup_method( + possible_rcvr_ty, + segment, + DUMMY_SP, + call_expr, + binding, + args, + ) + .ok()?; + let _ = self + .at(&ObligationCause::dummy(), self.param_env) + .eq(DefineOpaqueTypes::No, method.sig.inputs()[idx + 1], arg_ty) + .ok()?; + self.select_obligations_where_possible(|errs| { + // Yeet the errors, we're already reporting errors. + errs.clear(); + }); + Some(self.resolve_vars_if_possible(possible_rcvr_ty)) + }); + if let Some(rcvr_ty) = possible_rcvr_ty { + rcvr_ty + } else { + return false; + } + } + }; + if !self.can_eq(self.param_env, expected_ty, init_ty.fold_with(&mut fudger)) { return false; } @@ -360,7 +404,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "... which constrains `{ident}` to have type `{next_use_ty}`" ), ); - if let Ok(ideal_method_sig) = ideal_method_sig { + if matches!(source, TypeMismatchSource::Ty(_)) + && let Ok(ideal_method_sig) = ideal_method_sig + { self.emit_type_mismatch_suggestions( err, arg_expr, @@ -2044,3 +2090,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } + +pub enum TypeMismatchSource<'tcx> { + Ty(Ty<'tcx>), + Arg(&'tcx hir::Expr<'tcx>, usize), +} diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index d98e0d9096f..9ecb78e2dda 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -472,7 +472,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err_code: &str, fn_def_id: Option<DefId>, call_span: Span, - call_expr: &hir::Expr<'tcx>, + call_expr: &'tcx hir::Expr<'tcx>, ) { // Next, let's construct the error let (error_span, full_call_span, call_name, is_method) = match &call_expr.kind { @@ -808,8 +808,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("arguments to this {} are incorrect", call_name), ); - // TODO: We would like to point out when the rcvr was constrained - // such that the arg mismatch occurs. + if let hir::ExprKind::MethodCall(_, rcvr, _, _) = call_expr.kind + && provided_idx.as_usize() == expected_idx.as_usize() + { + self.note_source_of_type_mismatch_constraint( + &mut err, + rcvr, + crate::demand::TypeMismatchSource::Arg(call_expr, provided_idx.as_usize()), + ); + } // Call out where the function is defined self.label_fn_like( |
