Skip to content

Commit 85c5dfc

Browse files
committed
Auto merge of #125468 - BoxyUwU:remove_defid_from_regionparam, r=<try>
Remove `DefId` from `EarlyParamRegion` Currently we represent usages of `Region` parameters via the `ReEarlyParam` or `ReLateParam` variants. The `ReEarlyParam` is effectively equivalent to `TyKind::Param` and `ConstKind::Param` (i.e. it stores a `Symbol` and a `u32` index) however it also stores a `DefId` for the definition of the lifetime parameter. This was used in roughly two places: - Borrowck diagnostics instead of threading the appropriate `body_id` down to relevant locations. Interestingly there were already some places that had to pass down a `DefId` manually. - Some opaque type checking logic was using the `DefId` field to track captured lifetimes I've split this PR up into a commit for generate rote changes to diagnostics code to pass around a `DefId` manually everywhere, and another commit for the opaque type related changes which likely require more careful review as they might change the semantics of lints/errors. Instead of manually passing the `DefId` around everywhere I previously tried to bundle it in with `TypeErrCtxt` but ran into issues with some call sites of `infcx.err_ctxt` being unable to provide a `DefId`, particularly places involved with trait solving and normalization. It might be worth investigating adding some new wrapper type to pass this around everywhere but I think this might be acceptable for now. This pr also has the effect of reducing the size of `EarlyParamRegion` from 16 bytes -> 8 bytes. I wouldn't expect this to have any direct performance improvement however, other variants of `RegionKind` over `8` bytes are all because they contain a `BoundRegionKind` which is, as far as I know, mostly there for diagnostics. If we're ever able to remove this it would shrink the `RegionKind` type from `24` bytes to `12` (and with clever bit packing we might be able to get it to `8` bytes). I am curious what the performance impact would be of removing interning of `Region`'s if we ever manage to shrink `RegionKind` that much. Sidenote: by removing the `DefId` the `Debug` output for `Region` has gotten significantly nicer. As an example see this opaque type debug print before vs after this PR: `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a)_'a/#0, T, DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a)_'a/#0])` `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), ['a/#0, T, 'a/#0])` r? `@compiler-errors` (I would like someone who understands the opaque type setup to atleast review the type system commit, but the rest is likely reviewable by anyone)
2 parents 8679004 + 5451787 commit 85c5dfc

File tree

31 files changed

+330
-189
lines changed

31 files changed

+330
-189
lines changed

compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

+22-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_errors::Diag;
2+
use rustc_hir::def_id::LocalDefId;
23
use rustc_infer::infer::canonical::Canonical;
34
use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
45
use rustc_infer::infer::region_constraints::Constraint;
@@ -241,7 +242,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
241242
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
242243
let ocx = ObligationCtxt::new(&infcx);
243244
type_op_prove_predicate_with_cause(&ocx, key, cause);
244-
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
245+
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region, mbcx.mir_def_id())
245246
}
246247
}
247248

@@ -287,7 +288,7 @@ where
287288
let (param_env, value) = key.into_parts();
288289
let _ = ocx.normalize(&cause, param_env, value.value);
289290

290-
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
291+
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region, mbcx.mir_def_id())
291292
}
292293
}
293294

@@ -318,7 +319,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
318319
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
319320
let ocx = ObligationCtxt::new(&infcx);
320321
type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?;
321-
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
322+
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region, mbcx.mir_def_id())
322323
}
323324
}
324325

@@ -351,6 +352,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
351352
// our `mbcx` instead.
352353
|vid| mbcx.regioncx.var_infos[vid].origin,
353354
|vid| mbcx.regioncx.var_infos[vid].universe,
355+
mbcx.mir_def_id(),
354356
)
355357
}
356358
}
@@ -360,6 +362,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
360362
ocx: &ObligationCtxt<'_, 'tcx>,
361363
placeholder_region: ty::Region<'tcx>,
362364
error_region: Option<ty::Region<'tcx>>,
365+
generic_param_scope: LocalDefId,
363366
) -> Option<Diag<'tcx>> {
364367
// We generally shouldn't have errors here because the query was
365368
// already run, but there's no point using `span_delayed_bug`
@@ -373,6 +376,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
373376
&region_constraints,
374377
|vid| ocx.infcx.region_var_origin(vid),
375378
|vid| ocx.infcx.universe_of_region(ty::Region::new_var(ocx.infcx.tcx, vid)),
379+
generic_param_scope,
376380
)
377381
}
378382

