@@ -218,10 +218,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
218
218
// to type check, we will construct the type that `&M*expr` would
219
219
// yield.
220
220
221
- let r_a = match a. sty {
221
+ let ( r_a, mt_a ) = match a. sty {
222
222
ty:: TyRef ( r_a, mt_a) => {
223
223
try!( coerce_mutbls ( mt_a. mutbl , mt_b. mutbl ) ) ;
224
- r_a
224
+ ( r_a, mt_a )
225
225
}
226
226
_ => return self . unify_and_identity ( a, b)
227
227
} ;
@@ -355,6 +355,20 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
355
355
356
356
// Now apply the autoref. We have to extract the region out of
357
357
// the final ref type we got.
358
+ if ty == a && mt_a. mutbl == hir:: MutImmutable && autoderefs == 1 {
359
+ // As a special case, if we would produce `&'a *x`, that's
360
+ // a total no-op. We end up with the type `&'a T` just as
361
+ // we started with. In that case, just skip it
362
+ // altogether. This is just an optimization.
363
+ //
364
+ // Note that for `&mut`, we DO want to reborrow --
365
+ // otherwise, this would be a move, which might be an
366
+ // error. For example `foo(self.x)` where `self` and
367
+ // `self.x` both have `&mut `type would be a move of
368
+ // `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
369
+ // which is a borrow.
370
+ return self . identity ( ty) ;
371
+ }
358
372
let r_borrow = match ty. sty {
359
373
ty:: TyRef ( r_borrow, _) => r_borrow,
360
374
_ => self . tcx ( ) . sess . span_bug ( span,
0 commit comments