summaryrefslogtreecommitdiffstats
path: root/src/test/ui/self
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr39
-rw-r--r--src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr22
-rw-r--r--src/test/ui/self/arbitrary-self-types-not-object-safe.rs44
-rw-r--r--src/test/ui/self/arbitrary_self_types_nested.rs36
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime-async.rs35
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime.rs60
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs14
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr16
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs12
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr16
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs21
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr39
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs19
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr38
-rw-r--r--src/test/ui/self/arbitrary_self_types_pointers_and_wrappers.rs68
-rw-r--r--src/test/ui/self/arbitrary_self_types_raw_pointer_struct.rs28
-rw-r--r--src/test/ui/self/arbitrary_self_types_raw_pointer_trait.rs61
-rw-r--r--src/test/ui/self/arbitrary_self_types_silly.rs21
-rw-r--r--src/test/ui/self/arbitrary_self_types_stdlib_pointers.rs54
-rw-r--r--src/test/ui/self/arbitrary_self_types_struct.rs24
-rw-r--r--src/test/ui/self/arbitrary_self_types_trait.rs19
-rw-r--r--src/test/ui/self/arbitrary_self_types_unsized_struct.rs16
-rw-r--r--src/test/ui/self/auxiliary/explicit_self_xcrate.rs15
-rw-r--r--src/test/ui/self/builtin-superkinds-self-type.rs20
-rw-r--r--src/test/ui/self/by-value-self-in-mut-slot.rs22
-rw-r--r--src/test/ui/self/class-missing-self.rs16
-rw-r--r--src/test/ui/self/class-missing-self.stderr20
-rw-r--r--src/test/ui/self/elision/README.md75
-rw-r--r--src/test/ui/self/elision/alias-async.rs36
-rw-r--r--src/test/ui/self/elision/alias.rs35
-rw-r--r--src/test/ui/self/elision/assoc-async.rs40
-rw-r--r--src/test/ui/self/elision/assoc.rs39
-rw-r--r--src/test/ui/self/elision/lt-alias-async.rs38
-rw-r--r--src/test/ui/self/elision/lt-alias.rs37
-rw-r--r--src/test/ui/self/elision/lt-assoc-async.rs50
-rw-r--r--src/test/ui/self/elision/lt-assoc.rs43
-rw-r--r--src/test/ui/self/elision/lt-ref-self-async.rs45
-rw-r--r--src/test/ui/self/elision/lt-ref-self-async.stderr92
-rw-r--r--src/test/ui/self/elision/lt-ref-self.rs43
-rw-r--r--src/test/ui/self/elision/lt-ref-self.stderr92
-rw-r--r--src/test/ui/self/elision/lt-self-async.rs49
-rw-r--r--src/test/ui/self/elision/lt-self.rs48
-rw-r--r--src/test/ui/self/elision/lt-struct-async.rs36
-rw-r--r--src/test/ui/self/elision/lt-struct.rs35
-rw-r--r--src/test/ui/self/elision/multiple-ref-self-async.rs44
-rw-r--r--src/test/ui/self/elision/multiple-ref-self.rs43
-rw-r--r--src/test/ui/self/elision/ref-alias-async.rs39
-rw-r--r--src/test/ui/self/elision/ref-alias.rs38
-rw-r--r--src/test/ui/self/elision/ref-assoc-async.rs40
-rw-r--r--src/test/ui/self/elision/ref-assoc.rs39
-rw-r--r--src/test/ui/self/elision/ref-mut-alias-async.rs36
-rw-r--r--src/test/ui/self/elision/ref-mut-alias.rs35
-rw-r--r--src/test/ui/self/elision/ref-mut-self-async.rs45
-rw-r--r--src/test/ui/self/elision/ref-mut-self-async.stderr92
-rw-r--r--src/test/ui/self/elision/ref-mut-self.rs43
-rw-r--r--src/test/ui/self/elision/ref-mut-self.stderr92
-rw-r--r--src/test/ui/self/elision/ref-mut-struct-async.rs38
-rw-r--r--src/test/ui/self/elision/ref-mut-struct-async.stderr77
-rw-r--r--src/test/ui/self/elision/ref-mut-struct.rs36
-rw-r--r--src/test/ui/self/elision/ref-mut-struct.stderr77
-rw-r--r--src/test/ui/self/elision/ref-self-async.rs60
-rw-r--r--src/test/ui/self/elision/ref-self-async.stderr107
-rw-r--r--src/test/ui/self/elision/ref-self.rs58
-rw-r--r--src/test/ui/self/elision/ref-self.stderr107
-rw-r--r--src/test/ui/self/elision/ref-struct-async.rs38
-rw-r--r--src/test/ui/self/elision/ref-struct-async.stderr77
-rw-r--r--src/test/ui/self/elision/ref-struct.rs36
-rw-r--r--src/test/ui/self/elision/ref-struct.stderr77
-rw-r--r--src/test/ui/self/elision/self-async.rs36
-rw-r--r--src/test/ui/self/elision/self.rs35
-rw-r--r--src/test/ui/self/elision/struct-async.rs32
-rw-r--r--src/test/ui/self/elision/struct.rs31
-rw-r--r--src/test/ui/self/explicit-self-closures.rs17
-rw-r--r--src/test/ui/self/explicit-self-generic.rs28
-rw-r--r--src/test/ui/self/explicit-self-objects-uniq.rs21
-rw-r--r--src/test/ui/self/explicit-self.rs71
-rw-r--r--src/test/ui/self/explicit_self_xcrate_exe.rs12
-rw-r--r--src/test/ui/self/issue-61882-2.rs11
-rw-r--r--src/test/ui/self/issue-61882-2.stderr15
-rw-r--r--src/test/ui/self/issue-61882.rs9
-rw-r--r--src/test/ui/self/issue-61882.stderr26
-rw-r--r--src/test/ui/self/move-self.rs19
-rw-r--r--src/test/ui/self/object-safety-sized-self-by-value-self.rs39
-rw-r--r--src/test/ui/self/object-safety-sized-self-generic-method.rs39
-rw-r--r--src/test/ui/self/object-safety-sized-self-return-Self.rs39
-rw-r--r--src/test/ui/self/objects-owned-object-owned-method.rs23
-rw-r--r--src/test/ui/self/point-at-arbitrary-self-type-method.rs9
-rw-r--r--src/test/ui/self/point-at-arbitrary-self-type-method.stderr20
-rw-r--r--src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs10
-rw-r--r--src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr21
-rw-r--r--src/test/ui/self/self-impl-2.rs68
-rw-r--r--src/test/ui/self/self-impl.rs30
-rw-r--r--src/test/ui/self/self-impl.stderr15
-rw-r--r--src/test/ui/self/self-in-mut-slot-default-method.rs35
-rw-r--r--src/test/ui/self/self-in-mut-slot-immediate-value.rs23
-rw-r--r--src/test/ui/self/self-in-typedefs.rs38
-rw-r--r--src/test/ui/self/self-infer.rs8
-rw-r--r--src/test/ui/self/self-infer.stderr25
-rw-r--r--src/test/ui/self/self-re-assign.rs17
-rw-r--r--src/test/ui/self/self-shadowing-import.rs16
-rw-r--r--src/test/ui/self/self-type-param.rs19
-rw-r--r--src/test/ui/self/self-vs-path-ambiguity.rs12
-rw-r--r--src/test/ui/self/self-vs-path-ambiguity.stderr8
-rw-r--r--src/test/ui/self/self_lifetime-async.rs14
-rw-r--r--src/test/ui/self/self_lifetime.rs15
-rw-r--r--src/test/ui/self/self_type_keyword-2.rs13
-rw-r--r--src/test/ui/self/self_type_keyword-2.stderr28
-rw-r--r--src/test/ui/self/self_type_keyword.rs41
-rw-r--r--src/test/ui/self/self_type_keyword.stderr86
-rw-r--r--src/test/ui/self/string-self-append.rs14
-rw-r--r--src/test/ui/self/suggest-self-2.rs25
-rw-r--r--src/test/ui/self/suggest-self-2.stderr40
-rw-r--r--src/test/ui/self/suggest-self.rs41
-rw-r--r--src/test/ui/self/suggest-self.stderr30
-rw-r--r--src/test/ui/self/ufcs-explicit-self.rs49
-rw-r--r--src/test/ui/self/uniq-self-in-mut-slot.rs22
-rw-r--r--src/test/ui/self/where-for-self.rs51
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);
+ }
+}