Skip to content

Don't record adjustments twice in note_source_of_type_mismatch_constraint #112537

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
26 changes: 23 additions & 3 deletions compiler/rustc_hir_typeck/src/method/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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> {
Expand All @@ -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(
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
Expand Down
21 changes: 21 additions & 0 deletions compiler/rustc_hir_typeck/src/method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
29 changes: 29 additions & 0 deletions tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.rs
Original file line number Diff line number Diff line change
@@ -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
};
}
Original file line number Diff line number Diff line change
@@ -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`.