Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strict region folders #110312

Closed
Closed
Show file tree
Hide file tree
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
Expand Up @@ -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...
Expand All @@ -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 {
Expand Down
20 changes: 8 additions & 12 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:?}"),
}
}

Expand All @@ -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 {
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_borrowck/src/diagnostics/region_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:?}"),
}
}

Expand Down
50 changes: 29 additions & 21 deletions compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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:?}"),
})
}

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

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

Expand Down Expand Up @@ -201,7 +202,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
}
}
_ => region,
r => bug!("unexpected region: {r:?}"),
})
}
}
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_borrowck/src/renumber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:?}"),
})
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 13 additions & 6 deletions compiler/rustc_borrowck/src/universal_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:?}"),
})
}

Expand Down Expand Up @@ -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:?}"),
})
}
}

Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
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
Expand Up @@ -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:?}"),
}
}
}
Expand Down Expand Up @@ -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 {
Expand Down
15 changes: 4 additions & 11 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down Expand Up @@ -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();
Expand Down
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
Expand Up @@ -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:?}"),
})
}

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