summaryrefslogtreecommitdiffstats
path: root/src/test/ui/methods
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/methods')
-rw-r--r--src/test/ui/methods/assign-to-method.rs24
-rw-r--r--src/test/ui/methods/assign-to-method.stderr19
-rw-r--r--src/test/ui/methods/auxiliary/ambig_impl_2_lib.rs4
-rw-r--r--src/test/ui/methods/auxiliary/macro-in-other-crate.rs9
-rw-r--r--src/test/ui/methods/auxiliary/method_self_arg1.rs35
-rw-r--r--src/test/ui/methods/auxiliary/method_self_arg2.rs52
-rw-r--r--src/test/ui/methods/issues/issue-61525.rs20
-rw-r--r--src/test/ui/methods/issues/issue-61525.stderr39
-rw-r--r--src/test/ui/methods/issues/issue-84495.rs4
-rw-r--r--src/test/ui/methods/issues/issue-84495.stderr13
-rw-r--r--src/test/ui/methods/issues/issue-90315.rs7
-rw-r--r--src/test/ui/methods/issues/issue-90315.stderr13
-rw-r--r--src/test/ui/methods/issues/issue-94581.rs7
-rw-r--r--src/test/ui/methods/issues/issue-94581.stderr15
-rw-r--r--src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs36
-rw-r--r--src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr47
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-cross-crate.rs11
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr24
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-from-bounds.rs8
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-from-bounds.stderr28
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-from-impls.rs16
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-from-impls.stderr28
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-from-impls2.rs16
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr28
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-with-default-method.rs13
-rw-r--r--src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr28
-rw-r--r--src/test/ui/methods/method-argument-inference-associated-type.rs28
-rw-r--r--src/test/ui/methods/method-call-err-msg.rs22
-rw-r--r--src/test/ui/methods/method-call-err-msg.stderr92
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-fail.rs72
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-fail.stderr235
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-lint-fail.rs87
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-lint-fail.stderr187
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-lint.rs21
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-lint.stderr31
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-subst-index.rs15
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-unresolved.rs6
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-unresolved.stderr26
-rw-r--r--src/test/ui/methods/method-call-lifetime-args.rs15
-rw-r--r--src/test/ui/methods/method-call-lifetime-args.stderr26
-rw-r--r--src/test/ui/methods/method-call-type-binding.rs3
-rw-r--r--src/test/ui/methods/method-call-type-binding.stderr9
-rw-r--r--src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs179
-rw-r--r--src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr87
-rw-r--r--src/test/ui/methods/method-early-bound-lifetimes-on-self.rs31
-rw-r--r--src/test/ui/methods/method-lookup-order.rs190
-rw-r--r--src/test/ui/methods/method-macro-backtrace.rs25
-rw-r--r--src/test/ui/methods/method-macro-backtrace.stderr11
-rw-r--r--src/test/ui/methods/method-missing-call.rs30
-rw-r--r--src/test/ui/methods/method-missing-call.stderr25
-rw-r--r--src/test/ui/methods/method-mut-self-modifies-mut-slice-lvalue.rs44
-rw-r--r--src/test/ui/methods/method-normalize-bounds-issue-20604.rs61
-rw-r--r--src/test/ui/methods/method-not-found-generic-arg-elision.rs106
-rw-r--r--src/test/ui/methods/method-not-found-generic-arg-elision.stderr97
-rw-r--r--src/test/ui/methods/method-on-ambiguous-numeric-type.rs32
-rw-r--r--src/test/ui/methods/method-on-ambiguous-numeric-type.stderr56
-rw-r--r--src/test/ui/methods/method-path-in-pattern.rs32
-rw-r--r--src/test/ui/methods/method-path-in-pattern.stderr39
-rw-r--r--src/test/ui/methods/method-probe-no-guessing-dyn-trait.rs60
-rw-r--r--src/test/ui/methods/method-projection.rs61
-rw-r--r--src/test/ui/methods/method-recursive-blanket-impl.rs41
-rw-r--r--src/test/ui/methods/method-resolvable-path-in-pattern.rs14
-rw-r--r--src/test/ui/methods/method-resolvable-path-in-pattern.stderr9
-rw-r--r--src/test/ui/methods/method-self-arg-1.rs17
-rw-r--r--src/test/ui/methods/method-self-arg-1.stderr35
-rw-r--r--src/test/ui/methods/method-self-arg-2.rs25
-rw-r--r--src/test/ui/methods/method-self-arg-2.stderr24
-rw-r--r--src/test/ui/methods/method-self-arg-aux1.rs18
-rw-r--r--src/test/ui/methods/method-self-arg-aux2.rs22
-rw-r--r--src/test/ui/methods/method-self-arg-trait.rs67
-rw-r--r--src/test/ui/methods/method-self-arg.rs46
-rw-r--r--src/test/ui/methods/method-trait-object-with-hrtb.rs41
-rw-r--r--src/test/ui/methods/method-two-trait-defer-resolution-1.rs37
-rw-r--r--src/test/ui/methods/method-two-trait-defer-resolution-2.rs46
-rw-r--r--src/test/ui/methods/method-two-traits-distinguished-via-where-clause.rs27
-rw-r--r--src/test/ui/methods/method-where-clause.rs34
76 files changed, 3088 insertions, 0 deletions
diff --git a/src/test/ui/methods/assign-to-method.rs b/src/test/ui/methods/assign-to-method.rs
new file mode 100644
index 000000000..85beaee8d
--- /dev/null
+++ b/src/test/ui/methods/assign-to-method.rs
@@ -0,0 +1,24 @@
+// compile-flags: -Zsave-analysis
+// Also regression test for #69409
+
+struct Cat {
+ meows : usize,
+ how_hungry : isize,
+}
+
+impl Cat {
+ pub fn speak(&self) { self.meows += 1; }
+}
+
+fn cat(in_x : usize, in_y : isize) -> Cat {
+ Cat {
+ meows: in_x,
+ how_hungry: in_y
+ }
+}
+
+fn main() {
+ let nyan : Cat = cat(52, 99);
+ nyan.speak = || println!("meow"); //~ ERROR attempted to take value of method
+ nyan.speak += || println!("meow"); //~ ERROR attempted to take value of method
+}
diff --git a/src/test/ui/methods/assign-to-method.stderr b/src/test/ui/methods/assign-to-method.stderr
new file mode 100644
index 000000000..cafe9abae
--- /dev/null
+++ b/src/test/ui/methods/assign-to-method.stderr
@@ -0,0 +1,19 @@
+error[E0615]: attempted to take value of method `speak` on type `Cat`
+ --> $DIR/assign-to-method.rs:22:10
+ |
+LL | nyan.speak = || println!("meow");
+ | ^^^^^ method, not a field
+ |
+ = help: methods are immutable and cannot be assigned to
+
+error[E0615]: attempted to take value of method `speak` on type `Cat`
+ --> $DIR/assign-to-method.rs:23:10
+ |
+LL | nyan.speak += || println!("meow");
+ | ^^^^^ method, not a field
+ |
+ = help: methods are immutable and cannot be assigned to
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0615`.
diff --git a/src/test/ui/methods/auxiliary/ambig_impl_2_lib.rs b/src/test/ui/methods/auxiliary/ambig_impl_2_lib.rs
new file mode 100644
index 000000000..0ed68bf69
--- /dev/null
+++ b/src/test/ui/methods/auxiliary/ambig_impl_2_lib.rs
@@ -0,0 +1,4 @@
+pub trait Me {
+ fn me(&self) -> usize;
+}
+impl Me for usize { fn me(&self) -> usize { *self } }
diff --git a/src/test/ui/methods/auxiliary/macro-in-other-crate.rs b/src/test/ui/methods/auxiliary/macro-in-other-crate.rs
new file mode 100644
index 000000000..feda08463
--- /dev/null
+++ b/src/test/ui/methods/auxiliary/macro-in-other-crate.rs
@@ -0,0 +1,9 @@
+#[macro_export]
+macro_rules! mac {
+ ($ident:ident) => { let $ident = 42; }
+}
+
+#[macro_export]
+macro_rules! inline {
+ () => ()
+}
diff --git a/src/test/ui/methods/auxiliary/method_self_arg1.rs b/src/test/ui/methods/auxiliary/method_self_arg1.rs
new file mode 100644
index 000000000..f89019fe5
--- /dev/null
+++ b/src/test/ui/methods/auxiliary/method_self_arg1.rs
@@ -0,0 +1,35 @@
+#![crate_type = "lib"]
+
+static mut COUNT: u64 = 1;
+
+pub fn get_count() -> u64 { unsafe { COUNT } }
+
+#[derive(Copy, Clone)]
+pub struct Foo;
+
+impl Foo {
+ pub fn foo(self, x: &Foo) {
+ unsafe { COUNT *= 2; }
+ // Test internal call.
+ Foo::bar(&self);
+ Foo::bar(x);
+
+ Foo::baz(self);
+ Foo::baz(*x);
+
+ Foo::qux(Box::new(self));
+ Foo::qux(Box::new(*x));
+ }
+
+ pub fn bar(&self) {
+ unsafe { COUNT *= 3; }
+ }
+
+ pub fn baz(self) {
+ unsafe { COUNT *= 5; }
+ }
+
+ pub fn qux(self: Box<Foo>) {
+ unsafe { COUNT *= 7; }
+ }
+}
diff --git a/src/test/ui/methods/auxiliary/method_self_arg2.rs b/src/test/ui/methods/auxiliary/method_self_arg2.rs
new file mode 100644
index 000000000..967254562
--- /dev/null
+++ b/src/test/ui/methods/auxiliary/method_self_arg2.rs
@@ -0,0 +1,52 @@
+#![crate_type = "lib"]
+
+static mut COUNT: u64 = 1;
+
+pub fn get_count() -> u64 { unsafe { COUNT } }
+
+#[derive(Copy, Clone)]
+pub struct Foo;
+
+impl Foo {
+ pub fn run_trait(self) {
+ unsafe { COUNT *= 17; }
+ // Test internal call.
+ Bar::foo1(&self);
+ Bar::foo2(self);
+ Bar::foo3(Box::new(self));
+
+ Bar::bar1(&self);
+ Bar::bar2(self);
+ Bar::bar3(Box::new(self));
+ }
+}
+
+pub trait Bar : Sized {
+ fn foo1(&self);
+ fn foo2(self);
+ fn foo3(self: Box<Self>);
+
+ fn bar1(&self) {
+ unsafe { COUNT *= 7; }
+ }
+ fn bar2(self) {
+ unsafe { COUNT *= 11; }
+ }
+ fn bar3(self: Box<Self>) {
+ unsafe { COUNT *= 13; }
+ }
+}
+
+impl Bar for Foo {
+ fn foo1(&self) {
+ unsafe { COUNT *= 2; }
+ }
+
+ fn foo2(self) {
+ unsafe { COUNT *= 3; }
+ }
+
+ fn foo3(self: Box<Foo>) {
+ unsafe { COUNT *= 5; }
+ }
+}
diff --git a/src/test/ui/methods/issues/issue-61525.rs b/src/test/ui/methods/issues/issue-61525.rs
new file mode 100644
index 000000000..c5ca0326e
--- /dev/null
+++ b/src/test/ui/methods/issues/issue-61525.rs
@@ -0,0 +1,20 @@
+pub trait Example {
+ fn query<Q>(self, q: Q);
+}
+
+impl Example for i32 {
+ fn query<Q>(self, _: Q) {
+ unimplemented!()
+ }
+}
+
+mod nested {
+ use super::Example;
+ fn example() {
+ 1.query::<dyn ToString>("")
+ //~^ ERROR the size for values of type `dyn ToString` cannot be known at compilation time
+ //~| ERROR mismatched types
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/methods/issues/issue-61525.stderr b/src/test/ui/methods/issues/issue-61525.stderr
new file mode 100644
index 000000000..aec968d7c
--- /dev/null
+++ b/src/test/ui/methods/issues/issue-61525.stderr
@@ -0,0 +1,39 @@
+error[E0277]: the size for values of type `dyn ToString` cannot be known at compilation time
+ --> $DIR/issue-61525.rs:14:33
+ |
+LL | 1.query::<dyn ToString>("")
+ | ----- ^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `dyn ToString`
+note: required by a bound in `Example::query`
+ --> $DIR/issue-61525.rs:2:14
+ |
+LL | fn query<Q>(self, q: Q);
+ | ^ required by this bound in `Example::query`
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | fn query<Q: ?Sized>(self, q: Q);
+ | ++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/issue-61525.rs:14:33
+ |
+LL | 1.query::<dyn ToString>("")
+ | --------------------- ^^ expected trait object `dyn ToString`, found `&str`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected trait object `dyn ToString`
+ found reference `&'static str`
+note: associated function defined here
+ --> $DIR/issue-61525.rs:2:8
+ |
+LL | fn query<Q>(self, q: Q);
+ | ^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/methods/issues/issue-84495.rs b/src/test/ui/methods/issues/issue-84495.rs
new file mode 100644
index 000000000..28c094bf2
--- /dev/null
+++ b/src/test/ui/methods/issues/issue-84495.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let x: i32 = 1;
+ println!("{:?}", x.count()); //~ ERROR is not an iterator
+}
diff --git a/src/test/ui/methods/issues/issue-84495.stderr b/src/test/ui/methods/issues/issue-84495.stderr
new file mode 100644
index 000000000..b0217a7c8
--- /dev/null
+++ b/src/test/ui/methods/issues/issue-84495.stderr
@@ -0,0 +1,13 @@
+error[E0599]: `i32` is not an iterator
+ --> $DIR/issue-84495.rs:3:24
+ |
+LL | println!("{:?}", x.count());
+ | ^^^^^ `i32` is not an iterator
+ |
+ = note: the following trait bounds were not satisfied:
+ `i32: Iterator`
+ which is required by `&mut i32: Iterator`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/methods/issues/issue-90315.rs b/src/test/ui/methods/issues/issue-90315.rs
new file mode 100644
index 000000000..01bf9f484
--- /dev/null
+++ b/src/test/ui/methods/issues/issue-90315.rs
@@ -0,0 +1,7 @@
+fn main() {
+ let arr = &[0,1,2,3];
+ for _i in 0..arr.len().rev() { //~ERROR not an iterator
+ // The above error used to say “the method `rev` exists for type `usize`”.
+ // This regression test ensures it doesn't say that any more.
+ }
+}
diff --git a/src/test/ui/methods/issues/issue-90315.stderr b/src/test/ui/methods/issues/issue-90315.stderr
new file mode 100644
index 000000000..c6a76c9e7
--- /dev/null
+++ b/src/test/ui/methods/issues/issue-90315.stderr
@@ -0,0 +1,13 @@
+error[E0599]: `usize` is not an iterator
+ --> $DIR/issue-90315.rs:3:26
+ |
+LL | for _i in 0..arr.len().rev() {
+ | ^^^ `usize` is not an iterator
+ |
+ = note: the following trait bounds were not satisfied:
+ `usize: Iterator`
+ which is required by `&mut usize: Iterator`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/methods/issues/issue-94581.rs b/src/test/ui/methods/issues/issue-94581.rs
new file mode 100644
index 000000000..df393e91d
--- /dev/null
+++ b/src/test/ui/methods/issues/issue-94581.rs
@@ -0,0 +1,7 @@
+fn get_slice() -> &'static [i32] {
+ &[1, 2, 3, 4]
+}
+
+fn main() {
+ let sqsum = get_slice().map(|i| i * i).sum(); //~ ERROR [E0599]
+}
diff --git a/src/test/ui/methods/issues/issue-94581.stderr b/src/test/ui/methods/issues/issue-94581.stderr
new file mode 100644
index 000000000..d6be29cf5
--- /dev/null
+++ b/src/test/ui/methods/issues/issue-94581.stderr
@@ -0,0 +1,15 @@
+error[E0599]: `&'static [i32]` is not an iterator
+ --> $DIR/issue-94581.rs:6:29
+ |
+LL | let sqsum = get_slice().map(|i| i * i).sum();
+ | ^^^ `&'static [i32]` is not an iterator; try calling `.iter()`
+ |
+ = note: the following trait bounds were not satisfied:
+ `&'static [i32]: Iterator`
+ which is required by `&mut &'static [i32]: Iterator`
+ `[i32]: Iterator`
+ which is required by `&mut [i32]: Iterator`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs
new file mode 100644
index 000000000..7b2fc34e1
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs
@@ -0,0 +1,36 @@
+// Test that we invoking `foo()` successfully resolves to the trait `Foo`
+// (prompting the mismatched types error) but does not influence the choice
+// of what kind of `Vec` we have, eventually leading to a type error.
+
+trait Foo {
+ fn foo(&self) -> isize;
+}
+
+impl Foo for Vec<usize> {
+ fn foo(&self) -> isize {1}
+}
+
+impl Foo for Vec<isize> {
+ fn foo(&self) -> isize {2}
+}
+
+// This is very hokey: we have heuristics to suppress messages about
+// type annotations needed. But placing these two bits of code into
+// distinct functions, in this order, causes us to print out both
+// errors I'd like to see.
+
+fn m1() {
+ // we couldn't infer the type of the vector just based on calling foo()...
+ let mut x = Vec::new();
+ //~^ ERROR type annotations needed
+ x.foo(); //~ ERROR type annotations needed
+}
+
+fn m2() {
+ let mut x = Vec::new();
+
+ // ...but we still resolved `foo()` to the trait and hence know the return type.
+ let y: usize = x.foo(); //~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
new file mode 100644
index 000000000..e0f8a5447
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
@@ -0,0 +1,47 @@
+error[E0282]: type annotations needed for `Vec<T>`
+ --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:9
+ |
+LL | let mut x = Vec::new();
+ | ^^^^^
+ |
+help: consider giving `x` an explicit type, where the type for type parameter `T` is specified
+ |
+LL | let mut x: Vec<T> = Vec::new();
+ | ++++++++
+
+error[E0283]: type annotations needed
+ --> $DIR/method-ambig-one-trait-unknown-int-type.rs:26:7
+ |
+LL | x.foo();
+ | ^^^
+ |
+note: multiple `impl`s satisfying `Vec<_>: Foo` found
+ --> $DIR/method-ambig-one-trait-unknown-int-type.rs:9:1
+ |
+LL | impl Foo for Vec<usize> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Foo for Vec<isize> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+help: try using a fully qualified path to specify the expected types
+ |
+LL | <Vec<T> as Foo>::foo(&x);
+ | ++++++++++++++++++++++ ~
+
+error[E0308]: mismatched types
+ --> $DIR/method-ambig-one-trait-unknown-int-type.rs:33:20
+ |
+LL | let y: usize = x.foo();
+ | ----- ^^^^^^^ expected `usize`, found `isize`
+ | |
+ | expected due to this
+ |
+help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
+ |
+LL | let y: usize = x.foo().try_into().unwrap();
+ | ++++++++++++++++++++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0282, E0283, E0308.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/methods/method-ambig-two-traits-cross-crate.rs b/src/test/ui/methods/method-ambig-two-traits-cross-crate.rs
new file mode 100644
index 000000000..006e315b0
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-cross-crate.rs
@@ -0,0 +1,11 @@
+// Test an ambiguity scenario where one copy of the method is available
+// from a trait imported from another crate.
+
+// aux-build:ambig_impl_2_lib.rs
+extern crate ambig_impl_2_lib;
+use ambig_impl_2_lib::Me;
+trait Me2 {
+ fn me(&self) -> usize;
+}
+impl Me2 for usize { fn me(&self) -> usize { *self } }
+fn main() { 1_usize.me(); } //~ ERROR E0034
diff --git a/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr b/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr
new file mode 100644
index 000000000..4b2597eed
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr
@@ -0,0 +1,24 @@
+error[E0034]: multiple applicable items in scope
+ --> $DIR/method-ambig-two-traits-cross-crate.rs:11:21
+ |
+LL | fn main() { 1_usize.me(); }
+ | ^^ multiple `me` found
+ |
+ = note: candidate #1 is defined in an impl of the trait `Me` for the type `usize`
+note: candidate #2 is defined in an impl of the trait `Me2` for the type `usize`
+ --> $DIR/method-ambig-two-traits-cross-crate.rs:10:22
+ |
+LL | impl Me2 for usize { fn me(&self) -> usize { *self } }
+ | ^^^^^^^^^^^^^^^^^^^^^
+help: disambiguate the associated function for candidate #1
+ |
+LL | fn main() { Me::me(&1_usize); }
+ | ~~~~~~~~~~~~~~~~
+help: disambiguate the associated function for candidate #2
+ |
+LL | fn main() { Me2::me(&1_usize); }
+ | ~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/methods/method-ambig-two-traits-from-bounds.rs b/src/test/ui/methods/method-ambig-two-traits-from-bounds.rs
new file mode 100644
index 000000000..e3cc5557f
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-from-bounds.rs
@@ -0,0 +1,8 @@
+trait A { fn foo(&self); }
+trait B { fn foo(&self); }
+
+fn foo<T:A + B>(t: T) {
+ t.foo(); //~ ERROR E0034
+}
+
+fn main() {}
diff --git a/src/test/ui/methods/method-ambig-two-traits-from-bounds.stderr b/src/test/ui/methods/method-ambig-two-traits-from-bounds.stderr
new file mode 100644
index 000000000..1feaa2c73
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-from-bounds.stderr
@@ -0,0 +1,28 @@
+error[E0034]: multiple applicable items in scope
+ --> $DIR/method-ambig-two-traits-from-bounds.rs:5:7
+ |
+LL | t.foo();
+ | ^^^ multiple `foo` found
+ |
+note: candidate #1 is defined in the trait `A`
+ --> $DIR/method-ambig-two-traits-from-bounds.rs:1:11
+ |
+LL | trait A { fn foo(&self); }
+ | ^^^^^^^^^^^^^^
+note: candidate #2 is defined in the trait `B`
+ --> $DIR/method-ambig-two-traits-from-bounds.rs:2:11
+ |
+LL | trait B { fn foo(&self); }
+ | ^^^^^^^^^^^^^^
+help: disambiguate the associated function for candidate #1
+ |
+LL | A::foo(t);
+ | ~~~~~~~~~
+help: disambiguate the associated function for candidate #2
+ |
+LL | B::foo(t);
+ | ~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/methods/method-ambig-two-traits-from-impls.rs b/src/test/ui/methods/method-ambig-two-traits-from-impls.rs
new file mode 100644
index 000000000..22bf84066
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-from-impls.rs
@@ -0,0 +1,16 @@
+trait A { fn foo(self); }
+trait B { fn foo(self); }
+
+struct AB {}
+
+impl A for AB {
+ fn foo(self) {}
+}
+
+impl B for AB {
+ fn foo(self) {}
+}
+
+fn main() {
+ AB {}.foo(); //~ ERROR E0034
+}
diff --git a/src/test/ui/methods/method-ambig-two-traits-from-impls.stderr b/src/test/ui/methods/method-ambig-two-traits-from-impls.stderr
new file mode 100644
index 000000000..f69b56892
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-from-impls.stderr
@@ -0,0 +1,28 @@
+error[E0034]: multiple applicable items in scope
+ --> $DIR/method-ambig-two-traits-from-impls.rs:15:11
+ |
+LL | AB {}.foo();
+ | ^^^ multiple `foo` found
+ |
+note: candidate #1 is defined in an impl of the trait `A` for the type `AB`
+ --> $DIR/method-ambig-two-traits-from-impls.rs:7:5
+ |
+LL | fn foo(self) {}
+ | ^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `B` for the type `AB`
+ --> $DIR/method-ambig-two-traits-from-impls.rs:11:5
+ |
+LL | fn foo(self) {}
+ | ^^^^^^^^^^^^
+help: disambiguate the associated function for candidate #1
+ |
+LL | A::foo(AB {});
+ | ~~~~~~~~~~~~~
+help: disambiguate the associated function for candidate #2
+ |
+LL | B::foo(AB {});
+ | ~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/methods/method-ambig-two-traits-from-impls2.rs b/src/test/ui/methods/method-ambig-two-traits-from-impls2.rs
new file mode 100644
index 000000000..0a96c1223
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-from-impls2.rs
@@ -0,0 +1,16 @@
+trait A { fn foo(); }
+trait B { fn foo(); }
+
+struct AB {}
+
+impl A for AB {
+ fn foo() {}
+}
+
+impl B for AB {
+ fn foo() {}
+}
+
+fn main() {
+ AB::foo(); //~ ERROR E0034
+}
diff --git a/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr b/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr
new file mode 100644
index 000000000..4ba778e0e
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr
@@ -0,0 +1,28 @@
+error[E0034]: multiple applicable items in scope
+ --> $DIR/method-ambig-two-traits-from-impls2.rs:15:9
+ |
+LL | AB::foo();
+ | ^^^ multiple `foo` found
+ |
+note: candidate #1 is defined in an impl of the trait `A` for the type `AB`
+ --> $DIR/method-ambig-two-traits-from-impls2.rs:7:5
+ |
+LL | fn foo() {}
+ | ^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `B` for the type `AB`
+ --> $DIR/method-ambig-two-traits-from-impls2.rs:11:5
+ |
+LL | fn foo() {}
+ | ^^^^^^^^
+help: disambiguate the associated function for candidate #1
+ |
+LL | <AB as A>::foo();
+ | ~~~~~~~~~~~
+help: disambiguate the associated function for candidate #2
+ |
+LL | <AB as B>::foo();
+ | ~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/methods/method-ambig-two-traits-with-default-method.rs b/src/test/ui/methods/method-ambig-two-traits-with-default-method.rs
new file mode 100644
index 000000000..aa7094b9e
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-with-default-method.rs
@@ -0,0 +1,13 @@
+// Test that we correctly report an ambiguity where two applicable traits
+// are in scope and the method being invoked is a default method not
+// defined directly in the impl.
+
+trait Foo { fn method(&self) {} }
+trait Bar { fn method(&self) {} }
+
+impl Foo for usize {}
+impl Bar for usize {}
+
+fn main() {
+ 1_usize.method(); //~ ERROR E0034
+}
diff --git a/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr b/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr
new file mode 100644
index 000000000..e84dff8ba
--- /dev/null
+++ b/src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr
@@ -0,0 +1,28 @@
+error[E0034]: multiple applicable items in scope
+ --> $DIR/method-ambig-two-traits-with-default-method.rs:12:13
+ |
+LL | 1_usize.method();
+ | ^^^^^^ multiple `method` found
+ |
+note: candidate #1 is defined in an impl of the trait `Foo` for the type `usize`
+ --> $DIR/method-ambig-two-traits-with-default-method.rs:5:13
+ |
+LL | trait Foo { fn method(&self) {} }
+ | ^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `Bar` for the type `usize`
+ --> $DIR/method-ambig-two-traits-with-default-method.rs:6:13
+ |
+LL | trait Bar { fn method(&self) {} }
+ | ^^^^^^^^^^^^^^^^
+help: disambiguate the associated function for candidate #1
+ |
+LL | Foo::method(&1_usize);
+ | ~~~~~~~~~~~~~~~~~~~~~
+help: disambiguate the associated function for candidate #2
+ |
+LL | Bar::method(&1_usize);
+ | ~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/methods/method-argument-inference-associated-type.rs b/src/test/ui/methods/method-argument-inference-associated-type.rs
new file mode 100644
index 000000000..a3c31fab1
--- /dev/null
+++ b/src/test/ui/methods/method-argument-inference-associated-type.rs
@@ -0,0 +1,28 @@
+// run-pass
+pub struct ClientMap;
+pub struct ClientMap2;
+
+pub trait Service {
+ type Request;
+ fn call(&self, _req: Self::Request);
+}
+
+pub struct S<T>(#[allow(unused_tuple_struct_fields)] T);
+
+impl Service for ClientMap {
+ type Request = S<Box<dyn Fn(i32)>>;
+ fn call(&self, _req: Self::Request) {}
+}
+
+
+impl Service for ClientMap2 {
+ type Request = (Box<dyn Fn(i32)>,);
+ fn call(&self, _req: Self::Request) {}
+}
+
+
+fn main() {
+ ClientMap.call(S { 0: Box::new(|_msgid| ()) });
+ ClientMap.call(S(Box::new(|_msgid| ())));
+ ClientMap2.call((Box::new(|_msgid| ()),));
+}
diff --git a/src/test/ui/methods/method-call-err-msg.rs b/src/test/ui/methods/method-call-err-msg.rs
new file mode 100644
index 000000000..d53ef445a
--- /dev/null
+++ b/src/test/ui/methods/method-call-err-msg.rs
@@ -0,0 +1,22 @@
+// Test that parameter cardinality or missing method error gets span exactly.
+
+pub struct Foo;
+impl Foo {
+ fn zero(self) -> Foo { self }
+ fn one(self, _: isize) -> Foo { self }
+ fn two(self, _: isize, _: isize) -> Foo { self }
+ fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
+}
+
+fn main() {
+ let x = Foo;
+ x.zero(0) //~ ERROR this function takes 0 arguments but 1 argument was supplied
+ .one() //~ ERROR this function takes 1 argument but 0 arguments were supplied
+ .two(0); //~ ERROR this function takes 2 arguments but 1 argument was supplied
+
+ let y = Foo;
+ y.zero()
+ .take() //~ ERROR not an iterator
+ .one(0);
+ y.three::<usize>(); //~ ERROR this function takes 3 arguments but 0 arguments were supplied
+}
diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr
new file mode 100644
index 000000000..690fe8fa7
--- /dev/null
+++ b/src/test/ui/methods/method-call-err-msg.stderr
@@ -0,0 +1,92 @@
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+ --> $DIR/method-call-err-msg.rs:13:7
+ |
+LL | x.zero(0)
+ | ^^^^ - argument of type `{integer}` unexpected
+ |
+note: associated function defined here
+ --> $DIR/method-call-err-msg.rs:5:8
+ |
+LL | fn zero(self) -> Foo { self }
+ | ^^^^ ----
+help: remove the extra argument
+ |
+LL | x.zero()
+ | ~~~~~~
+
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+ --> $DIR/method-call-err-msg.rs:14:7
+ |
+LL | .one()
+ | ^^^-- an argument of type `isize` is missing
+ |
+note: associated function defined here
+ --> $DIR/method-call-err-msg.rs:6:8
+ |
+LL | fn one(self, _: isize) -> Foo { self }
+ | ^^^ ---- --------
+help: provide the argument
+ |
+LL | .one(/* isize */)
+ | ~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+ --> $DIR/method-call-err-msg.rs:15:7
+ |
+LL | .two(0);
+ | ^^^--- an argument of type `isize` is missing
+ |
+note: associated function defined here
+ --> $DIR/method-call-err-msg.rs:7:8
+ |
+LL | fn two(self, _: isize, _: isize) -> Foo { self }
+ | ^^^ ---- -------- --------
+help: provide the argument
+ |
+LL | .two(0, /* isize */);
+ | ~~~~~~~~~~~~~~~~~~~
+
+error[E0599]: `Foo` is not an iterator
+ --> $DIR/method-call-err-msg.rs:19:7
+ |
+LL | pub struct Foo;
+ | --------------
+ | |
+ | method `take` not found for this struct
+ | doesn't satisfy `Foo: Iterator`
+...
+LL | .take()
+ | ^^^^ `Foo` is not an iterator
+ |
+ = note: the following trait bounds were not satisfied:
+ `Foo: Iterator`
+ which is required by `&mut Foo: Iterator`
+note: the following trait must be implemented
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+ |
+LL | pub trait Iterator {
+ | ^^^^^^^^^^^^^^^^^^
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the following trait defines an item `take`, perhaps you need to implement it:
+ candidate #1: `Iterator`
+
+error[E0061]: this function takes 3 arguments but 0 arguments were supplied
+ --> $DIR/method-call-err-msg.rs:21:7
+ |
+LL | y.three::<usize>();
+ | ^^^^^^^^^^^^^^-- three arguments of type `usize`, `usize`, and `usize` are missing
+ |
+note: associated function defined here
+ --> $DIR/method-call-err-msg.rs:8:8
+ |
+LL | fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
+ | ^^^^^ ---- ---- ---- ----
+help: provide the arguments
+ |
+LL | y.three::<usize>(/* usize */, /* usize */, /* usize */);
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0061, E0599.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/src/test/ui/methods/method-call-lifetime-args-fail.rs b/src/test/ui/methods/method-call-lifetime-args-fail.rs
new file mode 100644
index 000000000..6bf55844d
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-fail.rs
@@ -0,0 +1,72 @@
+struct S;
+
+impl S {
+ fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ fn late_implicit(self, _: &u8, _: &u8) {}
+ fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+ fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+ fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+ fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
+ fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
+ fn life_and_type<'a, T>(self) -> &'a T { loop {} }
+}
+
+fn method_call() {
+ S.early(); // OK
+ S.early::<'static>();
+ //~^ ERROR this associated function takes 2 lifetime arguments but 1 lifetime argument
+ S.early::<'static, 'static, 'static>();
+ //~^ ERROR this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
+ let _: &u8 = S.life_and_type::<'static>();
+ S.life_and_type::<u8>();
+ S.life_and_type::<'static, u8>();
+}
+
+fn ufcs() {
+ S::late(S, &0, &0); // OK
+ S::late::<'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late::<'static, 'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late::<'static, 'static, 'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_early(S, &0); // OK
+ S::late_early::<'static, 'static>(S, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_early::<'static, 'static, 'static>(S, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+
+ S::late_implicit(S, &0, &0); // OK
+ S::late_implicit::<'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_implicit::<'static, 'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_implicit::<'static, 'static, 'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_implicit_early(S, &0); // OK
+ S::late_implicit_early::<'static, 'static>(S, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_implicit_early::<'static, 'static, 'static>(S, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_implicit_self_early(&S); // OK
+ S::late_implicit_self_early::<'static, 'static>(&S);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_implicit_self_early::<'static, 'static, 'static>(&S);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_unused_early(S); // OK
+ S::late_unused_early::<'static, 'static>(S);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_unused_early::<'static, 'static, 'static>(S);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+
+ S::early(S); // OK
+ S::early::<'static>(S);
+ //~^ ERROR this associated function takes 2 lifetime arguments but 1 lifetime argument
+ S::early::<'static, 'static, 'static>(S);
+ //~^ ERROR this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
+ let _: &u8 = S::life_and_type::<'static>(S);
+ S::life_and_type::<u8>(S);
+ S::life_and_type::<'static, u8>(S);
+}
+
+fn main() {}
diff --git a/src/test/ui/methods/method-call-lifetime-args-fail.stderr b/src/test/ui/methods/method-call-lifetime-args-fail.stderr
new file mode 100644
index 000000000..835edb4b0
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-fail.stderr
@@ -0,0 +1,235 @@
+error[E0107]: this associated function takes 2 lifetime arguments but 1 lifetime argument was supplied
+ --> $DIR/method-call-lifetime-args-fail.rs:16:7
+ |
+LL | S.early::<'static>();
+ | ^^^^^ ------- supplied 1 lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+ --> $DIR/method-call-lifetime-args-fail.rs:6:8
+ |
+LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+ | ^^^^^ -- --
+help: add missing lifetime argument
+ |
+LL | S.early::<'static, 'b>();
+ | ++++
+
+error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
+ --> $DIR/method-call-lifetime-args-fail.rs:18:7
+ |
+LL | S.early::<'static, 'static, 'static>();
+ | ^^^^^ ------- help: remove this lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+ --> $DIR/method-call-lifetime-args-fail.rs:6:8
+ |
+LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+ | ^^^^^ -- --
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:27:15
+ |
+LL | S::late::<'static>(S, &0, &0);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:4:13
+ |
+LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ | ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:29:15
+ |
+LL | S::late::<'static, 'static>(S, &0, &0);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:4:13
+ |
+LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ | ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:31:15
+ |
+LL | S::late::<'static, 'static, 'static>(S, &0, &0);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:4:13
+ |
+LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ | ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:34:21
+ |
+LL | S::late_early::<'static, 'static>(S, &0);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:7:19
+ |
+LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+ | ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:36:21
+ |
+LL | S::late_early::<'static, 'static, 'static>(S, &0);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:7:19
+ |
+LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+ | ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:40:24
+ |
+LL | S::late_implicit::<'static>(S, &0, &0);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:5:31
+ |
+LL | fn late_implicit(self, _: &u8, _: &u8) {}
+ | ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:42:24
+ |
+LL | S::late_implicit::<'static, 'static>(S, &0, &0);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:5:31
+ |
+LL | fn late_implicit(self, _: &u8, _: &u8) {}
+ | ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:44:24
+ |
+LL | S::late_implicit::<'static, 'static, 'static>(S, &0, &0);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:5:31
+ |
+LL | fn late_implicit(self, _: &u8, _: &u8) {}
+ | ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:47:30
+ |
+LL | S::late_implicit_early::<'static, 'static>(S, &0);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:8:41
+ |
+LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+ | ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:49:30
+ |
+LL | S::late_implicit_early::<'static, 'static, 'static>(S, &0);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:8:41
+ |
+LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+ | ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:52:35
+ |
+LL | S::late_implicit_self_early::<'static, 'static>(&S);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:9:37
+ |
+LL | fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
+ | ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:54:35
+ |
+LL | S::late_implicit_self_early::<'static, 'static, 'static>(&S);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:9:37
+ |
+LL | fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
+ | ^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:57:28
+ |
+LL | S::late_unused_early::<'static, 'static>(S);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:10:26
+ |
+LL | fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
+ | ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-fail.rs:59:28
+ |
+LL | S::late_unused_early::<'static, 'static, 'static>(S);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args-fail.rs:10:26
+ |
+LL | fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
+ | ^^
+
+error[E0107]: this associated function takes 2 lifetime arguments but 1 lifetime argument was supplied
+ --> $DIR/method-call-lifetime-args-fail.rs:63:8
+ |
+LL | S::early::<'static>(S);
+ | ^^^^^ ------- supplied 1 lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+ --> $DIR/method-call-lifetime-args-fail.rs:6:8
+ |
+LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+ | ^^^^^ -- --
+help: add missing lifetime argument
+ |
+LL | S::early::<'static, 'b>(S);
+ | ++++
+
+error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
+ --> $DIR/method-call-lifetime-args-fail.rs:65:8
+ |
+LL | S::early::<'static, 'static, 'static>(S);
+ | ^^^^^ ------- help: remove this lifetime argument
+ | |
+ | expected 2 lifetime arguments
+ |
+note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+ --> $DIR/method-call-lifetime-args-fail.rs:6:8
+ |
+LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+ | ^^^^^ -- --
+
+error: aborting due to 18 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/methods/method-call-lifetime-args-lint-fail.rs b/src/test/ui/methods/method-call-lifetime-args-lint-fail.rs
new file mode 100644
index 000000000..23893911e
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-lint-fail.rs
@@ -0,0 +1,87 @@
+#![deny(late_bound_lifetime_arguments)]
+#![allow(unused)]
+
+struct S;
+
+impl S {
+ fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ fn late_implicit(self, _: &u8, _: &u8) {}
+ fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+ fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+
+ // 'late lifetimes here belong to nested types not to the tested functions.
+ fn early_tricky_explicit<'a>(_: for<'late> fn(&'late u8),
+ _: Box<dyn for<'late> Fn(&'late u8)>)
+ -> &'a u8 { loop {} }
+ fn early_tricky_implicit<'a>(_: fn(&u8),
+ _: Box<dyn Fn(&u8)>)
+ -> &'a u8 { loop {} }
+}
+
+fn method_call() {
+ S.late(&0, &0); // OK
+ S.late::<'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late::<'static, 'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late::<'static, 'static, 'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_early(&0); // OK
+ S.late_early::<'static>(&0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_early::<'static, 'static>(&0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_early::<'static, 'static, 'static>(&0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+
+ S.late_implicit(&0, &0); // OK
+ S.late_implicit::<'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_implicit::<'static, 'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_implicit::<'static, 'static, 'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_implicit_early(&0); // OK
+ S.late_implicit_early::<'static>(&0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_implicit_early::<'static, 'static>(&0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_implicit_early::<'static, 'static, 'static>(&0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+
+ S::early_tricky_explicit::<'static>(loop {}, loop {}); // OK
+ S::early_tricky_implicit::<'static>(loop {}, loop {}); // OK
+}
+
+fn ufcs() {
+ S::late_early::<'static>(S, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+
+ S::late_implicit_early::<'static>(S, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+}
+
+fn lint_not_inference_error() {
+ fn f<'early, 'late, T: 'early>() {}
+
+ // Make sure `u8` is substituted and not replaced with an inference variable
+ f::<'static, u8>;
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+}
+
+fn main() {}
diff --git a/src/test/ui/methods/method-call-lifetime-args-lint-fail.stderr b/src/test/ui/methods/method-call-lifetime-args-lint-fail.stderr
new file mode 100644
index 000000000..9e07d5ea3
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-lint-fail.stderr
@@ -0,0 +1,187 @@
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:23:14
+ |
+LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ | -- the late bound lifetime parameter is introduced here
+...
+LL | S.late::<'static>(&0, &0);
+ | ^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:1:9
+ |
+LL | #![deny(late_bound_lifetime_arguments)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:26:14
+ |
+LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ | -- the late bound lifetime parameter is introduced here
+...
+LL | S.late::<'static, 'static>(&0, &0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:29:14
+ |
+LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ | -- the late bound lifetime parameter is introduced here
+...
+LL | S.late::<'static, 'static, 'static>(&0, &0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:33:20
+ |
+LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+ | -- the late bound lifetime parameter is introduced here
+...
+LL | S.late_early::<'static>(&0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:36:20
+ |
+LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+ | -- the late bound lifetime parameter is introduced here
+...
+LL | S.late_early::<'static, 'static>(&0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:39:20
+ |
+LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+ | -- the late bound lifetime parameter is introduced here
+...
+LL | S.late_early::<'static, 'static, 'static>(&0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:44:23
+ |
+LL | fn late_implicit(self, _: &u8, _: &u8) {}
+ | - the late bound lifetime parameter is introduced here
+...
+LL | S.late_implicit::<'static>(&0, &0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:47:23
+ |
+LL | fn late_implicit(self, _: &u8, _: &u8) {}
+ | - the late bound lifetime parameter is introduced here
+...
+LL | S.late_implicit::<'static, 'static>(&0, &0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:50:23
+ |
+LL | fn late_implicit(self, _: &u8, _: &u8) {}
+ | - the late bound lifetime parameter is introduced here
+...
+LL | S.late_implicit::<'static, 'static, 'static>(&0, &0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:54:29
+ |
+LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+ | - the late bound lifetime parameter is introduced here
+...
+LL | S.late_implicit_early::<'static>(&0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:57:29
+ |
+LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+ | - the late bound lifetime parameter is introduced here
+...
+LL | S.late_implicit_early::<'static, 'static>(&0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:60:29
+ |
+LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+ | - the late bound lifetime parameter is introduced here
+...
+LL | S.late_implicit_early::<'static, 'static, 'static>(&0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:69:21
+ |
+LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+ | -- the late bound lifetime parameter is introduced here
+...
+LL | S::late_early::<'static>(S, &0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:73:30
+ |
+LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+ | - the late bound lifetime parameter is introduced here
+...
+LL | S::late_implicit_early::<'static>(S, &0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint-fail.rs:82:9
+ |
+LL | fn f<'early, 'late, T: 'early>() {}
+ | ----- the late bound lifetime parameter is introduced here
+...
+LL | f::<'static, u8>;
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: aborting due to 15 previous errors
+
diff --git a/src/test/ui/methods/method-call-lifetime-args-lint.rs b/src/test/ui/methods/method-call-lifetime-args-lint.rs
new file mode 100644
index 000000000..14729e1e2
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-lint.rs
@@ -0,0 +1,21 @@
+#![deny(late_bound_lifetime_arguments)]
+#![allow(unused)]
+
+struct S;
+
+impl S {
+ fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ fn late_implicit(self, _: &u8, _: &u8) {}
+}
+
+fn method_call() {
+ S.late::<'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+
+ S.late_implicit::<'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+}
+
+fn main() {}
diff --git a/src/test/ui/methods/method-call-lifetime-args-lint.stderr b/src/test/ui/methods/method-call-lifetime-args-lint.stderr
new file mode 100644
index 000000000..f31f510a3
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-lint.stderr
@@ -0,0 +1,31 @@
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint.rs:12:14
+ |
+LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ | -- the late bound lifetime parameter is introduced here
+...
+LL | S.late::<'static>(&0, &0);
+ | ^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/method-call-lifetime-args-lint.rs:1:9
+ |
+LL | #![deny(late_bound_lifetime_arguments)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-lint.rs:16:23
+ |
+LL | fn late_implicit(self, _: &u8, _: &u8) {}
+ | - the late bound lifetime parameter is introduced here
+...
+LL | S.late_implicit::<'static>(&0, &0);
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/methods/method-call-lifetime-args-subst-index.rs b/src/test/ui/methods/method-call-lifetime-args-subst-index.rs
new file mode 100644
index 000000000..8df58a348
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-subst-index.rs
@@ -0,0 +1,15 @@
+// build-pass (FIXME(62277): could be check-pass?)
+#![allow(unused)]
+
+struct S;
+
+impl S {
+ fn early_and_type<'a, T>(self) -> &'a T { loop {} }
+}
+
+fn test() {
+ S.early_and_type::<u16>();
+}
+
+
+fn main() {}
diff --git a/src/test/ui/methods/method-call-lifetime-args-unresolved.rs b/src/test/ui/methods/method-call-lifetime-args-unresolved.rs
new file mode 100644
index 000000000..ba7231070
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-unresolved.rs
@@ -0,0 +1,6 @@
+fn main() {
+ 0.clone::<'a>();
+ //~^ ERROR use of undeclared lifetime name `'a`
+ //~| WARN cannot specify lifetime arguments explicitly if late bound
+ //~| WARN this was previously accepted by the compiler
+}
diff --git a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
new file mode 100644
index 000000000..78af19586
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
@@ -0,0 +1,26 @@
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/method-call-lifetime-args-unresolved.rs:2:15
+ |
+LL | fn main() {
+ | - help: consider introducing lifetime `'a` here: `<'a>`
+LL | 0.clone::<'a>();
+ | ^^ undeclared lifetime
+
+warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-unresolved.rs:2:15
+ |
+LL | 0.clone::<'a>();
+ | ^^
+ |
+ ::: $SRC_DIR/core/src/clone.rs:LL:COL
+ |
+LL | fn clone(&self) -> Self;
+ | - the late bound lifetime parameter is introduced here
+ |
+ = note: `#[warn(late_bound_lifetime_arguments)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/methods/method-call-lifetime-args.rs b/src/test/ui/methods/method-call-lifetime-args.rs
new file mode 100644
index 000000000..3292e9fcd
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args.rs
@@ -0,0 +1,15 @@
+struct S;
+
+impl S {
+ fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ fn late_implicit(self, _: &u8, _: &u8) {}
+}
+
+fn ufcs() {
+ S::late::<'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_implicit::<'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+}
+
+fn main() {}
diff --git a/src/test/ui/methods/method-call-lifetime-args.stderr b/src/test/ui/methods/method-call-lifetime-args.stderr
new file mode 100644
index 000000000..64ae79e9b
--- /dev/null
+++ b/src/test/ui/methods/method-call-lifetime-args.stderr
@@ -0,0 +1,26 @@
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args.rs:9:15
+ |
+LL | S::late::<'static>(S, &0, &0);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args.rs:4:13
+ |
+LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ | ^^
+
+error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args.rs:11:24
+ |
+LL | S::late_implicit::<'static>(S, &0, &0);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/method-call-lifetime-args.rs:5:31
+ |
+LL | fn late_implicit(self, _: &u8, _: &u8) {}
+ | ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/methods/method-call-type-binding.rs b/src/test/ui/methods/method-call-type-binding.rs
new file mode 100644
index 000000000..f547ca8d1
--- /dev/null
+++ b/src/test/ui/methods/method-call-type-binding.rs
@@ -0,0 +1,3 @@
+fn main() {
+ 0.clone::<T = u8>(); //~ ERROR associated type bindings are not allowed here
+}
diff --git a/src/test/ui/methods/method-call-type-binding.stderr b/src/test/ui/methods/method-call-type-binding.stderr
new file mode 100644
index 000000000..4b93082ac
--- /dev/null
+++ b/src/test/ui/methods/method-call-type-binding.stderr
@@ -0,0 +1,9 @@
+error[E0229]: associated type bindings are not allowed here
+ --> $DIR/method-call-type-binding.rs:2:15
+ |
+LL | 0.clone::<T = u8>();
+ | ^^^^^^ associated type not allowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
new file mode 100644
index 000000000..9e53ff079
--- /dev/null
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
@@ -0,0 +1,179 @@
+#![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize)]
+#![feature(unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete
+
+// This tests a few edge-cases around `arbitrary_self_types`. Most specifically,
+// it checks that the `ObjectCandidate` you get from method matching can't
+// match a trait with the same DefId as a supertrait but a bad type parameter.
+
+use std::marker::PhantomData;
+
+mod internal {
+ use std::ops::{CoerceUnsized, Deref, DispatchFromDyn};
+ use std::marker::{PhantomData, Unsize};
+
+ pub struct Smaht<T: ?Sized, MISC>(pub Box<T>, pub PhantomData<MISC>);
+
+ impl<T: ?Sized, MISC> Deref for Smaht<T, MISC> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+ }
+ impl<T: ?Sized + Unsize<U>, U: ?Sized, MISC> CoerceUnsized<Smaht<U, MISC>>
+ for Smaht<T, MISC>
+ {}
+ impl<T: ?Sized + Unsize<U>, U: ?Sized, MISC> DispatchFromDyn<Smaht<U, MISC>>
+ for Smaht<T, MISC>
+ {}
+
+ pub trait Foo: X<u32> {}
+ pub trait X<T> {
+ fn foo(self: Smaht<Self, T>) -> T;
+ }
+
+ impl X<u32> for () {
+ fn foo(self: Smaht<Self, u32>) -> u32 {
+ 0
+ }
+ }
+
+ pub trait Marker {}
+ impl Marker for dyn Foo {}
+ impl<T: Marker + ?Sized> X<u64> for T {
+ fn foo(self: Smaht<Self, u64>) -> u64 {
+ 1
+ }
+ }
+
+ impl Deref for dyn Foo {
+ type Target = ();
+ fn deref(&self) -> &() { &() }
+ }
+
+ impl Foo for () {}
+}
+
+pub trait FinalFoo {
+ fn foo(&self) -> u8;
+}
+
+impl FinalFoo for () {
+ fn foo(&self) -> u8 { 0 }
+}
+
+mod nuisance_foo {
+ pub trait NuisanceFoo {
+ fn foo(self);
+ }
+
+ impl<T: ?Sized> NuisanceFoo for T {
+ fn foo(self) {}
+ }
+}
+
+
+fn objectcandidate_impl() {
+ let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData);
+ let x: internal::Smaht<dyn internal::Foo, u32> = x;
+
+ // This picks `<dyn internal::Foo as X<u32>>::foo` via `ObjectCandidate`.
+ //
+ // The `TraitCandidate` is not relevant because `X` is not in scope.
+ let z = x.foo();
+
+ // Observe the type of `z` is `u32`
+ let _seetype: () = z; //~ ERROR mismatched types
+ //~| expected `()`, found `u32`
+}
+
+fn traitcandidate_impl() {
+ use internal::X;
+
+ let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData);
+ let x: internal::Smaht<dyn internal::Foo, u64> = x;
+
+ // This picks `<dyn internal::Foo as X<u64>>::foo` via `TraitCandidate`.
+ //
+ // The `ObjectCandidate` does not apply, as it only applies to
+ // `X<u32>` (and not `X<u64>`).
+ let z = x.foo();
+
+ // Observe the type of `z` is `u64`
+ let _seetype: () = z; //~ ERROR mismatched types
+ //~| expected `()`, found `u64`
+}
+
+fn traitcandidate_impl_with_nuisance() {
+ use internal::X;
+ use nuisance_foo::NuisanceFoo;
+
+ let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData);
+ let x: internal::Smaht<dyn internal::Foo, u64> = x;
+
+ // This picks `<dyn internal::Foo as X<u64>>::foo` via `TraitCandidate`.
+ //
+ // The `ObjectCandidate` does not apply, as it only applies to
+ // `X<u32>` (and not `X<u64>`).
+ //
+ // The NuisanceFoo impl has the same priority as the `X` impl,
+ // so we get a conflict.
+ let z = x.foo(); //~ ERROR multiple applicable items in scope
+}
+
+
+fn neither_impl() {
+ let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData);
+ let x: internal::Smaht<dyn internal::Foo, u64> = x;
+
+ // This can't pick the `TraitCandidate` impl, because `Foo` is not
+ // imported. However, this also can't pick the `ObjectCandidate`
+ // impl, because it only applies to `X<u32>` (and not `X<u64>`).
+ //
+ // Therefore, neither of the candidates is applicable, and we pick
+ // the `FinalFoo` impl after another deref, which will return `u8`.
+ let z = x.foo();
+
+ // Observe the type of `z` is `u8`
+ let _seetype: () = z; //~ ERROR mismatched types
+ //~| expected `()`, found `u8`
+}
+
+fn both_impls() {
+ use internal::X;
+
+ let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData);
+ let x: internal::Smaht<dyn internal::Foo, u32> = x;
+
+ // This can pick both the `TraitCandidate` and the `ObjectCandidate` impl.
+ //
+ // However, the `ObjectCandidate` is considered an "inherent candidate",
+ // and therefore has priority over both the `TraitCandidate` as well as
+ // any other "nuisance" candidate" (if present).
+ let z = x.foo();
+
+ // Observe the type of `z` is `u32`
+ let _seetype: () = z; //~ ERROR mismatched types
+ //~| expected `()`, found `u32`
+}
+
+
+fn both_impls_with_nuisance() {
+ // Similar to the `both_impls` example, except with a nuisance impl to
+ // make sure the `ObjectCandidate` indeed has a higher priority.
+
+ use internal::X;
+ use nuisance_foo::NuisanceFoo;
+
+ let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData);
+ let x: internal::Smaht<dyn internal::Foo, u32> = x;
+ let z = x.foo();
+
+ // Observe the type of `z` is `u32`
+ let _seetype: () = z; //~ ERROR mismatched types
+ //~| expected `()`, found `u32`
+}
+
+fn main() {
+}
diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
new file mode 100644
index 000000000..59075397e
--- /dev/null
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
@@ -0,0 +1,87 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:2:12
+ |
+LL | #![feature(unsized_locals, unsized_fn_params)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
+error[E0308]: mismatched types
+ --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:87:24
+ |
+LL | let _seetype: () = z;
+ | -- ^ expected `()`, found `u32`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:104:24
+ |
+LL | let _seetype: () = z;
+ | -- ^ expected `()`, found `u64`
+ | |
+ | expected due to this
+
+error[E0034]: multiple applicable items in scope
+ --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:122:15
+ |
+LL | let z = x.foo();
+ | ^^^ multiple `foo` found
+ |
+note: candidate #1 is defined in an impl of the trait `X` for the type `T`
+ --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:45:9
+ |
+LL | fn foo(self: Smaht<Self, u64>) -> u64 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `NuisanceFoo` for the type `T`
+ --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:72:9
+ |
+LL | fn foo(self) {}
+ | ^^^^^^^^^^^^
+note: candidate #3 is defined in the trait `FinalFoo`
+ --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:59:5
+ |
+LL | fn foo(&self) -> u8;
+ | ^^^^^^^^^^^^^^^^^^^^
+help: disambiguate the associated function for candidate #1
+ |
+LL | let z = X::foo(x);
+ | ~~~~~~~~~
+help: disambiguate the associated function for candidate #2
+ |
+LL | let z = NuisanceFoo::foo(x);
+ | ~~~~~~~~~~~~~~~~~~~
+help: disambiguate the associated function for candidate #3
+ |
+LL | let z = FinalFoo::foo(x);
+ | ~~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:139:24
+ |
+LL | let _seetype: () = z;
+ | -- ^ expected `()`, found `u8`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:157:24
+ |
+LL | let _seetype: () = z;
+ | -- ^ expected `()`, found `u32`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:174:24
+ |
+LL | let _seetype: () = z;
+ | -- ^ expected `()`, found `u32`
+ | |
+ | expected due to this
+
+error: aborting due to 6 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0034, E0308.
+For more information about an error, try `rustc --explain E0034`.
diff --git a/src/test/ui/methods/method-early-bound-lifetimes-on-self.rs b/src/test/ui/methods/method-early-bound-lifetimes-on-self.rs
new file mode 100644
index 000000000..f2ace32c6
--- /dev/null
+++ b/src/test/ui/methods/method-early-bound-lifetimes-on-self.rs
@@ -0,0 +1,31 @@
+// run-pass
+// Check that we successfully handle methods where the `self` type has
+// an early-bound lifetime. Issue #18208.
+
+// pretty-expanded FIXME #23616
+
+#![allow(dead_code)]
+
+use std::marker;
+
+struct Cursor<'a> {
+ m: marker::PhantomData<&'a ()>
+}
+
+trait CursorNavigator {
+ fn init_cursor<'a, 'b:'a>(&'a self, cursor: &mut Cursor<'b>) -> bool;
+}
+
+struct SimpleNavigator;
+
+impl CursorNavigator for SimpleNavigator {
+ fn init_cursor<'a, 'b: 'a>(&'a self, _cursor: &mut Cursor<'b>) -> bool {
+ false
+ }
+}
+
+fn main() {
+ let mut c = Cursor { m: marker::PhantomData };
+ let n = SimpleNavigator;
+ n.init_cursor(&mut c);
+}
diff --git a/src/test/ui/methods/method-lookup-order.rs b/src/test/ui/methods/method-lookup-order.rs
new file mode 100644
index 000000000..986fe103c
--- /dev/null
+++ b/src/test/ui/methods/method-lookup-order.rs
@@ -0,0 +1,190 @@
+// ignore-tidy-linelength
+
+// run-pass
+
+// There are five cfg's below. I explored the set of all non-empty combinations
+// of the below five cfg's, which is 2^5 - 1 = 31 combinations.
+//
+// Of the 31, 11 resulted in ambiguous method resolutions; while it may be good
+// to have a test for all of the eleven variations of that error, I am not sure
+// this particular test is the best way to encode it. So they are skipped in
+// this revisions list (but not in the expansion mapping the binary encoding to
+// the corresponding cfg flags).
+//
+// Notable, here are the cases that will be incompatible if something does not override them first:
+// {bar_for_foo, valbar_for_et_foo}: these are higher precedent than the `&mut self` method on `Foo`, and so no case matching bx1x1x is included.
+// {mutbar_for_foo, valbar_for_etmut_foo} (which are lower precedent than the inherent `&mut self` method on `Foo`; e.g. b10101 *is* included.
+
+// revisions: b00001 b00010 b00011 b00100 b00101 b00110 b00111 b01000 b01001 b01100 b01101 b10000 b10001 b10010 b10011 b10101 b10111 b11000 b11001 b11101
+
+//[b00001]compile-flags: --cfg inherent_mut
+//[b00010]compile-flags: --cfg bar_for_foo
+//[b00011]compile-flags: --cfg inherent_mut --cfg bar_for_foo
+//[b00100]compile-flags: --cfg mutbar_for_foo
+//[b00101]compile-flags: --cfg inherent_mut --cfg mutbar_for_foo
+//[b00110]compile-flags: --cfg bar_for_foo --cfg mutbar_for_foo
+//[b00111]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg mutbar_for_foo
+//[b01000]compile-flags: --cfg valbar_for_et_foo
+//[b01001]compile-flags: --cfg inherent_mut --cfg valbar_for_et_foo
+//[b01010]compile-flags: --cfg bar_for_foo --cfg valbar_for_et_foo
+//[b01011]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg valbar_for_et_foo
+//[b01100]compile-flags: --cfg mutbar_for_foo --cfg valbar_for_et_foo
+//[b01101]compile-flags: --cfg inherent_mut --cfg mutbar_for_foo --cfg valbar_for_et_foo
+//[b01110]compile-flags: --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_et_foo
+//[b01111]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_et_foo
+//[b10000]compile-flags: --cfg valbar_for_etmut_foo
+//[b10001]compile-flags: --cfg inherent_mut --cfg valbar_for_etmut_foo
+//[b10010]compile-flags: --cfg bar_for_foo --cfg valbar_for_etmut_foo
+//[b10011]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg valbar_for_etmut_foo
+//[b10100]compile-flags: --cfg mutbar_for_foo --cfg valbar_for_etmut_foo
+//[b10101]compile-flags: --cfg inherent_mut --cfg mutbar_for_foo --cfg valbar_for_etmut_foo
+//[b10110]compile-flags: --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_etmut_foo
+//[b10111]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_etmut_foo
+//[b11000]compile-flags: --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
+//[b11001]compile-flags: --cfg inherent_mut --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
+//[b11010]compile-flags: --cfg bar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
+//[b11011]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
+//[b11100]compile-flags: --cfg mutbar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
+//[b11101]compile-flags: --cfg inherent_mut --cfg mutbar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
+//[b11110]compile-flags: --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
+//[b11111]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
+
+struct Foo {}
+
+type S = &'static str;
+
+trait Bar {
+ fn bar(&self, _: &str) -> S;
+}
+
+trait MutBar {
+ fn bar(&mut self, _: &str) -> S;
+}
+
+trait ValBar {
+ fn bar(self, _: &str) -> S;
+}
+
+#[cfg(inherent_mut)]
+impl Foo {
+ fn bar(&mut self, _: &str) -> S {
+ "In struct impl!"
+ }
+}
+
+#[cfg(bar_for_foo)]
+impl Bar for Foo {
+ fn bar(&self, _: &str) -> S {
+ "In trait &self impl!"
+ }
+}
+
+#[cfg(mutbar_for_foo)]
+impl MutBar for Foo {
+ fn bar(&mut self, _: &str) -> S {
+ "In trait &mut self impl!"
+ }
+}
+
+#[cfg(valbar_for_et_foo)]
+impl ValBar for &Foo {
+ fn bar(self, _: &str) -> S {
+ "In trait self impl for &Foo!"
+ }
+}
+
+#[cfg(valbar_for_etmut_foo)]
+impl ValBar for &mut Foo {
+ fn bar(self, _: &str) -> S {
+ "In trait self impl for &mut Foo!"
+ }
+}
+
+fn main() {
+ #![allow(unused_mut)] // some of the impls above will want it.
+
+ #![allow(unreachable_patterns)] // the cfg-coding pattern below generates unreachable patterns.
+
+ {
+ macro_rules! all_variants_on_value {
+ ($e:expr) => {
+ match $e {
+ #[cfg(bar_for_foo)]
+ x => assert_eq!(x, "In trait &self impl!"),
+
+ #[cfg(valbar_for_et_foo)]
+ x => assert_eq!(x, "In trait self impl for &Foo!"),
+
+ #[cfg(inherent_mut)]
+ x => assert_eq!(x, "In struct impl!"),
+
+ #[cfg(mutbar_for_foo)]
+ x => assert_eq!(x, "In trait &mut self impl!"),
+
+ #[cfg(valbar_for_etmut_foo)]
+ x => assert_eq!(x, "In trait self impl for &mut Foo!"),
+ }
+ }
+ }
+
+ let mut f = Foo {};
+ all_variants_on_value!(f.bar("f.bar"));
+
+ let f_mr = &mut Foo {};
+ all_variants_on_value!((*f_mr).bar("(*f_mr).bar"));
+ }
+
+ // This is sort of interesting: `&mut Foo` ends up with a significantly
+ // different resolution order than what was devised above. Presumably this
+ // is because we can get to a `&self` method by first a deref of the given
+ // `&mut Foo` and then an autoref, and that is a longer path than a mere
+ // auto-ref of a `Foo`.
+
+ {
+ let f_mr = &mut Foo {};
+
+ match f_mr.bar("f_mr.bar") {
+ #[cfg(inherent_mut)]
+ x => assert_eq!(x, "In struct impl!"),
+
+ #[cfg(valbar_for_etmut_foo)]
+ x => assert_eq!(x, "In trait self impl for &mut Foo!"),
+
+ #[cfg(mutbar_for_foo)]
+ x => assert_eq!(x, "In trait &mut self impl!"),
+
+ #[cfg(valbar_for_et_foo)]
+ x => assert_eq!(x, "In trait self impl for &Foo!"),
+
+ #[cfg(bar_for_foo)]
+ x => assert_eq!(x, "In trait &self impl!"),
+ }
+ }
+
+
+ // Note that this isn't actually testing a resolution order; if both of these are
+ // enabled, it yields an ambiguous method resolution error. The test tries to embed
+ // that fact by testing *both* orders (and so the only way that can be right is if
+ // they are not actually compatible).
+ #[cfg(any(bar_for_foo, valbar_for_et_foo))]
+ {
+ let f_r = &Foo {};
+
+ match f_r.bar("f_r.bar") {
+ #[cfg(bar_for_foo)]
+ x => assert_eq!(x, "In trait &self impl!"),
+
+ #[cfg(valbar_for_et_foo)]
+ x => assert_eq!(x, "In trait self impl for &Foo!"),
+ }
+
+ match f_r.bar("f_r.bar") {
+ #[cfg(valbar_for_et_foo)]
+ x => assert_eq!(x, "In trait self impl for &Foo!"),
+
+ #[cfg(bar_for_foo)]
+ x => assert_eq!(x, "In trait &self impl!"),
+ }
+ }
+
+}
diff --git a/src/test/ui/methods/method-macro-backtrace.rs b/src/test/ui/methods/method-macro-backtrace.rs
new file mode 100644
index 000000000..00fe32b7c
--- /dev/null
+++ b/src/test/ui/methods/method-macro-backtrace.rs
@@ -0,0 +1,25 @@
+// forbid-output: in this expansion of
+
+macro_rules! make_method {
+ ($name:ident) => ( fn $name(&self) { } )
+}
+
+struct S;
+
+impl S {
+ // We had a bug where these wouldn't clean up macro backtrace frames.
+ make_method!(foo1);
+ make_method!(foo2);
+ make_method!(foo3);
+ make_method!(foo4);
+ make_method!(foo5);
+ make_method!(foo6);
+ make_method!(foo7);
+ make_method!(foo8);
+
+ // Cause an error. It shouldn't have any macro backtrace frames.
+ fn bar(&self) { }
+ fn bar(&self) { } //~ ERROR duplicate definitions
+}
+
+fn main() { }
diff --git a/src/test/ui/methods/method-macro-backtrace.stderr b/src/test/ui/methods/method-macro-backtrace.stderr
new file mode 100644
index 000000000..7ae00835c
--- /dev/null
+++ b/src/test/ui/methods/method-macro-backtrace.stderr
@@ -0,0 +1,11 @@
+error[E0201]: duplicate definitions with name `bar`:
+ --> $DIR/method-macro-backtrace.rs:22:5
+ |
+LL | fn bar(&self) { }
+ | ------------- previous definition of `bar` here
+LL | fn bar(&self) { }
+ | ^^^^^^^^^^^^^ duplicate definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0201`.
diff --git a/src/test/ui/methods/method-missing-call.rs b/src/test/ui/methods/method-missing-call.rs
new file mode 100644
index 000000000..7ce1e9a4f
--- /dev/null
+++ b/src/test/ui/methods/method-missing-call.rs
@@ -0,0 +1,30 @@
+// Tests to make sure that parens are needed for method calls without arguments.
+// outputs text to make sure either an anonymous function is provided or
+// open-close '()' parens are given
+
+
+struct Point {
+ x: isize,
+ y: isize
+}
+impl Point {
+ fn new() -> Point {
+ Point{x:0, y:0}
+ }
+ fn get_x(&self) -> isize {
+ self.x
+ }
+}
+
+fn main() {
+ let point: Point = Point::new();
+ let px: isize = point
+ .get_x;//~ ERROR attempted to take value of method `get_x` on type `Point`
+
+ // Ensure the span is useful
+ let ys = &[1,2,3,4,5,6,7];
+ let a = ys.iter()
+ .map(|x| x)
+ .filter(|&&x| x == 1)
+ .filter_map; //~ ERROR attempted to take value of method `filter_map` on type
+}
diff --git a/src/test/ui/methods/method-missing-call.stderr b/src/test/ui/methods/method-missing-call.stderr
new file mode 100644
index 000000000..040a65d16
--- /dev/null
+++ b/src/test/ui/methods/method-missing-call.stderr
@@ -0,0 +1,25 @@
+error[E0615]: attempted to take value of method `get_x` on type `Point`
+ --> $DIR/method-missing-call.rs:22:26
+ |
+LL | .get_x;
+ | ^^^^^ method, not a field
+ |
+help: use parentheses to call the method
+ |
+LL | .get_x();
+ | ++
+
+error[E0615]: attempted to take value of method `filter_map` on type `Filter<Map<std::slice::Iter<'_, {integer}>, [closure@$DIR/method-missing-call.rs:27:20: 27:23]>, [closure@$DIR/method-missing-call.rs:28:23: 28:28]>`
+ --> $DIR/method-missing-call.rs:29:16
+ |
+LL | .filter_map;
+ | ^^^^^^^^^^ method, not a field
+ |
+help: use parentheses to call the method
+ |
+LL | .filter_map(_);
+ | +++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0615`.
diff --git a/src/test/ui/methods/method-mut-self-modifies-mut-slice-lvalue.rs b/src/test/ui/methods/method-mut-self-modifies-mut-slice-lvalue.rs
new file mode 100644
index 000000000..daff037b2
--- /dev/null
+++ b/src/test/ui/methods/method-mut-self-modifies-mut-slice-lvalue.rs
@@ -0,0 +1,44 @@
+// run-pass
+// Test that an `&mut self` method, when invoked on a place whose
+// type is `&mut [u8]`, passes in a pointer to the place and not a
+// temporary. Issue #19147.
+
+use std::slice;
+use std::cmp;
+
+trait MyWriter {
+ fn my_write(&mut self, buf: &[u8]) -> Result<(), ()>;
+}
+
+impl<'a> MyWriter for &'a mut [u8] {
+ fn my_write(&mut self, buf: &[u8]) -> Result<(), ()> {
+ let amt = cmp::min(self.len(), buf.len());
+ self[..amt].clone_from_slice(&buf[..amt]);
+
+ let write_len = buf.len();
+ unsafe {
+ *self = slice::from_raw_parts_mut(
+ self.as_mut_ptr().add(write_len),
+ self.len() - write_len
+ );
+ }
+
+ Ok(())
+ }
+}
+
+fn main() {
+ let mut buf = [0; 6];
+
+ {
+ let mut writer: &mut [_] = &mut buf;
+ writer.my_write(&[0, 1, 2]).unwrap();
+ writer.my_write(&[3, 4, 5]).unwrap();
+ }
+
+ // If `my_write` is not modifying `buf` in place, then we will
+ // wind up with `[3, 4, 5, 0, 0, 0]` because the first call to
+ // `my_write()` doesn't update the starting point for the write.
+
+ assert_eq!(buf, [0, 1, 2, 3, 4, 5]);
+}
diff --git a/src/test/ui/methods/method-normalize-bounds-issue-20604.rs b/src/test/ui/methods/method-normalize-bounds-issue-20604.rs
new file mode 100644
index 000000000..9c0b95284
--- /dev/null
+++ b/src/test/ui/methods/method-normalize-bounds-issue-20604.rs
@@ -0,0 +1,61 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(stable_features)]
+
+// Test that we handle projection types which wind up important for
+// resolving methods. This test was reduced from a larger example; the
+// call to `foo()` at the end was failing to resolve because the
+// winnowing stage of method resolution failed to handle an associated
+// type projection.
+
+// pretty-expanded FIXME #23616
+
+#![feature(associated_types)]
+
+trait Hasher {
+ type Output;
+ fn finish(&self) -> Self::Output;
+}
+
+trait Hash<H: Hasher> {
+ fn hash(&self, h: &mut H);
+}
+
+trait HashState {
+ type Wut: Hasher;
+ fn hasher(&self) -> Self::Wut;
+}
+
+struct SipHasher;
+impl Hasher for SipHasher {
+ type Output = u64;
+ fn finish(&self) -> u64 { 4 }
+}
+
+impl Hash<SipHasher> for isize {
+ fn hash(&self, h: &mut SipHasher) {}
+}
+
+struct SipState;
+impl HashState for SipState {
+ type Wut = SipHasher;
+ fn hasher(&self) -> SipHasher { SipHasher }
+}
+
+struct Map<S> {
+ s: S,
+}
+
+impl<S> Map<S>
+ where S: HashState,
+ <S as HashState>::Wut: Hasher<Output=u64>,
+{
+ fn foo<K>(&self, k: K) where K: Hash< <S as HashState>::Wut> {}
+}
+
+fn foo<K: Hash<SipHasher>>(map: &Map<SipState>) {
+ map.foo(22);
+}
+
+fn main() {}
diff --git a/src/test/ui/methods/method-not-found-generic-arg-elision.rs b/src/test/ui/methods/method-not-found-generic-arg-elision.rs
new file mode 100644
index 000000000..799ced5e9
--- /dev/null
+++ b/src/test/ui/methods/method-not-found-generic-arg-elision.rs
@@ -0,0 +1,106 @@
+// Test for issue 81576
+// Remove generic arguments if no method is found for all possible generic argument
+
+use std::marker::PhantomData;
+
+struct Wrapper2<'a, T, const C: usize> {
+ x: &'a T,
+}
+
+impl<'a, const C: usize> Wrapper2<'a, i8, C> {
+ fn method(&self) {}
+}
+
+impl<'a, const C: usize> Wrapper2<'a, i16, C> {
+ fn method(&self) {}
+}
+
+impl<'a, const C: usize> Wrapper2<'a, i32, C> {
+ fn method(&self) {}
+}
+struct Wrapper<T>(T);
+
+impl Wrapper<i8> {
+ fn method(&self) {}
+}
+
+impl Wrapper<i16> {
+ fn method(&self) {}
+}
+
+impl Wrapper<i32> {
+ fn method(&self) {}
+}
+
+impl Wrapper<i64> {
+ fn method(&self) {}
+}
+
+impl Wrapper<u8> {
+ fn method(&self) {}
+}
+
+impl Wrapper<u16> {
+ fn method(&self) {}
+}
+
+struct Point<T> {
+ x: T,
+ y: T,
+}
+
+impl Point<f64> {
+ fn distance(&self) -> f64 {
+ self.x.hypot(self.y)
+ }
+}
+
+struct Other;
+
+impl Other {
+ fn other(&self) {}
+}
+
+struct Struct<T> {
+ _phatom: PhantomData<T>,
+}
+
+impl<T> Default for Struct<T> {
+ fn default() -> Self {
+ Self { _phatom: PhantomData }
+ }
+}
+
+impl<T: Clone + Copy + PartialEq + Eq + PartialOrd + Ord> Struct<T> {
+ fn method(&self) {}
+}
+
+fn main() {
+ let point_f64 = Point { x: 1_f64, y: 1_f64 };
+ let d = point_f64.distance();
+ let point_i32 = Point { x: 1_i32, y: 1_i32 };
+ let d = point_i32.distance();
+ //~^ ERROR no method named `distance` found for struct `Point<i32>
+ let d = point_i32.other();
+ //~^ ERROR no method named `other` found for struct `Point
+ let v = vec![1_i32, 2, 3];
+ v.iter().map(|x| x * x).extend(std::iter::once(100));
+ //~^ ERROR no method named `extend` found for struct `Map
+ let wrapper = Wrapper(true);
+ wrapper.method();
+ //~^ ERROR no method named `method` found for struct `Wrapper<bool>
+ wrapper.other();
+ //~^ ERROR no method named `other` found for struct `Wrapper
+ let boolean = true;
+ let wrapper = Wrapper2::<'_, _, 3> { x: &boolean };
+ wrapper.method();
+ //~^ ERROR no method named `method` found for struct `Wrapper2<'_, bool, 3>
+ wrapper.other();
+ //~^ ERROR no method named `other` found for struct `Wrapper2
+ let a = vec![1, 2, 3];
+ a.not_found();
+ //~^ ERROR no method named `not_found` found for struct `Vec
+ let s = Struct::<f64>::default();
+ s.method();
+ //~^ ERROR the method `method` exists for struct `Struct<f64>`, but its trait bounds were not satisfied
+}
diff --git a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr
new file mode 100644
index 000000000..fc42d1a4d
--- /dev/null
+++ b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr
@@ -0,0 +1,97 @@
+error[E0599]: no method named `distance` found for struct `Point<i32>` in the current scope
+ --> $DIR/method-not-found-generic-arg-elision.rs:82:23
+ |
+LL | struct Point<T> {
+ | --------------- method `distance` not found for this struct
+...
+LL | let d = point_i32.distance();
+ | ^^^^^^^^ method not found in `Point<i32>`
+ |
+ = note: the method was found for
+ - `Point<f64>`
+
+error[E0599]: no method named `other` found for struct `Point` in the current scope
+ --> $DIR/method-not-found-generic-arg-elision.rs:84:23
+ |
+LL | struct Point<T> {
+ | --------------- method `other` not found for this struct
+...
+LL | let d = point_i32.other();
+ | ^^^^^ method not found in `Point<i32>`
+
+error[E0599]: no method named `extend` found for struct `Map` in the current scope
+ --> $DIR/method-not-found-generic-arg-elision.rs:87:29
+ |
+LL | v.iter().map(|x| x * x).extend(std::iter::once(100));
+ | ^^^^^^ method not found in `Map<std::slice::Iter<'_, i32>, [closure@$DIR/method-not-found-generic-arg-elision.rs:87:18: 87:21]>`
+
+error[E0599]: no method named `method` found for struct `Wrapper<bool>` in the current scope
+ --> $DIR/method-not-found-generic-arg-elision.rs:90:13
+ |
+LL | struct Wrapper<T>(T);
+ | ----------------- method `method` not found for this struct
+...
+LL | wrapper.method();
+ | ^^^^^^ method not found in `Wrapper<bool>`
+ |
+ = note: the method was found for
+ - `Wrapper<i8>`
+ - `Wrapper<i16>`
+ - `Wrapper<i32>`
+ - `Wrapper<i64>`
+ and 2 more types
+
+error[E0599]: no method named `other` found for struct `Wrapper` in the current scope
+ --> $DIR/method-not-found-generic-arg-elision.rs:92:13
+ |
+LL | struct Wrapper<T>(T);
+ | ----------------- method `other` not found for this struct
+...
+LL | wrapper.other();
+ | ^^^^^ method not found in `Wrapper<bool>`
+
+error[E0599]: no method named `method` found for struct `Wrapper2<'_, bool, 3>` in the current scope
+ --> $DIR/method-not-found-generic-arg-elision.rs:96:13
+ |
+LL | struct Wrapper2<'a, T, const C: usize> {
+ | -------------------------------------- method `method` not found for this struct
+...
+LL | wrapper.method();
+ | ^^^^^^ method not found in `Wrapper2<'_, bool, 3>`
+ |
+ = note: the method was found for
+ - `Wrapper2<'a, i8, C>`
+ - `Wrapper2<'a, i16, C>`
+ - `Wrapper2<'a, i32, C>`
+
+error[E0599]: no method named `other` found for struct `Wrapper2` in the current scope
+ --> $DIR/method-not-found-generic-arg-elision.rs:98:13
+ |
+LL | struct Wrapper2<'a, T, const C: usize> {
+ | -------------------------------------- method `other` not found for this struct
+...
+LL | wrapper.other();
+ | ^^^^^ method not found in `Wrapper2<'_, bool, 3>`
+
+error[E0599]: no method named `not_found` found for struct `Vec<{integer}>` in the current scope
+ --> $DIR/method-not-found-generic-arg-elision.rs:101:7
+ |
+LL | a.not_found();
+ | ^^^^^^^^^ method not found in `Vec<{integer}>`
+
+error[E0599]: the method `method` exists for struct `Struct<f64>`, but its trait bounds were not satisfied
+ --> $DIR/method-not-found-generic-arg-elision.rs:104:7
+ |
+LL | struct Struct<T> {
+ | ---------------- method `method` not found for this struct
+...
+LL | s.method();
+ | ^^^^^^ method cannot be called on `Struct<f64>` due to unsatisfied trait bounds
+ |
+ = note: the following trait bounds were not satisfied:
+ `f64: Eq`
+ `f64: Ord`
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/methods/method-on-ambiguous-numeric-type.rs b/src/test/ui/methods/method-on-ambiguous-numeric-type.rs
new file mode 100644
index 000000000..82f47438d
--- /dev/null
+++ b/src/test/ui/methods/method-on-ambiguous-numeric-type.rs
@@ -0,0 +1,32 @@
+// aux-build:macro-in-other-crate.rs
+
+#[macro_use] extern crate macro_in_other_crate;
+
+macro_rules! local_mac {
+ ($ident:ident) => { let $ident = 42; }
+}
+
+fn main() {
+ let x = 2.0.neg();
+ //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
+
+ let y = 2.0;
+ let x = y.neg();
+ //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
+ println!("{:?}", x);
+
+ for i in 0..100 {
+ println!("{}", i.pow(2));
+ //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
+ }
+
+ local_mac!(local_bar);
+ local_bar.pow(2);
+ //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
+}
+
+fn qux() {
+ mac!(bar);
+ bar.pow(2);
+ //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
+}
diff --git a/src/test/ui/methods/method-on-ambiguous-numeric-type.stderr b/src/test/ui/methods/method-on-ambiguous-numeric-type.stderr
new file mode 100644
index 000000000..0af58bc61
--- /dev/null
+++ b/src/test/ui/methods/method-on-ambiguous-numeric-type.stderr
@@ -0,0 +1,56 @@
+error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
+ --> $DIR/method-on-ambiguous-numeric-type.rs:10:17
+ |
+LL | let x = 2.0.neg();
+ | ^^^
+ |
+help: you must specify a concrete type for this numeric value, like `f32`
+ |
+LL | let x = 2.0_f32.neg();
+ | ~~~~~~~
+
+error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
+ --> $DIR/method-on-ambiguous-numeric-type.rs:14:15
+ |
+LL | let x = y.neg();
+ | ^^^
+ |
+help: you must specify a type for this binding, like `f32`
+ |
+LL | let y: f32 = 2.0;
+ | ~~~~~~
+
+error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
+ --> $DIR/method-on-ambiguous-numeric-type.rs:19:26
+ |
+LL | for i in 0..100 {
+ | - you must specify a type for this binding, like `i32`
+LL | println!("{}", i.pow(2));
+ | ^^^
+
+error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
+ --> $DIR/method-on-ambiguous-numeric-type.rs:24:15
+ |
+LL | local_bar.pow(2);
+ | ^^^
+ |
+help: you must specify a type for this binding, like `i32`
+ |
+LL | ($ident:ident) => { let $ident: i32 = 42; }
+ | ~~~~~~~~~~~
+
+error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
+ --> $DIR/method-on-ambiguous-numeric-type.rs:30:9
+ |
+LL | bar.pow(2);
+ | ^^^
+ |
+help: you must specify a type for this binding, like `i32`
+ --> $DIR/auxiliary/macro-in-other-crate.rs:3:29
+ |
+LL | ($ident:ident) => { let $ident: i32 = 42; }
+ | ~~~~~~~~~~~
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0689`.
diff --git a/src/test/ui/methods/method-path-in-pattern.rs b/src/test/ui/methods/method-path-in-pattern.rs
new file mode 100644
index 000000000..406453095
--- /dev/null
+++ b/src/test/ui/methods/method-path-in-pattern.rs
@@ -0,0 +1,32 @@
+struct Foo;
+
+impl Foo {
+ fn bar(&self) {}
+}
+
+trait MyTrait {
+ fn trait_bar() {}
+}
+
+impl MyTrait for Foo {}
+
+fn main() {
+ match 0u32 {
+ Foo::bar => {}
+ //~^ ERROR expected unit struct, unit variant or constant, found associated function
+ }
+ match 0u32 {
+ <Foo>::bar => {}
+ //~^ ERROR expected unit struct, unit variant or constant, found associated function
+ }
+ match 0u32 {
+ <Foo>::trait_bar => {}
+ //~^ ERROR expected unit struct, unit variant or constant, found associated function
+ }
+ if let Foo::bar = 0u32 {}
+ //~^ ERROR expected unit struct, unit variant or constant, found associated function
+ if let <Foo>::bar = 0u32 {}
+ //~^ ERROR expected unit struct, unit variant or constant, found associated function
+ if let Foo::trait_bar = 0u32 {}
+ //~^ ERROR expected unit struct, unit variant or constant, found associated function
+}
diff --git a/src/test/ui/methods/method-path-in-pattern.stderr b/src/test/ui/methods/method-path-in-pattern.stderr
new file mode 100644
index 000000000..1d1bdb6b0
--- /dev/null
+++ b/src/test/ui/methods/method-path-in-pattern.stderr
@@ -0,0 +1,39 @@
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
+ --> $DIR/method-path-in-pattern.rs:15:9
+ |
+LL | Foo::bar => {}
+ | ^^^^^^^^
+
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
+ --> $DIR/method-path-in-pattern.rs:19:9
+ |
+LL | <Foo>::bar => {}
+ | ^^^^^^^^^^
+
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::trait_bar`
+ --> $DIR/method-path-in-pattern.rs:23:9
+ |
+LL | <Foo>::trait_bar => {}
+ | ^^^^^^^^^^^^^^^^
+
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
+ --> $DIR/method-path-in-pattern.rs:26:12
+ |
+LL | if let Foo::bar = 0u32 {}
+ | ^^^^^^^^
+
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
+ --> $DIR/method-path-in-pattern.rs:28:12
+ |
+LL | if let <Foo>::bar = 0u32 {}
+ | ^^^^^^^^^^
+
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::trait_bar`
+ --> $DIR/method-path-in-pattern.rs:30:12
+ |
+LL | if let Foo::trait_bar = 0u32 {}
+ | ^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0533`.
diff --git a/src/test/ui/methods/method-probe-no-guessing-dyn-trait.rs b/src/test/ui/methods/method-probe-no-guessing-dyn-trait.rs
new file mode 100644
index 000000000..ec41b7117
--- /dev/null
+++ b/src/test/ui/methods/method-probe-no-guessing-dyn-trait.rs
@@ -0,0 +1,60 @@
+// run-pass
+// Check that method matching does not make "guesses" depending on
+// Deref impls that don't eventually end up being picked.
+
+use std::ops::Deref;
+
+// An impl with less derefs will get called over an impl with more derefs,
+// so `(t: Foo<_>).my_fn()` will use `<Foo<u32> as MyTrait1>::my_fn(t)`,
+// and does *not* force the `_` to equal `()`, because the Deref impl
+// was *not* used.
+
+trait MyTrait1 {
+ fn my_fn(&self) {}
+}
+
+impl MyTrait1 for Foo<u32> {}
+
+struct Foo<T>(#[allow(unused_tuple_struct_fields)] T);
+
+impl Deref for Foo<()> {
+ type Target = dyn MyTrait1 + 'static;
+ fn deref(&self) -> &(dyn MyTrait1 + 'static) {
+ panic!()
+ }
+}
+
+// ...but if there is no impl with less derefs, the "guess" will be
+// forced, so `(t: Bar<_>).my_fn2()` is `<dyn MyTrait2 as MyTrait2>::my_fn2(*t)`,
+// and because the deref impl is used, the `_` is forced to equal `u8`.
+
+trait MyTrait2 {
+ fn my_fn2(&self) {}
+}
+
+impl MyTrait2 for u32 {}
+struct Bar<T>(#[allow(unused_tuple_struct_fields)] T, u32);
+impl Deref for Bar<u8> {
+ type Target = dyn MyTrait2 + 'static;
+ fn deref(&self) -> &(dyn MyTrait2 + 'static) {
+ &self.1
+ }
+}
+
+// actually invoke things
+
+fn main() {
+ let mut foo: Option<Foo<_>> = None;
+ let mut bar: Option<Bar<_>> = None;
+ let mut first_iter = true;
+ loop {
+ if !first_iter {
+ foo.as_ref().unwrap().my_fn();
+ bar.as_ref().unwrap().my_fn2();
+ break;
+ }
+ foo = Some(Foo(0));
+ bar = Some(Bar(Default::default(), 0));
+ first_iter = false;
+ }
+}
diff --git a/src/test/ui/methods/method-projection.rs b/src/test/ui/methods/method-projection.rs
new file mode 100644
index 000000000..21d983f19
--- /dev/null
+++ b/src/test/ui/methods/method-projection.rs
@@ -0,0 +1,61 @@
+// run-pass
+// Test that we can use method notation to call methods based on a
+// projection bound from a trait. Issue #20469.
+
+trait MakeString {
+ fn make_string(&self) -> String;
+}
+
+impl MakeString for isize {
+ fn make_string(&self) -> String {
+ format!("{}", *self)
+ }
+}
+
+impl MakeString for usize {
+ fn make_string(&self) -> String {
+ format!("{}", *self)
+ }
+}
+
+trait Foo {
+ type F: MakeString;
+
+ fn get(&self) -> &Self::F;
+}
+
+fn foo<F:Foo>(f: &F) -> String {
+ f.get().make_string()
+}
+
+struct SomeStruct {
+ field: isize,
+}
+
+impl Foo for SomeStruct {
+ type F = isize;
+
+ fn get(&self) -> &isize {
+ &self.field
+ }
+}
+
+struct SomeOtherStruct {
+ field: usize,
+}
+
+impl Foo for SomeOtherStruct {
+ type F = usize;
+
+ fn get(&self) -> &usize {
+ &self.field
+ }
+}
+
+fn main() {
+ let x = SomeStruct { field: 22 };
+ assert_eq!(foo(&x), format!("22"));
+
+ let x = SomeOtherStruct { field: 44 };
+ assert_eq!(foo(&x), format!("44"));
+}
diff --git a/src/test/ui/methods/method-recursive-blanket-impl.rs b/src/test/ui/methods/method-recursive-blanket-impl.rs
new file mode 100644
index 000000000..a2db75b4e
--- /dev/null
+++ b/src/test/ui/methods/method-recursive-blanket-impl.rs
@@ -0,0 +1,41 @@
+// run-pass
+#![allow(unused_variables)]
+#![allow(unused_imports)]
+// Test that we don't trigger on the blanket impl for all `&'a T` but
+// rather keep autoderefing and trigger on the underlying impl. To
+// know not to stop at the blanket, we have to recursively evaluate
+// the `T:Foo` bound.
+
+// pretty-expanded FIXME #23616
+
+use std::marker::Sized;
+
+// Note: this must be generic for the problem to show up
+trait Foo<A> {
+ fn foo(&self, a: A);
+}
+
+impl Foo<u8> for [u8] {
+ fn foo(&self, a: u8) {}
+}
+
+impl<'a, A, T> Foo<A> for &'a T where T: Foo<A> {
+ fn foo(&self, a: A) {
+ Foo::foo(*self, a)
+ }
+}
+
+trait Bar {
+ fn foo(&self);
+}
+
+struct MyType;
+
+impl Bar for MyType {
+ fn foo(&self) {}
+}
+
+fn main() {
+ let mut m = MyType;
+ (&mut m).foo()
+}
diff --git a/src/test/ui/methods/method-resolvable-path-in-pattern.rs b/src/test/ui/methods/method-resolvable-path-in-pattern.rs
new file mode 100644
index 000000000..2973800a4
--- /dev/null
+++ b/src/test/ui/methods/method-resolvable-path-in-pattern.rs
@@ -0,0 +1,14 @@
+struct Foo;
+
+trait MyTrait {
+ fn trait_bar() {}
+}
+
+impl MyTrait for Foo {}
+
+fn main() {
+ match 0u32 {
+ <Foo as MyTrait>::trait_bar => {}
+ //~^ ERROR expected unit struct, unit variant or constant, found associated function
+ }
+}
diff --git a/src/test/ui/methods/method-resolvable-path-in-pattern.stderr b/src/test/ui/methods/method-resolvable-path-in-pattern.stderr
new file mode 100644
index 000000000..7c454a9a7
--- /dev/null
+++ b/src/test/ui/methods/method-resolvable-path-in-pattern.stderr
@@ -0,0 +1,9 @@
+error[E0532]: expected unit struct, unit variant or constant, found associated function `MyTrait::trait_bar`
+ --> $DIR/method-resolvable-path-in-pattern.rs:11:9
+ |
+LL | <Foo as MyTrait>::trait_bar => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a unit struct, unit variant or constant
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/methods/method-self-arg-1.rs b/src/test/ui/methods/method-self-arg-1.rs
new file mode 100644
index 000000000..f589f20d8
--- /dev/null
+++ b/src/test/ui/methods/method-self-arg-1.rs
@@ -0,0 +1,17 @@
+// Test method calls with self as an argument cannot subvert type checking.
+
+struct Foo;
+
+impl Foo {
+ fn bar(&self) {}
+}
+
+fn main() {
+ let x = Foo;
+ Foo::bar(x); //~ ERROR mismatched types
+ //~| expected `&Foo`, found struct `Foo`
+ Foo::bar(&42); //~ ERROR mismatched types
+ //~| expected struct `Foo`, found integer
+ //~| expected reference `&Foo`
+ //~| found reference `&{integer}`
+}
diff --git a/src/test/ui/methods/method-self-arg-1.stderr b/src/test/ui/methods/method-self-arg-1.stderr
new file mode 100644
index 000000000..01fec6fca
--- /dev/null
+++ b/src/test/ui/methods/method-self-arg-1.stderr
@@ -0,0 +1,35 @@
+error[E0308]: mismatched types
+ --> $DIR/method-self-arg-1.rs:11:14
+ |
+LL | Foo::bar(x);
+ | -------- ^
+ | | |
+ | | expected `&Foo`, found struct `Foo`
+ | | help: consider borrowing here: `&x`
+ | arguments to this function are incorrect
+ |
+note: associated function defined here
+ --> $DIR/method-self-arg-1.rs:6:8
+ |
+LL | fn bar(&self) {}
+ | ^^^ -----
+
+error[E0308]: mismatched types
+ --> $DIR/method-self-arg-1.rs:13:14
+ |
+LL | Foo::bar(&42);
+ | -------- ^^^ expected struct `Foo`, found integer
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected reference `&Foo`
+ found reference `&{integer}`
+note: associated function defined here
+ --> $DIR/method-self-arg-1.rs:6:8
+ |
+LL | fn bar(&self) {}
+ | ^^^ -----
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/methods/method-self-arg-2.rs b/src/test/ui/methods/method-self-arg-2.rs
new file mode 100644
index 000000000..0f8c048ac
--- /dev/null
+++ b/src/test/ui/methods/method-self-arg-2.rs
@@ -0,0 +1,25 @@
+// Test method calls with self as an argument cannot subvert borrow checking.
+
+
+
+struct Foo;
+
+impl Foo {
+ fn bar(&self) {}
+ fn baz(&mut self) {}
+}
+
+fn main() {
+ let mut x = Foo;
+ let y = &mut x;
+ Foo::bar(&x); //~ERROR cannot borrow `x`
+ y.use_mut();
+
+ let mut x = Foo;
+ let y = &mut x;
+ Foo::baz(&mut x); //~ERROR cannot borrow `x`
+ y.use_mut();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } }
+impl<T> Fake for T { }
diff --git a/src/test/ui/methods/method-self-arg-2.stderr b/src/test/ui/methods/method-self-arg-2.stderr
new file mode 100644
index 000000000..b98f7a786
--- /dev/null
+++ b/src/test/ui/methods/method-self-arg-2.stderr
@@ -0,0 +1,24 @@
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+ --> $DIR/method-self-arg-2.rs:15:14
+ |
+LL | let y = &mut x;
+ | ------ mutable borrow occurs here
+LL | Foo::bar(&x);
+ | ^^ immutable borrow occurs here
+LL | y.use_mut();
+ | ----------- mutable borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+ --> $DIR/method-self-arg-2.rs:20:14
+ |
+LL | let y = &mut x;
+ | ------ first mutable borrow occurs here
+LL | Foo::baz(&mut x);
+ | ^^^^^^ second mutable borrow occurs here
+LL | y.use_mut();
+ | ----------- first borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0499, E0502.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/methods/method-self-arg-aux1.rs b/src/test/ui/methods/method-self-arg-aux1.rs
new file mode 100644
index 000000000..79b70a17c
--- /dev/null
+++ b/src/test/ui/methods/method-self-arg-aux1.rs
@@ -0,0 +1,18 @@
+// run-pass
+// Test method calls with self as an argument (cross-crate)
+
+// aux-build:method_self_arg1.rs
+extern crate method_self_arg1;
+use method_self_arg1::Foo;
+
+fn main() {
+ let x = Foo;
+ // Test external call.
+ Foo::bar(&x);
+ Foo::baz(x);
+ Foo::qux(Box::new(x));
+
+ x.foo(&x);
+
+ assert_eq!(method_self_arg1::get_count(), 2*3*3*3*5*5*5*7*7*7);
+}
diff --git a/src/test/ui/methods/method-self-arg-aux2.rs b/src/test/ui/methods/method-self-arg-aux2.rs
new file mode 100644
index 000000000..16487b54f
--- /dev/null
+++ b/src/test/ui/methods/method-self-arg-aux2.rs
@@ -0,0 +1,22 @@
+// run-pass
+// Test method calls with self as an argument (cross-crate)
+
+// aux-build:method_self_arg2.rs
+extern crate method_self_arg2;
+use method_self_arg2::{Foo, Bar};
+
+fn main() {
+ let x = Foo;
+ // Test external call.
+ Bar::foo1(&x);
+ Bar::foo2(x);
+ Bar::foo3(Box::new(x));
+
+ Bar::bar1(&x);
+ Bar::bar2(x);
+ Bar::bar3(Box::new(x));
+
+ x.run_trait();
+
+ assert_eq!(method_self_arg2::get_count(), 2*2*3*3*5*5*7*7*11*11*13*13*17);
+}
diff --git a/src/test/ui/methods/method-self-arg-trait.rs b/src/test/ui/methods/method-self-arg-trait.rs
new file mode 100644
index 000000000..ffa7a552b
--- /dev/null
+++ b/src/test/ui/methods/method-self-arg-trait.rs
@@ -0,0 +1,67 @@
+// run-pass
+// Test method calls with self as an argument
+
+static mut COUNT: u64 = 1;
+
+#[derive(Copy, Clone)]
+struct Foo;
+
+trait Bar : Sized {
+ fn foo1(&self);
+ fn foo2(self);
+ fn foo3(self: Box<Self>);
+
+ fn bar1(&self) {
+ unsafe { COUNT *= 7; }
+ }
+ fn bar2(self) {
+ unsafe { COUNT *= 11; }
+ }
+ fn bar3(self: Box<Self>) {
+ unsafe { COUNT *= 13; }
+ }
+}
+
+impl Bar for Foo {
+ fn foo1(&self) {
+ unsafe { COUNT *= 2; }
+ }
+
+ fn foo2(self) {
+ unsafe { COUNT *= 3; }
+ }
+
+ fn foo3(self: Box<Foo>) {
+ unsafe { COUNT *= 5; }
+ }
+}
+
+impl Foo {
+ fn baz(self) {
+ unsafe { COUNT *= 17; }
+ // Test internal call.
+ Bar::foo1(&self);
+ Bar::foo2(self);
+ Bar::foo3(Box::new(self));
+
+ Bar::bar1(&self);
+ Bar::bar2(self);
+ Bar::bar3(Box::new(self));
+ }
+}
+
+fn main() {
+ let x = Foo;
+ // Test external call.
+ Bar::foo1(&x);
+ Bar::foo2(x);
+ Bar::foo3(Box::new(x));
+
+ Bar::bar1(&x);
+ Bar::bar2(x);
+ Bar::bar3(Box::new(x));
+
+ x.baz();
+
+ unsafe { assert_eq!(COUNT, 2*2*3*3*5*5*7*7*11*11*13*13*17); }
+}
diff --git a/src/test/ui/methods/method-self-arg.rs b/src/test/ui/methods/method-self-arg.rs
new file mode 100644
index 000000000..f738fa19c
--- /dev/null
+++ b/src/test/ui/methods/method-self-arg.rs
@@ -0,0 +1,46 @@
+// run-pass
+// Test method calls with self as an argument
+
+static mut COUNT: usize = 1;
+
+#[derive(Copy, Clone)]
+struct Foo;
+
+impl Foo {
+ fn foo(self, x: &Foo) {
+ unsafe { COUNT *= 2; }
+ // Test internal call.
+ Foo::bar(&self);
+ Foo::bar(x);
+
+ Foo::baz(self);
+ Foo::baz(*x);
+
+ Foo::qux(Box::new(self));
+ Foo::qux(Box::new(*x));
+ }
+
+ fn bar(&self) {
+ unsafe { COUNT *= 3; }
+ }
+
+ fn baz(self) {
+ unsafe { COUNT *= 5; }
+ }
+
+ fn qux(self: Box<Foo>) {
+ unsafe { COUNT *= 7; }
+ }
+}
+
+fn main() {
+ let x = Foo;
+ // Test external call.
+ Foo::bar(&x);
+ Foo::baz(x);
+ Foo::qux(Box::new(x));
+
+ x.foo(&x);
+
+ unsafe { assert_eq!(COUNT, 2*3*3*3*5*5*5*7*7*7); }
+}
diff --git a/src/test/ui/methods/method-trait-object-with-hrtb.rs b/src/test/ui/methods/method-trait-object-with-hrtb.rs
new file mode 100644
index 000000000..d1bee676c
--- /dev/null
+++ b/src/test/ui/methods/method-trait-object-with-hrtb.rs
@@ -0,0 +1,41 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+// Check that method probing ObjectCandidate works in the presence of
+// auto traits and/or HRTBs.
+
+mod internal {
+ pub trait MyObject<'a> {
+ type Output;
+
+ fn foo(&self) -> Self::Output;
+ }
+
+ impl<'a> MyObject<'a> for () {
+ type Output = &'a u32;
+
+ fn foo(&self) -> Self::Output { &4 }
+ }
+}
+
+fn t1(d: &dyn for<'a> internal::MyObject<'a, Output=&'a u32>) {
+ d.foo();
+}
+
+fn t2(d: &dyn internal::MyObject<'static, Output=&'static u32>) {
+ d.foo();
+}
+
+fn t3(d: &(dyn for<'a> internal::MyObject<'a, Output=&'a u32> + Sync)) {
+ d.foo();
+}
+
+fn t4(d: &(dyn internal::MyObject<'static, Output=&'static u32> + Sync)) {
+ d.foo();
+}
+
+fn main() {
+ t1(&());
+ t2(&());
+ t3(&());
+ t4(&());
+}
diff --git a/src/test/ui/methods/method-two-trait-defer-resolution-1.rs b/src/test/ui/methods/method-two-trait-defer-resolution-1.rs
new file mode 100644
index 000000000..b768620cd
--- /dev/null
+++ b/src/test/ui/methods/method-two-trait-defer-resolution-1.rs
@@ -0,0 +1,37 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+// Test that we pick which version of `foo` to run based on the
+// type that is (ultimately) inferred for `x`.
+
+
+trait foo {
+ fn foo(&self) -> i32;
+}
+
+impl foo for Vec<u32> {
+ fn foo(&self) -> i32 {1}
+}
+
+impl foo for Vec<i32> {
+ fn foo(&self) -> i32 {2}
+}
+
+fn call_foo_uint() -> i32 {
+ let mut x = Vec::new();
+ let y = x.foo();
+ x.push(0u32);
+ y
+}
+
+fn call_foo_int() -> i32 {
+ let mut x = Vec::new();
+ let y = x.foo();
+ x.push(0i32);
+ y
+}
+
+fn main() {
+ assert_eq!(call_foo_uint(), 1);
+ assert_eq!(call_foo_int(), 2);
+}
diff --git a/src/test/ui/methods/method-two-trait-defer-resolution-2.rs b/src/test/ui/methods/method-two-trait-defer-resolution-2.rs
new file mode 100644
index 000000000..fc5766da9
--- /dev/null
+++ b/src/test/ui/methods/method-two-trait-defer-resolution-2.rs
@@ -0,0 +1,46 @@
+// run-pass
+// Test that when we write `x.foo()`, we do not have to know the
+// complete type of `x` in order to type-check the method call. In
+// this case, we know that `x: Vec<_1>`, but we don't know what type
+// `_1` is (because the call to `push` comes later). To pick between
+// the impls, we would have to know `_1`, since we have to know
+// whether `_1: MyCopy` or `_1 == Box<i32>`. However (and this is the
+// point of the test), we don't have to pick between the two impls --
+// it is enough to know that `foo` comes from the `Foo` trait. We can
+// codegen the call as `Foo::foo(&x)` and let the specific impl get
+// chosen later.
+
+trait Foo {
+ fn foo(&self) -> isize;
+}
+
+trait MyCopy { fn foo(&self) { } }
+impl MyCopy for i32 { }
+
+impl<T:MyCopy> Foo for Vec<T> {
+ fn foo(&self) -> isize {1}
+}
+
+impl Foo for Vec<Box<i32>> {
+ fn foo(&self) -> isize {2}
+}
+
+fn call_foo_copy() -> isize {
+ let mut x = Vec::new();
+ let y = x.foo();
+ x.push(0_i32);
+ y
+}
+
+fn call_foo_other() -> isize {
+ let mut x: Vec<_> = Vec::new();
+ let y = x.foo();
+ let z: Box<i32> = Box::new(0);
+ x.push(z);
+ y
+}
+
+fn main() {
+ assert_eq!(call_foo_copy(), 1);
+ assert_eq!(call_foo_other(), 2);
+}
diff --git a/src/test/ui/methods/method-two-traits-distinguished-via-where-clause.rs b/src/test/ui/methods/method-two-traits-distinguished-via-where-clause.rs
new file mode 100644
index 000000000..d820d2ad0
--- /dev/null
+++ b/src/test/ui/methods/method-two-traits-distinguished-via-where-clause.rs
@@ -0,0 +1,27 @@
+// run-pass
+// Test that we select between traits A and B. To do that, we must
+// consider the `Sized` bound.
+
+// pretty-expanded FIXME #23616
+
+trait A {
+ fn foo(self);
+}
+
+trait B {
+ fn foo(self);
+}
+
+impl<T: Sized> A for *const T {
+ fn foo(self) {}
+}
+
+impl<T> B for *const [T] {
+ fn foo(self) {}
+}
+
+fn main() {
+ let x: [isize; 4] = [1,2,3,4];
+ let xptr = &x[..] as *const [isize];
+ xptr.foo();
+}
diff --git a/src/test/ui/methods/method-where-clause.rs b/src/test/ui/methods/method-where-clause.rs
new file mode 100644
index 000000000..01692abf9
--- /dev/null
+++ b/src/test/ui/methods/method-where-clause.rs
@@ -0,0 +1,34 @@
+// run-pass
+// Test that we can use method notation to call methods based on a
+// where clause type, and not only type parameters.
+
+
+trait Foo {
+ fn foo(&self) -> i32;
+}
+
+impl Foo for Option<i32>
+{
+ fn foo(&self) -> i32 {
+ self.unwrap_or(22)
+ }
+}
+
+impl Foo for Option<u32>
+{
+ fn foo(&self) -> i32 {
+ self.unwrap_or(22) as i32
+ }
+}
+
+fn check<T>(x: Option<T>) -> (i32, i32)
+ where Option<T> : Foo
+{
+ let y: Option<T> = None;
+ (x.foo(), y.foo())
+}
+
+fn main() {
+ assert_eq!(check(Some(23u32)), (23, 22));
+ assert_eq!(check(Some(23)), (23, 22));
+}