@@ -384,6 +388,7 @@ fn try_extract_error_from_region_constraints<'tcx>(
384388
region_constraints: &RegionConstraintData<'tcx>,
385389
mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin,
386390
mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex,
391+
generic_param_scope: LocalDefId,
387392
) -> Option<Diag<'tcx>> {
388393
let placeholder_universe = match placeholder_region.kind() {
389394
ty::RePlaceholder(p) => p.universe,
@@ -452,15 +457,18 @@ fn try_extract_error_from_region_constraints<'tcx>(
452457
RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region)
453458
}
454459
};
455-
NiceRegionError::new(&infcx.err_ctxt(), error).try_report_from_nll().or_else(|| {
456-
if let SubregionOrigin::Subtype(trace) = cause {
457-
Some(
458-
infcx
459-
.err_ctxt()
460-
.report_and_explain_type_error(*trace, TypeError::RegionsPlaceholderMismatch),
461-
)
462-
} else {
463-
None
464-
}
465-
})
460+
NiceRegionError::new(&infcx.err_ctxt(), error, generic_param_scope)
461+
.try_report_from_nll()
462+
.or_else(|| {
463+
if let SubregionOrigin::Subtype(trace) = cause {
464+
Some(
465+
infcx.err_ctxt().report_and_explain_type_error(
466+
*trace,
467+
TypeError::RegionsPlaceholderMismatch,
468+
),
469+
)
470+
} else {
471+
None
472+
}
473+
})
466474
}

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

+24-15
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
362362
let diag = unexpected_hidden_region_diagnostic(
363363
self.infcx.tcx,
364364
span,
365+
self.mir_def_id(),
365366
named_ty,
366367
named_region,
367368
named_key,
@@ -453,7 +454,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
453454
// Check if we can use one of the "nice region errors".
454455
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
455456
let infer_err = self.infcx.err_ctxt();
456-
let nice = NiceRegionError::new_from_span(&infer_err, cause.span, o, f);
457+
let nice =
458+
NiceRegionError::new_from_span(&infer_err, self.mir_def_id(), cause.span, o, f);
457459
if let Some(diag) = nice.try_report_from_nll() {
458460
self.buffer_error(diag);
459461
return;
@@ -843,14 +845,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
843845
if *outlived_f != ty::ReStatic {
844846
return;
845847
}
846-
let suitable_region = self.infcx.tcx.is_suitable_region(f);
848+
let suitable_region = self.infcx.tcx.is_suitable_region(f, self.mir_def_id());
847849
let Some(suitable_region) = suitable_region else {
848850
return;
849851
};
850852

851853
let fn_returns = self.infcx.tcx.return_type_impl_or_dyn_traits(suitable_region.def_id);
852854

853-
let param = if let Some(param) = find_param_with_region(self.infcx.tcx, f, outlived_f) {
855+
let param = if let Some(param) =
856+
find_param_with_region(self.infcx.tcx, f, outlived_f, self.mir_def_id())
857+
{
854858
param
855859
} else {
856860
return;
@@ -959,7 +963,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
959963
return;
960964
};
961965

962-
let param = match find_param_with_region(tcx, f, o) {
966+
let param = match find_param_with_region(tcx, f, o, self.mir_def_id()) {
963967
Some(param) => param,
964968
None => return,
965969
};
@@ -1022,25 +1026,30 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
10221026
return;
10231027
};
10241028

1025-
let Some((ty_sub, _)) = self
1026-
.infcx
1027-
.tcx
1028-
.is_suitable_region(sub)
1029-
.and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.bound_region))
1029+
let Some((ty_sub, _)) =
1030+
self.infcx.tcx.is_suitable_region(sub, self.mir_def_id()).and_then(|anon_reg| {
1031+
find_anon_type(self.infcx.tcx, sub, &anon_reg.bound_region, self.mir_def_id())
1032+
})
10301033
else {
10311034
return;
10321035
};
10331036

1034-
let Some((ty_sup, _)) = self
1035-
.infcx
1036-
.tcx
1037-
.is_suitable_region(sup)
1038-
.and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.bound_region))
1037+
let Some((ty_sup, _)) =
1038+
self.infcx.tcx.is_suitable_region(sup, self.mir_def_id()).and_then(|anon_reg| {
1039+
find_anon_type(self.infcx.tcx, sup, &anon_reg.bound_region, self.mir_def_id())
1040+
})
10391041
else {
10401042
return;
10411043
};
10421044

1043-
suggest_adding_lifetime_params(self.infcx.tcx, sub, ty_sup, ty_sub, diag);
1045+
suggest_adding_lifetime_params(
1046+
self.infcx.tcx,
1047+
sub,
1048+
ty_sup,
1049+
ty_sub,
1050+
self.mir_def_id(),
1051+
diag,
1052+
);
10441053
}
10451054

10461055
#[allow(rustc::diagnostic_outside_of_impl)]

