diff options
| author | bors <bors@rust-lang.org> | 2024-05-27 06:36:57 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-05-27 06:36:57 +0000 |
| commit | fec98b3bbc94b54a0b3085d004708aabcc48081a (patch) | |
| tree | 3e65f2ec3e9afc8132a161fc8afb97ec43d17515 | |
| parent | cdc509f7c09361466d543fc8311ce7066b10cc4f (diff) | |
| parent | ed8e43691632645d7ca3cf0583a1a822d2eb3c48 (diff) | |
| download | rust-fec98b3bbc94b54a0b3085d004708aabcc48081a.tar.gz rust-fec98b3bbc94b54a0b3085d004708aabcc48081a.zip | |
Auto merge of #125468 - BoxyUwU:remove_defid_from_regionparam, r=compiler-errors
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)
31 files changed, 320 insertions, 212 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 9b8b7e8ddda..5e10f14f31b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -1,4 +1,5 @@ use rustc_errors::Diag; +use rustc_hir::def_id::LocalDefId; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError; use rustc_infer::infer::region_constraints::Constraint; @@ -241,7 +242,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); let ocx = ObligationCtxt::new(&infcx); type_op_prove_predicate_with_cause(&ocx, key, cause); - try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region) + try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region) } } @@ -287,7 +288,7 @@ where let (param_env, value) = key.into_parts(); let _ = ocx.normalize(&cause, param_env, value.value); - try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region) + try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region) } } @@ -318,7 +319,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); let ocx = ObligationCtxt::new(&infcx); type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?; - try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region) + try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region) } } @@ -342,6 +343,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { ) -> Option<Diag<'tcx>> { try_extract_error_from_region_constraints( mbcx.infcx, + mbcx.mir_def_id(), placeholder_region, error_region, self.region_constraints.as_ref().unwrap(), @@ -358,6 +360,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { #[instrument(skip(ocx), level = "debug")] fn try_extract_error_from_fulfill_cx<'tcx>( ocx: &ObligationCtxt<'_, 'tcx>, + generic_param_scope: LocalDefId, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, ) -> Option<Diag<'tcx>> { @@ -368,6 +371,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>( let region_constraints = ocx.infcx.with_region_constraints(|r| r.clone()); try_extract_error_from_region_constraints( ocx.infcx, + generic_param_scope, placeholder_region, error_region, ®ion_constraints, @@ -379,6 +383,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>( #[instrument(level = "debug", skip(infcx, region_var_origin, universe_of_region))] fn try_extract_error_from_region_constraints<'tcx>( infcx: &InferCtxt<'tcx>, + generic_param_scope: LocalDefId, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, region_constraints: &RegionConstraintData<'tcx>, @@ -452,15 +457,18 @@ fn try_extract_error_from_region_constraints<'tcx>( RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region) } }; - NiceRegionError::new(&infcx.err_ctxt(), error).try_report_from_nll().or_else(|| { - if let SubregionOrigin::Subtype(trace) = cause { - Some( - infcx - .err_ctxt() - .report_and_explain_type_error(*trace, TypeError::RegionsPlaceholderMismatch), - ) - } else { - None - } - }) + NiceRegionError::new(&infcx.err_ctxt(), generic_param_scope, error) + .try_report_from_nll() + .or_else(|| { + if let SubregionOrigin::Subtype(trace) = cause { + Some( + infcx.err_ctxt().report_and_explain_type_error( + *trace, + TypeError::RegionsPlaceholderMismatch, + ), + ) + } else { + None + } + }) } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 8112fb7b89c..e11e4a7247c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -361,6 +361,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region); let diag = unexpected_hidden_region_diagnostic( self.infcx.tcx, + self.mir_def_id(), span, named_ty, named_region, @@ -453,7 +454,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Check if we can use one of the "nice region errors". if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { let infer_err = self.infcx.err_ctxt(); - let nice = NiceRegionError::new_from_span(&infer_err, cause.span, o, f); + let nice = + NiceRegionError::new_from_span(&infer_err, self.mir_def_id(), cause.span, o, f); if let Some(diag) = nice.try_report_from_nll() { self.buffer_error(diag); return; @@ -843,14 +845,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if *outlived_f != ty::ReStatic { return; } - let suitable_region = self.infcx.tcx.is_suitable_region(f); + let suitable_region = self.infcx.tcx.is_suitable_region(self.mir_def_id(), f); let Some(suitable_region) = suitable_region else { return; }; let fn_returns = self.infcx.tcx.return_type_impl_or_dyn_traits(suitable_region.def_id); - let param = if let Some(param) = find_param_with_region(self.infcx.tcx, f, outlived_f) { + let param = if let Some(param) = + find_param_with_region(self.infcx.tcx, self.mir_def_id(), f, outlived_f) + { param } else { return; @@ -959,7 +963,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { return; }; - let param = match find_param_with_region(tcx, f, o) { + let param = match find_param_with_region(tcx, self.mir_def_id(), f, o) { Some(param) => param, None => return, }; @@ -1022,25 +1026,30 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { return; }; - let Some((ty_sub, _)) = self - .infcx - .tcx - .is_suitable_region(sub) - .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.bound_region)) + let Some((ty_sub, _)) = + self.infcx.tcx.is_suitable_region(self.mir_def_id(), sub).and_then(|anon_reg| { + find_anon_type(self.infcx.tcx, self.mir_def_id(), sub, &anon_reg.bound_region) + }) else { return; }; - let Some((ty_sup, _)) = self - .infcx - .tcx - .is_suitable_region(sup) - .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.bound_region)) + let Some((ty_sup, _)) = + self.infcx.tcx.is_suitable_region(self.mir_def_id(), sup).and_then(|anon_reg| { + find_anon_type(self.infcx.tcx, self.mir_def_id(), sup, &anon_reg.bound_region) + }) else { return; }; - suggest_adding_lifetime_params(self.infcx.tcx, sub, ty_sup, ty_sub, diag); + suggest_adding_lifetime_params( + self.infcx.tcx, + diag, + self.mir_def_id(), + sub, + ty_sup, + ty_sub, + ); } #[allow(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 46011c1f43e..c2db64e7702 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -289,7 +289,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { debug!("give_region_a_name: error_region = {:?}", error_region); match *error_region { ty::ReEarlyParam(ebr) => ebr.has_name().then(|| { - let span = tcx.hir().span_if_local(ebr.def_id).unwrap_or(DUMMY_SP); + let def_id = tcx.generics_of(self.mir_def_id()).region_param(ebr, tcx).def_id; + let span = tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP); RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyParamRegion(span) } }), @@ -912,7 +913,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { }; let tcx = self.infcx.tcx; - let region_parent = tcx.parent(region.def_id); + let region_def = tcx.generics_of(self.mir_def_id()).region_param(region, tcx).def_id; + let region_parent = tcx.parent(region_def); let DefKind::Impl { .. } = tcx.def_kind(region_parent) else { return None; }; @@ -925,7 +927,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { Some(RegionName { name: self.synthesize_region_name(), source: RegionNameSource::AnonRegionFromImplSignature( - tcx.def_span(region.def_id), + tcx.def_span(region_def), // FIXME(compiler-errors): Does this ever actually show up // anywhere other than the self type? I couldn't create an // example of a `'_` in the impl's trait being referenceable. diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index b5c06751405..8f21d826925 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -538,11 +538,9 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe // the cases that were stabilized with the `impl_trait_projection` // feature -- see <https://github.com/rust-lang/rust/pull/115659>. if let DefKind::LifetimeParam = tcx.def_kind(def_id) - && let ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. }) - | ty::ReLateParam(ty::LateParamRegion { - bound_region: ty::BoundRegionKind::BrNamed(def_id, _), - .. - }) = *tcx.map_opaque_lifetime_to_parent_lifetime(def_id.expect_local()) + && let Some(def_id) = tcx + .map_opaque_lifetime_to_parent_lifetime(def_id.expect_local()) + .opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id())) { shadowed_captures.insert(def_id); } @@ -585,12 +583,9 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe // Check if the lifetime param was captured but isn't named in the precise captures list. if variances[param.index as usize] == ty::Invariant { if let DefKind::OpaqueTy = tcx.def_kind(tcx.parent(param.def_id)) - && let ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. }) - | ty::ReLateParam(ty::LateParamRegion { - bound_region: ty::BoundRegionKind::BrNamed(def_id, _), - .. - }) = *tcx + && let Some(def_id) = tcx .map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()) + .opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id())) { tcx.dcx().emit_err(errors::LifetimeNotCaptured { opaque_span, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 44bf8fd2d93..39ced1c803f 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -876,7 +876,8 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> { ty::ReLateParam(_) => {} // Remap early-bound regions as long as they don't come from the `impl` itself, // in which case we don't really need to renumber them. - ty::ReEarlyParam(ebr) if self.tcx.parent(ebr.def_id) != self.impl_def_id => {} + ty::ReEarlyParam(ebr) + if ebr.index >= self.tcx.generics_of(self.impl_def_id).count() as u32 => {} _ => return Ok(region), } @@ -889,12 +890,8 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> { ); } } else { - let guar = match region.kind() { - ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. }) - | ty::ReLateParam(ty::LateParamRegion { - bound_region: ty::BoundRegionKind::BrNamed(def_id, _), - .. - }) => { + let guar = match region.opt_param_def_id(self.tcx, self.tcx.parent(self.def_id)) { + Some(def_id) => { let return_span = if let ty::Alias(ty::Opaque, opaque_ty) = self.ty.kind() { self.tcx.def_span(opaque_ty.def_id) } else { @@ -914,7 +911,7 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> { .with_note(format!("hidden type inferred to be `{}`", self.ty)) .emit() } - _ => { + None => { // This code path is not reached in any tests, but may be // reachable. If this is triggered, it should be converted // to `delayed_bug` and the triggering case turned into a @@ -928,7 +925,6 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> { Ok(ty::Region::new_early_param( self.tcx, ty::EarlyParamRegion { - def_id: e.def_id, name: e.name, index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32, }, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index e8ede804c3f..81e3d8c7ece 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -675,11 +675,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( let region_param = gat_generics.param_at(*region_a_idx, tcx); let region_param = ty::Region::new_early_param( tcx, - ty::EarlyParamRegion { - def_id: region_param.def_id, - index: region_param.index, - name: region_param.name, - }, + ty::EarlyParamRegion { index: region_param.index, name: region_param.name }, ); // The predicate we expect to see. (In our example, // `Self: 'me`.) @@ -708,21 +704,13 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( let region_a_param = gat_generics.param_at(*region_a_idx, tcx); let region_a_param = ty::Region::new_early_param( tcx, - ty::EarlyParamRegion { - def_id: region_a_param.def_id, - index: region_a_param.index, - name: region_a_param.name, - }, + ty::EarlyParamRegion { index: region_a_param.index, name: region_a_param.name }, ); // Same for the region. let region_b_param = gat_generics.param_at(*region_b_idx, tcx); let region_b_param = ty::Region::new_early_param( tcx, - ty::EarlyParamRegion { - def_id: region_b_param.def_id, - index: region_b_param.index, - name: region_b_param.name, - }, + ty::EarlyParamRegion { index: region_b_param.index, name: region_b_param.name }, ); // The predicate we expect to see. bounds.insert( @@ -2101,16 +2089,14 @@ fn lint_redundant_lifetimes<'tcx>( } for &victim in &lifetimes[(idx + 1)..] { - // We should only have late-bound lifetimes of the `BrNamed` variety, - // since we get these signatures straight from `hir_lowering`. And any - // other regions (ReError/ReStatic/etc.) shouldn't matter, since we + // All region parameters should have a `DefId` available as: + // - Late-bound parameters should be of the`BrNamed` variety, + // since we get these signatures straight from `hir_lowering`. + // - Early-bound parameters unconditionally have a `DefId` available. + // + // Any other regions (ReError/ReStatic/etc.) shouldn't matter, since we // can't really suggest to remove them. - let (ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. }) - | ty::ReLateParam(ty::LateParamRegion { - bound_region: ty::BoundRegionKind::BrNamed(def_id, _), - .. - })) = victim.kind() - else { + let Some(def_id) = victim.opt_param_def_id(tcx, owner_id.to_def_id()) else { continue; }; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b760b86a7bf..40cd65b899e 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -453,7 +453,6 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { poly_trait_ref, |_| { ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion { - def_id: item_def_id, index: 0, name: Symbol::intern(<_name), }) diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 606f1653767..072bb727901 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -323,7 +323,7 @@ fn compute_bidirectional_outlives_predicates<'tcx>( if let ty::ReEarlyParam(..) = *orig_lifetime { let dup_lifetime = ty::Region::new_early_param( tcx, - ty::EarlyParamRegion { def_id: param.def_id, index: param.index, name: param.name }, + ty::EarlyParamRegion { index: param.index, name: param.name }, ); let span = tcx.def_span(param.def_id); predicates.push(( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 4b1c0da6ce1..83a23de1654 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -280,7 +280,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local()); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; - ty::Region::new_early_param(tcx, ty::EarlyParamRegion { def_id, index, name }) + ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name }) } Some(rbv::ResolvedArg::Free(scope, id)) => { diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 8bb0dc39143..a801001eaf9 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -5,6 +5,7 @@ use rustc_errors::{ MultiSpan, SubdiagMessageOp, Subdiagnostic, }; use rustc_hir as hir; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::FnRetTy; use rustc_macros::{Diagnostic, Subdiagnostic}; @@ -344,6 +345,7 @@ impl Subdiagnostic for LifetimeMismatchLabels { pub struct AddLifetimeParamsSuggestion<'a> { pub tcx: TyCtxt<'a>, + pub generic_param_scope: LocalDefId, pub sub: Region<'a>, pub ty_sup: &'a hir::Ty<'a>, pub ty_sub: &'a hir::Ty<'a>, @@ -357,7 +359,8 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { _f: &F, ) { let mut mk_suggestion = || { - let Some(anon_reg) = self.tcx.is_suitable_region(self.sub) else { + let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub) + else { return false; }; diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index f0b336ca046..4fbeb0ec102 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -1,6 +1,7 @@ use crate::fluent_generated as fluent; use crate::infer::error_reporting::nice_region_error::find_anon_type; use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, SubdiagMessageOp, Subdiagnostic}; +use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{symbol::kw, Span}; @@ -14,12 +15,15 @@ struct DescriptionCtx<'a> { impl<'a> DescriptionCtx<'a> { fn new<'tcx>( tcx: TyCtxt<'tcx>, + generic_param_scope: LocalDefId, region: ty::Region<'tcx>, alt_span: Option<Span>, ) -> Option<Self> { let (span, kind, arg) = match *region { - ty::ReEarlyParam(ref br) => { - let scope = region.free_region_binding_scope(tcx).expect_local(); + ty::ReEarlyParam(br) => { + let scope = tcx + .parent(tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id) + .expect_local(); let span = if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) { @@ -35,11 +39,12 @@ impl<'a> DescriptionCtx<'a> { } ty::ReLateParam(ref fr) => { if !fr.bound_region.is_named() - && let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region) + && let Some((ty, _)) = + find_anon_type(tcx, generic_param_scope, region, &fr.bound_region) { (Some(ty.span), "defined_here", String::new()) } else { - let scope = region.free_region_binding_scope(tcx).expect_local(); + let scope = fr.scope.expect_local(); match fr.bound_region { ty::BoundRegionKind::BrNamed(_, name) => { let span = if let Some(param) = tcx @@ -143,12 +148,17 @@ pub struct RegionExplanation<'a> { impl RegionExplanation<'_> { pub fn new<'tcx>( tcx: TyCtxt<'tcx>, + generic_param_scope: LocalDefId, region: ty::Region<'tcx>, alt_span: Option<Span>, prefix: PrefixKind, suffix: SuffixKind, ) -> Option<Self> { - Some(Self { desc: DescriptionCtx::new(tcx, region, alt_span)?, prefix, suffix }) + Some(Self { + desc: DescriptionCtx::new(tcx, generic_param_scope, region, alt_span)?, + prefix, + suffix, + }) } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e0894ed31bf..7ab148e70a1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -161,6 +161,7 @@ impl<'tcx> Deref for TypeErrCtxt<'_, 'tcx> { pub(super) fn note_and_explain_region<'tcx>( tcx: TyCtxt<'tcx>, err: &mut Diag<'_>, + generic_param_scope: LocalDefId, prefix: &str, region: ty::Region<'tcx>, suffix: &str, @@ -168,7 +169,7 @@ pub(super) fn note_and_explain_region<'tcx>( ) { let (description, span) = match *region { ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::RePlaceholder(_) | ty::ReStatic => { - msg_span_from_named_region(tcx, region, alt_span) + msg_span_from_named_region(tcx, generic_param_scope, region, alt_span) } ty::ReError(_) => return, @@ -187,23 +188,27 @@ pub(super) fn note_and_explain_region<'tcx>( fn explain_free_region<'tcx>( tcx: TyCtxt<'tcx>, err: &mut Diag<'_>, + generic_param_scope: LocalDefId, prefix: &str, region: ty::Region<'tcx>, suffix: &str, ) { - let (description, span) = msg_span_from_named_region(tcx, region, None); + let (description, span) = msg_span_from_named_region(tcx, generic_param_scope, region, None); label_msg_span(err, prefix, description, span, suffix); } fn msg_span_from_named_region<'tcx>( tcx: TyCtxt<'tcx>, + generic_param_scope: LocalDefId, region: ty::Region<'tcx>, alt_span: Option<Span>, ) -> (String, Option<Span>) { match *region { - ty::ReEarlyParam(ref br) => { - let scope = region.free_region_binding_scope(tcx).expect_local(); + ty::ReEarlyParam(br) => { + let scope = tcx + .parent(tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id) + .expect_local(); let span = if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) { @@ -220,21 +225,21 @@ fn msg_span_from_named_region<'tcx>( } ty::ReLateParam(ref fr) => { if !fr.bound_region.is_named() - && let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region) + && let Some((ty, _)) = + find_anon_type(tcx, generic_param_scope, region, &fr.bound_region) { ("the anonymous lifetime defined here".to_string(), Some(ty.span)) } else { - let scope = region.free_region_binding_scope(tcx).expect_local(); match fr.bound_region { ty::BoundRegionKind::BrNamed(_, name) => { let span = if let Some(param) = tcx .hir() - .get_generics(scope) + .get_generics(generic_param_scope) .and_then(|generics| generics.get_named(name)) { param.span } else { - tcx.def_span(scope) + tcx.def_span(generic_param_scope) }; let text = if name == kw::UnderscoreLifetime { "the anonymous lifetime as defined here".to_string() @@ -245,11 +250,11 @@ fn msg_span_from_named_region<'tcx>( } ty::BrAnon => ( "the anonymous lifetime as defined here".to_string(), - Some(tcx.def_span(scope)), + Some(tcx.def_span(generic_param_scope)), ), _ => ( format!("the lifetime `{region}` as defined here"), - Some(tcx.def_span(scope)), + Some(tcx.def_span(generic_param_scope)), ), } } @@ -302,6 +307,7 @@ fn label_msg_span( #[instrument(level = "trace", skip(tcx))] pub fn unexpected_hidden_region_diagnostic<'tcx>( tcx: TyCtxt<'tcx>, + generic_param_scope: LocalDefId, span: Span, hidden_ty: Ty<'tcx>, hidden_region: ty::Region<'tcx>, @@ -327,11 +333,12 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( explain_free_region( tcx, &mut err, + generic_param_scope, &format!("hidden type `{hidden_ty}` captures "), hidden_region, "", ); - if let Some(reg_info) = tcx.is_suitable_region(hidden_region) { + if let Some(reg_info) = tcx.is_suitable_region(generic_param_scope, hidden_region) { let fn_returns = tcx.return_type_impl_or_dyn_traits(reg_info.def_id); nice_region_error::suggest_new_region_bound( tcx, @@ -349,6 +356,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( explain_free_region( tcx, &mut err, + generic_param_scope, &format!("hidden type `{}` captures ", hidden_ty), hidden_region, "", @@ -376,6 +384,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( note_and_explain_region( tcx, &mut err, + generic_param_scope, &format!("hidden type `{hidden_ty}` captures "), hidden_region, "", @@ -450,7 +459,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { for error in errors { debug!("report_region_errors: error = {:?}", error); - guar = Some(if let Some(guar) = self.try_report_nice_region_error(&error) { + let e = if let Some(guar) = + self.try_report_nice_region_error(generic_param_scope, &error) + { guar } else { match error.clone() { @@ -463,9 +474,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // general bit of code that displays the error information RegionResolutionError::ConcreteFailure(origin, sub, sup) => { if sub.is_placeholder() || sup.is_placeholder() { - self.report_placeholder_failure(origin, sub, sup).emit() + self.report_placeholder_failure(generic_param_scope, origin, sub, sup) + .emit() } else { - self.report_concrete_failure(origin, sub, sup).emit() + self.report_concrete_failure(generic_param_scope, origin, sub, sup) + .emit() } } @@ -488,12 +501,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { _, ) => { if sub_r.is_placeholder() { - self.report_placeholder_failure(sub_origin, sub_r, sup_r).emit() + self.report_placeholder_failure( + generic_param_scope, + sub_origin, + sub_r, + sup_r, + ) + .emit() } else if sup_r.is_placeholder() { - self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit() + self.report_placeholder_failure( + generic_param_scope, + sup_origin, + sub_r, + sup_r, + ) + .emit() } else { self.report_sub_sup_conflict( - var_origin, sub_origin, sub_r, sup_origin, sup_r, + generic_param_scope, + var_origin, + sub_origin, + sub_r, + sup_origin, + sup_r, ) } } @@ -514,7 +544,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // value. let sub_r = self.tcx.lifetimes.re_erased; - self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit() + self.report_placeholder_failure( + generic_param_scope, + sup_origin, + sub_r, + sup_r, + ) + .emit() } RegionResolutionError::CannotNormalize(clause, origin) => { @@ -526,7 +562,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .emit() } } - }) + }; + + guar = Some(e) } guar.unwrap() @@ -2347,7 +2385,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { '_explain: { let (description, span) = match sub.kind() { ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => { - msg_span_from_named_region(self.tcx, sub, Some(span)) + msg_span_from_named_region(self.tcx, generic_param_scope, sub, Some(span)) } _ => (format!("lifetime `{sub}`"), Some(span)), }; @@ -2398,7 +2436,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let suggestion_scope = { let lifetime_scope = match sub.kind() { ty::ReStatic => hir::def_id::CRATE_DEF_ID, - _ => match self.tcx.is_suitable_region(sub) { + _ => match self.tcx.is_suitable_region(generic_param_scope, sub) { Some(info) => info.def_id, None => generic_param_scope, }, @@ -2410,7 +2448,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }; let mut suggs = vec![]; - let lt_name = self.suggest_name_region(sub, &mut suggs); + let lt_name = self.suggest_name_region(generic_param_scope, sub, &mut suggs); if let Some((sp, has_lifetimes, open_paren_sp)) = type_param_sugg_span && suggestion_scope == type_scope @@ -2455,6 +2493,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { pub fn suggest_name_region( &self, + generic_param_scope: LocalDefId, lifetime: Region<'tcx>, add_lt_suggs: &mut Vec<(Span, String)>, ) -> String { @@ -2501,12 +2540,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } - let (lifetime_def_id, lifetime_scope) = match self.tcx.is_suitable_region(lifetime) { - Some(info) if !lifetime.has_name() => { - (info.bound_region.get_id().unwrap().expect_local(), info.def_id) - } - _ => return lifetime.get_name_or_anon().to_string(), - }; + let (lifetime_def_id, lifetime_scope) = + match self.tcx.is_suitable_region(generic_param_scope, lifetime) { + Some(info) if !lifetime.has_name() => { + (info.bound_region.get_id().unwrap().expect_local(), info.def_id) + } + _ => return lifetime.get_name_or_anon().to_string(), + }; let new_lt = { let generics = self.tcx.generics_of(lifetime_scope); @@ -2557,6 +2597,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn report_sub_sup_conflict( &self, + generic_param_scope: LocalDefId, var_origin: RegionVariableOrigin, sub_origin: SubregionOrigin<'tcx>, sub_region: Region<'tcx>, @@ -2568,6 +2609,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain_region( self.tcx, &mut err, + generic_param_scope, "first, the lifetime cannot outlive ", sup_region, "...", @@ -2590,6 +2632,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain_region( self.tcx, &mut err, + generic_param_scope, "...but the lifetime must also be valid for ", sub_region, "...", @@ -2613,6 +2656,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain_region( self.tcx, &mut err, + generic_param_scope, "but, the lifetime must be valid for ", sub_region, "...", diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs index 84bfa5b5af7..cbeec591960 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -13,6 +13,7 @@ use crate::infer::TyCtxt; use rustc_errors::Subdiagnostic; use rustc_errors::{Diag, ErrorGuaranteed}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::Ty; use rustc_middle::ty::Region; @@ -66,17 +67,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } // Determine whether the sub and sup consist of both anonymous (elided) regions. - let anon_reg_sup = self.tcx().is_suitable_region(sup)?; + let anon_reg_sup = self.tcx().is_suitable_region(self.generic_param_scope, sup)?; - let anon_reg_sub = self.tcx().is_suitable_region(sub)?; + let anon_reg_sub = self.tcx().is_suitable_region(self.generic_param_scope, sub)?; let scope_def_id_sup = anon_reg_sup.def_id; let bregion_sup = anon_reg_sup.bound_region; let scope_def_id_sub = anon_reg_sub.def_id; let bregion_sub = anon_reg_sub.bound_region; - let ty_sup = find_anon_type(self.tcx(), sup, &bregion_sup)?; + let ty_sup = find_anon_type(self.tcx(), self.generic_param_scope, sup, &bregion_sup)?; - let ty_sub = find_anon_type(self.tcx(), sub, &bregion_sub)?; + let ty_sub = find_anon_type(self.tcx(), self.generic_param_scope, sub, &bregion_sub)?; debug!( "try_report_anon_anon_conflict: found_param1={:?} sup={:?} br1={:?}", @@ -127,8 +128,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }, }; - let suggestion = - AddLifetimeParamsSuggestion { tcx: self.tcx(), sub, ty_sup, ty_sub, add_note: true }; + let suggestion = AddLifetimeParamsSuggestion { + tcx: self.tcx(), + sub, + ty_sup, + ty_sub, + add_note: true, + generic_param_scope: self.generic_param_scope, + }; let err = LifetimeMismatch { span, labels, suggestion }; let reported = self.tcx().dcx().emit_err(err); Some(reported) @@ -139,11 +146,19 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// removed in favour of public_errors::AddLifetimeParamsSuggestion pub fn suggest_adding_lifetime_params<'tcx>( tcx: TyCtxt<'tcx>, + err: &mut Diag<'_>, + generic_param_scope: LocalDefId, sub: Region<'tcx>, ty_sup: &'tcx Ty<'_>, ty_sub: &'tcx Ty<'_>, - err: &mut Diag<'_>, ) { - let suggestion = AddLifetimeParamsSuggestion { tcx, sub, ty_sup, ty_sub, add_note: false }; + let suggestion = AddLifetimeParamsSuggestion { + tcx, + sub, + ty_sup, + ty_sub, + add_note: false, + generic_param_scope, + }; suggestion.add_to_diag(err); } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index 265a315a559..b91b755d683 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -1,5 +1,6 @@ use core::ops::ControlFlow; use rustc_hir as hir; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; @@ -23,10 +24,11 @@ use rustc_middle::ty::{self, Region, TyCtxt}; /// for e.g., `&u8` and `Vec<&u8>`. pub fn find_anon_type<'tcx>( tcx: TyCtxt<'tcx>, + generic_param_scope: LocalDefId, region: Region<'tcx>, br: &ty::BoundRegionKind, ) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnSig<'tcx>)> { - let anon_reg = tcx.is_suitable_region(region)?; + let anon_reg = tcx.is_suitable_region(generic_param_scope, region)?; let fn_sig = tcx.hir_node_by_def_id(anon_reg.def_id).fn_sig()?; fn_sig diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index 45dce0a0e33..7996b4bf65b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -57,6 +57,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let expl = note_and_explain::RegionExplanation::new( self.tcx(), + self.generic_param_scope, sup, Some(binding_span), note_and_explain::PrefixKind::Empty, diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs index 62c163f0b7f..cffdfa88752 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs @@ -2,6 +2,7 @@ use crate::infer::error_reporting::TypeErrCtxt; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::lexical_region_resolve::RegionResolutionError::*; use rustc_errors::{Diag, ErrorGuaranteed}; +use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; @@ -23,30 +24,39 @@ pub use util::find_param_with_region; impl<'cx, 'tcx> TypeErrCtxt<'cx, 'tcx> { pub fn try_report_nice_region_error( &'cx self, + generic_param_scope: LocalDefId, error: &RegionResolutionError<'tcx>, ) -> Option<ErrorGuaranteed> { - NiceRegionError::new(self, error.clone()).try_report() + NiceRegionError::new(self, generic_param_scope, error.clone()).try_report() } } pub struct NiceRegionError<'cx, 'tcx> { cx: &'cx TypeErrCtxt<'cx, 'tcx>, + /// The innermost definition that introduces generic parameters that may be involved in + /// the region errors we are dealing with. + generic_param_scope: LocalDefId, error: Option<RegionResolutionError<'tcx>>, regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>, } impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { - pub fn new(cx: &'cx TypeErrCtxt<'cx, 'tcx>, error: RegionResolutionError<'tcx>) -> Self { - Self { cx, error: Some(error), regions: None } + pub fn new( + cx: &'cx TypeErrCtxt<'cx, 'tcx>, + generic_param_scope: LocalDefId, + error: RegionResolutionError<'tcx>, + ) -> Self { + Self { cx, error: Some(error), regions: None, generic_param_scope } } pub fn new_from_span( cx: &'cx TypeErrCtxt<'cx, 'tcx>, + generic_param_scope: LocalDefId, span: Span, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>, ) -> Self { - Self { cx, error: None, regions: Some((span, sub, sup)) } + Self { cx, error: None, regions: Some((span, sub, sup)), generic_param_scope } } fn tcx(&self) -> TyCtxt<'tcx> { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 239c2db30e2..29da12e7d15 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -27,12 +27,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // version new_ty of its type where the anonymous region is replaced // with the named one. let (named, anon, anon_param_info, region_info) = if sub.has_name() - && let Some(region_info) = self.tcx().is_suitable_region(sup) + && let Some(region_info) = self.tcx().is_suitable_region(self.generic_param_scope, sup) && let Some(anon_param_info) = self.find_param_with_region(sup, sub) { (sub, sup, anon_param_info, region_info) } else if sup.has_name() - && let Some(region_info) = self.tcx().is_suitable_region(sub) + && let Some(region_info) = self.tcx().is_suitable_region(self.generic_param_scope, sub) && let Some(anon_param_info) = self.find_param_with_region(sub, sup) { (sup, sub, anon_param_info, region_info) @@ -72,7 +72,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { return None; } - if find_anon_type(self.tcx(), anon, &br).is_some() + if find_anon_type(self.tcx(), self.generic_param_scope, anon, &br).is_some() && self.is_self_anon(is_first, scope_def_id) { return None; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 8a1e3a7ac71..71a86683c21 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -49,7 +49,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { if let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() { // This may have a closure and it would cause ICE // through `find_param_with_region` (#78262). - let anon_reg_sup = tcx.is_suitable_region(*sup_r)?; + let anon_reg_sup = tcx.is_suitable_region(self.generic_param_scope, *sup_r)?; let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); if fn_returns.is_empty() { return None; @@ -92,7 +92,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})", var_origin, sub_origin, sub_r, sup_origin, sup_r ); - let anon_reg_sup = tcx.is_suitable_region(*sup_r)?; + let anon_reg_sup = tcx.is_suitable_region(self.generic_param_scope, *sup_r)?; debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup); let sp = var_origin.span(); let return_sp = sub_origin.span(); diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index f1f8314661f..5f3f1081ca8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -37,13 +37,15 @@ pub struct AnonymousParamInfo<'tcx> { #[instrument(skip(tcx), level = "debug")] pub fn find_param_with_region<'tcx>( tcx: TyCtxt<'tcx>, + generic_param_scope: LocalDefId, anon_region: Region<'tcx>, replace_region: Region<'tcx>, ) -> Option<AnonymousParamInfo<'tcx>> { let (id, bound_region) = match *anon_region { ty::ReLateParam(late_param) => (late_param.scope, late_param.bound_region), ty::ReEarlyParam(ebr) => { - (tcx.parent(ebr.def_id), ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name)) + let region_def = tcx.generics_of(generic_param_scope).region_param(ebr, tcx).def_id; + (tcx.parent(region_def), ty::BoundRegionKind::BrNamed(region_def, ebr.name)) } _ => return None, // not a free region }; @@ -53,7 +55,7 @@ pub fn find_param_with_region<'tcx>( // FIXME: use def_kind // Don't perform this on closures - match tcx.hir_node_by_def_id(def_id) { + match tcx.hir_node_by_def_id(generic_param_scope) { hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => { return None; } @@ -110,7 +112,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { anon_region: Region<'tcx>, replace_region: Region<'tcx>, ) -> Option<AnonymousParamInfo<'tcx>> { - find_param_with_region(self.tcx(), anon_region, replace_region) + find_param_with_region(self.tcx(), self.generic_param_scope, anon_region, replace_region) } // Here, we check for the case where the anonymous region diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 00dd20a2cc2..acb74f8a82c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -75,6 +75,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { pub(super) fn report_concrete_failure( &self, + generic_param_scope: LocalDefId, origin: SubregionOrigin<'tcx>, sub: Region<'tcx>, sup: Region<'tcx>, @@ -89,6 +90,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain_region( self.tcx, &mut err, + generic_param_scope, "", sup, " doesn't meet the lifetime requirements", @@ -99,6 +101,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain_region( self.tcx, &mut err, + generic_param_scope, "the required lifetime does not necessarily outlive ", sub, "", @@ -106,10 +109,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); } _ => { - note_and_explain_region(self.tcx, &mut err, "", sup, "...", None); note_and_explain_region( self.tcx, &mut err, + generic_param_scope, + "", + sup, + "...", + None, + ); + note_and_explain_region( + self.tcx, + &mut err, + generic_param_scope, "...does not necessarily outlive ", sub, "", @@ -122,6 +134,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer::Reborrow(span) => { let reference_valid = note_and_explain::RegionExplanation::new( self.tcx, + generic_param_scope, sub, None, note_and_explain::PrefixKind::RefValidFor, @@ -129,6 +142,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); let content_valid = note_and_explain::RegionExplanation::new( self.tcx, + generic_param_scope, sup, None, note_and_explain::PrefixKind::ContentValidFor, @@ -142,6 +156,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer::RelateObjectBound(span) => { let object_valid = note_and_explain::RegionExplanation::new( self.tcx, + generic_param_scope, sub, None, note_and_explain::PrefixKind::TypeObjValidFor, @@ -149,6 +164,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); let pointer_valid = note_and_explain::RegionExplanation::new( self.tcx, + generic_param_scope, sup, None, note_and_explain::PrefixKind::SourcePointerValidFor, @@ -170,7 +186,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::SuffixKind::Empty }; let note = note_and_explain::RegionExplanation::new( - self.tcx, sub, opt_span, prefix, suffix, + self.tcx, + generic_param_scope, + sub, + opt_span, + prefix, + suffix, ); self.dcx().create_err(FulfillReqLifetime { span, @@ -181,6 +202,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer::RelateRegionParamBound(span) => { let param_instantiated = note_and_explain::RegionExplanation::new( self.tcx, + generic_param_scope, sup, None, note_and_explain::PrefixKind::LfParamInstantiatedWith, @@ -188,6 +210,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); let param_must_outlive = note_and_explain::RegionExplanation::new( self.tcx, + generic_param_scope, sub, None, note_and_explain::PrefixKind::LfParamMustOutlive, @@ -201,6 +224,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer::ReferenceOutlivesReferent(ty, span) => { let pointer_valid = note_and_explain::RegionExplanation::new( self.tcx, + generic_param_scope, sub, None, note_and_explain::PrefixKind::PointerValidFor, @@ -208,6 +232,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); let data_valid = note_and_explain::RegionExplanation::new( self.tcx, + generic_param_scope, sup, None, note_and_explain::PrefixKind::DataValidFor, @@ -239,7 +264,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { err } infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => { - let mut err = self.report_concrete_failure(*parent, sub, sup); + let mut err = self.report_concrete_failure(generic_param_scope, *parent, sub, sup); // Don't mention the item name if it's an RPITIT, since that'll just confuse // folks. @@ -262,6 +287,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer::AscribeUserTypeProvePredicate(span) => { let instantiated = note_and_explain::RegionExplanation::new( self.tcx, + generic_param_scope, sup, None, note_and_explain::PrefixKind::LfInstantiatedWith, @@ -269,6 +295,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); let must_outlive = note_and_explain::RegionExplanation::new( self.tcx, + generic_param_scope, sub, None, note_and_explain::PrefixKind::LfMustOutlive, @@ -347,6 +374,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { pub(super) fn report_placeholder_failure( &self, + generic_param_scope: LocalDefId, placeholder_origin: SubregionOrigin<'tcx>, sub: Region<'tcx>, sup: Region<'tcx>, @@ -368,7 +396,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { && !span.is_dummy() { let span = *span; - self.report_concrete_failure(placeholder_origin, sub, sup) + self.report_concrete_failure(generic_param_scope, placeholder_origin, sub, sup) .with_span_note(span, "the lifetime requirement is introduced here") } else { unreachable!( @@ -380,7 +408,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let terr = TypeError::RegionsPlaceholderMismatch; return self.report_and_explain_type_error(trace, terr); } - _ => return self.report_concrete_failure(placeholder_origin, sub, sup), + _ => { + return self.report_concrete_failure( + generic_param_scope, + placeholder_origin, + sub, + sup, + ); + } } } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 85d54ce563d..ba42eae3441 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1950,14 +1950,22 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN impl ExplicitOutlivesRequirements { fn lifetimes_outliving_lifetime<'tcx>( + tcx: TyCtxt<'tcx>, inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)], - def_id: DefId, + item: DefId, + lifetime: DefId, ) -> Vec<ty::Region<'tcx>> { + let item_generics = tcx.generics_of(item); + inferred_outlives .iter() .filter_map(|(clause, _)| match clause.kind().skip_binder() { ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a { - ty::ReEarlyParam(ebr) if ebr.def_id == def_id => Some(b), + ty::ReEarlyParam(ebr) + if item_generics.region_param(ebr, tcx).def_id == lifetime => + { + Some(b) + } _ => None, }, _ => None, @@ -1986,9 +1994,12 @@ impl ExplicitOutlivesRequirements { bounds: &hir::GenericBounds<'_>, inferred_outlives: &[ty::Region<'tcx>], predicate_span: Span, + item: DefId, ) -> Vec<(usize, Span)> { use rustc_middle::middle::resolve_bound_vars::ResolvedArg; + let item_generics = tcx.generics_of(item); + bounds .iter() .enumerate() @@ -2000,7 +2011,7 @@ impl ExplicitOutlivesRequirements { let is_inferred = match tcx.named_bound_var(lifetime.hir_id) { Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives .iter() - .any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { ebr.def_id == def_id })), + .any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { item_generics.region_param(ebr, tcx).def_id == def_id })), _ => false, }; @@ -2109,7 +2120,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { { ( Self::lifetimes_outliving_lifetime( + cx.tcx, inferred_outlives, + item.owner_id.to_def_id(), region_def_id, ), &predicate.bounds, @@ -2152,6 +2165,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { bounds, &relevant_lifetimes, predicate_span, + item.owner_id.to_def_id(), ); bound_count += bound_spans.len(); diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 30bf80b915b..c473b74b410 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -5,11 +5,11 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::LintDiagnostic; +use rustc_middle::bug; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use rustc_middle::{bug, span_bug}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{sym, BytePos, Span}; @@ -303,20 +303,12 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> { ResolvedArg::EarlyBound(def_id) | ResolvedArg::LateBound(_, _, def_id), ) => { if self.tcx.def_kind(self.tcx.parent(def_id)) == DefKind::OpaqueTy { - let (ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. }) - | ty::ReLateParam(ty::LateParamRegion { - bound_region: ty::BoundRegionKind::BrNamed(def_id, _), - .. - })) = self + let def_id = self .tcx .map_opaque_lifetime_to_parent_lifetime(def_id.expect_local()) - .kind() - else { - span_bug!( - self.tcx.def_span(def_id), - "variable should have been duplicated from a parent" - ); - }; + .opt_param_def_id(self.tcx, self.parent_def_id.to_def_id()) + .expect("variable should have been duplicated from parent"); + explicitly_captured.insert(def_id); } else { explicitly_captured.insert(def_id); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index d138cd9ceb9..33ce08991bb 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1489,13 +1489,14 @@ impl<'tcx> TyCtxt<'tcx> { } /// Returns the `DefId` and the `BoundRegionKind` corresponding to the given region. - pub fn is_suitable_region(self, mut region: Region<'tcx>) -> Option<FreeRegionInfo> { + pub fn is_suitable_region( + self, + generic_param_scope: LocalDefId, + mut region: Region<'tcx>, + ) -> Option<FreeRegionInfo> { let (suitable_region_binding_scope, bound_region) = loop { - let def_id = match region.kind() { - ty::ReLateParam(fr) => fr.bound_region.get_id()?.as_local()?, - ty::ReEarlyParam(ebr) => ebr.def_id.as_local()?, - _ => return None, // not a free region - }; + let def_id = + region.opt_param_def_id(self, generic_param_scope.to_def_id())?.as_local()?; let scope = self.local_parent(def_id); if self.def_kind(scope) == DefKind::OpaqueTy { // Lifetime params of opaque types are synthetic and thus irrelevant to @@ -2634,7 +2635,6 @@ impl<'tcx> TyCtxt<'tcx> { return ty::Region::new_early_param( self, ty::EarlyParamRegion { - def_id: ebv, index: generics .param_def_id_to_index(self, ebv) .expect("early-bound var should be present in fn generics"), diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 1c4462fc1dc..69a86bda43b 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -66,7 +66,7 @@ pub struct GenericParamDef { impl GenericParamDef { pub fn to_early_bound_region_data(&self) -> ty::EarlyParamRegion { if let GenericParamDefKind::Lifetime = self.kind { - ty::EarlyParamRegion { def_id: self.def_id, index: self.index, name: self.name } + ty::EarlyParamRegion { index: self.index, name: self.name } } else { bug!("cannot convert a non-lifetime parameter def to an early bound region") } diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 958e7e40168..0807cbf91d1 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -265,33 +265,6 @@ impl<'tcx> Region<'tcx> { flags } - /// Given an early-bound or free region, returns the `DefId` where it was bound. - /// For example, consider the regions in this snippet of code: - /// - /// ```ignore (illustrative) - /// impl<'a> Foo { - /// // ^^ -- early bound, declared on an impl - /// - /// fn bar<'b, 'c>(x: &self, y: &'b u32, z: &'c u64) where 'static: 'c - /// // ^^ ^^ ^ anonymous, late-bound - /// // | early-bound, appears in where-clauses - /// // late-bound, appears only in fn args - /// {..} - /// } - /// ``` - /// - /// Here, `free_region_binding_scope('a)` would return the `DefId` - /// of the impl, and for all the other highlighted regions, it - /// would return the `DefId` of the function. In other cases (not shown), this - /// function might return the `DefId` of a closure. - pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId { - match *self { - ty::ReEarlyParam(br) => tcx.parent(br.def_id), - ty::ReLateParam(fr) => fr.scope, - _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), - } - } - /// True for free regions other than `'static`. pub fn is_param(self) -> bool { matches!(*self, ty::ReEarlyParam(_) | ty::ReLateParam(_)) @@ -321,6 +294,21 @@ impl<'tcx> Region<'tcx> { _ => bug!("expected region {:?} to be of kind ReVar", self), } } + + /// Given some item `binding_item`, check if this region is a generic parameter introduced by it + /// or one of the parent generics. Returns the `DefId` of the parameter definition if so. + pub fn opt_param_def_id(self, tcx: TyCtxt<'tcx>, binding_item: DefId) -> Option<DefId> { + match self.kind() { + ty::ReEarlyParam(ebr) => { + Some(tcx.generics_of(binding_item).region_param(ebr, tcx).def_id) + } + ty::ReLateParam(ty::LateParamRegion { + bound_region: ty::BoundRegionKind::BrNamed(def_id, _), + .. + }) => Some(def_id), + _ => None, + } + } } impl<'tcx> Deref for Region<'tcx> { @@ -335,16 +323,13 @@ impl<'tcx> Deref for Region<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable)] pub struct EarlyParamRegion { - pub def_id: DefId, pub index: u32, pub name: Symbol, } impl std::fmt::Debug for EarlyParamRegion { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - // FIXME(BoxyUwU): self.def_id goes first because of `erased-regions-in-hidden-ty.rs` being impossible to write - // error annotations for otherwise. :). Ideally this would be `self.name, self.index, self.def_id`. - write!(f, "{:?}_{}/#{}", self.def_id, self.name, self.index) + write!(f, "{}/#{}", self.name, self.index) } } @@ -352,6 +337,12 @@ impl std::fmt::Debug for EarlyParamRegion { #[derive(HashStable)] /// The parameter representation of late-bound function parameters, "some region /// at least as big as the scope `fr.scope`". +/// +/// Similar to a placeholder region as we create `LateParam` regions when entering a binder +/// except they are always in the root universe and instead of using a boundvar to distinguish +/// between others we use the `DefId` of the parameter. For this reason the `bound_region` field +/// should basically always be `BoundRegionKind::BrNamed` as otherwise there is no way of telling +/// different parameters apart. pub struct LateParamRegion { pub scope: DefId, pub bound_region: BoundRegionKind, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index be20924670c..a511989d972 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -771,7 +771,6 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> { use stable_mir::ty::{BoundRegion, EarlyParamRegion, RegionKind}; match self { ty::ReEarlyParam(early_reg) => RegionKind::ReEarlyParam(EarlyParamRegion { - def_id: tables.region_def(early_reg.def_id), index: early_reg.index, name: early_reg.name.to_string(), }), diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index f6003a25028..ab4d06f2660 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -185,6 +185,7 @@ fn do_normalize_predicates<'tcx>( predicates: Vec<ty::Clause<'tcx>>, ) -> Result<Vec<ty::Clause<'tcx>>, ErrorGuaranteed> { let span = cause.span; + // FIXME. We should really... do something with these region // obligations. But this call just continues the older // behavior (i.e., doesn't cause any new bugs), and it would diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index e87058f9ba4..6f71951b516 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -79,11 +79,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' orig_lt, ty::Region::new_early_param( tcx, - ty::EarlyParamRegion { - def_id: param.def_id, - index: param.index, - name: param.name, - }, + ty::EarlyParamRegion { index: param.index, name: param.name }, ), ); } diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index f3ac2bfcdb0..d62054eff60 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -190,7 +190,6 @@ pub(crate) type DebruijnIndex = u32; #[derive(Clone, Debug, Eq, PartialEq)] pub struct EarlyParamRegion { - pub def_id: RegionDef, pub index: u32, pub name: Symbol, } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 65929cd5fea..38580dc5822 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -460,13 +460,19 @@ fn check_fn_args<'cx, 'tcx: 'cx>( } None }) { - if !lifetime.is_anonymous() + if let LifetimeName::Param(param_def_id) = lifetime.res + && !lifetime.is_anonymous() && fn_sig .output() .walk() .filter_map(|arg| { arg.as_region().and_then(|lifetime| match lifetime.kind() { - ty::ReEarlyParam(r) => Some(r.def_id), + ty::ReEarlyParam(r) => Some( + cx.tcx + .generics_of(cx.tcx.parent(param_def_id.to_def_id())) + .region_param(r, cx.tcx) + .def_id, + ), ty::ReBound(_, r) => r.kind.get_id(), ty::ReLateParam(r) => r.bound_region.get_id(), ty::ReStatic @@ -476,14 +482,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( | ty::ReError(_) => None, }) }) - .any(|def_id| { - matches!( - lifetime.res, - LifetimeName::Param(param_def_id) if def_id - .as_local() - .is_some_and(|def_id| def_id == param_def_id), - ) - }) + .any(|def_id| def_id.as_local().is_some_and(|def_id| def_id == param_def_id)) { // `&Cow<'a, T>` when the return type uses 'a is okay return None; diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr index 3893cdf482e..48569d1446d 100644 --- a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -1,4 +1,4 @@ -error[E0700]: hidden type for `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])` captures lifetime that does not appear in bounds +error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), ['a/#0, T, 'a/#0])` captures lifetime that does not appear in bounds --> $DIR/impl-trait-captures.rs:11:5 | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { @@ -8,7 +8,7 @@ LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { LL | x | ^ | -help: to declare that `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:14 ~ impl_trait_captures[aeb9]::foo::{opaque#0}::'a)_'a/#2])` captures `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound +help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), ['a/#0, T, 'a/#2])` captures `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) { | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
