Skip to content

Commit

Permalink
Rollup merge of #112537 - compiler-errors:dont-record-adjustments-twi…
Browse files Browse the repository at this point in the history
…ce, r=cjgillot

Don't record adjustments twice in `note_source_of_type_mismatch_constraint`

We call `lookup_method` a few times in `note_source_of_type_mismatch_constraint`, but that function has side-effects to the typeck results. Replace it with a less side-effect-y variant of the function for use in diagnostics.

Specifically the ICE in #112532 happens because we're recording deref adjustments twice for a call receiver, which causes `ExprUseVisitor` to be angry.

Fixes #112532
  • Loading branch information
compiler-errors committed Jun 18, 2023
2 parents 9397862 + 696cd98 commit 90e51f1
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 7 deletions.
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`.

0 comments on commit 90e51f1

Please sign in to comment.