Skip to content

Commit

Permalink
Auto merge of rust-lang#133961 - lcnr:borrowck-cleanup, r=jackh726
Browse files Browse the repository at this point in the history
cleanup region handling: add `LateParamRegionKind`

The second commit is to enable a split between `BoundRegionKind` and `LateParamRegionKind`, by avoiding `BoundRegionKind` where it isn't necessary.

The third comment then adds `LateParamRegionKind` to avoid having the same late-param region for separate bound regions. This fixes rust-lang#124021.

r? `@compiler-errors`
  • Loading branch information
bors committed Dec 19, 2024
2 parents bab18a5 + 4d5aaa0 commit a4079b2
Show file tree
Hide file tree
Showing 23 changed files with 194 additions and 66 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
/// Returns `true` if a closure is inferred to be an `FnMut` closure.
fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
if let Some(ty::ReLateParam(late_param)) = self.to_error_region(fr).as_deref()
&& let ty::BoundRegionKind::ClosureEnv = late_param.bound_region
&& let ty::LateParamRegionKind::ClosureEnv = late_param.kind
&& let DefiningTy::Closure(_, args) = self.regioncx.universal_regions().defining_ty
{
return args.as_closure().kind() == ty::ClosureKind::FnMut;
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_borrowck/src/diagnostics/region_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,17 +299,17 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
Some(RegionName { name: kw::StaticLifetime, source: RegionNameSource::Static })
}

ty::ReLateParam(late_param) => match late_param.bound_region {
ty::BoundRegionKind::Named(region_def_id, name) => {
ty::ReLateParam(late_param) => match late_param.kind {
ty::LateParamRegionKind::Named(region_def_id, name) => {
// Get the span to point to, even if we don't use the name.
let span = tcx.hir().span_if_local(region_def_id).unwrap_or(DUMMY_SP);
debug!(
"bound region named: {:?}, is_named: {:?}",
name,
late_param.bound_region.is_named()
late_param.kind.is_named()
);

if late_param.bound_region.is_named() {
if late_param.kind.is_named() {
// A named region that is actually named.
Some(RegionName {
name,
Expand All @@ -331,7 +331,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
}
}

ty::BoundRegionKind::ClosureEnv => {
ty::LateParamRegionKind::ClosureEnv => {
let def_ty = self.regioncx.universal_regions().defining_ty;

let closure_kind = match def_ty {
Expand Down Expand Up @@ -368,7 +368,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
})
}

ty::BoundRegionKind::Anon => None,
ty::LateParamRegionKind::Anon(_) => None,
},

ty::ReBound(..)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2230,7 +2230,7 @@ impl<'tcx> RegionDefinition<'tcx> {
fn new(universe: ty::UniverseIndex, rv_origin: RegionVariableOrigin) -> Self {
// Create a new region definition. Note that, for free
// regions, the `external_name` field gets updated later in
// `init_universal_regions`.
// `init_free_and_bound_regions`.

let origin = match rv_origin {
RegionVariableOrigin::Nll(origin) => origin,
Expand Down
18 changes: 10 additions & 8 deletions compiler/rustc_borrowck/src/universal_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -842,8 +842,9 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
{
let (value, _map) = self.tcx.instantiate_bound_regions(value, |br| {
debug!(?br);
let kind = ty::LateParamRegionKind::from_bound(br.var, br.kind);
let liberated_region =
ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), br.kind);
ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), kind);
let region_vid = {
let name = match br.kind.get_name() {
Some(name) => name,
Expand Down Expand Up @@ -941,12 +942,13 @@ fn for_each_late_bound_region_in_item<'tcx>(
return;
}

for bound_var in tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id)) {
let ty::BoundVariableKind::Region(bound_region) = bound_var else {
continue;
};
let liberated_region =
ty::Region::new_late_param(tcx, mir_def_id.to_def_id(), bound_region);
f(liberated_region);
for (idx, bound_var) in
tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id)).iter().enumerate()
{
if let ty::BoundVariableKind::Region(kind) = bound_var {
let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind);
let liberated_region = ty::Region::new_late_param(tcx, mir_def_id.to_def_id(), kind);
f(liberated_region);
}
}
}
8 changes: 4 additions & 4 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,12 +430,12 @@ fn compare_method_predicate_entailment<'tcx>(
Ok(())
}

struct RemapLateBound<'a, 'tcx> {
struct RemapLateParam<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
mapping: &'a FxIndexMap<ty::BoundRegionKind, ty::BoundRegionKind>,
mapping: &'a FxIndexMap<ty::LateParamRegionKind, ty::LateParamRegionKind>,
}

impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> {
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateParam<'_, 'tcx> {
fn cx(&self) -> TyCtxt<'tcx> {
self.tcx
}
Expand All @@ -445,7 +445,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> {
ty::Region::new_late_param(
self.tcx,
fr.scope,
self.mapping.get(&fr.bound_region).copied().unwrap_or(fr.bound_region),
self.mapping.get(&fr.kind).copied().unwrap_or(fr.kind),
)
} else {
r
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,19 +289,24 @@ fn report_mismatched_rpitit_signature<'tcx>(
tcx.fn_sig(trait_m_def_id).skip_binder().bound_vars(),
tcx.fn_sig(impl_m_def_id).skip_binder().bound_vars(),
)
.filter_map(|(impl_bv, trait_bv)| {
.enumerate()
.filter_map(|(idx, (impl_bv, trait_bv))| {
if let ty::BoundVariableKind::Region(impl_bv) = impl_bv
&& let ty::BoundVariableKind::Region(trait_bv) = trait_bv
{
Some((impl_bv, trait_bv))
let var = ty::BoundVar::from_usize(idx);
Some((
ty::LateParamRegionKind::from_bound(var, impl_bv),
ty::LateParamRegionKind::from_bound(var, trait_bv),
))
} else {
None
}
})
.collect();

let mut return_ty =
trait_m_sig.output().fold_with(&mut super::RemapLateBound { tcx, mapping: &mapping });
trait_m_sig.output().fold_with(&mut super::RemapLateParam { tcx, mapping: &mapping });

if tcx.asyncness(impl_m_def_id).is_async() && tcx.asyncness(trait_m_def_id).is_async() {
let ty::Alias(ty::Projection, future_ty) = return_ty.kind() else {
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2339,8 +2339,11 @@ fn lint_redundant_lifetimes<'tcx>(
);
// If we are in a function, add its late-bound lifetimes too.
if matches!(def_kind, DefKind::Fn | DefKind::AssocFn) {
for var in tcx.fn_sig(owner_id).instantiate_identity().bound_vars() {
for (idx, var) in
tcx.fn_sig(owner_id).instantiate_identity().bound_vars().iter().enumerate()
{
let ty::BoundVariableKind::Region(kind) = var else { continue };
let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind);
lifetimes.push(ty::Region::new_late_param(tcx, owner_id.to_def_id(), kind));
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
ty::Region::new_late_param(
tcx,
scope.to_def_id(),
ty::BoundRegionKind::Named(id.to_def_id(), name),
ty::LateParamRegionKind::Named(id.to_def_id(), name),
)

// (*) -- not late-bound, won't change
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_lint/src/impl_trait_overcaptures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ where
ParamKind::Free(def_id, name) => ty::Region::new_late_param(
self.tcx,
self.parent_def_id.to_def_id(),
ty::BoundRegionKind::Named(def_id, name),
ty::LateParamRegionKind::Named(def_id, name),
),
// Totally ignore late bound args from binders.
ParamKind::Late => return true,
Expand Down Expand Up @@ -475,7 +475,7 @@ fn extract_def_id_from_arg<'tcx>(
)
| ty::ReLateParam(ty::LateParamRegion {
scope: _,
bound_region: ty::BoundRegionKind::Named(def_id, ..),
kind: ty::LateParamRegionKind::Named(def_id, ..),
}) => def_id,
_ => unreachable!(),
},
Expand Down Expand Up @@ -544,7 +544,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for FunctionalVariances<'tcx> {
)
| ty::ReLateParam(ty::LateParamRegion {
scope: _,
bound_region: ty::BoundRegionKind::Named(def_id, ..),
kind: ty::LateParamRegionKind::Named(def_id, ..),
}) => def_id,
_ => {
return Ok(a);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3091,7 +3091,7 @@ impl<'tcx> TyCtxt<'tcx> {
return ty::Region::new_late_param(
self,
new_parent.to_def_id(),
ty::BoundRegionKind::Named(
ty::LateParamRegionKind::Named(
lbv.to_def_id(),
self.item_name(lbv.to_def_id()),
),
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/ty/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@ impl<'tcx> TyCtxt<'tcx> {
T: TypeFoldable<TyCtxt<'tcx>>,
{
self.instantiate_bound_regions_uncached(value, |br| {
ty::Region::new_late_param(self, all_outlive_scope, br.kind)
let kind = ty::LateParamRegionKind::from_bound(br.var, br.kind);
ty::Region::new_late_param(self, all_outlive_scope, kind)
})
}

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ pub use self::predicate::{
TypeOutlivesPredicate,
};
pub use self::region::{
BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, Region, RegionKind, RegionVid,
BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region,
RegionKind, RegionVid,
};
pub use self::rvalue_scopes::RvalueScopes;
pub use self::sty::{
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2374,8 +2374,8 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
match *region {
ty::ReEarlyParam(ref data) => data.has_name(),

ty::ReLateParam(ty::LateParamRegion { kind, .. }) => kind.is_named(),
ty::ReBound(_, ty::BoundRegion { kind: br, .. })
| ty::ReLateParam(ty::LateParamRegion { bound_region: br, .. })
| ty::RePlaceholder(ty::Placeholder {
bound: ty::BoundRegion { kind: br, .. }, ..
}) => {
Expand Down Expand Up @@ -2448,8 +2448,13 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
return Ok(());
}
}
ty::ReLateParam(ty::LateParamRegion { kind, .. }) => {
if let Some(name) = kind.get_name() {
p!(write("{}", name));
return Ok(());
}
}
ty::ReBound(_, ty::BoundRegion { kind: br, .. })
| ty::ReLateParam(ty::LateParamRegion { bound_region: br, .. })
| ty::RePlaceholder(ty::Placeholder {
bound: ty::BoundRegion { kind: br, .. }, ..
}) => {
Expand Down
81 changes: 73 additions & 8 deletions compiler/rustc_middle/src/ty/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ impl<'tcx> Region<'tcx> {
pub fn new_late_param(
tcx: TyCtxt<'tcx>,
scope: DefId,
bound_region: ty::BoundRegionKind,
kind: LateParamRegionKind,
) -> Region<'tcx> {
tcx.intern_region(ty::ReLateParam(ty::LateParamRegion { scope, bound_region }))
let data = LateParamRegion { scope, kind };
tcx.intern_region(ty::ReLateParam(data))
}

#[inline]
Expand Down Expand Up @@ -124,8 +125,8 @@ impl<'tcx> Region<'tcx> {
match kind {
ty::ReEarlyParam(region) => Region::new_early_param(tcx, region),
ty::ReBound(debruijn, region) => Region::new_bound(tcx, debruijn, region),
ty::ReLateParam(ty::LateParamRegion { scope, bound_region }) => {
Region::new_late_param(tcx, scope, bound_region)
ty::ReLateParam(ty::LateParamRegion { scope, kind }) => {
Region::new_late_param(tcx, scope, kind)
}
ty::ReStatic => tcx.lifetimes.re_static,
ty::ReVar(vid) => Region::new_var(tcx, vid),
Expand Down Expand Up @@ -165,7 +166,7 @@ impl<'tcx> Region<'tcx> {
match *self {
ty::ReEarlyParam(ebr) => Some(ebr.name),
ty::ReBound(_, br) => br.kind.get_name(),
ty::ReLateParam(fr) => fr.bound_region.get_name(),
ty::ReLateParam(fr) => fr.kind.get_name(),
ty::ReStatic => Some(kw::StaticLifetime),
ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(),
_ => None,
Expand All @@ -187,7 +188,7 @@ impl<'tcx> Region<'tcx> {
match *self {
ty::ReEarlyParam(ebr) => ebr.has_name(),
ty::ReBound(_, br) => br.kind.is_named(),
ty::ReLateParam(fr) => fr.bound_region.is_named(),
ty::ReLateParam(fr) => fr.kind.is_named(),
ty::ReStatic => true,
ty::ReVar(..) => false,
ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(),
Expand Down Expand Up @@ -310,7 +311,7 @@ impl<'tcx> Region<'tcx> {
Some(tcx.generics_of(binding_item).region_param(ebr, tcx).def_id)
}
ty::ReLateParam(ty::LateParamRegion {
bound_region: ty::BoundRegionKind::Named(def_id, _),
kind: ty::LateParamRegionKind::Named(def_id, _),
..
}) => Some(def_id),
_ => None,
Expand Down Expand Up @@ -358,7 +359,71 @@ impl std::fmt::Debug for EarlyParamRegion {
/// different parameters apart.
pub struct LateParamRegion {
pub scope: DefId,
pub bound_region: BoundRegionKind,
pub kind: LateParamRegionKind,
}

/// When liberating bound regions, we map their [`BoundRegionKind`]
/// to this as we need to track the index of anonymous regions. We
/// otherwise end up liberating multiple bound regions to the same
/// late-bound region.
#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Copy)]
#[derive(HashStable)]
pub enum LateParamRegionKind {
/// An anonymous region parameter for a given fn (&T)
///
/// Unlike [`BoundRegionKind::Anon`], this tracks the index of the
/// liberated bound region.
///
/// We should ideally never liberate anonymous regions, but do so for the
/// sake of diagnostics in `FnCtxt::sig_of_closure_with_expectation`.
Anon(u32),

/// Named region parameters for functions (a in &'a T)
///
/// The `DefId` is needed to distinguish free regions in
/// the event of shadowing.
Named(DefId, Symbol),

/// Anonymous region for the implicit env pointer parameter
/// to a closure
ClosureEnv,
}

impl LateParamRegionKind {
pub fn from_bound(var: BoundVar, br: BoundRegionKind) -> LateParamRegionKind {
match br {
BoundRegionKind::Anon => LateParamRegionKind::Anon(var.as_u32()),
BoundRegionKind::Named(def_id, name) => LateParamRegionKind::Named(def_id, name),
BoundRegionKind::ClosureEnv => LateParamRegionKind::ClosureEnv,
}
}

pub fn is_named(&self) -> bool {
match *self {
LateParamRegionKind::Named(_, name) => {
name != kw::UnderscoreLifetime && name != kw::Empty
}
_ => false,
}
}

pub fn get_name(&self) -> Option<Symbol> {
if self.is_named() {
match *self {
LateParamRegionKind::Named(_, name) => return Some(name),
_ => unreachable!(),
}
}

None
}

pub fn get_id(&self) -> Option<DefId> {
match *self {
LateParamRegionKind::Named(id, _) => Some(id),
_ => None,
}
}
}

#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Copy)]
Expand Down
18 changes: 17 additions & 1 deletion compiler/rustc_middle/src/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,23 @@ impl fmt::Debug for ty::BoundRegionKind {

impl fmt::Debug for ty::LateParamRegion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ReLateParam({:?}, {:?})", self.scope, self.bound_region)
write!(f, "ReLateParam({:?}, {:?})", self.scope, self.kind)
}
}

impl fmt::Debug for ty::LateParamRegionKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
ty::LateParamRegionKind::Anon(idx) => write!(f, "BrAnon({idx})"),
ty::LateParamRegionKind::Named(did, name) => {
if did.is_crate_root() {
write!(f, "BrNamed({name})")
} else {
write!(f, "BrNamed({did:?}, {name})")
}
}
ty::LateParamRegionKind::ClosureEnv => write!(f, "BrEnv"),
}
}
}

Expand Down
Loading

0 comments on commit a4079b2

Please sign in to comment.