Skip to content

some additional region refactorings #117944

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

Merged
merged 2 commits into from
Nov 17, 2023
Merged
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
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