Skip to content

Commit

Permalink
Auto merge of #117944 - lcnr:region-refactor-uwu, r=BoxyUwU
Browse files Browse the repository at this point in the history
some additional region refactorings

the commits are selfcontained ✨

r? `@BoxyUwU`
  • Loading branch information
bors committed Nov 17, 2023
2 parents 4d7f952 + 40b154e commit 069a4af
Show file tree
Hide file tree
Showing 39 changed files with 93 additions and 120 deletions.
5 changes: 3 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1578,8 +1578,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return;
};
let sig = args.as_closure().sig();
let tupled_params =
tcx.erase_late_bound_regions(sig.inputs().iter().next().unwrap().map_bound(|&b| b));
let tupled_params = tcx.instantiate_bound_regions_with_erased(
sig.inputs().iter().next().unwrap().map_bound(|&b| b),
);
let ty::Tuple(params) = tupled_params.kind() else { return };

// Find the first argument with a matching type, get its name
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1387,7 +1387,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
return;
}
};
let (sig, map) = tcx.replace_late_bound_regions(sig, |br| {
let (sig, map) = tcx.instantiate_bound_regions(sig, |br| {
use crate::renumber::RegionCtxt;

let region_ctxt_fn = || {
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_borrowck/src/universal_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -738,13 +738,13 @@ trait InferCtxtExt<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>;

fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope(
fn instantiate_bound_regions_with_nll_infer_vars_in_recursive_scope(
&self,
mir_def_id: LocalDefId,
indices: &mut UniversalRegionIndices<'tcx>,
);

fn replace_late_bound_regions_with_nll_infer_vars_in_item(
fn instantiate_bound_regions_with_nll_infer_vars_in_item(
&self,
mir_def_id: LocalDefId,
indices: &mut UniversalRegionIndices<'tcx>,
Expand Down Expand Up @@ -780,7 +780,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| {
let (value, _map) = self.tcx.instantiate_bound_regions(value, |br| {
debug!(?br);
let liberated_region =
ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), br.kind);
Expand Down Expand Up @@ -810,7 +810,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
/// set of late-bound regions and checks for any that we have not yet seen, adding them to the
/// inputs vector.
#[instrument(skip(self, indices))]
fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope(
fn instantiate_bound_regions_with_nll_infer_vars_in_recursive_scope(
&self,
mir_def_id: LocalDefId,
indices: &mut UniversalRegionIndices<'tcx>,
Expand All @@ -830,7 +830,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
}

#[instrument(skip(self, indices))]
fn replace_late_bound_regions_with_nll_infer_vars_in_item(
fn instantiate_bound_regions_with_nll_infer_vars_in_item(
&self,
mir_def_id: LocalDefId,
indices: &mut UniversalRegionIndices<'tcx>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ fn push_debuginfo_type_name<'tcx>(
.projection_bounds()
.map(|bound| {
let ExistentialProjection { def_id: item_def_id, term, .. } =
tcx.erase_late_bound_regions(bound);
tcx.instantiate_bound_regions_with_erased(bound);
// FIXME(associated_const_equality): allow for consts here
(item_def_id, term.ty().unwrap())
})
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_const_eval/src/transform/promote_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
};

// Use the underlying local for this (necessarily interior) borrow.
debug_assert!(region.is_erased());
let ty = local_decls[place.local].ty;
let span = statement.source_info.span;

Expand All @@ -873,8 +874,6 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
ty::TypeAndMut { ty, mutbl: borrow_kind.to_mutbl_lossy() },
);

*region = tcx.lifetimes.re_erased;

let mut projection = vec![PlaceElem::Deref];
projection.extend(place.projection);
place.projection = tcx.mk_place_elems(&projection);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
second: format!(
"{}::",
// Replace the existing lifetimes with a new named lifetime.
self.tcx.replace_late_bound_regions_uncached(
self.tcx.instantiate_bound_regions_uncached(
poly_trait_ref,
|_| {
ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion {
Expand Down
32 changes: 8 additions & 24 deletions compiler/rustc_hir_analysis/src/hir_wf_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_hir::{ForeignItem, ForeignItemKind};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ObligationCause, WellFormedLoc};
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::def_id::LocalDefId;
use rustc_trait_selection::traits::{self, ObligationCtxt};

Expand Down Expand Up @@ -68,7 +68,13 @@ fn diagnostic_hir_wf_check<'tcx>(
let infcx = self.tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);

let tcx_ty = self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx });
let tcx_ty = self.icx.to_ty(ty);
// This visitor can walk into binders, resulting in the `tcx_ty` to
// potentially reference escaping bound variables. We simply erase
// those here.
let tcx_ty = self.tcx.fold_regions(tcx_ty, |r, _| {
if r.is_bound() { self.tcx.lifetimes.re_erased } else { r }
});
let cause = traits::ObligationCause::new(
ty.span,
self.def_id,
Expand Down Expand Up @@ -178,25 +184,3 @@ fn diagnostic_hir_wf_check<'tcx>(
}
visitor.cause
}

struct EraseAllBoundRegions<'tcx> {
tcx: TyCtxt<'tcx>,
}

// Higher ranked regions are complicated.
// To make matters worse, the HIR WF check can instantiate them
// outside of a `Binder`, due to the way we (ab)use
// `ItemCtxt::to_ty`. To make things simpler, we just erase all
// of them, regardless of depth. At worse, this will give
// us an inaccurate span for an error message, but cannot
// lead to unsoundness (we call `delay_span_bug` at the start
// of `diagnostic_hir_wf_check`).
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseAllBoundRegions<'tcx> {
fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
// FIXME(@lcnr): only erase escaping bound regions!
if r.is_bound() { self.tcx.lifetimes.re_erased } else { r }
}
}
6 changes: 4 additions & 2 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into());
let ty = Binder::bind_with_vars(ty, bound_vars);
let ty = self.normalize(hir_ty.span, ty);
let ty = self.tcx.erase_late_bound_regions(ty);
let ty = self.tcx.instantiate_bound_regions_with_erased(ty);
if self.can_coerce(expected, ty) {
err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other {
span: hir_ty.span,
Expand Down Expand Up @@ -1023,7 +1023,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let hir::FnRetTy::Return(ty) = fn_decl.output {
let ty = self.astconv().ast_ty_to_ty(ty);
let bound_vars = self.tcx.late_bound_vars(fn_id);
let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
let ty = self
.tcx
.instantiate_bound_regions_with_erased(Binder::bind_with_vars(ty, bound_vars));
let ty = match self.tcx.asyncness(fn_id.owner) {
ty::Asyncness::Yes => self.get_impl_future_output_ty(ty).unwrap_or_else(|| {
span_bug!(fn_decl.output.span(), "failed to get output type of async function")
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
return;
}

let new_trait_ref = this.erase_late_bound_regions(new_trait_ref);
let new_trait_ref = this.instantiate_bound_regions_with_erased(new_trait_ref);

let (xform_self_ty, xform_ret_ty) =
this.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args);
Expand Down Expand Up @@ -1885,7 +1885,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
fn_sig.instantiate(self.tcx, args)
};

self.erase_late_bound_regions(xform_fn_sig)
self.instantiate_bound_regions_with_erased(xform_fn_sig)
}

/// Gets the type of an impl and generate substitutions with inference vars.
Expand All @@ -1897,7 +1897,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}

/// Replaces late-bound-regions bound by `value` with `'static` using
/// `ty::erase_late_bound_regions`.
/// `ty::instantiate_bound_regions_with_erased`.
///
/// This is only a reasonable thing to do during the *probe* phase, not the *confirm* phase, of
/// method matching. It is reasonable during the probe phase because we don't consider region
Expand All @@ -1914,11 +1914,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
/// region got replaced with the same variable, which requires a bit more coordination
/// and/or tracking the substitution and
/// so forth.
fn erase_late_bound_regions<T>(&self, value: ty::Binder<'tcx, T>) -> T
fn instantiate_bound_regions_with_erased<T>(&self, value: ty::Binder<'tcx, T>) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
self.tcx.erase_late_bound_regions(value)
self.tcx.instantiate_bound_regions_with_erased(value)
}

/// Determine if the given associated item type is relevant in the current context.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.filter_map(|item| {
// Only assoc fns that return `Self`, `Option<Self>` or `Result<Self, _>`.
let ret_ty = self.tcx.fn_sig(item.def_id).skip_binder().output();
let ret_ty = self.tcx.erase_late_bound_regions(ret_ty);
let ret_ty = self.tcx.instantiate_bound_regions_with_erased(ret_ty);
let ty::Adt(def, args) = ret_ty.kind() else {
return None;
};
Expand Down
29 changes: 5 additions & 24 deletions compiler/rustc_hir_typeck/src/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::symbol::sym;
Expand Down Expand Up @@ -768,49 +768,30 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
}
}

struct EraseEarlyRegions<'tcx> {
tcx: TyCtxt<'tcx>,
}

impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEarlyRegions<'tcx> {
fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if ty.has_type_flags(ty::TypeFlags::HAS_FREE_REGIONS) {
ty.super_fold_with(self)
} else {
ty
}
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
if r.is_bound() { r } else { self.tcx.lifetimes.re_erased }
}
}

impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
fn interner(&self) -> TyCtxt<'tcx> {
self.fcx.tcx
}

fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
let tcx = self.fcx.tcx;
match self.fcx.fully_resolve(t) {
Ok(t) if self.fcx.next_trait_solver() => {
// We must normalize erasing regions here, since later lints
// expect that types that show up in the typeck are fully
// normalized.
if let Ok(t) = self.fcx.tcx.try_normalize_erasing_regions(self.fcx.param_env, t) {
if let Ok(t) = tcx.try_normalize_erasing_regions(self.fcx.param_env, t) {
t
} else {
EraseEarlyRegions { tcx: self.fcx.tcx }.fold_ty(t)
tcx.fold_regions(t, |_, _| tcx.lifetimes.re_erased)
}
}
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.fcx.tcx }.fold_ty(t)
tcx.fold_regions(t, |_, _| tcx.lifetimes.re_erased)
}
Err(_) => {
debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/errors/note_and_explain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl<'a> DescriptionCtx<'a> {
// We shouldn't really be having unification failures with ReVar
// and ReBound though.
//
// FIXME(@lcnr): figure out why we `ReBound` have to handle `ReBound`
// FIXME(@lcnr): figure out why we have to handle `ReBound`
// here, this feels somewhat off.
ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => {
(alt_span, "revar", format!("{region:?}"))
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_lint/src/foreign_modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,8 @@ fn structurally_same_type_impl<'tcx>(

// We don't compare regions, but leaving bound regions around ICEs, so
// we erase them.
let a_sig = tcx.erase_late_bound_regions(a_poly_sig);
let b_sig = tcx.erase_late_bound_regions(b_poly_sig);
let a_sig = tcx.instantiate_bound_regions_with_erased(a_poly_sig);
let b_sig = tcx.instantiate_bound_regions_with_erased(b_poly_sig);

(a_sig.abi, a_sig.unsafety, a_sig.c_variadic)
== (b_sig.abi, b_sig.unsafety, b_sig.c_variadic)
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1234,7 +1234,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
};
}

let sig = tcx.erase_late_bound_regions(sig);
let sig = tcx.instantiate_bound_regions_with_erased(sig);
for arg in sig.inputs() {
match self.check_type_for_ffi(cache, *arg) {
FfiSafe => {}
Expand Down Expand Up @@ -1391,7 +1391,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
/// types that have external ABIs, as these still need checked.
fn check_fn(&mut self, def_id: LocalDefId, decl: &'tcx hir::FnDecl<'_>) {
let sig = self.cx.tcx.fn_sig(def_id).instantiate_identity();
let sig = self.cx.tcx.erase_late_bound_regions(sig);
let sig = self.cx.tcx.instantiate_bound_regions_with_erased(sig);

for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) {
for (fn_ptr_ty, span) in self.find_fn_ptr_ty_with_external_abi(input_hir, *input_ty) {
Expand All @@ -1409,7 +1409,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
/// Check if a function's argument types and result type are "ffi-safe".
fn check_foreign_fn(&mut self, def_id: LocalDefId, decl: &'tcx hir::FnDecl<'_>) {
let sig = self.cx.tcx.fn_sig(def_id).instantiate_identity();
let sig = self.cx.tcx.erase_late_bound_regions(sig);
let sig = self.cx.tcx.instantiate_bound_regions_with_erased(sig);

for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) {
self.check_type_for_ffi_and_report_errors(input_hir.span, *input_ty, false, false);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/native_libs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ impl<'tcx> Collector<'tcx> {
}

fn i686_arg_list_size(&self, item: DefId) -> usize {
let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions(
let argument_types: &List<Ty<'_>> = self.tcx.instantiate_bound_regions_with_erased(
self.tcx
.type_of(item)
.instantiate_identity()
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_middle/src/ty/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ impl<'tcx> TyCtxt<'tcx> {
///
/// This method only replaces late bound regions. Any types or
/// constants bound by `value` will cause an ICE.
pub fn replace_late_bound_regions<T, F>(
pub fn instantiate_bound_regions<T, F>(
self,
value: Binder<'tcx, T>,
mut fld_r: F,
Expand All @@ -261,11 +261,11 @@ impl<'tcx> TyCtxt<'tcx> {
{
let mut region_map = BTreeMap::new();
let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
let value = self.replace_late_bound_regions_uncached(value, real_fld_r);
let value = self.instantiate_bound_regions_uncached(value, real_fld_r);
(value, region_map)
}

pub fn replace_late_bound_regions_uncached<T, F>(
pub fn instantiate_bound_regions_uncached<T, F>(
self,
value: Binder<'tcx, T>,
mut replace_regions: F,
Expand Down Expand Up @@ -325,7 +325,7 @@ impl<'tcx> TyCtxt<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
self.replace_late_bound_regions_uncached(value, |br| {
self.instantiate_bound_regions_uncached(value, |br| {
ty::Region::new_late_param(self, all_outlive_scope, br.kind)
})
}
Expand Down Expand Up @@ -361,11 +361,11 @@ impl<'tcx> TyCtxt<'tcx> {

/// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also
/// method lookup and a few other places where precise region relationships are not required.
pub fn erase_late_bound_regions<T>(self, value: Binder<'tcx, T>) -> T
pub fn instantiate_bound_regions_with_erased<T>(self, value: Binder<'tcx, T>) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0
self.instantiate_bound_regions(value, |_| self.lifetimes.re_erased).0
}

/// Anonymize all bound variables in `value`, this is mostly used to improve caching.
Expand Down
Loading

0 comments on commit 069a4af

Please sign in to comment.