mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Rollup merge of #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 #112532 happens because we're recording deref adjustments twice for a call receiver, which causes `ExprUseVisitor` to be angry. Fixes #112532
This commit is contained in:
commit
90e51f110c
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
};
|
||||
}
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user