mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #103171 - jackh726:gen-interior-hrtb-error, r=cjgillot
Better error for HRTB error from generator interior cc #100013 This is just a first pass at an error. It could be better, and shouldn't really be emitted in the first place. But this is better than what was being emitted before.
This commit is contained in:
commit
bc2504a83c
@ -158,6 +158,7 @@ trait TypeOpInfo<'tcx> {
|
|||||||
error_region: Option<ty::Region<'tcx>>,
|
error_region: Option<ty::Region<'tcx>>,
|
||||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
|
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self, mbcx))]
|
||||||
fn report_error(
|
fn report_error(
|
||||||
&self,
|
&self,
|
||||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||||
@ -167,6 +168,7 @@ trait TypeOpInfo<'tcx> {
|
|||||||
) {
|
) {
|
||||||
let tcx = mbcx.infcx.tcx;
|
let tcx = mbcx.infcx.tcx;
|
||||||
let base_universe = self.base_universe();
|
let base_universe = self.base_universe();
|
||||||
|
debug!(?base_universe);
|
||||||
|
|
||||||
let Some(adjusted_universe) =
|
let Some(adjusted_universe) =
|
||||||
placeholder.universe.as_u32().checked_sub(base_universe.as_u32())
|
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>(
|
fn try_extract_error_from_region_constraints<'tcx>(
|
||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
placeholder_region: ty::Region<'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,
|
ty::ReLateBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => None,
|
||||||
|
@ -2980,7 +2980,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
) {
|
) {
|
||||||
for br in referenced_regions.difference(&constrained_regions) {
|
for br in referenced_regions.difference(&constrained_regions) {
|
||||||
let br_name = match *br {
|
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()
|
"an anonymous lifetime".to_string()
|
||||||
}
|
}
|
||||||
ty::BrNamed(_, name) => format!("lifetime `{}`", name),
|
ty::BrNamed(_, name) => format!("lifetime `{}`", name),
|
||||||
@ -2988,7 +2988,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
|
|
||||||
let mut err = generate_err(&br_name);
|
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
|
// The only way for an anonymous lifetime to wind up
|
||||||
// in the return type but **also** be unconstrained is
|
// in the return type but **also** be unconstrained is
|
||||||
// if it only appears in "associated types" in the
|
// 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 name_str = intrinsic_name.as_str();
|
||||||
|
|
||||||
let bound_vars = tcx.mk_bound_variable_kinds(
|
let bound_vars = tcx.mk_bound_variable_kinds(
|
||||||
[ty::BoundVariableKind::Region(ty::BrAnon(0)), ty::BoundVariableKind::Region(ty::BrEnv)]
|
[
|
||||||
.iter()
|
ty::BoundVariableKind::Region(ty::BrAnon(0, None)),
|
||||||
.copied(),
|
ty::BoundVariableKind::Region(ty::BrEnv),
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.copied(),
|
||||||
);
|
);
|
||||||
let mk_va_list_ty = |mutbl| {
|
let mk_va_list_ty = |mutbl| {
|
||||||
tcx.lang_items().va_list().map(|did| {
|
tcx.lang_items().va_list().map(|did| {
|
||||||
let region = tcx.mk_region(ty::ReLateBound(
|
let region = tcx.mk_region(ty::ReLateBound(
|
||||||
ty::INNERMOST,
|
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(
|
let env_region = tcx.mk_region(ty::ReLateBound(
|
||||||
ty::INNERMOST,
|
ty::INNERMOST,
|
||||||
@ -364,7 +367,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
|||||||
);
|
);
|
||||||
let discriminant_def_id = assoc_items[0];
|
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,
|
1,
|
||||||
vec![
|
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::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
|
||||||
|
|
||||||
sym::raw_eq => {
|
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 =
|
let param_ty =
|
||||||
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0));
|
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0));
|
||||||
(1, vec![param_ty; 2], tcx.types.bool)
|
(1, vec![param_ty; 2], tcx.types.bool)
|
||||||
|
@ -13,10 +13,13 @@ use rustc_hir::def_id::DefId;
|
|||||||
use rustc_hir::hir_id::HirIdSet;
|
use rustc_hir::hir_id::HirIdSet;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind};
|
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::middle::region::{self, Scope, ScopeData, YieldData};
|
||||||
use rustc_middle::ty::{self, RvalueScopes, Ty, TyCtxt, TypeVisitable};
|
use rustc_middle::ty::fold::FnMutDelegate;
|
||||||
|
use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitable};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
mod drop_ranges;
|
mod drop_ranges;
|
||||||
|
|
||||||
@ -211,31 +214,57 @@ pub fn resolve_interior<'a, 'tcx>(
|
|||||||
|
|
||||||
debug!("types in generator {:?}, span = {:?}", types, body.value.span);
|
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 mut captured_tys = FxHashSet::default();
|
||||||
let type_causes: Vec<_> = types
|
let type_causes: Vec<_> = types
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|mut cause| {
|
.filter_map(|mut cause| {
|
||||||
// Erase regions and canonicalize late-bound regions to deduplicate as many types as we
|
// Replace all regions inside the generator interior with late bound regions.
|
||||||
// can.
|
// Note that each region slot in the types gets a new fresh late bound region,
|
||||||
let ty = fcx.normalize_associated_types_in(cause.span, cause.ty);
|
// which means that none of the regions inside relate to any other, even if
|
||||||
let erased = fcx.tcx.erase_regions(ty);
|
// typeck had previously found constraints that would cause them to be related.
|
||||||
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
|
|
||||||
});
|
|
||||||
|
|
||||||
cause.ty = folded;
|
let mut counter = 0;
|
||||||
|
let mut mk_bound_region = |span| {
|
||||||
|
let kind = ty::BrAnon(counter, span);
|
||||||
|
let var = ty::BoundVar::from_u32(counter);
|
||||||
|
counter += 1;
|
||||||
|
ty::BoundRegion { var, kind }
|
||||||
|
};
|
||||||
|
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, _) => {
|
||||||
|
mk_bound_region(Some(span))
|
||||||
|
}
|
||||||
|
_ => mk_bound_region(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// FIXME: these should use `BrNamed`
|
||||||
|
ty::ReEarlyBound(region) => {
|
||||||
|
mk_bound_region(Some(fcx.tcx.def_span(region.def_id)))
|
||||||
|
}
|
||||||
|
ty::ReLateBound(_, ty::BoundRegion { kind, .. })
|
||||||
|
| ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind {
|
||||||
|
ty::BoundRegionKind::BrAnon(_, span) => mk_bound_region(span),
|
||||||
|
ty::BoundRegionKind::BrNamed(def_id, _) => {
|
||||||
|
mk_bound_region(Some(fcx.tcx.def_span(def_id)))
|
||||||
|
}
|
||||||
|
ty::BoundRegionKind::BrEnv => mk_bound_region(None),
|
||||||
|
},
|
||||||
|
_ => mk_bound_region(None),
|
||||||
|
};
|
||||||
|
let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
|
||||||
|
r
|
||||||
|
});
|
||||||
|
if captured_tys.insert(ty) {
|
||||||
|
cause.ty = ty;
|
||||||
Some(cause)
|
Some(cause)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -243,11 +272,38 @@ pub fn resolve_interior<'a, 'tcx>(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let mut bound_vars: SmallVec<[BoundVariableKind; 4]> = smallvec![];
|
||||||
|
let mut counter = 0;
|
||||||
|
// Optimization: If there is only one captured type, then we don't actually
|
||||||
|
// need to fold and reindex (since the first type doesn't change).
|
||||||
|
let type_causes = if captured_tys.len() > 0 {
|
||||||
|
// Optimization: Use `replace_escaping_bound_vars_uncached` instead of
|
||||||
|
// `fold_regions`, since we only have late bound regions, and it skips
|
||||||
|
// types without bound regions.
|
||||||
|
fcx.tcx.replace_escaping_bound_vars_uncached(
|
||||||
|
type_causes,
|
||||||
|
FnMutDelegate {
|
||||||
|
regions: &mut |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;
|
||||||
|
fcx.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var, kind }))
|
||||||
|
},
|
||||||
|
types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
|
||||||
|
consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
type_causes
|
||||||
|
};
|
||||||
|
|
||||||
// Extract type components to build the witness type.
|
// Extract type components to build the witness type.
|
||||||
let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));
|
let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));
|
||||||
let bound_vars = fcx.tcx.mk_bound_variable_kinds(
|
let bound_vars = fcx.tcx.mk_bound_variable_kinds(bound_vars.iter());
|
||||||
(0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))),
|
|
||||||
);
|
|
||||||
let witness =
|
let witness =
|
||||||
fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone()));
|
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)
|
typeck_with_fallback(tcx, def_id, fallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(tcx, fallback), ret)]
|
||||||
fn typeck_with_fallback<'tcx>(
|
fn typeck_with_fallback<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
|
@ -89,10 +89,13 @@ impl<'a> DescriptionCtx<'a> {
|
|||||||
};
|
};
|
||||||
me.span = Some(sp);
|
me.span = Some(sp);
|
||||||
}
|
}
|
||||||
ty::BrAnon(idx) => {
|
ty::BrAnon(idx, span) => {
|
||||||
me.kind = "anon_num_here";
|
me.kind = "anon_num_here";
|
||||||
me.num_arg = idx+1;
|
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";
|
me.kind = "defined_here_reg";
|
||||||
|
@ -738,7 +738,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
|
|||||||
r: ty::Region<'tcx>,
|
r: ty::Region<'tcx>,
|
||||||
) -> ty::Region<'tcx> {
|
) -> ty::Region<'tcx> {
|
||||||
let var = self.canonical_var(info, r.into());
|
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);
|
let region = ty::ReLateBound(self.binder_index, br);
|
||||||
self.tcx().mk_region(region)
|
self.tcx().mk_region(region)
|
||||||
}
|
}
|
||||||
|
@ -207,9 +207,12 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>(
|
|||||||
};
|
};
|
||||||
(text, sp)
|
(text, sp)
|
||||||
}
|
}
|
||||||
ty::BrAnon(idx) => (
|
ty::BrAnon(idx, span) => (
|
||||||
format!("the anonymous lifetime #{} defined here", idx + 1),
|
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),
|
format!("the lifetime `{}` as defined here", region),
|
||||||
|
@ -10,6 +10,7 @@ pub mod find_anon_type;
|
|||||||
mod mismatched_static_lifetime;
|
mod mismatched_static_lifetime;
|
||||||
mod named_anon_conflict;
|
mod named_anon_conflict;
|
||||||
mod placeholder_error;
|
mod placeholder_error;
|
||||||
|
mod placeholder_relation;
|
||||||
mod static_impl_trait;
|
mod static_impl_trait;
|
||||||
mod trait_impl_difference;
|
mod trait_impl_difference;
|
||||||
mod util;
|
mod util;
|
||||||
@ -52,7 +53,9 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
|
|||||||
pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
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
|
// 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.
|
// 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> {
|
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;
|
let is_impl_item = region_info.is_impl_item;
|
||||||
|
|
||||||
match br {
|
match br {
|
||||||
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) => {}
|
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) => {}
|
||||||
_ => {
|
_ => {
|
||||||
/* not an anonymous region */
|
/* not an anonymous region */
|
||||||
debug!("try_report_named_anon_conflict: not an anonymous region");
|
debug!("try_report_named_anon_conflict: not an anonymous region");
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
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"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
err.note("this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)");
|
||||||
|
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()
|
tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
|
||||||
}
|
}
|
||||||
GenericArgKind::Lifetime(..) => {
|
GenericArgKind::Lifetime(..) => {
|
||||||
let br =
|
let br = ty::BoundRegion {
|
||||||
ty::BoundRegion { var: ty::BoundVar::from_u32(i), kind: ty::BrAnon(i) };
|
var: ty::BoundVar::from_u32(i),
|
||||||
|
kind: ty::BrAnon(i, None),
|
||||||
|
};
|
||||||
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
|
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
|
||||||
}
|
}
|
||||||
GenericArgKind::Const(ct) => tcx
|
GenericArgKind::Const(ct) => tcx
|
||||||
|
@ -598,7 +598,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
.replace_late_bound_regions(sig, |_| {
|
.replace_late_bound_regions(sig, |_| {
|
||||||
let br = ty::BoundRegion {
|
let br = ty::BoundRegion {
|
||||||
var: ty::BoundVar::from_u32(counter),
|
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));
|
let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br));
|
||||||
counter += 1;
|
counter += 1;
|
||||||
@ -606,7 +606,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
})
|
})
|
||||||
.0;
|
.0;
|
||||||
let bound_vars = self.mk_bound_variable_kinds(
|
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)
|
Binder::bind_with_vars(inner, bound_vars)
|
||||||
}
|
}
|
||||||
@ -626,7 +626,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
let index = entry.index();
|
let index = entry.index();
|
||||||
let var = ty::BoundVar::from_usize(index);
|
let var = ty::BoundVar::from_usize(index);
|
||||||
let kind = entry
|
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();
|
.expect_region();
|
||||||
let br = ty::BoundRegion { var, kind };
|
let br = ty::BoundRegion { var, kind };
|
||||||
self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
|
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
|
// If this is an anonymous placeholder, don't rename. Otherwise, in some
|
||||||
// async fns, we get a `for<'r> Send` bound
|
// async fns, we get a `for<'r> Send` bound
|
||||||
match kind {
|
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
|
// 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 };
|
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 {
|
let ty::BoundVariableKind::Region(var) = var else {
|
||||||
// This doesn't really matter because it doesn't get used,
|
// This doesn't really matter because it doesn't get used,
|
||||||
// it's just an empty value
|
// it's just an empty value
|
||||||
return ty::BrAnon(0);
|
return ty::BrAnon(0, None);
|
||||||
};
|
};
|
||||||
match var {
|
match var {
|
||||||
ty::BrAnon(_) | ty::BrEnv => {
|
ty::BrAnon(..) | ty::BrEnv => {
|
||||||
start_or_continue(&mut self, "for<", ", ");
|
start_or_continue(&mut self, "for<", ", ");
|
||||||
let name = next_name(&self);
|
let name = next_name(&self);
|
||||||
debug!(?name);
|
debug!(?name);
|
||||||
@ -2271,7 +2271,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
|||||||
binder_level_idx: ty::DebruijnIndex,
|
binder_level_idx: ty::DebruijnIndex,
|
||||||
br: ty::BoundRegion| {
|
br: ty::BoundRegion| {
|
||||||
let (name, kind) = match br.kind {
|
let (name, kind) = match br.kind {
|
||||||
ty::BrAnon(_) | ty::BrEnv => {
|
ty::BrAnon(..) | ty::BrEnv => {
|
||||||
let name = next_name(&self);
|
let name = next_name(&self);
|
||||||
|
|
||||||
if let Some(lt_idx) = lifetime_idx {
|
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 {
|
impl fmt::Debug for ty::BoundRegionKind {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
|
ty::BrAnon(n, span) => write!(f, "BrAnon({n:?}, {span:?})"),
|
||||||
ty::BrNamed(did, name) => {
|
ty::BrNamed(did, name) => {
|
||||||
if did.is_crate_root() {
|
if did.is_crate_root() {
|
||||||
write!(f, "BrNamed({})", name)
|
write!(f, "BrNamed({})", name)
|
||||||
|
@ -59,7 +59,7 @@ pub struct FreeRegion {
|
|||||||
#[derive(HashStable)]
|
#[derive(HashStable)]
|
||||||
pub enum BoundRegionKind {
|
pub enum BoundRegionKind {
|
||||||
/// An anonymous region parameter for a given fn (&T)
|
/// An anonymous region parameter for a given fn (&T)
|
||||||
BrAnon(u32),
|
BrAnon(u32, Option<Span>),
|
||||||
|
|
||||||
/// Named region parameters for functions (a in &'a T)
|
/// Named region parameters for functions (a in &'a T)
|
||||||
///
|
///
|
||||||
|
@ -218,7 +218,7 @@ impl<'tcx> SymbolMangler<'tcx> {
|
|||||||
let lifetimes = regions
|
let lifetimes = regions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|br| match br {
|
.map(|br| match br {
|
||||||
ty::BrAnon(i) => i,
|
ty::BrAnon(i, _) => i,
|
||||||
_ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value),
|
_ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value),
|
||||||
})
|
})
|
||||||
.max()
|
.max()
|
||||||
@ -335,7 +335,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
|
|||||||
|
|
||||||
// Late-bound lifetimes use indices starting at 1,
|
// Late-bound lifetimes use indices starting at 1,
|
||||||
// see `BinderLevel` for more details.
|
// 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 binder = &self.binders[self.binders.len() - 1 - debruijn.index()];
|
||||||
let depth = binder.lifetime_depths.start + i;
|
let depth = binder.lifetime_depths.start + i;
|
||||||
|
|
||||||
|
@ -1971,6 +1971,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
/// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
|
/// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
|
||||||
/// Zed<i32> where enum Zed { A(T), B(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(
|
fn constituent_types_for_ty(
|
||||||
&self,
|
&self,
|
||||||
t: ty::Binder<'tcx, Ty<'tcx>>,
|
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 => {
|
ty::GenericParamDefKind::Lifetime => {
|
||||||
let br = ty::BoundRegion {
|
let br = ty::BoundRegion {
|
||||||
var: ty::BoundVar::from_usize(substs.len()),
|
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()
|
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::DebruijnIndex::from_u32(var.debruijn.depth()),
|
||||||
ty::BoundRegion {
|
ty::BoundRegion {
|
||||||
var: ty::BoundVar::from_usize(var.index),
|
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::InferenceVar(_var) => unimplemented!(),
|
||||||
chalk_ir::LifetimeData::Placeholder(p) => ty::RePlaceholder(ty::Placeholder {
|
chalk_ir::LifetimeData::Placeholder(p) => ty::RePlaceholder(ty::Placeholder {
|
||||||
universe: ty::UniverseIndex::from_usize(p.ui.counter),
|
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::Static => return interner.tcx.lifetimes.re_static,
|
||||||
chalk_ir::LifetimeData::Empty(_) => {
|
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::Vacant(entry) => {
|
||||||
entry.insert(chalk_ir::VariableKind::Lifetime);
|
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::ReLateBound(index, br) if index == self.binder_index => match br.kind {
|
||||||
ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
|
ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
|
||||||
Some(idx) => {
|
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));
|
return self.tcx.mk_region(ty::ReLateBound(index, new_br));
|
||||||
}
|
}
|
||||||
None => panic!("Missing `BrNamed`."),
|
None => panic!("Missing `BrNamed`."),
|
||||||
},
|
},
|
||||||
ty::BrEnv => unimplemented!(),
|
ty::BrEnv => unimplemented!(),
|
||||||
ty::BrAnon(_) => {}
|
ty::BrAnon(..) => {}
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
@ -1072,14 +1072,16 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
|
|||||||
Some(idx) => {
|
Some(idx) => {
|
||||||
let br = ty::BoundRegion {
|
let br = ty::BoundRegion {
|
||||||
var: ty::BoundVar::from_u32(*idx),
|
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))
|
self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let idx = self.named_regions.len() as u32;
|
let idx = self.named_regions.len() as u32;
|
||||||
let br =
|
let br = ty::BoundRegion {
|
||||||
ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) };
|
var: ty::BoundVar::from_u32(idx),
|
||||||
|
kind: ty::BrAnon(idx, None),
|
||||||
|
};
|
||||||
self.named_regions.insert(_re.def_id, idx);
|
self.named_regions.insert(_re.def_id, idx);
|
||||||
self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
|
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> {
|
fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
match *r {
|
match *r {
|
||||||
ty::RePlaceholder(p) if p.universe == self.universe_index => {
|
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);
|
self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
src/test/ui/generic-associated-types/bugs/issue-100013.rs
Normal file
39
src/test/ui/generic-associated-types/bugs/issue-100013.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// 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<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 call2<'a, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
async { // a generator checked for autotrait impl `Send`
|
||||||
|
//~^ lifetime bound not satisfied
|
||||||
|
let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
|
||||||
|
//~^ lifetime may not live long enough
|
||||||
|
async {}.await; // a yield point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
async { // a generator checked for autotrait impl `Send`
|
||||||
|
//~^ lifetime bound not satisfied
|
||||||
|
let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
|
||||||
|
async {}.await; // a yield point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,82 @@
|
|||||||
|
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
|
||||||
|
| ^^
|
||||||
|
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
|
||||||
|
|
||||||
|
error: lifetime bound not satisfied
|
||||||
|
--> $DIR/issue-100013.rs:23:5
|
||||||
|
|
|
||||||
|
LL | / async { // a generator checked for autotrait impl `Send`
|
||||||
|
LL | |
|
||||||
|
LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
|
||||||
|
LL | |
|
||||||
|
LL | | async {}.await; // a yield point
|
||||||
|
LL | | }
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
note: the lifetime defined here...
|
||||||
|
--> $DIR/issue-100013.rs:22:14
|
||||||
|
|
|
||||||
|
LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
| ^^
|
||||||
|
note: ...must outlive the lifetime defined here
|
||||||
|
--> $DIR/issue-100013.rs:22:10
|
||||||
|
|
|
||||||
|
LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
| ^^
|
||||||
|
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/issue-100013.rs:25:17
|
||||||
|
|
|
||||||
|
LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
| -- -- lifetime `'b` defined here
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
...
|
||||||
|
LL | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'a: 'b`
|
||||||
|
|
||||||
|
error: lifetime bound not satisfied
|
||||||
|
--> $DIR/issue-100013.rs:32:5
|
||||||
|
|
|
||||||
|
LL | / async { // a generator checked for autotrait impl `Send`
|
||||||
|
LL | |
|
||||||
|
LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
|
||||||
|
LL | | async {}.await; // a yield point
|
||||||
|
LL | | }
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
note: the lifetime defined here...
|
||||||
|
--> $DIR/issue-100013.rs:31:18
|
||||||
|
|
|
||||||
|
LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
| ^^
|
||||||
|
note: ...must outlive the lifetime defined here
|
||||||
|
--> $DIR/issue-100013.rs:31:10
|
||||||
|
|
|
||||||
|
LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
| ^^
|
||||||
|
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
Loading…
Reference in New Issue
Block a user