Skip to content

Commit 69c1c6a

Browse files
committed
Auto merge of rust-lang#89250 - Aaron1011:keep-bound-region-names, r=estebank
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.
2 parents 30acf6d + 78013f2 commit 69c1c6a

10 files changed

+48
-22
lines changed

compiler/rustc_typeck/src/check/writeback.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -736,14 +736,40 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
736736
}
737737
}
738738

739+
struct EraseEarlyRegions<'tcx> {
740+
tcx: TyCtxt<'tcx>,
741+
}
742+
743+
impl<'tcx> TypeFolder<'tcx> for EraseEarlyRegions<'tcx> {
744+
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
745+
self.tcx
746+
}
747+
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
748+
if ty.has_type_flags(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
749+
ty.super_fold_with(self)
750+
} else {
751+
ty
752+
}
753+
}
754+
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
755+
if let ty::ReLateBound(..) = r { r } else { self.tcx.lifetimes.re_erased }
756+
}
757+
}
758+
739759
impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
740760
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
741761
self.tcx
742762
}
743763

744764
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
745765
match self.infcx.fully_resolve(t) {
746-
Ok(t) => self.infcx.tcx.erase_regions(t),
766+
Ok(t) => {
767+
// Do not anonymize late-bound regions
768+
// (e.g. keep `for<'a>` named `for<'a>`).
769+
// This allows NLL to generate error messages that
770+
// refer to the higher-ranked lifetime names written by the user.
771+
EraseEarlyRegions { tcx: self.infcx.tcx }.fold_ty(t)
772+
}
747773
Err(_) => {
748774
debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
749775
self.report_type_error(t);

src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u3
88
LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) }
99
| |_____________________________________________- in this macro invocation
1010
|
11-
= note: expected enum `Option<for<'r, 's> fn(&'r u32, &'s u32) -> &'r u32>`
12-
found enum `Option<for<'r> fn(&'r u32, &'r u32) -> &'r u32>`
11+
= note: expected enum `Option<for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32>`
12+
found enum `Option<for<'a> fn(&'a u32, &'a u32) -> &'a u32>`
1313
= note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
1414

1515
error: aborting due to previous error

src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
88
LL | | fn(&'x u32)) }
99
| |______________- in this macro invocation
1010
|
11-
= note: expected enum `Option<for<'r> fn(&'r u32)>`
11+
= note: expected enum `Option<for<'a> fn(&'a u32)>`
1212
found enum `Option<fn(&u32)>`
1313
= note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
1414

src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
88
LL | | for<'a> fn(Inv<'a>, Inv<'a>)) }
99
| |__________________________________- in this macro invocation
1010
|
11-
= note: expected enum `Option<for<'r, 's> fn(Inv<'r>, Inv<'s>)>`
12-
found enum `Option<for<'r> fn(Inv<'r>, Inv<'r>)>`
11+
= note: expected enum `Option<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>`
12+
found enum `Option<for<'a> fn(Inv<'a>, Inv<'a>)>`
1313
= note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
1414

1515
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>),
2222
LL | | for<'a> fn(Inv<'a>, Inv<'a>)) }
2323
| |__________________________________- in this macro invocation
2424
|
25-
= note: expected enum `Option<for<'r, 's> fn(Inv<'r>, Inv<'s>)>`
26-
found enum `Option<for<'r> fn(Inv<'r>, Inv<'r>)>`
25+
= note: expected enum `Option<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>`
26+
found enum `Option<for<'a> fn(Inv<'a>, Inv<'a>)>`
2727
= note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
2828

2929
error: aborting due to 2 previous errors

src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
44
LL | _ => y,
55
| ^ one type is more general than the other
66
|
7-
= note: expected fn pointer `for<'r, 's> fn(&'r u8, &'s u8) -> &'r u8`
8-
found fn pointer `for<'r> fn(&'r u8, &'r u8) -> &'r u8`
7+
= note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
8+
found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
99

1010
error: aborting due to previous error
1111

src/test/ui/lub-glb/old-lub-glb-object.nll.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ error[E0308]: mismatched types
44
LL | _ => y,
55
| ^ one type is more general than the other
66
|
7-
= note: expected trait object `dyn for<'r, 's> Foo<&'r u8, &'s u8>`
8-
found trait object `dyn for<'r> Foo<&'r u8, &'r u8>`
7+
= note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>`
8+
found trait object `dyn for<'a> Foo<&'a u8, &'a u8>`
99

1010
error[E0308]: mismatched types
1111
--> $DIR/old-lub-glb-object.rs:10:14
1212
|
1313
LL | _ => y,
1414
| ^ one type is more general than the other
1515
|
16-
= note: expected trait object `dyn for<'r, 's> Foo<&'r u8, &'s u8>`
17-
found trait object `dyn for<'r> Foo<&'r u8, &'r u8>`
16+
= note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>`
17+
found trait object `dyn for<'a> Foo<&'a u8, &'a u8>`
1818

1919
error: aborting due to 2 previous errors
2020

src/test/ui/nll/relate_tys/fn-subtype.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
44
LL | let y: for<'a> fn(&'a ()) = x;
55
| ^ one type is more general than the other
66
|
7-
= note: expected fn pointer `for<'r> fn(&'r ())`
7+
= note: expected fn pointer `for<'a> fn(&'a ())`
88
found fn pointer `fn(&())`
99

1010
error: aborting due to previous error

src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
44
LL | let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
55
| ^^^^^^^^^ one type is more general than the other
66
|
7-
= note: expected fn pointer `for<'r, 's> fn(&'r u32, &'s u32) -> &'r u32`
7+
= note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32`
88
found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32`
99

1010
error[E0308]: mismatched types
@@ -14,7 +14,7 @@ LL | let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
1515
|
1616
= note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32`
17-
found fn pointer `for<'r> fn(&'r u32, &'r u32) -> &'r u32`
17+
found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32`
1818

1919
error: aborting due to 2 previous errors
2020

src/test/ui/nll/relate_tys/trait-hrtb.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
44
LL | let y: Box<dyn for<'a> Foo<'a>> = x;
55
| ^ one type is more general than the other
66
|
7-
= note: expected trait object `dyn for<'r> Foo<'r>`
7+
= note: expected trait object `dyn for<'a> Foo<'a>`
88
found trait object `dyn Foo<'_>`
99

1010
error: aborting due to previous error

src/test/ui/rfc1623.nll.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ LL | |
3131
LL | | };
3232
| |_^ one type is more general than the other
3333
|
34-
= note: expected type `for<'r, 's> Fn<(&'r Foo<'s>,)>`
34+
= note: expected type `for<'a, 'b> Fn<(&'a Foo<'b>,)>`
3535
found type `Fn<(&Foo<'_>,)>`
3636

3737
error[E0308]: mismatched types
@@ -46,7 +46,7 @@ LL | |
4646
LL | | };
4747
| |_^ one type is more general than the other
4848
|
49-
= note: expected type `for<'r, 's> Fn<(&'r Foo<'s>,)>`
49+
= note: expected type `for<'a, 'b> Fn<(&'a Foo<'b>,)>`
5050
found type `Fn<(&Foo<'_>,)>`
5151

5252
error: implementation of `FnOnce` is not general enough
@@ -61,7 +61,7 @@ LL | |
6161
LL | | };
6262
| |_^ implementation of `FnOnce` is not general enough
6363
|
64-
= note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'_>,)>`, for any lifetime `'1`...
64+
= note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any lifetime `'1`...
6565
= note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2`
6666

6767
error: implementation of `FnOnce` is not general enough
@@ -76,7 +76,7 @@ LL | |
7676
LL | | };
7777
| |_^ implementation of `FnOnce` is not general enough
7878
|
79-
= note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&Foo<'1>,)>`, for any lifetime `'1`...
79+
= note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&'a Foo<'1>,)>`, for any lifetime `'1`...
8080
= note: ...but it actually implements `FnOnce<(&Foo<'2>,)>`, for some specific lifetime `'2`
8181

8282
error: aborting due to 5 previous errors

0 commit comments

Comments
 (0)