about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAaron Hill <aa1ronham@gmail.com>2021-09-25 13:04:00 -0500
committerAaron Hill <aa1ronham@gmail.com>2021-09-25 13:04:00 -0500
commit78013f296acd79af84dede7dae1580fd36480c7c (patch)
tree3bc0d7fb7debb15d7f534f03a92e98f67f0f12dc
parent63cc2bb3d07d6c726dfcdc5f95cbe5ed4760641a (diff)
downloadrust-78013f296acd79af84dede7dae1580fd36480c7c.tar.gz
rust-78013f296acd79af84dede7dae1580fd36480c7c.zip
Don't anonymize bound region names during typeck
Once this anonymization has performed, we have no
way of recovering the original names during NLL
borrow checking. Keeping the original names allows
error messages in full NLL mode to contain the original
bound region names.

As a result, the typeck results may contain types that
differ only in the names used for their bound regions. However,
anonimization of bound regions does not guarantee that
all distinct types are unqual (e.g. not subtypes of each other).
For example, `for<'a> fn(&'a u32, &'a u32)` and
`for<'b, 'c> fn(&'b u32, &'c u32)` are subtypes of each other,
as explained here:

https://github.com/rust-lang/rust/blob/63cc2bb3d07d6c726dfcdc5f95cbe5ed4760641a/compiler/rustc_infer/src/infer/nll_relate/mod.rs#L682-L690

Therefore, any code handling types with higher-ranked regions already
needs to handle the case where two distinct `Ty`s are 'actually'
equal.
-rw-r--r--compiler/rustc_typeck/src/check/writeback.rs28
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr4
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr2
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr8
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr4
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-object.nll.stderr8
-rw-r--r--src/test/ui/nll/relate_tys/fn-subtype.stderr2
-rw-r--r--src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr4
-rw-r--r--src/test/ui/nll/relate_tys/trait-hrtb.stderr2
-rw-r--r--src/test/ui/rfc1623.nll.stderr8
10 files changed, 48 insertions, 22 deletions
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index c57ec9ef78f..5e080879253 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -732,6 +732,26 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
     }
 }
 
+struct EraseEarlyRegions<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> TypeFolder<'tcx> for EraseEarlyRegions<'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        if ty.has_type_flags(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
+            ty.super_fold_with(self)
+        } else {
+            ty
+        }
+    }
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        if let ty::ReLateBound(..) = r { r } else { self.tcx.lifetimes.re_erased }
+    }
+}
+
 impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
     fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
         self.tcx
@@ -739,7 +759,13 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match self.infcx.fully_resolve(t) {
-            Ok(t) => self.infcx.tcx.erase_regions(t),
+            Ok(t) => {
+                // Do not anonymize late-bound regions
+                // (e.g. keep `for<'a>` named `for<'a>`).
+                // This allows NLL to generate error messages that
+                // refer to the higher-ranked lifetime names written by the user.
+                EraseEarlyRegions { tcx: self.infcx.tcx }.fold_ty(t)
+            }
             Err(_) => {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
                 self.report_type_error(t);
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr
index 439a113ef38..87d826021b7 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr
@@ -8,8 +8,8 @@ LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u3
 LL | | for<'a>    fn(&'a u32, &'a u32) -> &'a u32) }
    | |_____________________________________________- in this macro invocation
    |
-   = note: expected enum `Option<for<'r, 's> fn(&'r u32, &'s u32) -> &'r u32>`
-              found enum `Option<for<'r> fn(&'r u32, &'r u32) -> &'r u32>`
+   = note: expected enum `Option<for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32>`
+              found enum `Option<for<'a> fn(&'a u32, &'a u32) -> &'a u32>`
    = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr
index 61b3f0ca284..bd97f6f0906 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr
@@ -8,7 +8,7 @@ LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
 LL | | fn(&'x u32)) }
    | |______________- in this macro invocation
    |
-   = note: expected enum `Option<for<'r> fn(&'r u32)>`
+   = note: expected enum `Option<for<'a> fn(&'a u32)>`
               found enum `Option<fn(&u32)>`
    = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr
index 75e2ba58f33..874909bf486 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr
@@ -8,8 +8,8 @@ LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
 LL | | for<'a>    fn(Inv<'a>, Inv<'a>)) }
    | |__________________________________- in this macro invocation
    |
-   = note: expected enum `Option<for<'r, 's> fn(Inv<'r>, Inv<'s>)>`
-              found enum `Option<for<'r> fn(Inv<'r>, Inv<'r>)>`
+   = note: expected enum `Option<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>`
+              found enum `Option<for<'a> fn(Inv<'a>, Inv<'a>)>`
    = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0308]: mismatched types
@@ -22,8 +22,8 @@ LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
 LL | | for<'a>    fn(Inv<'a>, Inv<'a>)) }
    | |__________________________________- in this macro invocation
    |
-   = note: expected enum `Option<for<'r, 's> fn(Inv<'r>, Inv<'s>)>`
-              found enum `Option<for<'r> fn(Inv<'r>, Inv<'r>)>`
+   = note: expected enum `Option<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>`
+              found enum `Option<for<'a> fn(Inv<'a>, Inv<'a>)>`
    = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr
index 3fdc2da9f1e..5ac392914e5 100644
--- a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr
+++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 LL |         _ => y,
    |              ^ one type is more general than the other
    |
-   = note: expected fn pointer `for<'r, 's> fn(&'r u8, &'s u8) -> &'r u8`
-              found fn pointer `for<'r> fn(&'r u8, &'r u8) -> &'r u8`
+   = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
+              found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr b/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr
index ad14d6b7521..355f0754ab1 100644
--- a/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr
+++ b/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 LL |         _ => y,
    |              ^ one type is more general than the other
    |
-   = note: expected trait object `dyn for<'r, 's> Foo<&'r u8, &'s u8>`
-              found trait object `dyn for<'r> Foo<&'r u8, &'r u8>`
+   = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>`
+              found trait object `dyn for<'a> Foo<&'a u8, &'a u8>`
 
 error[E0308]: mismatched types
   --> $DIR/old-lub-glb-object.rs:10:14
@@ -13,8 +13,8 @@ error[E0308]: mismatched types
 LL |         _ => y,
    |              ^ one type is more general than the other
    |
-   = note: expected trait object `dyn for<'r, 's> Foo<&'r u8, &'s u8>`
-              found trait object `dyn for<'r> Foo<&'r u8, &'r u8>`
+   = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>`
+              found trait object `dyn for<'a> Foo<&'a u8, &'a u8>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/relate_tys/fn-subtype.stderr b/src/test/ui/nll/relate_tys/fn-subtype.stderr
index 94def690086..6256c4a01d3 100644
--- a/src/test/ui/nll/relate_tys/fn-subtype.stderr
+++ b/src/test/ui/nll/relate_tys/fn-subtype.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     let y: for<'a> fn(&'a ()) = x;
    |                                 ^ one type is more general than the other
    |
-   = note: expected fn pointer `for<'r> fn(&'r ())`
+   = note: expected fn pointer `for<'a> fn(&'a ())`
               found fn pointer `fn(&())`
 
 error: aborting due to previous error
diff --git a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr
index 8c1eaeb6aa7..b839015f97f 100644
--- a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr
+++ b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
    |                                                          ^^^^^^^^^ one type is more general than the other
    |
-   = note: expected fn pointer `for<'r, 's> fn(&'r u32, &'s u32) -> &'r u32`
+   = note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32`
               found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32`
 
 error[E0308]: mismatched types
@@ -14,7 +14,7 @@ LL |     let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
    |
    = note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32`
-              found fn pointer `for<'r> fn(&'r u32, &'r u32) -> &'r u32`
+              found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/relate_tys/trait-hrtb.stderr b/src/test/ui/nll/relate_tys/trait-hrtb.stderr
index 60a7f204446..6d144a4be6e 100644
--- a/src/test/ui/nll/relate_tys/trait-hrtb.stderr
+++ b/src/test/ui/nll/relate_tys/trait-hrtb.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     let y: Box<dyn for<'a> Foo<'a>> = x;
    |                                       ^ one type is more general than the other
    |
-   = note: expected trait object `dyn for<'r> Foo<'r>`
+   = note: expected trait object `dyn for<'a> Foo<'a>`
               found trait object `dyn Foo<'_>`
 
 error: aborting due to previous error
diff --git a/src/test/ui/rfc1623.nll.stderr b/src/test/ui/rfc1623.nll.stderr
index cc247bbcb11..7f15c1c1f57 100644
--- a/src/test/ui/rfc1623.nll.stderr
+++ b/src/test/ui/rfc1623.nll.stderr
@@ -31,7 +31,7 @@ LL | |
 LL | | };
    | |_^ one type is more general than the other
    |
-   = note: expected type `for<'r, 's> Fn<(&'r Foo<'s>,)>`
+   = note: expected type `for<'a, 'b> Fn<(&'a Foo<'b>,)>`
               found type `Fn<(&Foo<'_>,)>`
 
 error[E0308]: mismatched types
@@ -46,7 +46,7 @@ LL | |
 LL | | };
    | |_^ one type is more general than the other
    |
-   = note: expected type `for<'r, 's> Fn<(&'r Foo<'s>,)>`
+   = note: expected type `for<'a, 'b> Fn<(&'a Foo<'b>,)>`
               found type `Fn<(&Foo<'_>,)>`
 
 error: implementation of `FnOnce` is not general enough
@@ -61,7 +61,7 @@ LL | |
 LL | | };
    | |_^ implementation of `FnOnce` is not general enough
    |
-   = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'_>,)>`, for any lifetime `'1`...
+   = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2`
 
 error: implementation of `FnOnce` is not general enough
@@ -76,7 +76,7 @@ LL | |
 LL | | };
    | |_^ implementation of `FnOnce` is not general enough
    |
-   = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&Foo<'1>,)>`, for any lifetime `'1`...
+   = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&'a Foo<'1>,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&Foo<'2>,)>`, for some specific lifetime `'2`
 
 error: aborting due to 5 previous errors