1
Fork 0

Auto merge of #89229 - oli-obk:i_love_inferctxt, r=jackh726

Remove redundant member-constraint check

impl trait will, for each lifetime in the hidden type, register a "member constraint" that says the lifetime must be equal or outlive one of the lifetimes of the impl trait. These member constraints will be solved by borrowck

But, as you can see in the big red block of removed code, there was an ad-hoc check for member constraints happening at the site where they get registered. This check had some minor effects on diagnostics, but will fall down on its feet with my big type alias impl trait refactor. So we removed it and I pulled the removal out into a (hopefully) reviewable PR that works on master directly.
This commit is contained in:
bors 2021-10-18 23:02:53 +00:00
commit ec724ac075
38 changed files with 277 additions and 708 deletions

View file

@ -689,6 +689,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// them down. // them down.
let mut choice_regions: Vec<ty::RegionVid> = choice_regions.to_vec(); let mut choice_regions: Vec<ty::RegionVid> = choice_regions.to_vec();
// Convert to the SCC representative: sometimes we have inference
// variables in the member constraint that wind up equated with
// universal regions. The scc representative is the minimal numbered
// one from the corresponding scc so it will be the universal region
// if one exists.
for c_r in &mut choice_regions {
let scc = self.constraint_sccs.scc(*c_r);
*c_r = self.scc_representatives[scc];
}
// The 'member region' in a member constraint is part of the // The 'member region' in a member constraint is part of the
// hidden type, which must be in the root universe. Therefore, // hidden type, which must be in the root universe. Therefore,
// it cannot have any placeholders in its value. // it cannot have any placeholders in its value.

View file

@ -1,20 +1,18 @@
use rustc_data_structures::frozen::Frozen; use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::transitive_relation::TransitiveRelation; use rustc_data_structures::transitive_relation::TransitiveRelation;
use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_infer::infer::free_regions::FreeRegionRelations;
use rustc_infer::infer::outlives; use rustc_infer::infer::outlives;
use rustc_infer::infer::region_constraints::GenericKind; use rustc_infer::infer::region_constraints::GenericKind;
use rustc_infer::infer::InferCtxt; use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::ConstraintCategory; use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::query::OutlivesBound; use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt}; use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use std::rc::Rc; use std::rc::Rc;
use type_op::TypeOpOutput; use type_op::TypeOpOutput;
use crate::{ use crate::{
nll::ToRegionVid,
type_check::constraint_conversion, type_check::constraint_conversion,
type_check::{Locations, MirTypeckRegionConstraints}, type_check::{Locations, MirTypeckRegionConstraints},
universal_regions::UniversalRegions, universal_regions::UniversalRegions,
@ -383,21 +381,3 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
} }
} }
} }
/// This trait is used by the `impl-trait` constraint code to abstract
/// over the `FreeRegionMap` from lexical regions and
/// `UniversalRegions` (from NLL)`.
impl<'tcx> FreeRegionRelations<'tcx> for UniversalRegionRelations<'tcx> {
fn sub_free_regions(
&self,
_tcx: TyCtxt<'tcx>,
shorter: ty::Region<'tcx>,
longer: ty::Region<'tcx>,
) -> bool {
let shorter = shorter.to_region_vid();
assert!(self.universal_regions.is_universal_region(shorter));
let longer = longer.to_region_vid();
assert!(self.universal_regions.is_universal_region(longer));
self.outlives(longer, shorter)
}
}

View file

@ -36,7 +36,7 @@ use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::VariantIdx; use rustc_target::abi::VariantIdx;
use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::opaque_types::{GenerateMemberConstraints, InferCtxtExt}; use rustc_trait_selection::opaque_types::InferCtxtExt;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
use rustc_trait_selection::traits::query::type_op; use rustc_trait_selection::traits::query::type_op;
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
@ -185,7 +185,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
&region_bound_pairs, &region_bound_pairs,
implicit_region_bound, implicit_region_bound,
&mut borrowck_context, &mut borrowck_context,
&universal_region_relations,
|mut cx| { |mut cx| {
cx.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output); cx.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table); liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table);
@ -253,15 +252,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
} }
#[instrument( #[instrument(
skip( skip(infcx, body, promoted, region_bound_pairs, borrowck_context, extra),
infcx,
body,
promoted,
region_bound_pairs,
borrowck_context,
universal_region_relations,
extra
),
level = "debug" level = "debug"
)] )]
fn type_check_internal<'a, 'tcx, R>( fn type_check_internal<'a, 'tcx, R>(
@ -272,7 +263,6 @@ fn type_check_internal<'a, 'tcx, R>(
region_bound_pairs: &'a RegionBoundPairs<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: ty::Region<'tcx>, implicit_region_bound: ty::Region<'tcx>,
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
universal_region_relations: &'a UniversalRegionRelations<'tcx>,
extra: impl FnOnce(TypeChecker<'a, 'tcx>) -> R, extra: impl FnOnce(TypeChecker<'a, 'tcx>) -> R,
) -> R { ) -> R {
let mut checker = TypeChecker::new( let mut checker = TypeChecker::new(
@ -282,7 +272,6 @@ fn type_check_internal<'a, 'tcx, R>(
region_bound_pairs, region_bound_pairs,
implicit_region_bound, implicit_region_bound,
borrowck_context, borrowck_context,
universal_region_relations,
); );
let errors_reported = { let errors_reported = {
let mut verifier = TypeVerifier::new(&mut checker, body, promoted); let mut verifier = TypeVerifier::new(&mut checker, body, promoted);
@ -901,7 +890,6 @@ struct TypeChecker<'a, 'tcx> {
implicit_region_bound: ty::Region<'tcx>, implicit_region_bound: ty::Region<'tcx>,
reported_errors: FxHashSet<(Ty<'tcx>, Span)>, reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
universal_region_relations: &'a UniversalRegionRelations<'tcx>,
} }
struct BorrowCheckContext<'a, 'tcx> { struct BorrowCheckContext<'a, 'tcx> {
@ -1050,7 +1038,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
region_bound_pairs: &'a RegionBoundPairs<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: ty::Region<'tcx>, implicit_region_bound: ty::Region<'tcx>,
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
universal_region_relations: &'a UniversalRegionRelations<'tcx>,
) -> Self { ) -> Self {
let mut checker = Self { let mut checker = Self {
infcx, infcx,
@ -1062,7 +1049,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
implicit_region_bound, implicit_region_bound,
borrowck_context, borrowck_context,
reported_errors: Default::default(), reported_errors: Default::default(),
universal_region_relations,
}; };
checker.check_user_type_annotations(); checker.check_user_type_annotations();
checker checker
@ -1322,8 +1308,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
), ),
)?; )?;
let universal_region_relations = self.universal_region_relations;
// Finally, if we instantiated the anon types successfully, we // Finally, if we instantiated the anon types successfully, we
// have to solve any bounds (e.g., `-> impl Iterator` needs to // have to solve any bounds (e.g., `-> impl Iterator` needs to
// prove that `T: Iterator` where `T` is the type we // prove that `T: Iterator` where `T` is the type we
@ -1335,12 +1319,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ConstraintCategory::OpaqueType, ConstraintCategory::OpaqueType,
CustomTypeOp::new( CustomTypeOp::new(
|infcx| { |infcx| {
infcx.constrain_opaque_type( infcx.constrain_opaque_type(opaque_type_key, &opaque_decl);
opaque_type_key,
&opaque_decl,
GenerateMemberConstraints::IfNoStaticBound,
universal_region_relations,
);
Ok(InferOk { value: (), obligations: vec![] }) Ok(InferOk { value: (), obligations: vec![] })
}, },
|| "opaque_type_map".to_string(), || "opaque_type_map".to_string(),

View file

@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.
A lifetime of a returned value does not outlive the function call. A lifetime of a returned value does not outlive the function call.
Erroneous code example: Erroneous code example:
```compile_fail,E0482 ```compile_fail,E0700
fn prefix<'a>( fn prefix<'a>(
words: impl Iterator<Item = &'a str> words: impl Iterator<Item = &'a str>
) -> impl Iterator<Item = String> { // error! ) -> impl Iterator<Item = String> { // error!
@ -41,7 +43,7 @@ fn prefix(
A similar lifetime problem might arise when returning closures: A similar lifetime problem might arise when returning closures:
```compile_fail,E0482 ```compile_fail,E0700
fn foo( fn foo(
x: &mut Vec<i32> x: &mut Vec<i32>
) -> impl FnMut(&mut Vec<i32>) -> &[i32] { // error! ) -> impl FnMut(&mut Vec<i32>) -> &[i32] { // error!

View file

@ -386,21 +386,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit(); self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
} }
RegionResolutionError::MemberConstraintFailure {
hidden_ty,
member_region,
span,
} => {
let hidden_ty = self.resolve_vars_if_possible(hidden_ty);
unexpected_hidden_region_diagnostic(
self.tcx,
span,
hidden_ty,
member_region,
)
.emit();
}
} }
} }
} }
@ -438,8 +423,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
RegionResolutionError::GenericBoundFailure(..) => true, RegionResolutionError::GenericBoundFailure(..) => true,
RegionResolutionError::ConcreteFailure(..) RegionResolutionError::ConcreteFailure(..)
| RegionResolutionError::SubSupConflict(..) | RegionResolutionError::SubSupConflict(..)
| RegionResolutionError::UpperBoundUniverseConflict(..) | RegionResolutionError::UpperBoundUniverseConflict(..) => false,
| RegionResolutionError::MemberConstraintFailure { .. } => false,
}; };
let mut errors = if errors.iter().all(|e| is_bound_failure(e)) { let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
@ -454,7 +438,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(), RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(), RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(),
RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(), RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(),
RegionResolutionError::MemberConstraintFailure { span, .. } => span,
}); });
errors errors
} }

View file

@ -53,9 +53,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
infer::RelateObjectBound(span) => { infer::RelateObjectBound(span) => {
label_or_note(span, "...so that it can be closed over into an object"); label_or_note(span, "...so that it can be closed over into an object");
} }
infer::CallReturn(span) => {
label_or_note(span, "...so that return value is valid for the call");
}
infer::DataBorrowed(ty, span) => { infer::DataBorrowed(ty, span) => {
label_or_note( label_or_note(
span, span,
@ -281,23 +278,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
); );
err err
} }
infer::CallReturn(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0482,
"lifetime of return value does not outlive the function call"
);
note_and_explain_region(
self.tcx,
&mut err,
"the return value is only valid for ",
sup,
"",
None,
);
err
}
infer::DataBorrowed(ty, span) => { infer::DataBorrowed(ty, span) => {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self.tcx.sess, self.tcx.sess,

View file

@ -66,8 +66,6 @@ impl<'tcx> FreeRegionMap<'tcx> {
/// follows. If we know that `r_b: 'static`, then this function /// follows. If we know that `r_b: 'static`, then this function
/// will return true, even though we don't know anything that /// will return true, even though we don't know anything that
/// directly relates `r_a` and `r_b`. /// directly relates `r_a` and `r_b`.
///
/// Also available through the `FreeRegionRelations` trait below.
pub fn sub_free_regions( pub fn sub_free_regions(
&self, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
@ -131,27 +129,6 @@ impl<'tcx> FreeRegionMap<'tcx> {
} }
} }
/// The NLL region handling code represents free region relations in a
/// slightly different way; this trait allows functions to be abstract
/// over which version is in use.
pub trait FreeRegionRelations<'tcx> {
/// Tests whether `r_a <= r_b`. Both must be free regions or
/// `'static`.
fn sub_free_regions(
&self,
tcx: TyCtxt<'tcx>,
shorter: ty::Region<'tcx>,
longer: ty::Region<'tcx>,
) -> bool;
}
impl<'tcx> FreeRegionRelations<'tcx> for FreeRegionMap<'tcx> {
fn sub_free_regions(&self, tcx: TyCtxt<'tcx>, r_a: Region<'tcx>, r_b: Region<'tcx>) -> bool {
// invoke the "inherent method"
self.sub_free_regions(tcx, r_a, r_b)
}
}
impl<'a, 'tcx> Lift<'tcx> for FreeRegionMap<'a> { impl<'a, 'tcx> Lift<'tcx> for FreeRegionMap<'a> {
type Lifted = FreeRegionMap<'tcx>; type Lifted = FreeRegionMap<'tcx>;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<FreeRegionMap<'tcx>> { fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<FreeRegionMap<'tcx>> {

View file

@ -2,7 +2,6 @@
use crate::infer::region_constraints::Constraint; use crate::infer::region_constraints::Constraint;
use crate::infer::region_constraints::GenericKind; use crate::infer::region_constraints::GenericKind;
use crate::infer::region_constraints::MemberConstraint;
use crate::infer::region_constraints::RegionConstraintData; use crate::infer::region_constraints::RegionConstraintData;
use crate::infer::region_constraints::VarInfos; use crate::infer::region_constraints::VarInfos;
use crate::infer::region_constraints::VerifyBound; use crate::infer::region_constraints::VerifyBound;
@ -20,7 +19,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic}; use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar}; use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar};
use rustc_middle::ty::{Region, RegionVid}; use rustc_middle::ty::{Region, RegionVid};
use rustc_span::Span;
use std::fmt; use std::fmt;
/// This function performs lexical region resolution given a complete /// This function performs lexical region resolution given a complete
@ -28,13 +26,13 @@ use std::fmt;
/// iteration to find region values which satisfy all constraints, /// iteration to find region values which satisfy all constraints,
/// assuming such values can be found. It returns the final values of /// assuming such values can be found. It returns the final values of
/// all the variables as well as a set of errors that must be reported. /// all the variables as well as a set of errors that must be reported.
#[instrument(level = "debug", skip(region_rels, var_infos, data))]
pub fn resolve<'tcx>( pub fn resolve<'tcx>(
region_rels: &RegionRelations<'_, 'tcx>, region_rels: &RegionRelations<'_, 'tcx>,
var_infos: VarInfos, var_infos: VarInfos,
data: RegionConstraintData<'tcx>, data: RegionConstraintData<'tcx>,
mode: RegionckMode, mode: RegionckMode,
) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) { ) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
debug!("RegionConstraintData: resolve_regions()");
let mut errors = vec![]; let mut errors = vec![];
let mut resolver = LexicalResolver { region_rels, var_infos, data }; let mut resolver = LexicalResolver { region_rels, var_infos, data };
match mode { match mode {
@ -109,11 +107,6 @@ pub enum RegionResolutionError<'tcx> {
SubregionOrigin<'tcx>, // cause of the constraint SubregionOrigin<'tcx>, // cause of the constraint
Region<'tcx>, // the placeholder `'b` Region<'tcx>, // the placeholder `'b`
), ),
/// Indicates a failure of a `MemberConstraint`. These arise during
/// impl trait processing explicitly -- basically, the impl trait's hidden type
/// included some region that it was not supposed to.
MemberConstraintFailure { span: Span, hidden_ty: Ty<'tcx>, member_region: Region<'tcx> },
} }
struct RegionAndOrigin<'tcx> { struct RegionAndOrigin<'tcx> {
@ -150,12 +143,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
let graph = self.construct_graph(); let graph = self.construct_graph();
self.expand_givens(&graph); self.expand_givens(&graph);
loop { self.expansion(&mut var_data);
self.expansion(&mut var_data);
if !self.enforce_member_constraints(&graph, &mut var_data) {
break;
}
}
self.collect_errors(&mut var_data, errors); self.collect_errors(&mut var_data, errors);
self.collect_var_errors(&var_data, &graph, errors); self.collect_var_errors(&var_data, &graph, errors);
var_data var_data
@ -233,120 +221,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
} }
} }
/// Enforce all member constraints and return true if anything
/// changed. See `enforce_member_constraint` for more details.
fn enforce_member_constraints(
&self,
graph: &RegionGraph<'tcx>,
var_values: &mut LexicalRegionResolutions<'tcx>,
) -> bool {
// Note: we don't use the `any` combinator because we don't
// want to stop at the first constraint that makes a change.
let mut any_changed = false;
for member_constraint in &self.data.member_constraints {
any_changed |= self.enforce_member_constraint(graph, member_constraint, var_values);
}
any_changed
}
/// Enforce a constraint like
///
/// ```
/// 'r member of ['c...]
/// ```
///
/// We look for all choice regions from the list `'c...` that:
///
/// (a) are greater than the current value of `'r` (which is a lower bound)
///
/// and
///
/// (b) are compatible with the upper bounds of `'r` that we can
/// find by traversing the graph.
///
/// From that list, we look for a *minimal* option `'c_min`. If we
/// find one, then we can enforce that `'r: 'c_min`.
fn enforce_member_constraint(
&self,
graph: &RegionGraph<'tcx>,
member_constraint: &MemberConstraint<'tcx>,
var_values: &mut LexicalRegionResolutions<'tcx>,
) -> bool {
debug!("enforce_member_constraint(member_constraint={:#?})", member_constraint);
// The constraint is some inference variable (`vid`) which
// must be equal to one of the options.
let member_vid = match member_constraint.member_region {
ty::ReVar(vid) => *vid,
_ => return false,
};
// The current value of `vid` is a lower bound LB -- i.e., we
// know that `LB <= vid` must be true.
let member_lower_bound: ty::Region<'tcx> = match var_values.value(member_vid) {
VarValue::ErrorValue => return false,
VarValue::Value(r) => r,
};
// Find all the "upper bounds" -- that is, each region `b` such that
// `r0 <= b` must hold.
let (member_upper_bounds, ..) =
self.collect_bounding_regions(graph, member_vid, OUTGOING, None);
// Get an iterator over the *available choice* -- that is,
// each choice region `c` where `lb <= c` and `c <= ub` for all the
// upper bounds `ub`.
debug!("enforce_member_constraint: upper_bounds={:#?}", member_upper_bounds);
let mut options = member_constraint.choice_regions.iter().filter(|option| {
self.sub_concrete_regions(member_lower_bound, option)
&& member_upper_bounds
.iter()
.all(|upper_bound| self.sub_concrete_regions(option, upper_bound.region))
});
// If there is more than one option, we only make a choice if
// there is a single *least* choice -- i.e., some available
// region that is `<=` all the others.
let mut least_choice: ty::Region<'tcx> = match options.next() {
Some(&r) => r,
None => return false,
};
debug!("enforce_member_constraint: least_choice={:?}", least_choice);
for &option in options {
debug!("enforce_member_constraint: option={:?}", option);
if !self.sub_concrete_regions(least_choice, option) {
if self.sub_concrete_regions(option, least_choice) {
debug!("enforce_member_constraint: new least choice");
least_choice = option;
} else {
debug!("enforce_member_constraint: no least choice");
return false;
}
}
}
// (#72087) Different `ty::Regions` can be known to be equal, for
// example, we know that `'a` and `'static` are equal in a function
// with a parameter of type `&'static &'a ()`.
//
// When we have two equal regions like this `expansion` will use
// `lub_concrete_regions` to pick a canonical representative. The same
// choice is needed here so that we don't end up in a cycle of
// `expansion` changing the region one way and the code here changing
// it back.
let lub = self.lub_concrete_regions(least_choice, member_lower_bound);
debug!(
"enforce_member_constraint: final least choice = {:?}\nlub = {:?}",
least_choice, lub
);
if lub != member_lower_bound {
*var_values.value_mut(member_vid) = VarValue::Value(least_choice);
true
} else {
false
}
}
fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) { fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
let mut constraints = IndexVec::from_elem_n(Vec::new(), var_values.values.len()); let mut constraints = IndexVec::from_elem_n(Vec::new(), var_values.values.len());
let mut changes = Vec::new(); let mut changes = Vec::new();
@ -461,6 +335,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
} }
/// True if `a <= b`, but not defined over inference variables. /// True if `a <= b`, but not defined over inference variables.
#[instrument(level = "trace", skip(self))]
fn sub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> bool { fn sub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> bool {
let tcx = self.tcx(); let tcx = self.tcx();
let sub_free_regions = |r1, r2| self.region_rels.free_regions.sub_free_regions(tcx, r1, r2); let sub_free_regions = |r1, r2| self.region_rels.free_regions.sub_free_regions(tcx, r1, r2);
@ -492,6 +367,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
/// ///
/// Neither `a` nor `b` may be an inference variable (hence the /// Neither `a` nor `b` may be an inference variable (hence the
/// term "concrete regions"). /// term "concrete regions").
#[instrument(level = "trace", skip(self))]
fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> { fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
let r = match (a, b) { let r = match (a, b) {
(&ReLateBound(..), _) | (_, &ReLateBound(..)) | (&ReErased, _) | (_, &ReErased) => { (&ReLateBound(..), _) | (_, &ReLateBound(..)) | (&ReErased, _) | (_, &ReErased) => {
@ -562,13 +438,14 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
/// After expansion is complete, go and check upper bounds (i.e., /// After expansion is complete, go and check upper bounds (i.e.,
/// cases where the region cannot grow larger than a fixed point) /// cases where the region cannot grow larger than a fixed point)
/// and check that they are satisfied. /// and check that they are satisfied.
#[instrument(skip(self, var_data, errors))]
fn collect_errors( fn collect_errors(
&self, &self,
var_data: &mut LexicalRegionResolutions<'tcx>, var_data: &mut LexicalRegionResolutions<'tcx>,
errors: &mut Vec<RegionResolutionError<'tcx>>, errors: &mut Vec<RegionResolutionError<'tcx>>,
) { ) {
for (constraint, origin) in &self.data.constraints { for (constraint, origin) in &self.data.constraints {
debug!("collect_errors: constraint={:?} origin={:?}", constraint, origin); debug!(?constraint, ?origin);
match *constraint { match *constraint {
Constraint::RegSubVar(..) | Constraint::VarSubVar(..) => { Constraint::RegSubVar(..) | Constraint::VarSubVar(..) => {
// Expansion will ensure that these constraints hold. Ignore. // Expansion will ensure that these constraints hold. Ignore.
@ -580,7 +457,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
} }
debug!( debug!(
"collect_errors: region error at {:?}: \ "region error at {:?}: \
cannot verify that {:?} <= {:?}", cannot verify that {:?} <= {:?}",
origin, sub, sup origin, sub, sup
); );
@ -606,7 +483,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// collect them later. // collect them later.
if !self.sub_concrete_regions(a_region, b_region) { if !self.sub_concrete_regions(a_region, b_region) {
debug!( debug!(
"collect_errors: region error at {:?}: \ "region error at {:?}: \
cannot verify that {:?}={:?} <= {:?}", cannot verify that {:?}={:?} <= {:?}",
origin, a_vid, a_region, b_region origin, a_vid, a_region, b_region
); );
@ -616,23 +493,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
} }
} }
// Check that all member constraints are satisfied.
for member_constraint in &self.data.member_constraints {
let member_region = var_data.normalize(self.tcx(), member_constraint.member_region);
let choice_regions = member_constraint
.choice_regions
.iter()
.map(|&choice_region| var_data.normalize(self.tcx(), choice_region));
if !choice_regions.clone().any(|choice_region| member_region == choice_region) {
let span = self.tcx().def_span(member_constraint.opaque_type_def_id);
errors.push(RegionResolutionError::MemberConstraintFailure {
span,
hidden_ty: member_constraint.hidden_ty,
member_region,
});
}
}
for verify in &self.data.verifys { for verify in &self.data.verifys {
debug!("collect_errors: verify={:?}", verify); debug!("collect_errors: verify={:?}", verify);
let sub = var_data.normalize(self.tcx(), verify.region); let sub = var_data.normalize(self.tcx(), verify.region);

View file

@ -417,9 +417,6 @@ pub enum SubregionOrigin<'tcx> {
/// (&'a &'b T) where a >= b /// (&'a &'b T) where a >= b
ReferenceOutlivesReferent(Ty<'tcx>, Span), ReferenceOutlivesReferent(Ty<'tcx>, Span),
/// Region in return type of invoked fn must enclose call
CallReturn(Span),
/// Comparing the signature and requirements of an impl method against /// Comparing the signature and requirements of an impl method against
/// the containing trait. /// the containing trait.
CompareImplMethodObligation { CompareImplMethodObligation {
@ -1803,7 +1800,6 @@ impl<'tcx> SubregionOrigin<'tcx> {
ReborrowUpvar(a, _) => a, ReborrowUpvar(a, _) => a,
DataBorrowed(_, a) => a, DataBorrowed(_, a) => a,
ReferenceOutlivesReferent(_, a) => a, ReferenceOutlivesReferent(_, a) => a,
CallReturn(a) => a,
CompareImplMethodObligation { span, .. } => span, CompareImplMethodObligation { span, .. } => span,
CompareImplTypeObligation { span, .. } => span, CompareImplTypeObligation { span, .. } => span,
} }

View file

@ -4,10 +4,9 @@ use rustc_data_structures::sync::Lrc;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
use rustc_infer::infer::free_regions::FreeRegionRelations;
use rustc_infer::infer::opaque_types::OpaqueTypeDecl; use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{self, InferCtxt, InferOk}; use rustc_infer::infer::{InferCtxt, InferOk};
use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst};
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt}; use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt};
@ -15,19 +14,6 @@ use rustc_span::Span;
use std::ops::ControlFlow; use std::ops::ControlFlow;
/// Whether member constraints should be generated for all opaque types
#[derive(Debug)]
pub enum GenerateMemberConstraints {
/// The default, used by typeck
WhenRequired,
/// The borrow checker needs member constraints in any case where we don't
/// have a `'static` bound. This is because the borrow checker has more
/// flexibility in the values of regions. For example, given `f<'a, 'b>`
/// the borrow checker can have an inference variable outlive `'a` and `'b`,
/// but not be equal to `'static`.
IfNoStaticBound,
}
pub trait InferCtxtExt<'tcx> { pub trait InferCtxtExt<'tcx> {
fn instantiate_opaque_types<T: TypeFoldable<'tcx>>( fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
&self, &self,
@ -37,14 +23,12 @@ pub trait InferCtxtExt<'tcx> {
value_span: Span, value_span: Span,
) -> InferOk<'tcx, T>; ) -> InferOk<'tcx, T>;
fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(&self, free_region_relations: &FRR); fn constrain_opaque_types(&self);
fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>( fn constrain_opaque_type(
&self, &self,
opaque_type_key: OpaqueTypeKey<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>,
opaque_defn: &OpaqueTypeDecl<'tcx>, opaque_defn: &OpaqueTypeDecl<'tcx>,
mode: GenerateMemberConstraints,
free_region_relations: &FRR,
); );
/*private*/ /*private*/
@ -270,26 +254,19 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
/// - `opaque_types` -- the map produced by `instantiate_opaque_types` /// - `opaque_types` -- the map produced by `instantiate_opaque_types`
/// - `free_region_relations` -- something that can be used to relate /// - `free_region_relations` -- something that can be used to relate
/// the free regions (`'a`) that appear in the impl trait. /// the free regions (`'a`) that appear in the impl trait.
fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(&self, free_region_relations: &FRR) { fn constrain_opaque_types(&self) {
let opaque_types = self.inner.borrow().opaque_types.clone(); let opaque_types = self.inner.borrow().opaque_types.clone();
for (opaque_type_key, opaque_defn) in opaque_types { for (opaque_type_key, opaque_defn) in opaque_types {
self.constrain_opaque_type( self.constrain_opaque_type(opaque_type_key, &opaque_defn);
opaque_type_key,
&opaque_defn,
GenerateMemberConstraints::WhenRequired,
free_region_relations,
);
} }
} }
/// See `constrain_opaque_types` for documentation. /// See `constrain_opaque_types` for documentation.
#[instrument(level = "debug", skip(self, free_region_relations))] #[instrument(level = "debug", skip(self))]
fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>( fn constrain_opaque_type(
&self, &self,
opaque_type_key: OpaqueTypeKey<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>,
opaque_defn: &OpaqueTypeDecl<'tcx>, opaque_defn: &OpaqueTypeDecl<'tcx>,
mode: GenerateMemberConstraints,
free_region_relations: &FRR,
) { ) {
let def_id = opaque_type_key.def_id; let def_id = opaque_type_key.def_id;
@ -318,118 +295,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
hir::OpaqueTyOrigin::TyAlias => 0, hir::OpaqueTyOrigin::TyAlias => 0,
}; };
let span = tcx.def_span(def_id); // The regions that appear in the hidden type must be equal to
// one of the regions in scope for the opaque type.
// Check if the `impl Trait` bounds include region bounds. self.generate_member_constraint(
// For example, this would be true for: concrete_ty,
// opaque_defn,
// fn foo<'a, 'b, 'c>() -> impl Trait<'c> + 'a + 'b opaque_type_key,
// first_own_region,
// but false for: );
//
// fn foo<'c>() -> impl Trait<'c>
//
// unless `Trait` was declared like:
//
// trait Trait<'c>: 'c
//
// in which case it would be true.
//
// This is used during regionck to decide whether we need to
// impose any additional constraints to ensure that region
// variables in `concrete_ty` wind up being constrained to
// something from `substs` (or, at minimum, things that outlive
// the fn body). (Ultimately, writeback is responsible for this
// check.)
let bounds = tcx.explicit_item_bounds(def_id);
debug!("{:#?}", bounds);
let bounds = bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_type_key.substs));
debug!("{:#?}", bounds);
let opaque_type = tcx.mk_opaque(def_id, opaque_type_key.substs);
let required_region_bounds = required_region_bounds(tcx, opaque_type, bounds);
if !required_region_bounds.is_empty() {
for required_region in required_region_bounds {
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
tcx,
op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
});
}
if let GenerateMemberConstraints::IfNoStaticBound = mode {
self.generate_member_constraint(
concrete_ty,
opaque_defn,
opaque_type_key,
first_own_region,
);
}
return;
}
// There were no `required_region_bounds`,
// so we have to search for a `least_region`.
// Go through all the regions used as arguments to the
// opaque type. These are the parameters to the opaque
// type; so in our example above, `substs` would contain
// `['a]` for the first impl trait and `'b` for the
// second.
let mut least_region = None;
for subst_arg in &opaque_type_key.substs[first_own_region..] {
let subst_region = match subst_arg.unpack() {
GenericArgKind::Lifetime(r) => r,
GenericArgKind::Type(_) | GenericArgKind::Const(_) => continue,
};
// Compute the least upper bound of it with the other regions.
debug!(?least_region);
debug!(?subst_region);
match least_region {
None => least_region = Some(subst_region),
Some(lr) => {
if free_region_relations.sub_free_regions(self.tcx, lr, subst_region) {
// keep the current least region
} else if free_region_relations.sub_free_regions(self.tcx, subst_region, lr) {
// switch to `subst_region`
least_region = Some(subst_region);
} else {
// There are two regions (`lr` and
// `subst_region`) which are not relatable. We
// can't find a best choice. Therefore,
// instead of creating a single bound like
// `'r: 'a` (which is our preferred choice),
// we will create a "in bound" like `'r in
// ['a, 'b, 'c]`, where `'a..'c` are the
// regions that appear in the impl trait.
return self.generate_member_constraint(
concrete_ty,
opaque_defn,
opaque_type_key,
first_own_region,
);
}
}
}
}
let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
debug!(?least_region);
if let GenerateMemberConstraints::IfNoStaticBound = mode {
if least_region != tcx.lifetimes.re_static {
self.generate_member_constraint(
concrete_ty,
opaque_defn,
opaque_type_key,
first_own_region,
);
}
}
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
tcx,
op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
});
} }
/// As a fallback, we sometimes generate an "in constraint". For /// As a fallback, we sometimes generate an "in constraint". For

View file

@ -341,7 +341,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
self.visit_body(body); self.visit_body(body);
self.visit_region_obligations(body_id.hir_id); self.visit_region_obligations(body_id.hir_id);
self.constrain_opaque_types(self.outlives_environment.free_region_map()); self.constrain_opaque_types();
} }
fn visit_region_obligations(&mut self, hir_id: hir::HirId) { fn visit_region_obligations(&mut self, hir_id: hir::HirId) {

View file

@ -1,13 +1,31 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/ret-impl-trait-one.rs:10:65 --> $DIR/ret-impl-trait-one.rs:10:85
|
LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
| ________________________________--__--_______________________________________________^
| | | |
| | | lifetime `'b` defined here
| | lifetime `'a` defined here
LL | |
LL | | (a, b)
LL | | }
| |_^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ret-impl-trait-one.rs:16:65
| |
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
| -- -- ^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a` | -- ^^^^^^^^^^^^^^
| | | | |
| | lifetime `'b` defined here | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
| lifetime `'a` defined here
| |
= help: consider adding the following bound: `'b: 'a` help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound
|
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
| ++++
error: aborting due to previous error error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0700`.

View file

@ -6,9 +6,15 @@
trait Trait<'a> { } trait Trait<'a> { }
impl<T> Trait<'_> for T { } impl<T> Trait<'_> for T { }
// Fails to recognize that both 'a and 'b are mentioned and should thus be accepted
async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
//~^ ERROR lifetime mismatch
(a, b)
}
// Only `'a` permitted in return type, not `'b`. // Only `'a` permitted in return type, not `'b`.
async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
//~^ ERROR lifetime mismatch //~^ ERROR captures lifetime that does not appear in bounds
(a, b) (a, b)
} }

View file

@ -1,13 +1,27 @@
error[E0623]: lifetime mismatch error[E0623]: lifetime mismatch
--> $DIR/ret-impl-trait-one.rs:10:65 --> $DIR/ret-impl-trait-one.rs:10:65
| |
LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
| ------ ^^^^^^^^^^^^^^^^^^^
| | |
| | ...but data from `a` is held across an await point here
| | this `async fn` implicitly returns an `impl Future<Output = impl Trait<'a> + 'b>`
| this parameter and the returned future are declared with different lifetimes...
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ret-impl-trait-one.rs:16:65
|
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
| ------ ^^^^^^^^^^^^^^ | -- ^^^^^^^^^^^^^^
| | | | |
| | ...but data from `b` is held across an await point here | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
| | this `async fn` implicitly returns an `impl Future<Output = impl Trait<'a>>` |
| this parameter and the returned future are declared with different lifetimes... help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound
|
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
| ++++
error: aborting due to previous error error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0623`. Some errors have detailed explanations: E0623, E0700.
For more information about an error, try `rustc --explain E0623`.

View file

@ -1,16 +0,0 @@
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ordinary-bounds-unrelated.rs:16:74
|
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
| -- ^^^^^^^^^^^^^^^^^^
| |
| hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
|
help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound
|
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b
| ++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0700`.

View file

@ -2,13 +2,14 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
--> $DIR/ordinary-bounds-unrelated.rs:16:74 --> $DIR/ordinary-bounds-unrelated.rs:16:74
| |
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
| ^^^^^^^^^^^^^^^^^^ | -- ^^^^^^^^^^^^^^^^^^
| |
| hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
| |
note: hidden type `Ordinary<'_>` captures lifetime smaller than the function body help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound
--> $DIR/ordinary-bounds-unrelated.rs:16:74
| |
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b
| ^^^^^^^^^^^^^^^^^^ | ++++
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,16 +0,0 @@
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ordinary-bounds-unsuited.rs:18:62
|
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
| -- ^^^^^^^^^^^^^^^^^^
| |
| hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
|
help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound
|
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b
| ++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0700`.

View file

@ -2,13 +2,14 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
--> $DIR/ordinary-bounds-unsuited.rs:18:62 --> $DIR/ordinary-bounds-unsuited.rs:18:62
| |
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
| ^^^^^^^^^^^^^^^^^^ | -- ^^^^^^^^^^^^^^^^^^
| |
| hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
| |
note: hidden type `Ordinary<'_>` captures lifetime smaller than the function body help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound
--> $DIR/ordinary-bounds-unsuited.rs:18:62
| |
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b
| ^^^^^^^^^^^^^^^^^^ | ++++
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,31 +1,31 @@
error: lifetime may not live long enough error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/must_outlive_least_region_or_bound.rs:3:23 --> $DIR/must_outlive_least_region_or_bound.rs:3:23
| |
LL | fn elided(x: &i32) -> impl Copy { x } LL | fn elided(x: &i32) -> impl Copy { x }
| - ^^^^^^^^^ opaque type requires that `'1` must outlive `'static` | ---- ^^^^^^^^^
| | | |
| let's call the lifetime of this reference `'1` | hidden type `&i32` captures the anonymous lifetime defined here
| |
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound help: to declare that the `impl Trait` captures '_, you can add an explicit `'_` lifetime bound
| |
LL | fn elided(x: &i32) -> impl Copy + '_ { x } LL | fn elided(x: &i32) -> impl Copy + '_ { x }
| ++++ | ++++
error: lifetime may not live long enough error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/must_outlive_least_region_or_bound.rs:5:32 --> $DIR/must_outlive_least_region_or_bound.rs:6:32
| |
LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
| -- ^^^^^^^^^ opaque type requires that `'a` must outlive `'static` | -- ^^^^^^^^^
| | | |
| lifetime `'a` defined here | hidden type `&'a i32` captures the lifetime `'a` as defined here
| |
help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound help: to declare that the `impl Trait` captures 'a, you can add an explicit `'a` lifetime bound
| |
LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
| ++++ | ++++
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/must_outlive_least_region_or_bound.rs:7:46 --> $DIR/must_outlive_least_region_or_bound.rs:9:46
| |
LL | fn elided2(x: &i32) -> impl Copy + 'static { x } LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
| - ^ returning this value requires that `'1` must outlive `'static` | - ^ returning this value requires that `'1` must outlive `'static`
@ -35,7 +35,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
= help: consider replacing `'1` with `'static` = help: consider replacing `'1` with `'static`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/must_outlive_least_region_or_bound.rs:9:55 --> $DIR/must_outlive_least_region_or_bound.rs:11:55
| |
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
@ -43,7 +43,7 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
= help: consider replacing `'a` with `'static` = help: consider replacing `'a` with `'static`
error[E0621]: explicit lifetime required in the type of `x` error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/must_outlive_least_region_or_bound.rs:11:41 --> $DIR/must_outlive_least_region_or_bound.rs:13:41
| |
LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
| ---- ^ lifetime `'a` required | ---- ^ lifetime `'a` required
@ -51,33 +51,36 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
| help: add explicit lifetime `'a` to the type of `x`: `&'a i32` | help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/must_outlive_least_region_or_bound.rs:22:24 --> $DIR/must_outlive_least_region_or_bound.rs:24:55
| |
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` | - ^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
| | | |
| let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'1`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/must_outlive_least_region_or_bound.rs:28:69 --> $DIR/must_outlive_least_region_or_bound.rs:29:69
| |
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
| |
= help: consider replacing `'a` with `'static` = help: consider replacing `'a` with `'static`
error: lifetime may not live long enough error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/must_outlive_least_region_or_bound.rs:32:61 --> $DIR/must_outlive_least_region_or_bound.rs:33:61
| |
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
| -- -- lifetime `'b` defined here ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a` | -- ^^^^^^^^^^^^^^^^
| | | |
| lifetime `'a` defined here | hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:35:5: 35:31]` captures the lifetime `'b` as defined here
| |
= help: consider adding the following bound: `'b: 'a` help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound
|
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + 'b {
| ++++
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/must_outlive_least_region_or_bound.rs:37:51 --> $DIR/must_outlive_least_region_or_bound.rs:38:51
| |
LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static { LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
@ -86,5 +89,5 @@ LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
error: aborting due to 9 previous errors error: aborting due to 9 previous errors
Some errors have detailed explanations: E0310, E0621. Some errors have detailed explanations: E0310, E0621, E0700.
For more information about an error, try `rustc --explain E0310`. For more information about an error, try `rustc --explain E0310`.

View file

@ -1,8 +1,10 @@
use std::fmt::Debug; use std::fmt::Debug;
fn elided(x: &i32) -> impl Copy { x } //~ ERROR E0759 fn elided(x: &i32) -> impl Copy { x }
//~^ ERROR: captures lifetime that does not appear in bounds
fn explicit<'a>(x: &'a i32) -> impl Copy { x } //~ ERROR E0759 fn explicit<'a>(x: &'a i32) -> impl Copy { x }
//~^ ERROR: captures lifetime that does not appear in bounds
fn elided2(x: &i32) -> impl Copy + 'static { x } //~ ERROR E0759 fn elided2(x: &i32) -> impl Copy + 'static { x } //~ ERROR E0759
@ -20,7 +22,6 @@ fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) } //~ ERROR E0759
fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) } //~ ERROR E0759 fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) } //~ ERROR E0759
fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } //~ ERROR E0759 fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } //~ ERROR E0759
//~^ ERROR E0759
trait LifetimeTrait<'a> {} trait LifetimeTrait<'a> {}
impl<'a> LifetimeTrait<'a> for &'a i32 {} impl<'a> LifetimeTrait<'a> for &'a i32 {}
@ -30,7 +31,7 @@ fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } //~ ERRO
// Tests that a closure type containing 'b cannot be returned from a type where // Tests that a closure type containing 'b cannot be returned from a type where
// only 'a was expected. // only 'a was expected.
fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
//~^ ERROR lifetime mismatch //~^ ERROR: captures lifetime that does not appear in bounds
move |_| println!("{}", y) move |_| println!("{}", y)
} }

View file

@ -1,41 +1,31 @@
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/must_outlive_least_region_or_bound.rs:3:35
|
LL | fn elided(x: &i32) -> impl Copy { x }
| ---- ^ ...is captured here...
| |
| this data with an anonymous lifetime `'_`...
|
note: ...and is required to live as long as `'static` here
--> $DIR/must_outlive_least_region_or_bound.rs:3:23 --> $DIR/must_outlive_least_region_or_bound.rs:3:23
| |
LL | fn elided(x: &i32) -> impl Copy { x } LL | fn elided(x: &i32) -> impl Copy { x }
| ^^^^^^^^^ | ---- ^^^^^^^^^
help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound | |
| hidden type `&i32` captures the anonymous lifetime defined here
|
help: to declare that the `impl Trait` captures '_, you can add an explicit `'_` lifetime bound
| |
LL | fn elided(x: &i32) -> impl Copy + '_ { x } LL | fn elided(x: &i32) -> impl Copy + '_ { x }
| ++++ | ++++
error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/must_outlive_least_region_or_bound.rs:5:44 --> $DIR/must_outlive_least_region_or_bound.rs:6:32
| |
LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
| ------- ^ ...is captured here... | -- ^^^^^^^^^
| | | |
| this data with lifetime `'a`... | hidden type `&'a i32` captures the lifetime `'a` as defined here
| |
note: ...and is required to live as long as `'static` here help: to declare that the `impl Trait` captures 'a, you can add an explicit `'a` lifetime bound
--> $DIR/must_outlive_least_region_or_bound.rs:5:32
|
LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
| ^^^^^^^^^
help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'a` lifetime bound
| |
LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
| ++++ | ++++
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/must_outlive_least_region_or_bound.rs:7:46 --> $DIR/must_outlive_least_region_or_bound.rs:9:46
| |
LL | fn elided2(x: &i32) -> impl Copy + 'static { x } LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
| ---- ^ ...is captured here... | ---- ^ ...is captured here...
@ -43,7 +33,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
| this data with an anonymous lifetime `'_`... | this data with an anonymous lifetime `'_`...
| |
note: ...and is required to live as long as `'static` here note: ...and is required to live as long as `'static` here
--> $DIR/must_outlive_least_region_or_bound.rs:7:24 --> $DIR/must_outlive_least_region_or_bound.rs:9:24
| |
LL | fn elided2(x: &i32) -> impl Copy + 'static { x } LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -57,7 +47,7 @@ LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x }
| ~~~~~~~~~~~~ | ~~~~~~~~~~~~
error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/must_outlive_least_region_or_bound.rs:9:55 --> $DIR/must_outlive_least_region_or_bound.rs:11:55
| |
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
| ------- ^ ...is captured here... | ------- ^ ...is captured here...
@ -65,7 +55,7 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
| this data with lifetime `'a`... | this data with lifetime `'a`...
| |
note: ...and is required to live as long as `'static` here note: ...and is required to live as long as `'static` here
--> $DIR/must_outlive_least_region_or_bound.rs:9:33 --> $DIR/must_outlive_least_region_or_bound.rs:11:33
| |
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -79,7 +69,7 @@ LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x }
| ~~~~~~~~~~~~ | ~~~~~~~~~~~~
error[E0621]: explicit lifetime required in the type of `x` error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/must_outlive_least_region_or_bound.rs:11:24 --> $DIR/must_outlive_least_region_or_bound.rs:13:24
| |
LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
| ---- ^^^^^^^^^^^^^^ lifetime `'a` required | ---- ^^^^^^^^^^^^^^ lifetime `'a` required
@ -87,7 +77,7 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
| help: add explicit lifetime `'a` to the type of `x`: `&'a i32` | help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/must_outlive_least_region_or_bound.rs:22:65 --> $DIR/must_outlive_least_region_or_bound.rs:24:65
| |
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
| ---- this data with an anonymous lifetime `'_`... ^ ...is captured here, requiring it to live as long as `'static` | ---- this data with an anonymous lifetime `'_`... ^ ...is captured here, requiring it to live as long as `'static`
@ -101,34 +91,14 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) } LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) }
| ++++ | ++++
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/must_outlive_least_region_or_bound.rs:22:69
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
| ---- this data with an anonymous lifetime `'_`... ^ ...is captured here...
|
note: ...and is required to live as long as `'static` here
--> $DIR/must_outlive_least_region_or_bound.rs:22:41
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
| ^^^^^^^^^^
help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug + '_>, impl Debug) { (Box::new(x), x) }
| ++++
help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) }
| ++++
error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/must_outlive_least_region_or_bound.rs:28:69 --> $DIR/must_outlive_least_region_or_bound.rs:29:69
| |
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
| ------- this data with lifetime `'a`... ^ ...is captured here... | ------- this data with lifetime `'a`... ^ ...is captured here...
| |
note: ...and is required to live as long as `'static` here note: ...and is required to live as long as `'static` here
--> $DIR/must_outlive_least_region_or_bound.rs:28:34 --> $DIR/must_outlive_least_region_or_bound.rs:29:34
| |
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -141,17 +111,21 @@ help: alternatively, add an explicit `'static` bound to this reference
LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x } LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x }
| ~~~~~~~~~~~~ | ~~~~~~~~~~~~
error[E0623]: lifetime mismatch error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/must_outlive_least_region_or_bound.rs:32:61 --> $DIR/must_outlive_least_region_or_bound.rs:33:61
| |
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
| ------- ^^^^^^^^^^^^^^^^ | -- ^^^^^^^^^^^^^^^^
| | | | |
| | ...but data from `y` is returned here | hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:35:5: 35:31]` captures the lifetime `'b` as defined here
| this parameter and the return type are declared with different lifetimes... |
help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound
|
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + 'b {
| ++++
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/must_outlive_least_region_or_bound.rs:37:51 --> $DIR/must_outlive_least_region_or_bound.rs:38:51
| |
LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static { LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
| -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
@ -159,7 +133,7 @@ LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
| help: consider adding an explicit lifetime bound...: `T: 'static +` | help: consider adding an explicit lifetime bound...: `T: 'static +`
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/must_outlive_least_region_or_bound.rs:14:50 --> $DIR/must_outlive_least_region_or_bound.rs:16:50
| |
LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) } LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
| ---- ^ ...is captured here, requiring it to live as long as `'static` | ---- ^ ...is captured here, requiring it to live as long as `'static`
@ -172,7 +146,7 @@ LL | fn elided3(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) }
| ++++ | ++++
error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/must_outlive_least_region_or_bound.rs:16:59 --> $DIR/must_outlive_least_region_or_bound.rs:18:59
| |
LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) } LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
| ------- ^ ...is captured here, requiring it to live as long as `'static` | ------- ^ ...is captured here, requiring it to live as long as `'static`
@ -185,7 +159,7 @@ LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }
| ++++ | ++++
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/must_outlive_least_region_or_bound.rs:18:60 --> $DIR/must_outlive_least_region_or_bound.rs:20:60
| |
LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) } LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
| ---- ^ ...is captured here, requiring it to live as long as `'static` | ---- ^ ...is captured here, requiring it to live as long as `'static`
@ -202,7 +176,7 @@ LL | fn elided4(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) }
| ~~~~~~~~~~~~ | ~~~~~~~~~~~~
error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/must_outlive_least_region_or_bound.rs:20:69 --> $DIR/must_outlive_least_region_or_bound.rs:22:69
| |
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) } LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
| ------- this data with lifetime `'a`... ^ ...is captured here, requiring it to live as long as `'static` | ------- this data with lifetime `'a`... ^ ...is captured here, requiring it to live as long as `'static`
@ -216,7 +190,7 @@ help: alternatively, add an explicit `'static` bound to this reference
LL | fn explicit4<'a>(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) } LL | fn explicit4<'a>(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) }
| ~~~~~~~~~~~~ | ~~~~~~~~~~~~
error: aborting due to 14 previous errors error: aborting due to 13 previous errors
Some errors have detailed explanations: E0310, E0621, E0623, E0759. Some errors have detailed explanations: E0310, E0621, E0700, E0759.
For more information about an error, try `rustc --explain E0310`. For more information about an error, try `rustc --explain E0310`.

View file

@ -1,28 +0,0 @@
error: lifetime may not live long enough
--> $DIR/static-return-lifetime-infered.rs:6:35
|
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
| - ^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
| |
| let's call the lifetime of this reference `'1`
|
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
|
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
| ++++
error: lifetime may not live long enough
--> $DIR/static-return-lifetime-infered.rs:9:37
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
| -- ^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static`
| |
| lifetime `'a` defined here
|
help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
| ++++
error: aborting due to 2 previous errors

View file

@ -4,10 +4,14 @@ struct A {
impl A { impl A {
fn iter_values_anon(&self) -> impl Iterator<Item=u32> { fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
self.x.iter().map(|a| a.0) //~ ERROR E0759 //~^ ERROR: captures lifetime that does not appear in bounds
//~| ERROR: captures lifetime that does not appear in bounds
self.x.iter().map(|a| a.0)
} }
fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> { fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
self.x.iter().map(|a| a.0) //~ ERROR E0759 //~^ ERROR: captures lifetime that does not appear in bounds
//~| ERROR: captures lifetime that does not appear in bounds
self.x.iter().map(|a| a.0)
} }
} }

View file

@ -1,43 +1,55 @@
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/static-return-lifetime-infered.rs:7:16
|
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
| ----- this data with an anonymous lifetime `'_`...
LL | self.x.iter().map(|a| a.0)
| ------ ^^^^
| |
| ...is captured here...
|
note: ...and is required to live as long as `'static` here
--> $DIR/static-return-lifetime-infered.rs:6:35 --> $DIR/static-return-lifetime-infered.rs:6:35
| |
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> { LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
| ^^^^^^^^^^^^^^^^^^^^^^^ | ----- ^^^^^^^^^^^^^^^^^^^^^^^
help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound | |
| hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:9:27: 9:34]>` captures the anonymous lifetime defined here
|
help: to declare that the `impl Trait` captures '_, you can add an explicit `'_` lifetime bound
| |
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ { LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
| ++++ | ++++
error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/static-return-lifetime-infered.rs:10:16 --> $DIR/static-return-lifetime-infered.rs:6:35
|
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
| ----- ^^^^^^^^^^^^^^^^^^^^^^^
| |
| hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:9:27: 9:34]>` captures the anonymous lifetime defined here
|
help: to declare that the `impl Trait` captures '_, you can add an explicit `'_` lifetime bound
|
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
| ++++
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/static-return-lifetime-infered.rs:11:37
| |
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> { LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
| -------- this data with lifetime `'a`... | -- ^^^^^^^^^^^^^^^^^^^^^^^
LL | self.x.iter().map(|a| a.0) | |
| ------ ^^^^ | hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:14:27: 14:34]>` captures the lifetime `'a` as defined here
| |
| ...is captured here...
| |
note: ...and is required to live as long as `'static` here help: to declare that the `impl Trait` captures 'a, you can add an explicit `'a` lifetime bound
--> $DIR/static-return-lifetime-infered.rs:9:37
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
| ^^^^^^^^^^^^^^^^^^^^^^^
help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound
| |
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a { LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
| ++++ | ++++
error: aborting due to 2 previous errors error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/static-return-lifetime-infered.rs:11:37
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
| -- ^^^^^^^^^^^^^^^^^^^^^^^
| |
| hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:14:27: 14:34]>` captures the lifetime `'a` as defined here
|
help: to declare that the `impl Trait` captures 'a, you can add an explicit `'a` lifetime bound
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
| ++++
For more information about this error, try `rustc --explain E0759`. error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0700`.

View file

@ -6,7 +6,8 @@
struct Foo<'a>(&'a [u8]); struct Foo<'a>(&'a [u8]);
impl<'a> Foo<'a> { impl<'a> Foo<'a> {
fn make_it(&self) -> impl Iterator<Item = u8> { //~ ERROR lifetime may not live fn make_it(&self) -> impl Iterator<Item = u8> {
//~^ ERROR: captures lifetime that does not appear in bounds
self.0.iter().copied() self.0.iter().copied()
} }
} }

View file

@ -1,10 +1,11 @@
error: lifetime may not live long enough error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/issue-73159-rpit-static.rs:9:26 --> $DIR/issue-73159-rpit-static.rs:9:26
| |
LL | impl<'a> Foo<'a> { LL | impl<'a> Foo<'a> {
| -- lifetime `'a` defined here | -- hidden type `Copied<std::slice::Iter<'a, u8>>` captures the lifetime `'a` as defined here
LL | fn make_it(&self) -> impl Iterator<Item = u8> { LL | fn make_it(&self) -> impl Iterator<Item = u8> {
| ^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static` | ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0700`.

View file

@ -8,7 +8,7 @@ trait Foo<'a> {
impl<'a, T> Foo<'a> for T { } impl<'a, T> Foo<'a> for T { }
fn foo<'a, T>(x: &T) -> impl Foo<'a> { fn foo<'a, T>(x: &T) -> impl Foo<'a> {
//~^ ERROR explicit lifetime required in the type of `x` [E0621] //~^ ERROR captures lifetime that does not appear in bounds
x x
} }

View file

@ -1,14 +1,16 @@
error[E0621]: explicit lifetime required in the type of `x` error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/impl-trait-captures.rs:10:25 --> $DIR/impl-trait-captures.rs:10:25
| |
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
| ^^^^^^^^^^^^ lifetime `ReEarlyBound(0, 'a)` required | -- ^^^^^^^^^^^^
| |
| hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[e9f4]::foo), BrAnon(0)) T` captures the anonymous lifetime defined here
| |
help: add explicit lifetime `ReEarlyBound(0, 'a)` to the type of `x` help: to declare that the `impl Trait` captures ReFree(DefId(0:8 ~ impl_trait_captures[e9f4]::foo), BrAnon(0)), you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[e9f4]::foo), BrAnon(0))` lifetime bound
| |
LL | fn foo<'a, T>(x: &ReEarlyBound(0, 'a) T) -> impl Foo<'a> { LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[e9f4]::foo), BrAnon(0)) {
| ~~~~~~~~~~~~~~~~~~~~~~ | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0621`. For more information about this error, try `rustc --explain E0700`.

View file

@ -1,15 +0,0 @@
error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37
|
LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
| - ^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
| |
| let's call the lifetime of this reference `'1`
|
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
|
LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
| ++++
error: aborting due to previous error

View file

@ -6,7 +6,7 @@ struct Foo;
impl Foo { impl Foo {
async fn f(self: Pin<&Self>) -> impl Clone { self } async fn f(self: Pin<&Self>) -> impl Clone { self }
//~^ ERROR E0759 //~^ ERROR: captures lifetime that does not appear in bounds
} }
fn main() { fn main() {

View file

@ -1,17 +1,16 @@
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37
| |
LL | async fn f(self: Pin<&Self>) -> impl Clone { self } LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
| ^^^^ ---------- ---------- ...and is required to live as long as `'static` here | - ^^^^^^^^^^
| | | | |
| | this data with an anonymous lifetime `'_`... | hidden type `Pin<&Foo>` captures the lifetime `'_` as defined here
| ...is captured here...
| |
help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound help: to declare that the `impl Trait` captures '_, you can add an explicit `'_` lifetime bound
| |
LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
| ++++ | ++++
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0759`. For more information about this error, try `rustc --explain E0700`.

View file

@ -1,15 +0,0 @@
error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:31
|
LL | fn f(self: Pin<&Self>) -> impl Clone { self }
| - ^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
| |
| let's call the lifetime of this reference `'1`
|
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
|
LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
| ++++
error: aborting due to previous error

View file

@ -3,7 +3,8 @@ use std::pin::Pin;
struct Foo; struct Foo;
impl Foo { impl Foo {
fn f(self: Pin<&Self>) -> impl Clone { self } //~ ERROR E0759 fn f(self: Pin<&Self>) -> impl Clone { self }
//~^ ERROR: captures lifetime that does not appear in bounds
} }
fn main() { fn main() {

View file

@ -1,21 +1,16 @@
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44
|
LL | fn f(self: Pin<&Self>) -> impl Clone { self }
| ---------- ^^^^ ...is captured here...
| |
| this data with an anonymous lifetime `'_`...
|
note: ...and is required to live as long as `'static` here
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:31 --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:31
| |
LL | fn f(self: Pin<&Self>) -> impl Clone { self } LL | fn f(self: Pin<&Self>) -> impl Clone { self }
| ^^^^^^^^^^ | ----- ^^^^^^^^^^
help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound | |
| hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
|
help: to declare that the `impl Trait` captures '_, you can add an explicit `'_` lifetime bound
| |
LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
| ++++ | ++++
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0759`. For more information about this error, try `rustc --explain E0700`.

View file

@ -1,17 +1,8 @@
error[E0597]: `val` does not live long enough error[E0515]: cannot return reference to function parameter `val`
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9 --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9
| |
LL | fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
| -- lifetime `'a` defined here ------------------- opaque type requires that `val` is borrowed for `'a`
LL | val.use_self() LL | val.use_self()
| ^^^^^^^^^^^^^^ borrowed value does not live long enough | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function
LL | }
| - `val` dropped here while still borrowed
|
help: you can add a bound to the opaque type to make it last less than `'static` and match `'a`
|
LL | fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> + 'a {
| ++++
error[E0515]: cannot return reference to function parameter `val` error[E0515]: cannot return reference to function parameter `val`
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9 --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9
@ -27,5 +18,4 @@ LL | val.use_self()
error: aborting due to 3 previous errors error: aborting due to 3 previous errors
Some errors have detailed explanations: E0515, E0597. For more information about this error, try `rustc --explain E0515`.
For more information about an error, try `rustc --explain E0515`.

View file

@ -18,7 +18,7 @@ mod bav {
impl Bar for i32 {} impl Bar for i32 {}
fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> { fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
val.use_self() //~ ERROR E0597 val.use_self() //~ ERROR cannot return reference to function parameter
} }
} }

