about summary refs log tree commit diff
path: root/tests/ui/methods
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/methods')
-rw-r--r--tests/ui/methods/assign-to-method.rs24
-rw-r--r--tests/ui/methods/assign-to-method.stderr19
-rw-r--r--tests/ui/methods/auxiliary/ambig_impl_2_lib.rs4
-rw-r--r--tests/ui/methods/auxiliary/macro-in-other-crate.rs9
-rw-r--r--tests/ui/methods/auxiliary/method_self_arg1.rs35
-rw-r--r--tests/ui/methods/auxiliary/method_self_arg2.rs52
-rw-r--r--tests/ui/methods/field-method-suggestion-using-return-ty.rs18
-rw-r--r--tests/ui/methods/field-method-suggestion-using-return-ty.stderr27
-rw-r--r--tests/ui/methods/issues/issue-105732.rs14
-rw-r--r--tests/ui/methods/issues/issue-105732.stderr18
-rw-r--r--tests/ui/methods/issues/issue-61525.rs20
-rw-r--r--tests/ui/methods/issues/issue-61525.stderr39
-rw-r--r--tests/ui/methods/issues/issue-84495.rs4
-rw-r--r--tests/ui/methods/issues/issue-84495.stderr13
-rw-r--r--tests/ui/methods/issues/issue-90315.rs75
-rw-r--r--tests/ui/methods/issues/issue-90315.stderr190
-rw-r--r--tests/ui/methods/issues/issue-94581.rs7
-rw-r--r--tests/ui/methods/issues/issue-94581.stderr15
-rw-r--r--tests/ui/methods/method-ambig-one-trait-unknown-int-type.rs36
-rw-r--r--tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr47
-rw-r--r--tests/ui/methods/method-ambig-two-traits-cross-crate.rs11
-rw-r--r--tests/ui/methods/method-ambig-two-traits-cross-crate.stderr24
-rw-r--r--tests/ui/methods/method-ambig-two-traits-from-bounds.rs8
-rw-r--r--tests/ui/methods/method-ambig-two-traits-from-bounds.stderr28
-rw-r--r--tests/ui/methods/method-ambig-two-traits-from-impls.rs16
-rw-r--r--tests/ui/methods/method-ambig-two-traits-from-impls.stderr28
-rw-r--r--tests/ui/methods/method-ambig-two-traits-from-impls2.rs16
-rw-r--r--tests/ui/methods/method-ambig-two-traits-from-impls2.stderr28
-rw-r--r--tests/ui/methods/method-ambig-two-traits-with-default-method.rs13
-rw-r--r--tests/ui/methods/method-ambig-two-traits-with-default-method.stderr28
-rw-r--r--tests/ui/methods/method-argument-inference-associated-type.rs28
-rw-r--r--tests/ui/methods/method-call-err-msg.rs22
-rw-r--r--tests/ui/methods/method-call-err-msg.stderr89
-rw-r--r--tests/ui/methods/method-call-lifetime-args-fail.rs72
-rw-r--r--tests/ui/methods/method-call-lifetime-args-fail.stderr235
-rw-r--r--tests/ui/methods/method-call-lifetime-args-lint-fail.rs87
-rw-r--r--tests/ui/methods/method-call-lifetime-args-lint-fail.stderr187
-rw-r--r--tests/ui/methods/method-call-lifetime-args-lint.rs21
-rw-r--r--tests/ui/methods/method-call-lifetime-args-lint.stderr31
-rw-r--r--tests/ui/methods/method-call-lifetime-args-subst-index.rs15
-rw-r--r--tests/ui/methods/method-call-lifetime-args-unresolved.rs6
-rw-r--r--tests/ui/methods/method-call-lifetime-args-unresolved.stderr24
-rw-r--r--tests/ui/methods/method-call-lifetime-args.rs15
-rw-r--r--tests/ui/methods/method-call-lifetime-args.stderr26
-rw-r--r--tests/ui/methods/method-call-type-binding.rs3
-rw-r--r--tests/ui/methods/method-call-type-binding.stderr9
-rw-r--r--tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs179
-rw-r--r--tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr87
-rw-r--r--tests/ui/methods/method-early-bound-lifetimes-on-self.rs31
-rw-r--r--tests/ui/methods/method-lookup-order.rs190
-rw-r--r--tests/ui/methods/method-macro-backtrace.rs25
-rw-r--r--tests/ui/methods/method-macro-backtrace.stderr11
-rw-r--r--tests/ui/methods/method-missing-call.rs30
-rw-r--r--tests/ui/methods/method-missing-call.stderr25
-rw-r--r--tests/ui/methods/method-mut-self-modifies-mut-slice-lvalue.rs44
-rw-r--r--tests/ui/methods/method-normalize-bounds-issue-20604.rs61
-rw-r--r--tests/ui/methods/method-not-found-generic-arg-elision.rs106
-rw-r--r--tests/ui/methods/method-not-found-generic-arg-elision.stderr97
-rw-r--r--tests/ui/methods/method-on-ambiguous-numeric-type.rs32
-rw-r--r--tests/ui/methods/method-on-ambiguous-numeric-type.stderr56
-rw-r--r--tests/ui/methods/method-path-in-pattern.rs32
-rw-r--r--tests/ui/methods/method-path-in-pattern.stderr39
-rw-r--r--tests/ui/methods/method-probe-no-guessing-dyn-trait.rs60
-rw-r--r--tests/ui/methods/method-projection.rs61
-rw-r--r--tests/ui/methods/method-recursive-blanket-impl.rs41
-rw-r--r--tests/ui/methods/method-resolvable-path-in-pattern.rs14
-rw-r--r--tests/ui/methods/method-resolvable-path-in-pattern.stderr9
-rw-r--r--tests/ui/methods/method-self-arg-1.rs17
-rw-r--r--tests/ui/methods/method-self-arg-1.stderr35
-rw-r--r--tests/ui/methods/method-self-arg-2.rs25
-rw-r--r--tests/ui/methods/method-self-arg-2.stderr24
-rw-r--r--tests/ui/methods/method-self-arg-aux1.rs18
-rw-r--r--tests/ui/methods/method-self-arg-aux2.rs22
-rw-r--r--tests/ui/methods/method-self-arg-trait.rs67
-rw-r--r--tests/ui/methods/method-self-arg.rs46
-rw-r--r--tests/ui/methods/method-trait-object-with-hrtb.rs41
-rw-r--r--tests/ui/methods/method-two-trait-defer-resolution-1.rs37
-rw-r--r--tests/ui/methods/method-two-trait-defer-resolution-2.rs46
-rw-r--r--tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs27
-rw-r--r--tests/ui/methods/method-where-clause.rs34
80 files changed, 3405 insertions, 0 deletions
diff --git a/tests/ui/methods/assign-to-method.rs b/tests/ui/methods/assign-to-method.rs
new file mode 100644
index 00000000000..85beaee8df0
--- /dev/null
+++ b/tests/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/tests/ui/methods/assign-to-method.stderr b/tests/ui/methods/assign-to-method.stderr
new file mode 100644
index 00000000000..cafe9abae04
--- /dev/null
+++ b/tests/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/tests/ui/methods/auxiliary/ambig_impl_2_lib.rs b/tests/ui/methods/auxiliary/ambig_impl_2_lib.rs
new file mode 100644
index 00000000000..0ed68bf6901
--- /dev/null
+++ b/tests/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/tests/ui/methods/auxiliary/macro-in-other-crate.rs b/tests/ui/methods/auxiliary/macro-in-other-crate.rs
new file mode 100644
index 00000000000..feda084634a
--- /dev/null
+++ b/tests/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/tests/ui/methods/auxiliary/method_self_arg1.rs b/tests/ui/methods/auxiliary/method_self_arg1.rs
new file mode 100644
index 00000000000..f89019fe585
--- /dev/null
+++ b/tests/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/tests/ui/methods/auxiliary/method_self_arg2.rs b/tests/ui/methods/auxiliary/method_self_arg2.rs
new file mode 100644
index 00000000000..96725456291
--- /dev/null
+++ b/tests/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/tests/ui/methods/field-method-suggestion-using-return-ty.rs b/tests/ui/methods/field-method-suggestion-using-return-ty.rs
new file mode 100644
index 00000000000..07b975c44c9
--- /dev/null
+++ b/tests/ui/methods/field-method-suggestion-using-return-ty.rs
@@ -0,0 +1,18 @@
+struct Wrapper<T>(T);
+
+impl Wrapper<Option<i32>> {
+    fn inner_mut(&self) -> Option<&mut i32> {
+        self.as_mut()
+        //~^ ERROR no method named `as_mut` found for reference `&Wrapper<Option<i32>>` in the current scope
+        //~| HELP one of the expressions' fields has a method of the same name
+        //~| HELP items from traits can only be used if
+    }
+
+    fn inner_mut_bad(&self) -> Option<&mut u32> {
+        self.as_mut()
+        //~^ ERROR no method named `as_mut` found for reference `&Wrapper<Option<i32>>` in the current scope
+        //~| HELP items from traits can only be used if
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/methods/field-method-suggestion-using-return-ty.stderr b/tests/ui/methods/field-method-suggestion-using-return-ty.stderr
new file mode 100644
index 00000000000..51c52a07e10
--- /dev/null
+++ b/tests/ui/methods/field-method-suggestion-using-return-ty.stderr
@@ -0,0 +1,27 @@
+error[E0599]: no method named `as_mut` found for reference `&Wrapper<Option<i32>>` in the current scope
+  --> $DIR/field-method-suggestion-using-return-ty.rs:5:14
+   |
+LL |         self.as_mut()
+   |              ^^^^^^ method not found in `&Wrapper<Option<i32>>`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `as_mut`, perhaps you need to implement it:
+           candidate #1: `AsMut`
+help: one of the expressions' fields has a method of the same name
+   |
+LL |         self.0.as_mut()
+   |              ++
+
+error[E0599]: no method named `as_mut` found for reference `&Wrapper<Option<i32>>` in the current scope
+  --> $DIR/field-method-suggestion-using-return-ty.rs:12:14
+   |
+LL |         self.as_mut()
+   |              ^^^^^^ method not found in `&Wrapper<Option<i32>>`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `as_mut`, perhaps you need to implement it:
+           candidate #1: `AsMut`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/methods/issues/issue-105732.rs b/tests/ui/methods/issues/issue-105732.rs
new file mode 100644
index 00000000000..d7005065813
--- /dev/null
+++ b/tests/ui/methods/issues/issue-105732.rs
@@ -0,0 +1,14 @@
+#![feature(auto_traits)]
+
+auto trait Foo {
+    fn g(&self); //~ ERROR auto traits cannot have associated items
+}
+
+trait Bar {
+    fn f(&self) {
+        // issue #105788
+        self.g(); //~ ERROR no method named `g` found for reference `&Self` in the current scope
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/methods/issues/issue-105732.stderr b/tests/ui/methods/issues/issue-105732.stderr
new file mode 100644
index 00000000000..7696642548d
--- /dev/null
+++ b/tests/ui/methods/issues/issue-105732.stderr
@@ -0,0 +1,18 @@
+error[E0380]: auto traits cannot have associated items
+  --> $DIR/issue-105732.rs:4:8
+   |
+LL | auto trait Foo {
+   |            --- auto trait cannot have associated items
+LL |     fn g(&self);
+   |     ---^-------- help: remove these associated items
+
+error[E0599]: no method named `g` found for reference `&Self` in the current scope
+  --> $DIR/issue-105732.rs:10:14
+   |
+LL |         self.g();
+   |              ^ help: there is a method with a similar name: `f`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0380, E0599.
+For more information about an error, try `rustc --explain E0380`.
diff --git a/tests/ui/methods/issues/issue-61525.rs b/tests/ui/methods/issues/issue-61525.rs
new file mode 100644
index 00000000000..c5ca0326e43
--- /dev/null
+++ b/tests/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/tests/ui/methods/issues/issue-61525.stderr b/tests/ui/methods/issues/issue-61525.stderr
new file mode 100644
index 00000000000..3e73b950a14
--- /dev/null
+++ b/tests/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 method 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/tests/ui/methods/issues/issue-84495.rs b/tests/ui/methods/issues/issue-84495.rs
new file mode 100644
index 00000000000..28c094bf2ac
--- /dev/null
+++ b/tests/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/tests/ui/methods/issues/issue-84495.stderr b/tests/ui/methods/issues/issue-84495.stderr
new file mode 100644
index 00000000000..b0217a7c844
--- /dev/null
+++ b/tests/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/tests/ui/methods/issues/issue-90315.rs b/tests/ui/methods/issues/issue-90315.rs
new file mode 100644
index 00000000000..fbecaf9b971
--- /dev/null
+++ b/tests/ui/methods/issues/issue-90315.rs
@@ -0,0 +1,75 @@
+#![allow(unused)]
+fn main() {
+    let arr = &[0, 1, 2, 3];
+    for _i in 0..arr.len().rev() {
+        //~^ ERROR can't call method
+        //~| surround the range in parentheses
+        // The above error used to say “the method `rev` exists for type `usize`”.
+        // This regression test ensures it doesn't say that any more.
+    }
+
+    // Test for #102396
+    for i in 1..11.rev() {
+        //~^ ERROR can't call method
+        //~| HELP surround the range in parentheses
+    }
+
+    let end: usize = 10;
+    for i in 1..end.rev() {
+        //~^ ERROR can't call method
+        //~| HELP surround the range in parentheses
+    }
+
+    for i in 1..(end + 1).rev() {
+        //~^ ERROR can't call method
+        //~| HELP surround the range in parentheses
+    }
+
+    if 1..(end + 1).is_empty() {
+        //~^ ERROR can't call method
+        //~| ERROR mismatched types [E0308]
+        //~| HELP surround the range in parentheses
+    }
+
+    if 1..(end + 1).is_sorted() {
+        //~^ ERROR mismatched types [E0308]
+        //~| ERROR can't call method
+        //~| HELP surround the range in parentheses
+    }
+
+    let _res: i32 = 3..6.take(2).sum();
+    //~^ ERROR can't call method
+    //~| ERROR mismatched types [E0308]
+    //~| HELP surround the range in parentheses
+
+    let _sum: i32 = 3..6.sum();
+    //~^ ERROR can't call method
+    //~| ERROR mismatched types [E0308]
+    //~| HELP surround the range in parentheses
+
+    let a = 1 as usize;
+    let b = 10 as usize;
+
+    for _a in a..=b.rev() {
+        //~^ ERROR can't call method
+        //~| HELP surround the range in parentheses
+    }
+
+    let _res = ..10.contains(3);
+    //~^ ERROR can't call method
+    //~| HELP surround the range in parentheses
+
+    if 1..end.error_method() {
+        //~^ ERROR no method named `error_method`
+        //~| ERROR mismatched types [E0308]
+        // Won't suggest
+    }
+
+    let _res = b.take(1)..a;
+    //~^ ERROR `usize` is not an iterator
+
+    let _res: i32 = ..6.take(2).sum();
+    //~^ ERROR can't call method `take` on ambiguous numeric type
+    //~| HELP you must specify a concrete type for this numeric value
+    // Won't suggest because `RangeTo` dest not implemented `take`
+}
diff --git a/tests/ui/methods/issues/issue-90315.stderr b/tests/ui/methods/issues/issue-90315.stderr
new file mode 100644
index 00000000000..4d3c086ff6e
--- /dev/null
+++ b/tests/ui/methods/issues/issue-90315.stderr
@@ -0,0 +1,190 @@
+error[E0689]: can't call method `rev` on type `usize`
+  --> $DIR/issue-90315.rs:4:28
+   |
+LL |     for _i in 0..arr.len().rev() {
+   |                            ^^^ can't call method `rev` on type `usize`
+   |
+help: you must surround the range in parentheses to call its `rev` function
+   |
+LL |     for _i in (0..arr.len()).rev() {
+   |               +            +
+
+error[E0689]: can't call method `rev` on type `{integer}`
+  --> $DIR/issue-90315.rs:12:20
+   |
+LL |     for i in 1..11.rev() {
+   |                    ^^^ can't call method `rev` on type `{integer}`
+   |
+help: you must surround the range in parentheses to call its `rev` function
+   |
+LL |     for i in (1..11).rev() {
+   |              +     +
+
+error[E0689]: can't call method `rev` on type `usize`
+  --> $DIR/issue-90315.rs:18:21
+   |
+LL |     for i in 1..end.rev() {
+   |                     ^^^ can't call method `rev` on type `usize`
+   |
+help: you must surround the range in parentheses to call its `rev` function
+   |
+LL |     for i in (1..end).rev() {
+   |              +      +
+
+error[E0689]: can't call method `rev` on type `usize`
+  --> $DIR/issue-90315.rs:23:27
+   |
+LL |     for i in 1..(end + 1).rev() {
+   |                           ^^^ can't call method `rev` on type `usize`
+   |
+help: you must surround the range in parentheses to call its `rev` function
+   |
+LL |     for i in (1..(end + 1)).rev() {
+   |              +            +
+
+error[E0689]: can't call method `is_empty` on type `usize`
+  --> $DIR/issue-90315.rs:28:21
+   |
+LL |     if 1..(end + 1).is_empty() {
+   |                     ^^^^^^^^ can't call method `is_empty` on type `usize`
+   |
+help: you must surround the range in parentheses to call its `is_empty` function
+   |
+LL |     if (1..(end + 1)).is_empty() {
+   |        +            +
+
+error[E0308]: mismatched types
+  --> $DIR/issue-90315.rs:28:8
+   |
+LL |     if 1..(end + 1).is_empty() {
+   |        ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+   |
+   = note: expected type `bool`
+            found struct `std::ops::Range<{integer}>`
+
+error[E0689]: can't call method `is_sorted` on type `usize`
+  --> $DIR/issue-90315.rs:34:21
+   |
+LL |     if 1..(end + 1).is_sorted() {
+   |                     ^^^^^^^^^ can't call method `is_sorted` on type `usize`
+   |
+help: you must surround the range in parentheses to call its `is_sorted` function
+   |
+LL |     if (1..(end + 1)).is_sorted() {
+   |        +            +
+
+error[E0308]: mismatched types
+  --> $DIR/issue-90315.rs:34:8
+   |
+LL |     if 1..(end + 1).is_sorted() {
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+   |
+   = note: expected type `bool`
+            found struct `std::ops::Range<{integer}>`
+
+error[E0689]: can't call method `take` on type `{integer}`
+  --> $DIR/issue-90315.rs:40:26
+   |
+LL |     let _res: i32 = 3..6.take(2).sum();
+   |                          ^^^^ can't call method `take` on type `{integer}`
+   |
+help: you must surround the range in parentheses to call its `take` function
+   |
+LL |     let _res: i32 = (3..6).take(2).sum();
+   |                     +    +
+
+error[E0308]: mismatched types
+  --> $DIR/issue-90315.rs:40:21
+   |
+LL |     let _res: i32 = 3..6.take(2).sum();
+   |               ---   ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `Range`
+   |               |
+   |               expected due to this
+   |
+   = note: expected type `i32`
+            found struct `std::ops::Range<{integer}>`
+
+error[E0689]: can't call method `sum` on type `{integer}`
+  --> $DIR/issue-90315.rs:45:26
+   |
+LL |     let _sum: i32 = 3..6.sum();
+   |                          ^^^ can't call method `sum` on type `{integer}`
+   |
+help: you must surround the range in parentheses to call its `sum` function
+   |
+LL |     let _sum: i32 = (3..6).sum();
+   |                     +    +
+
+error[E0308]: mismatched types
+  --> $DIR/issue-90315.rs:45:21
+   |
+LL |     let _sum: i32 = 3..6.sum();
+   |               ---   ^^^^^^^^^^ expected `i32`, found struct `Range`
+   |               |
+   |               expected due to this
+   |
+   = note: expected type `i32`
+            found struct `std::ops::Range<{integer}>`
+
+error[E0689]: can't call method `rev` on type `usize`
+  --> $DIR/issue-90315.rs:53:21
+   |
+LL |     for _a in a..=b.rev() {
+   |                     ^^^ can't call method `rev` on type `usize`
+   |
+help: you must surround the range in parentheses to call its `rev` function
+   |
+LL |     for _a in (a..=b).rev() {
+   |               +     +
+
+error[E0689]: can't call method `contains` on type `{integer}`
+  --> $DIR/issue-90315.rs:58:21
+   |
+LL |     let _res = ..10.contains(3);
+   |                     ^^^^^^^^ can't call method `contains` on type `{integer}`
+   |
+help: you must surround the range in parentheses to call its `contains` function
+   |
+LL |     let _res = (..10).contains(3);
+   |                +    +
+
+error[E0599]: no method named `error_method` found for type `usize` in the current scope
+  --> $DIR/issue-90315.rs:62:15
+   |
+LL |     if 1..end.error_method() {
+   |               ^^^^^^^^^^^^ method not found in `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-90315.rs:62:8
+   |
+LL |     if 1..end.error_method() {
+   |        ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+   |
+   = note: expected type `bool`
+            found struct `std::ops::Range<{integer}>`
+
+error[E0599]: `usize` is not an iterator
+  --> $DIR/issue-90315.rs:68:18
+   |
+LL |     let _res = b.take(1)..a;
+   |                  ^^^^ `usize` is not an iterator
+   |
+   = note: the following trait bounds were not satisfied:
+           `usize: Iterator`
+           which is required by `&mut usize: Iterator`
+
+error[E0689]: can't call method `take` on ambiguous numeric type `{integer}`
+  --> $DIR/issue-90315.rs:71:25
+   |
+LL |     let _res: i32 = ..6.take(2).sum();
+   |                         ^^^^
+   |
+help: you must specify a concrete type for this numeric value, like `i32`
+   |
+LL |     let _res: i32 = ..6_i32.take(2).sum();
+   |                       ~~~~~
+
+error: aborting due to 18 previous errors
+
+Some errors have detailed explanations: E0308, E0599, E0689.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/methods/issues/issue-94581.rs b/tests/ui/methods/issues/issue-94581.rs
new file mode 100644
index 00000000000..df393e91db0
--- /dev/null
+++ b/tests/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/tests/ui/methods/issues/issue-94581.stderr b/tests/ui/methods/issues/issue-94581.stderr
new file mode 100644
index 00000000000..d6be29cf582
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-ambig-one-trait-unknown-int-type.rs b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.rs
new file mode 100644
index 00000000000..7b2fc34e1af
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
new file mode 100644
index 00000000000..e0f8a5447b0
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-ambig-two-traits-cross-crate.rs b/tests/ui/methods/method-ambig-two-traits-cross-crate.rs
new file mode 100644
index 00000000000..006e315b02c
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr b/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr
new file mode 100644
index 00000000000..4b2597eed3c
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-ambig-two-traits-from-bounds.rs b/tests/ui/methods/method-ambig-two-traits-from-bounds.rs
new file mode 100644
index 00000000000..e3cc5557f42
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr
new file mode 100644
index 00000000000..1feaa2c73e0
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-ambig-two-traits-from-impls.rs b/tests/ui/methods/method-ambig-two-traits-from-impls.rs
new file mode 100644
index 00000000000..22bf8406605
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-ambig-two-traits-from-impls.stderr b/tests/ui/methods/method-ambig-two-traits-from-impls.stderr
new file mode 100644
index 00000000000..f69b5689239
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-ambig-two-traits-from-impls2.rs b/tests/ui/methods/method-ambig-two-traits-from-impls2.rs
new file mode 100644
index 00000000000..0a96c1223da
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr b/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr
new file mode 100644
index 00000000000..4ba778e0ef7
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-ambig-two-traits-with-default-method.rs b/tests/ui/methods/method-ambig-two-traits-with-default-method.rs
new file mode 100644
index 00000000000..aa7094b9e6e
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr b/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr
new file mode 100644
index 00000000000..e84dff8bab7
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-argument-inference-associated-type.rs b/tests/ui/methods/method-argument-inference-associated-type.rs
new file mode 100644
index 00000000000..a3c31fab1c2
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-call-err-msg.rs b/tests/ui/methods/method-call-err-msg.rs
new file mode 100644
index 00000000000..4807a956aa2
--- /dev/null
+++ b/tests/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 method takes 0 arguments but 1 argument was supplied
+     .one()     //~ ERROR this method takes 1 argument but 0 arguments were supplied
+     .two(0);   //~ ERROR this method 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 method takes 3 arguments but 0 arguments were supplied
+}
diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr
new file mode 100644
index 00000000000..81269b73b9a
--- /dev/null
+++ b/tests/ui/methods/method-call-err-msg.stderr
@@ -0,0 +1,89 @@
+error[E0061]: this method 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 method 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 method 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 trait `Iterator` must be implemented
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   = 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 method 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/tests/ui/methods/method-call-lifetime-args-fail.rs b/tests/ui/methods/method-call-lifetime-args-fail.rs
new file mode 100644
index 00000000000..6bf55844da8
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-call-lifetime-args-fail.stderr b/tests/ui/methods/method-call-lifetime-args-fail.stderr
new file mode 100644
index 00000000000..249b48ab194
--- /dev/null
+++ b/tests/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, 'static>();
+   |                      +++++++++
+
+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, 'static>(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/tests/ui/methods/method-call-lifetime-args-lint-fail.rs b/tests/ui/methods/method-call-lifetime-args-lint-fail.rs
new file mode 100644
index 00000000000..23893911eab
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-call-lifetime-args-lint-fail.stderr b/tests/ui/methods/method-call-lifetime-args-lint-fail.stderr
new file mode 100644
index 00000000000..394c1ac3c09
--- /dev/null
+++ b/tests/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);
+   |              ^^^^^^^
+   |
+   = 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>
+note: the lint level is defined here
+  --> $DIR/method-call-lifetime-args-lint-fail.rs:1:9
+   |
+LL | #![deny(late_bound_lifetime_arguments)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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/tests/ui/methods/method-call-lifetime-args-lint.rs b/tests/ui/methods/method-call-lifetime-args-lint.rs
new file mode 100644
index 00000000000..14729e1e27e
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-call-lifetime-args-lint.stderr b/tests/ui/methods/method-call-lifetime-args-lint.stderr
new file mode 100644
index 00000000000..b4fc2d71761
--- /dev/null
+++ b/tests/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);
+   |              ^^^^^^^
+   |
+   = 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>
+note: the lint level is defined here
+  --> $DIR/method-call-lifetime-args-lint.rs:1:9
+   |
+LL | #![deny(late_bound_lifetime_arguments)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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/tests/ui/methods/method-call-lifetime-args-subst-index.rs b/tests/ui/methods/method-call-lifetime-args-subst-index.rs
new file mode 100644
index 00000000000..8df58a3486e
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-call-lifetime-args-unresolved.rs b/tests/ui/methods/method-call-lifetime-args-unresolved.rs
new file mode 100644
index 00000000000..ba7231070a0
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-call-lifetime-args-unresolved.stderr b/tests/ui/methods/method-call-lifetime-args-unresolved.stderr
new file mode 100644
index 00000000000..25ad360b329
--- /dev/null
+++ b/tests/ui/methods/method-call-lifetime-args-unresolved.stderr
@@ -0,0 +1,24 @@
+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
+   |
+   = note: the late bound lifetime parameter is introduced here
+   |
+   = 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>
+   = note: `#[warn(late_bound_lifetime_arguments)]` on by default
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/tests/ui/methods/method-call-lifetime-args.rs b/tests/ui/methods/method-call-lifetime-args.rs
new file mode 100644
index 00000000000..3292e9fcdf8
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-call-lifetime-args.stderr b/tests/ui/methods/method-call-lifetime-args.stderr
new file mode 100644
index 00000000000..64ae79e9bb2
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-call-type-binding.rs b/tests/ui/methods/method-call-type-binding.rs
new file mode 100644
index 00000000000..f547ca8d1c2
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-call-type-binding.stderr b/tests/ui/methods/method-call-type-binding.stderr
new file mode 100644
index 00000000000..4b93082ace5
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
new file mode 100644
index 00000000000..9e53ff07917
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
new file mode 100644
index 00000000000..82addab9479
--- /dev/null
+++ b/tests/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: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+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/tests/ui/methods/method-early-bound-lifetimes-on-self.rs b/tests/ui/methods/method-early-bound-lifetimes-on-self.rs
new file mode 100644
index 00000000000..f2ace32c6b6
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-lookup-order.rs b/tests/ui/methods/method-lookup-order.rs
new file mode 100644
index 00000000000..986fe103cdc
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-macro-backtrace.rs b/tests/ui/methods/method-macro-backtrace.rs
new file mode 100644
index 00000000000..00fe32b7c15
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-macro-backtrace.stderr b/tests/ui/methods/method-macro-backtrace.stderr
new file mode 100644
index 00000000000..dd616c4a5e7
--- /dev/null
+++ b/tests/ui/methods/method-macro-backtrace.stderr
@@ -0,0 +1,11 @@
+error[E0592]: duplicate definitions with name `bar`
+  --> $DIR/method-macro-backtrace.rs:22:5
+   |
+LL |     fn bar(&self) { }
+   |     ------------- other definition for `bar`
+LL |     fn bar(&self) { }
+   |     ^^^^^^^^^^^^^ duplicate definitions for `bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/tests/ui/methods/method-missing-call.rs b/tests/ui/methods/method-missing-call.rs
new file mode 100644
index 00000000000..7ce1e9a4f1b
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-missing-call.stderr b/tests/ui/methods/method-missing-call.stderr
new file mode 100644
index 00000000000..040a65d1680
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-mut-self-modifies-mut-slice-lvalue.rs b/tests/ui/methods/method-mut-self-modifies-mut-slice-lvalue.rs
new file mode 100644
index 00000000000..daff037b27b
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-normalize-bounds-issue-20604.rs b/tests/ui/methods/method-normalize-bounds-issue-20604.rs
new file mode 100644
index 00000000000..9c0b952849e
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-not-found-generic-arg-elision.rs b/tests/ui/methods/method-not-found-generic-arg-elision.rs
new file mode 100644
index 00000000000..799ced5e9c4
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-not-found-generic-arg-elision.stderr b/tests/ui/methods/method-not-found-generic-arg-elision.stderr
new file mode 100644
index 00000000000..8846efba871
--- /dev/null
+++ b/tests/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<Iter<'_, i32>, [closure@method-not-found-generic-arg-elision.rs:87:18]>`
+
+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/tests/ui/methods/method-on-ambiguous-numeric-type.rs b/tests/ui/methods/method-on-ambiguous-numeric-type.rs
new file mode 100644
index 00000000000..82f47438d50
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-on-ambiguous-numeric-type.stderr b/tests/ui/methods/method-on-ambiguous-numeric-type.stderr
new file mode 100644
index 00000000000..91733411637
--- /dev/null
+++ b/tests/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:35
+   |
+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/tests/ui/methods/method-path-in-pattern.rs b/tests/ui/methods/method-path-in-pattern.rs
new file mode 100644
index 00000000000..40645309552
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-path-in-pattern.stderr b/tests/ui/methods/method-path-in-pattern.stderr
new file mode 100644
index 00000000000..63c7abe0e4a
--- /dev/null
+++ b/tests/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 => {}
+   |         ^^^^^^^^ not a unit struct, unit variant or constant
+
+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 => {}
+   |         ^^^^^^^^^^ not a unit struct, unit variant or constant
+
+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 => {}
+   |         ^^^^^^^^^^^^^^^^ not a unit struct, unit variant or constant
+
+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 {}
+   |            ^^^^^^^^ not a unit struct, unit variant or constant
+
+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 {}
+   |            ^^^^^^^^^^ not a unit struct, unit variant or constant
+
+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 {}
+   |            ^^^^^^^^^^^^^^ not a unit struct, unit variant or constant
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0533`.
diff --git a/tests/ui/methods/method-probe-no-guessing-dyn-trait.rs b/tests/ui/methods/method-probe-no-guessing-dyn-trait.rs
new file mode 100644
index 00000000000..ec41b711709
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-projection.rs b/tests/ui/methods/method-projection.rs
new file mode 100644
index 00000000000..21d983f192a
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-recursive-blanket-impl.rs b/tests/ui/methods/method-recursive-blanket-impl.rs
new file mode 100644
index 00000000000..a2db75b4e85
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-resolvable-path-in-pattern.rs b/tests/ui/methods/method-resolvable-path-in-pattern.rs
new file mode 100644
index 00000000000..2973800a4d4
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-resolvable-path-in-pattern.stderr b/tests/ui/methods/method-resolvable-path-in-pattern.stderr
new file mode 100644
index 00000000000..7c454a9a777
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-self-arg-1.rs b/tests/ui/methods/method-self-arg-1.rs
new file mode 100644
index 00000000000..f589f20d81d
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-self-arg-1.stderr b/tests/ui/methods/method-self-arg-1.stderr
new file mode 100644
index 00000000000..01fec6fcaae
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-self-arg-2.rs b/tests/ui/methods/method-self-arg-2.rs
new file mode 100644
index 00000000000..0f8c048ac98
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-self-arg-2.stderr b/tests/ui/methods/method-self-arg-2.stderr
new file mode 100644
index 00000000000..b98f7a78661
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-self-arg-aux1.rs b/tests/ui/methods/method-self-arg-aux1.rs
new file mode 100644
index 00000000000..79b70a17ca1
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-self-arg-aux2.rs b/tests/ui/methods/method-self-arg-aux2.rs
new file mode 100644
index 00000000000..16487b54f17
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-self-arg-trait.rs b/tests/ui/methods/method-self-arg-trait.rs
new file mode 100644
index 00000000000..ffa7a552b25
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-self-arg.rs b/tests/ui/methods/method-self-arg.rs
new file mode 100644
index 00000000000..f738fa19c85
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-trait-object-with-hrtb.rs b/tests/ui/methods/method-trait-object-with-hrtb.rs
new file mode 100644
index 00000000000..d1bee676c2f
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-two-trait-defer-resolution-1.rs b/tests/ui/methods/method-two-trait-defer-resolution-1.rs
new file mode 100644
index 00000000000..b768620cd3a
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-two-trait-defer-resolution-2.rs b/tests/ui/methods/method-two-trait-defer-resolution-2.rs
new file mode 100644
index 00000000000..fc5766da971
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs
new file mode 100644
index 00000000000..d820d2ad08a
--- /dev/null
+++ b/tests/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/tests/ui/methods/method-where-clause.rs b/tests/ui/methods/method-where-clause.rs
new file mode 100644
index 00000000000..01692abf9b6
--- /dev/null
+++ b/tests/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));
+}