about summary refs log tree commit diff
path: root/tests/ui/inference
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/inference')
-rw-r--r--tests/ui/inference/ambiguous_type_parameter.rs17
-rw-r--r--tests/ui/inference/ambiguous_type_parameter.stderr14
-rw-r--r--tests/ui/inference/auxiliary/inference_unstable_iterator.rs35
-rw-r--r--tests/ui/inference/auxiliary/inference_unstable_itertools.rs25
-rw-r--r--tests/ui/inference/cannot-infer-async.rs16
-rw-r--r--tests/ui/inference/cannot-infer-async.stderr14
-rw-r--r--tests/ui/inference/cannot-infer-closure-circular.rs13
-rw-r--r--tests/ui/inference/cannot-infer-closure-circular.stderr14
-rw-r--r--tests/ui/inference/cannot-infer-closure.rs7
-rw-r--r--tests/ui/inference/cannot-infer-closure.stderr14
-rw-r--r--tests/ui/inference/cannot-infer-partial-try-return.rs23
-rw-r--r--tests/ui/inference/cannot-infer-partial-try-return.stderr16
-rw-r--r--tests/ui/inference/char-as-str-multi.rs7
-rw-r--r--tests/ui/inference/char-as-str-multi.stderr19
-rw-r--r--tests/ui/inference/char-as-str-single.fixed12
-rw-r--r--tests/ui/inference/char-as-str-single.rs12
-rw-r--r--tests/ui/inference/char-as-str-single.stderr42
-rw-r--r--tests/ui/inference/deref-suggestion.rs75
-rw-r--r--tests/ui/inference/deref-suggestion.stderr180
-rw-r--r--tests/ui/inference/erase-type-params-in-label.rs27
-rw-r--r--tests/ui/inference/erase-type-params-in-label.stderr37
-rw-r--r--tests/ui/inference/infer-binary-operand-behind-reference.rs30
-rw-r--r--tests/ui/inference/inference-variable-behind-raw-pointer.rs11
-rw-r--r--tests/ui/inference/inference-variable-behind-raw-pointer.stderr12
-rw-r--r--tests/ui/inference/inference_unstable.rs31
-rw-r--r--tests/ui/inference/inference_unstable.stderr57
-rw-r--r--tests/ui/inference/inference_unstable_featured.rs17
-rw-r--r--tests/ui/inference/inference_unstable_featured.stderr20
-rw-r--r--tests/ui/inference/inference_unstable_forced.rs12
-rw-r--r--tests/ui/inference/inference_unstable_forced.stderr12
-rw-r--r--tests/ui/inference/issue-103587.rs12
-rw-r--r--tests/ui/inference/issue-103587.stderr40
-rw-r--r--tests/ui/inference/issue-104649.rs32
-rw-r--r--tests/ui/inference/issue-104649.stderr14
-rw-r--r--tests/ui/inference/issue-28935.rs9
-rw-r--r--tests/ui/inference/issue-36053.rs22
-rw-r--r--tests/ui/inference/issue-70703.rs26
-rw-r--r--tests/ui/inference/issue-71309.rs7
-rw-r--r--tests/ui/inference/issue-71309.stderr15
-rw-r--r--tests/ui/inference/issue-71732.rs24
-rw-r--r--tests/ui/inference/issue-71732.stderr22
-rw-r--r--tests/ui/inference/issue-72616.rs32
-rw-r--r--tests/ui/inference/issue-72616.stderr37
-rw-r--r--tests/ui/inference/issue-72690.rs70
-rw-r--r--tests/ui/inference/issue-72690.stderr229
-rw-r--r--tests/ui/inference/issue-80816.rs54
-rw-r--r--tests/ui/inference/issue-80816.stderr27
-rw-r--r--tests/ui/inference/issue-81522.rs31
-rw-r--r--tests/ui/inference/issue-83606.rs10
-rw-r--r--tests/ui/inference/issue-83606.stderr14
-rw-r--r--tests/ui/inference/issue-86162-1.rs9
-rw-r--r--tests/ui/inference/issue-86162-1.stderr22
-rw-r--r--tests/ui/inference/issue-86162-2.rs14
-rw-r--r--tests/ui/inference/issue-86162-2.stderr22
-rw-r--r--tests/ui/inference/lub-glb-with-unbound-infer-var.rs15
-rw-r--r--tests/ui/inference/need_type_info/channel.rs19
-rw-r--r--tests/ui/inference/need_type_info/channel.stderr25
-rw-r--r--tests/ui/inference/need_type_info/concrete-impl.rs16
-rw-r--r--tests/ui/inference/need_type_info/concrete-impl.stderr24
-rw-r--r--tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.rs11
-rw-r--r--tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr9
-rw-r--r--tests/ui/inference/need_type_info/expr-struct-type-relative-enum.rs21
-rw-r--r--tests/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr14
-rw-r--r--tests/ui/inference/need_type_info/expr-struct-type-relative-gat.rs19
-rw-r--r--tests/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr9
-rw-r--r--tests/ui/inference/need_type_info/expr-struct-type-relative.rs21
-rw-r--r--tests/ui/inference/need_type_info/expr-struct-type-relative.stderr14
-rw-r--r--tests/ui/inference/need_type_info/issue-103053.rs18
-rw-r--r--tests/ui/inference/need_type_info/issue-103053.stderr14
-rw-r--r--tests/ui/inference/need_type_info/self-ty-in-path.rs13
-rw-r--r--tests/ui/inference/need_type_info/self-ty-in-path.stderr14
-rw-r--r--tests/ui/inference/need_type_info/type-alias-indirect.rs18
-rw-r--r--tests/ui/inference/need_type_info/type-alias-indirect.stderr9
-rw-r--r--tests/ui/inference/need_type_info/type-alias.rs36
-rw-r--r--tests/ui/inference/need_type_info/type-alias.stderr15
-rw-r--r--tests/ui/inference/newlambdas-ret-infer.rs12
-rw-r--r--tests/ui/inference/newlambdas-ret-infer2.rs12
-rw-r--r--tests/ui/inference/question-mark-type-infer.rs16
-rw-r--r--tests/ui/inference/question-mark-type-infer.stderr9
-rw-r--r--tests/ui/inference/range-type-infer.rs22
-rw-r--r--tests/ui/inference/simple-infer.rs6
-rw-r--r--tests/ui/inference/str-as-char.fixed10
-rw-r--r--tests/ui/inference/str-as-char.rs10
-rw-r--r--tests/ui/inference/str-as-char.stderr38
-rw-r--r--tests/ui/inference/tutorial-suffix-inference-test.rs24
-rw-r--r--tests/ui/inference/tutorial-suffix-inference-test.stderr57
-rw-r--r--tests/ui/inference/type-infer-generalize-ty-var.rs56
87 files changed, 2241 insertions, 0 deletions
diff --git a/tests/ui/inference/ambiguous_type_parameter.rs b/tests/ui/inference/ambiguous_type_parameter.rs
new file mode 100644
index 00000000000..dc70ed661d2
--- /dev/null
+++ b/tests/ui/inference/ambiguous_type_parameter.rs
@@ -0,0 +1,17 @@
+use std::collections::HashMap;
+
+trait Store<K, V> {
+    fn get_raw(&self, key: &K) -> Option<()>;
+}
+
+struct InMemoryStore;
+
+impl<K> Store<String, HashMap<K, String>> for InMemoryStore {
+    fn get_raw(&self, key: &String) -> Option<()> {
+        None
+    }
+}
+
+fn main() {
+    InMemoryStore.get_raw(&String::default()); //~ ERROR type annotations needed
+}
diff --git a/tests/ui/inference/ambiguous_type_parameter.stderr b/tests/ui/inference/ambiguous_type_parameter.stderr
new file mode 100644
index 00000000000..9cbe221de13
--- /dev/null
+++ b/tests/ui/inference/ambiguous_type_parameter.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/ambiguous_type_parameter.rs:16:19
+   |
+LL |     InMemoryStore.get_raw(&String::default());
+   |                   ^^^^^^^
+   |
+help: try using a fully qualified path to specify the expected types
+   |
+LL |     <InMemoryStore as Store<String, HashMap<K, String>>>::get_raw(&InMemoryStore, &String::default());
+   |     +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++             ~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/auxiliary/inference_unstable_iterator.rs b/tests/ui/inference/auxiliary/inference_unstable_iterator.rs
new file mode 100644
index 00000000000..04bc0b1a8ac
--- /dev/null
+++ b/tests/ui/inference/auxiliary/inference_unstable_iterator.rs
@@ -0,0 +1,35 @@
+#![feature(staged_api)]
+#![feature(arbitrary_self_types)]
+
+#![stable(feature = "ipu_iterator", since = "1.0.0")]
+
+#[stable(feature = "ipu_iterator", since = "1.0.0")]
+pub trait IpuIterator {
+    #[unstable(feature = "ipu_flatten", issue = "99999")]
+    fn ipu_flatten(&self) -> u32 {
+        0
+    }
+
+    #[unstable(feature = "ipu_flatten", issue = "99999")]
+    fn ipu_by_value_vs_by_ref(self) -> u32 where Self: Sized {
+        0
+    }
+
+    #[unstable(feature = "ipu_flatten", issue = "99999")]
+    fn ipu_by_ref_vs_by_ref_mut(&self) -> u32 {
+        0
+    }
+
+    #[unstable(feature = "ipu_flatten", issue = "99999")]
+    fn ipu_by_mut_ptr_vs_by_const_ptr(self: *mut Self) -> u32 {
+        0
+    }
+
+    #[unstable(feature = "assoc_const_ipu_iter", issue = "99999")]
+    const C: i32;
+}
+
+#[stable(feature = "ipu_iterator", since = "1.0.0")]
+impl IpuIterator for char {
+    const C: i32 = 42;
+}
diff --git a/tests/ui/inference/auxiliary/inference_unstable_itertools.rs b/tests/ui/inference/auxiliary/inference_unstable_itertools.rs
new file mode 100644
index 00000000000..fa1efbcfefc
--- /dev/null
+++ b/tests/ui/inference/auxiliary/inference_unstable_itertools.rs
@@ -0,0 +1,25 @@
+#![feature(arbitrary_self_types)]
+
+pub trait IpuItertools {
+    fn ipu_flatten(&self) -> u32 {
+        1
+    }
+
+    fn ipu_by_value_vs_by_ref(&self) -> u32 {
+        1
+    }
+
+    fn ipu_by_ref_vs_by_ref_mut(&mut self) -> u32 {
+        1
+    }
+
+    fn ipu_by_mut_ptr_vs_by_const_ptr(self: *const Self) -> u32 {
+        1
+    }
+
+    const C: i32;
+}
+
+impl IpuItertools for char {
+    const C: i32 = 1;
+}
diff --git a/tests/ui/inference/cannot-infer-async.rs b/tests/ui/inference/cannot-infer-async.rs
new file mode 100644
index 00000000000..b5152d04f69
--- /dev/null
+++ b/tests/ui/inference/cannot-infer-async.rs
@@ -0,0 +1,16 @@
+// edition:2018
+
+use std::io::Error;
+
+fn make_unit() -> Result<(), Error> {
+    Ok(())
+}
+
+fn main() {
+    let fut = async {
+        make_unit()?;
+
+        Ok(())
+        //~^ ERROR type annotations needed
+    };
+}
diff --git a/tests/ui/inference/cannot-infer-async.stderr b/tests/ui/inference/cannot-infer-async.stderr
new file mode 100644
index 00000000000..0579cf238a9
--- /dev/null
+++ b/tests/ui/inference/cannot-infer-async.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot-infer-async.rs:13:9
+   |
+LL |         Ok(())
+   |         ^^ cannot infer type of the type parameter `E` declared on the enum `Result`
+   |
+help: consider specifying the generic arguments
+   |
+LL |         Ok::<(), E>(())
+   |           +++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/cannot-infer-closure-circular.rs b/tests/ui/inference/cannot-infer-closure-circular.rs
new file mode 100644
index 00000000000..affb481496d
--- /dev/null
+++ b/tests/ui/inference/cannot-infer-closure-circular.rs
@@ -0,0 +1,13 @@
+fn main() {
+    // Below we call the closure with its own return as the argument, unifying
+    // its inferred input and return types. We want to make sure that the generated
+    // error handles this gracefully, and in particular doesn't generate an extra
+    // note about the `?` operator in the closure body, which isn't relevant to
+    // the inference.
+    let x = |r| { //~ ERROR type annotations needed for `Result<(), E>`
+        let v = r?;
+        Ok(v)
+    };
+
+    let _ = x(x(Ok(())));
+}
diff --git a/tests/ui/inference/cannot-infer-closure-circular.stderr b/tests/ui/inference/cannot-infer-closure-circular.stderr
new file mode 100644
index 00000000000..b706cd2bc36
--- /dev/null
+++ b/tests/ui/inference/cannot-infer-closure-circular.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed for `Result<(), E>`
+  --> $DIR/cannot-infer-closure-circular.rs:7:14
+   |
+LL |     let x = |r| {
+   |              ^
+   |
+help: consider giving this closure parameter an explicit type, where the type for type parameter `E` is specified
+   |
+LL |     let x = |r: Result<(), E>| {
+   |               +++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/cannot-infer-closure.rs b/tests/ui/inference/cannot-infer-closure.rs
new file mode 100644
index 00000000000..bd5d10b4173
--- /dev/null
+++ b/tests/ui/inference/cannot-infer-closure.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let x = |a: (), b: ()| {
+        Err(a)?;
+        Ok(b)
+        //~^ ERROR type annotations needed
+    };
+}
diff --git a/tests/ui/inference/cannot-infer-closure.stderr b/tests/ui/inference/cannot-infer-closure.stderr
new file mode 100644
index 00000000000..a4b818e6e2b
--- /dev/null
+++ b/tests/ui/inference/cannot-infer-closure.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot-infer-closure.rs:4:9
+   |
+LL |         Ok(b)
+   |         ^^ cannot infer type of the type parameter `E` declared on the enum `Result`
+   |
+help: consider specifying the generic arguments
+   |
+LL |         Ok::<(), E>(b)
+   |           +++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/cannot-infer-partial-try-return.rs b/tests/ui/inference/cannot-infer-partial-try-return.rs
new file mode 100644
index 00000000000..b555697dc34
--- /dev/null
+++ b/tests/ui/inference/cannot-infer-partial-try-return.rs
@@ -0,0 +1,23 @@
+struct QualifiedError<E>(E);
+
+impl<E, T> From<E> for QualifiedError<T>
+where
+    E: std::error::Error,
+    T: From<E>,
+{
+    fn from(e: E) -> QualifiedError<T> {
+        QualifiedError(e.into())
+    }
+}
+
+fn infallible() -> Result<(), std::convert::Infallible> {
+    Ok(())
+}
+
+fn main() {
+    let x = || -> Result<_, QualifiedError<_>> {
+        infallible()?;
+        Ok(())
+        //~^ ERROR type annotations needed
+    };
+}
diff --git a/tests/ui/inference/cannot-infer-partial-try-return.stderr b/tests/ui/inference/cannot-infer-partial-try-return.stderr
new file mode 100644
index 00000000000..2a56aaa44fe
--- /dev/null
+++ b/tests/ui/inference/cannot-infer-partial-try-return.stderr
@@ -0,0 +1,16 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot-infer-partial-try-return.rs:20:9
+   |
+LL |         infallible()?;
+   |         ------------- type must be known at this point
+LL |         Ok(())
+   |         ^^ cannot infer type of the type parameter `E` declared on the enum `Result`
+   |
+help: consider specifying the generic arguments
+   |
+LL |         Ok::<(), QualifiedError<_>>(())
+   |           +++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/char-as-str-multi.rs b/tests/ui/inference/char-as-str-multi.rs
new file mode 100644
index 00000000000..c29a15025a9
--- /dev/null
+++ b/tests/ui/inference/char-as-str-multi.rs
@@ -0,0 +1,7 @@
+// When a MULTI/NO-character string literal is used where a char should be,
+// DO NOT suggest changing to single quotes.
+
+fn main() {
+    let _: char = "foo"; //~ ERROR mismatched types
+    let _: char = ""; //~ ERROR mismatched types
+}
diff --git a/tests/ui/inference/char-as-str-multi.stderr b/tests/ui/inference/char-as-str-multi.stderr
new file mode 100644
index 00000000000..297ca2b548f
--- /dev/null
+++ b/tests/ui/inference/char-as-str-multi.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+  --> $DIR/char-as-str-multi.rs:5:19
+   |
+LL |     let _: char = "foo";
+   |            ----   ^^^^^ expected `char`, found `&str`
+   |            |
+   |            expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/char-as-str-multi.rs:6:19
+   |
+LL |     let _: char = "";
+   |            ----   ^^ expected `char`, found `&str`
+   |            |
+   |            expected due to this
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/inference/char-as-str-single.fixed b/tests/ui/inference/char-as-str-single.fixed
new file mode 100644
index 00000000000..bab1854dc51
--- /dev/null
+++ b/tests/ui/inference/char-as-str-single.fixed
@@ -0,0 +1,12 @@
+// When a SINGLE-character string literal is used where a char should be,
+// suggest changing to single quotes.
+
+// Testing both single-byte and multi-byte characters, as we should handle both.
+
+// run-rustfix
+
+fn main() {
+    let _: char = 'a'; //~ ERROR mismatched types
+    let _: char = '人'; //~ ERROR mismatched types
+    let _: char = '\''; //~ ERROR mismatched types
+}
diff --git a/tests/ui/inference/char-as-str-single.rs b/tests/ui/inference/char-as-str-single.rs
new file mode 100644
index 00000000000..736920643b2
--- /dev/null
+++ b/tests/ui/inference/char-as-str-single.rs
@@ -0,0 +1,12 @@
+// When a SINGLE-character string literal is used where a char should be,
+// suggest changing to single quotes.
+
+// Testing both single-byte and multi-byte characters, as we should handle both.
+
+// run-rustfix
+
+fn main() {
+    let _: char = "a"; //~ ERROR mismatched types
+    let _: char = "人"; //~ ERROR mismatched types
+    let _: char = "'"; //~ ERROR mismatched types
+}
diff --git a/tests/ui/inference/char-as-str-single.stderr b/tests/ui/inference/char-as-str-single.stderr
new file mode 100644
index 00000000000..3375ec6ac32
--- /dev/null
+++ b/tests/ui/inference/char-as-str-single.stderr
@@ -0,0 +1,42 @@
+error[E0308]: mismatched types
+  --> $DIR/char-as-str-single.rs:9:19
+   |
+LL |     let _: char = "a";
+   |            ----   ^^^ expected `char`, found `&str`
+   |            |
+   |            expected due to this
+   |
+help: if you meant to write a `char` literal, use single quotes
+   |
+LL |     let _: char = 'a';
+   |                   ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/char-as-str-single.rs:10:19
+   |
+LL |     let _: char = "人";
+   |            ----   ^^^^ expected `char`, found `&str`
+   |            |
+   |            expected due to this
+   |
+help: if you meant to write a `char` literal, use single quotes
+   |
+LL |     let _: char = '人';
+   |                   ~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/char-as-str-single.rs:11:19
+   |
+LL |     let _: char = "'";
+   |            ----   ^^^ expected `char`, found `&str`
+   |            |
+   |            expected due to this
+   |
+help: if you meant to write a `char` literal, use single quotes
+   |
+LL |     let _: char = '\'';
+   |                   ~~~~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/inference/deref-suggestion.rs b/tests/ui/inference/deref-suggestion.rs
new file mode 100644
index 00000000000..0d8e7289dc8
--- /dev/null
+++ b/tests/ui/inference/deref-suggestion.rs
@@ -0,0 +1,75 @@
+macro_rules! borrow {
+    ($x:expr) => { &$x }
+}
+
+fn foo(_: String) {}
+
+fn foo2(s: &String) {
+    foo(s);
+    //~^ ERROR mismatched types
+}
+
+fn foo3(_: u32) {}
+fn foo4(u: &u32) {
+    foo3(u);
+    //~^ ERROR mismatched types
+}
+
+struct S<'a> {
+    u: &'a u32,
+}
+
+struct R {
+    i: u32,
+}
+
+fn main() {
+    let s = String::new();
+    let r_s = &s;
+    foo2(r_s);
+    foo(&"aaa".to_owned());
+    //~^ ERROR mismatched types
+    foo(&mut "aaa".to_owned());
+    //~^ ERROR mismatched types
+    foo3(borrow!(0));
+    //~^ ERROR mismatched types
+    foo4(&0);
+    assert_eq!(3i32, &3i32);
+    //~^ ERROR mismatched types
+    let u = 3;
+    let s = S { u };
+    //~^ ERROR mismatched types
+    let s = S { u: u };
+    //~^ ERROR mismatched types
+    let i = &4;
+    let r = R { i };
+    //~^ ERROR mismatched types
+    let r = R { i: i };
+    //~^ ERROR mismatched types
+
+
+    let a = &1;
+    let b = &2;
+    let val: i32 = if true {
+        a + 1
+    } else {
+        b
+        //~^ ERROR mismatched types
+    };
+    let val: i32 = if true {
+        let _ = 2;
+        a + 1
+    } else {
+        let _ = 2;
+        b
+        //~^ ERROR mismatched types
+    };
+    let val = if true {
+        *a
+    } else if true {
+    //~^ ERROR incompatible types
+        b
+    } else {
+        &0
+    };
+}
diff --git a/tests/ui/inference/deref-suggestion.stderr b/tests/ui/inference/deref-suggestion.stderr
new file mode 100644
index 00000000000..3db67cdb537
--- /dev/null
+++ b/tests/ui/inference/deref-suggestion.stderr
@@ -0,0 +1,180 @@
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:8:9
+   |
+LL |     foo(s);
+   |     --- ^- help: try using a conversion method: `.to_string()`
+   |     |   |
+   |     |   expected struct `String`, found `&String`
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/deref-suggestion.rs:5:4
+   |
+LL | fn foo(_: String) {}
+   |    ^^^ ---------
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:14:10
+   |
+LL |     foo3(u);
+   |     ---- ^ expected `u32`, found `&u32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/deref-suggestion.rs:12:4
+   |
+LL | fn foo3(_: u32) {}
+   |    ^^^^ ------
+help: consider dereferencing the borrow
+   |
+LL |     foo3(*u);
+   |          +
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:30:9
+   |
+LL |     foo(&"aaa".to_owned());
+   |     --- ^^^^^^^^^^^^^^^^^ expected struct `String`, found `&String`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/deref-suggestion.rs:5:4
+   |
+LL | fn foo(_: String) {}
+   |    ^^^ ---------
+help: consider removing the borrow
+   |
+LL -     foo(&"aaa".to_owned());
+LL +     foo("aaa".to_owned());
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:32:9
+   |
+LL |     foo(&mut "aaa".to_owned());
+   |     --- ^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/deref-suggestion.rs:5:4
+   |
+LL | fn foo(_: String) {}
+   |    ^^^ ---------
+help: consider removing the borrow
+   |
+LL -     foo(&mut "aaa".to_owned());
+LL +     foo("aaa".to_owned());
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:34:10
+   |
+LL |     foo3(borrow!(0));
+   |     ---- ^^^^^^^^^^ expected `u32`, found `&{integer}`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/deref-suggestion.rs:12:4
+   |
+LL | fn foo3(_: u32) {}
+   |    ^^^^ ------
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:37:5
+   |
+LL |     assert_eq!(3i32, &3i32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     expected `i32`, found `&i32`
+   |     expected because this is `i32`
+   |
+   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:40:17
+   |
+LL |     let s = S { u };
+   |                 ^
+   |                 |
+   |                 expected `&u32`, found integer
+   |                 help: consider borrowing here: `u: &u`
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:42:20
+   |
+LL |     let s = S { u: u };
+   |                    ^
+   |                    |
+   |                    expected `&u32`, found integer
+   |                    help: consider borrowing here: `&u`
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:45:17
+   |
+LL |     let r = R { i };
+   |                 ^ expected `u32`, found `&{integer}`
+   |
+help: consider dereferencing the borrow
+   |
+LL |     let r = R { i: *i };
+   |                 ++++
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:47:20
+   |
+LL |     let r = R { i: i };
+   |                    ^ expected `u32`, found `&{integer}`
+   |
+help: consider dereferencing the borrow
+   |
+LL |     let r = R { i: *i };
+   |                    +
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:56:9
+   |
+LL |         b
+   |         ^ expected `i32`, found `&{integer}`
+   |
+help: consider dereferencing the borrow
+   |
+LL |         *b
+   |         +
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:64:9
+   |
+LL |         b
+   |         ^ expected `i32`, found `&{integer}`
+   |
+help: consider dereferencing the borrow
+   |
+LL |         *b
+   |         +
+
+error[E0308]: `if` and `else` have incompatible types
+  --> $DIR/deref-suggestion.rs:69:12
+   |
+LL |        let val = if true {
+   |  ________________-
+LL | |          *a
+   | |          -- expected because of this
+LL | |      } else if true {
+   | | ____________^
+LL | ||
+LL | ||         b
+LL | ||     } else {
+LL | ||         &0
+LL | ||     };
+   | ||     ^
+   | ||_____|
+   |  |_____`if` and `else` have incompatible types
+   |        expected `i32`, found `&{integer}`
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/inference/erase-type-params-in-label.rs b/tests/ui/inference/erase-type-params-in-label.rs
new file mode 100644
index 00000000000..1fea2da92da
--- /dev/null
+++ b/tests/ui/inference/erase-type-params-in-label.rs
@@ -0,0 +1,27 @@
+fn main() {
+    let foo = foo(1, ""); //~ ERROR E0283
+}
+fn baz() {
+    let bar = bar(1, ""); //~ ERROR E0283
+}
+
+struct Bar<T, K, N: Default> {
+    t: T,
+    k: K,
+    n: N,
+}
+
+fn bar<T, K, Z: Default>(t: T, k: K) -> Bar<T, K, Z> {
+    Bar { t, k, n: Default::default() }
+}
+
+struct Foo<T, K, N: Default, M: Default> {
+    t: T,
+    k: K,
+    n: N,
+    m: M,
+}
+
+fn foo<T, K, W: Default, Z: Default>(t: T, k: K) -> Foo<T, K, W, Z> {
+    Foo { t, k, n: Default::default(), m: Default::default() }
+}
diff --git a/tests/ui/inference/erase-type-params-in-label.stderr b/tests/ui/inference/erase-type-params-in-label.stderr
new file mode 100644
index 00000000000..9be18286480
--- /dev/null
+++ b/tests/ui/inference/erase-type-params-in-label.stderr
@@ -0,0 +1,37 @@
+error[E0283]: type annotations needed for `Foo<i32, &str, W, Z>`
+  --> $DIR/erase-type-params-in-label.rs:2:9
+   |
+LL |     let foo = foo(1, "");
+   |         ^^^   --- type must be known at this point
+   |
+   = note: cannot satisfy `_: Default`
+note: required by a bound in `foo`
+  --> $DIR/erase-type-params-in-label.rs:25:17
+   |
+LL | fn foo<T, K, W: Default, Z: Default>(t: T, k: K) -> Foo<T, K, W, Z> {
+   |                 ^^^^^^^ required by this bound in `foo`
+help: consider giving `foo` an explicit type, where the type for type parameter `W` is specified
+   |
+LL |     let foo: Foo<i32, &str, W, Z> = foo(1, "");
+   |            ++++++++++++++++++++++
+
+error[E0283]: type annotations needed for `Bar<i32, &str, Z>`
+  --> $DIR/erase-type-params-in-label.rs:5:9
+   |
+LL |     let bar = bar(1, "");
+   |         ^^^   --- type must be known at this point
+   |
+   = note: cannot satisfy `_: Default`
+note: required by a bound in `bar`
+  --> $DIR/erase-type-params-in-label.rs:14:17
+   |
+LL | fn bar<T, K, Z: Default>(t: T, k: K) -> Bar<T, K, Z> {
+   |                 ^^^^^^^ required by this bound in `bar`
+help: consider giving `bar` an explicit type, where the type for type parameter `Z` is specified
+   |
+LL |     let bar: Bar<i32, &str, Z> = bar(1, "");
+   |            +++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/inference/infer-binary-operand-behind-reference.rs b/tests/ui/inference/infer-binary-operand-behind-reference.rs
new file mode 100644
index 00000000000..0c0a3171ee9
--- /dev/null
+++ b/tests/ui/inference/infer-binary-operand-behind-reference.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+fn main() {
+    // Test that we can infer the type of binary operands when
+    // references are involved, on various types and operators.
+    let _: u8 = 0 + 0;
+    let _: u8 = 0 + &0;
+    let _: u8 = &0 + 0;
+    let _: u8 = &0 + &0;
+
+    let _: f32 = 0.0 + 0.0;
+    let _: f32 = 0.0 + &0.0;
+    let _: f32 = &0.0 + 0.0;
+    let _: f32 = &0.0 + &0.0;
+
+    let _: u8 = 0 << 0;
+    let _: u8 = 0 << &0;
+    let _: u8 = &0 << 0;
+    let _: u8 = &0 << &0;
+
+    // Test type inference when variable types are indirectly inferred.
+    let a = 22;
+    let _: usize = a + &44;
+
+    // When we have no expected type, the types of the operands is the default type.
+    let _ = 0 + 0;
+    let _ = 0 + &0;
+    let _ = &0 + 0;
+    let _ = &0 + &0;
+}
diff --git a/tests/ui/inference/inference-variable-behind-raw-pointer.rs b/tests/ui/inference/inference-variable-behind-raw-pointer.rs
new file mode 100644
index 00000000000..6662e46b1c7
--- /dev/null
+++ b/tests/ui/inference/inference-variable-behind-raw-pointer.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+// tests that the following code compiles, but produces a future-compatibility warning
+
+fn main() {
+    let data = std::ptr::null();
+    let _ = &data as *const *const ();
+    if data.is_null() {}
+    //~^ WARNING type annotations needed
+    //~| WARNING this is accepted in the current edition
+}
diff --git a/tests/ui/inference/inference-variable-behind-raw-pointer.stderr b/tests/ui/inference/inference-variable-behind-raw-pointer.stderr
new file mode 100644
index 00000000000..3dea09e7f52
--- /dev/null
+++ b/tests/ui/inference/inference-variable-behind-raw-pointer.stderr
@@ -0,0 +1,12 @@
+warning: type annotations needed
+  --> $DIR/inference-variable-behind-raw-pointer.rs:8:13
+   |
+LL |     if data.is_null() {}
+   |             ^^^^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+   = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
+   = note: `#[warn(tyvar_behind_raw_pointer)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/inference/inference_unstable.rs b/tests/ui/inference/inference_unstable.rs
new file mode 100644
index 00000000000..daf0cf042c4
--- /dev/null
+++ b/tests/ui/inference/inference_unstable.rs
@@ -0,0 +1,31 @@
+// Ensures #[unstable] functions without opting in the corresponding #![feature]
+// will not break inference.
+
+// aux-build:inference_unstable_iterator.rs
+// aux-build:inference_unstable_itertools.rs
+// run-pass
+
+extern crate inference_unstable_iterator;
+extern crate inference_unstable_itertools;
+
+#[allow(unused_imports)]
+use inference_unstable_iterator::IpuIterator;
+use inference_unstable_itertools::IpuItertools;
+
+fn main() {
+    assert_eq!('x'.ipu_flatten(), 1);
+//~^ WARN an associated function with this name may be added to the standard library in the future
+//~| WARN once this associated item is added to the standard library, the ambiguity may cause an
+    assert_eq!('x'.ipu_by_value_vs_by_ref(), 1);
+//~^ WARN an associated function with this name may be added to the standard library in the future
+//~| WARN once this associated item is added to the standard library, the ambiguity may cause an
+    assert_eq!('x'.ipu_by_ref_vs_by_ref_mut(), 1);
+//~^ WARN an associated function with this name may be added to the standard library in the future
+//~| WARN once this associated item is added to the standard library, the ambiguity may cause an
+    assert_eq!((&mut 'x' as *mut char).ipu_by_mut_ptr_vs_by_const_ptr(), 1);
+//~^ WARN an associated function with this name may be added to the standard library in the future
+//~| WARN once this associated item is added to the standard library, the ambiguity may cause an
+    assert_eq!(char::C, 1);
+//~^ WARN an associated constant with this name may be added to the standard library in the future
+//~| WARN once this associated item is added to the standard library, the ambiguity may cause an
+}
diff --git a/tests/ui/inference/inference_unstable.stderr b/tests/ui/inference/inference_unstable.stderr
new file mode 100644
index 00000000000..ecbf2641bec
--- /dev/null
+++ b/tests/ui/inference/inference_unstable.stderr
@@ -0,0 +1,57 @@
+warning: an associated function with this name may be added to the standard library in the future
+  --> $DIR/inference_unstable.rs:16:20
+   |
+LL |     assert_eq!('x'.ipu_flatten(), 1);
+   |                    ^^^^^^^^^^^
+   |
+   = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior!
+   = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919>
+   = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_flatten(...)` to keep using the current method
+   = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_flatten`
+   = note: `#[warn(unstable_name_collisions)]` on by default
+
+warning: an associated function with this name may be added to the standard library in the future
+  --> $DIR/inference_unstable.rs:19:20
+   |
+LL |     assert_eq!('x'.ipu_by_value_vs_by_ref(), 1);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior!
+   = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919>
+   = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_by_value_vs_by_ref(...)` to keep using the current method
+   = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_by_value_vs_by_ref`
+
+warning: an associated function with this name may be added to the standard library in the future
+  --> $DIR/inference_unstable.rs:22:20
+   |
+LL |     assert_eq!('x'.ipu_by_ref_vs_by_ref_mut(), 1);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior!
+   = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919>
+   = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_by_ref_vs_by_ref_mut(...)` to keep using the current method
+   = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_by_ref_vs_by_ref_mut`
+
+warning: an associated function with this name may be added to the standard library in the future
+  --> $DIR/inference_unstable.rs:25:40
+   |
+LL |     assert_eq!((&mut 'x' as *mut char).ipu_by_mut_ptr_vs_by_const_ptr(), 1);
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior!
+   = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919>
+   = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_by_mut_ptr_vs_by_const_ptr(...)` to keep using the current method
+   = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_by_mut_ptr_vs_by_const_ptr`
+
+warning: an associated constant with this name may be added to the standard library in the future
+  --> $DIR/inference_unstable.rs:28:16
+   |
+LL |     assert_eq!(char::C, 1);
+   |                ^^^^^^^ help: use the fully qualified path to the associated const: `<char as IpuItertools>::C`
+   |
+   = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior!
+   = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919>
+   = help: add `#![feature(assoc_const_ipu_iter)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::C`
+
+warning: 5 warnings emitted
+
diff --git a/tests/ui/inference/inference_unstable_featured.rs b/tests/ui/inference/inference_unstable_featured.rs
new file mode 100644
index 00000000000..792b29aaadc
--- /dev/null
+++ b/tests/ui/inference/inference_unstable_featured.rs
@@ -0,0 +1,17 @@
+// There should be E0034 "multiple applicable items in scope" if we opt-in for
+// the feature.
+
+// aux-build:inference_unstable_iterator.rs
+// aux-build:inference_unstable_itertools.rs
+
+#![feature(ipu_flatten)]
+
+extern crate inference_unstable_iterator;
+extern crate inference_unstable_itertools;
+
+use inference_unstable_iterator::IpuIterator;
+use inference_unstable_itertools::IpuItertools;
+
+fn main() {
+    assert_eq!('x'.ipu_flatten(), 0);   //~ ERROR E0034
+}
diff --git a/tests/ui/inference/inference_unstable_featured.stderr b/tests/ui/inference/inference_unstable_featured.stderr
new file mode 100644
index 00000000000..4ddede29c85
--- /dev/null
+++ b/tests/ui/inference/inference_unstable_featured.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/inference_unstable_featured.rs:16:20
+   |
+LL |     assert_eq!('x'.ipu_flatten(), 0);
+   |                    ^^^^^^^^^^^ multiple `ipu_flatten` found
+   |
+   = note: candidate #1 is defined in an impl of the trait `IpuIterator` for the type `char`
+   = note: candidate #2 is defined in an impl of the trait `IpuItertools` for the type `char`
+help: disambiguate the associated function for candidate #1
+   |
+LL |     assert_eq!(IpuIterator::ipu_flatten(&'x'), 0);
+   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: disambiguate the associated function for candidate #2
+   |
+LL |     assert_eq!(IpuItertools::ipu_flatten(&'x'), 0);
+   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/inference/inference_unstable_forced.rs b/tests/ui/inference/inference_unstable_forced.rs
new file mode 100644
index 00000000000..649b3ed2a6f
--- /dev/null
+++ b/tests/ui/inference/inference_unstable_forced.rs
@@ -0,0 +1,12 @@
+// If the unstable API is the only possible solution,
+// still emit E0658 "use of unstable library feature".
+
+// aux-build:inference_unstable_iterator.rs
+
+extern crate inference_unstable_iterator;
+
+use inference_unstable_iterator::IpuIterator;
+
+fn main() {
+    assert_eq!('x'.ipu_flatten(), 0);   //~ ERROR E0658
+}
diff --git a/tests/ui/inference/inference_unstable_forced.stderr b/tests/ui/inference/inference_unstable_forced.stderr
new file mode 100644
index 00000000000..a1c4cd851cb
--- /dev/null
+++ b/tests/ui/inference/inference_unstable_forced.stderr
@@ -0,0 +1,12 @@
+error[E0658]: use of unstable library feature 'ipu_flatten'
+  --> $DIR/inference_unstable_forced.rs:11:20
+   |
+LL |     assert_eq!('x'.ipu_flatten(), 0);
+   |                    ^^^^^^^^^^^
+   |
+   = note: see issue #99999 <https://github.com/rust-lang/rust/issues/99999> for more information
+   = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/inference/issue-103587.rs b/tests/ui/inference/issue-103587.rs
new file mode 100644
index 00000000000..11536f9f4cc
--- /dev/null
+++ b/tests/ui/inference/issue-103587.rs
@@ -0,0 +1,12 @@
+fn main() {
+    let x = Some(123);
+
+    if let Some(_) == x {}
+    //~^ ERROR expected `=`, found `==`
+
+    if Some(_) = x {}
+    //~^ ERROR mismatched types
+
+    if None = x { }
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/inference/issue-103587.stderr b/tests/ui/inference/issue-103587.stderr
new file mode 100644
index 00000000000..b373fbfbb94
--- /dev/null
+++ b/tests/ui/inference/issue-103587.stderr
@@ -0,0 +1,40 @@
+error: expected `=`, found `==`
+  --> $DIR/issue-103587.rs:4:20
+   |
+LL |     if let Some(_) == x {}
+   |                    ^^
+   |
+help: consider using `=` here
+   |
+LL |     if let Some(_) = x {}
+   |                    ~
+
+error[E0308]: mismatched types
+  --> $DIR/issue-103587.rs:7:8
+   |
+LL |     if Some(_) = x {}
+   |        ^^^^^^^^^^^ expected `bool`, found `()`
+   |
+help: consider adding `let`
+   |
+LL |     if let Some(_) = x {}
+   |        +++
+
+error[E0308]: mismatched types
+  --> $DIR/issue-103587.rs:10:8
+   |
+LL |     if None = x { }
+   |        ^^^^^^^^ expected `bool`, found `()`
+   |
+help: you might have meant to use pattern matching
+   |
+LL |     if let None = x { }
+   |        +++
+help: you might have meant to compare for equality
+   |
+LL |     if None == x { }
+   |              +
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/inference/issue-104649.rs b/tests/ui/inference/issue-104649.rs
new file mode 100644
index 00000000000..4637b884d44
--- /dev/null
+++ b/tests/ui/inference/issue-104649.rs
@@ -0,0 +1,32 @@
+type Result<T, E = Error> = ::std::result::Result<T, E>;
+struct Error;
+
+trait ForEach {
+    type Input;
+    fn for_each<F, U>(self, f: F)
+    where
+        F: FnOnce(Self::Input) -> U;
+}
+
+impl<T> ForEach for A<T> {
+    type Input = T;
+    fn for_each<F, U>(self, f: F)
+    where
+        F: FnOnce(Self::Input) -> U,
+    {
+        todo!()
+    }
+}
+
+struct A<T>(T);
+
+fn main() {
+    let a = A(Result::Ok(Result::Ok(()))); //~ ERROR type annotations needed
+    a.for_each(|a: Result<_>| {
+        let f = || match a {
+            Ok(Ok(a)) => {}
+            Ok(Err(a)) => {}
+            Err(a) => {}
+        };
+    });
+}
diff --git a/tests/ui/inference/issue-104649.stderr b/tests/ui/inference/issue-104649.stderr
new file mode 100644
index 00000000000..4962b21f9fd
--- /dev/null
+++ b/tests/ui/inference/issue-104649.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed for `A<std::result::Result<std::result::Result<(), E>, Error>>`
+  --> $DIR/issue-104649.rs:24:9
+   |
+LL |     let a = A(Result::Ok(Result::Ok(())));
+   |         ^
+   |
+help: consider giving `a` an explicit type, where the type for type parameter `E` is specified
+   |
+LL |     let a: A<std::result::Result<std::result::Result<(), E>, Error>> = A(Result::Ok(Result::Ok(())));
+   |          +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/issue-28935.rs b/tests/ui/inference/issue-28935.rs
new file mode 100644
index 00000000000..872822dbd0f
--- /dev/null
+++ b/tests/ui/inference/issue-28935.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+use std::cell::RefCell;
+
+pub fn f(v: Vec<RefCell<u8>>) {
+    let _t = &mut *v[0].borrow_mut();
+}
+
+fn main() {}
diff --git a/tests/ui/inference/issue-36053.rs b/tests/ui/inference/issue-36053.rs
new file mode 100644
index 00000000000..5c6d0780416
--- /dev/null
+++ b/tests/ui/inference/issue-36053.rs
@@ -0,0 +1,22 @@
+// run-pass
+// Regression test for #36053. ICE was caused due to obligations being
+// added to a special, dedicated fulfillment cx during a
+// probe. Problem seems to be related to the particular definition of
+// `FusedIterator` in std but I was not able to isolate that into an
+// external crate.
+
+use std::iter::FusedIterator;
+
+struct Thing<'a>(#[allow(unused_tuple_struct_fields)] &'a str);
+impl<'a> Iterator for Thing<'a> {
+    type Item = &'a str;
+    fn next(&mut self) -> Option<&'a str> {
+        None
+    }
+}
+
+impl<'a> FusedIterator for Thing<'a> {}
+
+fn main() {
+    Thing("test").fuse().filter(|_| true).count();
+}
diff --git a/tests/ui/inference/issue-70703.rs b/tests/ui/inference/issue-70703.rs
new file mode 100644
index 00000000000..d90498e96ea
--- /dev/null
+++ b/tests/ui/inference/issue-70703.rs
@@ -0,0 +1,26 @@
+// check-pass
+
+trait Factory {
+    type Product;
+}
+
+impl Factory for () {
+    type Product = ();
+}
+
+trait ProductConsumer<P> {
+    fn consume(self, product: P);
+}
+
+impl<P> ProductConsumer<P> for () {
+    fn consume(self, _: P) {}
+}
+
+fn make_product_consumer<F: Factory>(_: F) -> impl ProductConsumer<F::Product> {
+    ()
+}
+
+fn main() {
+    let consumer = make_product_consumer(());
+    consumer.consume(());
+}
diff --git a/tests/ui/inference/issue-71309.rs b/tests/ui/inference/issue-71309.rs
new file mode 100644
index 00000000000..c31107d8fed
--- /dev/null
+++ b/tests/ui/inference/issue-71309.rs
@@ -0,0 +1,7 @@
+fn foo(x: Result<i32, ()>) -> Result<(), ()> {
+    let y: u32 = x?;
+    //~^ ERROR: `?` operator has incompatible types
+    Ok(())
+}
+
+fn main() {}
diff --git a/tests/ui/inference/issue-71309.stderr b/tests/ui/inference/issue-71309.stderr
new file mode 100644
index 00000000000..af8714f1c80
--- /dev/null
+++ b/tests/ui/inference/issue-71309.stderr
@@ -0,0 +1,15 @@
+error[E0308]: `?` operator has incompatible types
+  --> $DIR/issue-71309.rs:2:18
+   |
+LL |     let y: u32 = x?;
+   |                  ^^ expected `u32`, found `i32`
+   |
+   = note: `?` operator cannot convert from `i32` to `u32`
+help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
+   |
+LL |     let y: u32 = x?.try_into().unwrap();
+   |                    ++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/inference/issue-71732.rs b/tests/ui/inference/issue-71732.rs
new file mode 100644
index 00000000000..8a9d2b235f0
--- /dev/null
+++ b/tests/ui/inference/issue-71732.rs
@@ -0,0 +1,24 @@
+// Regression test for #71732, it used to emit incorrect diagnostics, like:
+// error[E0283]: type annotations needed
+//  --> src/main.rs:5:10
+//   |
+// 5 |         .get(&"key".into())
+//   |          ^^^ cannot infer type for struct `String`
+//   |
+//   = note: cannot satisfy `String: Borrow<_>`
+// help: consider specifying the type argument in the method call
+//   |
+// 5 |         .get::<Q>(&"key".into())
+//   |
+
+use std::collections::hash_map::HashMap;
+
+fn foo(parameters: &HashMap<String, String>) -> bool {
+    parameters
+        .get(&"key".into())
+        //~^ ERROR type annotations needed
+        .and_then(|found: &String| Some(false))
+        .unwrap_or(false)
+}
+
+fn main() {}
diff --git a/tests/ui/inference/issue-71732.stderr b/tests/ui/inference/issue-71732.stderr
new file mode 100644
index 00000000000..01b37f2acaa
--- /dev/null
+++ b/tests/ui/inference/issue-71732.stderr
@@ -0,0 +1,22 @@
+error[E0283]: type annotations needed
+  --> $DIR/issue-71732.rs:18:10
+   |
+LL |         .get(&"key".into())
+   |          ^^^ ------------- type must be known at this point
+   |          |
+   |          cannot infer type of the type parameter `Q` declared on the associated function `get`
+   |
+   = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`:
+           - impl Borrow<str> for String;
+           - impl<T> Borrow<T> for T
+             where T: ?Sized;
+note: required by a bound in `HashMap::<K, V, S>::get`
+  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
+help: consider specifying the generic argument
+   |
+LL |         .get::<Q>(&"key".into())
+   |             +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/inference/issue-72616.rs b/tests/ui/inference/issue-72616.rs
new file mode 100644
index 00000000000..69ade1a7515
--- /dev/null
+++ b/tests/ui/inference/issue-72616.rs
@@ -0,0 +1,32 @@
+// ignore-wasm32 FIXME: ignoring wasm as it suggests slightly different impls
+
+// Regression test for #72616, it used to emit incorrect diagnostics, like:
+// error[E0283]: type annotations needed for `String`
+//  --> src/main.rs:8:30
+//   |
+// 5 |         let _: String = "".to_owned().try_into().unwrap();
+//   |             - consider giving this pattern a type
+// ...
+// 8 |         if String::from("a") == "a".try_into().unwrap() {}
+//   |                              ^^ cannot infer type for struct `String`
+//   |
+//   = note: cannot satisfy `String: PartialEq<_>`
+
+use std::convert::TryInto;
+
+pub fn main() {
+    {
+        let _: String = "".to_owned().try_into().unwrap();
+    }
+    {
+        if String::from("a") == "a".try_into().unwrap() {}
+        //~^ ERROR type annotations needed
+        //~| ERROR type annotations needed
+    }
+    {
+        let _: String = match "_".try_into() {
+            Ok(a) => a,
+            Err(_) => "".into(),
+        };
+    }
+}
diff --git a/tests/ui/inference/issue-72616.stderr b/tests/ui/inference/issue-72616.stderr
new file mode 100644
index 00000000000..6ee0626cab8
--- /dev/null
+++ b/tests/ui/inference/issue-72616.stderr
@@ -0,0 +1,37 @@
+error[E0283]: type annotations needed
+  --> $DIR/issue-72616.rs:22:37
+   |
+LL |         if String::from("a") == "a".try_into().unwrap() {}
+   |                              --     ^^^^^^^^
+   |                              |
+   |                              type must be known at this point
+   |
+   = note: multiple `impl`s satisfying `String: PartialEq<_>` found in the `alloc` crate:
+           - impl PartialEq for String;
+           - impl<'a, 'b> PartialEq<&'a str> for String;
+           - impl<'a, 'b> PartialEq<Cow<'a, str>> for String;
+           - impl<'a, 'b> PartialEq<str> for String;
+help: try using a fully qualified path to specify the expected types
+   |
+LL |         if String::from("a") == <&str as TryInto<T>>::try_into("a").unwrap() {}
+   |                                 +++++++++++++++++++++++++++++++   ~
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72616.rs:22:37
+   |
+LL |         if String::from("a") == "a".try_into().unwrap() {}
+   |                                     ^^^^^^^^
+   |
+   = note: multiple `impl`s satisfying `_: TryFrom<&str>` found in the following crates: `core`, `std`:
+           - impl<> TryFrom<&str> for std::sys_common::net::LookupHost;
+           - impl<T, U> TryFrom<U> for T
+             where U: Into<T>;
+   = note: required for `&str` to implement `TryInto<_>`
+help: try using a fully qualified path to specify the expected types
+   |
+LL |         if String::from("a") == <&str as TryInto<T>>::try_into("a").unwrap() {}
+   |                                 +++++++++++++++++++++++++++++++   ~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/inference/issue-72690.rs b/tests/ui/inference/issue-72690.rs
new file mode 100644
index 00000000000..8c0a0f51a21
--- /dev/null
+++ b/tests/ui/inference/issue-72690.rs
@@ -0,0 +1,70 @@
+fn no_err() {
+    |x: String| x;
+    let _ = String::from("x");
+}
+
+fn err() {
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
+}
+
+fn arg_pat_closure_err() {
+    |x| String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~| ERROR type annotations needed
+}
+
+fn local_pat_closure_err() {
+    let _ = "x".as_ref(); //~ ERROR type annotations needed
+}
+
+fn err_first_arg_pat() {
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
+    |x: String| x;
+}
+
+fn err_second_arg_pat() {
+    |x: String| x;
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
+}
+
+fn err_mid_arg_pat() {
+    |x: String| x;
+    |x: String| x;
+    |x: String| x;
+    |x: String| x;
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
+    |x: String| x;
+    |x: String| x;
+    |x: String| x;
+    |x: String| x;
+}
+
+fn err_first_local_pat() {
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
+    let _ = String::from("x");
+}
+
+fn err_second_local_pat() {
+    let _ = String::from("x");
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
+}
+
+fn err_mid_local_pat() {
+    let _ = String::from("x");
+    let _ = String::from("x");
+    let _ = String::from("x");
+    let _ = String::from("x");
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
+    let _ = String::from("x");
+    let _ = String::from("x");
+    let _ = String::from("x");
+    let _ = String::from("x");
+}
+
+fn main() {}
diff --git a/tests/ui/inference/issue-72690.stderr b/tests/ui/inference/issue-72690.stderr
new file mode 100644
index 00000000000..8eda71ec09b
--- /dev/null
+++ b/tests/ui/inference/issue-72690.stderr
@@ -0,0 +1,229 @@
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:7:5
+   |
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
+   |
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:7:22
+   |
+LL |     String::from("x".as_ref());
+   |                      ^^^^^^
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+help: try using a fully qualified path to specify the expected types
+   |
+LL |     String::from(<str as AsRef<T>>::as_ref("x"));
+   |                  ++++++++++++++++++++++++++   ~
+
+error[E0282]: type annotations needed
+  --> $DIR/issue-72690.rs:12:6
+   |
+LL |     |x| String::from("x".as_ref());
+   |      ^
+   |
+help: consider giving this closure parameter an explicit type
+   |
+LL |     |x: /* Type */| String::from("x".as_ref());
+   |       ++++++++++++
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:12:26
+   |
+LL |     |x| String::from("x".as_ref());
+   |                          ^^^^^^
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+help: try using a fully qualified path to specify the expected types
+   |
+LL |     |x| String::from(<str as AsRef<T>>::as_ref("x"));
+   |                      ++++++++++++++++++++++++++   ~
+
+error[E0283]: type annotations needed for `&T`
+  --> $DIR/issue-72690.rs:17:9
+   |
+LL |     let _ = "x".as_ref();
+   |         ^       ------ type must be known at this point
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+help: consider giving this pattern a type, where the type for type parameter `T` is specified
+   |
+LL |     let _: &T = "x".as_ref();
+   |          ++++
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:21:5
+   |
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
+   |
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:21:22
+   |
+LL |     String::from("x".as_ref());
+   |                      ^^^^^^
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+help: try using a fully qualified path to specify the expected types
+   |
+LL |     String::from(<str as AsRef<T>>::as_ref("x"));
+   |                  ++++++++++++++++++++++++++   ~
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:28:5
+   |
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
+   |
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:28:22
+   |
+LL |     String::from("x".as_ref());
+   |                      ^^^^^^
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+help: try using a fully qualified path to specify the expected types
+   |
+LL |     String::from(<str as AsRef<T>>::as_ref("x"));
+   |                  ++++++++++++++++++++++++++   ~
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:37:5
+   |
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
+   |
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:37:22
+   |
+LL |     String::from("x".as_ref());
+   |                      ^^^^^^
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+help: try using a fully qualified path to specify the expected types
+   |
+LL |     String::from(<str as AsRef<T>>::as_ref("x"));
+   |                  ++++++++++++++++++++++++++   ~
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:46:5
+   |
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
+   |
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:46:22
+   |
+LL |     String::from("x".as_ref());
+   |                      ^^^^^^
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+help: try using a fully qualified path to specify the expected types
+   |
+LL |     String::from(<str as AsRef<T>>::as_ref("x"));
+   |                  ++++++++++++++++++++++++++   ~
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:53:5
+   |
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
+   |
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:53:22
+   |
+LL |     String::from("x".as_ref());
+   |                      ^^^^^^
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+help: try using a fully qualified path to specify the expected types
+   |
+LL |     String::from(<str as AsRef<T>>::as_ref("x"));
+   |                  ++++++++++++++++++++++++++   ~
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:62:5
+   |
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
+   |
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:62:22
+   |
+LL |     String::from("x".as_ref());
+   |                      ^^^^^^
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+help: try using a fully qualified path to specify the expected types
+   |
+LL |     String::from(<str as AsRef<T>>::as_ref("x"));
+   |                  ++++++++++++++++++++++++++   ~
+
+error: aborting due to 17 previous errors
+
+Some errors have detailed explanations: E0282, E0283.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/issue-80816.rs b/tests/ui/inference/issue-80816.rs
new file mode 100644
index 00000000000..ead320a4fe4
--- /dev/null
+++ b/tests/ui/inference/issue-80816.rs
@@ -0,0 +1,54 @@
+#![allow(unreachable_code)]
+
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::sync::Arc;
+
+pub struct Guard<T> {
+    _phantom: PhantomData<T>,
+}
+impl<T> Deref for Guard<T> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        unimplemented!()
+    }
+}
+
+pub struct DirectDeref<T>(T);
+impl<T> Deref for DirectDeref<Arc<T>> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        unimplemented!()
+    }
+}
+
+pub trait Access<T> {
+    type Guard: Deref<Target = T>;
+    fn load(&self) -> Self::Guard {
+        unimplemented!()
+    }
+}
+impl<T, A: Access<T>, P: Deref<Target = A>> Access<T> for P {
+    //~^ NOTE: required for `Arc<ArcSwapAny<Arc<usize>>>` to implement `Access<_>`
+    type Guard = A::Guard;
+}
+impl<T> Access<T> for ArcSwapAny<T> {
+    //~^ NOTE: multiple `impl`s satisfying `ArcSwapAny<Arc<usize>>: Access<_>` found
+    type Guard = Guard<T>;
+}
+impl<T> Access<T> for ArcSwapAny<Arc<T>> {
+    type Guard = DirectDeref<Arc<T>>;
+}
+
+pub struct ArcSwapAny<T> {
+    _phantom_arc: PhantomData<T>,
+}
+
+pub fn foo() {
+    let s: Arc<ArcSwapAny<Arc<usize>>> = unimplemented!();
+    let guard: Guard<Arc<usize>> = s.load();
+    //~^ ERROR: type annotations needed
+    //~| HELP: try using a fully qualified path to specify the expected types
+}
+
+fn main() {}
diff --git a/tests/ui/inference/issue-80816.stderr b/tests/ui/inference/issue-80816.stderr
new file mode 100644
index 00000000000..bd833340df4
--- /dev/null
+++ b/tests/ui/inference/issue-80816.stderr
@@ -0,0 +1,27 @@
+error[E0283]: type annotations needed
+  --> $DIR/issue-80816.rs:49:38
+   |
+LL |     let guard: Guard<Arc<usize>> = s.load();
+   |                                      ^^^^
+   |
+note: multiple `impl`s satisfying `ArcSwapAny<Arc<usize>>: Access<_>` found
+  --> $DIR/issue-80816.rs:35:1
+   |
+LL | impl<T> Access<T> for ArcSwapAny<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl<T> Access<T> for ArcSwapAny<Arc<T>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required for `Arc<ArcSwapAny<Arc<usize>>>` to implement `Access<_>`
+  --> $DIR/issue-80816.rs:31:45
+   |
+LL | impl<T, A: Access<T>, P: Deref<Target = A>> Access<T> for P {
+   |                                             ^^^^^^^^^     ^
+help: try using a fully qualified path to specify the expected types
+   |
+LL |     let guard: Guard<Arc<usize>> = <Arc<ArcSwapAny<Arc<usize>>> as Access<T>>::load(&s);
+   |                                    ++++++++++++++++++++++++++++++++++++++++++++++++++ ~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/inference/issue-81522.rs b/tests/ui/inference/issue-81522.rs
new file mode 100644
index 00000000000..902f8fdde58
--- /dev/null
+++ b/tests/ui/inference/issue-81522.rs
@@ -0,0 +1,31 @@
+// Regression test for #81522.
+// Ensures that `#[allow(unstable_name_collisions)]` appended to things other than function
+// suppresses the corresponding diagnostics emitted from inside them.
+// But note that this attribute doesn't work for macro invocations if it is appended directly.
+
+// aux-build:inference_unstable_iterator.rs
+// aux-build:inference_unstable_itertools.rs
+// run-pass
+
+extern crate inference_unstable_iterator;
+extern crate inference_unstable_itertools;
+
+#[allow(unused_imports)]
+use inference_unstable_iterator::IpuIterator;
+use inference_unstable_itertools::IpuItertools;
+
+fn main() {
+    // expression statement
+    #[allow(unstable_name_collisions)]
+    'x'.ipu_flatten();
+
+    // let statement
+    #[allow(unstable_name_collisions)]
+    let _ = 'x'.ipu_flatten();
+
+    // block expression
+    #[allow(unstable_name_collisions)]
+    {
+        'x'.ipu_flatten();
+    }
+}
diff --git a/tests/ui/inference/issue-83606.rs b/tests/ui/inference/issue-83606.rs
new file mode 100644
index 00000000000..eaaef3463dd
--- /dev/null
+++ b/tests/ui/inference/issue-83606.rs
@@ -0,0 +1,10 @@
+// Regression test for #83606.
+
+fn foo<const N: usize>(_: impl std::fmt::Display) -> [usize; N] {
+    [0; N]
+}
+
+fn main() {
+    let _ = foo("foo");
+    //~^ ERROR: type annotations needed for `[usize; _]`
+}
diff --git a/tests/ui/inference/issue-83606.stderr b/tests/ui/inference/issue-83606.stderr
new file mode 100644
index 00000000000..f5c84f96064
--- /dev/null
+++ b/tests/ui/inference/issue-83606.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed for `[usize; _]`
+  --> $DIR/issue-83606.rs:8:9
+   |
+LL |     let _ = foo("foo");
+   |         ^
+   |
+help: consider giving this pattern a type, where the the value of const parameter `N` is specified
+   |
+LL |     let _: [usize; _] = foo("foo");
+   |          ++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/issue-86162-1.rs b/tests/ui/inference/issue-86162-1.rs
new file mode 100644
index 00000000000..5a547eb38d1
--- /dev/null
+++ b/tests/ui/inference/issue-86162-1.rs
@@ -0,0 +1,9 @@
+// Regression test of #86162.
+
+fn foo(x: impl Clone) {}
+fn gen<T>() -> T { todo!() }
+
+fn main() {
+    foo(gen()); //<- Do not suggest `foo::<impl Clone>()`!
+    //~^ ERROR: type annotations needed
+}
diff --git a/tests/ui/inference/issue-86162-1.stderr b/tests/ui/inference/issue-86162-1.stderr
new file mode 100644
index 00000000000..4f621b82dc5
--- /dev/null
+++ b/tests/ui/inference/issue-86162-1.stderr
@@ -0,0 +1,22 @@
+error[E0283]: type annotations needed
+  --> $DIR/issue-86162-1.rs:7:9
+   |
+LL |     foo(gen()); //<- Do not suggest `foo::<impl Clone>()`!
+   |     --- ^^^ cannot infer type of the type parameter `T` declared on the function `gen`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = note: cannot satisfy `_: Clone`
+note: required by a bound in `foo`
+  --> $DIR/issue-86162-1.rs:3:16
+   |
+LL | fn foo(x: impl Clone) {}
+   |                ^^^^^ required by this bound in `foo`
+help: consider specifying the generic argument
+   |
+LL |     foo(gen::<T>()); //<- Do not suggest `foo::<impl Clone>()`!
+   |            +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/inference/issue-86162-2.rs b/tests/ui/inference/issue-86162-2.rs
new file mode 100644
index 00000000000..b8c75dd7728
--- /dev/null
+++ b/tests/ui/inference/issue-86162-2.rs
@@ -0,0 +1,14 @@
+// Regression test of #86162.
+
+fn gen<T>() -> T { todo!() }
+
+struct Foo;
+
+impl Foo {
+    fn bar(x: impl Clone) {}
+}
+
+fn main() {
+    Foo::bar(gen()); //<- Do not suggest `Foo::bar::<impl Clone>()`!
+    //~^ ERROR: type annotations needed
+}
diff --git a/tests/ui/inference/issue-86162-2.stderr b/tests/ui/inference/issue-86162-2.stderr
new file mode 100644
index 00000000000..9aff2cec160
--- /dev/null
+++ b/tests/ui/inference/issue-86162-2.stderr
@@ -0,0 +1,22 @@
+error[E0283]: type annotations needed
+  --> $DIR/issue-86162-2.rs:12:14
+   |
+LL |     Foo::bar(gen()); //<- Do not suggest `Foo::bar::<impl Clone>()`!
+   |     -------- ^^^ cannot infer type of the type parameter `T` declared on the function `gen`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = note: cannot satisfy `_: Clone`
+note: required by a bound in `Foo::bar`
+  --> $DIR/issue-86162-2.rs:8:20
+   |
+LL |     fn bar(x: impl Clone) {}
+   |                    ^^^^^ required by this bound in `Foo::bar`
+help: consider specifying the generic argument
+   |
+LL |     Foo::bar(gen::<T>()); //<- Do not suggest `Foo::bar::<impl Clone>()`!
+   |                 +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/inference/lub-glb-with-unbound-infer-var.rs b/tests/ui/inference/lub-glb-with-unbound-infer-var.rs
new file mode 100644
index 00000000000..c9e117089f5
--- /dev/null
+++ b/tests/ui/inference/lub-glb-with-unbound-infer-var.rs
@@ -0,0 +1,15 @@
+// run-pass
+// Test for a specific corner case: when we compute the LUB of two fn
+// types and their parameters have unbound variables. In that case, we
+// wind up relating those two variables. This was causing an ICE in an
+// in-progress PR.
+
+fn main() {
+    let a_f: fn(_) = |_| ();
+    let b_f: fn(_) = |_| ();
+    let c_f = match 22 {
+        0 => a_f,
+        _ => b_f,
+    };
+    c_f(4);
+}
diff --git a/tests/ui/inference/need_type_info/channel.rs b/tests/ui/inference/need_type_info/channel.rs
new file mode 100644
index 00000000000..e2ba5a94171
--- /dev/null
+++ b/tests/ui/inference/need_type_info/channel.rs
@@ -0,0 +1,19 @@
+// Test that we suggest specifying the generic argument of `channel`
+// instead of the return type of that function, which is a lot more
+// complex.
+use std::sync::mpsc::channel;
+
+fn no_tuple() {
+    let _data =
+        channel(); //~ ERROR type annotations needed
+}
+
+fn tuple() {
+    let (_sender, _receiver) =
+        channel(); //~ ERROR type annotations needed
+}
+
+fn main() {
+    no_tuple();
+    tuple();
+}
diff --git a/tests/ui/inference/need_type_info/channel.stderr b/tests/ui/inference/need_type_info/channel.stderr
new file mode 100644
index 00000000000..e33ace0338d
--- /dev/null
+++ b/tests/ui/inference/need_type_info/channel.stderr
@@ -0,0 +1,25 @@
+error[E0282]: type annotations needed
+  --> $DIR/channel.rs:8:9
+   |
+LL |         channel();
+   |         ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel`
+   |
+help: consider specifying the generic argument
+   |
+LL |         channel::<T>();
+   |                +++++
+
+error[E0282]: type annotations needed
+  --> $DIR/channel.rs:13:9
+   |
+LL |         channel();
+   |         ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel`
+   |
+help: consider specifying the generic argument
+   |
+LL |         channel::<T>();
+   |                +++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/need_type_info/concrete-impl.rs b/tests/ui/inference/need_type_info/concrete-impl.rs
new file mode 100644
index 00000000000..72e0e74f323
--- /dev/null
+++ b/tests/ui/inference/need_type_info/concrete-impl.rs
@@ -0,0 +1,16 @@
+trait Ambiguous<A> {
+    fn method() {}
+}
+
+struct One;
+struct Two;
+struct Struct;
+
+impl Ambiguous<One> for Struct {}
+impl Ambiguous<Two> for Struct {}
+
+fn main() {
+    <Struct as Ambiguous<_>>::method();
+    //~^ ERROR type annotations needed
+    //~| ERROR type annotations needed
+}
diff --git a/tests/ui/inference/need_type_info/concrete-impl.stderr b/tests/ui/inference/need_type_info/concrete-impl.stderr
new file mode 100644
index 00000000000..aa32969950d
--- /dev/null
+++ b/tests/ui/inference/need_type_info/concrete-impl.stderr
@@ -0,0 +1,24 @@
+error[E0282]: type annotations needed
+  --> $DIR/concrete-impl.rs:13:5
+   |
+LL |     <Struct as Ambiguous<_>>::method();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous`
+
+error[E0283]: type annotations needed
+  --> $DIR/concrete-impl.rs:13:5
+   |
+LL |     <Struct as Ambiguous<_>>::method();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous`
+   |
+note: multiple `impl`s satisfying `Struct: Ambiguous<_>` found
+  --> $DIR/concrete-impl.rs:9:1
+   |
+LL | impl Ambiguous<One> for Struct {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl Ambiguous<Two> for Struct {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0282, E0283.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.rs b/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.rs
new file mode 100644
index 00000000000..3084f6eac67
--- /dev/null
+++ b/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.rs
@@ -0,0 +1,11 @@
+enum OhNo<T, U> {
+    A(T),
+    B(U),
+    C,
+}
+
+fn uwu() {
+    OhNo::C::<u32, _>; //~ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr b/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr
new file mode 100644
index 00000000000..2ad35ab039f
--- /dev/null
+++ b/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/do-not-suggest-generic-arguments-for-turbofish.rs:8:5
+   |
+LL |     OhNo::C::<u32, _>;
+   |     ^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the enum `OhNo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.rs b/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.rs
new file mode 100644
index 00000000000..42af9fa8d11
--- /dev/null
+++ b/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.rs
@@ -0,0 +1,21 @@
+trait Foo {
+    type Output;
+
+    fn baz() -> Self::Output;
+}
+
+fn needs_infer<T>() {}
+
+enum Bar {
+    Variant {}
+}
+
+impl Foo for u8 {
+    type Output = Bar;
+    fn baz() -> Self::Output {
+        needs_infer(); //~ ERROR type annotations needed
+        Self::Output::Variant {}
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr b/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr
new file mode 100644
index 00000000000..68ecb381348
--- /dev/null
+++ b/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/expr-struct-type-relative-enum.rs:16:9
+   |
+LL |         needs_infer();
+   |         ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `needs_infer`
+   |
+help: consider specifying the generic argument
+   |
+LL |         needs_infer::<T>();
+   |                    +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.rs b/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.rs
new file mode 100644
index 00000000000..b0c0d33975c
--- /dev/null
+++ b/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.rs
@@ -0,0 +1,19 @@
+trait Foo {
+    type Output<T>;
+
+    fn baz();
+}
+
+enum Bar<T> {
+    Simple {},
+    Generic(T),
+}
+
+impl Foo for u8 {
+    type Output<T> = Bar<T>;
+    fn baz() {
+        Self::Output::Simple {}; //~ ERROR type annotations needed
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr b/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr
new file mode 100644
index 00000000000..cbc2477deb3
--- /dev/null
+++ b/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/expr-struct-type-relative-gat.rs:15:9
+   |
+LL |         Self::Output::Simple {};
+   |         ^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the associated type `Output`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative.rs b/tests/ui/inference/need_type_info/expr-struct-type-relative.rs
new file mode 100644
index 00000000000..c3ece2b16cf
--- /dev/null
+++ b/tests/ui/inference/need_type_info/expr-struct-type-relative.rs
@@ -0,0 +1,21 @@
+// regression test for #98598
+
+trait Foo {
+    type Output;
+
+    fn baz() -> Self::Output;
+}
+
+fn needs_infer<T>() {}
+
+struct Bar {}
+
+impl Foo for u8 {
+    type Output = Bar;
+    fn baz() -> Self::Output {
+        needs_infer(); //~ ERROR type annotations needed
+        Self::Output {}
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative.stderr b/tests/ui/inference/need_type_info/expr-struct-type-relative.stderr
new file mode 100644
index 00000000000..397d8e7be04
--- /dev/null
+++ b/tests/ui/inference/need_type_info/expr-struct-type-relative.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/expr-struct-type-relative.rs:16:9
+   |
+LL |         needs_infer();
+   |         ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `needs_infer`
+   |
+help: consider specifying the generic argument
+   |
+LL |         needs_infer::<T>();
+   |                    +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/need_type_info/issue-103053.rs b/tests/ui/inference/need_type_info/issue-103053.rs
new file mode 100644
index 00000000000..05169666f83
--- /dev/null
+++ b/tests/ui/inference/need_type_info/issue-103053.rs
@@ -0,0 +1,18 @@
+trait TypeMapper {
+    type MapType;
+}
+
+type Mapped<T> = <T as TypeMapper>::MapType;
+
+struct Test {}
+
+impl TypeMapper for () {
+    type MapType = Test;
+}
+
+fn test() {
+    Mapped::<()> {};
+    None; //~ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/inference/need_type_info/issue-103053.stderr b/tests/ui/inference/need_type_info/issue-103053.stderr
new file mode 100644
index 00000000000..84f0475d8cd
--- /dev/null
+++ b/tests/ui/inference/need_type_info/issue-103053.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-103053.rs:15:5
+   |
+LL |     None;
+   |     ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option`
+   |
+help: consider specifying the generic argument
+   |
+LL |     None::<T>;
+   |         +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/need_type_info/self-ty-in-path.rs b/tests/ui/inference/need_type_info/self-ty-in-path.rs
new file mode 100644
index 00000000000..768a8cc3778
--- /dev/null
+++ b/tests/ui/inference/need_type_info/self-ty-in-path.rs
@@ -0,0 +1,13 @@
+// Test that we don't ICE when encountering a `Self` in a path.
+struct TestErr<T>(T);
+
+impl<T> TestErr<T> {
+    fn func_a<U>() {}
+
+    fn func_b() {
+        Self::func_a();
+        //~^ ERROR type annotations needed
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/inference/need_type_info/self-ty-in-path.stderr b/tests/ui/inference/need_type_info/self-ty-in-path.stderr
new file mode 100644
index 00000000000..04b521dbdb3
--- /dev/null
+++ b/tests/ui/inference/need_type_info/self-ty-in-path.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/self-ty-in-path.rs:8:9
+   |
+LL |         Self::func_a();
+   |         ^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the associated function `func_a`
+   |
+help: consider specifying the generic argument
+   |
+LL |         Self::func_a::<U>();
+   |                     +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/need_type_info/type-alias-indirect.rs b/tests/ui/inference/need_type_info/type-alias-indirect.rs
new file mode 100644
index 00000000000..0ed02ddc5f3
--- /dev/null
+++ b/tests/ui/inference/need_type_info/type-alias-indirect.rs
@@ -0,0 +1,18 @@
+// An addition to the `type-alias.rs` test,
+// see the FIXME in that file for why this test
+// exists.
+//
+// If there is none, feel free to remove this test
+// again.
+struct Ty<T>(T);
+impl<T> Ty<T> {
+    fn new() {}
+}
+
+type IndirectAlias<T> = Ty<Box<T>>;
+fn indirect_alias() {
+    IndirectAlias::new();
+    //~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/inference/need_type_info/type-alias-indirect.stderr b/tests/ui/inference/need_type_info/type-alias-indirect.stderr
new file mode 100644
index 00000000000..6161690df50
--- /dev/null
+++ b/tests/ui/inference/need_type_info/type-alias-indirect.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/type-alias-indirect.rs:14:5
+   |
+LL |     IndirectAlias::new();
+   |     ^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/need_type_info/type-alias.rs b/tests/ui/inference/need_type_info/type-alias.rs
new file mode 100644
index 00000000000..f921b046b6c
--- /dev/null
+++ b/tests/ui/inference/need_type_info/type-alias.rs
@@ -0,0 +1,36 @@
+// Test the inference errors in case the relevant path
+// uses a type alias.
+//
+// Regression test for #97698.
+struct Ty<T>(T);
+impl<T> Ty<T> {
+    fn new() {}
+}
+
+type DirectAlias<T> = Ty<T>;
+fn direct_alias() {
+    DirectAlias::new()
+    //~^ ERROR type annotations needed
+}
+
+type IndirectAlias<T> = Ty<Box<T>>;
+fn indirect_alias() {
+    IndirectAlias::new();
+    // FIXME: This should also emit an error.
+    //
+    // Added it separately as `type-alias-indirect.rs`
+    // where it does error.
+}
+
+struct TyDefault<T, U = u32>(T, U);
+impl<T> TyDefault<T> {
+    fn new() {}
+}
+
+type DirectButWithDefaultAlias<T> = TyDefault<T>;
+fn direct_but_with_default_alias() {
+    DirectButWithDefaultAlias::new();
+    //~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/inference/need_type_info/type-alias.stderr b/tests/ui/inference/need_type_info/type-alias.stderr
new file mode 100644
index 00000000000..a33f49baf54
--- /dev/null
+++ b/tests/ui/inference/need_type_info/type-alias.stderr
@@ -0,0 +1,15 @@
+error[E0282]: type annotations needed
+  --> $DIR/type-alias.rs:12:5
+   |
+LL |     DirectAlias::new()
+   |     ^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
+
+error[E0282]: type annotations needed
+  --> $DIR/type-alias.rs:32:5
+   |
+LL |     DirectButWithDefaultAlias::new();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/newlambdas-ret-infer.rs b/tests/ui/inference/newlambdas-ret-infer.rs
new file mode 100644
index 00000000000..9b629838ffd
--- /dev/null
+++ b/tests/ui/inference/newlambdas-ret-infer.rs
@@ -0,0 +1,12 @@
+// run-pass
+
+#![allow(dead_code)]
+// Test that the lambda kind is inferred correctly as a return
+// expression
+
+// pretty-expanded FIXME #23616
+
+fn unique() -> Box<dyn FnMut()+'static> { return Box::new(|| ()); }
+
+pub fn main() {
+}
diff --git a/tests/ui/inference/newlambdas-ret-infer2.rs b/tests/ui/inference/newlambdas-ret-infer2.rs
new file mode 100644
index 00000000000..abe31a05f22
--- /dev/null
+++ b/tests/ui/inference/newlambdas-ret-infer2.rs
@@ -0,0 +1,12 @@
+// run-pass
+
+#![allow(dead_code)]
+// Test that the lambda kind is inferred correctly as a return
+// expression
+
+// pretty-expanded FIXME #23616
+
+fn unique() -> Box<dyn FnMut()+'static> { Box::new(|| ()) }
+
+pub fn main() {
+}
diff --git a/tests/ui/inference/question-mark-type-infer.rs b/tests/ui/inference/question-mark-type-infer.rs
new file mode 100644
index 00000000000..10560f85ed4
--- /dev/null
+++ b/tests/ui/inference/question-mark-type-infer.rs
@@ -0,0 +1,16 @@
+// Test that type inference fails where there are multiple possible return types
+// for the `?` operator.
+
+fn f(x: &i32) -> Result<i32, ()> {
+    Ok(*x)
+}
+
+fn g() -> Result<Vec<i32>, ()> {
+    let l = [1, 2, 3, 4];
+    l.iter().map(f).collect()?
+    //~^ ERROR type annotations needed
+}
+
+fn main() {
+    g();
+}
diff --git a/tests/ui/inference/question-mark-type-infer.stderr b/tests/ui/inference/question-mark-type-infer.stderr
new file mode 100644
index 00000000000..9b822714f82
--- /dev/null
+++ b/tests/ui/inference/question-mark-type-infer.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/question-mark-type-infer.rs:10:30
+   |
+LL |     l.iter().map(f).collect()?
+   |                              ^ cannot infer type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/inference/range-type-infer.rs b/tests/ui/inference/range-type-infer.rs
new file mode 100644
index 00000000000..f07c041717f
--- /dev/null
+++ b/tests/ui/inference/range-type-infer.rs
@@ -0,0 +1,22 @@
+// run-pass
+
+#![allow(unused_must_use)]
+// Make sure the type inference for the new range expression work as
+// good as the old one. Check out issue #21672, #21595 and #21649 for
+// more details.
+
+
+fn main() {
+    let xs = (0..8).map(|i| i == 1u64).collect::<Vec<_>>();
+    assert_eq!(xs[1], true);
+    let xs = (0..8).map(|i| 1u64 == i).collect::<Vec<_>>();
+    assert_eq!(xs[1], true);
+    let xs: Vec<u8> = (0..10).collect();
+    assert_eq!(xs.len(), 10);
+
+    for x in 0..10 { x % 2; }
+    for x in 0..100 { x as f32; }
+
+    let array = [true, false];
+    for i in 0..1 { array[i]; }
+}
diff --git a/tests/ui/inference/simple-infer.rs b/tests/ui/inference/simple-infer.rs
new file mode 100644
index 00000000000..561e4fdec7c
--- /dev/null
+++ b/tests/ui/inference/simple-infer.rs
@@ -0,0 +1,6 @@
+// run-pass
+
+#![allow(unused_mut)]
+
+
+pub fn main() { let mut n; n = 1; println!("{}", n); }
diff --git a/tests/ui/inference/str-as-char.fixed b/tests/ui/inference/str-as-char.fixed
new file mode 100644
index 00000000000..6aea809cbdb
--- /dev/null
+++ b/tests/ui/inference/str-as-char.fixed
@@ -0,0 +1,10 @@
+// When a char literal is used where a str should be,
+// suggest changing to double quotes.
+
+// run-rustfix
+
+fn main() {
+    let _: &str = "a";   //~ ERROR mismatched types
+    let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
+    let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
+}
diff --git a/tests/ui/inference/str-as-char.rs b/tests/ui/inference/str-as-char.rs
new file mode 100644
index 00000000000..eaa8d788c34
--- /dev/null
+++ b/tests/ui/inference/str-as-char.rs
@@ -0,0 +1,10 @@
+// When a char literal is used where a str should be,
+// suggest changing to double quotes.
+
+// run-rustfix
+
+fn main() {
+    let _: &str = 'a';   //~ ERROR mismatched types
+    let _: &str = '"""'; //~ ERROR character literal may only contain one codepoint
+    let _: &str = '\"\"\"'; //~ ERROR character literal may only contain one codepoint
+}
diff --git a/tests/ui/inference/str-as-char.stderr b/tests/ui/inference/str-as-char.stderr
new file mode 100644
index 00000000000..2c84dac8e0c
--- /dev/null
+++ b/tests/ui/inference/str-as-char.stderr
@@ -0,0 +1,38 @@
+error: character literal may only contain one codepoint
+  --> $DIR/str-as-char.rs:8:19
+   |
+LL |     let _: &str = '"""';
+   |                   ^^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let _: &str = "\"\"\"";
+   |                   ~~~~~~~~
+
+error: character literal may only contain one codepoint
+  --> $DIR/str-as-char.rs:9:19
+   |
+LL |     let _: &str = '\"\"\"';
+   |                   ^^^^^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let _: &str = "\"\"\"";
+   |                   ~~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/str-as-char.rs:7:19
+   |
+LL |     let _: &str = 'a';
+   |            ----   ^^^ expected `&str`, found `char`
+   |            |
+   |            expected due to this
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let _: &str = "a";
+   |                   ~~~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/inference/tutorial-suffix-inference-test.rs b/tests/ui/inference/tutorial-suffix-inference-test.rs
new file mode 100644
index 00000000000..849adfd5368
--- /dev/null
+++ b/tests/ui/inference/tutorial-suffix-inference-test.rs
@@ -0,0 +1,24 @@
+fn main() {
+    let x = 3;
+    let y: i32 = 3;
+
+    fn identity_u8(n: u8) -> u8 { n }
+    fn identity_u16(n: u16) -> u16 { n }
+
+    identity_u8(x);  // after this, `x` is assumed to have type `u8`
+    identity_u16(x);
+    //~^ ERROR mismatched types
+    //~| expected `u16`, found `u8`
+    identity_u16(y);
+    //~^ ERROR mismatched types
+    //~| expected `u16`, found `i32`
+
+    let a = 3;
+
+    fn identity_i(n: isize) -> isize { n }
+
+    identity_i(a); // ok
+    identity_u16(a);
+    //~^ ERROR mismatched types
+    //~| expected `u16`, found `isize`
+}
diff --git a/tests/ui/inference/tutorial-suffix-inference-test.stderr b/tests/ui/inference/tutorial-suffix-inference-test.stderr
new file mode 100644
index 00000000000..d83a1367dbf
--- /dev/null
+++ b/tests/ui/inference/tutorial-suffix-inference-test.stderr
@@ -0,0 +1,57 @@
+error[E0308]: mismatched types
+  --> $DIR/tutorial-suffix-inference-test.rs:9:18
+   |
+LL |     identity_u16(x);
+   |     ------------ ^ expected `u16`, found `u8`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/tutorial-suffix-inference-test.rs:6:8
+   |
+LL |     fn identity_u16(n: u16) -> u16 { n }
+   |        ^^^^^^^^^^^^ ------
+help: you can convert a `u8` to a `u16`
+   |
+LL |     identity_u16(x.into());
+   |                   +++++++
+
+error[E0308]: mismatched types
+  --> $DIR/tutorial-suffix-inference-test.rs:12:18
+   |
+LL |     identity_u16(y);
+   |     ------------ ^ expected `u16`, found `i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/tutorial-suffix-inference-test.rs:6:8
+   |
+LL |     fn identity_u16(n: u16) -> u16 { n }
+   |        ^^^^^^^^^^^^ ------
+help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit
+   |
+LL |     identity_u16(y.try_into().unwrap());
+   |                   ++++++++++++++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/tutorial-suffix-inference-test.rs:21:18
+   |
+LL |     identity_u16(a);
+   |     ------------ ^ expected `u16`, found `isize`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/tutorial-suffix-inference-test.rs:6:8
+   |
+LL |     fn identity_u16(n: u16) -> u16 { n }
+   |        ^^^^^^^^^^^^ ------
+help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
+   |
+LL |     identity_u16(a.try_into().unwrap());
+   |                   ++++++++++++++++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/inference/type-infer-generalize-ty-var.rs b/tests/ui/inference/type-infer-generalize-ty-var.rs
new file mode 100644
index 00000000000..a3d6916cbf7
--- /dev/null
+++ b/tests/ui/inference/type-infer-generalize-ty-var.rs
@@ -0,0 +1,56 @@
+// run-pass
+
+#![allow(non_upper_case_globals)]
+#![allow(dead_code)]
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
+// Test a scenario where we generate a constraint like `?1 <: &?2`.
+// In such a case, it is important that we instantiate `?1` with `&?3`
+// where `?3 <: ?2`, and not with `&?2`. This is a regression test for
+// #18653. The important thing is that we build.
+
+use std::cell::RefCell;
+
+enum Wrap<A> {
+    WrapSome(A),
+    WrapNone
+}
+
+use Wrap::*;
+
+struct T;
+struct U;
+
+trait Get<T: ?Sized> {
+    fn get(&self) -> &T;
+}
+
+impl Get<dyn MyShow + 'static> for Wrap<T> {
+    fn get(&self) -> &(dyn MyShow + 'static) {
+        static x: usize = 42;
+        &x
+    }
+}
+
+impl Get<usize> for Wrap<U> {
+    fn get(&self) -> &usize {
+        static x: usize = 55;
+        &x
+    }
+}
+
+trait MyShow { fn dummy(&self) { } }
+impl<'a> MyShow for &'a (dyn MyShow + 'a) { }
+impl MyShow for usize { }
+fn constrain<'a>(rc: RefCell<&'a (dyn MyShow + 'a)>) { }
+
+fn main() {
+    let mut collection: Wrap<_> = WrapNone;
+
+    {
+        let __arg0 = Get::get(&collection);
+        let __args_cell = RefCell::new(__arg0);
+        constrain(__args_cell);
+    }
+    collection = WrapSome(T);
+}