diff options
Diffstat (limited to '')
117 files changed, 4348 insertions, 0 deletions
diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr new file mode 100644 index 000000000..35a65facb --- /dev/null +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr @@ -0,0 +1,39 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/arbitrary-self-types-not-object-safe.rs:33:32 + | +LL | fn foo(self: &Rc<Self>) -> usize; + | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` +... +LL | let x = Rc::new(5usize) as Rc<dyn Foo>; + | ^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo(self: &Rc<Self>) -> usize; + | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 + | +LL | fn foo(self: &Rc<Self>) -> usize; + | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` +... +LL | let x = Rc::new(5usize) as Rc<dyn Foo>; + | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo(self: &Rc<Self>) -> usize; + | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on + = note: required because of the requirements on the impl of `CoerceUnsized<Rc<dyn Foo>>` for `Rc<usize>` + = note: required by cast to type `Rc<dyn Foo>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..a74752cf8 --- /dev/null +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr @@ -0,0 +1,22 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 + | +LL | fn foo(self: &Rc<Self>) -> usize; + | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` +... +LL | let x = Rc::new(5usize) as Rc<dyn Foo>; + | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo(self: &Rc<Self>) -> usize; + | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on + = note: required because of the requirements on the impl of `CoerceUnsized<Rc<dyn Foo>>` for `Rc<usize>` + = note: required by cast to type `Rc<dyn Foo>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.rs b/src/test/ui/self/arbitrary-self-types-not-object-safe.rs new file mode 100644 index 000000000..40e8df339 --- /dev/null +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.rs @@ -0,0 +1,44 @@ +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + +use std::rc::Rc; + +trait Foo { + fn foo(self: &Rc<Self>) -> usize; +} + +trait Bar { + fn foo(self: &Rc<Self>) -> usize where Self: Sized; + fn bar(self: Rc<Self>) -> usize; +} + +impl Foo for usize { + fn foo(self: &Rc<Self>) -> usize { + **self + } +} + +impl Bar for usize { + fn foo(self: &Rc<Self>) -> usize { + **self + } + + fn bar(self: Rc<Self>) -> usize { + *self + } +} + +fn make_foo() { + let x = Rc::new(5usize) as Rc<dyn Foo>; + //[curr]~^ ERROR E0038 + //[curr]~| ERROR E0038 + //[object_safe_for_dispatch]~^^^ ERROR E0038 +} + +fn make_bar() { + let x = Rc::new(5usize) as Rc<dyn Bar>; + x.bar(); +} + +fn main() {} diff --git a/src/test/ui/self/arbitrary_self_types_nested.rs b/src/test/ui/self/arbitrary_self_types_nested.rs new file mode 100644 index 000000000..680196fbb --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_nested.rs @@ -0,0 +1,36 @@ +// run-pass + +use { + std::{ + rc::Rc, + sync::Arc, + }, +}; + +#[derive(Default)] +struct Ty; + +trait Trait { + fn receive_trait(self: &Arc<Rc<Box<Self>>>) -> u32; +} + +const TRAIT_MAGIC: u32 = 42; +const INHERENT_MAGIC: u32 = 1995; + +impl Trait for Ty { + fn receive_trait(self: &Arc<Rc<Box<Self>>>) -> u32 { + TRAIT_MAGIC + } +} + +impl Ty { + fn receive_inherent(self: &Arc<Rc<Box<Self>>>) -> u32 { + INHERENT_MAGIC + } +} + +fn main() { + let ty = <Arc<Rc<Box<Ty>>>>::default(); + assert_eq!(TRAIT_MAGIC, ty.receive_trait()); + assert_eq!(INHERENT_MAGIC, ty.receive_inherent()); +} diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime-async.rs new file mode 100644 index 000000000..f3474bc1f --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime-async.rs @@ -0,0 +1,35 @@ +// check-pass +// edition:2018 + +use std::pin::Pin; +use std::task::{Context, Poll}; + +struct Foo; + +impl Foo { + async fn pin_ref(self: Pin<&Self>) -> Pin<&Self> { self } + + async fn pin_mut(self: Pin<&mut Self>) -> Pin<&mut Self> { self } + + async fn pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> Pin<Pin<Pin<&Self>>> { self } + + async fn pin_ref_impl_trait(self: Pin<&Self>) -> impl Clone + '_ { self } + + fn b(self: Pin<&Foo>, f: &Foo) -> Pin<&Foo> { self } +} + +type Alias<T> = Pin<T>; +impl Foo { + async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> Alias<&Self> { self } +} + +// FIXME(Centril): extend with the rest of the non-`async fn` test +// when we allow `async fn`s inside traits and trait implementations. + +fn main() { + let mut foo = Foo; + { Pin::new(&foo).pin_ref() }; + { Pin::new(&mut foo).pin_mut() }; + { Pin::new(Pin::new(Pin::new(&foo))).pin_pin_pin_ref() }; + { Pin::new(&foo).pin_ref_impl_trait() }; +} diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime.rs new file mode 100644 index 000000000..300201388 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime.rs @@ -0,0 +1,60 @@ +// check-pass + +use std::pin::Pin; +use std::task::{Context, Poll}; + +struct Foo; + +impl Foo { + fn pin_ref(self: Pin<&Self>) -> Pin<&Self> { self } + + fn pin_mut(self: Pin<&mut Self>) -> Pin<&mut Self> { self } + + fn pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> Pin<Pin<Pin<&Self>>> { self } + + fn pin_ref_impl_trait(self: Pin<&Self>) -> impl Clone + '_ { self } + + fn b(self: Pin<&Foo>, f: &Foo) -> Pin<&Foo> { self } +} + +type Alias<T> = Pin<T>; +impl Foo { + fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> Alias<&Self> { self } +} + +struct Bar<T: Unpin, U: Unpin> { + field1: T, + field2: U, +} + +impl<T: Unpin, U: Unpin> Bar<T, U> { + fn fields(self: Pin<&mut Self>) -> (Pin<&mut T>, Pin<&mut U>) { + let this = self.get_mut(); + (Pin::new(&mut this.field1), Pin::new(&mut this.field2)) + } +} + +trait AsyncBufRead { + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) + -> Poll<std::io::Result<&[u8]>>; +} + +struct Baz(Vec<u8>); + +impl AsyncBufRead for Baz { + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) + -> Poll<std::io::Result<&[u8]>> + { + Poll::Ready(Ok(&self.get_mut().0)) + } +} + +fn main() { + let mut foo = Foo; + { Pin::new(&foo).pin_ref() }; + { Pin::new(&mut foo).pin_mut() }; + { Pin::new(Pin::new(Pin::new(&foo))).pin_pin_pin_ref() }; + { Pin::new(&foo).pin_ref_impl_trait() }; + let mut bar = Bar { field1: 0u8, field2: 1u8 }; + { Pin::new(&mut bar).fields() }; +} diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs new file mode 100644 index 000000000..a1e7f4aa8 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs @@ -0,0 +1,14 @@ +// edition:2018 + +use std::pin::Pin; + +struct Foo; + +impl Foo { + async fn f(self: Pin<&Self>) -> impl Clone { self } + //~^ ERROR: captures lifetime that does not appear in bounds +} + +fn main() { + { Pin::new(&Foo).f() }; +} diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr new file mode 100644 index 000000000..7e7d60d0f --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -0,0 +1,16 @@ +error[E0700]: hidden type for `impl Clone` captures lifetime that does not appear in bounds + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48 + | +LL | async fn f(self: Pin<&Self>) -> impl Clone { self } + | ----- ^^^^^^^^ + | | + | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here + | +help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound + | +LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs new file mode 100644 index 000000000..4db2fa7dc --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs @@ -0,0 +1,12 @@ +use std::pin::Pin; + +struct Foo; + +impl Foo { + fn f(self: Pin<&Self>) -> impl Clone { self } + //~^ ERROR: captures lifetime that does not appear in bounds +} + +fn main() { + { Pin::new(&Foo).f() }; +} diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr new file mode 100644 index 000000000..30d2250c0 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -0,0 +1,16 @@ +error[E0700]: hidden type for `impl Clone` captures lifetime that does not appear in bounds + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 + | +LL | fn f(self: Pin<&Self>) -> impl Clone { self } + | ----- ^^^^ + | | + | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here + | +help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound + | +LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs new file mode 100644 index 000000000..a2b7f0805 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs @@ -0,0 +1,21 @@ +// edition:2018 + +use std::pin::Pin; + +struct Foo; + +impl Foo { + async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + //~^ lifetime may not live long enough + + async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + //~^ lifetime may not live long enough +} + +type Alias<T> = Pin<T>; +impl Foo { + async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + //~^ lifetime may not live long enough +} + +fn main() {} diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr new file mode 100644 index 000000000..6180e1e0f --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr @@ -0,0 +1,39 @@ +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52 + | +LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + | - - ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f } + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:75 + | +LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + | - - ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64 + | +LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + | -- - ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` + | | | + | | let's call the lifetime of this reference `'1` + | lifetime `'a` defined here + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs new file mode 100644 index 000000000..f1a3fb018 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs @@ -0,0 +1,19 @@ +use std::pin::Pin; + +struct Foo; + +impl Foo { + fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + //~^ lifetime may not live long enough + + fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + //~^ lifetime may not live long enough +} + +type Alias<T> = Pin<T>; +impl Foo { + fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + //~^ lifetime may not live long enough +} + +fn main() {} diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr new file mode 100644 index 000000000..fccee5d43 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr @@ -0,0 +1,38 @@ +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:6:46 + | +LL | fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + | - - ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f } + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:9:69 + | +LL | fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + | - - ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:15:58 + | +LL | fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + | -- ---- has type `Pin<&'1 Foo>` ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` + | | + | lifetime `'a` defined here + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/self/arbitrary_self_types_pointers_and_wrappers.rs b/src/test/ui/self/arbitrary_self_types_pointers_and_wrappers.rs new file mode 100644 index 000000000..65fec3bec --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pointers_and_wrappers.rs @@ -0,0 +1,68 @@ +// run-pass +#![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)] +#![feature(rustc_attrs)] + +use std::{ + ops::{Deref, CoerceUnsized, DispatchFromDyn}, + marker::Unsize, +}; + +struct Ptr<T: ?Sized>(Box<T>); + +impl<T: ?Sized> Deref for Ptr<T> { + type Target = T; + + fn deref(&self) -> &T { + &*self.0 + } +} + +impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {} +impl<T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T> {} + +struct Wrapper<T: ?Sized>(T); + +impl<T: ?Sized> Deref for Wrapper<T> { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +impl<T: CoerceUnsized<U>, U> CoerceUnsized<Wrapper<U>> for Wrapper<T> {} +impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Wrapper<U>> for Wrapper<T> {} + + +trait Trait { + // This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable + // without unsized_locals), but wrappers arond `Self` currently are not. + // FIXME (mikeyhew) uncomment this when unsized rvalues object-safety is implemented + // fn wrapper(self: Wrapper<Self>) -> i32; + fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32; + fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32; + fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32; +} + +impl Trait for i32 { + fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32 { + **self + } + fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32 { + **self + } + fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32 { + ***self + } +} + +fn main() { + let pw = Ptr(Box::new(Wrapper(5))) as Ptr<Wrapper<dyn Trait>>; + assert_eq!(pw.ptr_wrapper(), 5); + + let wp = Wrapper(Ptr(Box::new(6))) as Wrapper<Ptr<dyn Trait>>; + assert_eq!(wp.wrapper_ptr(), 6); + + let wpw = Wrapper(Ptr(Box::new(Wrapper(7)))) as Wrapper<Ptr<Wrapper<dyn Trait>>>; + assert_eq!(wpw.wrapper_ptr_wrapper(), 7); +} diff --git a/src/test/ui/self/arbitrary_self_types_raw_pointer_struct.rs b/src/test/ui/self/arbitrary_self_types_raw_pointer_struct.rs new file mode 100644 index 000000000..0eab7617f --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_raw_pointer_struct.rs @@ -0,0 +1,28 @@ +// run-pass +#![feature(arbitrary_self_types)] + +use std::rc::Rc; + +struct Foo(String); + +impl Foo { + unsafe fn foo(self: *const Self) -> *const str { + (*self).0.as_ref() + } + + fn complicated_1(self: *const Rc<Self>) -> &'static str { + "Foo::complicated_1" + } + + unsafe fn complicated_2(self: Rc<*const Self>) -> *const str { + (**self).0.as_ref() + } +} + +fn main() { + let foo = Foo("abc123".into()); + assert_eq!("abc123", unsafe { &*(&foo as *const Foo).foo() }); + assert_eq!("Foo::complicated_1", std::ptr::null::<Rc<Foo>>().complicated_1()); + let rc = Rc::new(&foo as *const Foo); + assert_eq!("abc123", unsafe { &*rc.complicated_2()}); +} diff --git a/src/test/ui/self/arbitrary_self_types_raw_pointer_trait.rs b/src/test/ui/self/arbitrary_self_types_raw_pointer_trait.rs new file mode 100644 index 000000000..0a9370e6f --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_raw_pointer_trait.rs @@ -0,0 +1,61 @@ +// run-pass +#![feature(arbitrary_self_types)] + +use std::ptr; + +trait Foo { + fn foo(self: *const Self) -> &'static str; + + unsafe fn bar(self: *const Self) -> i64; + + unsafe fn complicated(self: *const *const Self) -> i64 where Self: Sized { + (*self).bar() + } +} + +impl Foo for i32 { + fn foo(self: *const Self) -> &'static str { + "I'm an i32!" + } + + unsafe fn bar(self: *const Self) -> i64 { + *self as i64 + } +} + +impl Foo for u32 { + fn foo(self: *const Self) -> &'static str { + "I'm a u32!" + } + + unsafe fn bar(self: *const Self) -> i64 { + *self as i64 + } +} + +fn main() { + let null_i32 = ptr::null::<i32>() as *const dyn Foo; + let null_u32 = ptr::null::<u32>() as *const dyn Foo; + + assert_eq!("I'm an i32!", null_i32.foo()); + assert_eq!("I'm a u32!", null_u32.foo()); + + let valid_i32 = 5i32; + let valid_i32_thin = &valid_i32 as *const i32; + assert_eq!("I'm an i32!", valid_i32_thin.foo()); + assert_eq!(5, unsafe { valid_i32_thin.bar() }); + assert_eq!(5, unsafe { (&valid_i32_thin as *const *const i32).complicated() }); + let valid_i32_fat = valid_i32_thin as *const dyn Foo; + assert_eq!("I'm an i32!", valid_i32_fat.foo()); + assert_eq!(5, unsafe { valid_i32_fat.bar() }); + + let valid_u32 = 18u32; + let valid_u32_thin = &valid_u32 as *const u32; + assert_eq!("I'm a u32!", valid_u32_thin.foo()); + assert_eq!(18, unsafe { valid_u32_thin.bar() }); + assert_eq!(18, unsafe { (&valid_u32_thin as *const *const u32).complicated() }); + let valid_u32_fat = valid_u32_thin as *const dyn Foo; + assert_eq!("I'm a u32!", valid_u32_fat.foo()); + assert_eq!(18, unsafe { valid_u32_fat.bar() }); + +} diff --git a/src/test/ui/self/arbitrary_self_types_silly.rs b/src/test/ui/self/arbitrary_self_types_silly.rs new file mode 100644 index 000000000..fb5f9012b --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_silly.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(arbitrary_self_types)] + +struct Foo; +struct Bar; + +impl std::ops::Deref for Bar { + type Target = Foo; + + fn deref(&self) -> &Foo { + &Foo + } +} + +impl Foo { + fn bar(self: Bar) -> i32 { 3 } +} + +fn main() { + assert_eq!(3, Bar.bar()); +} diff --git a/src/test/ui/self/arbitrary_self_types_stdlib_pointers.rs b/src/test/ui/self/arbitrary_self_types_stdlib_pointers.rs new file mode 100644 index 000000000..29563fbbd --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_stdlib_pointers.rs @@ -0,0 +1,54 @@ +// run-pass +#![feature(arbitrary_self_types)] +#![feature(rustc_attrs)] + +use std::{ + rc::Rc, + sync::Arc, + pin::Pin, +}; + +trait Trait { + fn by_rc(self: Rc<Self>) -> i64; + fn by_arc(self: Arc<Self>) -> i64; + fn by_pin_mut(self: Pin<&mut Self>) -> i64; + fn by_pin_box(self: Pin<Box<Self>>) -> i64; + fn by_pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> i64; +} + +impl Trait for i64 { + fn by_rc(self: Rc<Self>) -> i64 { + *self + } + fn by_arc(self: Arc<Self>) -> i64 { + *self + } + fn by_pin_mut(self: Pin<&mut Self>) -> i64 { + *self + } + fn by_pin_box(self: Pin<Box<Self>>) -> i64 { + *self + } + fn by_pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> i64 { + *self + } +} + +fn main() { + let rc = Rc::new(1i64) as Rc<dyn Trait>; + assert_eq!(1, rc.by_rc()); + + let arc = Arc::new(2i64) as Arc<dyn Trait>; + assert_eq!(2, arc.by_arc()); + + let mut value = 3i64; + let pin_mut = Pin::new(&mut value) as Pin<&mut dyn Trait>; + assert_eq!(3, pin_mut.by_pin_mut()); + + let pin_box = Into::<Pin<Box<i64>>>::into(Box::new(4i64)) as Pin<Box<dyn Trait>>; + assert_eq!(4, pin_box.by_pin_box()); + + let value = 5i64; + let pin_pin_pin_ref = Pin::new(Pin::new(Pin::new(&value))) as Pin<Pin<Pin<&dyn Trait>>>; + assert_eq!(5, pin_pin_pin_ref.by_pin_pin_pin_ref()); +} diff --git a/src/test/ui/self/arbitrary_self_types_struct.rs b/src/test/ui/self/arbitrary_self_types_struct.rs new file mode 100644 index 000000000..905ad83b6 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_struct.rs @@ -0,0 +1,24 @@ +// run-pass + +use std::rc::Rc; + +struct Foo { + x: i32, + y: i32, +} + +impl Foo { + fn x(self: &Rc<Self>) -> i32 { + self.x + } + + fn y(self: Rc<Self>) -> i32 { + self.y + } +} + +fn main() { + let foo = Rc::new(Foo {x: 3, y: 4}); + assert_eq!(3, foo.x()); + assert_eq!(4, foo.y()); +} diff --git a/src/test/ui/self/arbitrary_self_types_trait.rs b/src/test/ui/self/arbitrary_self_types_trait.rs new file mode 100644 index 000000000..973c7cae8 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_trait.rs @@ -0,0 +1,19 @@ +// run-pass + +use std::rc::Rc; + +trait Trait { + fn trait_method<'a>(self: &'a Box<Rc<Self>>) -> &'a [i32]; +} + +impl Trait for Vec<i32> { + fn trait_method<'a>(self: &'a Box<Rc<Self>>) -> &'a [i32] { + &***self + } +} + +fn main() { + let v = vec![1,2,3]; + + assert_eq!(&[1,2,3], Box::new(Rc::new(v)).trait_method()); +} diff --git a/src/test/ui/self/arbitrary_self_types_unsized_struct.rs b/src/test/ui/self/arbitrary_self_types_unsized_struct.rs new file mode 100644 index 000000000..d43f31328 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_unsized_struct.rs @@ -0,0 +1,16 @@ +// run-pass + +use std::rc::Rc; + +struct Foo<T: ?Sized>(T); + +impl Foo<[u8]> { + fn len(self: Rc<Self>) -> usize { + self.0.len() + } +} + +fn main() { + let rc = Rc::new(Foo([1u8,2,3])) as Rc<Foo<[u8]>>; + assert_eq!(3, rc.len()); +} diff --git a/src/test/ui/self/auxiliary/explicit_self_xcrate.rs b/src/test/ui/self/auxiliary/explicit_self_xcrate.rs new file mode 100644 index 000000000..25cdfa909 --- /dev/null +++ b/src/test/ui/self/auxiliary/explicit_self_xcrate.rs @@ -0,0 +1,15 @@ +pub trait Foo { + #[inline(always)] + fn f(&self); +} + +pub struct Bar { + pub x: String +} + +impl Foo for Bar { + #[inline(always)] + fn f(&self) { + println!("{}", (*self).x); + } +} diff --git a/src/test/ui/self/builtin-superkinds-self-type.rs b/src/test/ui/self/builtin-superkinds-self-type.rs new file mode 100644 index 000000000..c56542bb4 --- /dev/null +++ b/src/test/ui/self/builtin-superkinds-self-type.rs @@ -0,0 +1,20 @@ +// run-pass +// Tests the ability for the Self type in default methods to use +// capabilities granted by builtin kinds as supertraits. + + +use std::sync::mpsc::{Sender, channel}; + +trait Foo : Send + Sized + 'static { + fn foo(self, tx: Sender<Self>) { + tx.send(self).unwrap(); + } +} + +impl <T: Send + 'static> Foo for T { } + +pub fn main() { + let (tx, rx) = channel(); + 1193182.foo(tx); + assert_eq!(rx.recv().unwrap(), 1193182); +} diff --git a/src/test/ui/self/by-value-self-in-mut-slot.rs b/src/test/ui/self/by-value-self-in-mut-slot.rs new file mode 100644 index 000000000..267afd1dc --- /dev/null +++ b/src/test/ui/self/by-value-self-in-mut-slot.rs @@ -0,0 +1,22 @@ +// run-pass + +struct X { + a: isize +} + +trait Changer { + fn change(self) -> Self; +} + +impl Changer for X { + fn change(mut self) -> X { + self.a = 55; + self + } +} + +pub fn main() { + let x = X { a: 32 }; + let new_x = x.change(); + assert_eq!(new_x.a, 55); +} diff --git a/src/test/ui/self/class-missing-self.rs b/src/test/ui/self/class-missing-self.rs new file mode 100644 index 000000000..8ad347d20 --- /dev/null +++ b/src/test/ui/self/class-missing-self.rs @@ -0,0 +1,16 @@ +struct Cat { + meows : usize, +} + +impl Cat { + fn sleep(&self) { loop{} } + fn meow(&self) { + println!("Meow"); + meows += 1; //~ ERROR cannot find value `meows` in this scope + sleep(); //~ ERROR cannot find function `sleep` in this + } + +} + + + fn main() { } diff --git a/src/test/ui/self/class-missing-self.stderr b/src/test/ui/self/class-missing-self.stderr new file mode 100644 index 000000000..d501200d7 --- /dev/null +++ b/src/test/ui/self/class-missing-self.stderr @@ -0,0 +1,20 @@ +error[E0425]: cannot find value `meows` in this scope + --> $DIR/class-missing-self.rs:9:7 + | +LL | meows += 1; + | ^^^^^ help: you might have meant to use the available field: `self.meows` + +error[E0425]: cannot find function `sleep` in this scope + --> $DIR/class-missing-self.rs:10:7 + | +LL | sleep(); + | ^^^^^ not found in this scope + | +help: consider importing this function + | +LL | use std::thread::sleep; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/self/elision/README.md b/src/test/ui/self/elision/README.md new file mode 100644 index 000000000..3bd7a6c00 --- /dev/null +++ b/src/test/ui/self/elision/README.md @@ -0,0 +1,75 @@ +Test cases intended to document behavior and try to exhaustively +explore the combinations. + +## Confidence + +These tests are not yet considered 100% normative, in that some +aspects of the current behavior are not desirable. This is expressed +in the "confidence" field in the following table. Values: + +| Confidence | Interpretation | +| --- | --- | +| 100% | this will remain recommended behavior | +| 75% | unclear whether we will continue to accept this | +| 50% | this will likely be deprecated but remain valid | +| 25% | this could change in the future | +| 0% | this is definitely bogus and will likely change in the future in *some* way | + +## Tests + +| Test file | `Self` type | Pattern | Current elision behavior | Confidence | +| --- | --- | --- | --- | --- | +| `self.rs` | `Struct` | `Self` | ignore `self` parameter | 100% | +| `struct.rs` | `Struct` | `Struct` | ignore `self` parameter | 100% | +| `alias.rs` | `Struct` | `Alias` | ignore `self` parameter | 100% | +| `ref-self.rs` | `Struct` | `&Self` | take lifetime from `&Self` | 100% | +| `ref-mut-self.rs` | `Struct` | `&mut Self` | take lifetime from `&mut Self` | 100% | +| `ref-struct.rs` | `Struct` | `&Struct` | take lifetime from `&Self` | 50% | +| `ref-mut-struct.rs` | `Struct` | `&mut Struct` | take lifetime from `&mut Self` | 50% | +| `ref-alias.rs` | `Struct` | `&Alias` | ignore `Alias` | 0% | +| `ref-mut-alias.rs` | `Struct` | `&mut Alias` | ignore `Alias` | 0% | +| `lt-self.rs` | `Struct<'a>` | `Self` | ignore `Self` (and hence `'a`) | 25% | +| `lt-struct.rs` | `Struct<'a>` | `Self` | ignore `Self` (and hence `'a`) | 0% | +| `lt-alias.rs` | `Alias<'a>` | `Self` | ignore `Self` (and hence `'a`) | 0% | +| `lt-ref-self.rs` | `Struct<'a>` | `&Self` | take lifetime from `&Self` | 75% | + +In each case, we test the following patterns: + +- `self: XXX` +- `self: Box<XXX>` +- `self: Pin<XXX>` +- `self: Box<Box<XXX>>` +- `self: Box<Pin<XXX>>` + +In the non-reference cases, `Pin` causes errors so we substitute `Rc`. + +### `async fn` + +For each of the tests above we also check that `async fn` behaves as an `fn` would. +These tests are in files named `*-async.rs`. + +Legends: +- ✓ ⟹ Yes / Pass +- X ⟹ No +- α ⟹ lifetime mismatch +- β ⟹ cannot infer an appropriate lifetime +- γ ⟹ missing lifetime specifier + +| `async` file | Pass? | Conforms to `fn`? | How does it diverge? <br/> `fn` ⟶ `async fn` | +| --- | --- | --- | --- | +| `self-async.rs` | ✓ | ✓ | N/A | +| `struct-async.rs`| ✓ | ✓ | N/A | +| `alias-async.rs`| ✓ | ✓ | N/A | +| `assoc-async.rs`| ✓ | ✓ | N/A | +| `ref-self-async.rs` | X | ✓ | N/A | +| `ref-mut-self-async.rs` | X | ✓ | N/A | +| `ref-struct-async.rs` | X | ✓ | N/A | +| `ref-mut-struct-async.rs` | X | ✓ | N/A | +| `ref-alias-async.rs` | ✓ | ✓ | N/A | +| `ref-assoc-async.rs` | ✓ | ✓ | N/A | +| `ref-mut-alias-async.rs` | ✓ | ✓ | N/A | +| `lt-self-async.rs` | ✓ | ✓ | N/A +| `lt-struct-async.rs` | ✓ | ✓ | N/A +| `lt-alias-async.rs` | ✓ | ✓ | N/A +| `lt-assoc-async.rs` | ✓ | ✓ | N/A +| `lt-ref-self-async.rs` | X | ✓ | N/A | diff --git a/src/test/ui/self/elision/alias-async.rs b/src/test/ui/self/elision/alias-async.rs new file mode 100644 index 000000000..7c0dd0686 --- /dev/null +++ b/src/test/ui/self/elision/alias-async.rs @@ -0,0 +1,36 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + + async fn alias(self: Alias, f: &u32) -> &u32 { + f + } + + async fn box_Alias(self: Box<Alias>, f: &u32) -> &u32 { + f + } + + async fn rc_Alias(self: Rc<Alias>, f: &u32) -> &u32 { + f + } + + async fn box_box_Alias(self: Box<Box<Alias>>, f: &u32) -> &u32 { + f + } + + async fn box_rc_Alias(self: Box<Rc<Alias>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/alias.rs b/src/test/ui/self/elision/alias.rs new file mode 100644 index 000000000..0c801d702 --- /dev/null +++ b/src/test/ui/self/elision/alias.rs @@ -0,0 +1,35 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + + fn alias(self: Alias, f: &u32) -> &u32 { + f + } + + fn box_Alias(self: Box<Alias>, f: &u32) -> &u32 { + f + } + + fn rc_Alias(self: Rc<Alias>, f: &u32) -> &u32 { + f + } + + fn box_box_Alias(self: Box<Box<Alias>>, f: &u32) -> &u32 { + f + } + + fn box_rc_Alias(self: Box<Rc<Alias>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/assoc-async.rs b/src/test/ui/self/elision/assoc-async.rs new file mode 100644 index 000000000..363b7fc2a --- /dev/null +++ b/src/test/ui/self/elision/assoc-async.rs @@ -0,0 +1,40 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +trait Trait { + type AssocType; +} + +struct Struct { } + +impl Trait for Struct { + type AssocType = Self; +} + +impl Struct { + async fn assoc(self: <Struct as Trait>::AssocType, f: &u32) -> &u32 { + f + } + + async fn box_AssocType(self: Box<<Struct as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn rc_AssocType(self: Rc<<Struct as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn box_box_AssocType(self: Box<Box<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } + + async fn box_rc_AssocType(self: Box<Rc<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/assoc.rs b/src/test/ui/self/elision/assoc.rs new file mode 100644 index 000000000..fa39a2b47 --- /dev/null +++ b/src/test/ui/self/elision/assoc.rs @@ -0,0 +1,39 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +trait Trait { + type AssocType; +} + +struct Struct { } + +impl Trait for Struct { + type AssocType = Self; +} + +impl Struct { + fn assoc(self: <Struct as Trait>::AssocType, f: &u32) -> &u32 { + f + } + + fn box_AssocType(self: Box<<Struct as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + fn rc_AssocType(self: Rc<<Struct as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + fn box_box_AssocType(self: Box<Box<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } + + fn box_rc_AssocType(self: Box<Rc<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-alias-async.rs b/src/test/ui/self/elision/lt-alias-async.rs new file mode 100644 index 000000000..3a6f8471e --- /dev/null +++ b/src/test/ui/self/elision/lt-alias-async.rs @@ -0,0 +1,38 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct<'a> { x: &'a u32 } + +type Alias<'a> = Struct<'a>; + +impl<'a> Alias<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Alias(self: Alias<'a>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Alias(self: Box<Alias<'a>>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Alias(self: Box<Box<Alias<'a>>>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Alias(self: Rc<Alias<'a>>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Alias(self: Box<Rc<Alias<'a>>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-alias.rs b/src/test/ui/self/elision/lt-alias.rs new file mode 100644 index 000000000..bbba88e4e --- /dev/null +++ b/src/test/ui/self/elision/lt-alias.rs @@ -0,0 +1,37 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct<'a> { x: &'a u32 } + +type Alias<'a> = Struct<'a>; + +impl<'a> Alias<'a> { + fn take_self(self, f: &u32) -> &u32 { + f + } + + fn take_Alias(self: Alias<'a>, f: &u32) -> &u32 { + f + } + + fn take_Box_Alias(self: Box<Alias<'a>>, f: &u32) -> &u32 { + f + } + + fn take_Box_Box_Alias(self: Box<Box<Alias<'a>>>, f: &u32) -> &u32 { + f + } + + fn take_Rc_Alias(self: Rc<Alias<'a>>, f: &u32) -> &u32 { + f + } + + fn take_Box_Rc_Alias(self: Box<Rc<Alias<'a>>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-assoc-async.rs b/src/test/ui/self/elision/lt-assoc-async.rs new file mode 100644 index 000000000..0d3ff630d --- /dev/null +++ b/src/test/ui/self/elision/lt-assoc-async.rs @@ -0,0 +1,50 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +trait Trait { + type AssocType; +} + +struct Struct<'a> { x: &'a u32 } + +impl<'a> Trait for Struct<'a> { + type AssocType = Self; +} + +impl<'a> Struct<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_AssocType(self: <Struct<'a> as Trait>::AssocType, f: &u32) -> &u32 { + f + } + + async fn take_Box_AssocType(self: Box<<Struct<'a> as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_AssocType( + self: Box<Box<<Struct<'a> as Trait>::AssocType>>, + f: &u32 + ) -> &u32 { + f + } + + async fn take_Rc_AssocType(self: Rc<<Struct<'a> as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_AssocType( + self: Box<Rc<<Struct<'a> as Trait>::AssocType>>, + f: &u32 + ) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-assoc.rs b/src/test/ui/self/elision/lt-assoc.rs new file mode 100644 index 000000000..8f3543135 --- /dev/null +++ b/src/test/ui/self/elision/lt-assoc.rs @@ -0,0 +1,43 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +trait Trait { + type AssocType; +} + +struct Struct<'a> { x: &'a u32 } + +impl<'a> Trait for Struct<'a> { + type AssocType = Self; +} + +impl<'a> Struct<'a> { + fn take_self(self, f: &u32) -> &u32 { + f + } + + fn take_AssocType(self: <Struct<'a> as Trait>::AssocType, f: &u32) -> &u32 { + f + } + + fn take_Box_AssocType(self: Box<<Struct<'a> as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + fn take_Box_Box_AssocType(self: Box<Box<<Struct<'a> as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } + + fn take_Rc_AssocType(self: Rc<<Struct<'a> as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + fn take_Box_Rc_AssocType(self: Box<Rc<<Struct<'a> as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-ref-self-async.rs b/src/test/ui/self/elision/lt-ref-self-async.rs new file mode 100644 index 000000000..a2325ba7f --- /dev/null +++ b/src/test/ui/self/elision/lt-ref-self-async.rs @@ -0,0 +1,45 @@ +// edition:2018 + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct<'a> { data: &'a u32 } + +impl<'a> Struct<'a> { + // Test using `&self` sugar: + + async fn ref_self(&self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + // Test using `&Self` explicitly: + + async fn ref_Self(self: &Self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-ref-self-async.stderr b/src/test/ui/self/elision/lt-ref-self-async.stderr new file mode 100644 index 000000000..787afd4dc --- /dev/null +++ b/src/test/ui/self/elision/lt-ref-self-async.stderr @@ -0,0 +1,92 @@ +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:13:9 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:20:9 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:25:9 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:30:9 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:35:9 + | +LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:40:9 + | +LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_pin_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/self/elision/lt-ref-self.rs b/src/test/ui/self/elision/lt-ref-self.rs new file mode 100644 index 000000000..d37ed5acb --- /dev/null +++ b/src/test/ui/self/elision/lt-ref-self.rs @@ -0,0 +1,43 @@ +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct<'a> { data: &'a u32 } + +impl<'a> Struct<'a> { + // Test using `&self` sugar: + + fn ref_self(&self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + // Test using `&Self` explicitly: + + fn ref_Self(self: &Self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-ref-self.stderr b/src/test/ui/self/elision/lt-ref-self.stderr new file mode 100644 index 000000000..49af638e4 --- /dev/null +++ b/src/test/ui/self/elision/lt-ref-self.stderr @@ -0,0 +1,92 @@ +error: lifetime may not live long enough + --> $DIR/lt-ref-self.rs:11:9 + | +LL | fn ref_self(&self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self.rs:18:9 + | +LL | fn ref_Self(self: &Self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self.rs:23:9 + | +LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self.rs:28:9 + | +LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self.rs:33:9 + | +LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self.rs:38:9 + | +LL | fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_pin_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/self/elision/lt-self-async.rs b/src/test/ui/self/elision/lt-self-async.rs new file mode 100644 index 000000000..4cedaf79d --- /dev/null +++ b/src/test/ui/self/elision/lt-self-async.rs @@ -0,0 +1,49 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::pin::Pin; +use std::rc::Rc; + +struct Struct<'a> { + x: &'a u32 +} + +impl<'a> Struct<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Self(self: Self, f: &u32) -> &u32 { + f + } + + async fn take_Box_Self(self: Box<Self>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Self(self: Box<Box<Self>>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Self(self: Rc<Self>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Self(self: Box<Rc<Self>>, f: &u32) -> &u32 { + f + } + + // N/A + //fn take_Pin_Self(self: Pin<Self>, f: &u32) -> &u32 { + // f + //} + + // N/A + //fn take_Box_Pin_Self(self: Box<Pin<Self>>, f: &u32) -> &u32 { + // f + //} +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-self.rs b/src/test/ui/self/elision/lt-self.rs new file mode 100644 index 000000000..cf74f892b --- /dev/null +++ b/src/test/ui/self/elision/lt-self.rs @@ -0,0 +1,48 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; +use std::rc::Rc; + +struct Struct<'a> { + x: &'a u32 +} + +impl<'a> Struct<'a> { + fn take_self(self, f: &u32) -> &u32 { + f + } + + fn take_Self(self: Self, f: &u32) -> &u32 { + f + } + + fn take_Box_Self(self: Box<Self>, f: &u32) -> &u32 { + f + } + + fn take_Box_Box_Self(self: Box<Box<Self>>, f: &u32) -> &u32 { + f + } + + fn take_Rc_Self(self: Rc<Self>, f: &u32) -> &u32 { + f + } + + fn take_Box_Rc_Self(self: Box<Rc<Self>>, f: &u32) -> &u32 { + f + } + + // N/A + //fn take_Pin_Self(self: Pin<Self>, f: &u32) -> &u32 { + // f + //} + + // N/A + //fn take_Box_Pin_Self(self: Box<Pin<Self>>, f: &u32) -> &u32 { + // f + //} +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-struct-async.rs b/src/test/ui/self/elision/lt-struct-async.rs new file mode 100644 index 000000000..abbee7fdf --- /dev/null +++ b/src/test/ui/self/elision/lt-struct-async.rs @@ -0,0 +1,36 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct<'a> { x: &'a u32 } + +impl<'a> Struct<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Struct(self: Struct<'a>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Struct(self: Box<Struct<'a>>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Struct(self: Box<Box<Struct<'a>>>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Struct(self: Rc<Struct<'a>>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Struct(self: Box<Rc<Struct<'a>>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-struct.rs b/src/test/ui/self/elision/lt-struct.rs new file mode 100644 index 000000000..799c6c079 --- /dev/null +++ b/src/test/ui/self/elision/lt-struct.rs @@ -0,0 +1,35 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct<'a> { x: &'a u32 } + +impl<'a> Struct<'a> { + fn take_self(self, f: &u32) -> &u32 { + f + } + + fn take_Struct(self: Struct<'a>, f: &u32) -> &u32 { + f + } + + fn take_Box_Struct(self: Box<Struct<'a>>, f: &u32) -> &u32 { + f + } + + fn take_Box_Box_Struct(self: Box<Box<Struct<'a>>>, f: &u32) -> &u32 { + f + } + + fn take_Rc_Struct(self: Rc<Struct<'a>>, f: &u32) -> &u32 { + f + } + + fn take_Box_Rc_Struct(self: Box<Rc<Struct<'a>>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/multiple-ref-self-async.rs b/src/test/ui/self/elision/multiple-ref-self-async.rs new file mode 100644 index 000000000..be073c6ed --- /dev/null +++ b/src/test/ui/self/elision/multiple-ref-self-async.rs @@ -0,0 +1,44 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::marker::PhantomData; +use std::ops::Deref; +use std::pin::Pin; + +struct Struct { } + +struct Wrap<T, P>(T, PhantomData<P>); + +impl<T, P> Deref for Wrap<T, P> { + type Target = T; + fn deref(&self) -> &T { &self.0 } +} + +impl Struct { + // Test using multiple `&Self`: + + async fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 { + f + } + + async fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 { + f + } + + async fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 { + f + } + + async fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 { + f + } + + async fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/multiple-ref-self.rs b/src/test/ui/self/elision/multiple-ref-self.rs new file mode 100644 index 000000000..f39613d0c --- /dev/null +++ b/src/test/ui/self/elision/multiple-ref-self.rs @@ -0,0 +1,43 @@ +// check-pass + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::marker::PhantomData; +use std::ops::Deref; +use std::pin::Pin; + +struct Struct { } + +struct Wrap<T, P>(T, PhantomData<P>); + +impl<T, P> Deref for Wrap<T, P> { + type Target = T; + fn deref(&self) -> &T { &self.0 } +} + +impl Struct { + // Test using multiple `&Self`: + + fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 { + f + } + + fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 { + f + } + + fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 { + f + } + + fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 { + f + } + + fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-alias-async.rs b/src/test/ui/self/elision/ref-alias-async.rs new file mode 100644 index 000000000..15f16525b --- /dev/null +++ b/src/test/ui/self/elision/ref-alias-async.rs @@ -0,0 +1,39 @@ +// edition:2018 +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + // + // FIXME. We currently fail to recognize this as the self type, which + // feels like a bug. + + async fn ref_Alias(self: &Alias, f: &u32) -> &u32 { + f + } + + async fn box_ref_Alias(self: Box<&Alias>, f: &u32) -> &u32 { + f + } + + async fn pin_ref_Alias(self: Pin<&Alias>, f: &u32) -> &u32 { + f + } + + async fn box_box_ref_Alias(self: Box<Box<&Alias>>, f: &u32) -> &u32 { + f + } + + async fn box_pin_ref_Alias(self: Box<Pin<&Alias>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-alias.rs b/src/test/ui/self/elision/ref-alias.rs new file mode 100644 index 000000000..341f5b52d --- /dev/null +++ b/src/test/ui/self/elision/ref-alias.rs @@ -0,0 +1,38 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + // + // FIXME. We currently fail to recognize this as the self type, which + // feels like a bug. + + fn ref_Alias(self: &Alias, f: &u32) -> &u32 { + f + } + + fn box_ref_Alias(self: Box<&Alias>, f: &u32) -> &u32 { + f + } + + fn pin_ref_Alias(self: Pin<&Alias>, f: &u32) -> &u32 { + f + } + + fn box_box_ref_Alias(self: Box<Box<&Alias>>, f: &u32) -> &u32 { + f + } + + fn box_pin_ref_Alias(self: Box<Pin<&Alias>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-assoc-async.rs b/src/test/ui/self/elision/ref-assoc-async.rs new file mode 100644 index 000000000..ad10d8ba4 --- /dev/null +++ b/src/test/ui/self/elision/ref-assoc-async.rs @@ -0,0 +1,40 @@ +// edition:2018 +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; + +trait Trait { + type AssocType; +} + +struct Struct { } + +impl Trait for Struct { + type AssocType = Self; +} + +impl Struct { + async fn ref_AssocType(self: &<Struct as Trait>::AssocType, f: &u32) -> &u32 { + f + } + + async fn box_ref_AssocType(self: Box<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn pin_ref_AssocType(self: Pin<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn box_box_ref_AssocType(self: Box<Box<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } + + async fn box_pin_ref_AssocType(self: Box<Pin<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-assoc.rs b/src/test/ui/self/elision/ref-assoc.rs new file mode 100644 index 000000000..2f02cb5f3 --- /dev/null +++ b/src/test/ui/self/elision/ref-assoc.rs @@ -0,0 +1,39 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; + +trait Trait { + type AssocType; +} + +struct Struct { } + +impl Trait for Struct { + type AssocType = Self; +} + +impl Struct { + fn ref_AssocType(self: &<Struct as Trait>::AssocType, f: &u32) -> &u32 { + f + } + + fn box_ref_AssocType(self: Box<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + fn pin_ref_AssocType(self: Pin<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + fn box_box_ref_AssocType(self: Box<Box<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } + + fn box_pin_ref_AssocType(self: Box<Pin<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-alias-async.rs b/src/test/ui/self/elision/ref-mut-alias-async.rs new file mode 100644 index 000000000..2c3f971d2 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-alias-async.rs @@ -0,0 +1,36 @@ +// edition:2018 +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + + async fn ref_Alias(self: &mut Alias, f: &u32) -> &u32 { + f + } + + async fn box_ref_Alias(self: Box<&mut Alias>, f: &u32) -> &u32 { + f + } + + async fn pin_ref_Alias(self: Pin<&mut Alias>, f: &u32) -> &u32 { + f + } + + async fn box_box_ref_Alias(self: Box<Box<&mut Alias>>, f: &u32) -> &u32 { + f + } + + async fn box_pin_ref_Alias(self: Box<Pin<&mut Alias>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-alias.rs b/src/test/ui/self/elision/ref-mut-alias.rs new file mode 100644 index 000000000..ce1ab3ffc --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-alias.rs @@ -0,0 +1,35 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + + fn ref_Alias(self: &mut Alias, f: &u32) -> &u32 { + f + } + + fn box_ref_Alias(self: Box<&mut Alias>, f: &u32) -> &u32 { + f + } + + fn pin_ref_Alias(self: Pin<&mut Alias>, f: &u32) -> &u32 { + f + } + + fn box_box_ref_Alias(self: Box<Box<&mut Alias>>, f: &u32) -> &u32 { + f + } + + fn box_pin_ref_Alias(self: Box<Pin<&mut Alias>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-self-async.rs b/src/test/ui/self/elision/ref-mut-self-async.rs new file mode 100644 index 000000000..e07bc8564 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-self-async.rs @@ -0,0 +1,45 @@ +// edition:2018 + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&mut self` sugar: + + async fn ref_self(&mut self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + // Test using `&mut Self` explicitly: + + async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-self-async.stderr b/src/test/ui/self/elision/ref-mut-self-async.stderr new file mode 100644 index 000000000..dff50aee9 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-self-async.stderr @@ -0,0 +1,92 @@ +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:13:9 + | +LL | async fn ref_self(&mut self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:20:9 + | +LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:25:9 + | +LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:30:9 + | +LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:35:9 + | +LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_box_ref_Self<'a>(self: Box<Box<&'a mut Self>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:40:9 + | +LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_pin_ref_Self<'a>(self: Box<Pin<&'a mut Self>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/self/elision/ref-mut-self.rs b/src/test/ui/self/elision/ref-mut-self.rs new file mode 100644 index 000000000..bb82e6be7 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-self.rs @@ -0,0 +1,43 @@ +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&mut self` sugar: + + fn ref_self(&mut self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + // Test using `&mut Self` explicitly: + + fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-self.stderr b/src/test/ui/self/elision/ref-mut-self.stderr new file mode 100644 index 000000000..ccf183016 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-self.stderr @@ -0,0 +1,92 @@ +error: lifetime may not live long enough + --> $DIR/ref-mut-self.rs:11:9 + | +LL | fn ref_self(&mut self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self.rs:18:9 + | +LL | fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self.rs:23:9 + | +LL | fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self.rs:28:9 + | +LL | fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self.rs:33:9 + | +LL | fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_box_ref_Self<'a>(self: Box<Box<&'a mut Self>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self.rs:38:9 + | +LL | fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_pin_ref_Self<'a>(self: Box<Pin<&'a mut Self>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/self/elision/ref-mut-struct-async.rs b/src/test/ui/self/elision/ref-mut-struct-async.rs new file mode 100644 index 000000000..392bf1d6b --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-struct-async.rs @@ -0,0 +1,38 @@ +// edition:2018 + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&mut Struct` explicitly: + + async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-struct-async.stderr b/src/test/ui/self/elision/ref-mut-struct-async.stderr new file mode 100644 index 000000000..5b7ad026f --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-struct-async.stderr @@ -0,0 +1,77 @@ +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:13:9 + | +LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:18:9 + | +LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:23:9 + | +LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:28:9 + | +LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_box_ref_Struct<'a>(self: Box<Box<&'a mut Struct>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:33:9 + | +LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_pin_ref_Struct<'a>(self: Box<Pin<&'a mut Struct>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/self/elision/ref-mut-struct.rs b/src/test/ui/self/elision/ref-mut-struct.rs new file mode 100644 index 000000000..ca8bd8da1 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-struct.rs @@ -0,0 +1,36 @@ +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&mut Struct` explicitly: + + fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-struct.stderr b/src/test/ui/self/elision/ref-mut-struct.stderr new file mode 100644 index 000000000..b9c71e843 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-struct.stderr @@ -0,0 +1,77 @@ +error: lifetime may not live long enough + --> $DIR/ref-mut-struct.rs:11:9 + | +LL | fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct.rs:16:9 + | +LL | fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct.rs:21:9 + | +LL | fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct.rs:26:9 + | +LL | fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_box_ref_Struct<'a>(self: Box<Box<&'a mut Struct>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct.rs:31:9 + | +LL | fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_pin_ref_Struct<'a>(self: Box<Pin<&'a mut Struct>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/self/elision/ref-self-async.rs b/src/test/ui/self/elision/ref-self-async.rs new file mode 100644 index 000000000..b0133ec1b --- /dev/null +++ b/src/test/ui/self/elision/ref-self-async.rs @@ -0,0 +1,60 @@ +// edition:2018 + +#![allow(non_snake_case)] +#![feature(arbitrary_self_types)] + +use std::marker::PhantomData; +use std::ops::Deref; +use std::pin::Pin; + +struct Struct { } + +struct Wrap<T, P>(T, PhantomData<P>); + +impl<T, P> Deref for Wrap<T, P> { + type Target = T; + fn deref(&self) -> &T { &self.0 } +} + +impl Struct { + // Test using `&self` sugar: + + async fn ref_self(&self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + // Test using `&Self` explicitly: + + async fn ref_Self(self: &Self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-self-async.stderr b/src/test/ui/self/elision/ref-self-async.stderr new file mode 100644 index 000000000..26ef9779b --- /dev/null +++ b/src/test/ui/self/elision/ref-self-async.stderr @@ -0,0 +1,107 @@ +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:23:9 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:30:9 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:35:9 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:40:9 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:45:9 + | +LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:50:9 + | +LL | async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_pin_ref_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:55:9 + | +LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &u8 { + | ++++ ++ ++ + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/self/elision/ref-self.rs b/src/test/ui/self/elision/ref-self.rs new file mode 100644 index 000000000..dd07fe1b0 --- /dev/null +++ b/src/test/ui/self/elision/ref-self.rs @@ -0,0 +1,58 @@ +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::marker::PhantomData; +use std::ops::Deref; +use std::pin::Pin; + +struct Struct { } + +struct Wrap<T, P>(T, PhantomData<P>); + +impl<T, P> Deref for Wrap<T, P> { + type Target = T; + fn deref(&self) -> &T { &self.0 } +} + +impl Struct { + // Test using `&self` sugar: + + fn ref_self(&self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + // Test using `&Self` explicitly: + + fn ref_Self(self: &Self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-self.stderr b/src/test/ui/self/elision/ref-self.stderr new file mode 100644 index 000000000..32448f3a6 --- /dev/null +++ b/src/test/ui/self/elision/ref-self.stderr @@ -0,0 +1,107 @@ +error: lifetime may not live long enough + --> $DIR/ref-self.rs:21:9 + | +LL | fn ref_self(&self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self.rs:28:9 + | +LL | fn ref_Self(self: &Self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self.rs:33:9 + | +LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self.rs:38:9 + | +LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self.rs:43:9 + | +LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self.rs:48:9 + | +LL | fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_pin_ref_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self.rs:53:9 + | +LL | fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &u8 { + | ++++ ++ ++ + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/self/elision/ref-struct-async.rs b/src/test/ui/self/elision/ref-struct-async.rs new file mode 100644 index 000000000..0be748745 --- /dev/null +++ b/src/test/ui/self/elision/ref-struct-async.rs @@ -0,0 +1,38 @@ +// edition:2018 + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&Struct` explicitly: + + async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-struct-async.stderr b/src/test/ui/self/elision/ref-struct-async.stderr new file mode 100644 index 000000000..edb5c54ab --- /dev/null +++ b/src/test/ui/self/elision/ref-struct-async.stderr @@ -0,0 +1,77 @@ +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:13:9 + | +LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:18:9 + | +LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:23:9 + | +LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:28:9 + | +LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_box_ref_Struct<'a>(self: Box<Box<&'a Struct>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:33:9 + | +LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_pin_Struct<'a>(self: Box<Pin<&'a Struct>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/self/elision/ref-struct.rs b/src/test/ui/self/elision/ref-struct.rs new file mode 100644 index 000000000..13a42cd1a --- /dev/null +++ b/src/test/ui/self/elision/ref-struct.rs @@ -0,0 +1,36 @@ +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&Struct` explicitly: + + fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-struct.stderr b/src/test/ui/self/elision/ref-struct.stderr new file mode 100644 index 000000000..4492ed4aa --- /dev/null +++ b/src/test/ui/self/elision/ref-struct.stderr @@ -0,0 +1,77 @@ +error: lifetime may not live long enough + --> $DIR/ref-struct.rs:11:9 + | +LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct.rs:16:9 + | +LL | fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct.rs:21:9 + | +LL | fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct.rs:26:9 + | +LL | fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_box_ref_Struct<'a>(self: Box<Box<&'a Struct>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct.rs:31:9 + | +LL | fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_pin_Struct<'a>(self: Box<Pin<&'a Struct>>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/self/elision/self-async.rs b/src/test/ui/self/elision/self-async.rs new file mode 100644 index 000000000..eb01cfc97 --- /dev/null +++ b/src/test/ui/self/elision/self-async.rs @@ -0,0 +1,36 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +impl Struct { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Self(self: Self, f: &u32) -> &u32 { + f + } + + async fn take_Box_Self(self: Box<Self>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Self(self: Box<Box<Self>>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Self(self: Rc<Self>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Self(self: Box<Rc<Self>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/self.rs b/src/test/ui/self/elision/self.rs new file mode 100644 index 000000000..574b7e7c9 --- /dev/null +++ b/src/test/ui/self/elision/self.rs @@ -0,0 +1,35 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +impl Struct { + fn take_self(self, f: &u32) -> &u32 { + f + } + + fn take_Self(self: Self, f: &u32) -> &u32 { + f + } + + fn take_Box_Self(self: Box<Self>, f: &u32) -> &u32 { + f + } + + fn take_Box_Box_Self(self: Box<Box<Self>>, f: &u32) -> &u32 { + f + } + + fn take_Rc_Self(self: Rc<Self>, f: &u32) -> &u32 { + f + } + + fn take_Box_Rc_Self(self: Box<Rc<Self>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/struct-async.rs b/src/test/ui/self/elision/struct-async.rs new file mode 100644 index 000000000..e018e0daf --- /dev/null +++ b/src/test/ui/self/elision/struct-async.rs @@ -0,0 +1,32 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +impl Struct { + async fn ref_Struct(self: Struct, f: &u32) -> &u32 { + f + } + + async fn box_Struct(self: Box<Struct>, f: &u32) -> &u32 { + f + } + + async fn rc_Struct(self: Rc<Struct>, f: &u32) -> &u32 { + f + } + + async fn box_box_Struct(self: Box<Box<Struct>>, f: &u32) -> &u32 { + f + } + + async fn box_rc_Struct(self: Box<Rc<Struct>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/struct.rs b/src/test/ui/self/elision/struct.rs new file mode 100644 index 000000000..d1ac99d13 --- /dev/null +++ b/src/test/ui/self/elision/struct.rs @@ -0,0 +1,31 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +impl Struct { + fn ref_Struct(self: Struct, f: &u32) -> &u32 { + f + } + + fn box_Struct(self: Box<Struct>, f: &u32) -> &u32 { + f + } + + fn rc_Struct(self: Rc<Struct>, f: &u32) -> &u32 { + f + } + + fn box_box_Struct(self: Box<Box<Struct>>, f: &u32) -> &u32 { + f + } + + fn box_rc_Struct(self: Box<Rc<Struct>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/explicit-self-closures.rs b/src/test/ui/self/explicit-self-closures.rs new file mode 100644 index 000000000..b409dfd7a --- /dev/null +++ b/src/test/ui/self/explicit-self-closures.rs @@ -0,0 +1,17 @@ +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] +// Test to make sure that explicit self params work inside closures + +// pretty-expanded FIXME #23616 + +struct Box { + x: usize +} + +impl Box { + pub fn set_many(&mut self, xs: &[usize]) { + for x in xs { self.x = *x; } + } +} + +pub fn main() {} diff --git a/src/test/ui/self/explicit-self-generic.rs b/src/test/ui/self/explicit-self-generic.rs new file mode 100644 index 000000000..8f6bed3b0 --- /dev/null +++ b/src/test/ui/self/explicit-self-generic.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] + +#[derive(Copy, Clone)] +struct LM { resize_at: usize, size: usize } + +enum HashMap<K,V> { + HashMap_(LM, Vec<(K,V)>) +} + +fn linear_map<K,V>() -> HashMap<K,V> { + HashMap::HashMap_(LM{ + resize_at: 32, + size: 0}, Vec::new()) +} + +impl<K,V> HashMap<K,V> { + pub fn len(&mut self) -> usize { + match *self { + HashMap::HashMap_(ref l, _) => l.size + } + } +} + +pub fn main() { + let mut m: Box<_> = Box::new(linear_map::<(),()>()); + assert_eq!(m.len(), 0); +} diff --git a/src/test/ui/self/explicit-self-objects-uniq.rs b/src/test/ui/self/explicit-self-objects-uniq.rs new file mode 100644 index 000000000..250ea12e5 --- /dev/null +++ b/src/test/ui/self/explicit-self-objects-uniq.rs @@ -0,0 +1,21 @@ +// run-pass + +trait Foo { + fn f(self: Box<Self>); +} + +struct S { + x: isize +} + +impl Foo for S { + fn f(self: Box<S>) { + assert_eq!(self.x, 3); + } +} + +pub fn main() { + let x = Box::new(S { x: 3 }); + let y = x as Box<dyn Foo>; + y.f(); +} diff --git a/src/test/ui/self/explicit-self.rs b/src/test/ui/self/explicit-self.rs new file mode 100644 index 000000000..873c3621a --- /dev/null +++ b/src/test/ui/self/explicit-self.rs @@ -0,0 +1,71 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] + +static tau: f64 = 2.0*3.14159265358979323; + +struct Point {x: f64, y: f64} +struct Size {w: f64, h: f64} +enum shape { + circle(Point, f64), + rectangle(Point, Size) +} + + +fn compute_area(shape: &shape) -> f64 { + match *shape { + shape::circle(_, radius) => 0.5 * tau * radius * radius, + shape::rectangle(_, ref size) => size.w * size.h + } +} + +impl shape { + // self is in the implicit self region + pub fn select<'r, T>(&self, threshold: f64, a: &'r T, b: &'r T) + -> &'r T { + if compute_area(self) > threshold {a} else {b} + } +} + +fn select_based_on_unit_circle<'r, T>( + threshold: f64, a: &'r T, b: &'r T) -> &'r T { + + let shape = &shape::circle(Point{x: 0.0, y: 0.0}, 1.0); + shape.select(threshold, a, b) +} + +#[derive(Clone)] +struct thing { + x: A +} + +#[derive(Clone)] +struct A { + a: isize +} + +fn thing(x: A) -> thing { + thing { + x: x + } +} + +impl thing { + pub fn bar(self: Box<thing>) -> isize { self.x.a } + pub fn quux(&self) -> isize { self.x.a } + pub fn baz<'a>(&'a self) -> &'a A { &self.x } + pub fn spam(self) -> isize { self.x.a } +} + +trait Nus { fn f(&self); } +impl Nus for thing { fn f(&self) {} } + +pub fn main() { + let y: Box<_> = Box::new(thing(A {a: 10})); + assert_eq!(y.clone().bar(), 10); + assert_eq!(y.quux(), 10); + + let z = thing(A {a: 11}); + assert_eq!(z.spam(), 11); +} diff --git a/src/test/ui/self/explicit_self_xcrate_exe.rs b/src/test/ui/self/explicit_self_xcrate_exe.rs new file mode 100644 index 000000000..c3796f73a --- /dev/null +++ b/src/test/ui/self/explicit_self_xcrate_exe.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:explicit_self_xcrate.rs + +// pretty-expanded FIXME #23616 + +extern crate explicit_self_xcrate; +use explicit_self_xcrate::{Foo, Bar}; + +pub fn main() { + let x = Bar { x: "hello".to_string() }; + x.f(); +} diff --git a/src/test/ui/self/issue-61882-2.rs b/src/test/ui/self/issue-61882-2.rs new file mode 100644 index 000000000..1209b54bc --- /dev/null +++ b/src/test/ui/self/issue-61882-2.rs @@ -0,0 +1,11 @@ +struct A<T>(T); + +impl A<&'static u8> { + fn f() { + let x = 0; + Self(&x); + //~^ ERROR `x` does not live long enough + } +} + +fn main() {} diff --git a/src/test/ui/self/issue-61882-2.stderr b/src/test/ui/self/issue-61882-2.stderr new file mode 100644 index 000000000..0b8e134c9 --- /dev/null +++ b/src/test/ui/self/issue-61882-2.stderr @@ -0,0 +1,15 @@ +error[E0597]: `x` does not live long enough + --> $DIR/issue-61882-2.rs:6:14 + | +LL | Self(&x); + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `x` is borrowed for `'static` +LL | +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/self/issue-61882.rs b/src/test/ui/self/issue-61882.rs new file mode 100644 index 000000000..013398b45 --- /dev/null +++ b/src/test/ui/self/issue-61882.rs @@ -0,0 +1,9 @@ +struct A<T>(T); + +impl A<bool> { + const B: A<u8> = Self(0); + //~^ ERROR mismatched types + //~| ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/self/issue-61882.stderr b/src/test/ui/self/issue-61882.stderr new file mode 100644 index 000000000..dd7194dc2 --- /dev/null +++ b/src/test/ui/self/issue-61882.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/issue-61882.rs:4:27 + | +LL | const B: A<u8> = Self(0); + | ---- ^ expected `bool`, found integer + | | + | arguments to this function are incorrect + | +note: tuple struct defined here + --> $DIR/issue-61882.rs:1:8 + | +LL | struct A<T>(T); + | ^ + +error[E0308]: mismatched types + --> $DIR/issue-61882.rs:4:22 + | +LL | const B: A<u8> = Self(0); + | ^^^^^^^ expected `u8`, found `bool` + | + = note: expected struct `A<u8>` + found struct `A<bool>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/self/move-self.rs b/src/test/ui/self/move-self.rs new file mode 100644 index 000000000..66032780b --- /dev/null +++ b/src/test/ui/self/move-self.rs @@ -0,0 +1,19 @@ +// run-pass +struct S { + x: String +} + +impl S { + pub fn foo(self) { + self.bar(); + } + + pub fn bar(self) { + println!("{}", self.x); + } +} + +pub fn main() { + let x = S { x: "Hello!".to_string() }; + x.foo(); +} diff --git a/src/test/ui/self/object-safety-sized-self-by-value-self.rs b/src/test/ui/self/object-safety-sized-self-by-value-self.rs new file mode 100644 index 000000000..43b1d8b91 --- /dev/null +++ b/src/test/ui/self/object-safety-sized-self-by-value-self.rs @@ -0,0 +1,39 @@ +// run-pass +#![allow(unused_mut)] +// Check that a trait is still object-safe (and usable) if it has +// methods with by-value self so long as they require `Self : Sized`. + + +trait Counter { + fn tick(&mut self) -> u32; + fn get(self) -> u32 where Self : Sized; +} + +struct CCounter { + c: u32 +} + +impl Counter for CCounter { + fn tick(&mut self) -> u32 { self.c += 1; self.c } + fn get(self) -> u32 where Self : Sized { self.c } +} + +fn tick1<C:Counter>(mut c: C) -> u32 { + tick2(&mut c); + c.get() +} + +fn tick2(c: &mut dyn Counter) { + tick3(c); +} + +fn tick3<C:?Sized+Counter>(c: &mut C) { + c.tick(); + c.tick(); +} + +fn main() { + let mut c = CCounter { c: 0 }; + let value = tick1(c); + assert_eq!(value, 2); +} diff --git a/src/test/ui/self/object-safety-sized-self-generic-method.rs b/src/test/ui/self/object-safety-sized-self-generic-method.rs new file mode 100644 index 000000000..e0b0526a3 --- /dev/null +++ b/src/test/ui/self/object-safety-sized-self-generic-method.rs @@ -0,0 +1,39 @@ +// run-pass +#![allow(unused_variables)] +// Check that a trait is still object-safe (and usable) if it has +// generic methods so long as they require `Self : Sized`. + + +trait Counter { + fn tick(&mut self) -> u32; + fn with<F:FnOnce(u32)>(&self, f: F) where Self : Sized; +} + +struct CCounter { + c: u32 +} + +impl Counter for CCounter { + fn tick(&mut self) -> u32 { self.c += 1; self.c } + fn with<F:FnOnce(u32)>(&self, f: F) { f(self.c); } +} + +fn tick1<C:Counter>(c: &mut C) { + tick2(c); + c.with(|i| ()); +} + +fn tick2(c: &mut dyn Counter) { + tick3(c); +} + +fn tick3<C:?Sized+Counter>(c: &mut C) { + c.tick(); + c.tick(); +} + +fn main() { + let mut c = CCounter { c: 0 }; + tick1(&mut c); + assert_eq!(c.tick(), 3); +} diff --git a/src/test/ui/self/object-safety-sized-self-return-Self.rs b/src/test/ui/self/object-safety-sized-self-return-Self.rs new file mode 100644 index 000000000..222c75439 --- /dev/null +++ b/src/test/ui/self/object-safety-sized-self-return-Self.rs @@ -0,0 +1,39 @@ +// run-pass +// Check that a trait is still object-safe (and usable) if it has +// methods that return `Self` so long as they require `Self : Sized`. + + +trait Counter { + fn new() -> Self where Self : Sized; + fn tick(&mut self) -> u32; +} + +struct CCounter { + c: u32 +} + +impl Counter for CCounter { + fn new() -> CCounter { CCounter { c: 0 } } + fn tick(&mut self) -> u32 { self.c += 1; self.c } +} + +fn preticked<C:Counter>() -> C { + let mut c: C = Counter::new(); + tick(&mut c); + c +} + +fn tick(c: &mut dyn Counter) { + tick_generic(c); +} + +fn tick_generic<C:?Sized+Counter>(c: &mut C) { + c.tick(); + c.tick(); +} + +fn main() { + let mut c = preticked::<CCounter>(); + tick(&mut c); + assert_eq!(c.tick(), 5); +} diff --git a/src/test/ui/self/objects-owned-object-owned-method.rs b/src/test/ui/self/objects-owned-object-owned-method.rs new file mode 100644 index 000000000..15677a518 --- /dev/null +++ b/src/test/ui/self/objects-owned-object-owned-method.rs @@ -0,0 +1,23 @@ +// run-pass +// Test invoked `&self` methods on owned objects where the values +// closed over contain managed values. This implies that the boxes +// will have headers that must be skipped over. + +trait FooTrait { + fn foo(self: Box<Self>) -> usize; +} + +struct BarStruct { + x: usize +} + +impl FooTrait for BarStruct { + fn foo(self: Box<BarStruct>) -> usize { + self.x + } +} + +pub fn main() { + let foo = Box::new(BarStruct{ x: 22 }) as Box<dyn FooTrait>; + assert_eq!(22, foo.foo()); +} diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.rs b/src/test/ui/self/point-at-arbitrary-self-type-method.rs new file mode 100644 index 000000000..0f7deeaca --- /dev/null +++ b/src/test/ui/self/point-at-arbitrary-self-type-method.rs @@ -0,0 +1,9 @@ +struct A; + +impl A { + fn foo(self: Box<Self>) {} +} + +fn main() { + A.foo(); //~ ERROR E0599 +} diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr new file mode 100644 index 000000000..3c7cccfc9 --- /dev/null +++ b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr @@ -0,0 +1,20 @@ +error[E0599]: no method named `foo` found for struct `A` in the current scope + --> $DIR/point-at-arbitrary-self-type-method.rs:8:7 + | +LL | struct A; + | -------- method `foo` not found for this struct +... +LL | fn foo(self: Box<Self>) {} + | --- the method is available for `Box<A>` here +... +LL | A.foo(); + | ^^^ method not found in `A` + | +help: consider wrapping the receiver expression with the appropriate type + | +LL | Box::new(A).foo(); + | +++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs new file mode 100644 index 000000000..53d992771 --- /dev/null +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs @@ -0,0 +1,10 @@ +trait B { fn foo(self: Box<Self>); } +struct A; + +impl B for A { + fn foo(self: Box<Self>) {} +} + +fn main() { + A.foo() //~ ERROR E0599 +} diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr new file mode 100644 index 000000000..366c14f76 --- /dev/null +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -0,0 +1,21 @@ +error[E0599]: no method named `foo` found for struct `A` in the current scope + --> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7 + | +LL | trait B { fn foo(self: Box<Self>); } + | --- --------- the method might not be found because of this arbitrary self type + | | + | the method is available for `Box<A>` here +LL | struct A; + | -------- method `foo` not found for this struct +... +LL | A.foo() + | ^^^ method not found in `A` + | +help: consider wrapping the receiver expression with the appropriate type + | +LL | Box::new(A).foo() + | +++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/self/self-impl-2.rs b/src/test/ui/self/self-impl-2.rs new file mode 100644 index 000000000..7eed3f056 --- /dev/null +++ b/src/test/ui/self/self-impl-2.rs @@ -0,0 +1,68 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test that we can use `Self` types in impls in the expected way. + +// pretty-expanded FIXME #23616 + +struct Foo; + +// Test uses on inherent impl. +impl Foo { + fn foo(_x: Self, _y: &Self, _z: Box<Self>) -> Self { + Foo + } + + fn baz() { + // Test that Self cannot be shadowed. + type Foo = i32; + // There is no empty method on i32. + Self::empty(); + + let _: Self = Foo; + } + + fn empty() {} +} + +// Test uses when implementing a trait and with a type parameter. +pub struct Baz<X> { + pub f: X, +} + +trait SuperBar { + type SuperQux; +} + +trait Bar<X>: SuperBar { + type Qux; + + fn bar(x: Self, y: &Self, z: Box<Self>, _: Self::SuperQux) -> Self; + fn dummy(&self, x: X) { } +} + +impl SuperBar for Box<Baz<isize>> { + type SuperQux = bool; +} + +impl Bar<isize> for Box<Baz<isize>> { + type Qux = i32; + + fn bar(_x: Self, _y: &Self, _z: Box<Self>, _: Self::SuperQux) -> Self { + let _: Self::Qux = 42; + let _: <Self as Bar<isize>>::Qux = 42; + + let _: Self::SuperQux = true; + let _: <Self as SuperBar>::SuperQux = true; + + Box::new(Baz { f: 42 }) + } +} + +fn main() { + let _: Foo = Foo::foo(Foo, &Foo, Box::new(Foo)); + let _: Box<Baz<isize>> = Bar::bar(Box::new(Baz { f: 42 }), + &Box::new(Baz { f: 42 }), + Box::new(Box::new(Baz { f: 42 })), + true); +} diff --git a/src/test/ui/self/self-impl.rs b/src/test/ui/self/self-impl.rs new file mode 100644 index 000000000..ed250ce52 --- /dev/null +++ b/src/test/ui/self/self-impl.rs @@ -0,0 +1,30 @@ +// Test that unsupported uses of `Self` in impls don't crash + +struct Bar; + +trait Foo { + type Baz; +} + +trait SuperFoo { + type SuperBaz; +} + +impl Foo for Bar { + type Baz = bool; +} + +impl SuperFoo for Bar { + type SuperBaz = bool; +} + +impl Bar { + fn f() { + let _: <Self>::Baz = true; + //~^ ERROR ambiguous associated type + let _: Self::Baz = true; + //~^ ERROR ambiguous associated type + } +} + +fn main() {} diff --git a/src/test/ui/self/self-impl.stderr b/src/test/ui/self/self-impl.stderr new file mode 100644 index 000000000..fb47f27e0 --- /dev/null +++ b/src/test/ui/self/self-impl.stderr @@ -0,0 +1,15 @@ +error[E0223]: ambiguous associated type + --> $DIR/self-impl.rs:23:16 + | +LL | let _: <Self>::Baz = true; + | ^^^^^^^^^^^ help: use fully-qualified syntax: `<Bar as Trait>::Baz` + +error[E0223]: ambiguous associated type + --> $DIR/self-impl.rs:25:16 + | +LL | let _: Self::Baz = true; + | ^^^^^^^^^ help: use fully-qualified syntax: `<Bar as Trait>::Baz` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0223`. diff --git a/src/test/ui/self/self-in-mut-slot-default-method.rs b/src/test/ui/self/self-in-mut-slot-default-method.rs new file mode 100644 index 000000000..45e122c8d --- /dev/null +++ b/src/test/ui/self/self-in-mut-slot-default-method.rs @@ -0,0 +1,35 @@ +// run-pass + +struct X { + a: isize +} + +trait Changer : Sized { + fn change(mut self) -> Self { + self.set_to(55); + self + } + + fn change_again(mut self: Box<Self>) -> Box<Self> { + self.set_to(45); + self + } + + fn set_to(&mut self, a: isize); +} + +impl Changer for X { + fn set_to(&mut self, a: isize) { + self.a = a; + } +} + +pub fn main() { + let x = X { a: 32 }; + let new_x = x.change(); + assert_eq!(new_x.a, 55); + + let x: Box<_> = Box::new(new_x); + let new_x = x.change_again(); + assert_eq!(new_x.a, 45); +} diff --git a/src/test/ui/self/self-in-mut-slot-immediate-value.rs b/src/test/ui/self/self-in-mut-slot-immediate-value.rs new file mode 100644 index 000000000..60865304f --- /dev/null +++ b/src/test/ui/self/self-in-mut-slot-immediate-value.rs @@ -0,0 +1,23 @@ +// run-pass +// Assert that `mut self` on an immediate value doesn't +// allow mutating the original - issue #10615. + + +#[derive(Copy, Clone)] +struct Value { + n: isize +} + +impl Value { + fn squared(mut self) -> Value { + self.n *= self.n; + self + } +} + +pub fn main() { + let x = Value { n: 3 }; + let y = x.squared(); + assert_eq!(x.n, 3); + assert_eq!(y.n, 9); +} diff --git a/src/test/ui/self/self-in-typedefs.rs b/src/test/ui/self/self-in-typedefs.rs new file mode 100644 index 000000000..81e557d53 --- /dev/null +++ b/src/test/ui/self/self-in-typedefs.rs @@ -0,0 +1,38 @@ +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] + +use std::mem::ManuallyDrop; + +enum A<'a, T: 'a> +where + Self: Send, T: PartialEq<Self> +{ + Foo(&'a Self), + Bar(T), +} + +struct B<'a, T: 'a> +where + Self: Send, T: PartialEq<Self> +{ + foo: &'a Self, + bar: T, +} + +union C<'a, T: 'a> +where + Self: Send, T: PartialEq<Self> +{ + foo: &'a Self, + bar: ManuallyDrop<T>, +} + +union D<'a, T: 'a> +where + Self: Send, T: PartialEq<Self> + Copy +{ + foo: &'a Self, + bar: T, +} + +fn main() {} diff --git a/src/test/ui/self/self-infer.rs b/src/test/ui/self/self-infer.rs new file mode 100644 index 000000000..9839b8880 --- /dev/null +++ b/src/test/ui/self/self-infer.rs @@ -0,0 +1,8 @@ +struct S; + +impl S { + fn f(self: _) {} //~ERROR the placeholder `_` is not allowed within types on item signatures for functions + fn g(self: &_) {} //~ERROR the placeholder `_` is not allowed within types on item signatures for functions +} + +fn main() {} diff --git a/src/test/ui/self/self-infer.stderr b/src/test/ui/self/self-infer.stderr new file mode 100644 index 000000000..4f9e3f21d --- /dev/null +++ b/src/test/ui/self/self-infer.stderr @@ -0,0 +1,25 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/self-infer.rs:4:16 + | +LL | fn f(self: _) {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn f<T>(self: T) {} + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/self-infer.rs:5:17 + | +LL | fn g(self: &_) {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn g<T>(self: &T) {} + | +++ ~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/self/self-re-assign.rs b/src/test/ui/self/self-re-assign.rs new file mode 100644 index 000000000..9595ebf96 --- /dev/null +++ b/src/test/ui/self/self-re-assign.rs @@ -0,0 +1,17 @@ +// run-pass +// Ensure assigning an owned or managed variable to itself works. In particular, +// that we do not glue_drop before we glue_take (#3290). + +#![allow(dead_code)] + +use std::rc::Rc; + +pub fn main() { + let mut x: Box<_> = Box::new(3); + x = x; + assert_eq!(*x, 3); + + let mut x = Rc::new(3); + x = x; + assert_eq!(*x, 3); +} diff --git a/src/test/ui/self/self-shadowing-import.rs b/src/test/ui/self/self-shadowing-import.rs new file mode 100644 index 000000000..1d60c6c22 --- /dev/null +++ b/src/test/ui/self/self-shadowing-import.rs @@ -0,0 +1,16 @@ +// run-pass + +mod a { + pub mod b { + pub mod a { + pub fn foo() -> isize { return 1; } + } + } +} + +mod c { + use a::b::a; + pub fn bar() { assert_eq!(a::foo(), 1); } +} + +pub fn main() { c::bar(); } diff --git a/src/test/ui/self/self-type-param.rs b/src/test/ui/self/self-type-param.rs new file mode 100644 index 000000000..5eb8c3622 --- /dev/null +++ b/src/test/ui/self/self-type-param.rs @@ -0,0 +1,19 @@ +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait MyTrait { + fn f(&self) -> Self; +} + +struct S { + x: isize +} + +impl MyTrait for S { + fn f(&self) -> S { + S { x: 3 } + } +} + +pub fn main() {} diff --git a/src/test/ui/self/self-vs-path-ambiguity.rs b/src/test/ui/self/self-vs-path-ambiguity.rs new file mode 100644 index 000000000..5a06d56c8 --- /dev/null +++ b/src/test/ui/self/self-vs-path-ambiguity.rs @@ -0,0 +1,12 @@ +// Check that `self::foo` is parsed as a general pattern and not a self argument. + +struct S; + +impl S { + fn f(self::S: S) {} + fn g(&self::S: &S) {} + fn h(&mut self::S: &mut S) {} + fn i(&'a self::S: &S) {} //~ ERROR unexpected lifetime `'a` in pattern +} + +fn main() {} diff --git a/src/test/ui/self/self-vs-path-ambiguity.stderr b/src/test/ui/self/self-vs-path-ambiguity.stderr new file mode 100644 index 000000000..2beef50cd --- /dev/null +++ b/src/test/ui/self/self-vs-path-ambiguity.stderr @@ -0,0 +1,8 @@ +error: unexpected lifetime `'a` in pattern + --> $DIR/self-vs-path-ambiguity.rs:9:11 + | +LL | fn i(&'a self::S: &S) {} + | ^^ help: remove the lifetime + +error: aborting due to previous error + diff --git a/src/test/ui/self/self_lifetime-async.rs b/src/test/ui/self/self_lifetime-async.rs new file mode 100644 index 000000000..c3c6e5658 --- /dev/null +++ b/src/test/ui/self/self_lifetime-async.rs @@ -0,0 +1,14 @@ +// check-pass +// edition:2018 + +struct Foo<'a>(&'a ()); +impl<'a> Foo<'a> { + async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } +} + +type Alias = Foo<'static>; +impl Alias { + async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } +} + +fn main() {} diff --git a/src/test/ui/self/self_lifetime.rs b/src/test/ui/self/self_lifetime.rs new file mode 100644 index 000000000..f04bd83ab --- /dev/null +++ b/src/test/ui/self/self_lifetime.rs @@ -0,0 +1,15 @@ +// check-pass + +// https://github.com/rust-lang/rust/pull/60944#issuecomment-495346120 + +struct Foo<'a>(&'a ()); +impl<'a> Foo<'a> { + fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } +} + +type Alias = Foo<'static>; +impl Alias { + fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } +} + +fn main() {} diff --git a/src/test/ui/self/self_type_keyword-2.rs b/src/test/ui/self/self_type_keyword-2.rs new file mode 100644 index 000000000..cfb87f518 --- /dev/null +++ b/src/test/ui/self/self_type_keyword-2.rs @@ -0,0 +1,13 @@ +use self::Self as Foo; //~ ERROR unresolved import `self::Self` + +pub fn main() { + let Self = 5; + //~^ ERROR cannot find unit struct, unit variant or constant `Self` in this scope + + match 15 { + Self => (), + //~^ ERROR cannot find unit struct, unit variant or constant `Self` in this scope + Foo { x: Self } => (), + //~^ ERROR cannot find unit struct, unit variant or constant `Self` in this scope + } +} diff --git a/src/test/ui/self/self_type_keyword-2.stderr b/src/test/ui/self/self_type_keyword-2.stderr new file mode 100644 index 000000000..4e931f91f --- /dev/null +++ b/src/test/ui/self/self_type_keyword-2.stderr @@ -0,0 +1,28 @@ +error[E0432]: unresolved import `self::Self` + --> $DIR/self_type_keyword-2.rs:1:5 + | +LL | use self::Self as Foo; + | ^^^^^^^^^^^^^^^^^ no `Self` in the root + +error[E0531]: cannot find unit struct, unit variant or constant `Self` in this scope + --> $DIR/self_type_keyword-2.rs:4:9 + | +LL | let Self = 5; + | ^^^^ not found in this scope + +error[E0531]: cannot find unit struct, unit variant or constant `Self` in this scope + --> $DIR/self_type_keyword-2.rs:8:9 + | +LL | Self => (), + | ^^^^ not found in this scope + +error[E0531]: cannot find unit struct, unit variant or constant `Self` in this scope + --> $DIR/self_type_keyword-2.rs:10:18 + | +LL | Foo { x: Self } => (), + | ^^^^ not found in this scope + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0432, E0531. +For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/self/self_type_keyword.rs b/src/test/ui/self/self_type_keyword.rs new file mode 100644 index 000000000..b42bf8eea --- /dev/null +++ b/src/test/ui/self/self_type_keyword.rs @@ -0,0 +1,41 @@ +mod foo { + struct Self; + //~^ ERROR expected identifier, found keyword `Self` +} + +struct Bar<'Self>; +//~^ ERROR lifetimes cannot use keyword names +//~| ERROR parameter `'Self` is never used + +struct Foo; + +pub fn main() { + match 15 { + ref Self => (), + //~^ ERROR expected identifier, found keyword `Self` + mut Self => (), + //~^ ERROR `mut` must be followed by a named binding + //~| ERROR cannot find unit struct, unit variant or constant `Self` + ref mut Self => (), + //~^ ERROR expected identifier, found keyword `Self` + Self!() => (), + //~^ ERROR cannot find macro `Self` in this scope + Foo { Self } => (), + //~^ ERROR expected identifier, found keyword `Self` + } +} + +mod m1 { + extern crate core as Self; + //~^ ERROR expected identifier, found keyword `Self` +} + +mod m2 { + use std::option::Option as Self; + //~^ ERROR expected identifier, found keyword `Self` +} + +mod m3 { + trait Self {} + //~^ ERROR expected identifier, found keyword `Self` +} diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr new file mode 100644 index 000000000..aca08d811 --- /dev/null +++ b/src/test/ui/self/self_type_keyword.stderr @@ -0,0 +1,86 @@ +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:2:10 + | +LL | struct Self; + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:14:13 + | +LL | ref Self => (), + | ^^^^ expected identifier, found keyword + +error: `mut` must be followed by a named binding + --> $DIR/self_type_keyword.rs:16:9 + | +LL | mut Self => (), + | ^^^^^^^^ help: remove the `mut` prefix: `Self` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:19:17 + | +LL | ref mut Self => (), + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:23:15 + | +LL | Foo { Self } => (), + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:29:26 + | +LL | extern crate core as Self; + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:34:32 + | +LL | use std::option::Option as Self; + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:39:11 + | +LL | trait Self {} + | ^^^^ expected identifier, found keyword + +error: lifetimes cannot use keyword names + --> $DIR/self_type_keyword.rs:6:12 + | +LL | struct Bar<'Self>; + | ^^^^^ + +error: cannot find macro `Self` in this scope + --> $DIR/self_type_keyword.rs:21:9 + | +LL | Self!() => (), + | ^^^^ + +error[E0531]: cannot find unit struct, unit variant or constant `Self` in this scope + --> $DIR/self_type_keyword.rs:16:13 + | +LL | mut Self => (), + | ^^^^ not found in this scope + | +note: unit struct `foo::Self` exists but is inaccessible + --> $DIR/self_type_keyword.rs:2:3 + | +LL | struct Self; + | ^^^^^^^^^^^^ not accessible + +error[E0392]: parameter `'Self` is never used + --> $DIR/self_type_keyword.rs:6:12 + | +LL | struct Bar<'Self>; + | ^^^^^ unused parameter + | + = help: consider removing `'Self`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0392, E0531. +For more information about an error, try `rustc --explain E0392`. diff --git a/src/test/ui/self/string-self-append.rs b/src/test/ui/self/string-self-append.rs new file mode 100644 index 000000000..e63dc0090 --- /dev/null +++ b/src/test/ui/self/string-self-append.rs @@ -0,0 +1,14 @@ +// run-pass +pub fn main() { + // Make sure we properly handle repeated self-appends. + let mut a: String = "A".to_string(); + let mut i = 20; + let mut expected_len = 1; + while i > 0 { + println!("{}", a.len()); + assert_eq!(a.len(), expected_len); + a = format!("{}{}", a, a); + i -= 1; + expected_len *= 2; + } +} diff --git a/src/test/ui/self/suggest-self-2.rs b/src/test/ui/self/suggest-self-2.rs new file mode 100644 index 000000000..1e001827e --- /dev/null +++ b/src/test/ui/self/suggest-self-2.rs @@ -0,0 +1,25 @@ +struct Foo {} + +impl Foo { + fn foo(&self) { + bar(self); + //~^ ERROR cannot find function `bar` in this scope + //~| HELP try calling `bar` as a method + + bar(&&self, 102); + //~^ ERROR cannot find function `bar` in this scope + //~| HELP try calling `bar` as a method + + bar(&mut self, 102, &"str"); + //~^ ERROR cannot find function `bar` in this scope + //~| HELP try calling `bar` as a method + + bar(); + //~^ ERROR cannot find function `bar` in this scope + + self.bar(); + //~^ ERROR no method named `bar` found for reference + } +} + +fn main() {} diff --git a/src/test/ui/self/suggest-self-2.stderr b/src/test/ui/self/suggest-self-2.stderr new file mode 100644 index 000000000..4bd025ea0 --- /dev/null +++ b/src/test/ui/self/suggest-self-2.stderr @@ -0,0 +1,40 @@ +error[E0425]: cannot find function `bar` in this scope + --> $DIR/suggest-self-2.rs:5:9 + | +LL | bar(self); + | ^^^------ + | | + | help: try calling `bar` as a method: `self.bar()` + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/suggest-self-2.rs:9:9 + | +LL | bar(&&self, 102); + | ^^^------------- + | | + | help: try calling `bar` as a method: `self.bar(102)` + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/suggest-self-2.rs:13:9 + | +LL | bar(&mut self, 102, &"str"); + | ^^^------------------------ + | | + | help: try calling `bar` as a method: `self.bar(102, &"str")` + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/suggest-self-2.rs:17:9 + | +LL | bar(); + | ^^^ not found in this scope + +error[E0599]: no method named `bar` found for reference `&Foo` in the current scope + --> $DIR/suggest-self-2.rs:20:14 + | +LL | self.bar(); + | ^^^ method not found in `&Foo` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0425, E0599. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/self/suggest-self.rs b/src/test/ui/self/suggest-self.rs new file mode 100644 index 000000000..1cc17116e --- /dev/null +++ b/src/test/ui/self/suggest-self.rs @@ -0,0 +1,41 @@ +struct Foo { + x: i32, +} + +impl Foo { + fn this1(&self) -> i32 { + let this = self; + let a = 1; + this.x + } + + fn this2(&self) -> i32 { + let a = Foo { + x: 2 + }; + let this = a; + this.x + } + + fn foo(&self) -> i32 { + this.x + //~^ ERROR cannot find value `this` in this scope + } + + fn bar(&self) -> i32 { + this.foo() + //~^ ERROR cannot find value `this` in this scope + } + + fn baz(&self) -> i32 { + my.bar() + //~^ ERROR cannot find value `my` in this scope + } +} + +fn main() { + let this = vec![1, 2, 3]; + let my = vec![1, 2, 3]; + let len = this.len(); + let len = my.len(); +} diff --git a/src/test/ui/self/suggest-self.stderr b/src/test/ui/self/suggest-self.stderr new file mode 100644 index 000000000..0d38b9d87 --- /dev/null +++ b/src/test/ui/self/suggest-self.stderr @@ -0,0 +1,30 @@ +error[E0425]: cannot find value `this` in this scope + --> $DIR/suggest-self.rs:21:9 + | +LL | this.x + | ^^^^ + | | + | not found in this scope + | help: you might have meant to use `self` here instead + +error[E0425]: cannot find value `this` in this scope + --> $DIR/suggest-self.rs:26:9 + | +LL | this.foo() + | ^^^^ + | | + | not found in this scope + | help: you might have meant to use `self` here instead + +error[E0425]: cannot find value `my` in this scope + --> $DIR/suggest-self.rs:31:9 + | +LL | my.bar() + | ^^ + | | + | not found in this scope + | help: you might have meant to use `self` here instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/self/ufcs-explicit-self.rs b/src/test/ui/self/ufcs-explicit-self.rs new file mode 100644 index 000000000..d83af14d3 --- /dev/null +++ b/src/test/ui/self/ufcs-explicit-self.rs @@ -0,0 +1,49 @@ +// run-pass +#![allow(dead_code)] + +#[derive(Copy, Clone)] +struct Foo { + f: isize, +} + +impl Foo { + fn foo(self: Foo, x: isize) -> isize { + self.f + x + } + fn bar(self: &Foo, x: isize) -> isize { + self.f + x + } + fn baz(self: Box<Foo>, x: isize) -> isize { + self.f + x + } +} + +#[derive(Copy, Clone)] +struct Bar<T> { + f: T, +} + +impl<T> Bar<T> { + fn foo(self: Bar<T>, x: isize) -> isize { + x + } + fn bar<'a>(self: &'a Bar<T>, x: isize) -> isize { + x + } + fn baz(self: Bar<T>, x: isize) -> isize { + x + } +} + +fn main() { + let foo: Box<_> = Box::new(Foo { + f: 1, + }); + println!("{} {} {}", foo.foo(2), foo.bar(2), foo.baz(2)); + let bar: Box<_> = Box::new(Bar { + f: 1, + }); + println!("{} {} {}", bar.foo(2), bar.bar(2), bar.baz(2)); + let bar: Box<Bar<isize>> = bar; + println!("{} {} {}", bar.foo(2), bar.bar(2), bar.baz(2)); +} diff --git a/src/test/ui/self/uniq-self-in-mut-slot.rs b/src/test/ui/self/uniq-self-in-mut-slot.rs new file mode 100644 index 000000000..71e57d8c1 --- /dev/null +++ b/src/test/ui/self/uniq-self-in-mut-slot.rs @@ -0,0 +1,22 @@ +// run-pass + +struct X { + a: isize +} + +trait Changer { + fn change(self: Box<Self>) -> Box<Self>; +} + +impl Changer for X { + fn change(mut self: Box<X>) -> Box<X> { + self.a = 55; + self + } +} + +pub fn main() { + let x: Box<_> = Box::new(X { a: 32 }); + let new_x = x.change(); + assert_eq!(new_x.a, 55); +} diff --git a/src/test/ui/self/where-for-self.rs b/src/test/ui/self/where-for-self.rs new file mode 100644 index 000000000..76c592dc4 --- /dev/null +++ b/src/test/ui/self/where-for-self.rs @@ -0,0 +1,51 @@ +// run-pass +// Test that we can quantify lifetimes outside a constraint (i.e., including +// the self type) in a where clause. + + +static mut COUNT: u32 = 1; + +trait Bar<'a> { + fn bar(&self); +} + +trait Baz<'a> +{ + fn baz(&self); +} + +impl<'a, 'b> Bar<'b> for &'a u32 { + fn bar(&self) { + unsafe { COUNT *= 2; } + } +} + +impl<'a, 'b> Baz<'b> for &'a u32 { + fn baz(&self) { + unsafe { COUNT *= 3; } + } +} + +// Test we can use the syntax for HRL including the self type. +fn foo1<T>(x: &T) + where for<'a, 'b> &'a T: Bar<'b> +{ + x.bar() +} + +// Test we can quantify multiple bounds (i.e., the precedence is sensible). +fn foo2<T>(x: &T) + where for<'a, 'b> &'a T: Bar<'b> + Baz<'b> +{ + x.baz(); + x.bar() +} + +fn main() { + let x = 42; + foo1(&x); + foo2(&x); + unsafe { + assert_eq!(COUNT, 12); + } +} |