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)
This commit is contained in:
commit
fec98b3bbc
31 changed files with 320 additions and 212 deletions
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
"...",
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue