Skip to content

Commit cdb10b8

Browse files
committed
A very simple hack to force an autoderef if the callee has type `&mut
F`, so that if we have `x: &mut FnMut()`, then `x()` is translated to `FnMut::call_mut(&mut *x, ())` rather than `&mut x`. The latter would require `mut x: &mut FnMut()`, which is really a lot of mut. (Actually, the `mut` is normally required except for the special case of a `&mut F` reference, because that's the one case where we distinguish a unique path like `x` from a mutable path.)
1 parent cead47c commit cdb10b8

File tree

1 file changed

+18
-6
lines changed

1 file changed

+18
-6
lines changed

src/librustc_typeck/check/callee.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,7 @@ pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
8383
UnresolvedTypeAction::Error,
8484
LvaluePreference::NoPreference,
8585
|adj_ty, idx| {
86-
let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
87-
try_overloaded_call_step(fcx, call_expr, callee_expr,
88-
adj_ty, autoderefref)
86+
try_overloaded_call_step(fcx, call_expr, callee_expr, adj_ty, idx)
8987
});
9088

9189
match result {
@@ -119,13 +117,15 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
119117
call_expr: &'tcx ast::Expr,
120118
callee_expr: &'tcx ast::Expr,
121119
adjusted_ty: Ty<'tcx>,
122-
autoderefref: ty::AutoDerefRef<'tcx>)
120+
autoderefs: usize)
123121
-> Option<CallStep<'tcx>>
124122
{
125-
debug!("try_overloaded_call_step(call_expr={}, adjusted_ty={}, autoderefref={})",
123+
debug!("try_overloaded_call_step(call_expr={}, adjusted_ty={}, autoderefs={})",
126124
call_expr.repr(fcx.tcx()),
127125
adjusted_ty.repr(fcx.tcx()),
128-
autoderefref.repr(fcx.tcx()));
126+
autoderefs);
127+
128+
let autoderefref = ty::AutoDerefRef { autoderefs: autoderefs, autoref: None };
129129

130130
// If the callee is a bare function or a closure, then we're all set.
131131
match structurally_resolved_type(fcx, callee_expr.span, adjusted_ty).sty {
@@ -161,6 +161,18 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
161161
}
162162
}
163163

164+
// Hack: we know that there are traits implementing Fn for &F
165+
// where F:Fn and so forth. In the particular case of types
166+
// like `x: &mut FnMut()`, if there is a call `x()`, we would
167+
// normally translate to `FnMut::call_mut(&mut x, ())`, but
168+
// that winds up requiring `mut x: &mut FnMut()`. A little
169+
// over the top. The simplest fix by far is to just ignore
170+
// this case and deref again, so we wind up with
171+
// `FnMut::call_mut(&mut *x, ())`.
172+
ty::ty_rptr(..) if autoderefs == 0 => {
173+
return None;
174+
}
175+
164176
_ => {}
165177
}
166178

0 commit comments

Comments
 (0)