about summary refs log tree commit diff
path: root/tests/ui/nll/user-annotations
diff options
context:
space:
mode:
authorAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-05 09:13:28 +0100
committerAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-11 09:32:08 +0000
commitcf2dff2b1e3fa55fa5415d524200070d0d7aacfe (patch)
tree40a88d9a46aaf3e8870676eb2538378b75a263eb /tests/ui/nll/user-annotations
parentca855e6e42787ecd062d81d53336fe6788ef51a9 (diff)
downloadrust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.tar.gz
rust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.zip
Move /src/test to /tests
Diffstat (limited to 'tests/ui/nll/user-annotations')
-rw-r--r--tests/ui/nll/user-annotations/adt-brace-enums.rs50
-rw-r--r--tests/ui/nll/user-annotations/adt-brace-enums.stderr42
-rw-r--r--tests/ui/nll/user-annotations/adt-brace-structs.rs48
-rw-r--r--tests/ui/nll/user-annotations/adt-brace-structs.stderr42
-rw-r--r--tests/ui/nll/user-annotations/adt-nullary-enums.rs69
-rw-r--r--tests/ui/nll/user-annotations/adt-nullary-enums.stderr45
-rw-r--r--tests/ui/nll/user-annotations/adt-tuple-enums.rs53
-rw-r--r--tests/ui/nll/user-annotations/adt-tuple-enums.stderr42
-rw-r--r--tests/ui/nll/user-annotations/adt-tuple-struct-calls.rs71
-rw-r--r--tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr56
-rw-r--r--tests/ui/nll/user-annotations/adt-tuple-struct.rs48
-rw-r--r--tests/ui/nll/user-annotations/adt-tuple-struct.stderr42
-rw-r--r--tests/ui/nll/user-annotations/ascribed-type-wf.rs17
-rw-r--r--tests/ui/nll/user-annotations/ascribed-type-wf.stderr10
-rw-r--r--tests/ui/nll/user-annotations/cast_static_lifetime.rs6
-rw-r--r--tests/ui/nll/user-annotations/cast_static_lifetime.stderr14
-rw-r--r--tests/ui/nll/user-annotations/closure-sig.rs15
-rw-r--r--tests/ui/nll/user-annotations/closure-substs.polonius.stderr61
-rw-r--r--tests/ui/nll/user-annotations/closure-substs.rs31
-rw-r--r--tests/ui/nll/user-annotations/closure-substs.stderr42
-rw-r--r--tests/ui/nll/user-annotations/constant-in-expr-inherent-1.rs12
-rw-r--r--tests/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr10
-rw-r--r--tests/ui/nll/user-annotations/constant-in-expr-inherent-2.rs27
-rw-r--r--tests/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr50
-rw-r--r--tests/ui/nll/user-annotations/constant-in-expr-normalize.rs22
-rw-r--r--tests/ui/nll/user-annotations/constant-in-expr-normalize.stderr10
-rw-r--r--tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs14
-rw-r--r--tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr10
-rw-r--r--tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs14
-rw-r--r--tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr10
-rw-r--r--tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs14
-rw-r--r--tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr10
-rw-r--r--tests/ui/nll/user-annotations/downcast-infer.rs11
-rw-r--r--tests/ui/nll/user-annotations/dump-adt-brace-struct.rs20
-rw-r--r--tests/ui/nll/user-annotations/dump-adt-brace-struct.stderr8
-rw-r--r--tests/ui/nll/user-annotations/dump-fn-method.rs57
-rw-r--r--tests/ui/nll/user-annotations/dump-fn-method.stderr26
-rw-r--r--tests/ui/nll/user-annotations/fns.rs48
-rw-r--r--tests/ui/nll/user-annotations/fns.stderr42
-rw-r--r--tests/ui/nll/user-annotations/inherent-associated-constants.rs15
-rw-r--r--tests/ui/nll/user-annotations/inherent-associated-constants.stderr10
-rw-r--r--tests/ui/nll/user-annotations/issue-54124.rs8
-rw-r--r--tests/ui/nll/user-annotations/issue-54124.stderr20
-rw-r--r--tests/ui/nll/user-annotations/issue-54570-bootstrapping.rs30
-rw-r--r--tests/ui/nll/user-annotations/issue-55219.rs18
-rw-r--r--tests/ui/nll/user-annotations/issue-55241.rs26
-rw-r--r--tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs68
-rw-r--r--tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr29
-rw-r--r--tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs40
-rw-r--r--tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr38
-rw-r--r--tests/ui/nll/user-annotations/method-call.rs69
-rw-r--r--tests/ui/nll/user-annotations/method-call.stderr42
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-1.rs63
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-1.stderr46
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-2.rs63
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-2.stderr46
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-3.rs69
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-3.stderr42
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-inherent-1.rs18
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr18
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-inherent-2.rs19
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-inherent-2.stderr33
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-inherent-3.rs18
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr18
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-inherent-4.rs20
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-inherent-4.stderr33
-rw-r--r--tests/ui/nll/user-annotations/normalization-2.rs152
-rw-r--r--tests/ui/nll/user-annotations/normalization-2.stderr296
-rw-r--r--tests/ui/nll/user-annotations/normalization-default.rs22
-rw-r--r--tests/ui/nll/user-annotations/normalization-default.stderr36
-rw-r--r--tests/ui/nll/user-annotations/normalization-infer.rs40
-rw-r--r--tests/ui/nll/user-annotations/normalization-infer.stderr101
-rw-r--r--tests/ui/nll/user-annotations/normalization-self.rs26
-rw-r--r--tests/ui/nll/user-annotations/normalization-self.stderr36
-rw-r--r--tests/ui/nll/user-annotations/normalization.rs17
-rw-r--r--tests/ui/nll/user-annotations/normalization.stderr25
-rw-r--r--tests/ui/nll/user-annotations/normalize-self-ty.rs23
-rw-r--r--tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs22
-rw-r--r--tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr26
-rw-r--r--tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs20
-rw-r--r--tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr26
-rw-r--r--tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs22
-rw-r--r--tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr26
-rw-r--r--tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs20
-rw-r--r--tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr26
-rw-r--r--tests/ui/nll/user-annotations/patterns.rs136
-rw-r--r--tests/ui/nll/user-annotations/patterns.stderr189
-rw-r--r--tests/ui/nll/user-annotations/promoted-annotation.rs10
-rw-r--r--tests/ui/nll/user-annotations/promoted-annotation.stderr17
-rw-r--r--tests/ui/nll/user-annotations/type-annotation-with-hrtb.rs33
-rw-r--r--tests/ui/nll/user-annotations/type_ascription_static_lifetime.rs7
-rw-r--r--tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr14
-rw-r--r--tests/ui/nll/user-annotations/wf-self-type.rs13
-rw-r--r--tests/ui/nll/user-annotations/wf-self-type.stderr14
94 files changed, 3533 insertions, 0 deletions
diff --git a/tests/ui/nll/user-annotations/adt-brace-enums.rs b/tests/ui/nll/user-annotations/adt-brace-enums.rs
new file mode 100644
index 00000000000..0d9828342d8
--- /dev/null
+++ b/tests/ui/nll/user-annotations/adt-brace-enums.rs
@@ -0,0 +1,50 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+enum SomeEnum<T> {
+    SomeVariant { t: T }
+}
+
+fn no_annot() {
+    let c = 66;
+    SomeEnum::SomeVariant { t: &c };
+}
+
+fn annot_underscore() {
+    let c = 66;
+    SomeEnum::SomeVariant::<_> { t: &c };
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    SomeEnum::SomeVariant::<&u32> { t: &c };
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    SomeEnum::SomeVariant::<&'static u32> { t: &c }; //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    SomeEnum::SomeVariant::<&'a u32> { t: c };
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        SomeEnum::SomeVariant::<&'a u32> { t: c };
+    };
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/adt-brace-enums.stderr b/tests/ui/nll/user-annotations/adt-brace-enums.stderr
new file mode 100644
index 00000000000..253e3825110
--- /dev/null
+++ b/tests/ui/nll/user-annotations/adt-brace-enums.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-enums.rs:25:48
+   |
+LL |     SomeEnum::SomeVariant::<&'static u32> { t: &c };
+   |                                                ^^
+   |                                                |
+   |                                                borrowed value does not live long enough
+   |                                                this usage requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-enums.rs:30:43
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+LL |     let c = 66;
+LL |     SomeEnum::SomeVariant::<&'a u32> { t: &c };
+   |                                           ^^
+   |                                           |
+   |                                           borrowed value does not live long enough
+   |                                           this usage requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-enums.rs:40:47
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         SomeEnum::SomeVariant::<&'a u32> { t: &c };
+   |                                               ^^
+   |                                               |
+   |                                               borrowed value does not live long enough
+   |                                               this usage requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/adt-brace-structs.rs b/tests/ui/nll/user-annotations/adt-brace-structs.rs
new file mode 100644
index 00000000000..bdbfd87d584
--- /dev/null
+++ b/tests/ui/nll/user-annotations/adt-brace-structs.rs
@@ -0,0 +1,48 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+struct SomeStruct<T> { t: T }
+
+fn no_annot() {
+    let c = 66;
+    SomeStruct { t: &c };
+}
+
+fn annot_underscore() {
+    let c = 66;
+    SomeStruct::<_> { t: &c };
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    SomeStruct::<&u32> { t: &c };
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    SomeStruct::<&'static u32> { t: &c }; //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    SomeStruct::<&'a u32> { t: &c }; //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    SomeStruct::<&'a u32> { t: c };
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        SomeStruct::<&'a u32> { t: &c }; //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        SomeStruct::<&'a u32> { t: c };
+    };
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/adt-brace-structs.stderr b/tests/ui/nll/user-annotations/adt-brace-structs.stderr
new file mode 100644
index 00000000000..8b9d1705df6
--- /dev/null
+++ b/tests/ui/nll/user-annotations/adt-brace-structs.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-structs.rs:23:37
+   |
+LL |     SomeStruct::<&'static u32> { t: &c };
+   |                                     ^^
+   |                                     |
+   |                                     borrowed value does not live long enough
+   |                                     this usage requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-structs.rs:28:32
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+LL |     let c = 66;
+LL |     SomeStruct::<&'a u32> { t: &c };
+   |                                ^^
+   |                                |
+   |                                borrowed value does not live long enough
+   |                                this usage requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-brace-structs.rs:38:36
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         SomeStruct::<&'a u32> { t: &c };
+   |                                    ^^
+   |                                    |
+   |                                    borrowed value does not live long enough
+   |                                    this usage requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/adt-nullary-enums.rs b/tests/ui/nll/user-annotations/adt-nullary-enums.rs
new file mode 100644
index 00000000000..53853668d19
--- /dev/null
+++ b/tests/ui/nll/user-annotations/adt-nullary-enums.rs
@@ -0,0 +1,69 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![allow(warnings)]
+
+use std::cell::Cell;
+
+enum SomeEnum<T> {
+    SomeVariant(T),
+    SomeOtherVariant,
+}
+
+fn combine<T>(_: T, _: T) { }
+
+fn no_annot() {
+    let c = 66;
+    combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant);
+}
+
+fn annot_underscore() {
+    let c = 66;
+    combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::<Cell<_>>);
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::<Cell<&u32>>);
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    combine(
+        SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR
+        SomeEnum::SomeOtherVariant::<Cell<&'static u32>>,
+    );
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    combine(
+        SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR
+        SomeEnum::SomeOtherVariant::<Cell<&'a u32>>,
+    );
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    combine(SomeEnum::SomeVariant(Cell::new(c)), SomeEnum::SomeOtherVariant::<Cell<&'a u32>>);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        combine(
+            SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR
+            SomeEnum::SomeOtherVariant::<Cell<&'a u32>>,
+        );
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        combine(
+            SomeEnum::SomeVariant(Cell::new(c)),
+            SomeEnum::SomeOtherVariant::<Cell<&'a u32>>,
+        );
+    };
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/adt-nullary-enums.stderr b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr
new file mode 100644
index 00000000000..3326fa521fc
--- /dev/null
+++ b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr
@@ -0,0 +1,45 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-nullary-enums.rs:33:41
+   |
+LL | /     combine(
+LL | |         SomeEnum::SomeVariant(Cell::new(&c)),
+   | |                                         ^^ borrowed value does not live long enough
+LL | |         SomeEnum::SomeOtherVariant::<Cell<&'static u32>>,
+LL | |     );
+   | |_____- argument requires that `c` is borrowed for `'static`
+LL |   }
+   |   - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-nullary-enums.rs:41:41
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+...
+LL |         SomeEnum::SomeVariant(Cell::new(&c)),
+   |                               ----------^^-
+   |                               |         |
+   |                               |         borrowed value does not live long enough
+   |                               argument requires that `c` is borrowed for `'a`
+...
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-nullary-enums.rs:54:45
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |             SomeEnum::SomeVariant(Cell::new(&c)),
+   |                                   ----------^^-
+   |                                   |         |
+   |                                   |         borrowed value does not live long enough
+   |                                   argument requires that `c` is borrowed for `'a`
+...
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/adt-tuple-enums.rs b/tests/ui/nll/user-annotations/adt-tuple-enums.rs
new file mode 100644
index 00000000000..efe8dfda191
--- /dev/null
+++ b/tests/ui/nll/user-annotations/adt-tuple-enums.rs
@@ -0,0 +1,53 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+#![allow(warnings)]
+
+enum SomeEnum<T> {
+    SomeVariant(T),
+    SomeOtherVariant,
+}
+
+fn no_annot() {
+    let c = 66;
+    SomeEnum::SomeVariant(&c);
+}
+
+fn annot_underscore() {
+    let c = 66;
+    SomeEnum::SomeVariant::<_>(&c);
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    SomeEnum::SomeVariant::<&u32>(&c);
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    SomeEnum::SomeVariant::<&'static u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    SomeEnum::SomeVariant::<&'a u32>(c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        SomeEnum::SomeVariant::<&'a u32>(c);
+    };
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/adt-tuple-enums.stderr b/tests/ui/nll/user-annotations/adt-tuple-enums.stderr
new file mode 100644
index 00000000000..2fa7042631d
--- /dev/null
+++ b/tests/ui/nll/user-annotations/adt-tuple-enums.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-enums.rs:28:43
+   |
+LL |     SomeEnum::SomeVariant::<&'static u32>(&c);
+   |                                           ^^
+   |                                           |
+   |                                           borrowed value does not live long enough
+   |                                           this usage requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-enums.rs:33:38
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+LL |     let c = 66;
+LL |     SomeEnum::SomeVariant::<&'a u32>(&c);
+   |                                      ^^
+   |                                      |
+   |                                      borrowed value does not live long enough
+   |                                      this usage requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-enums.rs:43:42
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         SomeEnum::SomeVariant::<&'a u32>(&c);
+   |                                          ^^
+   |                                          |
+   |                                          borrowed value does not live long enough
+   |                                          this usage requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.rs b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.rs
new file mode 100644
index 00000000000..11658322392
--- /dev/null
+++ b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.rs
@@ -0,0 +1,71 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+struct SomeStruct<T>(T);
+
+fn no_annot() {
+    let c = 66;
+    let f = SomeStruct;
+    f(&c);
+}
+
+fn annot_underscore() {
+    let c = 66;
+    let f = SomeStruct::<_>;
+    f(&c);
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    let f = SomeStruct::<&u32>;
+    f(&c);
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    let f = SomeStruct::<&'static u32>;
+    f(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    let f = SomeStruct::<&'a u32>;
+    f(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    let f = SomeStruct::<&'a u32>;
+    f(c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        let f = SomeStruct::<&'a u32>;
+        f(&c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_across_closure<'a>(_: &'a u32) {
+    let f = SomeStruct::<&'a u32>;
+    let _closure = || {
+        let c = 66;
+        f(&c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        let f = SomeStruct::<&'a u32>;
+        f(c);
+    };
+}
+
+fn annot_reference_named_lifetime_across_closure_ok<'a>(c: &'a u32) {
+    let f = SomeStruct::<&'a u32>;
+    let _closure = || {
+        f(c);
+    };
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr
new file mode 100644
index 00000000000..9664fb9f548
--- /dev/null
+++ b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr
@@ -0,0 +1,56 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-struct-calls.rs:27:7
+   |
+LL |     f(&c);
+   |     --^^-
+   |     | |
+   |     | borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-struct-calls.rs:33:7
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+...
+LL |     f(&c);
+   |     --^^-
+   |     | |
+   |     | borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-struct-calls.rs:45:11
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         f(&c);
+   |         --^^-
+   |         | |
+   |         | borrowed value does not live long enough
+   |         argument requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-struct-calls.rs:53:11
+   |
+LL |     let f = SomeStruct::<&'a u32>;
+   |         - lifetime `'1` appears in the type of `f`
+...
+LL |         f(&c);
+   |         --^^-
+   |         | |
+   |         | borrowed value does not live long enough
+   |         argument requires that `c` is borrowed for `'1`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct.rs b/tests/ui/nll/user-annotations/adt-tuple-struct.rs
new file mode 100644
index 00000000000..37284e1fda8
--- /dev/null
+++ b/tests/ui/nll/user-annotations/adt-tuple-struct.rs
@@ -0,0 +1,48 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+struct SomeStruct<T>(T);
+
+fn no_annot() {
+    let c = 66;
+    SomeStruct(&c);
+}
+
+fn annot_underscore() {
+    let c = 66;
+    SomeStruct::<_>(&c);
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    SomeStruct::<&u32>(&c);
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    SomeStruct::<&'static u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    SomeStruct::<&'a u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    SomeStruct::<&'a u32>(c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        SomeStruct::<&'a u32>(&c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        SomeStruct::<&'a u32>(c);
+    };
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct.stderr b/tests/ui/nll/user-annotations/adt-tuple-struct.stderr
new file mode 100644
index 00000000000..76b5252258c
--- /dev/null
+++ b/tests/ui/nll/user-annotations/adt-tuple-struct.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-struct.rs:23:32
+   |
+LL |     SomeStruct::<&'static u32>(&c);
+   |                                ^^
+   |                                |
+   |                                borrowed value does not live long enough
+   |                                this usage requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-struct.rs:28:27
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+LL |     let c = 66;
+LL |     SomeStruct::<&'a u32>(&c);
+   |                           ^^
+   |                           |
+   |                           borrowed value does not live long enough
+   |                           this usage requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/adt-tuple-struct.rs:38:31
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         SomeStruct::<&'a u32>(&c);
+   |                               ^^
+   |                               |
+   |                               borrowed value does not live long enough
+   |                               this usage requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/ascribed-type-wf.rs b/tests/ui/nll/user-annotations/ascribed-type-wf.rs
new file mode 100644
index 00000000000..5db02c46ec3
--- /dev/null
+++ b/tests/ui/nll/user-annotations/ascribed-type-wf.rs
@@ -0,0 +1,17 @@
+// Regression test for #101350.
+// check-fail
+
+trait Trait {
+    type Ty;
+}
+
+impl Trait for &'static () {
+    type Ty = ();
+}
+
+fn extend<'a>() {
+    None::<<&'a () as Trait>::Ty>;
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/ascribed-type-wf.stderr b/tests/ui/nll/user-annotations/ascribed-type-wf.stderr
new file mode 100644
index 00000000000..91e7c6b8ecf
--- /dev/null
+++ b/tests/ui/nll/user-annotations/ascribed-type-wf.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/ascribed-type-wf.rs:13:5
+   |
+LL | fn extend<'a>() {
+   |           -- lifetime `'a` defined here
+LL |     None::<<&'a () as Trait>::Ty>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/nll/user-annotations/cast_static_lifetime.rs b/tests/ui/nll/user-annotations/cast_static_lifetime.rs
new file mode 100644
index 00000000000..bb6129dacda
--- /dev/null
+++ b/tests/ui/nll/user-annotations/cast_static_lifetime.rs
@@ -0,0 +1,6 @@
+#![allow(warnings)]
+
+fn main() {
+    let x = 22_u32;
+    let y: &u32 = (&x) as &'static u32; //~ ERROR `x` does not live long enough
+}
diff --git a/tests/ui/nll/user-annotations/cast_static_lifetime.stderr b/tests/ui/nll/user-annotations/cast_static_lifetime.stderr
new file mode 100644
index 00000000000..4599d04e7e2
--- /dev/null
+++ b/tests/ui/nll/user-annotations/cast_static_lifetime.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/cast_static_lifetime.rs:5:19
+   |
+LL |     let y: &u32 = (&x) as &'static u32;
+   |                   ^^^^----------------
+   |                   |
+   |                   borrowed value does not live long enough
+   |                   type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/closure-sig.rs b/tests/ui/nll/user-annotations/closure-sig.rs
new file mode 100644
index 00000000000..4dbd3fd8d81
--- /dev/null
+++ b/tests/ui/nll/user-annotations/closure-sig.rs
@@ -0,0 +1,15 @@
+// This test fails if #104478 is fixed before #104477.
+
+// check-pass
+
+struct Printer<'a, 'b>(&'a (), &'b ());
+
+impl Printer<'_, '_> {
+    fn test(self) {
+        let clo = |_: &'_ Self| {};
+        clo(&self);
+        clo(&self);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/closure-substs.polonius.stderr b/tests/ui/nll/user-annotations/closure-substs.polonius.stderr
new file mode 100644
index 00000000000..af159a6cd1b
--- /dev/null
+++ b/tests/ui/nll/user-annotations/closure-substs.polonius.stderr
@@ -0,0 +1,61 @@
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:8:16
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |         return x;
+   |                ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:15:16
+   |
+LL |     |x: &i32| -> &'static i32 {
+   |         - let's call the lifetime of this reference `'1`
+LL |         return x;
+   |                ^ returning this value requires that `'1` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:15:16
+   |
+LL |     |x: &i32| -> &'static i32 {
+   |         -        - let's call the lifetime of this reference `'2`
+   |         |
+   |         let's call the lifetime of this reference `'1`
+LL |         return x;
+   |                ^ returning this value requires that `'1` must outlive `'2`
+
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:22:9
+   |
+LL | fn bar<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |         b(x);
+   |         ^^^^ argument requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
+
+error[E0521]: borrowed data escapes outside of closure
+  --> $DIR/closure-substs.rs:29:9
+   |
+LL |     |x: &i32, b: fn(&'static i32)| {
+   |      - `x` is a reference that is only valid in the closure body
+LL |         b(x);
+   |         ^^^^ `x` escapes the closure body here
+
+error[E0521]: borrowed data escapes outside of closure
+  --> $DIR/closure-substs.rs:29:9
+   |
+LL |     |x: &i32, b: fn(&'static i32)| {
+   |      -        - `b` declared here, outside of the closure body
+   |      |
+   |      `x` is a reference that is only valid in the closure body
+LL |         b(x);
+   |         ^^^^ `x` escapes the closure body here
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/tests/ui/nll/user-annotations/closure-substs.rs b/tests/ui/nll/user-annotations/closure-substs.rs
new file mode 100644
index 00000000000..f7af54e8df4
--- /dev/null
+++ b/tests/ui/nll/user-annotations/closure-substs.rs
@@ -0,0 +1,31 @@
+// Test that we enforce user-provided type annotations on closures.
+
+fn foo<'a>() {
+    // Here `x` is free in the closure sig:
+    |x: &'a i32| -> &'static i32 {
+        return x; //~ ERROR lifetime may not live long enough
+    };
+}
+
+fn foo1() {
+    // Here `x` is bound in the closure sig:
+    |x: &i32| -> &'static i32 {
+        return x; //~ ERROR lifetime may not live long enough
+    };
+}
+
+fn bar<'a>() {
+    // Here `x` is free in the closure sig:
+    |x: &'a i32, b: fn(&'static i32)| {
+        b(x); //~ ERROR lifetime may not live long enough
+    };
+}
+
+fn bar1() {
+    // Here `x` is bound in the closure sig:
+    |x: &i32, b: fn(&'static i32)| {
+        b(x); //~ ERROR borrowed data escapes outside of closure
+    };
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/closure-substs.stderr b/tests/ui/nll/user-annotations/closure-substs.stderr
new file mode 100644
index 00000000000..1e8de4ba905
--- /dev/null
+++ b/tests/ui/nll/user-annotations/closure-substs.stderr
@@ -0,0 +1,42 @@
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:6:16
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |         return x;
+   |                ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:13:16
+   |
+LL |     |x: &i32| -> &'static i32 {
+   |         - let's call the lifetime of this reference `'1`
+LL |         return x;
+   |                ^ returning this value requires that `'1` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:20:9
+   |
+LL | fn bar<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |         b(x);
+   |         ^^^^ argument requires that `'a` must outlive `'static`
+
+error[E0521]: borrowed data escapes outside of closure
+  --> $DIR/closure-substs.rs:27:9
+   |
+LL |     |x: &i32, b: fn(&'static i32)| {
+   |      -  - let's call the lifetime of this reference `'1`
+   |      |
+   |      `x` is a reference that is only valid in the closure body
+LL |         b(x);
+   |         ^^^^
+   |         |
+   |         `x` escapes the closure body here
+   |         argument requires that `'1` must outlive `'static`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.rs b/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.rs
new file mode 100644
index 00000000000..e3a8a5f58df
--- /dev/null
+++ b/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.rs
@@ -0,0 +1,12 @@
+struct Foo<'a> { x: &'a u32 }
+
+impl<'a> Foo<'a> {
+    const C: &'a u32 = &22;
+}
+
+fn foo<'a>(_: &'a u32) -> &'static u32 {
+    <Foo<'a>>::C //~ ERROR
+}
+
+fn main() {
+}
diff --git a/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
new file mode 100644
index 00000000000..c39301588ac
--- /dev/null
+++ b/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/constant-in-expr-inherent-1.rs:8:5
+   |
+LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
+   |        -- lifetime `'a` defined here
+LL |     <Foo<'a>>::C
+   |     ^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.rs b/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.rs
new file mode 100644
index 00000000000..90696d4b17d
--- /dev/null
+++ b/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.rs
@@ -0,0 +1,27 @@
+// Test that we still check constants are well-formed, even when we there's no
+// type annotation to check.
+
+const FUN: fn(&'static ()) = |_| {};
+struct A;
+impl A {
+    const ASSOCIATED_FUN: fn(&'static ()) = |_| {};
+}
+
+struct B<'a>(&'a ());
+impl B<'static> {
+    const ALSO_ASSOCIATED_FUN: fn(&'static ()) = |_| {};
+}
+
+trait Z: 'static {
+    const TRAIT_ASSOCIATED_FUN: fn(&'static Self) = |_| ();
+}
+
+impl Z for () {}
+
+fn main() {
+    let x = ();
+    FUN(&x);                        //~ ERROR `x` does not live long enough
+    A::ASSOCIATED_FUN(&x);          //~ ERROR `x` does not live long enough
+    B::ALSO_ASSOCIATED_FUN(&x);     //~ ERROR `x` does not live long enough
+    <_>::TRAIT_ASSOCIATED_FUN(&x);  //~ ERROR `x` does not live long enough
+}
diff --git a/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr b/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr
new file mode 100644
index 00000000000..12065a85aa4
--- /dev/null
+++ b/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr
@@ -0,0 +1,50 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/constant-in-expr-inherent-2.rs:23:9
+   |
+LL |     FUN(&x);
+   |     ----^^-
+   |     |   |
+   |     |   borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+...
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/constant-in-expr-inherent-2.rs:24:23
+   |
+LL |     A::ASSOCIATED_FUN(&x);
+   |     ------------------^^-
+   |     |                 |
+   |     |                 borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+...
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/constant-in-expr-inherent-2.rs:25:28
+   |
+LL |     B::ALSO_ASSOCIATED_FUN(&x);
+   |     -----------------------^^-
+   |     |                      |
+   |     |                      borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+LL |     <_>::TRAIT_ASSOCIATED_FUN(&x);
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/constant-in-expr-inherent-2.rs:26:31
+   |
+LL |     <_>::TRAIT_ASSOCIATED_FUN(&x);
+   |     --------------------------^^-
+   |     |                         |
+   |     |                         borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/constant-in-expr-normalize.rs b/tests/ui/nll/user-annotations/constant-in-expr-normalize.rs
new file mode 100644
index 00000000000..b7095430d8b
--- /dev/null
+++ b/tests/ui/nll/user-annotations/constant-in-expr-normalize.rs
@@ -0,0 +1,22 @@
+trait Mirror {
+    type Me;
+}
+
+impl<T> Mirror for T {
+    type Me = T;
+}
+
+trait Foo<'a> {
+    const C: <&'a u32 as Mirror>::Me;
+}
+
+impl<'a, T> Foo<'a> for T {
+    const C: &'a u32 = &22;
+}
+
+fn foo<'a>(_: &'a u32) -> &'static u32 {
+    <() as Foo<'a>>::C //~ ERROR
+}
+
+fn main() {
+}
diff --git a/tests/ui/nll/user-annotations/constant-in-expr-normalize.stderr b/tests/ui/nll/user-annotations/constant-in-expr-normalize.stderr
new file mode 100644
index 00000000000..541a2cfaf29
--- /dev/null
+++ b/tests/ui/nll/user-annotations/constant-in-expr-normalize.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/constant-in-expr-normalize.rs:18:5
+   |
+LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
+   |        -- lifetime `'a` defined here
+LL |     <() as Foo<'a>>::C
+   |     ^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs
new file mode 100644
index 00000000000..e0400b2cc02
--- /dev/null
+++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs
@@ -0,0 +1,14 @@
+trait Foo<'a> {
+    const C: &'a u32;
+}
+
+impl<'a, T> Foo<'a> for T {
+    const C: &'a u32 = &22;
+}
+
+fn foo<'a>(_: &'a u32) -> &'static u32 {
+    <() as Foo<'a>>::C //~ ERROR
+}
+
+fn main() {
+}
diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr
new file mode 100644
index 00000000000..ea0fcb6d634
--- /dev/null
+++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/constant-in-expr-trait-item-1.rs:10:5
+   |
+LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
+   |        -- lifetime `'a` defined here
+LL |     <() as Foo<'a>>::C
+   |     ^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs
new file mode 100644
index 00000000000..73c4e577b05
--- /dev/null
+++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs
@@ -0,0 +1,14 @@
+trait Foo<'a> {
+    const C: &'a u32;
+}
+
+impl<'a, T> Foo<'a> for T {
+    const C: &'a u32 = &22;
+}
+
+fn foo<'a, T: Foo<'a>>() -> &'static u32 {
+    <T as Foo<'a>>::C //~ ERROR
+}
+
+fn main() {
+}
diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr
new file mode 100644
index 00000000000..ff549f1d88b
--- /dev/null
+++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/constant-in-expr-trait-item-2.rs:10:5
+   |
+LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
+   |        -- lifetime `'a` defined here
+LL |     <T as Foo<'a>>::C
+   |     ^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs
new file mode 100644
index 00000000000..567e31ef936
--- /dev/null
+++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs
@@ -0,0 +1,14 @@
+trait Foo<'a> {
+    const C: &'a u32;
+}
+
+impl<'a, T> Foo<'a> for T {
+    const C: &'a u32 = &22;
+}
+
+fn foo<'a, T: Foo<'a>>() -> &'static u32 {
+    T::C //~ ERROR
+}
+
+fn main() {
+}
diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
new file mode 100644
index 00000000000..7f160d8e398
--- /dev/null
+++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/constant-in-expr-trait-item-3.rs:10:5
+   |
+LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
+   |        -- lifetime `'a` defined here
+LL |     T::C
+   |     ^^^^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/nll/user-annotations/downcast-infer.rs b/tests/ui/nll/user-annotations/downcast-infer.rs
new file mode 100644
index 00000000000..b27429f4d19
--- /dev/null
+++ b/tests/ui/nll/user-annotations/downcast-infer.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+// Check that we don't try to downcast `_` when type-checking the annotation.
+fn main() {
+    let x = Some(Some(Some(1)));
+
+    match x {
+        Some::<Option<_>>(Some(Some(v))) => (),
+        _ => (),
+    }
+}
diff --git a/tests/ui/nll/user-annotations/dump-adt-brace-struct.rs b/tests/ui/nll/user-annotations/dump-adt-brace-struct.rs
new file mode 100644
index 00000000000..ccda9129dab
--- /dev/null
+++ b/tests/ui/nll/user-annotations/dump-adt-brace-struct.rs
@@ -0,0 +1,20 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+// compile-flags:-Zverbose
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+struct SomeStruct<T> { t: T }
+
+#[rustc_dump_user_substs]
+fn main() {
+    SomeStruct { t: 22 }; // Nothing given, no annotation.
+
+    SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation.
+
+    SomeStruct::<u32> { t: 22 }; // No lifetime bounds given.
+
+    SomeStruct::<&'static u32> { t: &22 }; //~ ERROR [&ReStatic u32]
+}
diff --git a/tests/ui/nll/user-annotations/dump-adt-brace-struct.stderr b/tests/ui/nll/user-annotations/dump-adt-brace-struct.stderr
new file mode 100644
index 00000000000..5860621909c
--- /dev/null
+++ b/tests/ui/nll/user-annotations/dump-adt-brace-struct.stderr
@@ -0,0 +1,8 @@
+error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: None }
+  --> $DIR/dump-adt-brace-struct.rs:19:5
+   |
+LL |     SomeStruct::<&'static u32> { t: &22 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/nll/user-annotations/dump-fn-method.rs b/tests/ui/nll/user-annotations/dump-fn-method.rs
new file mode 100644
index 00000000000..148d63d848f
--- /dev/null
+++ b/tests/ui/nll/user-annotations/dump-fn-method.rs
@@ -0,0 +1,57 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+// compile-flags:-Zverbose
+
+#![feature(rustc_attrs)]
+
+// Note: we reference the names T and U in the comments below.
+trait Bazoom<T> {
+    fn method<U>(&self, arg: T, arg2: U) { }
+}
+
+impl<S, T> Bazoom<T> for S {
+}
+
+fn foo<'a, T>(_: T) { }
+
+#[rustc_dump_user_substs]
+fn main() {
+    // Here: nothing is given, so we don't have any annotation.
+    let x = foo;
+    x(22);
+
+    // Here: `u32` is given, which doesn't contain any lifetimes, so we don't
+    // have any annotation.
+    let x = foo::<u32>;
+    x(22);
+
+    let x = foo::<&'static u32>; //~ ERROR [&ReStatic u32]
+    x(&22);
+
+    // Here: we only want the `T` to be given, the rest should be variables.
+    //
+    // (`T` refers to the declaration of `Bazoom`)
+    let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1]
+    x(&22, 44, 66);
+
+    // Here: all are given and definitely contain no lifetimes, so we
+    // don't have any annotation.
+    let x = <u8 as Bazoom<u16>>::method::<u32>;
+    x(&22, 44, 66);
+
+    // Here: all are given and we have a lifetime.
+    let x = <u8 as Bazoom<&'static u16>>::method::<u32>; //~ ERROR [u8, &ReStatic u16, u32]
+    x(&22, &44, 66);
+
+    // Here: we want in particular that *only* the method `U`
+    // annotation is given, the rest are variables.
+    //
+    // (`U` refers to the declaration of `Bazoom`)
+    let y = 22_u32;
+    y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32]
+
+    // Here: nothing is given, so we don't have any annotation.
+    let y = 22_u32;
+    y.method(44, 66);
+}
diff --git a/tests/ui/nll/user-annotations/dump-fn-method.stderr b/tests/ui/nll/user-annotations/dump-fn-method.stderr
new file mode 100644
index 00000000000..d139efa888f
--- /dev/null
+++ b/tests/ui/nll/user-annotations/dump-fn-method.stderr
@@ -0,0 +1,26 @@
+error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: None }
+  --> $DIR/dump-fn-method.rs:29:13
+   |
+LL |     let x = foo::<&'static u32>;
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: user substs: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None }
+  --> $DIR/dump-fn-method.rs:35:13
+   |
+LL |     let x = <_ as Bazoom<u32>>::method::<_>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: user substs: UserSubsts { substs: [u8, &ReStatic u16, u32], user_self_ty: None }
+  --> $DIR/dump-fn-method.rs:44:13
+   |
+LL |     let x = <u8 as Bazoom<&'static u16>>::method::<u32>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: user substs: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None }
+  --> $DIR/dump-fn-method.rs:52:5
+   |
+LL |     y.method::<u32>(44, 66);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/nll/user-annotations/fns.rs b/tests/ui/nll/user-annotations/fns.rs
new file mode 100644
index 00000000000..38db6d1c4c5
--- /dev/null
+++ b/tests/ui/nll/user-annotations/fns.rs
@@ -0,0 +1,48 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+fn some_fn<T>(arg: T) { }
+
+fn no_annot() {
+    let c = 66;
+    some_fn(&c); // OK
+}
+
+fn annot_underscore() {
+    let c = 66;
+    some_fn::<_>(&c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let c = 66;
+    some_fn::<&u32>(&c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let c = 66;
+    some_fn::<&'static u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let c = 66;
+    some_fn::<&'a u32>(&c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    some_fn::<&'a u32>(c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let _closure = || {
+        let c = 66;
+        some_fn::<&'a u32>(&c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let _closure = || {
+        some_fn::<&'a u32>(c);
+    };
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/fns.stderr b/tests/ui/nll/user-annotations/fns.stderr
new file mode 100644
index 00000000000..e0640da39e2
--- /dev/null
+++ b/tests/ui/nll/user-annotations/fns.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/fns.rs:23:29
+   |
+LL |     some_fn::<&'static u32>(&c);
+   |     ------------------------^^-
+   |     |                       |
+   |     |                       borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/fns.rs:28:24
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+LL |     let c = 66;
+LL |     some_fn::<&'a u32>(&c);
+   |     -------------------^^-
+   |     |                  |
+   |     |                  borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/fns.rs:38:28
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         some_fn::<&'a u32>(&c);
+   |         -------------------^^-
+   |         |                  |
+   |         |                  borrowed value does not live long enough
+   |         argument requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/inherent-associated-constants.rs b/tests/ui/nll/user-annotations/inherent-associated-constants.rs
new file mode 100644
index 00000000000..fe2641fd63b
--- /dev/null
+++ b/tests/ui/nll/user-annotations/inherent-associated-constants.rs
@@ -0,0 +1,15 @@
+struct A<'a>(&'a ());
+
+impl A<'static> {
+    const IC: i32 = 10;
+}
+
+fn non_wf_associated_const<'a>(x: i32) {
+    A::<'a>::IC; //~ ERROR lifetime may not live long enough
+}
+
+fn wf_associated_const<'a>(x: i32) {
+    A::<'static>::IC;
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/inherent-associated-constants.stderr b/tests/ui/nll/user-annotations/inherent-associated-constants.stderr
new file mode 100644
index 00000000000..ffbfc40f537
--- /dev/null
+++ b/tests/ui/nll/user-annotations/inherent-associated-constants.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/inherent-associated-constants.rs:8:5
+   |
+LL | fn non_wf_associated_const<'a>(x: i32) {
+   |                            -- lifetime `'a` defined here
+LL |     A::<'a>::IC;
+   |     ^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/nll/user-annotations/issue-54124.rs b/tests/ui/nll/user-annotations/issue-54124.rs
new file mode 100644
index 00000000000..5ae03c89406
--- /dev/null
+++ b/tests/ui/nll/user-annotations/issue-54124.rs
@@ -0,0 +1,8 @@
+fn test<'a>() {
+    let _:fn(&()) = |_:&'a ()| {}; //~ ERROR lifetime may not live long enough
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+    test();
+}
diff --git a/tests/ui/nll/user-annotations/issue-54124.stderr b/tests/ui/nll/user-annotations/issue-54124.stderr
new file mode 100644
index 00000000000..2556af2dd7d
--- /dev/null
+++ b/tests/ui/nll/user-annotations/issue-54124.stderr
@@ -0,0 +1,20 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-54124.rs:2:22
+   |
+LL | fn test<'a>() {
+   |         -- lifetime `'a` defined here
+LL |     let _:fn(&()) = |_:&'a ()| {};
+   |                      ^ - let's call the lifetime of this reference `'1`
+   |                      |
+   |                      requires that `'1` must outlive `'a`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-54124.rs:2:22
+   |
+LL | fn test<'a>() {
+   |         -- lifetime `'a` defined here
+LL |     let _:fn(&()) = |_:&'a ()| {};
+   |                      ^ requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/nll/user-annotations/issue-54570-bootstrapping.rs b/tests/ui/nll/user-annotations/issue-54570-bootstrapping.rs
new file mode 100644
index 00000000000..ff5b2244e48
--- /dev/null
+++ b/tests/ui/nll/user-annotations/issue-54570-bootstrapping.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+// This test is reduced from a scenario pnkfelix encountered while
+// bootstrapping the compiler.
+
+#[derive(Copy, Clone)]
+pub struct Spanned<T> {
+    pub node: T,
+    pub span: Span,
+}
+
+pub type Variant = Spanned<VariantKind>;
+// #[derive(Clone)] pub struct Variant { pub node: VariantKind, pub span: Span, }
+
+#[derive(Clone)]
+pub struct VariantKind { }
+
+#[derive(Copy, Clone)]
+pub struct Span;
+
+pub fn variant_to_span(variant: Variant) {
+    match variant {
+        Variant {
+            span: _span,
+            ..
+        } => { }
+    };
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/issue-55219.rs b/tests/ui/nll/user-annotations/issue-55219.rs
new file mode 100644
index 00000000000..14741366389
--- /dev/null
+++ b/tests/ui/nll/user-annotations/issue-55219.rs
@@ -0,0 +1,18 @@
+// Regression test for #55219:
+//
+// The `Self::HASH_LEN` here expands to a "self-type" where `T` is not
+// known. This unbound inference variable was causing an ICE.
+//
+// check-pass
+
+pub struct Foo<T>(T);
+
+impl<T> Foo<T> {
+    const HASH_LEN: usize = 20;
+
+    fn stuff() {
+        let _ = Self::HASH_LEN;
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/issue-55241.rs b/tests/ui/nll/user-annotations/issue-55241.rs
new file mode 100644
index 00000000000..29969c7b4c6
--- /dev/null
+++ b/tests/ui/nll/user-annotations/issue-55241.rs
@@ -0,0 +1,26 @@
+// Regression test for #55241:
+//
+// The reference to `C::HASHED_NULL_NODE` resulted in a type like `<C
+// as NodeCodec<_>>::Out`; normalizing this type requires knowing the
+// value of `_`; solving that requires having normalized, so we can
+// test against `C: NodeCodec<H>` in the environment.
+//
+// run-pass
+
+pub trait Hasher {
+    type Out: Eq;
+}
+
+pub trait NodeCodec<H: Hasher> {
+    const HASHED_NULL_NODE: H::Out;
+}
+
+pub trait Trie<H: Hasher, C: NodeCodec<H>> {
+    /// Returns the root of the trie.
+    fn root(&self) -> &H::Out;
+
+    /// Is the trie empty?
+    fn is_empty(&self) -> bool { *self.root() == C::HASHED_NULL_NODE }
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs b/tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs
new file mode 100644
index 00000000000..c71937a5021
--- /dev/null
+++ b/tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs
@@ -0,0 +1,68 @@
+// This test is ensuring that type ascriptions on let bindings
+// constrain both:
+//
+// 1. the input expression on the right-hand side (after any potential
+//    coercion, and allowing for covariance), *and*
+//
+// 2. the bindings (if any) nested within the pattern on the left-hand
+//    side (and here, the type-constraint is *invariant*).
+
+#![allow(dead_code, unused_mut)]
+type PairUncoupled<'a, 'b, T> = (&'a T, &'b T);
+type PairCoupledRegions<'a, T> = (&'a T, &'a T);
+type PairCoupledTypes<T> = (T, T);
+
+fn uncoupled_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((mut y, mut _z),): (PairUncoupled<u32>,) = ((s, &_x),); // ok
+    // Above compiling does *not* imply below would compile.
+    // ::std::mem::swap(&mut y, &mut _z);
+    y
+}
+
+fn swap_regions((mut y, mut _z): PairCoupledRegions<u32>) {
+    ::std::mem::swap(&mut y, &mut _z);
+}
+
+fn coupled_regions_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),): (PairCoupledRegions<u32>,) = ((s, &_x),);
+    // If above line compiled, so should line below ...
+
+    // swap_regions((y, _z));
+
+    // ... but the ascribed type also invalidates this use of `y`
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn swap_types((mut y, mut _z): PairCoupledTypes<&u32>) {
+    ::std::mem::swap(&mut y, &mut _z);
+}
+
+fn coupled_types_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),): (PairCoupledTypes<&u32>,) = ((s, &_x),);
+    // If above line compiled, so should line below ...
+
+    // swap_types((y, _z));
+
+    // ... but the ascribed type also invalidates this use of `y`
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn swap_wilds((mut y, mut _z): PairCoupledTypes<&u32>) {
+    ::std::mem::swap(&mut y, &mut _z);
+}
+
+fn coupled_wilds_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),): (PairCoupledTypes<_>,) = ((s, &_x),);
+    // If above line compiled, so should line below
+    // swap_wilds((y, _z));
+
+    // ... but the ascribed type also invalidates this use of `y`
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn main() {
+    uncoupled_lhs(&3, &4);
+    coupled_regions_lhs(&3, &4);
+    coupled_types_lhs(&3, &4);
+    coupled_wilds_lhs(&3, &4);
+}
diff --git a/tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr b/tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr
new file mode 100644
index 00000000000..8399ef04e83
--- /dev/null
+++ b/tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr
@@ -0,0 +1,29 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-55748-pat-types-constrain-bindings.rs:33:5
+   |
+LL | fn coupled_regions_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                        -- lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-55748-pat-types-constrain-bindings.rs:47:5
+   |
+LL | fn coupled_types_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                      -- lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-55748-pat-types-constrain-bindings.rs:60:5
+   |
+LL | fn coupled_wilds_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                      -- lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs b/tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs
new file mode 100644
index 00000000000..95c655654ea
--- /dev/null
+++ b/tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs
@@ -0,0 +1,40 @@
+// Check that repeated type variables are correctly handled
+
+#![allow(unused)]
+#![feature(type_ascription)]
+
+type PairUncoupled<'a, 'b, T> = (&'a T, &'b T);
+type PairCoupledTypes<T> = (T, T);
+type PairCoupledRegions<'a, T> = (&'a T, &'a T);
+
+fn uncoupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = type_ascribe!(((s, _x),), (PairUncoupled<_>,));
+    y // OK
+}
+
+fn coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = type_ascribe!(((s, _x),), (PairCoupledTypes<_>,));
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = type_ascribe!(((s, _x),), (PairCoupledRegions<_>,));
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn cast_uncoupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),) as (PairUncoupled<_>,);
+    y // OK
+}
+
+fn cast_coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),) as (PairCoupledTypes<_>,);
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn cast_coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),) as (PairCoupledRegions<_>,);
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr b/tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr
new file mode 100644
index 00000000000..8601691e88a
--- /dev/null
+++ b/tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr
@@ -0,0 +1,38 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-57731-ascibed-coupled-types.rs:17:5
+   |
+LL | fn coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                      -- lifetime `'a` defined here
+LL |     let ((y, _z),) = type_ascribe!(((s, _x),), (PairCoupledTypes<_>,));
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-57731-ascibed-coupled-types.rs:22:5
+   |
+LL | fn coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                        -- lifetime `'a` defined here
+LL |     let ((y, _z),) = type_ascribe!(((s, _x),), (PairCoupledRegions<_>,));
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-57731-ascibed-coupled-types.rs:32:5
+   |
+LL | fn cast_coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                           -- lifetime `'a` defined here
+LL |     let ((y, _z),) = ((s, _x),) as (PairCoupledTypes<_>,);
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-57731-ascibed-coupled-types.rs:37:5
+   |
+LL | fn cast_coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                             -- lifetime `'a` defined here
+LL |     let ((y, _z),) = ((s, _x),) as (PairCoupledRegions<_>,);
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/nll/user-annotations/method-call.rs b/tests/ui/nll/user-annotations/method-call.rs
new file mode 100644
index 00000000000..beafc597ac1
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-call.rs
@@ -0,0 +1,69 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+trait Bazoom<T> {
+    fn method<U>(&self, arg: T, arg2: U) { }
+}
+
+impl<T, U> Bazoom<U> for T {
+}
+
+fn no_annot() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method(b,  &c); // OK
+}
+
+fn annot_underscore() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method::<_>(b,  &c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method::<&u32>(b,  &c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method::<&'static u32>(b,  &c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    a.method::<&'a u32>(b,  &c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    let a = 22;
+    let b = 44;
+    a.method::<&'a u32>(b,  c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        let c = 66;
+        a.method::<&'a u32>(b,  &c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        a.method::<&'a u32>(b,  c);
+    };
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/method-call.stderr b/tests/ui/nll/user-annotations/method-call.stderr
new file mode 100644
index 00000000000..10447e45a6d
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-call.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-call.rs:36:34
+   |
+LL |     a.method::<&'static u32>(b,  &c);
+   |     -----------------------------^^-
+   |     |                            |
+   |     |                            borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-call.rs:43:29
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+...
+LL |     a.method::<&'a u32>(b,  &c);
+   |     ------------------------^^-
+   |     |                       |
+   |     |                       borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-call.rs:57:33
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         a.method::<&'a u32>(b,  &c);
+   |         ------------------------^^-
+   |         |                       |
+   |         |                       borrowed value does not live long enough
+   |         argument requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/method-ufcs-1.rs b/tests/ui/nll/user-annotations/method-ufcs-1.rs
new file mode 100644
index 00000000000..950771f35e4
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-1.rs
@@ -0,0 +1,63 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+trait Bazoom<T>: Sized {
+    fn method<U>(self, arg: T, arg2: U) { }
+}
+
+impl<T, U> Bazoom<U> for T {
+}
+
+fn annot_underscore() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<_>(&a, b, c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <&u32 as Bazoom<_>>::method(&a, b, c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    let x = <&'static u32 as Bazoom<_>>::method;
+    x(&a, b, c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <&'a u32 as Bazoom<_>>::method(&a, b, c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(a: &'a u32) {
+    let b = 44;
+    let c = 66;
+    <&'a u32 as Bazoom<_>>::method(&a, b, c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        let c = 66;
+        <&'a u32 as Bazoom<_>>::method(&a, b, c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(a: &'a u32) {
+    let b = 44;
+    let c = 66;
+    let _closure = || {
+        <&'a u32 as Bazoom<_>>::method(&a, b, c);
+    };
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/method-ufcs-1.stderr b/tests/ui/nll/user-annotations/method-ufcs-1.stderr
new file mode 100644
index 00000000000..962ddfd2bd1
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-1.stderr
@@ -0,0 +1,46 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/method-ufcs-1.rs:30:7
+   |
+LL |     x(&a, b, c);
+   |     --^^-------
+   |     | |
+   |     | borrowed value does not live long enough
+   |     argument requires that `a` is borrowed for `'static`
+LL | }
+   | - `a` dropped here while still borrowed
+
+error[E0597]: `a` does not live long enough
+  --> $DIR/method-ufcs-1.rs:37:36
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+...
+LL |     <&'a u32 as Bazoom<_>>::method(&a, b, c);
+   |     -------------------------------^^-------
+   |     |                              |
+   |     |                              borrowed value does not live long enough
+   |     argument requires that `a` is borrowed for `'a`
+LL | }
+   | - `a` dropped here while still borrowed
+
+error[E0597]: `a` does not live long enough
+  --> $DIR/method-ufcs-1.rs:51:41
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |     let _closure = || {
+   |                    -- value captured here
+LL |         let c = 66;
+LL |         <&'a u32 as Bazoom<_>>::method(&a, b, c);
+   |         --------------------------------^-------
+   |         |                               |
+   |         |                               borrowed value does not live long enough
+   |         argument requires that `a` is borrowed for `'a`
+LL |     };
+LL | }
+   | - `a` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/method-ufcs-2.rs b/tests/ui/nll/user-annotations/method-ufcs-2.rs
new file mode 100644
index 00000000000..7dc0f0c12a4
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-2.rs
@@ -0,0 +1,63 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+trait Bazoom<T>: Sized {
+    fn method<U>(self, arg: T, arg2: U) { }
+}
+
+impl<T, U> Bazoom<U> for T {
+}
+
+fn annot_underscore() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method(a, &b, c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<&u32>>::method(a, &b, c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    let x = <&'static u32 as Bazoom<_>>::method;
+    x(&a, b, c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<&'a u32>>::method(a, &b, c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(b: &'a u32) {
+    let a = 44;
+    let c = 66;
+    <_ as Bazoom<&'a u32>>::method(a, &b, c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        let c = 66;
+        <_ as Bazoom<&'a u32>>::method(a, &b, c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(b: &'a u32) {
+    let a = 44;
+    let c = 66;
+    let _closure = || {
+        <_ as Bazoom<&'a u32>>::method(a, &b, c);
+    };
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/method-ufcs-2.stderr b/tests/ui/nll/user-annotations/method-ufcs-2.stderr
new file mode 100644
index 00000000000..63d59905e1c
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-2.stderr
@@ -0,0 +1,46 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/method-ufcs-2.rs:30:7
+   |
+LL |     x(&a, b, c);
+   |     --^^-------
+   |     | |
+   |     | borrowed value does not live long enough
+   |     argument requires that `a` is borrowed for `'static`
+LL | }
+   | - `a` dropped here while still borrowed
+
+error[E0597]: `b` does not live long enough
+  --> $DIR/method-ufcs-2.rs:37:39
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+...
+LL |     <_ as Bazoom<&'a u32>>::method(a, &b, c);
+   |     ----------------------------------^^----
+   |     |                                 |
+   |     |                                 borrowed value does not live long enough
+   |     argument requires that `b` is borrowed for `'a`
+LL | }
+   | - `b` dropped here while still borrowed
+
+error[E0597]: `b` does not live long enough
+  --> $DIR/method-ufcs-2.rs:51:44
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |     let _closure = || {
+   |                    -- value captured here
+LL |         let c = 66;
+LL |         <_ as Bazoom<&'a u32>>::method(a, &b, c);
+   |         -----------------------------------^----
+   |         |                                  |
+   |         |                                  borrowed value does not live long enough
+   |         argument requires that `b` is borrowed for `'a`
+LL |     };
+LL | }
+   | - `b` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/method-ufcs-3.rs b/tests/ui/nll/user-annotations/method-ufcs-3.rs
new file mode 100644
index 00000000000..59d2009d14b
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-3.rs
@@ -0,0 +1,69 @@
+// Unit test for the "user substitutions" that are annotated on each
+// node.
+
+trait Bazoom<T> {
+    fn method<U>(&self, arg: T, arg2: U) { }
+}
+
+impl<T, U> Bazoom<U> for T {
+}
+
+fn no_annot() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method(&a, b, &c); // OK
+}
+
+fn annot_underscore() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<_>(&a, b, &c); // OK
+}
+
+fn annot_reference_any_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<&u32>(&a, b, &c); // OK
+}
+
+fn annot_reference_static_lifetime() {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<&'static u32>(&a, b, &c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let c = 66;
+    <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c); //~ ERROR
+}
+
+fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) {
+    let a = 22;
+    let b = 44;
+    <_ as Bazoom<_>>::method::<&'a u32>(&a, b, c);
+}
+
+fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        let c = 66;
+        <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c); //~ ERROR
+    };
+}
+
+fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) {
+    let a = 22;
+    let b = 44;
+    let _closure = || {
+        <_ as Bazoom<_>>::method::<&'a u32>(&a, b, c);
+    };
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/method-ufcs-3.stderr b/tests/ui/nll/user-annotations/method-ufcs-3.stderr
new file mode 100644
index 00000000000..e7851833e93
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-3.stderr
@@ -0,0 +1,42 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-ufcs-3.rs:36:53
+   |
+LL |     <_ as Bazoom<_>>::method::<&'static u32>(&a, b, &c);
+   |     ------------------------------------------------^^-
+   |     |                                               |
+   |     |                                               borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'static`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-ufcs-3.rs:43:48
+   |
+LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                   -- lifetime `'a` defined here
+...
+LL |     <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c);
+   |     -------------------------------------------^^-
+   |     |                                          |
+   |     |                                          borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'a`
+LL | }
+   | - `c` dropped here while still borrowed
+
+error[E0597]: `c` does not live long enough
+  --> $DIR/method-ufcs-3.rs:57:52
+   |
+LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                              -- lifetime `'a` defined here
+...
+LL |         <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c);
+   |         -------------------------------------------^^-
+   |         |                                          |
+   |         |                                          borrowed value does not live long enough
+   |         argument requires that `c` is borrowed for `'a`
+LL |     };
+   |     - `c` dropped here while still borrowed
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-1.rs b/tests/ui/nll/user-annotations/method-ufcs-inherent-1.rs
new file mode 100644
index 00000000000..7bfed61d40a
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-1.rs
@@ -0,0 +1,18 @@
+// Check that substitutions given on the self type (here, `A`) carry
+// through to NLL.
+
+struct A<'a> { x: &'a u32 }
+
+impl<'a> A<'a> {
+    fn new<'b, T>(x: &'a u32, y: T) -> Self {
+        Self { x }
+    }
+}
+
+fn foo<'a>() {
+    let v = 22;
+    let x = A::<'a>::new(&v, 22);
+    //~^ ERROR
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr
new file mode 100644
index 00000000000..94861babd6f
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `v` does not live long enough
+  --> $DIR/method-ufcs-inherent-1.rs:14:26
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let v = 22;
+LL |     let x = A::<'a>::new(&v, 22);
+   |             -------------^^-----
+   |             |            |
+   |             |            borrowed value does not live long enough
+   |             argument requires that `v` is borrowed for `'a`
+LL |
+LL | }
+   | - `v` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-2.rs b/tests/ui/nll/user-annotations/method-ufcs-inherent-2.rs
new file mode 100644
index 00000000000..cfbc0bcf6b0
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-2.rs
@@ -0,0 +1,19 @@
+// Check that substitutions given on the self type (here, `A`) can be
+// used in combination with annotations given for method arguments.
+
+struct A<'a> { x: &'a u32 }
+
+impl<'a> A<'a> {
+    fn new<'b, T>(x: &'a u32, y: T) -> Self {
+        Self { x }
+    }
+}
+
+fn foo<'a>() {
+    let v = 22;
+    let x = A::<'a>::new::<&'a u32>(&v, &v);
+    //~^ ERROR
+    //~| ERROR
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-2.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-2.stderr
new file mode 100644
index 00000000000..06f20d9b235
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-2.stderr
@@ -0,0 +1,33 @@
+error[E0597]: `v` does not live long enough
+  --> $DIR/method-ufcs-inherent-2.rs:14:37
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let v = 22;
+LL |     let x = A::<'a>::new::<&'a u32>(&v, &v);
+   |             ------------------------^^-----
+   |             |                       |
+   |             |                       borrowed value does not live long enough
+   |             argument requires that `v` is borrowed for `'a`
+...
+LL | }
+   | - `v` dropped here while still borrowed
+
+error[E0597]: `v` does not live long enough
+  --> $DIR/method-ufcs-inherent-2.rs:14:41
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let v = 22;
+LL |     let x = A::<'a>::new::<&'a u32>(&v, &v);
+   |             ----------------------------^^-
+   |             |                           |
+   |             |                           borrowed value does not live long enough
+   |             argument requires that `v` is borrowed for `'a`
+...
+LL | }
+   | - `v` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-3.rs b/tests/ui/nll/user-annotations/method-ufcs-inherent-3.rs
new file mode 100644
index 00000000000..7ddb1336082
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-3.rs
@@ -0,0 +1,18 @@
+// Check that inherent methods invoked with `<T>::new` style
+// carry their annotations through to NLL.
+
+struct A<'a> { x: &'a u32 }
+
+impl<'a> A<'a> {
+    fn new<'b, T>(x: &'a u32, y: T) -> Self {
+        Self { x }
+    }
+}
+
+fn foo<'a>() {
+    let v = 22;
+    let x = <A<'a>>::new(&v, 22);
+    //~^ ERROR
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr
new file mode 100644
index 00000000000..4ad61dc81c4
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `v` does not live long enough
+  --> $DIR/method-ufcs-inherent-3.rs:14:26
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let v = 22;
+LL |     let x = <A<'a>>::new(&v, 22);
+   |             -------------^^-----
+   |             |            |
+   |             |            borrowed value does not live long enough
+   |             argument requires that `v` is borrowed for `'a`
+LL |
+LL | }
+   | - `v` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-4.rs b/tests/ui/nll/user-annotations/method-ufcs-inherent-4.rs
new file mode 100644
index 00000000000..85e7597390d
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-4.rs
@@ -0,0 +1,20 @@
+// Check that inherent methods invoked with `<T>::new` style
+// carry their annotations through to NLL in connection with
+// method type parameters.
+
+struct A<'a> { x: &'a u32 }
+
+impl<'a> A<'a> {
+    fn new<'b, T>(x: &'a u32, y: T) -> Self {
+        Self { x }
+    }
+}
+
+fn foo<'a>() {
+    let v = 22;
+    let x = <A<'a>>::new::<&'a u32>(&v, &v);
+    //~^ ERROR
+    //~| ERROR
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-4.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-4.stderr
new file mode 100644
index 00000000000..0f83e99cdfb
--- /dev/null
+++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-4.stderr
@@ -0,0 +1,33 @@
+error[E0597]: `v` does not live long enough
+  --> $DIR/method-ufcs-inherent-4.rs:15:37
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let v = 22;
+LL |     let x = <A<'a>>::new::<&'a u32>(&v, &v);
+   |             ------------------------^^-----
+   |             |                       |
+   |             |                       borrowed value does not live long enough
+   |             argument requires that `v` is borrowed for `'a`
+...
+LL | }
+   | - `v` dropped here while still borrowed
+
+error[E0597]: `v` does not live long enough
+  --> $DIR/method-ufcs-inherent-4.rs:15:41
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let v = 22;
+LL |     let x = <A<'a>>::new::<&'a u32>(&v, &v);
+   |             ----------------------------^^-
+   |             |                           |
+   |             |                           borrowed value does not live long enough
+   |             argument requires that `v` is borrowed for `'a`
+...
+LL | }
+   | - `v` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/normalization-2.rs b/tests/ui/nll/user-annotations/normalization-2.rs
new file mode 100644
index 00000000000..be23c3b7478
--- /dev/null
+++ b/tests/ui/nll/user-annotations/normalization-2.rs
@@ -0,0 +1,152 @@
+// Make sure we honor region constraints when normalizing type annotations.
+
+// check-fail
+
+#![feature(more_qualified_paths)]
+
+trait Trait {
+    type Assoc;
+}
+
+impl<T> Trait for T
+where
+    T: 'static,
+{
+    type Assoc = MyTy<()>;
+}
+
+enum MyTy<T> {
+    Unit,
+    Tuple(),
+    Struct {},
+    Dumb(T),
+}
+
+impl<T> MyTy<T> {
+    const CONST: () = ();
+    fn method<X>() {}
+    fn method2<X>(&self) {}
+}
+
+trait TraitAssoc {
+    const TRAIT_CONST: ();
+    fn trait_method<X>(&self);
+}
+impl<T> TraitAssoc for T {
+    const TRAIT_CONST: () = ();
+    fn trait_method<X>(&self) {}
+}
+
+type Ty<'a> = <&'a () as Trait>::Assoc;
+
+fn test_local<'a>() {
+    let _: Ty<'a> = MyTy::Unit;
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn test_closure_sig<'a, 'b>() {
+    |_: Ty<'a>| {};
+    //~^ ERROR lifetime may not live long enough
+    || -> Option<Ty<'b>> { None };
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
+    <Ty<'a>>::method::<Ty<'static>>;
+    //~^ ERROR lifetime may not live long enough
+    <Ty<'static>>::method::<Ty<'b>>;
+    //~^ ERROR lifetime may not live long enough
+
+    <Ty<'c>>::trait_method::<Ty<'static>>;
+    //~^ ERROR lifetime may not live long enough
+    <Ty<'static>>::trait_method::<Ty<'d>>;
+    //~^ ERROR lifetime may not live long enough
+
+    <Ty<'e>>::CONST;
+    //~^ ERROR lifetime may not live long enough
+    <Ty<'f>>::TRAIT_CONST;
+    //~^ ERROR lifetime may not live long enough
+
+    <Ty<'static>>::method::<Ty<'static>>;
+    <Ty<'static>>::trait_method::<Ty<'static>>;
+    <Ty<'static>>::CONST;
+    <Ty<'static>>::TRAIT_CONST;
+
+    MyTy::Unit::<Ty<'g>>;
+    //~^ ERROR lifetime may not live long enough
+    MyTy::<Ty<'h>>::Unit;
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn test_call<'a, 'b, 'c>() {
+    <Ty<'a>>::method::<Ty<'static>>();
+    //~^ ERROR lifetime may not live long enough
+    <Ty<'static>>::method::<Ty<'b>>();
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn test_variants<'a, 'b, 'c>() {
+    <Ty<'a>>::Struct {};
+    //~^ ERROR lifetime may not live long enough
+    <Ty<'b>>::Tuple();
+    //~^ ERROR lifetime may not live long enough
+    <Ty<'c>>::Unit;
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn test_method_call<'a, 'b>(x: MyTy<()>) {
+    x.method2::<Ty<'a>>();
+    //~^ ERROR lifetime may not live long enough
+    x.trait_method::<Ty<'b>>();
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn test_struct_path<'a, 'b, 'c, 'd>() {
+    struct Struct<T> { x: Option<T>, }
+
+    trait Project {
+        type Struct;
+        type Enum;
+    }
+    impl<T> Project for T {
+        type Struct = Struct<()>;
+        type Enum = MyTy<()>;
+    }
+
+    // Resolves to enum variant
+    MyTy::<Ty<'a>>::Struct {}; // without SelfTy
+    //~^ ERROR lifetime may not live long enough
+    <Ty<'b> as Project>::Enum::Struct {}; // with SelfTy
+    //~^ ERROR lifetime may not live long enough
+
+    // Resolves to struct and associated type respectively
+    Struct::<Ty<'c>> { x: None, }; // without SelfTy
+    //~^ ERROR lifetime may not live long enough
+    <Ty<'d> as Project>::Struct { x: None, }; // with SelfTy
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
+    use MyTy::*;
+    match MyTy::Unit {
+        Struct::<Ty<'a>> {..} => {},
+        //~^ ERROR lifetime may not live long enough
+        Tuple::<Ty<'b>> (..) => {},
+        //~^ ERROR lifetime may not live long enough
+        Unit::<Ty<'c>> => {},
+        //~^ ERROR lifetime may not live long enough
+        Dumb(_) => {},
+    };
+    match MyTy::Unit {
+        <Ty<'d>>::Struct {..} => {},
+        //~^ ERROR lifetime may not live long enough
+        <Ty<'e>>::Tuple (..) => {},
+        //~^ ERROR lifetime may not live long enough
+        <Ty<'f>>::Unit => {},
+        //~^ ERROR lifetime may not live long enough
+        Dumb(_) => {},
+    };
+}
+
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/normalization-2.stderr b/tests/ui/nll/user-annotations/normalization-2.stderr
new file mode 100644
index 00000000000..5299282ea15
--- /dev/null
+++ b/tests/ui/nll/user-annotations/normalization-2.stderr
@@ -0,0 +1,296 @@
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:43:12
+   |
+LL | fn test_local<'a>() {
+   |               -- lifetime `'a` defined here
+LL |     let _: Ty<'a> = MyTy::Unit;
+   |            ^^^^^^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:48:6
+   |
+LL | fn test_closure_sig<'a, 'b>() {
+   |                     -- lifetime `'a` defined here
+LL |     |_: Ty<'a>| {};
+   |      ^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:50:11
+   |
+LL | fn test_closure_sig<'a, 'b>() {
+   |                         -- lifetime `'b` defined here
+...
+LL |     || -> Option<Ty<'b>> { None };
+   |           ^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
+
+help: the following changes may resolve your lifetime errors
+   |
+   = help: replace `'a` with `'static`
+   = help: replace `'b` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:55:5
+   |
+LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
+   |              -- lifetime `'a` defined here
+LL |     <Ty<'a>>::method::<Ty<'static>>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:57:5
+   |
+LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
+   |                  -- lifetime `'b` defined here
+...
+LL |     <Ty<'static>>::method::<Ty<'b>>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:60:5
+   |
+LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
+   |                      -- lifetime `'c` defined here
+...
+LL |     <Ty<'c>>::trait_method::<Ty<'static>>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'c` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:62:5
+   |
+LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
+   |                          -- lifetime `'d` defined here
+...
+LL |     <Ty<'static>>::trait_method::<Ty<'d>>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'d` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:65:5
+   |
+LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
+   |                              -- lifetime `'e` defined here
+...
+LL |     <Ty<'e>>::CONST;
+   |     ^^^^^^^^^^^^^^^ requires that `'e` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:67:5
+   |
+LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
+   |                                  -- lifetime `'f` defined here
+...
+LL |     <Ty<'f>>::TRAIT_CONST;
+   |     ^^^^^^^^^^^^^^^^^^^^^ requires that `'f` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:75:5
+   |
+LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
+   |                                      -- lifetime `'g` defined here
+...
+LL |     MyTy::Unit::<Ty<'g>>;
+   |     ^^^^^^^^^^^^^^^^^^^^ requires that `'g` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:77:5
+   |
+LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() {
+   |                                          -- lifetime `'h` defined here
+...
+LL |     MyTy::<Ty<'h>>::Unit;
+   |     ^^^^^^^^^^^^^^^^^^^^ requires that `'h` must outlive `'static`
+
+help: the following changes may resolve your lifetime errors
+   |
+   = help: replace `'a` with `'static`
+   = help: replace `'b` with `'static`
+   = help: replace `'c` with `'static`
+   = help: replace `'d` with `'static`
+   = help: replace `'e` with `'static`
+   = help: replace `'f` with `'static`
+   = help: replace `'g` with `'static`
+   = help: replace `'h` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:82:5
+   |
+LL | fn test_call<'a, 'b, 'c>() {
+   |              -- lifetime `'a` defined here
+LL |     <Ty<'a>>::method::<Ty<'static>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:84:5
+   |
+LL | fn test_call<'a, 'b, 'c>() {
+   |                  -- lifetime `'b` defined here
+...
+LL |     <Ty<'static>>::method::<Ty<'b>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
+
+help: the following changes may resolve your lifetime errors
+   |
+   = help: replace `'a` with `'static`
+   = help: replace `'b` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:89:5
+   |
+LL | fn test_variants<'a, 'b, 'c>() {
+   |                  -- lifetime `'a` defined here
+LL |     <Ty<'a>>::Struct {};
+   |     ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:91:5
+   |
+LL | fn test_variants<'a, 'b, 'c>() {
+   |                      -- lifetime `'b` defined here
+...
+LL |     <Ty<'b>>::Tuple();
+   |     ^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:93:5
+   |
+LL | fn test_variants<'a, 'b, 'c>() {
+   |                          -- lifetime `'c` defined here
+...
+LL |     <Ty<'c>>::Unit;
+   |     ^^^^^^^^^^^^^^ requires that `'c` must outlive `'static`
+
+help: the following changes may resolve your lifetime errors
+   |
+   = help: replace `'a` with `'static`
+   = help: replace `'b` with `'static`
+   = help: replace `'c` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:98:7
+   |
+LL | fn test_method_call<'a, 'b>(x: MyTy<()>) {
+   |                     -- lifetime `'a` defined here
+LL |     x.method2::<Ty<'a>>();
+   |       ^^^^^^^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:100:7
+   |
+LL | fn test_method_call<'a, 'b>(x: MyTy<()>) {
+   |                         -- lifetime `'b` defined here
+...
+LL |     x.trait_method::<Ty<'b>>();
+   |       ^^^^^^^^^^^^ requires that `'b` must outlive `'static`
+
+help: the following changes may resolve your lifetime errors
+   |
+   = help: replace `'a` with `'static`
+   = help: replace `'b` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:117:5
+   |
+LL | fn test_struct_path<'a, 'b, 'c, 'd>() {
+   |                     -- lifetime `'a` defined here
+...
+LL |     MyTy::<Ty<'a>>::Struct {}; // without SelfTy
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:119:5
+   |
+LL | fn test_struct_path<'a, 'b, 'c, 'd>() {
+   |                         -- lifetime `'b` defined here
+...
+LL |     <Ty<'b> as Project>::Enum::Struct {}; // with SelfTy
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:123:5
+   |
+LL | fn test_struct_path<'a, 'b, 'c, 'd>() {
+   |                             -- lifetime `'c` defined here
+...
+LL |     Struct::<Ty<'c>> { x: None, }; // without SelfTy
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'c` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:125:5
+   |
+LL | fn test_struct_path<'a, 'b, 'c, 'd>() {
+   |                                 -- lifetime `'d` defined here
+...
+LL |     <Ty<'d> as Project>::Struct { x: None, }; // with SelfTy
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'d` must outlive `'static`
+
+help: the following changes may resolve your lifetime errors
+   |
+   = help: replace `'a` with `'static`
+   = help: replace `'b` with `'static`
+   = help: replace `'c` with `'static`
+   = help: replace `'d` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:132:9
+   |
+LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
+   |                 -- lifetime `'a` defined here
+...
+LL |         Struct::<Ty<'a>> {..} => {},
+   |         ^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:134:9
+   |
+LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
+   |                     -- lifetime `'b` defined here
+...
+LL |         Tuple::<Ty<'b>> (..) => {},
+   |         ^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:136:9
+   |
+LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
+   |                         -- lifetime `'c` defined here
+...
+LL |         Unit::<Ty<'c>> => {},
+   |         ^^^^^^^^^^^^^^ requires that `'c` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:141:9
+   |
+LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
+   |                             -- lifetime `'d` defined here
+...
+LL |         <Ty<'d>>::Struct {..} => {},
+   |         ^^^^^^^^^^^^^^^^^^^^^ requires that `'d` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:143:9
+   |
+LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
+   |                                 -- lifetime `'e` defined here
+...
+LL |         <Ty<'e>>::Tuple (..) => {},
+   |         ^^^^^^^^^^^^^^^^^^^^ requires that `'e` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-2.rs:145:9
+   |
+LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() {
+   |                                     -- lifetime `'f` defined here
+...
+LL |         <Ty<'f>>::Unit => {},
+   |         ^^^^^^^^^^^^^^ requires that `'f` must outlive `'static`
+
+help: the following changes may resolve your lifetime errors
+   |
+   = help: replace `'a` with `'static`
+   = help: replace `'b` with `'static`
+   = help: replace `'c` with `'static`
+   = help: replace `'d` with `'static`
+   = help: replace `'e` with `'static`
+   = help: replace `'f` with `'static`
+
+error: aborting due to 28 previous errors
+
diff --git a/tests/ui/nll/user-annotations/normalization-default.rs b/tests/ui/nll/user-annotations/normalization-default.rs
new file mode 100644
index 00000000000..fa52e6d857f
--- /dev/null
+++ b/tests/ui/nll/user-annotations/normalization-default.rs
@@ -0,0 +1,22 @@
+// check-fail
+
+trait Trait { type Assoc; }
+impl<'a> Trait for &'a () { type Assoc = &'a (); }
+
+struct MyTuple<T, U = <&'static () as Trait>::Assoc>(T, U);
+fn test_tuple(x: &(), y: &()) {
+    MyTuple::<_>((), x);
+    //~^ ERROR
+    let _: MyTuple::<_> = MyTuple((), y);
+    //~^ ERROR
+}
+
+struct MyStruct<T, U = <&'static () as Trait>::Assoc> { val: (T, U), }
+fn test_struct(x: &(), y: &()) {
+    MyStruct::<_> { val: ((), x) };
+    //~^ ERROR
+    let _: MyStruct::<_> = MyStruct { val: ((), y) };
+    //~^ ERROR
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/normalization-default.stderr b/tests/ui/nll/user-annotations/normalization-default.stderr
new file mode 100644
index 00000000000..6c73ac69254
--- /dev/null
+++ b/tests/ui/nll/user-annotations/normalization-default.stderr
@@ -0,0 +1,36 @@
+error: lifetime may not live long enough
+  --> $DIR/normalization-default.rs:8:22
+   |
+LL | fn test_tuple(x: &(), y: &()) {
+   |                  - let's call the lifetime of this reference `'1`
+LL |     MyTuple::<_>((), x);
+   |                      ^ this usage requires that `'1` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-default.rs:10:12
+   |
+LL | fn test_tuple(x: &(), y: &()) {
+   |                          - let's call the lifetime of this reference `'2`
+...
+LL |     let _: MyTuple::<_> = MyTuple((), y);
+   |            ^^^^^^^^^^^^ type annotation requires that `'2` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-default.rs:16:26
+   |
+LL | fn test_struct(x: &(), y: &()) {
+   |                   - let's call the lifetime of this reference `'1`
+LL |     MyStruct::<_> { val: ((), x) };
+   |                          ^^^^^^^ this usage requires that `'1` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-default.rs:18:12
+   |
+LL | fn test_struct(x: &(), y: &()) {
+   |                           - let's call the lifetime of this reference `'2`
+...
+LL |     let _: MyStruct::<_> = MyStruct { val: ((), y) };
+   |            ^^^^^^^^^^^^^ type annotation requires that `'2` must outlive `'static`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/nll/user-annotations/normalization-infer.rs b/tests/ui/nll/user-annotations/normalization-infer.rs
new file mode 100644
index 00000000000..8bfc272d4ba
--- /dev/null
+++ b/tests/ui/nll/user-annotations/normalization-infer.rs
@@ -0,0 +1,40 @@
+// Annnotations may contain projection types with inference variables as input.
+// Make sure we don't get ambiguities when normalizing them.
+
+// check-fail
+
+// Single impl.
+fn test1<A, B, C, D>(a: A, b: B, c: C) {
+    trait Tr { type Ty; }
+    impl<T: 'static> Tr for (T,) { type Ty = T; }
+
+    let _: <(_,) as Tr>::Ty = a; //~ ERROR type `A`
+    Some::<<(_,) as Tr>::Ty>(b); //~ ERROR type `B`
+    || -> <(_,) as Tr>::Ty { c }; //~ ERROR type `C`
+    |d: <(_,) as Tr>::Ty| -> D { d }; //~ ERROR type `D`
+}
+
+
+// Two impls. The selected impl depends on the actual type.
+fn test2<A, B, C>(a: A, b: B, c: C) {
+    trait Tr { type Ty; }
+    impl<T: 'static> Tr for (u8, T) { type Ty = T; }
+    impl<T>          Tr for (i8, T) { type Ty = T; }
+    type Alias<X, Y> = (<(X, Y) as Tr>::Ty, X);
+
+    fn temp() -> String { todo!() }
+
+    // `u8` impl, requires static.
+    let _: Alias<_, _> = (a, 0u8); //~ ERROR type `A`
+    Some::<Alias<_, _>>((b, 0u8)); //~ ERROR type `B`
+    || -> Alias<_, _> { (c, 0u8) }; //~ ERROR type `C`
+
+    let _: Alias<_, _> = (&temp(), 0u8); //~ ERROR temporary value
+    Some::<Alias<_, _>>((&temp(), 0u8)); //~ ERROR temporary value
+
+    // `i8` impl, no region constraints.
+    let _: Alias<_, _> = (&temp(), 0i8);
+    Some::<Alias<_, _>>((&temp(), 0i8));
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/normalization-infer.stderr b/tests/ui/nll/user-annotations/normalization-infer.stderr
new file mode 100644
index 00000000000..12854ab6816
--- /dev/null
+++ b/tests/ui/nll/user-annotations/normalization-infer.stderr
@@ -0,0 +1,101 @@
+error[E0310]: the parameter type `A` may not live long enough
+  --> $DIR/normalization-infer.rs:11:12
+   |
+LL |     let _: <(_,) as Tr>::Ty = a;
+   |            ^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn test1<A: 'static, B, C, D>(a: A, b: B, c: C) {
+   |           +++++++++
+
+error[E0310]: the parameter type `B` may not live long enough
+  --> $DIR/normalization-infer.rs:12:5
+   |
+LL |     Some::<<(_,) as Tr>::Ty>(b);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `B` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn test1<A, B: 'static, C, D>(a: A, b: B, c: C) {
+   |              +++++++++
+
+error[E0310]: the parameter type `C` may not live long enough
+  --> $DIR/normalization-infer.rs:13:11
+   |
+LL |     || -> <(_,) as Tr>::Ty { c };
+   |           ^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn test1<A, B, C: 'static, D>(a: A, b: B, c: C) {
+   |                 +++++++++
+
+error[E0310]: the parameter type `D` may not live long enough
+  --> $DIR/normalization-infer.rs:14:6
+   |
+LL |     |d: <(_,) as Tr>::Ty| -> D { d };
+   |      ^ ...so that the type `D` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn test1<A, B, C, D: 'static>(a: A, b: B, c: C) {
+   |                    +++++++++
+
+error[E0310]: the parameter type `A` may not live long enough
+  --> $DIR/normalization-infer.rs:28:12
+   |
+LL |     let _: Alias<_, _> = (a, 0u8);
+   |            ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn test2<A: 'static, B, C>(a: A, b: B, c: C) {
+   |           +++++++++
+
+error[E0310]: the parameter type `B` may not live long enough
+  --> $DIR/normalization-infer.rs:29:5
+   |
+LL |     Some::<Alias<_, _>>((b, 0u8));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `B` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn test2<A, B: 'static, C>(a: A, b: B, c: C) {
+   |              +++++++++
+
+error[E0310]: the parameter type `C` may not live long enough
+  --> $DIR/normalization-infer.rs:30:11
+   |
+LL |     || -> Alias<_, _> { (c, 0u8) };
+   |           ^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn test2<A, B, C: 'static>(a: A, b: B, c: C) {
+   |                 +++++++++
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/normalization-infer.rs:32:28
+   |
+LL |     let _: Alias<_, _> = (&temp(), 0u8);
+   |            -----------     ^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/normalization-infer.rs:33:27
+   |
+LL |     Some::<Alias<_, _>>((&temp(), 0u8));
+   |                         --^^^^^^------ - temporary value is freed at the end of this statement
+   |                         | |
+   |                         | creates a temporary value which is freed while still in use
+   |                         this usage requires that borrow lasts for `'static`
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0310, E0716.
+For more information about an error, try `rustc --explain E0310`.
diff --git a/tests/ui/nll/user-annotations/normalization-self.rs b/tests/ui/nll/user-annotations/normalization-self.rs
new file mode 100644
index 00000000000..c18760b53cf
--- /dev/null
+++ b/tests/ui/nll/user-annotations/normalization-self.rs
@@ -0,0 +1,26 @@
+// check-fail
+
+trait Trait { type Assoc; }
+impl<'a> Trait for &'a () { type Assoc = &'a (); }
+
+struct MyTuple<T>(T);
+impl MyTuple<<&'static () as Trait>::Assoc> {
+    fn test(x: &(), y: &()) {
+        Self(x);
+        //~^ ERROR
+        let _: Self = MyTuple(y);
+        //~^ ERROR
+    }
+}
+
+struct MyStruct<T> { val: T, }
+impl MyStruct<<&'static () as Trait>::Assoc> {
+    fn test(x: &(), y: &()) {
+        Self { val: x };
+        //~^ ERROR
+        let _: Self = MyStruct { val: y };
+        //~^ ERROR
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/normalization-self.stderr b/tests/ui/nll/user-annotations/normalization-self.stderr
new file mode 100644
index 00000000000..e231ed03c2e
--- /dev/null
+++ b/tests/ui/nll/user-annotations/normalization-self.stderr
@@ -0,0 +1,36 @@
+error: lifetime may not live long enough
+  --> $DIR/normalization-self.rs:9:14
+   |
+LL |     fn test(x: &(), y: &()) {
+   |                - let's call the lifetime of this reference `'1`
+LL |         Self(x);
+   |              ^ this usage requires that `'1` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-self.rs:11:16
+   |
+LL |     fn test(x: &(), y: &()) {
+   |                        - let's call the lifetime of this reference `'2`
+...
+LL |         let _: Self = MyTuple(y);
+   |                ^^^^ type annotation requires that `'2` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-self.rs:19:21
+   |
+LL |     fn test(x: &(), y: &()) {
+   |                - let's call the lifetime of this reference `'1`
+LL |         Self { val: x };
+   |                     ^ this usage requires that `'1` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-self.rs:21:16
+   |
+LL |     fn test(x: &(), y: &()) {
+   |                        - let's call the lifetime of this reference `'2`
+...
+LL |         let _: Self = MyStruct { val: y };
+   |                ^^^^ type annotation requires that `'2` must outlive `'static`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/nll/user-annotations/normalization.rs b/tests/ui/nll/user-annotations/normalization.rs
new file mode 100644
index 00000000000..c2e892f573c
--- /dev/null
+++ b/tests/ui/nll/user-annotations/normalization.rs
@@ -0,0 +1,17 @@
+// Test that we enforce a `&'static` requirement that is only visible
+// after normalization.
+
+trait Foo { type Out; }
+impl Foo for () { type Out = &'static u32; }
+impl<'a> Foo for &'a () { type Out = &'a u32; }
+
+fn main() {
+    let a = 22;
+    let _: <() as Foo>::Out = &a; //~ ERROR
+
+    let a = 22;
+    let _: <&'static () as Foo>::Out = &a; //~ ERROR
+
+    let a = 22;
+    let _: <&'_ () as Foo>::Out = &a;
+}
diff --git a/tests/ui/nll/user-annotations/normalization.stderr b/tests/ui/nll/user-annotations/normalization.stderr
new file mode 100644
index 00000000000..975cb4b66d9
--- /dev/null
+++ b/tests/ui/nll/user-annotations/normalization.stderr
@@ -0,0 +1,25 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/normalization.rs:10:31
+   |
+LL |     let _: <() as Foo>::Out = &a;
+   |            ----------------   ^^ borrowed value does not live long enough
+   |            |
+   |            type annotation requires that `a` is borrowed for `'static`
+...
+LL | }
+   | - `a` dropped here while still borrowed
+
+error[E0597]: `a` does not live long enough
+  --> $DIR/normalization.rs:13:40
+   |
+LL |     let _: <&'static () as Foo>::Out = &a;
+   |            -------------------------   ^^ borrowed value does not live long enough
+   |            |
+   |            type annotation requires that `a` is borrowed for `'static`
+...
+LL | }
+   | - `a` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/normalize-self-ty.rs b/tests/ui/nll/user-annotations/normalize-self-ty.rs
new file mode 100644
index 00000000000..df905c8786a
--- /dev/null
+++ b/tests/ui/nll/user-annotations/normalize-self-ty.rs
@@ -0,0 +1,23 @@
+// Regression test for #55183: check a case where the self type from
+// the inherent impl requires normalization to be equal to the
+// user-provided type.
+//
+// check-pass
+
+trait Mirror {
+    type Me;
+}
+
+impl<T> Mirror for T {
+    type Me = T;
+}
+
+struct Foo<A, B>(A, B);
+
+impl<A> Foo<A, <A as Mirror>::Me> {
+    fn m(_: A) { }
+}
+
+fn main() {
+    <Foo<&'static u32, &u32>>::m(&22);
+}
diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs b/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs
new file mode 100644
index 00000000000..59cd69c0ca5
--- /dev/null
+++ b/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs
@@ -0,0 +1,22 @@
+enum Foo<'a> {
+    Bar { field: &'a u32 }
+}
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo::Bar { field: &y };
+    //~^ ERROR `y` does not live long enough
+    let Foo::Bar::<'static> { field: _z } = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo::Bar { field: &y };
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::Bar::<'static> { field: _z } => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr b/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr
new file mode 100644
index 00000000000..a97e7a9fd46
--- /dev/null
+++ b/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr
@@ -0,0 +1,26 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_enum_variant.rs:7:33
+   |
+LL |     let foo = Foo::Bar { field: &y };
+   |                                 ^^ borrowed value does not live long enough
+LL |
+LL |     let Foo::Bar::<'static> { field: _z } = foo;
+   |         --------------------------------- type annotation requires that `y` is borrowed for `'static`
+LL | }
+   | - `y` dropped here while still borrowed
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_enum_variant.rs:14:33
+   |
+LL |     let foo = Foo::Bar { field: &y };
+   |                                 ^^ borrowed value does not live long enough
+...
+LL |         Foo::Bar::<'static> { field: _z } => {
+   |         --------------------------------- type annotation requires that `y` is borrowed for `'static`
+...
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs b/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs
new file mode 100644
index 00000000000..1586c4ea30c
--- /dev/null
+++ b/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs
@@ -0,0 +1,20 @@
+struct Foo<'a> { field: &'a u32 }
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo { field: &y };
+    //~^ ERROR `y` does not live long enough
+    let Foo::<'static> { field: _z } = foo;
+}
+
+fn in_main() {
+    let y = 22;
+    let foo = Foo { field: &y };
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::<'static> { field: _z } => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr b/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr
new file mode 100644
index 00000000000..408d7c2a5e2
--- /dev/null
+++ b/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr
@@ -0,0 +1,26 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_struct.rs:5:28
+   |
+LL |     let foo = Foo { field: &y };
+   |                            ^^ borrowed value does not live long enough
+LL |
+LL |     let Foo::<'static> { field: _z } = foo;
+   |         ---------------------------- type annotation requires that `y` is borrowed for `'static`
+LL | }
+   | - `y` dropped here while still borrowed
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_struct.rs:12:28
+   |
+LL |     let foo = Foo { field: &y };
+   |                            ^^ borrowed value does not live long enough
+...
+LL |         Foo::<'static> { field: _z } => {
+   |         ---------------------------- type annotation requires that `y` is borrowed for `'static`
+...
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs
new file mode 100644
index 00000000000..6fa59fdd8d8
--- /dev/null
+++ b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs
@@ -0,0 +1,22 @@
+enum Foo<'a> {
+    Bar(&'a u32)
+}
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo::Bar(&y);
+    //~^ ERROR `y` does not live long enough
+    let Foo::Bar::<'static>(_z) = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo::Bar(&y);
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::Bar::<'static>(_z) => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr
new file mode 100644
index 00000000000..920c906f63a
--- /dev/null
+++ b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr
@@ -0,0 +1,26 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_enum_variant.rs:7:24
+   |
+LL |     let foo = Foo::Bar(&y);
+   |                        ^^ borrowed value does not live long enough
+LL |
+LL |     let Foo::Bar::<'static>(_z) = foo;
+   |         ----------------------- type annotation requires that `y` is borrowed for `'static`
+LL | }
+   | - `y` dropped here while still borrowed
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_enum_variant.rs:14:24
+   |
+LL |     let foo = Foo::Bar(&y);
+   |                        ^^ borrowed value does not live long enough
+...
+LL |         Foo::Bar::<'static>(_z) => {
+   |         ----------------------- type annotation requires that `y` is borrowed for `'static`
+...
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs
new file mode 100644
index 00000000000..7486aab0e08
--- /dev/null
+++ b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs
@@ -0,0 +1,20 @@
+struct Foo<'a>(&'a u32);
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo(&y);
+    //~^ ERROR `y` does not live long enough
+    let Foo::<'static>(_z) = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo(&y);
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::<'static>(_z) => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr
new file mode 100644
index 00000000000..3f01638d847
--- /dev/null
+++ b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr
@@ -0,0 +1,26 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_struct.rs:5:19
+   |
+LL |     let foo = Foo(&y);
+   |                   ^^ borrowed value does not live long enough
+LL |
+LL |     let Foo::<'static>(_z) = foo;
+   |         ------------------ type annotation requires that `y` is borrowed for `'static`
+LL | }
+   | - `y` dropped here while still borrowed
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_struct.rs:12:19
+   |
+LL |     let foo = Foo(&y);
+   |                   ^^ borrowed value does not live long enough
+...
+LL |         Foo::<'static>(_z) => {
+   |         ------------------ type annotation requires that `y` is borrowed for `'static`
+...
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/patterns.rs b/tests/ui/nll/user-annotations/patterns.rs
new file mode 100644
index 00000000000..1f635d7f50c
--- /dev/null
+++ b/tests/ui/nll/user-annotations/patterns.rs
@@ -0,0 +1,136 @@
+// Test that various patterns also enforce types.
+
+fn variable_no_initializer() {
+    let x = 22;
+    let y: &'static u32;
+    y = &x; //~ ERROR
+}
+
+fn tuple_no_initializer() {
+
+
+    let x = 22;
+    let (y, z): (&'static u32, &'static u32);
+    y = &x; //~ ERROR
+}
+
+fn ref_with_ascribed_static_type() -> u32 {
+    // Check the behavior in some wacky cases.
+    let x = 22;
+    let y = &x; //~ ERROR
+    let ref z: &'static u32 = y;
+    **z
+}
+
+fn ref_with_ascribed_any_type() -> u32 {
+    let x = 22;
+    let y = &x;
+    let ref z: &u32 = y;
+    **z
+}
+
+struct Single<T> { value: T }
+
+fn struct_no_initializer() {
+
+
+    let x = 22;
+    let Single { value: y }: Single<&'static u32>;
+    y = &x; //~ ERROR
+}
+
+
+fn struct_no_initializer_must_normalize() {
+    trait Indirect { type Assoc; }
+    struct StaticU32;
+    impl Indirect for StaticU32 { type Assoc = &'static u32; }
+    struct Single2<T: Indirect> { value: <T as Indirect>::Assoc }
+
+    let x = 22;
+    let Single2 { value: mut _y }: Single2<StaticU32>;
+    _y = &x; //~ ERROR
+}
+
+fn variable_with_initializer() {
+    let x = 22;
+    let y: &'static u32 = &x; //~ ERROR
+}
+
+fn underscore_with_initializer() {
+    let x = 22;
+    let _: &'static u32 = &x; //~ ERROR
+
+    let _: Vec<&'static String> = vec![&String::new()];
+    //~^ ERROR temporary value dropped while borrowed [E0716]
+
+    let (_, a): (Vec<&'static String>, _) = (vec![&String::new()], 44);
+    //~^ ERROR temporary value dropped while borrowed [E0716]
+
+    let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44);
+    //~^ ERROR temporary value dropped while borrowed [E0716]
+}
+
+fn pair_underscores_with_initializer() {
+    let x = 22;
+    let (_, _): (&'static u32, u32) = (&x, 44); //~ ERROR
+}
+
+fn pair_variable_with_initializer() {
+    let x = 22;
+    let (y, _): (&'static u32, u32) = (&x, 44); //~ ERROR
+}
+
+fn struct_single_field_variable_with_initializer() {
+    let x = 22;
+    let Single { value: y }: Single<&'static u32> = Single { value: &x }; //~ ERROR
+}
+
+fn struct_single_field_underscore_with_initializer() {
+    let x = 22;
+    let Single { value: _ }: Single<&'static u32> = Single { value: &x }; //~ ERROR
+}
+
+struct Double<T> { value1: T, value2: T }
+
+fn struct_double_field_underscore_with_initializer() {
+    let x = 22;
+    let Double { value1: _, value2: _ }: Double<&'static u32> = Double {
+        value1: &x, //~ ERROR
+        value2: &44,
+    };
+}
+
+fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 {
+
+
+
+
+
+
+    let y: &'a u32 = &22;
+    y //~ ERROR
+}
+
+fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 {
+
+
+
+
+
+
+
+    let (y, _z): (&'a u32, u32) = (&22, 44);
+    y //~ ERROR
+}
+
+fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 {
+    let Single { value: y }: Single<&'a u32> = Single { value: &22 };
+    y //~ ERROR
+}
+
+fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
+    let (y, _z): (&'static u32, u32) = (x, 44); //~ ERROR
+    y
+}
+
+fn main() { }
diff --git a/tests/ui/nll/user-annotations/patterns.stderr b/tests/ui/nll/user-annotations/patterns.stderr
new file mode 100644
index 00000000000..de6f8f80fe2
--- /dev/null
+++ b/tests/ui/nll/user-annotations/patterns.stderr
@@ -0,0 +1,189 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:6:9
+   |
+LL |     let y: &'static u32;
+   |            ------------ type annotation requires that `x` is borrowed for `'static`
+LL |     y = &x;
+   |         ^^ borrowed value does not live long enough
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:14:9
+   |
+LL |     let (y, z): (&'static u32, &'static u32);
+   |                 ---------------------------- type annotation requires that `x` is borrowed for `'static`
+LL |     y = &x;
+   |         ^^ borrowed value does not live long enough
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:20:13
+   |
+LL |     let y = &x;
+   |             ^^ borrowed value does not live long enough
+LL |     let ref z: &'static u32 = y;
+   |                ------------ type annotation requires that `x` is borrowed for `'static`
+LL |     **z
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:39:9
+   |
+LL |     let Single { value: y }: Single<&'static u32>;
+   |                              -------------------- type annotation requires that `x` is borrowed for `'static`
+LL |     y = &x;
+   |         ^^ borrowed value does not live long enough
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:51:10
+   |
+LL |     let Single2 { value: mut _y }: Single2<StaticU32>;
+   |                                    ------------------ type annotation requires that `x` is borrowed for `'static`
+LL |     _y = &x;
+   |          ^^ borrowed value does not live long enough
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:56:27
+   |
+LL |     let y: &'static u32 = &x;
+   |            ------------   ^^ borrowed value does not live long enough
+   |            |
+   |            type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:61:27
+   |
+LL |     let _: &'static u32 = &x;
+   |            ------------   ^^ borrowed value does not live long enough
+   |            |
+   |            type annotation requires that `x` is borrowed for `'static`
+...
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/patterns.rs:63:41
+   |
+LL |     let _: Vec<&'static String> = vec![&String::new()];
+   |            --------------------         ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
+   |            |                            |
+   |            |                            creates a temporary value which is freed while still in use
+   |            type annotation requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/patterns.rs:66:52
+   |
+LL |     let (_, a): (Vec<&'static String>, _) = (vec![&String::new()], 44);
+   |                 -------------------------          ^^^^^^^^^^^^^      - temporary value is freed at the end of this statement
+   |                 |                                  |
+   |                 |                                  creates a temporary value which is freed while still in use
+   |                 type annotation requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/patterns.rs:69:53
+   |
+LL |     let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44);
+   |                  -------------------------          ^^^^^^^^^^^^^      - temporary value is freed at the end of this statement
+   |                  |                                  |
+   |                  |                                  creates a temporary value which is freed while still in use
+   |                  type annotation requires that borrow lasts for `'static`
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:75:40
+   |
+LL |     let (_, _): (&'static u32, u32) = (&x, 44);
+   |                 -------------------    ^^ borrowed value does not live long enough
+   |                 |
+   |                 type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:80:40
+   |
+LL |     let (y, _): (&'static u32, u32) = (&x, 44);
+   |                 -------------------    ^^ borrowed value does not live long enough
+   |                 |
+   |                 type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:85:69
+   |
+LL |     let Single { value: y }: Single<&'static u32> = Single { value: &x };
+   |                              --------------------                   ^^ borrowed value does not live long enough
+   |                              |
+   |                              type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:90:69
+   |
+LL |     let Single { value: _ }: Single<&'static u32> = Single { value: &x };
+   |                              --------------------                   ^^ borrowed value does not live long enough
+   |                              |
+   |                              type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/patterns.rs:98:17
+   |
+LL |     let Double { value1: _, value2: _ }: Double<&'static u32> = Double {
+   |                                          -------------------- type annotation requires that `x` is borrowed for `'static`
+LL |         value1: &x,
+   |                 ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: lifetime may not live long enough
+  --> $DIR/patterns.rs:111:5
+   |
+LL | fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 {
+   |                                           -- lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/patterns.rs:123:5
+   |
+LL | fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 {
+   |                                        -- lifetime `'a` defined here
+...
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/patterns.rs:128:5
+   |
+LL | fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 {
+   |                                         -- lifetime `'a` defined here
+LL |     let Single { value: y }: Single<&'a u32> = Single { value: &22 };
+LL |     y
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/patterns.rs:132:18
+   |
+LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
+   |                            -- lifetime `'a` defined here
+LL |     let (y, _z): (&'static u32, u32) = (x, 44);
+   |                  ^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 19 previous errors
+
+Some errors have detailed explanations: E0597, E0716.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/promoted-annotation.rs b/tests/ui/nll/user-annotations/promoted-annotation.rs
new file mode 100644
index 00000000000..b92f8bfd23b
--- /dev/null
+++ b/tests/ui/nll/user-annotations/promoted-annotation.rs
@@ -0,0 +1,10 @@
+// Test that type annotations are checked in promoted constants correctly.
+
+fn foo<'a>() {
+    let x = 0;
+    let f = &drop::<&'a i32>;
+    f(&x);
+    //~^ ERROR `x` does not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/promoted-annotation.stderr b/tests/ui/nll/user-annotations/promoted-annotation.stderr
new file mode 100644
index 00000000000..cb99a6a369d
--- /dev/null
+++ b/tests/ui/nll/user-annotations/promoted-annotation.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/promoted-annotation.rs:6:7
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let x = 0;
+LL |     let f = &drop::<&'a i32>;
+   |             ---------------- assignment requires that `x` is borrowed for `'a`
+LL |     f(&x);
+   |       ^^ borrowed value does not live long enough
+LL |
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/type-annotation-with-hrtb.rs b/tests/ui/nll/user-annotations/type-annotation-with-hrtb.rs
new file mode 100644
index 00000000000..1f7c060386b
--- /dev/null
+++ b/tests/ui/nll/user-annotations/type-annotation-with-hrtb.rs
@@ -0,0 +1,33 @@
+// Regression test for issue #69490
+
+// check-pass
+
+pub trait Trait<T> {
+    const S: &'static str;
+}
+
+impl<T> Trait<()> for T
+where
+    T: for<'a> Trait<&'a ()>,
+{
+    // Use of `T::S` here caused an ICE
+    const S: &'static str = T::S;
+}
+
+// Some similar cases that didn't ICE:
+
+impl<'a, T> Trait<()> for (T,)
+where
+    T: Trait<&'a ()>,
+{
+    const S: &'static str = T::S;
+}
+
+impl<T> Trait<()> for [T; 1]
+where
+    T: Trait<for<'a> fn(&'a ())>,
+{
+    const S: &'static str = T::S;
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/type_ascription_static_lifetime.rs b/tests/ui/nll/user-annotations/type_ascription_static_lifetime.rs
new file mode 100644
index 00000000000..88d646dee7c
--- /dev/null
+++ b/tests/ui/nll/user-annotations/type_ascription_static_lifetime.rs
@@ -0,0 +1,7 @@
+#![allow(warnings)]
+#![feature(type_ascription)]
+
+fn main() {
+    let x = 22_u32;
+    let y: &u32 = type_ascribe!(&x, &'static u32); //~ ERROR E0597
+}
diff --git a/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr b/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr
new file mode 100644
index 00000000000..ccbf3c1d927
--- /dev/null
+++ b/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/type_ascription_static_lifetime.rs:6:33
+   |
+LL |     let y: &u32 = type_ascribe!(&x, &'static u32);
+   |                   --------------^^---------------
+   |                   |             |
+   |                   |             borrowed value does not live long enough
+   |                   type annotation requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/nll/user-annotations/wf-self-type.rs b/tests/ui/nll/user-annotations/wf-self-type.rs
new file mode 100644
index 00000000000..539226aabd7
--- /dev/null
+++ b/tests/ui/nll/user-annotations/wf-self-type.rs
@@ -0,0 +1,13 @@
+struct Foo<'a, 'b: 'a>(&'a &'b ());
+
+impl<'a, 'b> Foo<'a, 'b> {
+    fn xmute(a: &'b ()) -> &'a () {
+        unreachable!()
+    }
+}
+
+pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
+    Foo::xmute(u) //~ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/nll/user-annotations/wf-self-type.stderr b/tests/ui/nll/user-annotations/wf-self-type.stderr
new file mode 100644
index 00000000000..1d3ae7cfbd7
--- /dev/null
+++ b/tests/ui/nll/user-annotations/wf-self-type.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+  --> $DIR/wf-self-type.rs:10:5
+   |
+LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
+   |            --  -- lifetime `'b` defined here
+   |            |
+   |            lifetime `'a` defined here
+LL |     Foo::xmute(u)
+   |     ^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to previous error
+