Skip to content

Commit

Permalink
Rollup merge of rust-lang#136124 - adetaylor:test-comment, r=compiler…
Browse files Browse the repository at this point in the history
…-errors

Arbitrary self types v2: explain test.

The purpose of this test wasn't obvious, as ``@traviscross`` noted. Add a comment.

Confession: although this test was added to demonstrate this particular corner-case, I can no longer reproduce the original problem, even if I adjust `rustc` to do the "wrong" thing. I have spent several hours trying to adjust the case to trigger the "faulty" behavior with no success. This test may therefore not be as useful as it originally was. But it still seems worthwhile retaining as a regression test that we don't break things in these quirky circumstances. Ideally we'd find a new test which tests this behavior but I've failed to come up with one.

r? ``@traviscross``
  • Loading branch information
matthiaskrgr authored Jan 28, 2025
2 parents 2c0d773 + d898aa3 commit 87b1c67
Showing 1 changed file with 23 additions and 1 deletion.
24 changes: 23 additions & 1 deletion tests/ui/self/arbitrary_self_types_recursive_receiver.rs
Original file line number Diff line number Diff line change
@@ -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> {
Expand All @@ -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)
Expand Down

0 comments on commit 87b1c67

Please sign in to comment.