-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Arbitrary self types v2: main compiler changes #132961
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
bors
merged 6 commits into
rust-lang:master
from
adetaylor:arbitrary-self-types-the-big-bit
Dec 13, 2024
Merged
Changes from 1 commit
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
e75660d
Arbitrary self types v2: use Receiver trait
adetaylor 7f7c964
Arbitrary self types v2: pick diags to stack.
adetaylor 2707f55
Arbitrary self types v2: deshadowing probe
adetaylor 48e1df8
Arbitrary self types v2: deshadow quicker
adetaylor a269b31
Arbitrary self types v2: detect shadowing problems.
adetaylor 337af8a
Arbitrary self types v2: generics test.
adetaylor File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Arbitrary self types v2: detect shadowing problems.
This builds on the previous commits by actually adding checks for cases where a new method shadows an older method.
- Loading branch information
commit a269b312314e5c3fb96188ff8e797603bc669f63
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
//@ run-pass | ||
|
||
#![feature(arbitrary_self_types)] | ||
#![allow(dead_code)] | ||
|
||
// With arbitrary self types v2, we show an error if there are | ||
// multiple contenders for a method call in an inner and outer type. | ||
// The goal is to avoid any possibility of confusion by a new | ||
// 'shadowing' method calling a 'shadowed' method. | ||
// However, there are niche circumstances where this | ||
// algorithm doesn't quite work, due to reborrows to get a different | ||
// lifetime. The test below explicitly tests those circumstances to ensure | ||
adetaylor marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// the behavior is as expected, even if it's not 100% desirable. They're | ||
// very niche circumstances. | ||
|
||
#[derive(Debug, PartialEq)] | ||
enum Callee { | ||
INNER, | ||
OUTER | ||
} | ||
|
||
struct MyNonNull<T>(T); | ||
|
||
impl<T> std::ops::Receiver for MyNonNull<T> { | ||
type Target = T; | ||
} | ||
|
||
struct A; | ||
impl A { | ||
fn foo(self: MyNonNull<A>) -> Callee { | ||
Callee::INNER | ||
} | ||
|
||
fn bar(self: &MyNonNull<A>) -> Callee { | ||
Callee::INNER | ||
} | ||
|
||
fn baz(self: &&MyNonNull<A>) -> Callee { | ||
// note this is by DOUBLE reference | ||
Callee::INNER | ||
} | ||
} | ||
|
||
impl<T> MyNonNull<T> { | ||
fn foo(&self) -> Callee{ | ||
Callee::OUTER | ||
} | ||
|
||
fn bar(&self) -> Callee{ | ||
Callee::OUTER | ||
} | ||
|
||
fn baz(&self) -> Callee{ | ||
Callee::OUTER | ||
} | ||
} | ||
|
||
fn main() { | ||
// The normal deshadowing case. Does not compile. | ||
// assert_eq!(MyNonNull(A).foo(), Callee::INNER); | ||
|
||
// Similarly, does not compile. | ||
//assert_eq!(MyNonNull(A).bar(), Callee::INNER); | ||
|
||
// The double-reference case. | ||
// We call the newly-added outer type method. | ||
// Not ideal but very niche so we accept it. | ||
assert_eq!(MyNonNull(A).baz(), Callee::OUTER); | ||
} |
33 changes: 33 additions & 0 deletions
33
tests/ui/self/arbitrary_self_types_shadowing_val_constptr.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
//@ run-pass | ||
|
||
#![feature(arbitrary_self_types)] | ||
#![feature(arbitrary_self_types_pointers)] | ||
|
||
pub struct A; | ||
|
||
impl A { | ||
pub fn f(self: *const MyNonNull<Self>) -> i32 { 1 } | ||
} | ||
|
||
pub struct MyNonNull<T>(T); | ||
|
||
impl<T> core::ops::Receiver for MyNonNull<T> { | ||
type Target = T; | ||
} | ||
|
||
impl<T> MyNonNull<T> { | ||
// Imagine this a NEW method in B<T> shadowing an EXISTING | ||
// method in A. | ||
pub fn f(self: *mut Self) -> i32 { | ||
2 | ||
} | ||
} | ||
|
||
fn main() { | ||
let mut b = MyNonNull(A); | ||
let b = &mut b; | ||
let b = b as *mut MyNonNull<A>; | ||
// We actually allow the shadowing in the case of const vs mut raw | ||
// pointer receivers. | ||
assert_eq!(b.f(), 2); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#![feature(arbitrary_self_types)] | ||
|
||
pub struct A; | ||
|
||
// The receiver of the potentially shadowed method | ||
// precisely matches that of the shadower | ||
impl A { | ||
pub fn f(self: Wrapper<Self>) -> i32 { 1 } | ||
pub fn g(self: &Wrapper<Self>) -> i32 { 2 } | ||
pub fn h(self: &mut Wrapper<Self>) -> i32 { 3 } | ||
} | ||
|
||
// The receiver of the potentially shadowed method is a reference | ||
pub struct B; | ||
|
||
impl B { | ||
pub fn f(self: &Wrapper<Self>) -> i32 { 9 } | ||
} | ||
|
||
// The receiver of the potentially shadowed method is a mut reference | ||
|
||
pub struct C; | ||
|
||
impl C { | ||
pub fn f(self: &mut Wrapper<Self>) -> i32 { 10 } | ||
pub fn g(self: &mut Wrapper<Self>) -> i32 { 11 } | ||
} | ||
|
||
pub struct Wrapper<T>(T); | ||
|
||
impl<T> core::ops::Receiver for Wrapper<T> { | ||
type Target = T; | ||
} | ||
|
||
impl<T> Wrapper<T> { | ||
pub fn f(self) -> i32 { 5 } | ||
pub fn g(&self) -> i32 { 6 } | ||
pub fn h(&mut self) -> i32 { 7 } | ||
} | ||
|
||
fn main() { | ||
assert_eq!(Wrapper(A).f(), 1); | ||
//~^ ERROR: multiple applicable items in scope | ||
assert_eq!(Wrapper(A).g(), 2); | ||
//~^ ERROR: multiple applicable items in scope | ||
assert_eq!(Wrapper(A).h(), 3); | ||
//~^ ERROR: multiple applicable items in scope | ||
let a = Wrapper(A); | ||
assert_eq!(Wrapper(B).f(), 9); | ||
//~^ ERROR: multiple applicable items in scope | ||
assert_eq!(Wrapper(C).f(), 10); | ||
//~^ ERROR: multiple applicable items in scope | ||
assert_eq!(Wrapper(C).g(), 11); | ||
//~^ ERROR: multiple applicable items in scope | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
error[E0034]: multiple applicable items in scope | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:42:27 | ||
| | ||
LL | assert_eq!(Wrapper(A).f(), 1); | ||
| ^ multiple `f` found | ||
| | ||
note: candidate #1 is defined in an impl for the type `A` | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:8:5 | ||
| | ||
LL | pub fn f(self: Wrapper<Self>) -> i32 { 1 } | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
note: candidate #2 is defined in an impl for the type `Wrapper<T>` | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:36:5 | ||
| | ||
LL | pub fn f(self) -> i32 { 5 } | ||
| ^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0034]: multiple applicable items in scope | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:44:27 | ||
| | ||
LL | assert_eq!(Wrapper(A).g(), 2); | ||
| ^ multiple `g` found | ||
| | ||
note: candidate #1 is defined in an impl for the type `A` | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:9:5 | ||
| | ||
LL | pub fn g(self: &Wrapper<Self>) -> i32 { 2 } | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
note: candidate #2 is defined in an impl for the type `Wrapper<T>` | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:37:5 | ||
| | ||
LL | pub fn g(&self) -> i32 { 6 } | ||
| ^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0034]: multiple applicable items in scope | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:46:27 | ||
| | ||
LL | assert_eq!(Wrapper(A).h(), 3); | ||
| ^ multiple `h` found | ||
| | ||
note: candidate #1 is defined in an impl for the type `A` | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:10:5 | ||
| | ||
LL | pub fn h(self: &mut Wrapper<Self>) -> i32 { 3 } | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
note: candidate #2 is defined in an impl for the type `Wrapper<T>` | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:38:5 | ||
| | ||
LL | pub fn h(&mut self) -> i32 { 7 } | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0034]: multiple applicable items in scope | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:49:27 | ||
| | ||
LL | assert_eq!(Wrapper(B).f(), 9); | ||
| ^ multiple `f` found | ||
| | ||
note: candidate #1 is defined in an impl for the type `B` | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:17:5 | ||
| | ||
LL | pub fn f(self: &Wrapper<Self>) -> i32 { 9 } | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
note: candidate #2 is defined in an impl for the type `Wrapper<T>` | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:36:5 | ||
| | ||
LL | pub fn f(self) -> i32 { 5 } | ||
| ^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0034]: multiple applicable items in scope | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:51:27 | ||
| | ||
LL | assert_eq!(Wrapper(C).f(), 10); | ||
| ^ multiple `f` found | ||
| | ||
note: candidate #1 is defined in an impl for the type `C` | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:25:5 | ||
| | ||
LL | pub fn f(self: &mut Wrapper<Self>) -> i32 { 10 } | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
note: candidate #2 is defined in an impl for the type `Wrapper<T>` | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:36:5 | ||
| | ||
LL | pub fn f(self) -> i32 { 5 } | ||
| ^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0034]: multiple applicable items in scope | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:53:27 | ||
| | ||
LL | assert_eq!(Wrapper(C).g(), 11); | ||
| ^ multiple `g` found | ||
| | ||
note: candidate #1 is defined in an impl for the type `C` | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:26:5 | ||
| | ||
LL | pub fn g(self: &mut Wrapper<Self>) -> i32 { 11 } | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
note: candidate #2 is defined in an impl for the type `Wrapper<T>` | ||
--> $DIR/arbitrary_self_types_unshadowing.rs:37:5 | ||
| | ||
LL | pub fn g(&self) -> i32 { 6 } | ||
| ^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: aborting due to 6 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0034`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#![feature(arbitrary_self_types_pointers)] | ||
#![feature(arbitrary_self_types)] | ||
|
||
pub struct A; | ||
|
||
// The receiver of the potentially shadowed method | ||
// precisely matches that of the shadower | ||
impl A { | ||
pub fn f(self: Wrapper<Self>) -> i32 { 1 } | ||
pub fn g(self: &Wrapper<Self>) -> i32 { 2 } | ||
pub fn h(self: &mut Wrapper<Self>) -> i32 { 3 } | ||
pub fn i(self: *const Wrapper<Self>) -> i32 { 4 } | ||
} | ||
|
||
// The receiver of the potentially shadowed method is a reference | ||
pub struct B; | ||
|
||
impl B { | ||
pub fn f(self: &Wrapper<Self>) -> i32 { 9 } | ||
} | ||
|
||
// The receiver of the potentially shadowed method is a mut reference | ||
|
||
pub struct C; | ||
|
||
impl C { | ||
pub fn f(self: &mut Wrapper<Self>) -> i32 { 10 } | ||
pub fn g(self: &mut Wrapper<Self>) -> i32 { 11 } | ||
} | ||
|
||
pub struct Wrapper<T>(T); | ||
|
||
impl<T> core::ops::Receiver for Wrapper<T> { | ||
type Target = T; | ||
} | ||
|
||
impl<T> Wrapper<T> { | ||
pub fn f(self) -> i32 { 5 } | ||
pub fn g(&self) -> i32 { 6 } | ||
pub fn h(&mut self) -> i32 { 7 } | ||
pub fn i(self: *const Self) -> i32 { 8 } | ||
} | ||
|
||
fn main() { | ||
assert_eq!(Wrapper(A).f(), 1); | ||
//~^ ERROR: multiple applicable items in scope | ||
assert_eq!(Wrapper(A).g(), 2); | ||
//~^ ERROR: multiple applicable items in scope | ||
assert_eq!(Wrapper(A).h(), 3); | ||
//~^ ERROR: multiple applicable items in scope | ||
let a = Wrapper(A); | ||
let a_ptr = &a as *const Wrapper<A>; | ||
assert_eq!(a_ptr.i(), 4); | ||
//~^ ERROR: multiple applicable items in scope | ||
assert_eq!(Wrapper(B).f(), 9); | ||
//~^ ERROR: multiple applicable items in scope | ||
assert_eq!(Wrapper(C).f(), 10); | ||
//~^ ERROR: multiple applicable items in scope | ||
assert_eq!(Wrapper(C).g(), 11); | ||
//~^ ERROR: multiple applicable items in scope | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think maybe this should be an unresolved question on the tracking issue. T-lang can decide if they're fine with this niche case before stabilization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good. I'll wait until we're largely through the review process here, and after we've done a crater run, then accumulate a list of questions which have come up, including this one.
Other assumptions I've made which might merit wider discussion: