Final bits
This commit is contained in:
parent
f1767dbb42
commit
e09242d5b8
12 changed files with 124 additions and 34 deletions
|
@ -272,9 +272,12 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
||||||
|
|
||||||
for extra in extra_info {
|
for extra in extra_info {
|
||||||
match extra {
|
match extra {
|
||||||
_ => {}
|
ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
|
||||||
|
err.span_note(*span, format!("due to current limitations in the borrow checker, this implies a `'static` lifetime"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name);
|
self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -246,7 +246,9 @@ enum Trace<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum ExtraConstraintInfo {}
|
pub enum ExtraConstraintInfo {
|
||||||
|
PlaceholderFromPredicate(Span),
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> RegionInferenceContext<'tcx> {
|
impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
/// Creates a new region inference context with a total of
|
/// Creates a new region inference context with a total of
|
||||||
|
@ -2028,7 +2030,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
);
|
);
|
||||||
|
|
||||||
let extra_info = vec![];
|
let mut extra_info = vec![];
|
||||||
|
for constraint in path.iter() {
|
||||||
|
let outlived = constraint.sub;
|
||||||
|
let Some(origin) = self.var_infos.get(outlived) else { continue; };
|
||||||
|
let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(p)) = origin.origin else { continue; };
|
||||||
|
debug!(?constraint, ?p);
|
||||||
|
let ConstraintCategory::Predicate(span) = constraint.category else { continue; };
|
||||||
|
extra_info.push(ExtraConstraintInfo::PlaceholderFromPredicate(span));
|
||||||
|
// We only want to point to one
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint.
|
// We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint.
|
||||||
// Instead, we use it to produce an improved `ObligationCauseCode`.
|
// Instead, we use it to produce an improved `ObligationCauseCode`.
|
||||||
|
|
|
@ -25,7 +25,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
/// constraints should occur within this method so that those
|
/// constraints should occur within this method so that those
|
||||||
/// constraints can be properly localized!**
|
/// constraints can be properly localized!**
|
||||||
#[instrument(skip(self, op), level = "trace")]
|
#[instrument(skip(self, op), level = "trace")]
|
||||||
pub(super) fn fully_perform_op<R, Op>(
|
pub(super) fn fully_perform_op<R: fmt::Debug, Op>(
|
||||||
&mut self,
|
&mut self,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
category: ConstraintCategory<'tcx>,
|
category: ConstraintCategory<'tcx>,
|
||||||
|
@ -39,6 +39,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
|
|
||||||
let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?;
|
let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?;
|
||||||
|
|
||||||
|
debug!(?output, ?constraints);
|
||||||
|
|
||||||
if let Some(data) = constraints {
|
if let Some(data) = constraints {
|
||||||
self.push_region_constraints(locations, category, data);
|
self.push_region_constraints(locations, category, data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
|
fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'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.
|
||||||
|
|
|
@ -130,7 +130,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
||||||
let region_constraints = self.with_region_constraints(|region_constraints| {
|
let region_constraints = self.with_region_constraints(|region_constraints| {
|
||||||
make_query_region_constraints(
|
make_query_region_constraints(
|
||||||
tcx,
|
tcx,
|
||||||
region_obligations.iter().map(|r_o| (r_o.sup_type, r_o.sub_region)),
|
region_obligations
|
||||||
|
.iter()
|
||||||
|
.map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
|
||||||
region_constraints,
|
region_constraints,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
@ -630,7 +632,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
||||||
/// creates query region constraints.
|
/// creates query region constraints.
|
||||||
pub fn make_query_region_constraints<'tcx>(
|
pub fn make_query_region_constraints<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>)>,
|
outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>, ConstraintCategory<'tcx>)>,
|
||||||
region_constraints: &RegionConstraintData<'tcx>,
|
region_constraints: &RegionConstraintData<'tcx>,
|
||||||
) -> QueryRegionConstraints<'tcx> {
|
) -> QueryRegionConstraints<'tcx> {
|
||||||
let RegionConstraintData { constraints, verifys, givens, member_constraints } =
|
let RegionConstraintData { constraints, verifys, givens, member_constraints } =
|
||||||
|
@ -644,6 +646,7 @@ pub fn make_query_region_constraints<'tcx>(
|
||||||
let outlives: Vec<_> = constraints
|
let outlives: Vec<_> = constraints
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(k, origin)| {
|
.map(|(k, origin)| {
|
||||||
|
// no bound vars in the code above
|
||||||
let constraint = ty::Binder::dummy(match *k {
|
let constraint = ty::Binder::dummy(match *k {
|
||||||
// Swap regions because we are going from sub (<=) to outlives
|
// Swap regions because we are going from sub (<=) to outlives
|
||||||
// (>=).
|
// (>=).
|
||||||
|
@ -659,17 +662,13 @@ pub fn make_query_region_constraints<'tcx>(
|
||||||
}
|
}
|
||||||
Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
|
Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
|
||||||
});
|
});
|
||||||
|
|
||||||
(constraint, origin.to_constraint_category())
|
(constraint, origin.to_constraint_category())
|
||||||
})
|
})
|
||||||
.chain(
|
.chain(
|
||||||
outlives_obligations
|
outlives_obligations
|
||||||
// no bound vars in the code above
|
// no bound vars in the code above
|
||||||
.map(|(ty, r)| {
|
.map(|(ty, r, constraint_category)| {
|
||||||
(
|
(ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), r)), constraint_category)
|
||||||
ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), r)),
|
|
||||||
ConstraintCategory::BoringNoLocation,
|
|
||||||
)
|
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
@ -433,6 +433,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
|
||||||
pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
|
pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
|
||||||
match self {
|
match self {
|
||||||
Self::Subtype(type_trace) => type_trace.cause.to_constraint_category(),
|
Self::Subtype(type_trace) => type_trace.cause.to_constraint_category(),
|
||||||
|
Self::AscribeUserTypeProvePredicate(span) => ConstraintCategory::Predicate(*span),
|
||||||
_ => ConstraintCategory::BoringNoLocation,
|
_ => ConstraintCategory::BoringNoLocation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ impl<F, G> CustomTypeOp<F, G> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, F, R, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
|
impl<'tcx, F, R: fmt::Debug, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
|
||||||
where
|
where
|
||||||
F: for<'a, 'cx> FnOnce(&'a InferCtxt<'cx, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
|
F: for<'a, 'cx> FnOnce(&'a InferCtxt<'cx, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
|
||||||
G: Fn() -> String,
|
G: Fn() -> String,
|
||||||
|
@ -89,8 +89,8 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
|
||||||
infcx.tcx,
|
infcx.tcx,
|
||||||
region_obligations
|
region_obligations
|
||||||
.iter()
|
.iter()
|
||||||
.map(|r_o| (r_o.sup_type, r_o.sub_region))
|
.map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category()))
|
||||||
.map(|(ty, r)| (infcx.resolve_vars_if_possible(ty), r)),
|
.map(|(ty, r, cc)| (infcx.resolve_vars_if_possible(ty), r, cc)),
|
||||||
®ion_constraint_data,
|
®ion_constraint_data,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub use rustc_middle::traits::query::type_op::*;
|
||||||
/// extract out the resulting region constraints (or an error if it
|
/// extract out the resulting region constraints (or an error if it
|
||||||
/// cannot be completed).
|
/// cannot be completed).
|
||||||
pub trait TypeOp<'tcx>: Sized + fmt::Debug {
|
pub trait TypeOp<'tcx>: Sized + fmt::Debug {
|
||||||
type Output;
|
type Output: fmt::Debug;
|
||||||
type ErrorInfo;
|
type ErrorInfo;
|
||||||
|
|
||||||
/// Processes the operation and all resulting obligations,
|
/// Processes the operation and all resulting obligations,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::at::ToTrace;
|
use rustc_infer::infer::at::ToTrace;
|
||||||
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
|
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
|
||||||
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
|
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
|
||||||
use rustc_infer::traits::TraitEngineExt as _;
|
use rustc_infer::traits::{ObligationCauseCode, TraitEngineExt as _};
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::subst::{GenericArg, Subst, UserSelfTy, UserSubsts};
|
use rustc_middle::ty::subst::{GenericArg, Subst, UserSelfTy, UserSubsts};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
|
@ -22,6 +22,7 @@ use rustc_trait_selection::traits::query::type_op::subtype::Subtype;
|
||||||
use rustc_trait_selection::traits::query::{Fallible, NoSolution};
|
use rustc_trait_selection::traits::query::{Fallible, NoSolution};
|
||||||
use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, TraitEngine};
|
use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, TraitEngine};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::iter::zip;
|
||||||
|
|
||||||
pub(crate) fn provide(p: &mut Providers) {
|
pub(crate) fn provide(p: &mut Providers) {
|
||||||
*p = Providers {
|
*p = Providers {
|
||||||
|
@ -61,14 +62,15 @@ pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>(
|
||||||
mir_ty, def_id, user_substs
|
mir_ty, def_id, user_substs
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
|
let mut cx = AscribeUserTypeCx { infcx, param_env, span: span.unwrap_or(DUMMY_SP), fulfill_cx };
|
||||||
cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs, span)?;
|
cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AscribeUserTypeCx<'me, 'tcx> {
|
struct AscribeUserTypeCx<'me, 'tcx> {
|
||||||
infcx: &'me InferCtxt<'me, 'tcx>,
|
infcx: &'me InferCtxt<'me, 'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
|
span: Span,
|
||||||
fulfill_cx: &'me mut dyn TraitEngine<'tcx>,
|
fulfill_cx: &'me mut dyn TraitEngine<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +81,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
|
||||||
{
|
{
|
||||||
self.infcx
|
self.infcx
|
||||||
.partially_normalize_associated_types_in(
|
.partially_normalize_associated_types_in(
|
||||||
ObligationCause::misc(DUMMY_SP, hir::CRATE_HIR_ID),
|
ObligationCause::misc(self.span, hir::CRATE_HIR_ID),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
value,
|
value,
|
||||||
)
|
)
|
||||||
|
@ -91,18 +93,13 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
|
||||||
T: ToTrace<'tcx>,
|
T: ToTrace<'tcx>,
|
||||||
{
|
{
|
||||||
self.infcx
|
self.infcx
|
||||||
.at(&ObligationCause::dummy(), self.param_env)
|
.at(&ObligationCause::dummy_with_span(self.span), self.param_env)
|
||||||
.relate(a, variance, b)?
|
.relate(a, variance, b)?
|
||||||
.into_value_registering_obligations(self.infcx, self.fulfill_cx);
|
.into_value_registering_obligations(self.infcx, self.fulfill_cx);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prove_predicate(&mut self, predicate: Predicate<'tcx>, span: Option<Span>) {
|
fn prove_predicate(&mut self, predicate: Predicate<'tcx>, cause: ObligationCause<'tcx>) {
|
||||||
let cause = if let Some(span) = span {
|
|
||||||
ObligationCause::dummy_with_span(span)
|
|
||||||
} else {
|
|
||||||
ObligationCause::dummy()
|
|
||||||
};
|
|
||||||
self.fulfill_cx.register_predicate_obligation(
|
self.fulfill_cx.register_predicate_obligation(
|
||||||
self.infcx,
|
self.infcx,
|
||||||
Obligation::new(cause, self.param_env, predicate),
|
Obligation::new(cause, self.param_env, predicate),
|
||||||
|
@ -126,7 +123,6 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
|
||||||
mir_ty: Ty<'tcx>,
|
mir_ty: Ty<'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
user_substs: UserSubsts<'tcx>,
|
user_substs: UserSubsts<'tcx>,
|
||||||
span: Option<Span>,
|
|
||||||
) -> Result<(), NoSolution> {
|
) -> Result<(), NoSolution> {
|
||||||
let UserSubsts { user_self_ty, substs } = user_substs;
|
let UserSubsts { user_self_ty, substs } = user_substs;
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
@ -145,10 +141,20 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
|
||||||
// outlives" error messages.
|
// outlives" error messages.
|
||||||
let instantiated_predicates =
|
let instantiated_predicates =
|
||||||
self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
|
self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
|
||||||
|
|
||||||
|
let cause = ObligationCause::dummy_with_span(self.span);
|
||||||
|
|
||||||
debug!(?instantiated_predicates);
|
debug!(?instantiated_predicates);
|
||||||
for instantiated_predicate in instantiated_predicates.predicates {
|
for (instantiated_predicate, predicate_span) in
|
||||||
let instantiated_predicate = self.normalize(instantiated_predicate);
|
zip(instantiated_predicates.predicates, instantiated_predicates.spans)
|
||||||
self.prove_predicate(instantiated_predicate, span);
|
{
|
||||||
|
let span = if self.span == DUMMY_SP { predicate_span } else { self.span };
|
||||||
|
let cause = ObligationCause::new(
|
||||||
|
span,
|
||||||
|
hir::CRATE_HIR_ID,
|
||||||
|
ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
|
||||||
|
);
|
||||||
|
self.prove_predicate(instantiated_predicate, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
|
if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
|
||||||
|
@ -161,7 +167,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
|
||||||
self.prove_predicate(
|
self.prove_predicate(
|
||||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()))
|
ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()))
|
||||||
.to_predicate(self.tcx()),
|
.to_predicate(self.tcx()),
|
||||||
span,
|
cause.clone(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +184,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
|
||||||
// which...could happen with normalization...
|
// which...could happen with normalization...
|
||||||
self.prove_predicate(
|
self.prove_predicate(
|
||||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(self.tcx()),
|
ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(self.tcx()),
|
||||||
span,
|
cause,
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
35
src/test/ui/generic-associated-types/bugs/hrtb-implied-1.rs
Normal file
35
src/test/ui/generic-associated-types/bugs/hrtb-implied-1.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// check-fail
|
||||||
|
// known-bug
|
||||||
|
|
||||||
|
// This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for
|
||||||
|
// all 'a where I::Item<'a> is WF", but really means "for all 'a possible"
|
||||||
|
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
pub trait LendingIterator {
|
||||||
|
type Item<'this>
|
||||||
|
where
|
||||||
|
Self: 'this;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WindowsMut<'x> {
|
||||||
|
slice: &'x (),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'y> LendingIterator for WindowsMut<'y> {
|
||||||
|
type Item<'this> = &'this mut () where 'y: 'this;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_items<I>(_iter: I)
|
||||||
|
where
|
||||||
|
I: LendingIterator,
|
||||||
|
for<'a> I::Item<'a>: Debug,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let slice = &mut ();
|
||||||
|
//~^ temporary value dropped while borrowed
|
||||||
|
let windows = WindowsMut { slice };
|
||||||
|
print_items::<WindowsMut<'_>>(windows);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
error[E0716]: temporary value dropped while borrowed
|
||||||
|
--> $DIR/hrtb-implied-1.rs:31:22
|
||||||
|
|
|
||||||
|
LL | let slice = &mut ();
|
||||||
|
| ^^ creates a temporary which is freed while still in use
|
||||||
|
...
|
||||||
|
LL | print_items::<WindowsMut<'_>>(windows);
|
||||||
|
| -------------------------------------- argument requires that borrow lasts for `'static`
|
||||||
|
LL | }
|
||||||
|
| - temporary value is freed at the end of this statement
|
||||||
|
|
|
||||||
|
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
|
||||||
|
--> $DIR/hrtb-implied-1.rs:26:26
|
||||||
|
|
|
||||||
|
LL | for<'a> I::Item<'a>: Debug,
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0716`.
|
|
@ -9,6 +9,12 @@ LL | assert_static_via_hrtb(&local);
|
||||||
LL | assert_static_via_hrtb_with_assoc_type(&&local);
|
LL | assert_static_via_hrtb_with_assoc_type(&&local);
|
||||||
LL | }
|
LL | }
|
||||||
| - `local` dropped here while still borrowed
|
| - `local` dropped here while still borrowed
|
||||||
|
|
|
||||||
|
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
|
||||||
|
--> $DIR/local-outlives-static-via-hrtb.rs:15:53
|
||||||
|
|
|
||||||
|
LL | fn assert_static_via_hrtb<G>(_: G) where for<'a> G: Outlives<'a> {}
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0597]: `local` does not live long enough
|
error[E0597]: `local` does not live long enough
|
||||||
--> $DIR/local-outlives-static-via-hrtb.rs:25:45
|
--> $DIR/local-outlives-static-via-hrtb.rs:25:45
|
||||||
|
@ -20,6 +26,12 @@ LL | assert_static_via_hrtb_with_assoc_type(&&local);
|
||||||
| argument requires that `local` is borrowed for `'static`
|
| argument requires that `local` is borrowed for `'static`
|
||||||
LL | }
|
LL | }
|
||||||
| - `local` dropped here while still borrowed
|
| - `local` dropped here while still borrowed
|
||||||
|
|
|
||||||
|
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
|
||||||
|
--> $DIR/local-outlives-static-via-hrtb.rs:19:20
|
||||||
|
|
|
||||||
|
LL | for<'a> &'a T: Reference<AssociatedType = &'a ()>,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue