Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -428,7 +428,7 @@ fn try_extract_error_from_region_constraints<'tcx>(
placeholder_region,
vec![],
),
(Some(error_region), _) => {
(Some(error_region), ty::RePlaceholder(_)) => {
RegionResolutionError::ConcreteFailure(cause.clone(), error_region, placeholder_region)
}
// Note universe here is wrong...
@@ -439,9 +439,11 @@ fn try_extract_error_from_region_constraints<'tcx>(
cause.clone(),
placeholder_region,
),
(None, _) => {
(None, ty::ReStatic) => {
RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region)
}
(Some(_), r) => bug!("unexpected region with `Some`: {r:?}"),
(None, r) => bug!("unexpected region with `None`: {r:?}"),
};
NiceRegionError::new(&infcx.err_ctxt(), error).try_report_from_nll().or_else(|| {
if let SubregionOrigin::Subtype(trace) = cause {
20 changes: 8 additions & 12 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
@@ -466,12 +466,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// lifetimes without names with the value `'0`.
if let ty::Ref(region, ..) = ty.kind() {
match **region {
ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
| ty::RePlaceholder(ty::PlaceholderRegion {
bound: ty::BoundRegion { kind: br, .. },
..
}) => printer.region_highlight_mode.highlighting_bound_region(br, counter),
_ => {}
ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) => {
printer.region_highlight_mode.highlighting_bound_region(br, counter)
}
r => bug!("unexpected region: {r:?}"),
}
}

@@ -485,12 +483,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {

let region = if let ty::Ref(region, ..) = ty.kind() {
match **region {
ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
| ty::RePlaceholder(ty::PlaceholderRegion {
bound: ty::BoundRegion { kind: br, .. },
..
}) => printer.region_highlight_mode.highlighting_bound_region(br, counter),
_ => {}
ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) => {
printer.region_highlight_mode.highlighting_bound_region(br, counter)
}
r => bug!("unexpected region: {r:?}"),
}
region
} else {
6 changes: 1 addition & 5 deletions compiler/rustc_borrowck/src/diagnostics/region_name.rs
Original file line number Diff line number Diff line change
@@ -357,11 +357,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
ty::BoundRegionKind::BrAnon(..) => None,
},

ty::ReLateBound(..)
| ty::ReVar(..)
| ty::RePlaceholder(..)
| ty::ReErased
| ty::ReError(_) => None,
r => bug!("unexpected region: {r:?}"),
}
}

50 changes: 29 additions & 21 deletions compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
@@ -1127,22 +1127,27 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let ty = ty.fold_with(&mut OpaqueFolder { tcx });

let ty = tcx.fold_regions(ty, |r, _depth| {
let r_vid = self.to_region_vid(r);
let r_scc = self.constraint_sccs.scc(r_vid);

// The challenge is this. We have some region variable `r`
// whose value is a set of CFG points and universal
// regions. We want to find if that set is *equivalent* to
// any of the named regions found in the closure.
// To do so, we simply check every candidate `u_r` for equality.
self.scc_values
.universal_regions_outlived_by(r_scc)
.filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
.find(|&u_r| self.eval_equal(u_r, r_vid))
.map(|u_r| tcx.mk_re_var(u_r))
// In the case of a failure, use `ReErased`. We will eventually
// return `None` in this case.
.unwrap_or(tcx.lifetimes.re_erased)
match r.kind() {
ty::ReStatic | ty::ReVar(_) => {
let r_vid = self.to_region_vid(r);
let r_scc = self.constraint_sccs.scc(r_vid);

// The challenge is this. We have some region variable `r`
// whose value is a set of CFG points and universal
// regions. We want to find if that set is *equivalent* to
// any of the named regions found in the closure.
// To do so, we simply check every candidate `u_r` for equality.
self.scc_values
.universal_regions_outlived_by(r_scc)
.filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
.find(|&u_r| self.eval_equal(u_r, r_vid))
.map(|u_r| tcx.mk_re_var(u_r))
// In the case of a failure, use `ReErased`. We will eventually
// return `None` in this case.
.unwrap_or(tcx.lifetimes.re_erased)
}
r => bug!("unexpected region: {r:?}"),
}
});

debug!("try_promote_type_test_subject: folded ty = {:?}", ty);
@@ -1332,11 +1337,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
tcx.fold_regions(value, |r, _db| {
let vid = self.to_region_vid(r);
let scc = self.constraint_sccs.scc(vid);
let repr = self.scc_representatives[scc];
tcx.mk_re_var(repr)
tcx.fold_regions(value, |r, _db| match r.kind() {
ty::ReEarlyBound(_) | ty::ReStatic | ty::ReVar(_) => {
let vid = self.to_region_vid(r);
let scc = self.constraint_sccs.scc(vid);
let repr = self.scc_representatives[scc];
tcx.mk_re_var(repr)
}
r => bug!("unexpected region: {r:?}"),
})
}

21 changes: 11 additions & 10 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
@@ -110,14 +110,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {

// Next, insert universal regions from substs, so we can translate regions that appear
// in them but are not subject to member constraints, for instance closure substs.
let universal_substs = infcx.tcx.fold_regions(substs, |region, _| {
if let ty::RePlaceholder(..) = region.kind() {
// Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
return region;
}
let vid = self.to_region_vid(region);
to_universal_region(vid, &mut subst_regions)
});
let universal_substs =
infcx.tcx.fold_regions(substs, |region, _| match region.kind() {
ty::ReVar(_) => {
let vid = self.to_region_vid(region);
to_universal_region(vid, &mut subst_regions)
}
r => bug!("unexpected region: {r:?}"),
});
debug!(?universal_substs);
debug!(?subst_regions);

@@ -132,7 +132,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.find(|ur_vid| self.eval_equal(vid, **ur_vid))
.and_then(|ur_vid| self.definitions[*ur_vid].external_name)
.unwrap_or(infcx.tcx.lifetimes.re_erased),
_ => region,
ty::ReEarlyBound(_) | ty::ReStatic => region,
r => bug!("unexpected region: {r:?}"),
});
debug!(?universal_concrete_type);

@@ -201,7 +202,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
}
}
_ => region,
r => bug!("unexpected region: {r:?}"),
})
}
}
7 changes: 5 additions & 2 deletions compiler/rustc_borrowck/src/renumber.rs
Original file line number Diff line number Diff line change
@@ -75,8 +75,11 @@ impl<'a, 'tcx> RegionRenumberer<'a, 'tcx> {
F: Fn() -> RegionCtxt,
{
let origin = NllRegionVariableOrigin::Existential { from_forall: false };
self.infcx.tcx.fold_regions(value, |_region, _depth| {
self.infcx.next_nll_region_var(origin, || region_ctxt_fn())
self.infcx.tcx.fold_regions(value, |region, _depth| match region.kind() {
ty::ReErased | ty::ReError(_) => {
self.infcx.next_nll_region_var(origin, || region_ctxt_fn())
}
r => bug!("unexpected region: {r:?}"),
})
}
}
Original file line number Diff line number Diff line change
@@ -178,7 +178,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
ty::RePlaceholder(placeholder) => {
self.constraints.placeholder_region(self.infcx, placeholder)
}
_ => r,
ty::ReStatic | ty::ReVar(_) => r,
r => bug!("unexpected region: {r:?}"),
})
} else {
value
19 changes: 13 additions & 6 deletions compiler/rustc_borrowck/src/universal_regions.rs
Original file line number Diff line number Diff line change
@@ -757,11 +757,13 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
self.infcx.tcx.fold_regions(value, |region, _depth| {
let name = region.get_name_or_anon();
debug!(?region, ?name);

self.next_nll_region_var(origin, || RegionCtxt::Free(name))
self.infcx.tcx.fold_regions(value, |region, _depth| match region.kind() {
ty::ReEarlyBound(_) | ty::ReStatic | ty::ReErased | ty::ReError(_) => {
let name = region.get_name_or_anon();
debug!(?region, ?name);
self.next_nll_region_var(origin, || RegionCtxt::Free(name))
}
r => bug!("unexpected region: {r:?}"),
})
}

@@ -889,7 +891,12 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
tcx.fold_regions(value, |region, _| tcx.mk_re_var(self.to_region_vid(region)))
tcx.fold_regions(value, |region, _| match region.kind() {
ty::ReEarlyBound(_) | ty::ReStatic | ty::ReError(_) => {
tcx.mk_re_var(self.to_region_vid(region))
}
r => bug!("unexpected region: {r:?}"),
})
}
}

5 changes: 3 additions & 2 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
@@ -3226,8 +3226,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
hir::TyKind::Typeof(e) => {
let ty_erased = tcx.type_of(e.def_id).subst_identity();
let ty = tcx.fold_regions(ty_erased, |r, _| {
if r.is_erased() { tcx.lifetimes.re_static } else { r }
let ty = tcx.fold_regions(ty_erased, |r, _| match r.kind() {
ty::ReErased => tcx.lifetimes.re_static,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think ReErased is the only kind we expect here.

r => bug!("unexpected region: {r:?}"),
});
let span = ast_ty.span;
let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false) {
3 changes: 2 additions & 1 deletion compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
@@ -419,7 +419,8 @@ fn check_opaque_meets_bounds<'tcx>(
let hidden_ty = tcx.type_of(def_id.to_def_id()).subst(tcx, substs);
let hidden_ty = tcx.fold_regions(hidden_ty, |re, _dbi| match re.kind() {
ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)),
_ => re,
ty::ReEarlyBound(_) | ty::ReStatic | ty::ReError(_) => re,
r => bug!("unexpected region: {r:?}"),
});

let misc_cause = traits::ObligationCause::misc(span, def_id);
20 changes: 12 additions & 8 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
@@ -458,13 +458,13 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> {
}

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
if let ty::ReFree(fr) = *r {
self.tcx.mk_re_free(
match r.kind() {
ty::ReFree(fr) => self.tcx.mk_re_free(
fr.scope,
self.mapping.get(&fr.bound_region).copied().unwrap_or(fr.bound_region),
)
} else {
r
),
ty::ReEarlyBound(_) | ty::ReStatic => r,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably need to support ReError here, but after staring at this code for the last hour or so I am starting to get exhausted providing examples 😅

r => bug!("unexpected region: {r:?}"),
}
}
}
@@ -765,11 +765,15 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len();
let ty = tcx.fold_regions(ty, |region, _| {
match region.kind() {
// Remap all free regions, which correspond to late-bound regions in the function.
// Remap all free regions, which correspond to late-bound regions in the
// function.
ty::ReFree(_) => {}
// Remap early-bound regions as long as they don't come from the `impl` itself.
// Remap early-bound regions as long as they don't come from the `impl`
// itself.
ty::ReEarlyBound(ebr) if tcx.parent(ebr.def_id) != impl_m.container_id(tcx) => {}
_ => return region,
ty::ReEarlyBound(_) |
ty::ReStatic => return region,
r => bug!("unexpected region: {r:?}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReError here

}
let Some(ty::ReEarlyBound(e)) = map.get(&region.into()).map(|r| r.expect_region().kind())
else {
15 changes: 4 additions & 11 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
@@ -1574,17 +1574,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
&& source == self.fn_def_id
{
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, depth| {
if let ty::ReLateBound(index, bv) = re.kind() {
if depth != ty::INNERMOST {
return tcx.mk_re_error_with_message(
DUMMY_SP,
"we shouldn't walk non-predicate binders with `impl Trait`...",
);
}
tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
} else {
re
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {
match re.kind() {
ty::ReEarlyBound(_) | ty::ReFree(_) => re,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably need to support ReError here, but actually, but I guess I never noticed that all the late-bound lifetimes are liberated here, so that's good news I guess. Simplifes the logic a bit.

r => bug!("unexpected region: {r:?}"),
}
});
for (bound, bound_span) in tcx
8 changes: 5 additions & 3 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
@@ -387,8 +387,10 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {

fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
let ty = self.tcx.fold_regions(ty, |r, _| match *r {
ty::ReErased => self.tcx.lifetimes.re_static,
_ => r,
// This is never reached in practice. If it ever is reached,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not hit this in practice, I checked. But as far as I know, ReErased is the only region we should see... anyways, this is fine to keep here I guess.

// `ReErased` should be changed to `ReStatic`, and any other region
// left alone.
r => bug!("unexpected region: {r:?}"),
});
self.tcx().const_error_with_message(ty, span, "bad placeholder constant")
}
@@ -1142,7 +1144,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
// Typeck doesn't expect erased regions to be returned from `type_of`.
let fn_sig = tcx.fold_regions(fn_sig, |r, _| match *r {
ty::ReErased => tcx.lifetimes.re_static,
_ => r,
r => bug!("unexpected region: {r:?}"),
});

let mut visitor = HirPlaceholderCollector::default();
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect/type_of.rs
Original file line number Diff line number Diff line change
@@ -933,7 +933,7 @@ fn infer_placeholder_type<'a>(
// Typeck doesn't expect erased regions to be returned from `type_of`.
tcx.fold_regions(ty, |r, _| match *r {
ty::ReErased => tcx.lifetimes.re_static,
_ => r,
r => bug!("unexpected region: {r:?}"),
})
}

6 changes: 5 additions & 1 deletion compiler/rustc_hir_analysis/src/hir_wf_check.rs
Original file line number Diff line number Diff line change
@@ -194,6 +194,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseAllBoundRegions<'tcx> {
self.tcx
}
fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
if r.is_late_bound() { self.tcx.lifetimes.re_erased } else { r }
match r.kind() {
ty::ReLateBound(..) => self.tcx.lifetimes.re_erased,
ty::ReEarlyBound(_) | ty::ReStatic | ty::ReError(_) => r,
r => bug!("unexpected region: {r:?}"),
}
}
}
5 changes: 4 additions & 1 deletion compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
@@ -270,7 +270,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Hack to make equality checks on types with inference variables and regions useful.
let mut eraser = BottomUpFolder {
tcx: self.tcx,
lt_op: |_| self.tcx.lifetimes.re_erased,
lt_op: |r| match r.kind() {
ty::ReStatic | ty::ReVar(_) | ty::ReErased => self.tcx.lifetimes.re_erased,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ICEs on ReEarlyBound. Probably needs to handle ReError too, now that I think of it.

struct Wrapper<'a, T>(&'a T);

fn foo<'a, T>() -> Wrapper<'a, T> {}
fn needs_i32(_: Wrapper<'static, i32>) {}

fn test<'a>() {
    let x = foo::<'a, ()>();
    needs_i32(x);
}

fn main() {}

But also, I just rewrote all this code in #108687, so whatever.

r => bug!("unexpected region: {r:?}"),
},
ct_op: |c| c,
ty_op: |t| match *t.kind() {
ty::Infer(ty::TyVar(_)) => self.tcx.mk_ty_var(ty::TyVid::from_u32(0)),
9 changes: 5 additions & 4 deletions compiler/rustc_hir_typeck/src/generator_interior/mod.rs
Original file line number Diff line number Diff line change
@@ -257,19 +257,20 @@ pub fn resolve_interior<'a, 'tcx>(
_ => mk_bound_region(None),
}
}
// FIXME: these should use `BrNamed`
// // FIXME: these should use `BrNamed`
ty::ReEarlyBound(region) => {
mk_bound_region(Some(fcx.tcx.def_span(region.def_id)))
}
ty::ReLateBound(_, ty::BoundRegion { kind, .. })
| ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind {
// ty::ReLateBound(_, ty::BoundRegion { kind, .. })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stray comment? I think it's ok to ICE on ReLateBound here... I think...

ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind {
ty::BoundRegionKind::BrAnon(span) => mk_bound_region(span),
ty::BoundRegionKind::BrNamed(def_id, _) => {
mk_bound_region(Some(fcx.tcx.def_span(def_id)))
}
ty::BoundRegionKind::BrEnv => mk_bound_region(None),
},
_ => mk_bound_region(None),
ty::ReStatic | ty::ReErased => mk_bound_region(None),
r => bug!("unexpected region: {r:?}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We must handle ReError here:

fn missing() -> &'missing () {  &() }

async fn async_fn() {}

fn main() {
    async {
        let x = missing();
        async_fn().await;
        drop(x);
    };
}

};
let r = fcx.tcx.mk_re_late_bound(current_depth, br);
r
22 changes: 19 additions & 3 deletions compiler/rustc_hir_typeck/src/writeback.rs
Original file line number Diff line number Diff line change
@@ -774,7 +774,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEarlyRegions<'tcx> {
}
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
if r.is_late_bound() { r } else { self.tcx.lifetimes.re_erased }
match r.kind() {
ty::ReLateBound(..) => r,
ty::ReEarlyBound(_)
| ty::ReFree(..)
| ty::ReStatic
| ty::RePlaceholder(_)
| ty::ReErased
| ty::ReError(_) => self.tcx.lifetimes.re_erased,
ty::ReVar(_) => bug!("unexpected region: {r:?}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes me somewhat nervous that we need to handle ReVar below but not here. I wonder if there's some strange user type ascription that can cause us to trigger this ICE, but I haven't looked into it.

}
}
}

@@ -802,8 +811,15 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
}

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
debug_assert!(!r.is_late_bound(), "Should not be resolving bound region.");
self.tcx.lifetimes.re_erased
match r.kind() {
ty::ReEarlyBound(_)
| ty::ReFree(_)
| ty::ReStatic
| ty::ReVar(_)
| ty::RePlaceholder(_)
| ty::ReError(_) => self.tcx.lifetimes.re_erased,
r => bug!("unexpected region: {r:?}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReLateBound and ReErased missing from here should be ok.

}
}

fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
1 change: 1 addition & 0 deletions compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
@@ -343,6 +343,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
// All region variants occur in this match.
ty::ReLateBound(index, ..) => {
if index >= self.binder_index {
bug!("escaping late-bound region during canonicalization");
35 changes: 15 additions & 20 deletions compiler/rustc_infer/src/infer/combine.rs
Original file line number Diff line number Diff line change
@@ -939,30 +939,25 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for ConstInferUnifier<'_, 'tcx> {
) -> Result<ty::Region<'tcx>, TypeError<'tcx>> {
debug!("ConstInferUnifier: r={:?}", r);

match *r {
Ok(match *r {
// Never make variables for regions bound within the type itself,
// nor for erased regions.
ty::ReLateBound(..) | ty::ReErased | ty::ReError(_) => {
return Ok(r);
}
ty::ReLateBound(..) | ty::ReErased | ty::ReError(_) => r,

ty::RePlaceholder(..)
| ty::ReVar(..)
| ty::ReStatic
| ty::ReEarlyBound(..)
| ty::ReFree(..) => {
// see common code below
// ty::RePlaceholder(..)
ty::ReVar(..) | ty::ReStatic | ty::ReEarlyBound(..) | ty::ReFree(..) => {
let r_universe = self.infcx.universe_of_region(r);
if self.for_universe.can_name(r_universe) {
r
} else {
// FIXME: This is non-ideal because we don't give a
// very descriptive origin for this region variable.
self.infcx
.next_region_var_in_universe(MiscVariable(self.span), self.for_universe)
}
}
}

let r_universe = self.infcx.universe_of_region(r);
if self.for_universe.can_name(r_universe) {
return Ok(r);
} else {
// FIXME: This is non-ideal because we don't give a
// very descriptive origin for this region variable.
Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe))
}
r => bug!("unexpected region: {r:?}"),
})
}

#[instrument(level = "debug", skip(self), ret)]
Original file line number Diff line number Diff line change
@@ -82,13 +82,16 @@ pub fn find_param_with_region<'tcx>(
// May return None; sometimes the tables are not yet populated.
let ty = fn_sig.inputs()[index];
let mut found_anon_region = false;
let new_param_ty = tcx.fold_regions(ty, |r, _| {
if r == anon_region {
found_anon_region = true;
replace_region
} else {
r
let new_param_ty = tcx.fold_regions(ty, |r, _| match r.kind() {
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
if r == anon_region {
found_anon_region = true;
replace_region
} else {
r
}
}
r => bug!("unexpected region: {r:?}"),
});
found_anon_region.then(|| {
let ty_hir_id = fn_decl.inputs[index].hir_id;
7 changes: 2 additions & 5 deletions compiler/rustc_infer/src/infer/freshen.rs
Original file line number Diff line number Diff line change
@@ -110,11 +110,8 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
ty::ReLateBound(..) => {
// leave bound regions alone
r
}

// All region variants occur in this match.
ty::ReLateBound(..) => r, // leave bound regions alone
ty::ReEarlyBound(..)
| ty::ReFree(_)
| ty::ReVar(_)
17 changes: 12 additions & 5 deletions compiler/rustc_infer/src/infer/fudge.rs
Original file line number Diff line number Diff line change
@@ -220,12 +220,19 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> {
}

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
if let ty::ReVar(vid) = *r && self.region_vars.0.contains(&vid) {
let idx = vid.index() - self.region_vars.0.start.index();
let origin = self.region_vars.1[idx];
return self.infcx.next_region_var(origin);
match r.kind() {
ty::ReVar(vid) if self.region_vars.0.contains(&vid) => {
let idx = vid.index() - self.region_vars.0.start.index();
let origin = self.region_vars.1[idx];
return self.infcx.next_region_var(origin);
}
ty::ReEarlyBound(_)
| ty::ReLateBound(..)
| ty::ReFree(_)
| ty::ReStatic
| ty::ReVar(_) => r,
r => bug!("unexpected region: {r:?}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ICE:

fn test<T>(x: &'missing T) -> &'missing T { todo!() }

fn main() {
    let &() = test(&());
}

Need to handle ReError.

}
r
}

fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
13 changes: 12 additions & 1 deletion compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
Original file line number Diff line number Diff line change
@@ -989,7 +989,18 @@ impl<'tcx> LexicalRegionResolutions<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
tcx.fold_regions(value, |r, _db| self.resolve_region(tcx, r))
tcx.fold_regions(value, |r, _db| {
match r.kind() {
ty::ReEarlyBound(_)
| ty::ReFree(_)
| ty::ReStatic
| ty::ReVar(_)
| ty::RePlaceholder(_)
| ty::ReError(_) => {}
r => bug!("unexpected region: {r:?}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only ReErased missing? If so, probably ok.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, also ReLateBound? That's probably ok too. Maybe we should just assert if there !value.has_escaping_bound_regions() though.

}
self.resolve_region(tcx, r)
})
}

fn value(&self, rid: RegionVid) -> &VarValue<'tcx> {
19 changes: 17 additions & 2 deletions compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
@@ -57,7 +57,19 @@ impl<'tcx> InferCtxt<'tcx> {
};
let value = value.fold_with(&mut BottomUpFolder {
tcx: self.tcx,
lt_op: |lt| lt,
lt_op: |lt| {
// All region variants occur in this match.
match lt.kind() {
ty::ReEarlyBound(_)
| ty::ReLateBound(..)
| ty::ReFree(_)
| ty::ReStatic
| ty::ReVar(_)
| ty::RePlaceholder(_)
| ty::ReErased
| ty::ReError(_) => lt,
}
},
ct_op: |ct| ct,
ty_op: |ty| match *ty.kind() {
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })
@@ -580,7 +592,10 @@ impl<'tcx> InferCtxt<'tcx> {
) if def_id.to_def_id() == def_id2 && substs == substs2 => hidden_ty,
_ => ty,
},
lt_op: |lt| lt,
lt_op: |lt| {
// All region variants occur in this function.
lt
},
ct_op: |ct| ct,
});

16 changes: 14 additions & 2 deletions compiler/rustc_infer/src/infer/resolve.rs
Original file line number Diff line number Diff line change
@@ -91,7 +91,13 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticRegionResolver<'a, 'tcx
.borrow_mut()
.unwrap_region_constraints()
.opportunistic_resolve_var(TypeFolder::interner(self), vid),
_ => r,
ty::ReEarlyBound(_)
| ty::ReLateBound(..)
| ty::ReFree(_)
| ty::ReStatic
| ty::RePlaceholder(_)
| ty::ReErased => r,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually surprised ReErased must be handled here but not in the full region resolver below.

r => bug!("unexpected region: {r:?}"),
}
}

@@ -238,7 +244,13 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
.as_ref()
.expect("region resolution not performed")
.resolve_region(self.infcx.tcx, r)),
_ => Ok(r),
ty::ReEarlyBound(_)
| ty::ReLateBound(..)
| ty::ReFree(_)
| ty::ReStatic
| ty::RePlaceholder(_)
| ty::ReError(_) => Ok(r),
r => bug!("unexpected region: {r:?}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReErased is the only missing variant here? If so, probably okay.

}
}

8 changes: 7 additions & 1 deletion compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
Original file line number Diff line number Diff line change
@@ -104,7 +104,13 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
let proj_replacer = &mut BottomUpFolder {
tcx: cx.tcx,
ty_op: |ty| if ty == proj_ty { proj_term } else { ty },
lt_op: |lt| lt,
lt_op: |lt| {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will (probably?) ICE if we ever make lints fire on code with errors previously run on it:

#![feature(type_alias_impl_trait)]

trait Foo<'a> {
    type Output: Bar + 'a;
}
impl Foo<'_> for () {
    type Output = ();
}

trait Bar {}
impl Bar for () {}

type Tait = impl Foo<'missing, Output = impl Sized>;

fn main() {
    let _: Tait = ();
}

match lt.kind() {
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {}
r => bug!("unexpected region: {r:?}"),
}
lt
},
ct_op: |ct| ct,
};
// For example, in `impl Trait<Assoc = impl Send>`, for all of the bounds on `Assoc`,
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/query.rs
Original file line number Diff line number Diff line change
@@ -415,7 +415,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon(None) };
tcx.mk_re_late_bound(depth, br)
}
_ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
_ => bug!("unexpected region: {r:?}"),
});

Self { inner }
11 changes: 9 additions & 2 deletions compiler/rustc_middle/src/ty/erase_regions.rs
Original file line number Diff line number Diff line change
@@ -52,7 +52,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> {
}

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
// because late-bound regions affect subtyping, we can't
// Because late-bound regions affect subtyping, we can't
// erase the bound/free distinction, but we can replace
// all free regions with 'erased.
//
@@ -61,8 +61,15 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> {
// away. In codegen, they will always be erased to 'erased
// whenever a substitution occurs.
match *r {
// All region variants occur in this match.
ty::ReLateBound(..) => r,
_ => self.tcx.lifetimes.re_erased,
ty::ReEarlyBound(_)
| ty::ReFree(_)
| ty::ReStatic
| ty::ReVar(_)
| ty::RePlaceholder(_)
| ty::ReErased
| ty::ReError(_) => self.tcx.lifetimes.re_erased,
}
}
}
23 changes: 20 additions & 3 deletions compiler/rustc_middle/src/ty/fold.rs
Original file line number Diff line number Diff line change
@@ -116,11 +116,19 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
#[instrument(skip(self), level = "debug", ret)]
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
// All region variants occur in this match.
ty::ReLateBound(debruijn, _) if debruijn < self.current_index => {
debug!(?self.current_index, "skipped bound region");
r
}
_ => {
ty::ReEarlyBound(_)
| ty::ReLateBound(..)
| ty::ReFree(_)
| ty::ReStatic
| ty::ReVar(_)
| ty::RePlaceholder(_)
| ty::ReErased
| ty::ReError(_) => {
debug!(?self.current_index, "folding free region");
(self.fold_region_fn)(r, self.current_index)
}
@@ -204,6 +212,7 @@ where

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
// All region variants occur in this match.
ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
let region = self.delegate.replace_region(br);
if let ty::ReLateBound(debruijn1, br) = *region {
@@ -217,7 +226,14 @@ where
region
}
}
_ => r,
ty::ReEarlyBound(..)
| ty::ReLateBound(..)
| ty::ReFree(_)
| ty::ReStatic
| ty::ReVar(_)
| ty::RePlaceholder(_)
| ty::ReErased
| ty::ReError(_) => r,
}
}

@@ -452,7 +468,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
let debruijn = debruijn.shifted_in(self.amount);
self.tcx.mk_re_late_bound(debruijn, br)
}
_ => r,
ty::ReEarlyBound(_) | ty::ReLateBound(..) | ty::ReStatic => r,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to handle ReError here:

type FuncTuple<A> = (A, fn(A));
type MetaFuncTuple = for<'a> fn(FuncTuple<&'missing &'a i32>);

fn main() {}

r => bug!("unexpected region: {r:?}"),
}
}

10 changes: 4 additions & 6 deletions compiler/rustc_middle/src/ty/opaque_types.rs
Original file line number Diff line number Diff line change
@@ -114,12 +114,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
// The regions that we expect from borrow checking.
ty::ReEarlyBound(_) | ty::ReFree(_) => {}

ty::RePlaceholder(_) | ty::ReVar(_) => {
// All of the regions in the type should either have been
// erased by writeback, or mapped back to named regions by
// borrow checking.
bug!("unexpected region kind in opaque type: {:?}", r);
}
// All of the regions in the type should either have been
// erased by writeback, or mapped back to named regions by
// borrow checking.
ty::RePlaceholder(_) | ty::ReVar(_) => bug!("unexpected region: {r:?}"),
}

match self.map.get(&r.into()).map(|k| k.unpack()) {
9 changes: 8 additions & 1 deletion compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
@@ -2258,6 +2258,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
let name = &mut self.name;
let region = match *r {
// All region variants occur in this match.
ty::ReLateBound(db, br) if db >= self.current_index => {
*self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br))
}
@@ -2279,7 +2280,13 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
}
}
}
_ => return r,
ty::ReEarlyBound(_)
| ty::ReLateBound(..)
| ty::ReFree(_)
| ty::ReStatic
| ty::ReVar(_)
| ty::ReErased
| ty::ReError(_) => return r,
};
if let ty::ReLateBound(debruijn1, br) = *region {
assert_eq!(debruijn1, ty::INNERMOST);
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/ty/subst.rs
Original file line number Diff line number Diff line change
@@ -840,7 +840,8 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> {
None => region_param_out_of_range(data, self.substs),
}
}
_ => r,
ty::ReLateBound(..) | ty::ReFree(_) | ty::ReStatic | ty::ReErased | ty::ReError(_) => r,
r => bug!("unexpected region: {r:?}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised and skeptical that we can't get this to ICE with some RePlaceholder, especially in the new solver.

This probably should be an ICE for ReVar though.

}
}

Original file line number Diff line number Diff line change
@@ -85,20 +85,20 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
}
}

pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
fn replace_erased_lifetimes_with_bound_vars<'tcx>(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
) -> ty::Binder<'tcx, Ty<'tcx>> {
debug_assert!(!ty.has_late_bound_regions());
let mut counter = 0;
let ty = tcx.fold_regions(ty, |mut r, current_depth| {
if let ty::ReErased = r.kind() {
let ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() {
ty::ReErased => {
let br =
ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon(None) };
counter += 1;
r = tcx.mk_re_late_bound(current_depth, br);
tcx.mk_re_late_bound(current_depth, br)
}
r
r => bug!("unexpected region: {r:?}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is fine. This probably should have some correctness comment saying that all (free) regions are erased here.

});
let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
(0..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon(None))),
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/solve/canonicalize.rs
Original file line number Diff line number Diff line change
@@ -242,7 +242,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
}
},

ty::ReError(_) => return r,
r => bug!("unexpected region: {r:?}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ICE:

// compile-flags: -Ztrait-solver=next

struct Wrapper<'a, 'b>(&'a (), &'b ());

fn missing<'a>() -> Wrapper<'missing, 'a> { todo!() }

fn main() {
}

};

let existing_bound_var = match self.canonicalize_mode {
14 changes: 12 additions & 2 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
@@ -776,7 +776,12 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
self.mapped_regions.insert(p, br);
self.infcx.tcx.mk_re_placeholder(p)
}
_ => r,
ty::ReEarlyBound(_)
| ty::ReLateBound(..)
| ty::ReFree(_)
| ty::ReStatic
| ty::RePlaceholder(_) => r,
r => bug!("unexpected region: {r:?}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ICE:

trait Trait<'a, 'b> {
    type Assoc;
}

fn foo() where for<'a> fn(<() as Trait<'a, 'missing>>::Assoc): Send {}

fn main() {
    foo();
}

Other than that, what's still missing? ReErased? There's probably some way of triggering that too, that I fear is just missing from the test suite.

}
}

@@ -879,7 +884,12 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
.borrow_mut()
.unwrap_region_constraints()
.opportunistic_resolve_var(self.infcx.tcx, vid),
_ => r0,
ty::ReEarlyBound(_)
| ty::ReLateBound(..)
| ty::ReStatic
| ty::RePlaceholder(_)
| ty::ReErased => r0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need ReError support here too.

r => bug!("unexpected region: {r:?}"),
};

