diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index dde6b8ce9b8b2..d13b2b04bb739 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -337,9 +337,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { *entry.get_mut() = adj; } + ( + &mut [.., Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. }], + &[Adjustment { kind: Adjust::Deref(_), .. }, ..], + ) => { + // A reborrow has no effect before a dereference, so we can safely merge adjustments. + // A more general version of the above case. + let entry_mut = entry.get_mut(); + entry_mut.pop(); + entry_mut.extend_from_slice(&adj[1..]); + } + _ => { - // FIXME: currently we never try to compose autoderefs - // and ReifyFnPointer/UnsafeFnPointer, but we could. + // FIXME: currently we never try to compose ReifyFnPointer/UnsafeFnPointer, but we could. self.dcx().span_delayed_bug( expr.span, format!( diff --git a/tests/ui/coercion/compose_autoderefs.rs b/tests/ui/coercion/compose_autoderefs.rs new file mode 100644 index 0000000000000..60af45795664e --- /dev/null +++ b/tests/ui/coercion/compose_autoderefs.rs @@ -0,0 +1,32 @@ +//@ edition:2021 +//@ check-pass + +use core::ops::Deref; + +struct A; +struct B; +struct C; + +impl Deref for C { + type Target = B; + fn deref(&self) -> &Self::Target { + &B + } +} + +impl Deref for B { + type Target = A; + fn deref(&self) -> &Self::Target { + &A + } +} + +fn f(v: u8) { + let _ = match v { + 0 => &C, + 1 => &B, + _ => &A, + }; +} + +fn main() {}