Make regionck care about placeholders in outlives components
This commit is contained in:
parent
290fc68f2d
commit
8f267e2b87
@ -80,6 +80,10 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
|
|||||||
.or_insert(span);
|
.or_insert(span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component::Placeholder(_) => {
|
||||||
|
span_bug!(span, "Should not deduce placeholder outlives component");
|
||||||
|
}
|
||||||
|
|
||||||
Component::Alias(alias_ty) => {
|
Component::Alias(alias_ty) => {
|
||||||
// This would either arise from something like:
|
// This would either arise from something like:
|
||||||
//
|
//
|
||||||
|
@ -2351,6 +2351,7 @@ pub fn construct_generic_bound_failure(
|
|||||||
|
|
||||||
let labeled_user_string = match bound_kind {
|
let labeled_user_string = match bound_kind {
|
||||||
GenericKind::Param(ref p) => format!("the parameter type `{p}`"),
|
GenericKind::Param(ref p) => format!("the parameter type `{p}`"),
|
||||||
|
GenericKind::Placeholder(ref p) => format!("the placeholder type `{p:?}`"),
|
||||||
GenericKind::Alias(ref p) => match p.kind(self.tcx) {
|
GenericKind::Alias(ref p) => match p.kind(self.tcx) {
|
||||||
ty::AliasKind::Projection | ty::AliasKind::Inherent => {
|
ty::AliasKind::Projection | ty::AliasKind::Inherent => {
|
||||||
format!("the associated type `{p}`")
|
format!("the associated type `{p}`")
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
pub enum Component<'tcx> {
|
pub enum Component<'tcx> {
|
||||||
Region(ty::Region<'tcx>),
|
Region(ty::Region<'tcx>),
|
||||||
Param(ty::ParamTy),
|
Param(ty::ParamTy),
|
||||||
|
Placeholder(ty::PlaceholderType),
|
||||||
UnresolvedInferenceVariable(ty::InferTy),
|
UnresolvedInferenceVariable(ty::InferTy),
|
||||||
|
|
||||||
// Projections like `T::Foo` are tricky because a constraint like
|
// Projections like `T::Foo` are tricky because a constraint like
|
||||||
@ -120,6 +121,10 @@ fn compute_components<'tcx>(
|
|||||||
out.push(Component::Param(p));
|
out.push(Component::Param(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ty::Placeholder(p) => {
|
||||||
|
out.push(Component::Placeholder(p));
|
||||||
|
}
|
||||||
|
|
||||||
// For projections, we prefer to generate an obligation like
|
// For projections, we prefer to generate an obligation like
|
||||||
// `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
|
// `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
|
||||||
// regionck more ways to prove that it holds. However,
|
// regionck more ways to prove that it holds. However,
|
||||||
@ -176,7 +181,6 @@ fn compute_components<'tcx>(
|
|||||||
ty::Tuple(..) | // ...
|
ty::Tuple(..) | // ...
|
||||||
ty::FnPtr(_) | // OutlivesFunction (*)
|
ty::FnPtr(_) | // OutlivesFunction (*)
|
||||||
ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*)
|
ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*)
|
||||||
ty::Placeholder(..) |
|
|
||||||
ty::Bound(..) |
|
ty::Bound(..) |
|
||||||
ty::Error(_) => {
|
ty::Error(_) => {
|
||||||
// (*) Function pointers and trait objects are both binders.
|
// (*) Function pointers and trait objects are both binders.
|
||||||
|
@ -243,6 +243,9 @@ fn components_must_outlive(
|
|||||||
Component::Param(param_ty) => {
|
Component::Param(param_ty) => {
|
||||||
self.param_ty_must_outlive(origin, region, *param_ty);
|
self.param_ty_must_outlive(origin, region, *param_ty);
|
||||||
}
|
}
|
||||||
|
Component::Placeholder(placeholder_ty) => {
|
||||||
|
self.placeholder_ty_must_outlive(origin, region, *placeholder_ty);
|
||||||
|
}
|
||||||
Component::Alias(alias_ty) => self.alias_ty_must_outlive(origin, region, *alias_ty),
|
Component::Alias(alias_ty) => self.alias_ty_must_outlive(origin, region, *alias_ty),
|
||||||
Component::EscapingAlias(subcomponents) => {
|
Component::EscapingAlias(subcomponents) => {
|
||||||
self.components_must_outlive(origin, &subcomponents, region, category);
|
self.components_must_outlive(origin, &subcomponents, region, category);
|
||||||
@ -267,10 +270,28 @@ fn param_ty_must_outlive(
|
|||||||
region: ty::Region<'tcx>,
|
region: ty::Region<'tcx>,
|
||||||
param_ty: ty::ParamTy,
|
param_ty: ty::ParamTy,
|
||||||
) {
|
) {
|
||||||
let verify_bound = self.verify_bound.param_bound(param_ty);
|
let verify_bound = self.verify_bound.param_or_placeholder_bound(param_ty.to_ty(self.tcx));
|
||||||
self.delegate.push_verify(origin, GenericKind::Param(param_ty), region, verify_bound);
|
self.delegate.push_verify(origin, GenericKind::Param(param_ty), region, verify_bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
fn placeholder_ty_must_outlive(
|
||||||
|
&mut self,
|
||||||
|
origin: infer::SubregionOrigin<'tcx>,
|
||||||
|
region: ty::Region<'tcx>,
|
||||||
|
placeholder_ty: ty::PlaceholderType,
|
||||||
|
) {
|
||||||
|
let verify_bound = self
|
||||||
|
.verify_bound
|
||||||
|
.param_or_placeholder_bound(Ty::new_placeholder(self.tcx, placeholder_ty));
|
||||||
|
self.delegate.push_verify(
|
||||||
|
origin,
|
||||||
|
GenericKind::Placeholder(placeholder_ty),
|
||||||
|
region,
|
||||||
|
verify_bound,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn alias_ty_must_outlive(
|
fn alias_ty_must_outlive(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -37,11 +37,11 @@ pub fn new(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
|
pub fn param_or_placeholder_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
|
||||||
// Start with anything like `T: 'a` we can scrape from the
|
// Start with anything like `T: 'a` we can scrape from the
|
||||||
// environment. If the environment contains something like
|
// environment. If the environment contains something like
|
||||||
// `for<'a> T: 'a`, then we know that `T` outlives everything.
|
// `for<'a> T: 'a`, then we know that `T` outlives everything.
|
||||||
let declared_bounds_from_env = self.declared_generic_bounds_from_env(param_ty);
|
let declared_bounds_from_env = self.declared_generic_bounds_from_env(ty);
|
||||||
debug!(?declared_bounds_from_env);
|
debug!(?declared_bounds_from_env);
|
||||||
let mut param_bounds = vec![];
|
let mut param_bounds = vec![];
|
||||||
for declared_bound in declared_bounds_from_env {
|
for declared_bound in declared_bounds_from_env {
|
||||||
@ -51,7 +51,7 @@ pub fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
|
|||||||
param_bounds.push(VerifyBound::OutlivedBy(region));
|
param_bounds.push(VerifyBound::OutlivedBy(region));
|
||||||
} else {
|
} else {
|
||||||
// This is `for<'a> T: 'a`. This means that `T` outlives everything! All done here.
|
// This is `for<'a> T: 'a`. This means that `T` outlives everything! All done here.
|
||||||
debug!("found that {param_ty:?} outlives any lifetime, returning empty vector");
|
debug!("found that {ty:?} outlives any lifetime, returning empty vector");
|
||||||
return VerifyBound::AllBounds(vec![]);
|
return VerifyBound::AllBounds(vec![]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,7 +168,10 @@ fn bound_from_single_component(
|
|||||||
) -> VerifyBound<'tcx> {
|
) -> VerifyBound<'tcx> {
|
||||||
match *component {
|
match *component {
|
||||||
Component::Region(lt) => VerifyBound::OutlivedBy(lt),
|
Component::Region(lt) => VerifyBound::OutlivedBy(lt),
|
||||||
Component::Param(param_ty) => self.param_bound(param_ty),
|
Component::Param(param_ty) => self.param_or_placeholder_bound(param_ty.to_ty(self.tcx)),
|
||||||
|
Component::Placeholder(placeholder_ty) => {
|
||||||
|
self.param_or_placeholder_bound(Ty::new_placeholder(self.tcx, placeholder_ty))
|
||||||
|
}
|
||||||
Component::Alias(alias_ty) => self.alias_bound(alias_ty, visited),
|
Component::Alias(alias_ty) => self.alias_bound(alias_ty, visited),
|
||||||
Component::EscapingAlias(ref components) => {
|
Component::EscapingAlias(ref components) => {
|
||||||
self.bound_from_components(components, visited)
|
self.bound_from_components(components, visited)
|
||||||
@ -195,9 +198,9 @@ fn bound_from_single_component(
|
|||||||
/// bounds, but all the bounds it returns can be relied upon.
|
/// bounds, but all the bounds it returns can be relied upon.
|
||||||
fn declared_generic_bounds_from_env(
|
fn declared_generic_bounds_from_env(
|
||||||
&self,
|
&self,
|
||||||
param_ty: ty::ParamTy,
|
generic_ty: Ty<'tcx>,
|
||||||
) -> Vec<ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>> {
|
) -> Vec<ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>> {
|
||||||
let generic_ty = param_ty.to_ty(self.tcx);
|
assert!(matches!(generic_ty.kind(), ty::Param(_) | ty::Placeholder(_)));
|
||||||
self.declared_generic_bounds_from_env_for_erased_ty(generic_ty)
|
self.declared_generic_bounds_from_env_for_erased_ty(generic_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +147,7 @@ pub struct Verify<'tcx> {
|
|||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
|
||||||
pub enum GenericKind<'tcx> {
|
pub enum GenericKind<'tcx> {
|
||||||
Param(ty::ParamTy),
|
Param(ty::ParamTy),
|
||||||
|
Placeholder(ty::PlaceholderType),
|
||||||
Alias(ty::AliasTy<'tcx>),
|
Alias(ty::AliasTy<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,6 +708,7 @@ impl<'tcx> fmt::Debug for GenericKind<'tcx> {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
GenericKind::Param(ref p) => write!(f, "{p:?}"),
|
GenericKind::Param(ref p) => write!(f, "{p:?}"),
|
||||||
|
GenericKind::Placeholder(ref p) => write!(f, "{p:?}"),
|
||||||
GenericKind::Alias(ref p) => write!(f, "{p:?}"),
|
GenericKind::Alias(ref p) => write!(f, "{p:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -716,6 +718,7 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
GenericKind::Param(ref p) => write!(f, "{p}"),
|
GenericKind::Param(ref p) => write!(f, "{p}"),
|
||||||
|
GenericKind::Placeholder(ref p) => write!(f, "{p:?}"),
|
||||||
GenericKind::Alias(ref p) => write!(f, "{p}"),
|
GenericKind::Alias(ref p) => write!(f, "{p}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -725,6 +728,7 @@ impl<'tcx> GenericKind<'tcx> {
|
|||||||
pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||||
match *self {
|
match *self {
|
||||||
GenericKind::Param(ref p) => p.to_ty(tcx),
|
GenericKind::Param(ref p) => p.to_ty(tcx),
|
||||||
|
GenericKind::Placeholder(ref p) => Ty::new_placeholder(tcx, *p),
|
||||||
GenericKind::Alias(ref p) => p.to_ty(tcx),
|
GenericKind::Alias(ref p) => p.to_ty(tcx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,6 +365,11 @@ fn elaborate(&mut self, elaboratable: &O) {
|
|||||||
Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min)))
|
Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component::Placeholder(p) => {
|
||||||
|
let ty = Ty::new_placeholder(tcx, p);
|
||||||
|
Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min)))
|
||||||
|
}
|
||||||
|
|
||||||
Component::UnresolvedInferenceVariable(_) => None,
|
Component::UnresolvedInferenceVariable(_) => None,
|
||||||
|
|
||||||
Component::Alias(alias_ty) => {
|
Component::Alias(alias_ty) => {
|
||||||
|
@ -398,7 +398,8 @@ fn impl_intersection_has_negative_obligation(
|
|||||||
debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
|
debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
|
||||||
|
|
||||||
let ref infcx = tcx.infer_ctxt().intercrate(true).with_next_trait_solver(true).build();
|
let ref infcx = tcx.infer_ctxt().intercrate(true).with_next_trait_solver(true).build();
|
||||||
let universe = infcx.universe();
|
let root_universe = infcx.universe();
|
||||||
|
assert_eq!(root_universe, ty::UniverseIndex::ROOT);
|
||||||
|
|
||||||
let impl1_header = fresh_impl_header(infcx, impl1_def_id);
|
let impl1_header = fresh_impl_header(infcx, impl1_def_id);
|
||||||
let param_env =
|
let param_env =
|
||||||
@ -414,7 +415,12 @@ fn impl_intersection_has_negative_obligation(
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
plug_infer_with_placeholders(infcx, universe, (impl1_header.impl_args, impl2_header.impl_args));
|
plug_infer_with_placeholders(
|
||||||
|
infcx,
|
||||||
|
root_universe,
|
||||||
|
(impl1_header.impl_args, impl2_header.impl_args),
|
||||||
|
);
|
||||||
|
let param_env = infcx.resolve_vars_if_possible(param_env);
|
||||||
|
|
||||||
util::elaborate(tcx, tcx.predicates_of(impl2_def_id).instantiate(tcx, impl2_header.impl_args))
|
util::elaborate(tcx, tcx.predicates_of(impl2_def_id).instantiate(tcx, impl2_header.impl_args))
|
||||||
.any(|(clause, _)| try_prove_negated_where_clause(infcx, clause, param_env))
|
.any(|(clause, _)| try_prove_negated_where_clause(infcx, clause, param_env))
|
||||||
|
@ -208,6 +208,9 @@ fn implied_bounds_from_components<'tcx>(
|
|||||||
Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)),
|
Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)),
|
||||||
Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)),
|
Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)),
|
||||||
Component::Alias(p) => Some(OutlivesBound::RegionSubAlias(sub_region, p)),
|
Component::Alias(p) => Some(OutlivesBound::RegionSubAlias(sub_region, p)),
|
||||||
|
Component::Placeholder(_) => {
|
||||||
|
unimplemented!("Shouldn't expect a placeholder type in implied bounds (yet)")
|
||||||
|
}
|
||||||
Component::EscapingAlias(_) =>
|
Component::EscapingAlias(_) =>
|
||||||
// If the projection has escaping regions, don't
|
// If the projection has escaping regions, don't
|
||||||
// try to infer any implied bounds even for its
|
// try to infer any implied bounds even for its
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
#![feature(negative_impls)]
|
||||||
|
#![feature(with_negative_coherence)]
|
||||||
|
|
||||||
|
struct Wrap<T>(T);
|
||||||
|
|
||||||
|
trait Foo {}
|
||||||
|
impl<T: 'static> !Foo for Box<T> {}
|
||||||
|
|
||||||
|
trait Bar {}
|
||||||
|
impl<T> Bar for T where T: Foo {}
|
||||||
|
impl<T> Bar for Box<T> {}
|
||||||
|
//~^ ERROR conflicting implementations of trait `Bar` for type `Box<_>`
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,11 @@
|
|||||||
|
error[E0119]: conflicting implementations of trait `Bar` for type `Box<_>`
|
||||||
|
--> $DIR/negative-coherence-check-placeholder-outlives.rs:11:1
|
||||||
|
|
|
||||||
|
LL | impl<T> Bar for T where T: Foo {}
|
||||||
|
| ------------------------------ first implementation here
|
||||||
|
LL | impl<T> Bar for Box<T> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0119`.
|
@ -0,0 +1,26 @@
|
|||||||
|
warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/placeholders-dont-outlive-static.rs:6:12
|
||||||
|
|
|
||||||
|
LL | #![feature(non_lifetime_binders)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0310]: the placeholder type `!1_"T"` may not live long enough
|
||||||
|
--> $DIR/placeholders-dont-outlive-static.rs:13:5
|
||||||
|
|
|
||||||
|
LL | foo();
|
||||||
|
| ^^^^^
|
||||||
|
| |
|
||||||
|
| the placeholder type `!1_"T"` must be valid for the static lifetime...
|
||||||
|
| ...so that the type `T` will meet its required lifetime bounds
|
||||||
|
|
|
||||||
|
help: consider adding an explicit lifetime bound
|
||||||
|
|
|
||||||
|
LL | fn bad() where !1_"T": 'static {
|
||||||
|
| +++++++++++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0310`.
|
@ -0,0 +1,26 @@
|
|||||||
|
warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/placeholders-dont-outlive-static.rs:6:12
|
||||||
|
|
|
||||||
|
LL | #![feature(non_lifetime_binders)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0310]: the placeholder type `!1_"T"` may not live long enough
|
||||||
|
--> $DIR/placeholders-dont-outlive-static.rs:19:5
|
||||||
|
|
|
||||||
|
LL | foo();
|
||||||
|
| ^^^^^
|
||||||
|
| |
|
||||||
|
| the placeholder type `!1_"T"` must be valid for the static lifetime...
|
||||||
|
| ...so that the type `T` will meet its required lifetime bounds
|
||||||
|
|
|
||||||
|
help: consider adding an explicit lifetime bound
|
||||||
|
|
|
||||||
|
LL | fn good() where for<T> T: 'static, !1_"T": 'static {
|
||||||
|
| +++++++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0310`.
|
@ -0,0 +1,22 @@
|
|||||||
|
// revisions: good bad
|
||||||
|
|
||||||
|
//[good] known-bug: unknown
|
||||||
|
// `for<T> T: 'static` doesn't imply itself when processing outlives obligations
|
||||||
|
|
||||||
|
#![feature(non_lifetime_binders)]
|
||||||
|
//[bad]~^ WARN the feature `non_lifetime_binders` is incomplete
|
||||||
|
|
||||||
|
fn foo() where for<T> T: 'static {}
|
||||||
|
|
||||||
|
#[cfg(bad)]
|
||||||
|
fn bad() {
|
||||||
|
foo();
|
||||||
|
//[bad]~^ ERROR the placeholder type `!1_"T"` may not live long enough
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(good)]
|
||||||
|
fn good() where for<T> T: 'static {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -1,10 +1,9 @@
|
|||||||
// edition:2021
|
// edition:2021
|
||||||
// check-pass
|
// known-bug: unknown
|
||||||
|
|
||||||
// Checks that test_type_match code doesn't ICE when predicates have late-bound types
|
// Checks that test_type_match code doesn't ICE when predicates have late-bound types
|
||||||
|
|
||||||
#![feature(non_lifetime_binders)]
|
#![feature(non_lifetime_binders)]
|
||||||
//~^ WARN is incomplete and may not be safe to use
|
|
||||||
|
|
||||||
async fn walk2<'a, T: 'a>(_: T)
|
async fn walk2<'a, T: 'a>(_: T)
|
||||||
where
|
where
|
||||||
|
@ -7,5 +7,20 @@ LL | #![feature(non_lifetime_binders)]
|
|||||||
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
warning: 1 warning emitted
|
error[E0309]: the placeholder type `!1_"F"` may not live long enough
|
||||||
|
--> $DIR/type-match-with-late-bound.rs:11:1
|
||||||
|
|
|
||||||
|
LL | async fn walk2<'a, T: 'a>(_: T)
|
||||||
|
| -- the placeholder type `!1_"F"` must be valid for the lifetime `'a` as defined here...
|
||||||
|
...
|
||||||
|
LL | {}
|
||||||
|
| ^^ ...so that the type `F` will meet its required lifetime bounds
|
||||||
|
|
|
||||||
|
help: consider adding an explicit lifetime bound
|
||||||
|
|
|
||||||
|
LL | for<F> F: 'a, !1_"F": 'a
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0309`.
|
||||||
|
Loading…
Reference in New Issue
Block a user