From 39a03779f8412c776cebaca7173369dbc0025d50 Mon Sep 17 00:00:00 2001
From: lcnr <rust@lcnr.de>
Date: Thu, 28 Apr 2022 13:48:54 +0200
Subject: [PATCH] correctly deal with user type ascriptions in pat

---
 compiler/rustc_middle/src/thir.rs             | 50 +++-------------
 .../rustc_mir_build/src/build/matches/mod.rs  | 59 +++++++------------
 .../src/build/matches/simplify.rs             |  5 +-
 compiler/rustc_mir_build/src/thir/cx/block.rs |  9 ++-
 .../rustc_mir_build/src/thir/pattern/mod.rs   | 42 ++++++-------
 .../ui/hr-subtype/placeholder-pattern-fail.rs | 27 +++++++++
 .../placeholder-pattern-fail.stderr           | 42 +++++++++++++
 src/test/ui/hr-subtype/placeholder-pattern.rs | 18 ++++++
 src/test/ui/lifetimes/re-empty-in-error.rs    | 10 ++++
 .../ui/lifetimes/re-empty-in-error.stderr     | 15 +++++
 src/test/ui/nll/issue-57280-1-flipped.rs      | 23 ++++++++
 src/test/ui/nll/issue-57280-1-flipped.stderr  | 11 ++++
 12 files changed, 208 insertions(+), 103 deletions(-)
 create mode 100644 src/test/ui/hr-subtype/placeholder-pattern-fail.rs
 create mode 100644 src/test/ui/hr-subtype/placeholder-pattern-fail.stderr
 create mode 100644 src/test/ui/hr-subtype/placeholder-pattern.rs
 create mode 100644 src/test/ui/lifetimes/re-empty-in-error.rs
 create mode 100644 src/test/ui/lifetimes/re-empty-in-error.stderr
 create mode 100644 src/test/ui/nll/issue-57280-1-flipped.rs
 create mode 100644 src/test/ui/nll/issue-57280-1-flipped.stderr

diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 26e070af764..b99e7573000 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -18,15 +18,11 @@ use rustc_index::vec::IndexVec;
 use rustc_middle::infer::canonical::Canonical;
 use rustc_middle::middle::region;
 use rustc_middle::mir::interpret::AllocId;
-use rustc_middle::mir::{
-    self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp, UserTypeProjection,
-};
+use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp};
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::CanonicalUserTypeAnnotation;
 use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts, UserType};
-use rustc_middle::ty::{
-    CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
-};
 use rustc_span::{Span, Symbol, DUMMY_SP};
 use rustc_target::abi::VariantIdx;
 use rustc_target::asm::InlineAsmRegOrRegClass;
@@ -540,13 +536,13 @@ pub enum BindingMode {
     ByRef(BorrowKind),
 }
 
-#[derive(Clone, Debug, PartialEq, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub struct FieldPat<'tcx> {
     pub field: Field,
     pub pattern: Pat<'tcx>,
 }
 
-#[derive(Clone, Debug, PartialEq, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub struct Pat<'tcx> {
     pub ty: Ty<'tcx>,
     pub span: Span,
@@ -559,37 +555,10 @@ impl<'tcx> Pat<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
-pub struct PatTyProj<'tcx> {
-    pub user_ty: CanonicalUserType<'tcx>,
-}
-
-impl<'tcx> PatTyProj<'tcx> {
-    pub fn from_user_type(user_annotation: CanonicalUserType<'tcx>) -> Self {
-        Self { user_ty: user_annotation }
-    }
-
-    pub fn user_ty(
-        self,
-        annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
-        inferred_ty: Ty<'tcx>,
-        span: Span,
-    ) -> UserTypeProjection {
-        UserTypeProjection {
-            base: annotations.push(CanonicalUserTypeAnnotation {
-                span,
-                user_ty: self.user_ty,
-                inferred_ty,
-            }),
-            projs: Vec::new(),
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub struct Ascription<'tcx> {
-    pub user_ty: PatTyProj<'tcx>,
-    /// Variance to use when relating the type `user_ty` to the **type of the value being
+    pub annotation: CanonicalUserTypeAnnotation<'tcx>,
+    /// Variance to use when relating the `user_ty` to the **type of the value being
     /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
     /// have a type that is some subtype of the ascribed type.
     ///
@@ -608,12 +577,11 @@ pub struct Ascription<'tcx> {
     /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
     /// of the old type-check for now. See #57280 for details.
     pub variance: ty::Variance,
-    pub user_ty_span: Span,
 }
 
-#[derive(Clone, Debug, PartialEq, HashStable)]
+#[derive(Clone, Debug, HashStable)]
 pub enum PatKind<'tcx> {
-    /// A wildward pattern: `_`.
+    /// A wildcard pattern: `_`.
     Wild,
 
     AscribeUserType {
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 05b1342cf8c..6225193ea1a 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -523,8 +523,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             },
                         ..
                     },
-                ascription:
-                    thir::Ascription { user_ty: pat_ascription_ty, variance: _, user_ty_span },
+                ascription: thir::Ascription { annotation, variance: _ },
             } => {
                 let place =
                     self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
@@ -535,18 +534,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let cause_let = FakeReadCause::ForLet(None);
                 self.cfg.push_fake_read(block, pattern_source_info, cause_let, place);
 
-                let ty_source_info = self.source_info(user_ty_span);
-                let user_ty = pat_ascription_ty.user_ty(
-                    &mut self.canonical_user_type_annotations,
-                    place.ty(&self.local_decls, self.tcx).ty,
-                    ty_source_info.span,
-                );
+                let ty_source_info = self.source_info(annotation.span);
+
+                let base = self.canonical_user_type_annotations.push(annotation);
                 self.cfg.push(
                     block,
                     Statement {
                         source_info: ty_source_info,
                         kind: StatementKind::AscribeUserType(
-                            Box::new((place, user_ty)),
+                            Box::new((place, UserTypeProjection { base, projs: Vec::new() })),
                             // We always use invariant as the variance here. This is because the
                             // variance field from the ascription refers to the variance to use
                             // when applying the type to the value being matched, but this
@@ -784,7 +780,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             PatKind::AscribeUserType {
                 ref subpattern,
-                ascription: thir::Ascription { ref user_ty, user_ty_span, variance: _ },
+                ascription: thir::Ascription { ref annotation, variance: _ },
             } => {
                 // This corresponds to something like
                 //
@@ -794,16 +790,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 //
                 // Note that the variance doesn't apply here, as we are tracking the effect
                 // of `user_ty` on any bindings contained with subpattern.
-                let annotation = CanonicalUserTypeAnnotation {
-                    span: user_ty_span,
-                    user_ty: user_ty.user_ty,
-                    inferred_ty: subpattern.ty,
-                };
+
                 let projection = UserTypeProjection {
-                    base: self.canonical_user_type_annotations.push(annotation),
+                    base: self.canonical_user_type_annotations.push(annotation.clone()),
                     projs: Vec::new(),
                 };
-                let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span);
+                let subpattern_user_ty =
+                    pattern_user_ty.push_projection(&projection, annotation.span);
                 self.visit_primary_bindings(subpattern, subpattern_user_ty, f)
             }
 
@@ -927,9 +920,8 @@ struct Binding<'tcx> {
 /// influence region inference.
 #[derive(Clone, Debug)]
 struct Ascription<'tcx> {
-    span: Span,
     source: Place<'tcx>,
-    user_ty: PatTyProj<'tcx>,
+    annotation: CanonicalUserTypeAnnotation<'tcx>,
     variance: ty::Variance,
 }
 
@@ -1858,7 +1850,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             parent_bindings
                 .iter()
                 .flat_map(|(_, ascriptions)| ascriptions)
-                .chain(&candidate.ascriptions),
+                .cloned()
+                .chain(candidate.ascriptions),
         );
 
         // rust-lang/rust#27282: The `autoref` business deserves some
@@ -2062,32 +2055,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
     /// Append `AscribeUserType` statements onto the end of `block`
     /// for each ascription
-    fn ascribe_types<'b>(
+    fn ascribe_types(
         &mut self,
         block: BasicBlock,
-        ascriptions: impl IntoIterator<Item = &'b Ascription<'tcx>>,
-    ) where
-        'tcx: 'b,
-    {
+        ascriptions: impl IntoIterator<Item = Ascription<'tcx>>,
+    ) {
         for ascription in ascriptions {
-            let source_info = self.source_info(ascription.span);
+            let source_info = self.source_info(ascription.annotation.span);
 
-            debug!(
-                "adding user ascription at span {:?} of place {:?} and {:?}",
-                source_info.span, ascription.source, ascription.user_ty,
-            );
-
-            let user_ty = ascription.user_ty.user_ty(
-                &mut self.canonical_user_type_annotations,
-                ascription.source.ty(&self.local_decls, self.tcx).ty,
-                source_info.span,
-            );
+            let base = self.canonical_user_type_annotations.push(ascription.annotation);
             self.cfg.push(
                 block,
                 Statement {
                     source_info,
                     kind: StatementKind::AscribeUserType(
-                        Box::new((ascription.source, user_ty)),
+                        Box::new((
+                            ascription.source,
+                            UserTypeProjection { base, projs: Vec::new() },
+                        )),
                         ascription.variance,
                     ),
                 },
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index 895df5808db..b4a0c965d6b 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -152,15 +152,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         match *match_pair.pattern.kind {
             PatKind::AscribeUserType {
                 ref subpattern,
-                ascription: thir::Ascription { variance, user_ty, user_ty_span },
+                ascription: thir::Ascription { ref annotation, variance },
             } => {
                 // Apply the type ascription to the value at `match_pair.place`, which is the
                 if let Ok(place_resolved) =
                     match_pair.place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
                 {
                     candidate.ascriptions.push(Ascription {
-                        span: user_ty_span,
-                        user_ty,
+                        annotation: annotation.clone(),
                         source: place_resolved.into_place(self.tcx, self.typeck_results),
                         variance,
                     });
diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs
index 2d9b5c1d98a..ad1d7daec95 100644
--- a/compiler/rustc_mir_build/src/thir/cx/block.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/block.rs
@@ -6,6 +6,7 @@ use rustc_middle::thir::*;
 use rustc_middle::ty;
 
 use rustc_index::vec::Idx;
+use rustc_middle::ty::CanonicalUserTypeAnnotation;
 
 impl<'tcx> Cx<'tcx> {
     crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block {
@@ -80,13 +81,17 @@ impl<'tcx> Cx<'tcx> {
                                 self.typeck_results.user_provided_types().get(ty.hir_id)
                             {
                                 debug!("mirror_stmts: user_ty={:?}", user_ty);
+                                let annotation = CanonicalUserTypeAnnotation {
+                                    user_ty,
+                                    span: ty.span,
+                                    inferred_ty: self.typeck_results.node_type(ty.hir_id),
+                                };
                                 pattern = Pat {
                                     ty: pattern.ty,
                                     span: pattern.span,
                                     kind: Box::new(PatKind::AscribeUserType {
                                         ascription: Ascription {
-                                            user_ty: PatTyProj::from_user_type(user_ty),
-                                            user_ty_span: ty.span,
+                                            annotation,
                                             variance: ty::Variance::Covariant,
                                         },
                                         subpattern: pattern,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 55d84782c48..5d7a4215c57 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -19,8 +19,9 @@ use rustc_middle::mir::interpret::{get_slice_bytes, ConstValue};
 use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInput};
 use rustc_middle::mir::{self, UserTypeProjection};
 use rustc_middle::mir::{BorrowKind, Field, Mutability};
-use rustc_middle::thir::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange, PatTyProj};
+use rustc_middle::thir::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange};
 use rustc_middle::ty::subst::{GenericArg, SubstsRef};
+use rustc_middle::ty::CanonicalUserTypeAnnotation;
 use rustc_middle::ty::{self, AdtDef, ConstKind, DefIdTree, Region, Ty, TyCtxt, UserType};
 use rustc_span::{Span, Symbol};
 
@@ -227,7 +228,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 for end in &[lo, hi] {
                     if let Some((_, Some(ascription))) = end {
                         let subpattern = Pat { span: pat.span, ty, kind: Box::new(kind) };
-                        kind = PatKind::AscribeUserType { ascription: *ascription, subpattern };
+                        kind =
+                            PatKind::AscribeUserType { ascription: ascription.clone(), subpattern };
                     }
                 }
 
@@ -432,13 +434,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
         if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
             debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span);
+            let annotation = CanonicalUserTypeAnnotation {
+                user_ty,
+                span,
+                inferred_ty: self.typeck_results.node_type(hir_id),
+            };
             kind = PatKind::AscribeUserType {
                 subpattern: Pat { span, ty, kind: Box::new(kind) },
-                ascription: Ascription {
-                    user_ty: PatTyProj::from_user_type(user_ty),
-                    user_ty_span: span,
-                    variance: ty::Variance::Covariant,
-                },
+                ascription: Ascription { annotation, variance: ty::Variance::Covariant },
             };
         }
 
@@ -499,18 +502,21 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 }
 
                 let user_provided_types = self.typeck_results().user_provided_types();
-                if let Some(u_ty) = user_provided_types.get(id) {
-                    let user_ty = PatTyProj::from_user_type(*u_ty);
+                if let Some(&user_ty) = user_provided_types.get(id) {
+                    let annotation = CanonicalUserTypeAnnotation {
+                        user_ty,
+                        span,
+                        inferred_ty: self.typeck_results().node_type(id),
+                    };
                     Pat {
                         span,
                         kind: Box::new(PatKind::AscribeUserType {
                             subpattern: pattern,
                             ascription: Ascription {
+                                annotation,
                                 /// Note that use `Contravariant` here. See the
                                 /// `variance` field documentation for details.
                                 variance: ty::Variance::Contravariant,
-                                user_ty,
-                                user_ty_span: span,
                             },
                         }),
                         ty: const_.ty(),
@@ -645,7 +651,7 @@ impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option<T> {
     }
 }
 
-macro_rules! CloneImpls {
+macro_rules! ClonePatternFoldableImpls {
     (<$lt_tcx:tt> $($ty:ty),+) => {
         $(
             impl<$lt_tcx> PatternFoldable<$lt_tcx> for $ty {
@@ -657,11 +663,11 @@ macro_rules! CloneImpls {
     }
 }
 
-CloneImpls! { <'tcx>
+ClonePatternFoldableImpls! { <'tcx>
     Span, Field, Mutability, Symbol, hir::HirId, usize, ty::Const<'tcx>,
     Region<'tcx>, Ty<'tcx>, BindingMode, AdtDef<'tcx>,
     SubstsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>,
-    UserTypeProjection, PatTyProj<'tcx>
+    UserTypeProjection, CanonicalUserTypeAnnotation<'tcx>
 }
 
 impl<'tcx> PatternFoldable<'tcx> for FieldPat<'tcx> {
@@ -694,14 +700,10 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> {
             PatKind::Wild => PatKind::Wild,
             PatKind::AscribeUserType {
                 ref subpattern,
-                ascription: Ascription { variance, ref user_ty, user_ty_span },
+                ascription: Ascription { ref annotation, variance },
             } => PatKind::AscribeUserType {
                 subpattern: subpattern.fold_with(folder),
-                ascription: Ascription {
-                    user_ty: user_ty.fold_with(folder),
-                    variance,
-                    user_ty_span,
-                },
+                ascription: Ascription { annotation: annotation.fold_with(folder), variance },
             },
             PatKind::Binding { mutability, name, mode, var, ty, ref subpattern, is_primary } => {
                 PatKind::Binding {
diff --git a/src/test/ui/hr-subtype/placeholder-pattern-fail.rs b/src/test/ui/hr-subtype/placeholder-pattern-fail.rs
new file mode 100644
index 00000000000..3b5b075cb58
--- /dev/null
+++ b/src/test/ui/hr-subtype/placeholder-pattern-fail.rs
@@ -0,0 +1,27 @@
+// Check that incorrect higher ranked subtyping
+// causes an error.
+struct Inv<'a>(fn(&'a ()) -> &'a ());
+fn hr_subtype<'c>(f: for<'a, 'b> fn(Inv<'a>, Inv<'a>)) {
+    // ok
+    let _: for<'a> fn(Inv<'a>, Inv<'a>) = f;
+    let sub: for<'a> fn(Inv<'a>, Inv<'a>) = f;
+    // no
+    let _: for<'a, 'b> fn(Inv<'a>, Inv<'b>) = sub;
+    //~^ ERROR mismatched types
+}
+
+fn simple1<'c>(x: (&'c i32,)) {
+    let _x: (&'static i32,) = x;
+    //~^ ERROR mismatched types
+}
+
+fn simple2<'c>(x: (&'c i32,)) {
+    let _: (&'static i32,) = x;
+    //~^ ERROR mismatched types
+}
+
+fn main() {
+    hr_subtype(|_, _| {});
+    simple1((&3,));
+    simple2((&3,));
+}
diff --git a/src/test/ui/hr-subtype/placeholder-pattern-fail.stderr b/src/test/ui/hr-subtype/placeholder-pattern-fail.stderr
new file mode 100644
index 00000000000..7bd5308052b
--- /dev/null
+++ b/src/test/ui/hr-subtype/placeholder-pattern-fail.stderr
@@ -0,0 +1,42 @@
+error[E0308]: mismatched types
+  --> $DIR/placeholder-pattern-fail.rs:9:47
+   |
+LL |     let _: for<'a, 'b> fn(Inv<'a>, Inv<'b>) = sub;
+   |                                               ^^^ one type is more general than the other
+   |
+   = note: expected fn pointer `for<'a, 'b> fn(Inv<'a>, Inv<'b>)`
+              found fn pointer `for<'a> fn(Inv<'a>, Inv<'a>)`
+
+error[E0308]: mismatched types
+  --> $DIR/placeholder-pattern-fail.rs:14:31
+   |
+LL |     let _x: (&'static i32,) = x;
+   |                               ^ lifetime mismatch
+   |
+   = note: expected tuple `(&'static i32,)`
+              found tuple `(&'c i32,)`
+note: the lifetime `'c` as defined here...
+  --> $DIR/placeholder-pattern-fail.rs:13:12
+   |
+LL | fn simple1<'c>(x: (&'c i32,)) {
+   |            ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/placeholder-pattern-fail.rs:19:30
+   |
+LL |     let _: (&'static i32,) = x;
+   |                              ^ lifetime mismatch
+   |
+   = note: expected tuple `(&'static i32,)`
+              found tuple `(&'c i32,)`
+note: the lifetime `'c` as defined here...
+  --> $DIR/placeholder-pattern-fail.rs:18:12
+   |
+LL | fn simple2<'c>(x: (&'c i32,)) {
+   |            ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/placeholder-pattern.rs b/src/test/ui/hr-subtype/placeholder-pattern.rs
new file mode 100644
index 00000000000..061e66e54d2
--- /dev/null
+++ b/src/test/ui/hr-subtype/placeholder-pattern.rs
@@ -0,0 +1,18 @@
+// check-pass
+// Check that higher ranked subtyping correctly works when using
+// placeholder patterns.
+fn hr_subtype<'c>(f: for<'a, 'b> fn(&'a (), &'b ())) {
+    let _: for<'a> fn(&'a (), &'a ()) = f;
+    let _: for<'a, 'b> fn(&'a (), &'b ()) = f;
+    let _: for<'a> fn(&'a (), &'c ()) = f;
+    let _: fn(&'c (), &'c ()) = f;
+}
+
+fn simple<'c>(x: (&'static i32,)) {
+    let _: (&'c i32,) = x;
+}
+
+fn main() {
+    hr_subtype(|_, _| {});
+    simple((&3,));
+}
diff --git a/src/test/ui/lifetimes/re-empty-in-error.rs b/src/test/ui/lifetimes/re-empty-in-error.rs
new file mode 100644
index 00000000000..41c3718592d
--- /dev/null
+++ b/src/test/ui/lifetimes/re-empty-in-error.rs
@@ -0,0 +1,10 @@
+// We didn't have a single test mentioning
+// `ReEmpty` and this test changes that.
+fn foo<'a>(_a: &'a u32) where for<'b> &'b (): 'a {
+    //~^ NOTE type must outlive the empty lifetime as required by this binding
+}
+
+fn main() {
+    foo(&10);
+    //~^ ERROR the type `&'b ()` does not fulfill the required lifetime
+}
diff --git a/src/test/ui/lifetimes/re-empty-in-error.stderr b/src/test/ui/lifetimes/re-empty-in-error.stderr
new file mode 100644
index 00000000000..227e3ca6139
--- /dev/null
+++ b/src/test/ui/lifetimes/re-empty-in-error.stderr
@@ -0,0 +1,15 @@
+error[E0477]: the type `&'b ()` does not fulfill the required lifetime
+  --> $DIR/re-empty-in-error.rs:8:5
+   |
+LL |     foo(&10);
+   |     ^^^
+   |
+note: type must outlive the empty lifetime as required by this binding
+  --> $DIR/re-empty-in-error.rs:3:47
+   |
+LL | fn foo<'a>(_a: &'a u32) where for<'b> &'b (): 'a {
+   |                                               ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0477`.
diff --git a/src/test/ui/nll/issue-57280-1-flipped.rs b/src/test/ui/nll/issue-57280-1-flipped.rs
new file mode 100644
index 00000000000..ad4b8dcfde4
--- /dev/null
+++ b/src/test/ui/nll/issue-57280-1-flipped.rs
@@ -0,0 +1,23 @@
+// This test should compile, as the lifetimes
+// in matches don't really matter.
+//
+// We currently use contravariance when checking the
+// type of match arms.
+
+trait Foo<'a> {
+    const C: &'a u32;
+}
+
+impl<'a, T> Foo<'a> for T {
+    const C: &'a u32 = &22;
+}
+
+fn foo<'a>(x: &'static u32) {
+    match x {
+        <() as Foo<'a>>::C => { }
+        //~^ ERROR lifetime may not live long enough
+        &_ => { }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-57280-1-flipped.stderr b/src/test/ui/nll/issue-57280-1-flipped.stderr
new file mode 100644
index 00000000000..7a2135a2ade
--- /dev/null
+++ b/src/test/ui/nll/issue-57280-1-flipped.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-57280-1-flipped.rs:17:9
+   |
+LL | fn foo<'a>(x: &'static u32) {
+   |        -- lifetime `'a` defined here
+LL |     match x {
+LL |         <() as Foo<'a>>::C => { }
+   |         ^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+