Skip to content

Commit

Permalink
Auto merge of #89250 - Aaron1011:keep-bound-region-names, r=estebank
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bors committed Sep 30, 2021
2 parents 30acf6d + 78013f2 commit 69c1c6a
Show file tree
Hide file tree
Showing 10 changed files with 48 additions and 22 deletions.
28 changes: 27 additions & 1 deletion compiler/rustc_typeck/src/check/writeback.rs
Expand Up @@ -736,14 +736,40 @@ 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
}

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);
Expand Down
Expand Up @@ -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
Expand Down
Expand Up @@ -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)

Expand Down
Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr
Expand Up @@ -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

Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/lub-glb/old-lub-glb-object.nll.stderr
Expand Up @@ -4,17 +4,17 @@ 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
|
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

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/nll/relate_tys/fn-subtype.stderr
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr
Expand Up @@ -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
Expand All @@ -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

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/nll/relate_tys/trait-hrtb.stderr
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/rfc1623.nll.stderr
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 69c1c6a

Please sign in to comment.