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.
This commit is contained in:
parent
48e1df87e1
commit
a269b31231
9 changed files with 565 additions and 4 deletions
|
|
@ -1386,16 +1386,22 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
// the shadowing, because the autoderef-based maths wouldn't line up.
|
||||
// This is a niche case and we can live without generating an error
|
||||
// in the case of such shadowing.
|
||||
let _potentially_shadowed_pick = self.pick_autorefd_method(
|
||||
let potentially_shadowed_pick = self.pick_autorefd_method(
|
||||
step,
|
||||
self_ty,
|
||||
mutbl,
|
||||
&mut pick_diag_hints,
|
||||
Some(&pick_constraints),
|
||||
);
|
||||
|
||||
// At the moment, this function does no checks. A future
|
||||
// commit will fill out the body here.
|
||||
// Look for actual pairs of shadower/shadowed which are
|
||||
// the sort of shadowing case we want to avoid. Specifically...
|
||||
if let Some(Ok(possible_shadowed)) = potentially_shadowed_pick.as_ref() {
|
||||
let sources = [possible_shadower, possible_shadowed]
|
||||
.into_iter()
|
||||
.map(|p| self.candidate_source_from_pick(p))
|
||||
.collect();
|
||||
return Err(MethodError::Ambiguity(sources));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -1771,6 +1777,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn candidate_source_from_pick(&self, pick: &Pick<'tcx>) -> CandidateSource {
|
||||
match pick.kind {
|
||||
InherentImplPick => CandidateSource::Impl(pick.item.container_id(self.tcx)),
|
||||
ObjectPick | WhereClausePick(_) | TraitPick => {
|
||||
CandidateSource::Trait(pick.item.container_id(self.tcx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, possibly_unsatisfied_predicates), ret)]
|
||||
fn consider_probe(
|
||||
&self,
|
||||
|
|
|
|||
69
tests/ui/self/arbitrary_self_types_by_value_reborrow.rs
Normal file
69
tests/ui/self/arbitrary_self_types_by_value_reborrow.rs
Normal file
|
|
@ -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
|
||||
// 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
tests/ui/self/arbitrary_self_types_shadowing_val_constptr.rs
Normal file
33
tests/ui/self/arbitrary_self_types_shadowing_val_constptr.rs
Normal file
|
|
@ -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);
|
||||
}
|
||||
55
tests/ui/self/arbitrary_self_types_unshadowing.rs
Normal file
55
tests/ui/self/arbitrary_self_types_unshadowing.rs
Normal file
|
|
@ -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
|
||||
}
|
||||
105
tests/ui/self/arbitrary_self_types_unshadowing.stderr
Normal file
105
tests/ui/self/arbitrary_self_types_unshadowing.stderr
Normal file
|
|
@ -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`.
|
||||
61
tests/ui/self/arbitrary_self_types_unshadowing_ptrs.rs
Normal file
61
tests/ui/self/arbitrary_self_types_unshadowing_ptrs.rs
Normal file
|
|
@ -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
|
||||
}
|
||||
122
tests/ui/self/arbitrary_self_types_unshadowing_ptrs.stderr
Normal file
122
tests/ui/self/arbitrary_self_types_unshadowing_ptrs.stderr
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:45: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_ptrs.rs:9: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_ptrs.rs:38:5
|
||||
|
|
||||
LL | pub fn f(self) -> i32 { 5 }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:47: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_ptrs.rs:10: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_ptrs.rs:39:5
|
||||
|
|
||||
LL | pub fn g(&self) -> i32 { 6 }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:49: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_ptrs.rs:11: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_ptrs.rs:40:5
|
||||
|
|
||||
LL | pub fn h(&mut self) -> i32 { 7 }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:53:22
|
||||
|
|
||||
LL | assert_eq!(a_ptr.i(), 4);
|
||||
| ^ multiple `i` found
|
||||
|
|
||||
note: candidate #1 is defined in an impl for the type `A`
|
||||
--> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:12:5
|
||||
|
|
||||
LL | pub fn i(self: *const Wrapper<Self>) -> i32 { 4 }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: candidate #2 is defined in an impl for the type `Wrapper<T>`
|
||||
--> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:41:5
|
||||
|
|
||||
LL | pub fn i(self: *const Self) -> i32 { 8 }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:55: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_ptrs.rs:19: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_ptrs.rs:38:5
|
||||
|
|
||||
LL | pub fn f(self) -> i32 { 5 }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:57: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_ptrs.rs:27: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_ptrs.rs:38:5
|
||||
|
|
||||
LL | pub fn f(self) -> i32 { 5 }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:59: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_ptrs.rs:28: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_ptrs.rs:39:5
|
||||
|
|
||||
LL | pub fn g(&self) -> i32 { 6 }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0034`.
|
||||
38
tests/ui/self/conflicting_inner.rs
Normal file
38
tests/ui/self/conflicting_inner.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
//@ run-pass
|
||||
//@ revisions: default feature
|
||||
#![cfg_attr(feature, feature(arbitrary_self_types))]
|
||||
|
||||
// This test aims to be like the IndexVec within rustc, and conflicts
|
||||
// over its into_iter().
|
||||
|
||||
#[allow(dead_code)]
|
||||
trait Foo {
|
||||
fn foo(self) -> usize;
|
||||
}
|
||||
|
||||
struct IndexVec<T>(T);
|
||||
|
||||
impl<T> std::ops::Deref for IndexVec<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Foo for &'a IndexVec<T> {
|
||||
fn foo(self) -> usize {
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IndexVec<T> {
|
||||
fn foo(self) -> usize {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let ivec = IndexVec(0usize);
|
||||
assert_eq!(ivec.foo(), 1);
|
||||
}
|
||||
63
tests/ui/self/conflicting_inner2.rs
Normal file
63
tests/ui/self/conflicting_inner2.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
//@ run-pass
|
||||
//@ revisions: default feature
|
||||
#![cfg_attr(feature, feature(arbitrary_self_types))]
|
||||
|
||||
use std::pin::Pin;
|
||||
use std::ops::DerefMut;
|
||||
use std::marker::Unpin;
|
||||
|
||||
struct TryChunks;
|
||||
|
||||
impl TryChunks {
|
||||
#[allow(dead_code)]
|
||||
fn take(self: std::pin::Pin<&mut Self>) -> usize {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
trait Stream {
|
||||
fn poll_next(self: std::pin::Pin<&mut Self>);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
trait StreamExt: Stream {
|
||||
#[allow(dead_code)]
|
||||
fn take(self) -> usize where Self: Sized
|
||||
{
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> StreamExt for T where T: Stream {}
|
||||
|
||||
impl Stream for TryChunks {
|
||||
fn poll_next(self: std::pin::Pin<&mut Self>) {
|
||||
assert_eq!(self.take(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<S: ?Sized + Stream + Unpin> Stream for &mut S {
|
||||
#[allow(dead_code)]
|
||||
fn poll_next(mut self: Pin<&mut Self>) {
|
||||
S::poll_next(Pin::new(&mut **self))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<P> Stream for Pin<P>
|
||||
where
|
||||
P: DerefMut + Unpin,
|
||||
P::Target: Stream,
|
||||
{
|
||||
#[allow(dead_code)]
|
||||
fn poll_next(self: Pin<&mut Self>) {
|
||||
self.get_mut().as_mut().poll_next()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut item = Box::pin(TryChunks);
|
||||
item.as_mut().poll_next();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue