1
Fork 0

Auto merge of #102618 - aliemjay:simplify-closure-promote, r=compiler-errors

rework applying closure requirements in borrowck

Previously the promoted closure constraints were registered under the category `ConstraintCategory::ClosureBounds` in `type_check::prove_closure_bounds()` and then mapped back their original category in `regions_infer::best_blame_constraint` using the complicated map `closure_bounds_mapping`.

Now we're registering promoted constraints under their original category and span earlier in `type_check::prove_closure_bounds`.

See commit messages.

Fixes #99245
This commit is contained in:
bors 2022-11-06 05:26:09 +00:00
commit e30fb6a26f
26 changed files with 173 additions and 349 deletions

View file

@ -163,6 +163,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> {
span: DUMMY_SP, span: DUMMY_SP,
category: ConstraintCategory::Internal, category: ConstraintCategory::Internal,
variance_info: VarianceDiagInfo::default(), variance_info: VarianceDiagInfo::default(),
from_closure: false,
}) })
} else { } else {
None None

View file

@ -96,6 +96,9 @@ pub struct OutlivesConstraint<'tcx> {
/// Variance diagnostic information /// Variance diagnostic information
pub variance_info: VarianceDiagInfo<'tcx>, pub variance_info: VarianceDiagInfo<'tcx>,
/// If this constraint is promoted from closure requirements.
pub from_closure: bool,
} }
impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> { impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {

View file

@ -181,7 +181,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// Try to convert the lower-bound region into something named we can print for the user. // Try to convert the lower-bound region into something named we can print for the user.
let lower_bound_region = self.to_error_region(type_test.lower_bound); let lower_bound_region = self.to_error_region(type_test.lower_bound);
let type_test_span = type_test.locations.span(&self.body); let type_test_span = type_test.span;
if let Some(lower_bound_region) = lower_bound_region { if let Some(lower_bound_region) = lower_bound_region {
let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx); let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);

View file

@ -242,7 +242,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
mut liveness_constraints, mut liveness_constraints,
outlives_constraints, outlives_constraints,
member_constraints, member_constraints,
closure_bounds_mapping,
universe_causes, universe_causes,
type_tests, type_tests,
} = constraints; } = constraints;
@ -264,7 +263,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
universal_region_relations, universal_region_relations,
outlives_constraints, outlives_constraints,
member_constraints, member_constraints,
closure_bounds_mapping,
universe_causes, universe_causes,
type_tests, type_tests,
liveness_constraints, liveness_constraints,

View file

@ -74,8 +74,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let mut constraints: Vec<_> = self.constraints.outlives().iter().collect(); let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
constraints.sort_by_key(|c| (c.sup, c.sub)); constraints.sort_by_key(|c| (c.sup, c.sub));
for constraint in &constraints { for constraint in &constraints {
let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } = let OutlivesConstraint { sup, sub, locations, category, span, .. } = constraint;
constraint;
let (name, arg) = match locations { let (name, arg) = match locations {
Locations::All(span) => { Locations::All(span) => {
("All", tcx.sess.source_map().span_to_embeddable_string(*span)) ("All", tcx.sess.source_map().span_to_embeddable_string(*span))

View file

@ -6,10 +6,9 @@ use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::graph::scc::Sccs; use rustc_data_structures::graph::scc::Sccs;
use rustc_errors::Diagnostic; use rustc_errors::Diagnostic;
use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::def_id::CRATE_DEF_ID;
use rustc_hir::CRATE_HIR_ID; use rustc_hir::CRATE_HIR_ID;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_infer::infer::canonical::QueryOutlivesConstraint;
use rustc_infer::infer::outlives::test_type_match; use rustc_infer::infer::outlives::test_type_match;
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq}; use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
@ -19,9 +18,7 @@ use rustc_middle::mir::{
}; };
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::ObligationCauseCode; use rustc_middle::traits::ObligationCauseCode;
use rustc_middle::ty::{ use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable};
self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable,
};
use rustc_span::Span; use rustc_span::Span;
use crate::{ use crate::{
@ -89,10 +86,6 @@ pub struct RegionInferenceContext<'tcx> {
/// `member_region_scc`. /// `member_region_scc`.
member_constraints_applied: Vec<AppliedMemberConstraint>, member_constraints_applied: Vec<AppliedMemberConstraint>,
/// Map closure bounds to a `Span` that should be used for error reporting.
closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
/// Map universe indexes to information on why we created it. /// Map universe indexes to information on why we created it.
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>, universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
@ -221,8 +214,8 @@ pub struct TypeTest<'tcx> {
/// The region `'x` that the type must outlive. /// The region `'x` that the type must outlive.
pub lower_bound: RegionVid, pub lower_bound: RegionVid,
/// Where did this constraint arise and why? /// The span to blame.
pub locations: Locations, pub span: Span,
/// A test which, if met by the region `'x`, proves that this type /// A test which, if met by the region `'x`, proves that this type
/// constraint is satisfied. /// constraint is satisfied.
@ -265,10 +258,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>, universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
outlives_constraints: OutlivesConstraintSet<'tcx>, outlives_constraints: OutlivesConstraintSet<'tcx>,
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>, member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
closure_bounds_mapping: FxHashMap<
Location,
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>,
>,
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>, universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
type_tests: Vec<TypeTest<'tcx>>, type_tests: Vec<TypeTest<'tcx>>,
liveness_constraints: LivenessValues<RegionVid>, liveness_constraints: LivenessValues<RegionVid>,
@ -310,7 +299,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
rev_scc_graph: None, rev_scc_graph: None,
member_constraints, member_constraints,
member_constraints_applied: Vec::new(), member_constraints_applied: Vec::new(),
closure_bounds_mapping,
universe_causes, universe_causes,
scc_universes, scc_universes,
scc_representatives, scc_representatives,
@ -882,13 +870,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
if deduplicate_errors.insert(( if deduplicate_errors.insert((
erased_generic_kind, erased_generic_kind,
type_test.lower_bound, type_test.lower_bound,
type_test.locations, type_test.span,
)) { )) {
debug!( debug!(
"check_type_test: reporting error for erased_generic_kind={:?}, \ "check_type_test: reporting error for erased_generic_kind={:?}, \
lower_bound_region={:?}, \ lower_bound_region={:?}, \
type_test.locations={:?}", type_test.span={:?}",
erased_generic_kind, type_test.lower_bound, type_test.locations, erased_generic_kind, type_test.lower_bound, type_test.span,
); );
errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() }); errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() });
@ -931,7 +919,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) -> bool { ) -> bool {
let tcx = infcx.tcx; let tcx = infcx.tcx;
let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test; let TypeTest { generic_kind, lower_bound, span: _, verify_bound: _ } = type_test;
let generic_ty = generic_kind.to_ty(tcx); let generic_ty = generic_kind.to_ty(tcx);
let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else { let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else {
@ -959,7 +947,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
propagated_outlives_requirements.push(ClosureOutlivesRequirement { propagated_outlives_requirements.push(ClosureOutlivesRequirement {
subject, subject,
outlived_free_region: static_r, outlived_free_region: static_r,
blame_span: locations.span(body), blame_span: type_test.span,
category: ConstraintCategory::Boring, category: ConstraintCategory::Boring,
}); });
@ -1011,7 +999,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let requirement = ClosureOutlivesRequirement { let requirement = ClosureOutlivesRequirement {
subject, subject,
outlived_free_region: upper_bound, outlived_free_region: upper_bound,
blame_span: locations.span(body), blame_span: type_test.span,
category: ConstraintCategory::Boring, category: ConstraintCategory::Boring,
}; };
debug!("try_promote_type_test: pushing {:#?}", requirement); debug!("try_promote_type_test: pushing {:#?}", requirement);
@ -1804,18 +1792,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
} }
} }
pub(crate) fn retrieve_closure_constraint_info(
&self,
constraint: OutlivesConstraint<'tcx>,
) -> Option<(ConstraintCategory<'tcx>, Span)> {
match constraint.locations {
Locations::All(_) => None,
Locations::Single(loc) => {
self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)).copied()
}
}
}
/// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`. /// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
pub(crate) fn find_outlives_blame_span( pub(crate) fn find_outlives_blame_span(
&self, &self,
@ -1921,6 +1897,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
span: p_c.definition_span, span: p_c.definition_span,
category: ConstraintCategory::OpaqueType, category: ConstraintCategory::OpaqueType,
variance_info: ty::VarianceDiagInfo::default(), variance_info: ty::VarianceDiagInfo::default(),
from_closure: false,
}; };
handle_constraint(constraint); handle_constraint(constraint);
} }
@ -2066,31 +2043,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Classify each of the constraints along the path. // Classify each of the constraints along the path.
let mut categorized_path: Vec<BlameConstraint<'tcx>> = path let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
.iter() .iter()
.map(|constraint| { .map(|constraint| BlameConstraint {
let (category, span, from_closure, cause_code) = category: constraint.category,
if constraint.category == ConstraintCategory::ClosureBounds { from_closure: constraint.from_closure,
if let Some((category, span)) = cause: ObligationCause::new(constraint.span, CRATE_HIR_ID, cause_code.clone()),
self.retrieve_closure_constraint_info(*constraint) variance_info: constraint.variance_info,
{ outlives_constraint: *constraint,
(category, span, true, ObligationCauseCode::MiscObligation)
} else {
(
constraint.category,
constraint.span,
false,
ObligationCauseCode::MiscObligation,
)
}
} else {
(constraint.category, constraint.span, false, cause_code.clone())
};
BlameConstraint {
category,
from_closure,
cause: ObligationCause::new(span, CRATE_HIR_ID, cause_code),
variance_info: constraint.variance_info,
outlives_constraint: *constraint,
}
}) })
.collect(); .collect();
debug!("categorized_path={:#?}", categorized_path); debug!("categorized_path={:#?}", categorized_path);
@ -2274,92 +2232,6 @@ impl<'tcx> RegionDefinition<'tcx> {
} }
} }
pub trait ClosureRegionRequirementsExt<'tcx> {
fn apply_requirements(
&self,
tcx: TyCtxt<'tcx>,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
) -> Vec<QueryOutlivesConstraint<'tcx>>;
}
impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx> {
/// Given an instance T of the closure type, this method
/// instantiates the "extra" requirements that we computed for the
/// closure into the inference context. This has the effect of
/// adding new outlives obligations to existing variables.
///
/// As described on `ClosureRegionRequirements`, the extra
/// requirements are expressed in terms of regionvids that index
/// into the free regions that appear on the closure type. So, to
/// do this, we first copy those regions out from the type T into
/// a vector. Then we can just index into that vector to extract
/// out the corresponding region from T and apply the
/// requirements.
fn apply_requirements(
&self,
tcx: TyCtxt<'tcx>,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
) -> Vec<QueryOutlivesConstraint<'tcx>> {
debug!(
"apply_requirements(closure_def_id={:?}, closure_substs={:?})",
closure_def_id, closure_substs
);
// Extract the values of the free regions in `closure_substs`
// into a vector. These are the regions that we will be
// relating to one another.
let closure_mapping = &UniversalRegions::closure_mapping(
tcx,
closure_substs,
self.num_external_vids,
closure_def_id.expect_local(),
);
debug!("apply_requirements: closure_mapping={:?}", closure_mapping);
// Create the predicates.
self.outlives_requirements
.iter()
.map(|outlives_requirement| {
let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
match outlives_requirement.subject {
ClosureOutlivesSubject::Region(region) => {
let region = closure_mapping[region];
debug!(
"apply_requirements: region={:?} \
outlived_region={:?} \
outlives_requirement={:?}",
region, outlived_region, outlives_requirement,
);
(
ty::Binder::dummy(ty::OutlivesPredicate(
region.into(),
outlived_region,
)),
ConstraintCategory::BoringNoLocation,
)
}
ClosureOutlivesSubject::Ty(ty) => {
debug!(
"apply_requirements: ty={:?} \
outlived_region={:?} \
outlives_requirement={:?}",
ty, outlived_region, outlives_requirement,
);
(
ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)),
ConstraintCategory::BoringNoLocation,
)
}
}
})
.collect()
}
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct BlameConstraint<'tcx> { pub struct BlameConstraint<'tcx> {
pub category: ConstraintCategory<'tcx>, pub category: ConstraintCategory<'tcx>,

View file

@ -1,10 +1,10 @@
use rustc_infer::infer::canonical::QueryOutlivesConstraint; use rustc_hir::def_id::DefId;
use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::outlives::env::RegionBoundPairs;
use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
use rustc_middle::mir::ConstraintCategory; use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
@ -38,6 +38,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
locations: Locations, locations: Locations,
span: Span, span: Span,
category: ConstraintCategory<'tcx>, category: ConstraintCategory<'tcx>,
from_closure: bool,
constraints: &'a mut MirTypeckRegionConstraints<'tcx>, constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
} }
@ -64,6 +65,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
span, span,
category, category,
constraints, constraints,
from_closure: false,
} }
} }
@ -81,12 +83,62 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
} }
self.constraints.member_constraints = tmp; self.constraints.member_constraints = tmp;
for query_constraint in outlives { for (predicate, constraint_category) in outlives {
self.convert(query_constraint); // At the moment, we never generate any "higher-ranked"
// region constraints like `for<'a> 'a: 'b`. At some point
// when we move to universes, we will, and this assertion
// will start to fail.
let predicate = predicate.no_bound_vars().unwrap_or_else(|| {
bug!("query_constraint {:?} contained bound vars", predicate,);
});
self.convert(predicate, *constraint_category);
} }
} }
fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) { /// Given an instance of the closure type, this method instantiates the "extra" requirements
/// that we computed for the closure. This has the effect of adding new outlives obligations
/// to existing region variables in `closure_substs`.
#[instrument(skip(self), level = "debug")]
pub fn apply_closure_requirements(
&mut self,
closure_requirements: &ClosureRegionRequirements<'tcx>,
closure_def_id: DefId,
closure_substs: ty::SubstsRef<'tcx>,
) {
// Extract the values of the free regions in `closure_substs`
// into a vector. These are the regions that we will be
// relating to one another.
let closure_mapping = &UniversalRegions::closure_mapping(
self.tcx,
closure_substs,
closure_requirements.num_external_vids,
closure_def_id.expect_local(),
);
debug!(?closure_mapping);
// Create the predicates.
let backup = (self.category, self.span, self.from_closure);
self.from_closure = true;
for outlives_requirement in &closure_requirements.outlives_requirements {
let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
let subject = match outlives_requirement.subject {
ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
ClosureOutlivesSubject::Ty(ty) => ty.into(),
};
self.category = outlives_requirement.category;
self.span = outlives_requirement.blame_span;
self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category);
}
(self.category, self.span, self.from_closure) = backup;
}
fn convert(
&mut self,
predicate: ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>,
constraint_category: ConstraintCategory<'tcx>,
) {
debug!("generate: constraints at: {:#?}", self.locations); debug!("generate: constraints at: {:#?}", self.locations);
// Extract out various useful fields we'll need below. // Extract out various useful fields we'll need below.
@ -94,17 +146,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
tcx, region_bound_pairs, implicit_region_bound, param_env, .. tcx, region_bound_pairs, implicit_region_bound, param_env, ..
} = *self; } = *self;
// At the moment, we never generate any "higher-ranked" let ty::OutlivesPredicate(k1, r2) = predicate;
// region constraints like `for<'a> 'a: 'b`. At some point
// when we move to universes, we will, and this assertion
// will start to fail.
let ty::OutlivesPredicate(k1, r2) =
query_constraint.0.no_bound_vars().unwrap_or_else(|| {
bug!("query_constraint {:?} contained bound vars", query_constraint,);
});
let constraint_category = query_constraint.1;
match k1.unpack() { match k1.unpack() {
GenericArgKind::Lifetime(r1) => { GenericArgKind::Lifetime(r1) => {
let r1_vid = self.to_region_vid(r1); let r1_vid = self.to_region_vid(r1);
@ -127,10 +169,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
.type_must_outlive(origin, t1, r2, constraint_category); .type_must_outlive(origin, t1, r2, constraint_category);
} }
GenericArgKind::Const(_) => { GenericArgKind::Const(_) => unreachable!(),
// Consts cannot outlive one another, so we
// don't need to handle any relations here.
}
} }
} }
@ -160,7 +199,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
verify_bound: VerifyBound<'tcx>, verify_bound: VerifyBound<'tcx>,
) -> TypeTest<'tcx> { ) -> TypeTest<'tcx> {
let lower_bound = self.to_region_vid(region); let lower_bound = self.to_region_vid(region);
TypeTest { generic_kind, lower_bound, locations: self.locations, verify_bound } TypeTest { generic_kind, lower_bound, span: self.span, verify_bound }
} }
fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid { fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
@ -188,6 +227,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
sub, sub,
sup, sup,
variance_info: ty::VarianceDiagInfo::default(), variance_info: ty::VarianceDiagInfo::default(),
from_closure: self.from_closure,
}); });
} }

View file

@ -27,7 +27,7 @@ use rustc_middle::mir::AssertKind;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts}; use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic, self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
@ -61,7 +61,7 @@ use crate::{
region_infer::values::{ region_infer::values::{
LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements, LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
}, },
region_infer::{ClosureRegionRequirementsExt, TypeTest}, region_infer::TypeTest,
type_check::free_region_relations::{CreateResult, UniversalRegionRelations}, type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
universal_regions::{DefiningTy, UniversalRegions}, universal_regions::{DefiningTy, UniversalRegions},
Upvar, Upvar,
@ -144,7 +144,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
liveness_constraints: LivenessValues::new(elements.clone()), liveness_constraints: LivenessValues::new(elements.clone()),
outlives_constraints: OutlivesConstraintSet::default(), outlives_constraints: OutlivesConstraintSet::default(),
member_constraints: MemberConstraintSet::default(), member_constraints: MemberConstraintSet::default(),
closure_bounds_mapping: Default::default(),
type_tests: Vec::default(), type_tests: Vec::default(),
universe_causes: FxHashMap::default(), universe_causes: FxHashMap::default(),
}; };
@ -584,8 +583,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
// modify their locations. // modify their locations.
let all_facts = &mut None; let all_facts = &mut None;
let mut constraints = Default::default(); let mut constraints = Default::default();
let mut type_tests = Default::default();
let mut closure_bounds = Default::default();
let mut liveness_constraints = let mut liveness_constraints =
LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body))); LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body)));
// Don't try to add borrow_region facts for the promoted MIR // Don't try to add borrow_region facts for the promoted MIR
@ -596,11 +593,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
&mut this.cx.borrowck_context.constraints.outlives_constraints, &mut this.cx.borrowck_context.constraints.outlives_constraints,
&mut constraints, &mut constraints,
); );
mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests);
mem::swap(
&mut this.cx.borrowck_context.constraints.closure_bounds_mapping,
&mut closure_bounds,
);
mem::swap( mem::swap(
&mut this.cx.borrowck_context.constraints.liveness_constraints, &mut this.cx.borrowck_context.constraints.liveness_constraints,
&mut liveness_constraints, &mut liveness_constraints,
@ -621,13 +613,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
swap_constraints(self); swap_constraints(self);
let locations = location.to_locations(); let locations = location.to_locations();
// Use location of promoted const in collected constraints
for type_test in type_tests.iter() {
let mut type_test = type_test.clone();
type_test.locations = locations;
self.cx.borrowck_context.constraints.type_tests.push(type_test)
}
for constraint in constraints.outlives().iter() { for constraint in constraints.outlives().iter() {
let mut constraint = constraint.clone(); let mut constraint = constraint.clone();
constraint.locations = locations; constraint.locations = locations;
@ -653,18 +638,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
.add_element(region, location); .add_element(region, location);
} }
} }
if !closure_bounds.is_empty() {
let combined_bounds_mapping =
closure_bounds.into_iter().flat_map(|(_, value)| value).collect();
let existing = self
.cx
.borrowck_context
.constraints
.closure_bounds_mapping
.insert(location, combined_bounds_mapping);
assert!(existing.is_none(), "Multiple promoteds/closures at the same location.");
}
} }
fn sanitize_projection( fn sanitize_projection(
@ -941,9 +914,6 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>, pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
pub(crate) closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>, pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
pub(crate) type_tests: Vec<TypeTest<'tcx>>, pub(crate) type_tests: Vec<TypeTest<'tcx>>,
@ -2562,6 +2532,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
span: location.to_locations().span(body), span: location.to_locations().span(body),
category, category,
variance_info: ty::VarianceDiagInfo::default(), variance_info: ty::VarianceDiagInfo::default(),
from_closure: false,
}); });
match mutbl { match mutbl {
@ -2679,62 +2650,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
substs: SubstsRef<'tcx>, substs: SubstsRef<'tcx>,
location: Location, location: Location,
) -> ty::InstantiatedPredicates<'tcx> { ) -> ty::InstantiatedPredicates<'tcx> {
if let Some(ref closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements if let Some(ref closure_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
{ constraint_conversion::ConstraintConversion::new(
let closure_constraints = QueryRegionConstraints { self.infcx,
outlives: closure_region_requirements.apply_requirements( self.borrowck_context.universal_regions,
tcx, self.region_bound_pairs,
def_id.to_def_id(), self.implicit_region_bound,
substs, self.param_env,
),
// Presently, closures never propagate member
// constraints to their parents -- they are enforced
// locally. This is largely a non-issue as member
// constraints only come from `-> impl Trait` and
// friends which don't appear (thus far...) in
// closures.
member_constraints: vec![],
};
let bounds_mapping = closure_constraints
.outlives
.iter()
.enumerate()
.filter_map(|(idx, constraint)| {
let ty::OutlivesPredicate(k1, r2) =
constraint.0.no_bound_vars().unwrap_or_else(|| {
bug!("query_constraint {:?} contained bound vars", constraint,);
});
match k1.unpack() {
GenericArgKind::Lifetime(r1) => {
// constraint is r1: r2
let r1_vid = self.borrowck_context.universal_regions.to_region_vid(r1);
let r2_vid = self.borrowck_context.universal_regions.to_region_vid(r2);
let outlives_requirements =
&closure_region_requirements.outlives_requirements[idx];
Some((
(r1_vid, r2_vid),
(outlives_requirements.category, outlives_requirements.blame_span),
))
}
GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
}
})
.collect();
let existing = self
.borrowck_context
.constraints
.closure_bounds_mapping
.insert(location, bounds_mapping);
assert!(existing.is_none(), "Multiple closures at the same location.");
self.push_region_constraints(
location.to_locations(), location.to_locations(),
ConstraintCategory::ClosureBounds, DUMMY_SP, // irrelevant; will be overrided.
&closure_constraints, ConstraintCategory::Boring, // same as above.
&mut self.borrowck_context.constraints,
)
.apply_closure_requirements(
&closure_requirements,
def_id.to_def_id(),
substs,
); );
} }

View file

@ -136,6 +136,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
span: self.locations.span(self.type_checker.body), span: self.locations.span(self.type_checker.body),
category: self.category, category: self.category,
variance_info: info, variance_info: info,
from_closure: false,
}, },
); );
} }

View file

@ -14,11 +14,11 @@ pub struct VTable {
impl VTable { impl VTable {
pub fn new<T>() -> &'static Self { pub fn new<T>() -> &'static Self {
const { const {
//~^ ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
&VTable { &VTable {
layout: Layout::new::<T>(), layout: Layout::new::<T>(),
type_id: TypeId::of::<T>(), type_id: TypeId::of::<T>(),
//~^ ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
drop_in_place: unsafe { drop_in_place: unsafe {
transmute::<unsafe fn(*mut T), unsafe fn(*mut ())>(drop_in_place::<T>) transmute::<unsafe fn(*mut T), unsafe fn(*mut ())>(drop_in_place::<T>)
}, },

View file

@ -1,14 +1,8 @@
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/issue-102117.rs:16:9 --> $DIR/issue-102117.rs:19:26
| |
LL | / const { LL | type_id: TypeId::of::<T>(),
LL | | | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
LL | |
LL | | &VTable {
... |
LL | | }
LL | | }
| |_________^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |
@ -16,16 +10,10 @@ LL | pub fn new<T: 'static>() -> &'static Self {
| +++++++++ | +++++++++
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/issue-102117.rs:16:9 --> $DIR/issue-102117.rs:19:26
| |
LL | / const { LL | type_id: TypeId::of::<T>(),
LL | | | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
LL | |
LL | | &VTable {
... |
LL | | }
LL | | }
| |_________^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |

View file

@ -21,6 +21,7 @@ fn foo<T>() {
//~| ERROR `T` does not live long enough //~| ERROR `T` does not live long enough
//~| ERROR `T` does not live long enough //~| ERROR `T` does not live long enough
//~| ERROR `T` may not live long enough //~| ERROR `T` may not live long enough
//~| ERROR `T` may not live long enough
// //
// FIXME: This error is bogus, but it arises because we try to validate // FIXME: This error is bogus, but it arises because we try to validate
// that `<() as Foo<T>>::Type<'a>` is valid, which requires proving // that `<() as Foo<T>>::Type<'a>` is valid, which requires proving

View file

@ -22,6 +22,17 @@ error: `T` does not live long enough
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/issue-91139.rs:14:58
|
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
| ^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn foo<T: 'static>() {
| +++++++++
error: `T` does not live long enough error: `T` does not live long enough
--> $DIR/issue-91139.rs:14:58 --> $DIR/issue-91139.rs:14:58
| |
@ -57,6 +68,6 @@ error: `T` does not live long enough
LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); LL | let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
| ^^^^^^^^^ | ^^^^^^^^^
error: aborting due to 9 previous errors error: aborting due to 10 previous errors
For more information about this error, try `rustc --explain E0310`. For more information about this error, try `rustc --explain E0310`.

View file

@ -30,8 +30,6 @@ where
T: Trait<'a>, T: Trait<'a>,
{ {
establish_relationships(value, |value| { establish_relationships(value, |value| {
//~^ ERROR the parameter type `T` may not live long enough
// This function call requires that // This function call requires that
// //
// (a) T: Trait<'a> // (a) T: Trait<'a>
@ -43,6 +41,7 @@ where
// The latter does not hold. // The latter does not hold.
require(value); require(value);
//~^ ERROR the parameter type `T` may not live long enough
}); });
} }

View file

@ -23,17 +23,10 @@ LL | | T: Trait<'a>,
= note: defining type: supply::<'_#1r, T> = note: defining type: supply::<'_#1r, T>
error[E0309]: the parameter type `T` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/propagate-from-trait-match.rs:32:36 --> $DIR/propagate-from-trait-match.rs:43:9
| |
LL | establish_relationships(value, |value| { LL | require(value);
| ____________________________________^ | ^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
LL | |
LL | |
LL | | // This function call requires that
... |
LL | | require(value);
LL | | });
| |_____^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |

View file

@ -35,10 +35,10 @@ LL | || { None::<&'a &'b ()>; };
= help: consider adding the following bound: `'b: 'a` = help: consider adding the following bound: `'b: 'a`
error[E0309]: the parameter type `T` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/issue-98589-closures-relate-named-regions.rs:26:5 --> $DIR/issue-98589-closures-relate-named-regions.rs:26:10
| |
LL | || { None::<&'a T>; }; LL | || { None::<&'a T>; };
| ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |
@ -46,10 +46,10 @@ LL | fn test_early_type<'a: 'a, T: 'a>() {
| ++++ | ++++
error[E0309]: the parameter type `T` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/issue-98589-closures-relate-named-regions.rs:32:5 --> $DIR/issue-98589-closures-relate-named-regions.rs:32:10
| |
LL | || { None::<&'a T>; }; LL | || { None::<&'a T>; };
| ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |

View file

@ -13,8 +13,8 @@ where
fn test<T>() { fn test<T>() {
|| { || {
//~^ ERROR the parameter type `T` may not live long enough
assert_static::<T>(); assert_static::<T>();
//~^ ERROR the parameter type `T` may not live long enough
}; };
} }

View file

@ -1,11 +1,8 @@
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/issue-98693.rs:15:5 --> $DIR/issue-98693.rs:16:9
| |
LL | / || { LL | assert_static::<T>();
LL | | | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
LL | | assert_static::<T>();
LL | | };
| |_____^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |

View file

@ -1,8 +1,8 @@
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/projection-implied-bounds.rs:30:18 --> $DIR/projection-implied-bounds.rs:30:36
| |
LL | twice(value, |value_ref, item| invoke2(value_ref, item)); LL | twice(value, |value_ref, item| invoke2(value_ref, item));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | ^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |

View file

@ -23,10 +23,10 @@ LL | | T: Iterator,
= note: defining type: no_region::<'_#1r, T> = note: defining type: no_region::<'_#1r, T>
error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough
--> $DIR/projection-no-regions-closure.rs:25:23 --> $DIR/projection-no-regions-closure.rs:25:31
| |
LL | with_signature(x, |mut y| Box::new(y.next())) LL | with_signature(x, |mut y| Box::new(y.next()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
| |
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`... = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
= note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
@ -80,10 +80,10 @@ LL | | T: 'b + Iterator,
= note: defining type: wrong_region::<'_#1r, '_#2r, T> = note: defining type: wrong_region::<'_#1r, '_#2r, T>
error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough
--> $DIR/projection-no-regions-closure.rs:42:23 --> $DIR/projection-no-regions-closure.rs:42:31
| |
LL | with_signature(x, |mut y| Box::new(y.next())) LL | with_signature(x, |mut y| Box::new(y.next()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
| |
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`... = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
= note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds

View file

@ -25,10 +25,10 @@ LL | | T: Anything<'b>,
= note: defining type: no_relationships_late::<'_#1r, T> = note: defining type: no_relationships_late::<'_#1r, T>
error[E0309]: the parameter type `T` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/projection-one-region-closure.rs:45:29 --> $DIR/projection-one-region-closure.rs:45:39
| |
LL | with_signature(cell, t, |cell, t| require(cell, t)); LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |
@ -75,10 +75,10 @@ LL | | 'a: 'a,
= note: defining type: no_relationships_early::<'_#1r, '_#2r, T> = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>
error[E0309]: the parameter type `T` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/projection-one-region-closure.rs:56:29 --> $DIR/projection-one-region-closure.rs:56:39
| |
LL | with_signature(cell, t, |cell, t| require(cell, t)); LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |

View file

@ -24,10 +24,10 @@ LL | | T: Anything<'b, 'c>,
= note: defining type: no_relationships_late::<'_#1r, '_#2r, T> = note: defining type: no_relationships_late::<'_#1r, '_#2r, T>
error[E0309]: the associated type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` may not live long enough error[E0309]: the associated type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` may not live long enough
--> $DIR/projection-two-region-trait-bound-closure.rs:38:29 --> $DIR/projection-two-region-trait-bound-closure.rs:38:39
| |
LL | with_signature(cell, t, |cell, t| require(cell, t)); LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
| |
= help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType: 'a`... = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType: 'a`...
= note: ...so that the type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` will meet its required lifetime bounds = note: ...so that the type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` will meet its required lifetime bounds
@ -58,10 +58,10 @@ LL | | 'a: 'a,
= note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T> = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T>
error[E0309]: the associated type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` may not live long enough error[E0309]: the associated type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` may not live long enough
--> $DIR/projection-two-region-trait-bound-closure.rs:48:29 --> $DIR/projection-two-region-trait-bound-closure.rs:48:39
| |
LL | with_signature(cell, t, |cell, t| require(cell, t)); LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
| |
= help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: 'a`... = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: 'a`...
= note: ...so that the type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` will meet its required lifetime bounds = note: ...so that the type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` will meet its required lifetime bounds
@ -167,7 +167,7 @@ LL | | T: Anything<'b, 'b>,
= note: defining type: two_regions::<'_#1r, T> = note: defining type: two_regions::<'_#1r, T>
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/projection-two-region-trait-bound-closure.rs:87:29 --> $DIR/projection-two-region-trait-bound-closure.rs:87:5
| |
LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
@ -175,9 +175,12 @@ LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
| lifetime `'a` defined here | lifetime `'a` defined here
... ...
LL | with_signature(cell, t, |cell, t| require(cell, t)); LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
| |
= help: consider adding the following bound: `'b: 'a` = help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of the type `Cell<&'_#8r ()>`, which makes the generic argument `&'_#8r ()` invariant
= note: the struct `Cell<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
note: external requirements note: external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:97:29 --> $DIR/projection-two-region-trait-bound-closure.rs:97:29

View file

@ -44,10 +44,10 @@ LL | fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
= note: defining type: generic_fail::<T> = note: defining type: generic_fail::<T>
error[E0309]: the parameter type `T` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24 --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:31
| |
LL | twice(cell, value, |a, b| invoke(a, b)); LL | twice(cell, value, |a, b| invoke(a, b));
| ^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |

View file

@ -23,10 +23,10 @@ LL | | T: Debug,
= note: defining type: no_region::<'_#1r, T> = note: defining type: no_region::<'_#1r, T>
error[E0309]: the parameter type `T` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23 --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:27
| |
LL | with_signature(x, |y| y) LL | with_signature(x, |y| y)
| ^^^^^ ...so that the type `T` will meet its required lifetime bounds | ^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |

View file

@ -25,13 +25,12 @@ where
#[rustc_regions] #[rustc_regions]
fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
with_signature(a, b, |x, y| { with_signature(a, b, |x, y| {
//~^ ERROR the parameter type `T` may not live long enough
//
// See `correct_region`, which explains the point of this // See `correct_region`, which explains the point of this
// test. The only difference is that, in the case of this // test. The only difference is that, in the case of this
// function, there is no where clause *anywhere*, and hence we // function, there is no where clause *anywhere*, and hence we
// get an error (but reported by the closure creator). // get an error (but reported by the closure creator).
require(&x, &y) require(&x, &y)
//~^ ERROR the parameter type `T` may not live long enough
}) })
} }
@ -62,9 +61,9 @@ where
T: 'b, T: 'b,
{ {
with_signature(a, b, |x, y| { with_signature(a, b, |x, y| {
//~^ ERROR the parameter type `T` may not live long enough
// See `correct_region` // See `correct_region`
require(&x, &y) require(&x, &y)
//~^ ERROR the parameter type `T` may not live long enough
}) })
} }

View file

@ -22,17 +22,10 @@ LL | fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
= note: defining type: no_region::<T> = note: defining type: no_region::<T>
error[E0309]: the parameter type `T` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26 --> $DIR/ty-param-closure-outlives-from-where-clause.rs:32:9
| |
LL | with_signature(a, b, |x, y| { LL | require(&x, &y)
| __________________________^ | ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
LL | |
LL | | //
LL | | // See `correct_region`, which explains the point of this
... |
LL | | require(&x, &y)
LL | | })
| |_____^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |
@ -40,7 +33,7 @@ LL | fn no_region<'a, T: 'a>(a: Cell<&'a ()>, b: T) {
| ++++ | ++++
note: external requirements note: external requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26 --> $DIR/ty-param-closure-outlives-from-where-clause.rs:42:26
| |
LL | with_signature(a, b, |x, y| { LL | with_signature(a, b, |x, y| {
| ^^^^^^ | ^^^^^^
@ -54,7 +47,7 @@ LL | with_signature(a, b, |x, y| {
= note: where T: '_#2r = note: where T: '_#2r
note: no external requirements note: no external requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:39:1 --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:1
| |
LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T) LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T)
LL | | where LL | | where
@ -64,7 +57,7 @@ LL | | T: 'a,
= note: defining type: correct_region::<'_#1r, T> = note: defining type: correct_region::<'_#1r, T>
note: external requirements note: external requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26 --> $DIR/ty-param-closure-outlives-from-where-clause.rs:63:26
| |
LL | with_signature(a, b, |x, y| { LL | with_signature(a, b, |x, y| {
| ^^^^^^ | ^^^^^^
@ -79,7 +72,7 @@ LL | with_signature(a, b, |x, y| {
= note: where T: '_#2r = note: where T: '_#2r
note: no external requirements note: no external requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:60:1 --> $DIR/ty-param-closure-outlives-from-where-clause.rs:59:1
| |
LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
LL | | where LL | | where
@ -89,15 +82,10 @@ LL | | T: 'b,
= note: defining type: wrong_region::<'_#1r, T> = note: defining type: wrong_region::<'_#1r, T>
error[E0309]: the parameter type `T` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26 --> $DIR/ty-param-closure-outlives-from-where-clause.rs:65:9
| |
LL | with_signature(a, b, |x, y| { LL | require(&x, &y)
| __________________________^ | ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
LL | |
LL | | // See `correct_region`
LL | | require(&x, &y)
LL | | })
| |_____^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |
@ -105,7 +93,7 @@ LL | T: 'b + 'a,
| ++++ | ++++
note: external requirements note: external requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26 --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26
| |
LL | with_signature(a, b, |x, y| { LL | with_signature(a, b, |x, y| {
| ^^^^^^ | ^^^^^^
@ -119,7 +107,7 @@ LL | with_signature(a, b, |x, y| {
= note: where T: '_#3r = note: where T: '_#3r
note: no external requirements note: no external requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1 --> $DIR/ty-param-closure-outlives-from-where-clause.rs:71:1
| |
LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
LL | | where LL | | where