about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs26
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs21
-rw-r--r--tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.rs29
-rw-r--r--tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr17
5 files changed, 93 insertions, 7 deletions
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index b62f689ec6b..9ce03060e0f 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -370,13 +370,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // Fudge the receiver, so we can do new inference on it.
                     let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger);
                     let method = self
-                        .lookup_method(
+                        .lookup_method_for_diagnostic(
                             possible_rcvr_ty,
                             segment,
                             DUMMY_SP,
                             call_expr,
                             binding,
-                            args,
                         )
                         .ok()?;
                     // Unify the method signature with our incompatible arg, to
@@ -435,14 +434,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let Some(rcvr_ty) = self.node_ty_opt(rcvr.hir_id) else { continue; };
                 let rcvr_ty = rcvr_ty.fold_with(&mut fudger);
                 let Ok(method) =
-                    self.lookup_method(rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr, args)
+                    self.lookup_method_for_diagnostic(rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr)
                 else {
                     continue;
                 };
 
                 let ideal_rcvr_ty = rcvr_ty.fold_with(&mut fudger);
                 let ideal_method = self
-                    .lookup_method(ideal_rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr, args)
+                    .lookup_method_for_diagnostic(ideal_rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr)
                     .ok()
                     .and_then(|method| {
                         let _ = self.at(&ObligationCause::dummy(), self.param_env)
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 98529b66602..6cd7bd5d196 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -26,6 +26,7 @@ struct ConfirmContext<'a, 'tcx> {
     span: Span,
     self_expr: &'tcx hir::Expr<'tcx>,
     call_expr: &'tcx hir::Expr<'tcx>,
+    skip_record_for_diagnostics: bool,
 }
 
 impl<'a, 'tcx> Deref for ConfirmContext<'a, 'tcx> {
@@ -59,6 +60,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr);
         confirm_cx.confirm(unadjusted_self_ty, pick, segment)
     }
+
+    pub fn confirm_method_for_diagnostic(
+        &self,
+        span: Span,
+        self_expr: &'tcx hir::Expr<'tcx>,
+        call_expr: &'tcx hir::Expr<'tcx>,
+        unadjusted_self_ty: Ty<'tcx>,
+        pick: &probe::Pick<'tcx>,
+        segment: &hir::PathSegment<'_>,
+    ) -> ConfirmResult<'tcx> {
+        let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr);
+        confirm_cx.skip_record_for_diagnostics = true;
+        confirm_cx.confirm(unadjusted_self_ty, pick, segment)
+    }
 }
 
 impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
@@ -68,7 +83,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         self_expr: &'tcx hir::Expr<'tcx>,
         call_expr: &'tcx hir::Expr<'tcx>,
     ) -> ConfirmContext<'a, 'tcx> {
-        ConfirmContext { fcx, span, self_expr, call_expr }
+        ConfirmContext { fcx, span, self_expr, call_expr, skip_record_for_diagnostics: false }
     }
 
     fn confirm(
@@ -219,7 +234,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         self.register_predicates(autoderef.into_obligations());
 
         // Write out the final adjustments.
-        self.apply_adjustments(self.self_expr, adjustments);
+        if !self.skip_record_for_diagnostics {
+            self.apply_adjustments(self.self_expr, adjustments);
+        }
 
         target
     }
@@ -453,7 +470,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             });
 
             debug!("instantiate_method_substs: user_type_annotation={:?}", user_type_annotation);
-            self.fcx.write_user_type_annotation(self.call_expr.hir_id, user_type_annotation);
+
+            if !self.skip_record_for_diagnostics {
+                self.fcx.write_user_type_annotation(self.call_expr.hir_id, user_type_annotation);
+            }
         }
 
         self.normalize(self.span, substs)
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 6f4d674ba10..dabade36589 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -254,6 +254,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         Ok(result.callee)
     }
 
+    pub fn lookup_method_for_diagnostic(
+        &self,
+        self_ty: Ty<'tcx>,
+        segment: &hir::PathSegment<'_>,
+        span: Span,
+        call_expr: &'tcx hir::Expr<'tcx>,
+        self_expr: &'tcx hir::Expr<'tcx>,
+    ) -> Result<MethodCallee<'tcx>, MethodError<'tcx>> {
+        let pick = self.lookup_probe_for_diagnostic(
+            segment.ident,
+            self_ty,
+            call_expr,
+            ProbeScope::TraitsInScope,
+            None,
+        )?;
+
+        Ok(self
+            .confirm_method_for_diagnostic(span, self_expr, call_expr, self_ty, &pick, segment)
+            .callee)
+    }
+
     #[instrument(level = "debug", skip(self, call_expr))]
     pub fn lookup_probe(
         &self,
diff --git a/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.rs b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.rs
new file mode 100644
index 00000000000..0c2d71707c9
--- /dev/null
+++ b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.rs
@@ -0,0 +1,29 @@
+pub trait NSWindow: Sized {
+    fn frame(self) -> () {
+        unimplemented!()
+    }
+    fn setFrame_display_(self, display: ()) {}
+}
+impl NSWindow for () {}
+
+pub struct NSRect {}
+
+use std::ops::Deref;
+struct MainThreadSafe<T = ()>(T);
+impl<T> Deref for MainThreadSafe<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unimplemented!()
+    }
+}
+
+fn main() {
+    || {
+        let ns_window = MainThreadSafe(());
+        // Don't record adjustments twice for `*ns_window`
+        (*ns_window).frame();
+        ns_window.setFrame_display_(0);
+        //~^ ERROR mismatched types
+    };
+}
diff --git a/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr
new file mode 100644
index 00000000000..02e87d701b6
--- /dev/null
+++ b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/dont-record-adjustments-when-pointing-at-arg.rs:26:37
+   |
+LL |         ns_window.setFrame_display_(0);
+   |                   ----------------- ^ expected `()`, found integer
+   |                   |
+   |                   arguments to this method are incorrect
+   |
+note: method defined here
+  --> $DIR/dont-record-adjustments-when-pointing-at-arg.rs:5:8
+   |
+LL |     fn setFrame_display_(self, display: ()) {}
+   |        ^^^^^^^^^^^^^^^^^       -----------
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.