diff --git a/tests/ui/self/arbitrary_self_types_recursive_receiver.rs b/tests/ui/self/arbitrary_self_types_recursive_receiver.rs
index f3e7f96d7c4de..8b1b6a8a105f3 100644
--- a/tests/ui/self/arbitrary_self_types_recursive_receiver.rs
+++ b/tests/ui/self/arbitrary_self_types_recursive_receiver.rs
@@ -1,6 +1,22 @@
 //@ run-pass
 #![feature(arbitrary_self_types)]
 
+// When probing for methods, we step forward through a chain of types. The first
+// few of those steps can be reached by jumping through the chain of Derefs or the
+// chain of Receivers. Later steps can only be reached by following the chain of
+// Receivers. For instance, supposing A and B implement both Receiver and Deref,
+// while C and D implement only Receiver:
+//
+// Type A<B<C<D<E>>>>
+//
+//     Deref chain:      A -> B -> C
+//     Receiver chain:   A -> B -> C -> D -> E
+//
+// We report bad type errors from the end of the chain. But at the end of which
+// chain? We never morph the type as far as E so the correct behavior is to
+// report errors from point C, i.e. the end of the Deref chain. This test case
+// ensures we do that.
+
 struct MyNonNull<T>(*const T);
 
 impl<T> std::ops::Receiver for MyNonNull<T> {
@@ -10,7 +26,13 @@ impl<T> std::ops::Receiver for MyNonNull<T> {
 #[allow(dead_code)]
 impl<T> MyNonNull<T> {
     fn foo<U>(&self) -> *const U {
-        self.cast::<U>().bar()
+        let mnn = self.cast::<U>();
+        // The following method call is the point of this test.
+        // If probe.rs reported errors from the last type discovered
+        // in the Receiver chain, it would be sad here because U is just
+        // a type variable. But this is a valid call so it ensures
+        // probe.rs doesn't make that mistake.
+        mnn.bar()
     }
     fn cast<U>(&self) -> MyNonNull<U> {
         MyNonNull(self.0 as *const U)