View file

@ -1,17 +1,8 @@
error[E0597]: `val` does not live long enough error[E0515]: cannot return reference to function parameter `val`
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9 --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9
| |
LL | fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
| -- lifetime `'a` defined here ------------------- opaque type requires that `val` is borrowed for `'a`
LL | val.use_self() LL | val.use_self()
| ^^^^^^^^^^^^^^ borrowed value does not live long enough | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function
LL | }
| - `val` dropped here while still borrowed
|
help: you can add a bound to the opaque type to make it last less than `'static` and match `'a`
|
LL | fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> + 'a {
| ++++
error[E0515]: cannot return reference to function parameter `val` error[E0515]: cannot return reference to function parameter `val`
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9 --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9
@ -47,5 +38,4 @@ LL | impl MyTrait for Box<dyn ObjectTrait<Assoc = i32> + '_> {
error: aborting due to 4 previous errors error: aborting due to 4 previous errors
Some errors have detailed explanations: E0515, E0597. For more information about this error, try `rustc --explain E0515`.
For more information about an error, try `rustc --explain E0515`.

View file

@ -1,10 +1,13 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/trait-object-nested-in-impl-trait.rs:27:23 --> $DIR/trait-object-nested-in-impl-trait.rs:28:9
| |
LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> { LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` | - let's call the lifetime of this reference `'1`
| | LL | / Iter {
| let's call the lifetime of this reference `'1` LL | | current: None,
LL | | remaining: self.0.iter(),
LL | | }
| |_________^ returning this value requires that `'1` must outlive `'static`
| |
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
| |
@ -34,12 +37,15 @@ LL | | }
| |_________^ returning this value requires that `'a` must outlive `'static` | |_________^ returning this value requires that `'a` must outlive `'static`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/trait-object-nested-in-impl-trait.rs:60:30 --> $DIR/trait-object-nested-in-impl-trait.rs:61:9
| |
LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> { LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static` | -- lifetime `'a` defined here
| | LL | / Iter {
| lifetime `'a` defined here LL | | current: None,
LL | | remaining: self.0.iter(),
LL | | }
| |_________^ returning this value requires that `'a` must outlive `'static`
| |
help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound
| |