mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 17:03:35 +00:00
Add an optional Span to BrAnon and use it to print better error for HRTB error from generator interior
This commit is contained in:
parent
1e1e5b8d98
commit
00e314d5ed
@ -158,6 +158,7 @@ trait TypeOpInfo<'tcx> {
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
|
||||
|
||||
#[instrument(level = "debug", skip(self, mbcx))]
|
||||
fn report_error(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
@ -167,6 +168,7 @@ trait TypeOpInfo<'tcx> {
|
||||
) {
|
||||
let tcx = mbcx.infcx.tcx;
|
||||
let base_universe = self.base_universe();
|
||||
debug!(?base_universe);
|
||||
|
||||
let Some(adjusted_universe) =
|
||||
placeholder.universe.as_u32().checked_sub(base_universe.as_u32())
|
||||
@ -389,6 +391,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>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
|
@ -355,7 +355,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
ty::BoundRegionKind::BrAnon(_) => None,
|
||||
ty::BoundRegionKind::BrAnon(..) => None,
|
||||
},
|
||||
|
||||
ty::ReLateBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => None,
|
||||
|
@ -2976,7 +2976,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
) {
|
||||
for br in referenced_regions.difference(&constrained_regions) {
|
||||
let br_name = match *br {
|
||||
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) | ty::BrEnv => {
|
||||
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) | ty::BrEnv => {
|
||||
"an anonymous lifetime".to_string()
|
||||
}
|
||||
ty::BrNamed(_, name) => format!("lifetime `{}`", name),
|
||||
@ -2984,7 +2984,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
|
||||
let mut err = generate_err(&br_name);
|
||||
|
||||
if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) = *br {
|
||||
if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) = *br {
|
||||
// The only way for an anonymous lifetime to wind up
|
||||
// in the return type but **also** be unconstrained is
|
||||
// if it only appears in "associated types" in the
|
||||
|
@ -134,15 +134,18 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||
let name_str = intrinsic_name.as_str();
|
||||
|
||||
let bound_vars = tcx.mk_bound_variable_kinds(
|
||||
[ty::BoundVariableKind::Region(ty::BrAnon(0)), ty::BoundVariableKind::Region(ty::BrEnv)]
|
||||
.iter()
|
||||
.copied(),
|
||||
[
|
||||
ty::BoundVariableKind::Region(ty::BrAnon(0, None)),
|
||||
ty::BoundVariableKind::Region(ty::BrEnv),
|
||||
]
|
||||
.iter()
|
||||
.copied(),
|
||||
);
|
||||
let mk_va_list_ty = |mutbl| {
|
||||
tcx.lang_items().va_list().map(|did| {
|
||||
let region = tcx.mk_region(ty::ReLateBound(
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) },
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) },
|
||||
));
|
||||
let env_region = tcx.mk_region(ty::ReLateBound(
|
||||
ty::INNERMOST,
|
||||
@ -364,7 +367,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||
);
|
||||
let discriminant_def_id = assoc_items[0];
|
||||
|
||||
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) };
|
||||
let br =
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
|
||||
(
|
||||
1,
|
||||
vec![
|
||||
@ -418,7 +422,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||
sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
|
||||
|
||||
sym::raw_eq => {
|
||||
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) };
|
||||
let br =
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
|
||||
let param_ty =
|
||||
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0));
|
||||
(1, vec![param_ty; 2], tcx.types.bool)
|
||||
|
@ -13,8 +13,9 @@ use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::hir_id::HirIdSet;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind};
|
||||
use rustc_infer::infer::RegionVariableOrigin;
|
||||
use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData};
|
||||
use rustc_middle::ty::{self, RvalueScopes, Ty, TyCtxt, TypeVisitable};
|
||||
use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitable};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
|
||||
@ -211,31 +212,52 @@ pub fn resolve_interior<'a, 'tcx>(
|
||||
|
||||
debug!("types in generator {:?}, span = {:?}", types, body.value.span);
|
||||
|
||||
let mut counter = 0;
|
||||
// We want to deduplicate if the lifetimes are the same modulo some non-informative counter.
|
||||
// So, we need to actually do two passes: first by type to anonymize (preserving information
|
||||
// required for diagnostics), then a second pass over all captured types to reassign disjoint
|
||||
// region indices.
|
||||
let mut captured_tys = FxHashSet::default();
|
||||
let type_causes: Vec<_> = types
|
||||
.into_iter()
|
||||
.filter_map(|mut cause| {
|
||||
// Erase regions and canonicalize late-bound regions to deduplicate as many types as we
|
||||
// can.
|
||||
let ty = fcx.normalize_associated_types_in(cause.span, cause.ty);
|
||||
let erased = fcx.tcx.erase_regions(ty);
|
||||
if captured_tys.insert(erased) {
|
||||
// Replace all regions inside the generator interior with late bound regions.
|
||||
// Note that each region slot in the types gets a new fresh late bound region,
|
||||
// which means that none of the regions inside relate to any other, even if
|
||||
// typeck had previously found constraints that would cause them to be related.
|
||||
let folded = fcx.tcx.fold_regions(erased, |_, current_depth| {
|
||||
let br = ty::BoundRegion {
|
||||
var: ty::BoundVar::from_u32(counter),
|
||||
kind: ty::BrAnon(counter),
|
||||
};
|
||||
let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
|
||||
counter += 1;
|
||||
r
|
||||
});
|
||||
// Replace all regions inside the generator interior with late bound regions.
|
||||
// Note that each region slot in the types gets a new fresh late bound region,
|
||||
// which means that none of the regions inside relate to any other, even if
|
||||
// typeck had previously found constraints that would cause them to be related.
|
||||
|
||||
cause.ty = folded;
|
||||
let mut counter = 0;
|
||||
let ty = fcx.normalize_associated_types_in(cause.span, cause.ty);
|
||||
let ty = fcx.tcx.fold_regions(ty, |region, current_depth| {
|
||||
let br = match region.kind() {
|
||||
ty::ReVar(vid) => {
|
||||
let origin = fcx.region_var_origin(vid);
|
||||
match origin {
|
||||
RegionVariableOrigin::EarlyBoundRegion(span, _) => {
|
||||
let kind = ty::BrAnon(counter, Some(span));
|
||||
let var = ty::BoundVar::from_u32(counter);
|
||||
counter += 1;
|
||||
ty::BoundRegion { var, kind }
|
||||
}
|
||||
_ => {
|
||||
let kind = ty::BrAnon(counter, None);
|
||||
let var = ty::BoundVar::from_u32(counter);
|
||||
counter += 1;
|
||||
ty::BoundRegion { var, kind }
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let kind = ty::BrAnon(counter, None);
|
||||
let var = ty::BoundVar::from_u32(counter);
|
||||
counter += 1;
|
||||
ty::BoundRegion { var, kind }
|
||||
}
|
||||
};
|
||||
let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
|
||||
r
|
||||
});
|
||||
if captured_tys.insert(ty) {
|
||||
cause.ty = ty;
|
||||
Some(cause)
|
||||
} else {
|
||||
None
|
||||
@ -243,11 +265,29 @@ pub fn resolve_interior<'a, 'tcx>(
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut bound_vars: Vec<BoundVariableKind> = vec![];
|
||||
let mut counter = 0;
|
||||
let type_causes = fcx.tcx.fold_regions(type_causes, |region, current_depth| {
|
||||
let br = match region.kind() {
|
||||
ty::ReLateBound(_, br) => {
|
||||
let kind = match br.kind {
|
||||
ty::BrAnon(_, span) => ty::BrAnon(counter, span),
|
||||
_ => br.kind,
|
||||
};
|
||||
let var = ty::BoundVar::from_usize(bound_vars.len());
|
||||
bound_vars.push(ty::BoundVariableKind::Region(kind));
|
||||
counter += 1;
|
||||
ty::BoundRegion { var, kind }
|
||||
}
|
||||
_ => bug!("All regions should have been replaced by ReLateBound"),
|
||||
};
|
||||
let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
|
||||
r
|
||||
});
|
||||
|
||||
// Extract type components to build the witness type.
|
||||
let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));
|
||||
let bound_vars = fcx.tcx.mk_bound_variable_kinds(
|
||||
(0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))),
|
||||
);
|
||||
let bound_vars = fcx.tcx.mk_bound_variable_kinds(bound_vars.iter());
|
||||
let witness =
|
||||
fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone()));
|
||||
|
||||
|
@ -209,6 +209,7 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T
|
||||
typeck_with_fallback(tcx, def_id, fallback)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(tcx, fallback), ret)]
|
||||
fn typeck_with_fallback<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
|
@ -89,10 +89,13 @@ impl<'a> DescriptionCtx<'a> {
|
||||
};
|
||||
me.span = Some(sp);
|
||||
}
|
||||
ty::BrAnon(idx) => {
|
||||
ty::BrAnon(idx, span) => {
|
||||
me.kind = "anon_num_here";
|
||||
me.num_arg = idx+1;
|
||||
me.span = Some(tcx.def_span(scope));
|
||||
me.span = match span {
|
||||
Some(_) => span,
|
||||
None => Some(tcx.def_span(scope)),
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
me.kind = "defined_here_reg";
|
||||
|
@ -738,7 +738,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
|
||||
r: ty::Region<'tcx>,
|
||||
) -> ty::Region<'tcx> {
|
||||
let var = self.canonical_var(info, r.into());
|
||||
let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32()) };
|
||||
let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32(), None) };
|
||||
let region = ty::ReLateBound(self.binder_index, br);
|
||||
self.tcx().mk_region(region)
|
||||
}
|
||||
|
@ -206,9 +206,12 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>(
|
||||
};
|
||||
(text, sp)
|
||||
}
|
||||
ty::BrAnon(idx) => (
|
||||
ty::BrAnon(idx, span) => (
|
||||
format!("the anonymous lifetime #{} defined here", idx + 1),
|
||||
tcx.def_span(scope)
|
||||
match span {
|
||||
Some(span) => span,
|
||||
None => tcx.def_span(scope)
|
||||
}
|
||||
),
|
||||
_ => (
|
||||
format!("the lifetime `{}` as defined here", region),
|
||||
|
@ -10,6 +10,7 @@ pub mod find_anon_type;
|
||||
mod mismatched_static_lifetime;
|
||||
mod named_anon_conflict;
|
||||
mod placeholder_error;
|
||||
mod placeholder_relation;
|
||||
mod static_impl_trait;
|
||||
mod trait_impl_difference;
|
||||
mod util;
|
||||
@ -52,7 +53,9 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
|
||||
pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
// Due to the improved diagnostics returned by the MIR borrow checker, only a subset of
|
||||
// the nice region errors are required when running under the MIR borrow checker.
|
||||
self.try_report_named_anon_conflict().or_else(|| self.try_report_placeholder_conflict())
|
||||
self.try_report_named_anon_conflict()
|
||||
.or_else(|| self.try_report_placeholder_conflict())
|
||||
.or_else(|| self.try_report_placeholder_relation())
|
||||
}
|
||||
|
||||
pub fn try_report(&self) -> Option<ErrorGuaranteed> {
|
||||
|
@ -68,7 +68,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||
let is_impl_item = region_info.is_impl_item;
|
||||
|
||||
match br {
|
||||
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) => {}
|
||||
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) => {}
|
||||
_ => {
|
||||
/* not an anonymous region */
|
||||
debug!("try_report_named_anon_conflict: not an anonymous region");
|
||||
|
@ -0,0 +1,78 @@
|
||||
use crate::infer::{
|
||||
error_reporting::nice_region_error::NiceRegionError, RegionResolutionError, SubregionOrigin,
|
||||
};
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_middle::ty::{self, RePlaceholder, Region};
|
||||
|
||||
impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||
/// Emitted wwhen given a `ConcreteFailure` when relating two placeholders.
|
||||
pub(super) fn try_report_placeholder_relation(
|
||||
&self,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
match &self.error {
|
||||
Some(RegionResolutionError::ConcreteFailure(
|
||||
SubregionOrigin::RelateRegionParamBound(span),
|
||||
Region(Interned(RePlaceholder(ty::Placeholder { name: sub_name, .. }), _)),
|
||||
Region(Interned(RePlaceholder(ty::Placeholder { name: sup_name, .. }), _)),
|
||||
)) => {
|
||||
let msg = "lifetime bound not satisfied";
|
||||
let mut err = self.tcx().sess.struct_span_err(*span, msg);
|
||||
let (sub_span, sub_symbol) = match sub_name {
|
||||
ty::BrNamed(def_id, symbol) => {
|
||||
(Some(self.tcx().def_span(def_id)), Some(symbol))
|
||||
}
|
||||
ty::BrAnon(_, span) => (*span, None),
|
||||
ty::BrEnv => (None, None),
|
||||
};
|
||||
let (sup_span, sup_symbol) = match sup_name {
|
||||
ty::BrNamed(def_id, symbol) => {
|
||||
(Some(self.tcx().def_span(def_id)), Some(symbol))
|
||||
}
|
||||
ty::BrAnon(_, span) => (*span, None),
|
||||
ty::BrEnv => (None, None),
|
||||
};
|
||||
match (sub_span, sup_span, sub_symbol, sup_symbol) {
|
||||
(Some(sub_span), Some(sup_span), Some(sub_symbol), Some(sup_symbol)) => {
|
||||
err.span_note(
|
||||
sub_span,
|
||||
format!("the lifetime `{sub_symbol}` defined here..."),
|
||||
);
|
||||
err.span_note(
|
||||
sup_span,
|
||||
format!("...must outlive the lifetime `{sup_symbol}` defined here"),
|
||||
);
|
||||
}
|
||||
(Some(sub_span), Some(sup_span), _, Some(sup_symbol)) => {
|
||||
err.span_note(sub_span, format!("the lifetime defined here..."));
|
||||
err.span_note(
|
||||
sup_span,
|
||||
format!("...must outlive the lifetime `{sup_symbol}` defined here"),
|
||||
);
|
||||
}
|
||||
(Some(sub_span), Some(sup_span), Some(sub_symbol), _) => {
|
||||
err.span_note(
|
||||
sub_span,
|
||||
format!("the lifetime `{sub_symbol}` defined here..."),
|
||||
);
|
||||
err.span_note(
|
||||
sup_span,
|
||||
format!("...must outlive the lifetime defined here"),
|
||||
);
|
||||
}
|
||||
(Some(sub_span), Some(sup_span), _, _) => {
|
||||
err.span_note(sub_span, format!("the lifetime defined here, ..."));
|
||||
err.span_note(
|
||||
sup_span,
|
||||
format!("...must outlive the lifetime defined here"),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Some(err)
|
||||
}
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
@ -336,8 +336,10 @@ impl<'tcx> CanonicalVarValues<'tcx> {
|
||||
tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
|
||||
}
|
||||
GenericArgKind::Lifetime(..) => {
|
||||
let br =
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(i), kind: ty::BrAnon(i) };
|
||||
let br = ty::BoundRegion {
|
||||
var: ty::BoundVar::from_u32(i),
|
||||
kind: ty::BrAnon(i, None),
|
||||
};
|
||||
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
|
||||
}
|
||||
GenericArgKind::Const(ct) => tcx
|
||||
|
@ -598,7 +598,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
.replace_late_bound_regions(sig, |_| {
|
||||
let br = ty::BoundRegion {
|
||||
var: ty::BoundVar::from_u32(counter),
|
||||
kind: ty::BrAnon(counter),
|
||||
kind: ty::BrAnon(counter, None),
|
||||
};
|
||||
let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br));
|
||||
counter += 1;
|
||||
@ -606,7 +606,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
})
|
||||
.0;
|
||||
let bound_vars = self.mk_bound_variable_kinds(
|
||||
(0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))),
|
||||
(0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))),
|
||||
);
|
||||
Binder::bind_with_vars(inner, bound_vars)
|
||||
}
|
||||
@ -626,7 +626,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
let index = entry.index();
|
||||
let var = ty::BoundVar::from_usize(index);
|
||||
let kind = entry
|
||||
.or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(index as u32)))
|
||||
.or_insert_with(|| {
|
||||
ty::BoundVariableKind::Region(ty::BrAnon(index as u32, None))
|
||||
})
|
||||
.expect_region();
|
||||
let br = ty::BoundRegion { var, kind };
|
||||
self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
|
||||
|
@ -2115,7 +2115,7 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
|
||||
// If this is an anonymous placeholder, don't rename. Otherwise, in some
|
||||
// async fns, we get a `for<'r> Send` bound
|
||||
match kind {
|
||||
ty::BrAnon(_) | ty::BrEnv => r,
|
||||
ty::BrAnon(..) | ty::BrEnv => r,
|
||||
_ => {
|
||||
// Index doesn't matter, since this is just for naming and these never get bound
|
||||
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind };
|
||||
@ -2226,10 +2226,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
||||
let ty::BoundVariableKind::Region(var) = var else {
|
||||
// This doesn't really matter because it doesn't get used,
|
||||
// it's just an empty value
|
||||
return ty::BrAnon(0);
|
||||
return ty::BrAnon(0, None);
|
||||
};
|
||||
match var {
|
||||
ty::BrAnon(_) | ty::BrEnv => {
|
||||
ty::BrAnon(..) | ty::BrEnv => {
|
||||
start_or_continue(&mut self, "for<", ", ");
|
||||
let name = next_name(&self);
|
||||
debug!(?name);
|
||||
@ -2271,7 +2271,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
||||
binder_level_idx: ty::DebruijnIndex,
|
||||
br: ty::BoundRegion| {
|
||||
let (name, kind) = match br.kind {
|
||||
ty::BrAnon(_) | ty::BrEnv => {
|
||||
ty::BrAnon(..) | ty::BrEnv => {
|
||||
let name = next_name(&self);
|
||||
|
||||
if let Some(lt_idx) = lifetime_idx {
|
||||
|
@ -68,7 +68,7 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
|
||||
impl fmt::Debug for ty::BoundRegionKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
|
||||
ty::BrAnon(n, span) => write!(f, "BrAnon({n:?}, {span:?})"),
|
||||
ty::BrNamed(did, name) => {
|
||||
if did.is_crate_root() {
|
||||
write!(f, "BrNamed({})", name)
|
||||
|
@ -59,7 +59,7 @@ pub struct FreeRegion {
|
||||
#[derive(HashStable)]
|
||||
pub enum BoundRegionKind {
|
||||
/// An anonymous region parameter for a given fn (&T)
|
||||
BrAnon(u32),
|
||||
BrAnon(u32, Option<Span>),
|
||||
|
||||
/// Named region parameters for functions (a in &'a T)
|
||||
///
|
||||
|
@ -218,7 +218,7 @@ impl<'tcx> SymbolMangler<'tcx> {
|
||||
let lifetimes = regions
|
||||
.into_iter()
|
||||
.map(|br| match br {
|
||||
ty::BrAnon(i) => i,
|
||||
ty::BrAnon(i, _) => i,
|
||||
_ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value),
|
||||
})
|
||||
.max()
|
||||
@ -335,7 +335,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
|
||||
|
||||
// Late-bound lifetimes use indices starting at 1,
|
||||
// see `BinderLevel` for more details.
|
||||
ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => {
|
||||
ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i, _), .. }) => {
|
||||
let binder = &self.binders[self.binders.len() - 1 - debruijn.index()];
|
||||
let depth = binder.lifetime_depths.start + i;
|
||||
|
||||
|
@ -1975,6 +1975,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
/// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
|
||||
/// Zed<i32> where enum Zed { A(T), B(u32) } -> [i32, u32]
|
||||
/// ```
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn constituent_types_for_ty(
|
||||
&self,
|
||||
t: ty::Binder<'tcx, Ty<'tcx>>,
|
||||
|
@ -728,7 +728,7 @@ fn bound_vars_for_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx
|
||||
ty::GenericParamDefKind::Lifetime => {
|
||||
let br = ty::BoundRegion {
|
||||
var: ty::BoundVar::from_usize(substs.len()),
|
||||
kind: ty::BrAnon(substs.len() as u32),
|
||||
kind: ty::BrAnon(substs.len() as u32, None),
|
||||
};
|
||||
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
|
||||
}
|
||||
|
@ -498,13 +498,13 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
|
||||
ty::DebruijnIndex::from_u32(var.debruijn.depth()),
|
||||
ty::BoundRegion {
|
||||
var: ty::BoundVar::from_usize(var.index),
|
||||
kind: ty::BrAnon(var.index as u32),
|
||||
kind: ty::BrAnon(var.index as u32, None),
|
||||
},
|
||||
),
|
||||
chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(),
|
||||
chalk_ir::LifetimeData::Placeholder(p) => ty::RePlaceholder(ty::Placeholder {
|
||||
universe: ty::UniverseIndex::from_usize(p.ui.counter),
|
||||
name: ty::BoundRegionKind::BrAnon(p.idx as u32),
|
||||
name: ty::BoundRegionKind::BrAnon(p.idx as u32, None),
|
||||
}),
|
||||
chalk_ir::LifetimeData::Static => return interner.tcx.lifetimes.re_static,
|
||||
chalk_ir::LifetimeData::Empty(_) => {
|
||||
@ -933,7 +933,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
ty::BoundRegionKind::BrAnon(var) => match self.parameters.entry(var) {
|
||||
ty::BoundRegionKind::BrAnon(var, _) => match self.parameters.entry(var) {
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(chalk_ir::VariableKind::Lifetime);
|
||||
}
|
||||
@ -991,13 +991,13 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> {
|
||||
ty::ReLateBound(index, br) if index == self.binder_index => match br.kind {
|
||||
ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
|
||||
Some(idx) => {
|
||||
let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx) };
|
||||
let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx, None) };
|
||||
return self.tcx.mk_region(ty::ReLateBound(index, new_br));
|
||||
}
|
||||
None => panic!("Missing `BrNamed`."),
|
||||
},
|
||||
ty::BrEnv => unimplemented!(),
|
||||
ty::BrAnon(_) => {}
|
||||
ty::BrAnon(..) => {}
|
||||
},
|
||||
_ => (),
|
||||
};
|
||||
@ -1072,14 +1072,16 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
|
||||
Some(idx) => {
|
||||
let br = ty::BoundRegion {
|
||||
var: ty::BoundVar::from_u32(*idx),
|
||||
kind: ty::BrAnon(*idx),
|
||||
kind: ty::BrAnon(*idx, None),
|
||||
};
|
||||
self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
|
||||
}
|
||||
None => {
|
||||
let idx = self.named_regions.len() as u32;
|
||||
let br =
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) };
|
||||
let br = ty::BoundRegion {
|
||||
var: ty::BoundVar::from_u32(idx),
|
||||
kind: ty::BrAnon(idx, None),
|
||||
};
|
||||
self.named_regions.insert(_re.def_id, idx);
|
||||
self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
|
||||
}
|
||||
@ -1156,7 +1158,7 @@ impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
|
||||
fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match *r {
|
||||
ty::RePlaceholder(p) if p.universe == self.universe_index => {
|
||||
if let ty::BoundRegionKind::BrAnon(anon) = p.name {
|
||||
if let ty::BoundRegionKind::BrAnon(anon, _) = p.name {
|
||||
self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon);
|
||||
}
|
||||
}
|
||||
|
22
src/test/ui/generic-associated-types/bugs/issue-100013.rs
Normal file
22
src/test/ui/generic-associated-types/bugs/issue-100013.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// check-fail
|
||||
// known-bug
|
||||
// edition: 2021
|
||||
|
||||
// We really should accept this, but we need implied bounds between the regions
|
||||
// in a generator interior.
|
||||
|
||||
pub trait FutureIterator {
|
||||
type Future<'s, 'cx>: Send
|
||||
where
|
||||
's: 'cx;
|
||||
}
|
||||
|
||||
fn call_2<I: FutureIterator>() -> impl Send {
|
||||
async { // a generator checked for autotrait impl `Send`
|
||||
//~^ lifetime bound not satisfied
|
||||
let x = None::<I::Future<'_, '_>>; // a type referencing GAT
|
||||
async {}.await; // a yield point
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,23 @@
|
||||
error: lifetime bound not satisfied
|
||||
--> $DIR/issue-100013.rs:15:5
|
||||
|
|
||||
LL | / async { // a generator checked for autotrait impl `Send`
|
||||
LL | |
|
||||
LL | | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
|
||||
LL | | async {}.await; // a yield point
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: the lifetime defined here, ...
|
||||
--> $DIR/issue-100013.rs:17:38
|
||||
|
|
||||
LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
|
||||
| ^^
|
||||
note: ...must outlive the lifetime defined here
|
||||
--> $DIR/issue-100013.rs:17:34
|
||||
|
|
||||
LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
|
||||
| ^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Reference in New Issue
Block a user