RPITITs capture all their lifetimes
This commit is contained in:
parent
8550f15e14
commit
13d3e57237
4 changed files with 60 additions and 92 deletions
|
@ -236,7 +236,7 @@ enum ImplTraitContext {
|
||||||
ReturnPositionOpaqueTy {
|
ReturnPositionOpaqueTy {
|
||||||
/// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
|
/// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
|
||||||
origin: hir::OpaqueTyOrigin,
|
origin: hir::OpaqueTyOrigin,
|
||||||
in_trait: bool,
|
fn_kind: FnDeclKind,
|
||||||
},
|
},
|
||||||
/// Impl trait in type aliases.
|
/// Impl trait in type aliases.
|
||||||
TypeAliasesOpaqueTy { in_assoc_ty: bool },
|
TypeAliasesOpaqueTy { in_assoc_ty: bool },
|
||||||
|
@ -312,7 +312,7 @@ impl std::fmt::Display for ImplTraitPosition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
enum FnDeclKind {
|
enum FnDeclKind {
|
||||||
Fn,
|
Fn,
|
||||||
Inherent,
|
Inherent,
|
||||||
|
@ -1401,13 +1401,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
TyKind::ImplTrait(def_node_id, bounds) => {
|
TyKind::ImplTrait(def_node_id, bounds) => {
|
||||||
let span = t.span;
|
let span = t.span;
|
||||||
match itctx {
|
match itctx {
|
||||||
ImplTraitContext::ReturnPositionOpaqueTy { origin, in_trait } => self
|
ImplTraitContext::ReturnPositionOpaqueTy { origin, fn_kind } => self
|
||||||
.lower_opaque_impl_trait(
|
.lower_opaque_impl_trait(
|
||||||
span,
|
span,
|
||||||
*origin,
|
*origin,
|
||||||
*def_node_id,
|
*def_node_id,
|
||||||
bounds,
|
bounds,
|
||||||
*in_trait,
|
Some(*fn_kind),
|
||||||
itctx,
|
itctx,
|
||||||
),
|
),
|
||||||
&ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self
|
&ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self
|
||||||
|
@ -1416,7 +1416,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty },
|
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty },
|
||||||
*def_node_id,
|
*def_node_id,
|
||||||
bounds,
|
bounds,
|
||||||
false,
|
None,
|
||||||
itctx,
|
itctx,
|
||||||
),
|
),
|
||||||
ImplTraitContext::Universal => {
|
ImplTraitContext::Universal => {
|
||||||
|
@ -1523,7 +1523,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
origin: hir::OpaqueTyOrigin,
|
origin: hir::OpaqueTyOrigin,
|
||||||
opaque_ty_node_id: NodeId,
|
opaque_ty_node_id: NodeId,
|
||||||
bounds: &GenericBounds,
|
bounds: &GenericBounds,
|
||||||
in_trait: bool,
|
fn_kind: Option<FnDeclKind>,
|
||||||
itctx: &ImplTraitContext,
|
itctx: &ImplTraitContext,
|
||||||
) -> hir::TyKind<'hir> {
|
) -> hir::TyKind<'hir> {
|
||||||
// Make sure we know that some funky desugaring has been going on here.
|
// Make sure we know that some funky desugaring has been going on here.
|
||||||
|
@ -1540,10 +1540,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
hir::OpaqueTyOrigin::FnReturn(..) => {
|
hir::OpaqueTyOrigin::FnReturn(..) => {
|
||||||
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a`
|
if let FnDeclKind::Impl | FnDeclKind::Trait =
|
||||||
// example, we only need to duplicate lifetimes that appear in the
|
fn_kind.expect("expected RPITs to be lowered with a FnKind")
|
||||||
// bounds, since those are the only ones that are captured by the opaque.
|
{
|
||||||
lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds)
|
// return-position impl trait in trait was decided to capture all
|
||||||
|
// in-scope lifetimes, which we collect for all opaques during resolution.
|
||||||
|
self.resolver
|
||||||
|
.take_extra_lifetime_params(opaque_ty_node_id)
|
||||||
|
.into_iter()
|
||||||
|
.map(|(ident, id, _)| Lifetime { id, ident })
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a`
|
||||||
|
// example, we only need to duplicate lifetimes that appear in the
|
||||||
|
// bounds, since those are the only ones that are captured by the opaque.
|
||||||
|
lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
hir::OpaqueTyOrigin::AsyncFn(..) => {
|
hir::OpaqueTyOrigin::AsyncFn(..) => {
|
||||||
unreachable!("should be using `lower_async_fn_ret_ty`")
|
unreachable!("should be using `lower_async_fn_ret_ty`")
|
||||||
|
@ -1554,7 +1566,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
self.lower_opaque_inner(
|
self.lower_opaque_inner(
|
||||||
opaque_ty_node_id,
|
opaque_ty_node_id,
|
||||||
origin,
|
origin,
|
||||||
in_trait,
|
matches!(fn_kind, Some(FnDeclKind::Trait)),
|
||||||
captured_lifetimes_to_duplicate,
|
captured_lifetimes_to_duplicate,
|
||||||
span,
|
span,
|
||||||
opaque_ty_span,
|
opaque_ty_span,
|
||||||
|
@ -1802,12 +1814,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let fn_def_id = self.local_def_id(fn_node_id);
|
let fn_def_id = self.local_def_id(fn_node_id);
|
||||||
self.lower_async_fn_ret_ty(
|
self.lower_async_fn_ret_ty(&decl.output, fn_def_id, ret_id, kind)
|
||||||
&decl.output,
|
|
||||||
fn_def_id,
|
|
||||||
ret_id,
|
|
||||||
matches!(kind, FnDeclKind::Trait),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
match &decl.output {
|
match &decl.output {
|
||||||
FnRetTy::Ty(ty) => {
|
FnRetTy::Ty(ty) => {
|
||||||
|
@ -1815,7 +1822,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
let fn_def_id = self.local_def_id(fn_node_id);
|
let fn_def_id = self.local_def_id(fn_node_id);
|
||||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||||
in_trait: matches!(kind, FnDeclKind::Trait),
|
fn_kind: kind,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let position = match kind {
|
let position = match kind {
|
||||||
|
@ -1883,7 +1890,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
output: &FnRetTy,
|
output: &FnRetTy,
|
||||||
fn_def_id: LocalDefId,
|
fn_def_id: LocalDefId,
|
||||||
opaque_ty_node_id: NodeId,
|
opaque_ty_node_id: NodeId,
|
||||||
in_trait: bool,
|
fn_kind: FnDeclKind,
|
||||||
) -> hir::FnRetTy<'hir> {
|
) -> hir::FnRetTy<'hir> {
|
||||||
let span = self.lower_span(output.span());
|
let span = self.lower_span(output.span());
|
||||||
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
|
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
|
||||||
|
@ -1898,7 +1905,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
let opaque_ty_ref = self.lower_opaque_inner(
|
let opaque_ty_ref = self.lower_opaque_inner(
|
||||||
opaque_ty_node_id,
|
opaque_ty_node_id,
|
||||||
hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
|
hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
|
||||||
in_trait,
|
matches!(fn_kind, FnDeclKind::Trait),
|
||||||
captured_lifetimes,
|
captured_lifetimes,
|
||||||
span,
|
span,
|
||||||
opaque_ty_span,
|
opaque_ty_span,
|
||||||
|
@ -1906,7 +1913,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
let future_bound = this.lower_async_fn_output_type_to_future_bound(
|
let future_bound = this.lower_async_fn_output_type_to_future_bound(
|
||||||
output,
|
output,
|
||||||
span,
|
span,
|
||||||
if in_trait && !this.tcx.features().return_position_impl_trait_in_trait {
|
if let FnDeclKind::Trait = fn_kind
|
||||||
|
&& !this.tcx.features().return_position_impl_trait_in_trait
|
||||||
|
{
|
||||||
ImplTraitContext::FeatureGated(
|
ImplTraitContext::FeatureGated(
|
||||||
ImplTraitPosition::TraitReturn,
|
ImplTraitPosition::TraitReturn,
|
||||||
sym::return_position_impl_trait_in_trait,
|
sym::return_position_impl_trait_in_trait,
|
||||||
|
@ -1914,7 +1923,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
} else {
|
} else {
|
||||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||||
in_trait,
|
fn_kind,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -772,9 +772,10 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
||||||
self.r.record_partial_res(ty.id, PartialRes::new(res));
|
self.r.record_partial_res(ty.id, PartialRes::new(res));
|
||||||
visit::walk_ty(self, ty)
|
visit::walk_ty(self, ty)
|
||||||
}
|
}
|
||||||
TyKind::ImplTrait(..) => {
|
TyKind::ImplTrait(node_id, _) => {
|
||||||
let candidates = self.lifetime_elision_candidates.take();
|
let candidates = self.lifetime_elision_candidates.take();
|
||||||
visit::walk_ty(self, ty);
|
visit::walk_ty(self, ty);
|
||||||
|
self.record_lifetime_params_for_impl_trait(*node_id);
|
||||||
self.lifetime_elision_candidates = candidates;
|
self.lifetime_elision_candidates = candidates;
|
||||||
}
|
}
|
||||||
TyKind::TraitObject(bounds, ..) => {
|
TyKind::TraitObject(bounds, ..) => {
|
||||||
|
@ -909,8 +910,8 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
||||||
&sig.decl.output,
|
&sig.decl.output,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some((async_node_id, span)) = sig.header.asyncness.opt_return_id() {
|
if let Some((async_node_id, _)) = sig.header.asyncness.opt_return_id() {
|
||||||
this.record_lifetime_params_for_impl_trait(async_node_id, span);
|
this.record_lifetime_params_for_impl_trait(async_node_id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -951,8 +952,8 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
||||||
&declaration.output,
|
&declaration.output,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some((async_node_id, span)) = async_node_id {
|
if let Some((async_node_id, _)) = async_node_id {
|
||||||
this.record_lifetime_params_for_impl_trait(async_node_id, span);
|
this.record_lifetime_params_for_impl_trait(async_node_id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -4367,7 +4368,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
/// We include all lifetime parameters, either named or "Fresh".
|
/// We include all lifetime parameters, either named or "Fresh".
|
||||||
/// The order of those parameters does not matter, as long as it is
|
/// The order of those parameters does not matter, as long as it is
|
||||||
/// deterministic.
|
/// deterministic.
|
||||||
fn record_lifetime_params_for_impl_trait(&mut self, impl_trait_node_id: NodeId, span: Span) {
|
fn record_lifetime_params_for_impl_trait(&mut self, impl_trait_node_id: NodeId) {
|
||||||
let mut extra_lifetime_params = vec![];
|
let mut extra_lifetime_params = vec![];
|
||||||
|
|
||||||
for rib in self.lifetime_ribs.iter().rev() {
|
for rib in self.lifetime_ribs.iter().rev() {
|
||||||
|
@ -4380,14 +4381,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
extra_lifetime_params.extend(earlier_fresh);
|
extra_lifetime_params.extend(earlier_fresh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LifetimeRibKind::Generics { .. } => {}
|
_ => {}
|
||||||
_ => {
|
|
||||||
// We are in a function definition. We should only find `Generics`
|
|
||||||
// and `AnonymousCreateParameter` inside the innermost `Item`.
|
|
||||||
span_bug!(span, "unexpected rib kind: {:?}", rib.kind)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.r.extra_lifetime_params_map.insert(impl_trait_node_id, extra_lifetime_params);
|
self.r.extra_lifetime_params_map.insert(impl_trait_node_id, extra_lifetime_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,14 @@ LL | fn baz(&self) -> impl Debug;
|
||||||
| ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
|
| ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
|
||||||
= help: consider moving `baz` to another trait
|
= help: consider moving `baz` to another trait
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `dyn Foo: Foo` is not satisfied
|
||||||
|
--> $DIR/object-safety.rs:20:15
|
||||||
|
|
|
||||||
|
LL | let s = i.baz();
|
||||||
|
| ^^^ the trait `Foo` is not implemented for `dyn Foo`
|
||||||
|
|
|
||||||
|
= help: the trait `Foo` is implemented for `u32`
|
||||||
|
|
||||||
error[E0038]: the trait `Foo` cannot be made into an object
|
error[E0038]: the trait `Foo` cannot be made into an object
|
||||||
--> $DIR/object-safety.rs:20:13
|
--> $DIR/object-safety.rs:20:13
|
||||||
|
|
|
|
||||||
|
@ -44,6 +52,7 @@ LL | fn baz(&self) -> impl Debug;
|
||||||
= help: consider moving `baz` to another trait
|
= help: consider moving `baz` to another trait
|
||||||
= note: required for the cast from `Box<u32>` to `Box<dyn Foo>`
|
= note: required for the cast from `Box<u32>` to `Box<dyn Foo>`
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0038`.
|
Some errors have detailed explanations: E0038, E0277.
|
||||||
|
For more information about an error, try `rustc --explain E0038`.
|
||||||
|
|
|
@ -1,61 +1,14 @@
|
||||||
error: return type captures more lifetimes than trait definition
|
error[E0623]: lifetime mismatch
|
||||||
--> $DIR/signature-mismatch.rs:34:47
|
|
||||||
|
|
|
||||||
LL | fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
|
|
||||||
| -- this lifetime was captured ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: hidden type must only reference lifetimes captured by this impl trait
|
|
||||||
--> $DIR/signature-mismatch.rs:15:40
|
|
||||||
|
|
|
||||||
LL | fn async_fn(&self, buff: &[u8]) -> impl Future<Output = Vec<u8>>;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: hidden type inferred to be `impl Future<Output = Vec<u8>> + 'a`
|
|
||||||
|
|
||||||
error: return type captures more lifetimes than trait definition
|
|
||||||
--> $DIR/signature-mismatch.rs:39:57
|
|
||||||
|
|
|
||||||
LL | fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
|
|
||||||
| -- this lifetime was captured ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: hidden type must only reference lifetimes captured by this impl trait
|
|
||||||
--> $DIR/signature-mismatch.rs:16:57
|
|
||||||
|
|
|
||||||
LL | fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>>;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: hidden type inferred to be `impl Future<Output = Vec<u8>> + 'a`
|
|
||||||
|
|
||||||
error: return type captures more lifetimes than trait definition
|
|
||||||
--> $DIR/signature-mismatch.rs:47:10
|
|
||||||
|
|
|
||||||
LL | fn async_fn_multiple<'a, 'b>(
|
|
||||||
| -- this lifetime was captured
|
|
||||||
...
|
|
||||||
LL | ) -> impl Future<Output = Vec<u8>> + Captures2<'a, 'b> {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: hidden type must only reference lifetimes captured by this impl trait
|
|
||||||
--> $DIR/signature-mismatch.rs:18:12
|
|
||||||
|
|
|
||||||
LL | -> impl Future<Output = Vec<u8>> + Captures<'a>;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: hidden type inferred to be `impl Future<Output = Vec<u8>> + Captures2<'a, 'b>`
|
|
||||||
|
|
||||||
error[E0309]: the parameter type `T` may not live long enough
|
|
||||||
--> $DIR/signature-mismatch.rs:56:10
|
--> $DIR/signature-mismatch.rs:56:10
|
||||||
|
|
|
|
||||||
|
LL | &'a self,
|
||||||
|
| -------- this parameter and the return type are declared with different lifetimes...
|
||||||
|
...
|
||||||
LL | ) -> impl Future<Output = Vec<u8>> {
|
LL | ) -> impl Future<Output = Vec<u8>> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `impl Future<Output = Vec<u8>>` will meet its required lifetime bounds...
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
| |
|
||||||
note: ...that is required by this bound
|
| ...but data from `buff` is returned here
|
||||||
--> $DIR/signature-mismatch.rs:23:42
|
|
||||||
|
|
|
||||||
LL | ) -> impl Future<Output = Vec<u8>> + 'a;
|
|
||||||
| ^^
|
|
||||||
help: consider adding an explicit lifetime bound...
|
|
||||||
|
|
|
||||||
LL | fn async_fn_reduce_outlive<'a, 'b, T: 'a>(
|
|
||||||
| ++++
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0309`.
|
For more information about this error, try `rustc --explain E0623`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue