Rollup merge of #93227 - compiler-errors:gat-hrtb-wfcheck, r=jackh726

Liberate late bound regions when collecting GAT substs in wfcheck

The issue here is that the [`GATSubstCollector`](https://github.com/rust-lang/rust/blob/master/compiler/rustc_typeck/src/check/wfcheck.rs#L604) does not currently do anything wrt `Binder`s, so the GAT substs it copies out have escaping late bound regions when it walks through types like `for<'x> fn() -> Self::Gat<'x>`.

I made that visitor call `liberate_late_bound_regions`, not sure if that's the right thing here or we need to do something else to replace these bound vars with placeholders. I'm not familiar with other code doing anything similar.. But the issue is indeed no longer ICEing.

Fixes #92954

r? `@jackh726`
since you last touched this code, feel free to reassign
This commit is contained in:
Matthias Krüger 2022-01-23 20:13:06 +01:00 committed by GitHub
commit 8810af8082
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 3 deletions

View File

@ -312,7 +312,7 @@ fn check_gat_where_clauses(
// of the function signature. In our example, the GAT in the return
// type is `<Self as LendingIterator>::Item<'a>`, so 'a and Self are arguments.
let (regions, types) =
GATSubstCollector::visit(trait_item.def_id.to_def_id(), sig.output());
GATSubstCollector::visit(tcx, trait_item.def_id.to_def_id(), sig.output());
// If both regions and types are empty, then this GAT isn't in the
// return type, and we shouldn't try to do clause analysis
@ -602,6 +602,7 @@ fn resolve_regions_with_wf_tys<'tcx>(
/// the two vectors, `regions` and `types` (depending on their kind). For each
/// parameter `Pi` also track the index `i`.
struct GATSubstCollector<'tcx> {
tcx: TyCtxt<'tcx>,
gat: DefId,
// Which region appears and which parameter index its subsituted for
regions: FxHashSet<(ty::Region<'tcx>, usize)>,
@ -611,11 +612,16 @@ struct GATSubstCollector<'tcx> {
impl<'tcx> GATSubstCollector<'tcx> {
fn visit<T: TypeFoldable<'tcx>>(
tcx: TyCtxt<'tcx>,
gat: DefId,
t: T,
) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) {
let mut visitor =
GATSubstCollector { gat, regions: FxHashSet::default(), types: FxHashSet::default() };
let mut visitor = GATSubstCollector {
tcx,
gat,
regions: FxHashSet::default(),
types: FxHashSet::default(),
};
t.visit_with(&mut visitor);
(visitor.regions, visitor.types)
}
@ -624,6 +630,13 @@ impl<'tcx> GATSubstCollector<'tcx> {
impl<'tcx> TypeVisitor<'tcx> for GATSubstCollector<'tcx> {
type BreakTy = !;
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &ty::Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
self.tcx.liberate_late_bound_regions(self.gat, t.clone()).visit_with(self)
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
ty::Projection(p) if p.item_def_id == self.gat => {

View File

@ -0,0 +1,10 @@
// check-pass
#![feature(generic_associated_types)]
pub trait Foo {
type Assoc<'c>;
fn function() -> for<'x> fn(Self::Assoc<'x>);
}
fn main() {}