diff options
Diffstat (limited to 'tests/ui/autoref-autoderef')
14 files changed, 329 insertions, 0 deletions
diff --git a/tests/ui/autoref-autoderef/auto-ref-bounded-ty-param.rs b/tests/ui/autoref-autoderef/auto-ref-bounded-ty-param.rs new file mode 100644 index 000000000..2482e1878 --- /dev/null +++ b/tests/ui/autoref-autoderef/auto-ref-bounded-ty-param.rs @@ -0,0 +1,29 @@ +// run-pass +trait Foo { + fn f(&self); +} + +struct Bar { + x: isize +} + +trait Baz { + fn g(&self); +} + +impl<T:Baz> Foo for T { + fn f(&self) { + self.g(); + } +} + +impl Baz for Bar { + fn g(&self) { + println!("{}", self.x); + } +} + +pub fn main() { + let y = Bar { x: 42 }; + y.f(); +} diff --git a/tests/ui/autoref-autoderef/auto-ref-sliceable.rs b/tests/ui/autoref-autoderef/auto-ref-sliceable.rs new file mode 100644 index 000000000..e5f79d780 --- /dev/null +++ b/tests/ui/autoref-autoderef/auto-ref-sliceable.rs @@ -0,0 +1,19 @@ +// run-pass + + +trait Pushable<T> { + fn push_val(&mut self, t: T); +} + +impl<T> Pushable<T> for Vec<T> { + fn push_val(&mut self, t: T) { + self.push(t); + } +} + +pub fn main() { + let mut v = vec![1]; + v.push_val(2); + v.push_val(3); + assert_eq!(v, [1, 2, 3]); +} diff --git a/tests/ui/autoref-autoderef/auto-ref.rs b/tests/ui/autoref-autoderef/auto-ref.rs new file mode 100644 index 000000000..b77f9c342 --- /dev/null +++ b/tests/ui/autoref-autoderef/auto-ref.rs @@ -0,0 +1,19 @@ +// run-pass +struct Foo { + x: isize, +} + +trait Stuff { + fn printme(&self); +} + +impl Stuff for Foo { + fn printme(&self) { + println!("{}", self.x); + } +} + +pub fn main() { + let x = Foo { x: 3 }; + x.printme(); +} diff --git a/tests/ui/autoref-autoderef/autoderef-and-borrow-method-receiver.rs b/tests/ui/autoref-autoderef/autoderef-and-borrow-method-receiver.rs new file mode 100644 index 000000000..874f42282 --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-and-borrow-method-receiver.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +struct Foo { + x: isize, +} + +impl Foo { + pub fn f(&self) {} +} + +fn g(x: &mut Foo) { + x.f(); +} + +pub fn main() { +} diff --git a/tests/ui/autoref-autoderef/autoderef-method-on-trait.rs b/tests/ui/autoref-autoderef/autoderef-method-on-trait.rs new file mode 100644 index 000000000..af747cc76 --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-method-on-trait.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(non_camel_case_types)] + +trait double { + fn double(self: Box<Self>) -> usize; +} + +impl double for usize { + fn double(self: Box<usize>) -> usize { *self * 2 } +} + +pub fn main() { + let x: Box<_> = Box::new(Box::new(3usize) as Box<dyn double>); + assert_eq!(x.double(), 6); +} diff --git a/tests/ui/autoref-autoderef/autoderef-method-priority.rs b/tests/ui/autoref-autoderef/autoderef-method-priority.rs new file mode 100644 index 000000000..88a5140dc --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-method-priority.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(non_camel_case_types)] + +trait double { + fn double(self) -> usize; +} + +impl double for usize { + fn double(self) -> usize { self } +} + +impl double for Box<usize> { + fn double(self) -> usize { *self * 2 } +} + +pub fn main() { + let x: Box<_> = Box::new(3); + assert_eq!(x.double(), 6); +} diff --git a/tests/ui/autoref-autoderef/autoderef-method-twice-but-not-thrice.rs b/tests/ui/autoref-autoderef/autoderef-method-twice-but-not-thrice.rs new file mode 100644 index 000000000..3657e61d4 --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-method-twice-but-not-thrice.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(non_camel_case_types)] + +trait double { + fn double(self: Box<Self>) -> usize; +} + +impl double for Box<usize> { + fn double(self: Box<Box<usize>>) -> usize { **self * 2 } +} + +pub fn main() { + let x: Box<Box<Box<Box<Box<_>>>>> = Box::new(Box::new(Box::new(Box::new(Box::new(3))))); + assert_eq!(x.double(), 6); +} diff --git a/tests/ui/autoref-autoderef/autoderef-method-twice.rs b/tests/ui/autoref-autoderef/autoderef-method-twice.rs new file mode 100644 index 000000000..ed86b31b8 --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-method-twice.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(non_camel_case_types)] + +trait double { + fn double(self: Box<Self>) -> usize; +} + +impl double for usize { + fn double(self: Box<usize>) -> usize { *self * 2 } +} + +pub fn main() { + let x: Box<Box<_>> = Box::new(Box::new(3)); + assert_eq!(x.double(), 6); +} diff --git a/tests/ui/autoref-autoderef/autoderef-method.rs b/tests/ui/autoref-autoderef/autoderef-method.rs new file mode 100644 index 000000000..5b7965e95 --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-method.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(non_camel_case_types)] + +trait double { + fn double(self: Box<Self>) -> usize; +} + +impl double for usize { + fn double(self: Box<usize>) -> usize { *self * 2 } +} + +pub fn main() { + let x: Box<_> = Box::new(3); + assert_eq!(x.double(), 6); +} diff --git a/tests/ui/autoref-autoderef/autoderef-privacy.rs b/tests/ui/autoref-autoderef/autoderef-privacy.rs new file mode 100644 index 000000000..841be930b --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-privacy.rs @@ -0,0 +1,51 @@ +// run-pass +// Check we do not select a private method or field when computing autoderefs + +#![allow(unused)] + +#[derive(Default)] +pub struct Bar2 { i: i32 } +#[derive(Default)] +pub struct Baz2(i32); + +impl Bar2 { + fn f(&self) -> bool { true } +} + +mod foo { + #[derive(Default)] + pub struct Bar { i: ::Bar2 } + #[derive(Default)] + pub struct Baz(::Baz2); + + impl Bar { + fn f(&self) -> bool { false } + } + + impl ::std::ops::Deref for Bar { + type Target = ::Bar2; + fn deref(&self) -> &::Bar2 { &self.i } + } + + impl ::std::ops::Deref for Baz { + type Target = ::Baz2; + fn deref(&self) -> &::Baz2 { &self.0 } + } + + pub fn f(bar: &Bar, baz: &Baz) { + // Since the private fields and methods are visible here, there should be no autoderefs. + let _: &::Bar2 = &bar.i; + let _: &::Baz2 = &baz.0; + assert!(!bar.f()); + } +} + +fn main() { + let bar = foo::Bar::default(); + let baz = foo::Baz::default(); + foo::f(&bar, &baz); + + let _: i32 = bar.i; + let _: i32 = baz.0; + assert!(bar.f()); +} diff --git a/tests/ui/autoref-autoderef/autoref-intermediate-types-issue-3585.rs b/tests/ui/autoref-autoderef/autoref-intermediate-types-issue-3585.rs new file mode 100644 index 000000000..3bdc248ff --- /dev/null +++ b/tests/ui/autoref-autoderef/autoref-intermediate-types-issue-3585.rs @@ -0,0 +1,22 @@ +// run-pass + +trait Foo { + fn foo(&self) -> String; +} + +impl<T:Foo> Foo for Box<T> { + fn foo(&self) -> String { + format!("box {}", (**self).foo()) + } +} + +impl Foo for usize { + fn foo(&self) -> String { + format!("{}", *self) + } +} + +pub fn main() { + let x: Box<_> = Box::new(3); + assert_eq!(x.foo(), "box 3".to_string()); +} diff --git a/tests/ui/autoref-autoderef/deref-into-array.rs b/tests/ui/autoref-autoderef/deref-into-array.rs new file mode 100644 index 000000000..855a82d2f --- /dev/null +++ b/tests/ui/autoref-autoderef/deref-into-array.rs @@ -0,0 +1,17 @@ +// check-pass + +struct Test<T>([T; 1]); + +impl<T> std::ops::Deref for Test<T> { + type Target = [T; 1]; + + fn deref(&self) -> &[T; 1] { + &self.0 + } +} + +fn main() { + let out = Test([(); 1]); + let blah = out.len(); + println!("{}", blah); +} diff --git a/tests/ui/autoref-autoderef/issue-38940.rs b/tests/ui/autoref-autoderef/issue-38940.rs new file mode 100644 index 000000000..d2f1c6e32 --- /dev/null +++ b/tests/ui/autoref-autoderef/issue-38940.rs @@ -0,0 +1,52 @@ +// issue-38940: error printed twice for deref recursion limit exceeded +// Test that the recursion limit can be changed. In this case, we have +// deeply nested types that will fail the `Send` check by overflow +// when the recursion limit is set very low. +// compile-flags: -Zdeduplicate-diagnostics=yes + +#![allow(dead_code)] +#![recursion_limit = "10"] +macro_rules! link { + ($outer:ident, $inner:ident) => { + struct $outer($inner); + impl $outer { + fn new() -> $outer { + $outer($inner::new()) + } + } + impl std::ops::Deref for $outer { + type Target = $inner; + fn deref(&self) -> &$inner { + &self.0 + } + } + }; +} + +struct Bottom; + +impl Bottom { + fn new() -> Bottom { + Bottom + } +} + +link!(Top, A); +link!(A, B); +link!(B, C); +link!(C, D); +link!(D, E); +link!(E, F); +link!(F, G); +link!(G, H); +link!(H, I); +link!(I, J); +link!(J, K); +link!(K, Bottom); + +fn main() { + let t = Top::new(); + let x: &Bottom = &t; + //~^ ERROR mismatched types + //~| ERROR reached the recursion limit while auto-dereferencing `J` +} diff --git a/tests/ui/autoref-autoderef/issue-38940.stderr b/tests/ui/autoref-autoderef/issue-38940.stderr new file mode 100644 index 000000000..f0b840577 --- /dev/null +++ b/tests/ui/autoref-autoderef/issue-38940.stderr @@ -0,0 +1,23 @@ +error[E0055]: reached the recursion limit while auto-dereferencing `J` + --> $DIR/issue-38940.rs:49:22 + | +LL | let x: &Bottom = &t; + | ^^ deref recursion limit reached + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`issue_38940`) + +error[E0308]: mismatched types + --> $DIR/issue-38940.rs:49:22 + | +LL | let x: &Bottom = &t; + | ------- ^^ expected struct `Bottom`, found struct `Top` + | | + | expected due to this + | + = note: expected reference `&Bottom` + found reference `&Top` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0055, E0308. +For more information about an error, try `rustc --explain E0055`. |