Skip to content

Commit 90e51f1

Browse files
Rollup merge of rust-lang#112537 - compiler-errors:dont-record-adjustments-twice, 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 rust-lang#112532 happens because we're recording deref adjustments twice for a call receiver, which causes `ExprUseVisitor` to be angry. Fixes rust-lang#112532
2 parents 9397862 + 696cd98 commit 90e51f1

File tree

5 files changed

+93
-7
lines changed

5 files changed

+93
-7
lines changed

compiler/rustc_hir_typeck/src/demand.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -370,13 +370,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
370370
// Fudge the receiver, so we can do new inference on it.
371371
let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger);
372372
let method = self
373-
.lookup_method(
373+
.lookup_method_for_diagnostic(
374374
possible_rcvr_ty,
375375
segment,
376376
DUMMY_SP,
377377
call_expr,
378378
binding,
379-
args,
380379
)
381380
.ok()?;
382381
// Unify the method signature with our incompatible arg, to
@@ -435,14 +434,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
435434
let Some(rcvr_ty) = self.node_ty_opt(rcvr.hir_id) else { continue; };
436435
let rcvr_ty = rcvr_ty.fold_with(&mut fudger);
437436
let Ok(method) =
438-
self.lookup_method(rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr, args)
437+
self.lookup_method_for_diagnostic(rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr)
439438
else {
440439
continue;
441440
};
442441

443442
let ideal_rcvr_ty = rcvr_ty.fold_with(&mut fudger);
444443
let ideal_method = self
445-
.lookup_method(ideal_rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr, args)
444+
.lookup_method_for_diagnostic(ideal_rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr)
446445
.ok()
447446
.and_then(|method| {
448447
let _ = self.at(&ObligationCause::dummy(), self.param_env)

compiler/rustc_hir_typeck/src/method/confirm.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct ConfirmContext<'a, 'tcx> {
2626
span: Span,
2727
self_expr: &'tcx hir::Expr<'tcx>,
2828
call_expr: &'tcx hir::Expr<'tcx>,
29+
skip_record_for_diagnostics: bool,
2930
}
3031

3132
impl<'a, 'tcx> Deref for ConfirmContext<'a, 'tcx> {
@@ -59,6 +60,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5960
let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr);
6061
confirm_cx.confirm(unadjusted_self_ty, pick, segment)
6162
}
63+
64+
pub fn confirm_method_for_diagnostic(
65+
&self,
66+
span: Span,
67+
self_expr: &'tcx hir::Expr<'tcx>,
68+
call_expr: &'tcx hir::Expr<'tcx>,
69+
unadjusted_self_ty: Ty<'tcx>,
70+
pick: &probe::Pick<'tcx>,
71+
segment: &hir::PathSegment<'_>,
72+
) -> ConfirmResult<'tcx> {
73+
let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr);
74+
confirm_cx.skip_record_for_diagnostics = true;
75+
confirm_cx.confirm(unadjusted_self_ty, pick, segment)
76+
}
6277
}
6378

6479
impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
@@ -68,7 +83,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
6883
self_expr: &'tcx hir::Expr<'tcx>,
6984
call_expr: &'tcx hir::Expr<'tcx>,
7085
) -> ConfirmContext<'a, 'tcx> {
71-
ConfirmContext { fcx, span, self_expr, call_expr }
86+
ConfirmContext { fcx, span, self_expr, call_expr, skip_record_for_diagnostics: false }
7287
}
7388

7489
fn confirm(
@@ -219,7 +234,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
219234
self.register_predicates(autoderef.into_obligations());
220235

221236
// Write out the final adjustments.
222-
self.apply_adjustments(self.self_expr, adjustments);
237+
if !self.skip_record_for_diagnostics {
238+
self.apply_adjustments(self.self_expr, adjustments);
239+
}
223240

224241
target
225242
}
@@ -453,7 +470,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
453470
});
454471

455472
debug!("instantiate_method_substs: user_type_annotation={:?}", user_type_annotation);
456-
self.fcx.write_user_type_annotation(self.call_expr.hir_id, user_type_annotation);
473+
474+
if !self.skip_record_for_diagnostics {
475+
self.fcx.write_user_type_annotation(self.call_expr.hir_id, user_type_annotation);
476+
}
457477
}
458478

459479
self.normalize(self.span, substs)

compiler/rustc_hir_typeck/src/method/mod.rs

+21
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
254254
Ok(result.callee)
255255
}
256256

257+
pub fn lookup_method_for_diagnostic(
258+
&self,
259+
self_ty: Ty<'tcx>,
260+
segment: &hir::PathSegment<'_>,
261+
span: Span,
262+
call_expr: &'tcx hir::Expr<'tcx>,
263+
self_expr: &'tcx hir::Expr<'tcx>,
264+
) -> Result<MethodCallee<'tcx>, MethodError<'tcx>> {
265+
let pick = self.lookup_probe_for_diagnostic(
266+
segment.ident,
267+
self_ty,
268+
call_expr,
269+
ProbeScope::TraitsInScope,
270+
None,
271+
)?;
272+
273+
Ok(self
274+
.confirm_method_for_diagnostic(span, self_expr, call_expr, self_ty, &pick, segment)
275+
.callee)
276+
}
277+
257278
#[instrument(level = "debug", skip(self, call_expr))]
258279
pub fn lookup_probe(
259280
&self,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
pub trait NSWindow: Sized {
2+
fn frame(self) -> () {
3+
unimplemented!()
4+
}
5+
fn setFrame_display_(self, display: ()) {}
6+
}
7+
impl NSWindow for () {}
8+
9+
pub struct NSRect {}
10+
11+
use std::ops::Deref;
12+
struct MainThreadSafe<T = ()>(T);
13+
impl<T> Deref for MainThreadSafe<T> {
14+
type Target = T;
15+
16+
fn deref(&self) -> &T {
17+
unimplemented!()
18+
}
19+
}
20+
21+
fn main() {
22+
|| {
23+
let ns_window = MainThreadSafe(());
24+
// Don't record adjustments twice for `*ns_window`
25+
(*ns_window).frame();
26+
ns_window.setFrame_display_(0);
27+
//~^ ERROR mismatched types
28+
};
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/dont-record-adjustments-when-pointing-at-arg.rs:26:37
3+
|
4+
LL | ns_window.setFrame_display_(0);
5+
| ----------------- ^ expected `()`, found integer
6+
| |
7+
| arguments to this method are incorrect
8+
|
9+
note: method defined here
10+
--> $DIR/dont-record-adjustments-when-pointing-at-arg.rs:5:8
11+
|
12+
LL | fn setFrame_display_(self, display: ()) {}
13+
| ^^^^^^^^^^^^^^^^^ -----------
14+
15+
error: aborting due to previous error
16+
17+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)