let r2 = match *r1 {
16 changes: 11 additions & 5 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
@@ -2459,7 +2459,13 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
let value = value.fold_with(&mut BottomUpFolder {
tcx: self.tcx(),
ty_op: |_| err,
lt_op: |l| l,
lt_op: |lt| {
match lt {
// This is never reached in practice. If it ever is reached,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only reason we never hit this in practice is because our tests are lacking. We can take tests/ui/impl-trait/issues/issue-84073.rs and just add a lifetime to the impl, causing an ICE:

use std::marker::PhantomData;

pub trait StatefulFuture<S> {}
pub struct Never<T>(PhantomData<T>);
impl<T> StatefulFuture<T> for Never<T> {}

pub struct RaceBuilder<F, S> {
    future: F,
    _phantom: PhantomData<S>,
}

impl<T, F> RaceBuilder<T, F>
where
    F: StatefulFuture<Option<T>>,
{
    pub fn when(self) {}
}

pub struct Race<T, R> {
    race: R,
    _phantom: PhantomData<T>,
}

impl<T, R> Race<T, R>
where
    R: Fn(RaceBuilder<T, Never<T>>),
{
    pub fn new(race: R) {}
}

fn main() {
    Race::new(|race| race.when()); //~ ERROR type annotations needed
}

Also, this should return ReError, not ReErased, probably.

// it should just return `ReErased`.
r => bug!("unexpected region: {r:?}"),
}
},
ct_op: |c| c,
});
Normalized { value, obligations: vec![] }
@@ -3007,16 +3013,16 @@ fn bind_generator_hidden_types_above<'tcx>(

// Only remap erased regions if we use them.
if considering_regions {
ty = tcx.fold_regions(ty, |mut r, current_depth| {
if let ty::ReErased = r.kind() {
ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cjgillot made this so all lifetimes are explicitly erased, so I think this is ok.

ty::ReErased => {
let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(counter),
kind: ty::BrAnon(None),
};
counter += 1;
r = tcx.mk_re_late_bound(current_depth, br);
tcx.mk_re_late_bound(current_depth, br)
}
r
r => bug!("unexpected region: {r:?}"),
})
}

8 changes: 5 additions & 3 deletions compiler/rustc_traits/src/chalk/lowering.rs
Original file line number Diff line number Diff line change
@@ -1045,7 +1045,8 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for NamedBoundVarSubstitutor<'a, 'tcx> {
ty::BrEnv => unimplemented!(),
ty::BrAnon(..) => {}
},
_ => (),
ty::ReLateBound(..) | ty::ReStatic => (),
r => bug!("unexpected region: {r:?}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably ICEs on ReError if we do something like:

fn def<'a, T>(_: T) where T: Fn() {}

fn foo() where &'missing i32: Copy {}

fn main() {
    def(foo);
}

But that's obscured by other canonicalizer+ReError bugs in chalk.

};

r.super_fold_with(self)
@@ -1141,8 +1142,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> {
self.tcx.mk_re_late_bound(self.binder_index, br)
}
},

_ => r.super_fold_with(self),
// Other region kinds might need the same treatment here.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Canonicalization already canonicalizes all free regions for chalk. We probably shouldn't even have this folder at all.

Unrelated, but this ICEs on nightly already, lol:

// compile-flags: -Ztrait-solver=chalk

trait Trait {}

impl Trait for &() {}

fn trait_pred() where &'missing (): Trait {}

fn main() {
    trait_pred();
}

ty::ReLateBound(..) => r.super_fold_with(self),
r => bug!("unexpected region: {r:?}"),
}
}
}
20 changes: 11 additions & 9 deletions compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
@@ -287,16 +287,18 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
// bounds of the RPITIT. Shift these binders back out when
// constructing the top-level projection predicate.
let shifted_alias_ty = self.tcx.fold_regions(unshifted_alias_ty, |re, depth| {
if let ty::ReLateBound(index, bv) = re.kind() {
if depth != ty::INNERMOST {
return self.tcx.mk_re_error_with_message(
DUMMY_SP,
"we shouldn't walk non-predicate binders with `impl Trait`...",
);
match re.kind() {
ty::ReEarlyBound(_) => re,
ty::ReLateBound(index, bv) => {
Copy link
Member

@compiler-errors compiler-errors Apr 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ICEs on ReEarlyBound:

#![feature(return_position_impl_trait_in_trait)]

use std::ops::Deref;

trait Foo {
    fn test<'a: 'a>() -> impl Deref<Target = impl Sized> { &() }
}

fn main() {}

Copy link
Member

@compiler-errors compiler-errors Apr 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, that error is coming from somewhere else in borrowck.

if depth != ty::INNERMOST {
return self.tcx.mk_re_error_with_message(
DUMMY_SP,
"we shouldn't walk non-predicate binders with `impl Trait`...",
);
}
self.tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
}
self.tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
} else {
re
r => bug!("unexpected region: {r:?}"),
}
});

12 changes: 6 additions & 6 deletions src/librustdoc/clean/auto_trait.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_middle::ty::{self, Region, RegionVid, TypeFoldable, TypeSuperFoldable};
use rustc_middle::ty::{self, Region, RegionVid, TypeFoldable};
use rustc_trait_selection::traits::auto_trait::{self, AutoTraitResult};
use thin_vec::ThinVec;

@@ -740,10 +740,10 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionReplacer<'a, 'tcx> {
}

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
(match *r {
ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
_ => None,
})
.unwrap_or_else(|| r.super_fold_with(self))
match *r {
ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned().unwrap_or(r),
ty::ReEarlyBound(_) | ty::ReStatic | ty::ReLateBound(..) => r,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably fine. If I were being defensive, I'd also include ReError here, but whatever.

Some comment to the effect of "these are the regions that can be seen in AST" as justification.

r => bug!("unexpected region: {r:?}"),
}
}
}