compiler/rustc_borrowck/src/diagnostics/region_name.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
289289
debug!("give_region_a_name: error_region = {:?}", error_region);
290290
match *error_region {
291291
ty::ReEarlyParam(ebr) => ebr.has_name().then(|| {
292-
let span = tcx.hir().span_if_local(ebr.def_id).unwrap_or(DUMMY_SP);
292+
let def_id = tcx.generics_of(self.mir_def_id()).region_param(ebr, tcx).def_id;
293+
let span = tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
293294
RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyParamRegion(span) }
294295
}),
295296

@@ -912,7 +913,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
912913
};
913914

914915
let tcx = self.infcx.tcx;
915-
let region_parent = tcx.parent(region.def_id);
916+
let region_def = tcx.generics_of(self.mir_def_id()).region_param(region, tcx).def_id;
917+
let region_parent = tcx.parent(region_def);
916918
let DefKind::Impl { .. } = tcx.def_kind(region_parent) else {
917919
return None;
918920
};
@@ -925,7 +927,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
925927
Some(RegionName {
926928
name: self.synthesize_region_name(),
927929
source: RegionNameSource::AnonRegionFromImplSignature(
928-
tcx.def_span(region.def_id),
930+
tcx.def_span(region_def),
929931
// FIXME(compiler-errors): Does this ever actually show up
930932
// anywhere other than the self type? I couldn't create an
931933
// example of a `'_` in the impl's trait being referenceable.

compiler/rustc_hir_analysis/src/check/check.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -538,11 +538,9 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
538538
// the cases that were stabilized with the `impl_trait_projection`
539539
// feature -- see <https://github.com/rust-lang/rust/pull/115659>.
540540
if let DefKind::LifetimeParam = tcx.def_kind(def_id)
541-
&& let ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
542-
| ty::ReLateParam(ty::LateParamRegion {
543-
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
544-
..
545-
}) = *tcx.map_opaque_lifetime_to_parent_lifetime(def_id.expect_local())
541+
&& let Some(def_id) = tcx
542+
.map_opaque_lifetime_to_parent_lifetime(def_id.expect_local())
543+
.opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id()))
546544
{
547545
shadowed_captures.insert(def_id);
548546
}
@@ -585,12 +583,9 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
585583
// Check if the lifetime param was captured but isn't named in the precise captures list.
586584
if variances[param.index as usize] == ty::Invariant {
587585
if let DefKind::OpaqueTy = tcx.def_kind(tcx.parent(param.def_id))
588-
&& let ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
589-
| ty::ReLateParam(ty::LateParamRegion {
590-
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
591-
..
592-
}) = *tcx
586+
&& let Some(def_id) = tcx
593587
.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local())
588+
.opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id()))
594589
{
595590
tcx.dcx().emit_err(errors::LifetimeNotCaptured {
596591
opaque_span,

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,8 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
876876
ty::ReLateParam(_) => {}
877877
// Remap early-bound regions as long as they don't come from the `impl` itself,
878878
// in which case we don't really need to renumber them.
879-
ty::ReEarlyParam(ebr) if self.tcx.parent(ebr.def_id) != self.impl_def_id => {}
879+
ty::ReEarlyParam(ebr)
880+
if ebr.index >= self.tcx.generics_of(self.impl_def_id).count() as u32 => {}
880881
_ => return Ok(region),
881882
}
882883

@@ -889,12 +890,8 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
889890
);
890891
}
891892
} else {
892-
let guar = match region.kind() {
893-
ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
894-
| ty::ReLateParam(ty::LateParamRegion {
895-
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
896-
..
897-
}) => {
893+
let guar = match region.opt_param_def_id(self.tcx, self.tcx.parent(self.def_id)) {
894+
Some(def_id) => {
898895
let return_span = if let ty::Alias(ty::Opaque, opaque_ty) = self.ty.kind() {
899896
self.tcx.def_span(opaque_ty.def_id)
900897
} else {
@@ -914,7 +911,7 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
914911
.with_note(format!("hidden type inferred to be `{}`", self.ty))
915912
.emit()
916913
}
917-
_ => {
914+
None => {
918915
// This code path is not reached in any tests, but may be
919916
// reachable. If this is triggered, it should be converted
920917
// to `delayed_bug` and the triggering case turned into a
@@ -928,7 +925,6 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
928925
Ok(ty::Region::new_early_param(
929926
self.tcx,
930927
ty::EarlyParamRegion {
931-
def_id: e.def_id,
932928
name: e.name,
933929
index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32,
934930
},

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+10-24
Original file line numberDiff line numberDiff line change
@@ -675,11 +675,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
675675
let region_param = gat_generics.param_at(*region_a_idx, tcx);
676676
let region_param = ty::Region::new_early_param(
677677
tcx,
678-
ty::EarlyParamRegion {
679-
def_id: region_param.def_id,
680-
index: region_param.index,
681-
name: region_param.name,
682-
},
678+
ty::EarlyParamRegion { index: region_param.index, name: region_param.name },
683679
);
684680
// The predicate we expect to see. (In our example,
685681
// `Self: 'me`.)
@@ -708,21 +704,13 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
708704
let region_a_param = gat_generics.param_at(*region_a_idx, tcx);
709705
let region_a_param = ty::Region::new_early_param(
710706
tcx,
711-
ty::EarlyParamRegion {
712-
def_id: region_a_param.def_id,
713-
index: region_a_param.index,
714-
name: region_a_param.name,
715-
},
707+
ty::EarlyParamRegion { index: region_a_param.index, name: region_a_param.name },
716708
);
717709
// Same for the region.
718710
let region_b_param = gat_generics.param_at(*region_b_idx, tcx);
719711
let region_b_param = ty::Region::new_early_param(
720712
tcx,
721-
ty::EarlyParamRegion {
722-
def_id: region_b_param.def_id,
723-
index: region_b_param.index,
724-
name: region_b_param.name,
725-
},
713+
ty::EarlyParamRegion { index: region_b_param.index, name: region_b_param.name },
726714
);
727715
// The predicate we expect to see.
728716
bounds.insert(
@@ -2101,16 +2089,14 @@ fn lint_redundant_lifetimes<'tcx>(
21012089
}
21022090

21032091
for &victim in &lifetimes[(idx + 1)..] {
2104-
// We should only have late-bound lifetimes of the `BrNamed` variety,
2105-
// since we get these signatures straight from `hir_lowering`. And any
2106-
// other regions (ReError/ReStatic/etc.) shouldn't matter, since we
2092+
// All region parameters should have a `DefId` available as:
2093+
// - Late-bound parameters should be of the`BrNamed` variety,
2094+
// since we get these signatures straight from `hir_lowering`.
2095+
// - Early-bound parameters unconditionally have a `DefId` available.
2096+
//
2097+
// Any other regions (ReError/ReStatic/etc.) shouldn't matter, since we
21072098
// can't really suggest to remove them.
2108-
let (ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
2109-
| ty::ReLateParam(ty::LateParamRegion {
2110-
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
2111-
..
2112-
})) = victim.kind()
2113-
else {
2099+
let Some(def_id) = victim.opt_param_def_id(tcx, owner_id.to_def_id()) else {
21142100
continue;
21152101
};
21162102

compiler/rustc_hir_analysis/src/collect.rs

-1
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,6 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
453453
poly_trait_ref,
454454
|_| {
455455
ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion {
456-
def_id: item_def_id,
457456
index: 0,
458457
name: Symbol::intern(&lt_name),
459458
})

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ fn compute_bidirectional_outlives_predicates<'tcx>(
323323
if let ty::ReEarlyParam(..) = *orig_lifetime {
324324
let dup_lifetime = ty::Region::new_early_param(
325325
tcx,
326-
ty::EarlyParamRegion { def_id: param.def_id, index: param.index, name: param.name },
326+
ty::EarlyParamRegion { index: param.index, name: param.name },
327327
);
328328
let span = tcx.def_span(param.def_id);
329329
predicates.push((

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
280280
let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
281281
let generics = tcx.generics_of(item_def_id);
282282
let index = generics.param_def_id_to_index[&def_id];
283-
ty::Region::new_early_param(tcx, ty::EarlyParamRegion { def_id, index, name })
283+
ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name })
284284
}
285285

286286
Some(rbv::ResolvedArg::Free(scope, id)) => {

compiler/rustc_infer/src/errors/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_errors::{
55
MultiSpan, SubdiagMessageOp, Subdiagnostic,
66
};
77
use rustc_hir as hir;
8+
use rustc_hir::def_id::LocalDefId;
89
use rustc_hir::intravisit::{walk_ty, Visitor};
910
use rustc_hir::FnRetTy;
1011
use rustc_macros::{Diagnostic, Subdiagnostic};
@@ -348,6 +349,7 @@ pub struct AddLifetimeParamsSuggestion<'a> {
348349
pub ty_sup: &'a hir::Ty<'a>,
349350
pub ty_sub: &'a hir::Ty<'a>,
350351
pub add_note: bool,
352+
pub generic_param_scope: LocalDefId,
351353
}
352354

353355
impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
@@ -357,7 +359,8 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
357359
_f: &F,
358360
) {
359361
let mut mk_suggestion = || {
360-
let Some(anon_reg) = self.tcx.is_suitable_region(self.sub) else {
362+
let Some(anon_reg) = self.tcx.is_suitable_region(self.sub, self.generic_param_scope)
363+
else {
361364
return false;
362365
};
363366

0 commit comments

Comments
 (0)