Create a specific struct for lifetime capture.
This commit is contained in:
parent
a621b8499f
commit
6857a8d14e
2 changed files with 170 additions and 137 deletions
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
|
#![feature(let_chains)]
|
||||||
#![feature(let_else)]
|
#![feature(let_else)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
@ -135,24 +136,8 @@ struct LoweringContext<'a, 'hir: 'a> {
|
||||||
/// Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB.
|
/// Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB.
|
||||||
in_scope_lifetimes: Vec<(ParamName, LocalDefId)>,
|
in_scope_lifetimes: Vec<(ParamName, LocalDefId)>,
|
||||||
|
|
||||||
/// Used to handle lifetimes appearing in impl-traits. When we lower a lifetime,
|
/// Used to handle lifetimes appearing in impl-traits.
|
||||||
/// it is inserted in the `FxHashMap`, and the resolution is modified so to point
|
captured_lifetimes: Option<LifetimeCaptureContext>,
|
||||||
/// to the lifetime parameter impl-trait will generate.
|
|
||||||
/// When traversing `for<...>` binders, they are inserted in the `FxHashSet` so
|
|
||||||
/// we know *not* to rebind the introduced lifetimes.
|
|
||||||
captured_lifetimes: Option<(
|
|
||||||
LocalDefId, // parent def_id for new definitions
|
|
||||||
FxHashMap<
|
|
||||||
LocalDefId, // original parameter id
|
|
||||||
(
|
|
||||||
Span, // Span
|
|
||||||
NodeId, // synthetized parameter id
|
|
||||||
ParamName, // parameter name
|
|
||||||
LifetimeRes, // original resolution
|
|
||||||
),
|
|
||||||
>,
|
|
||||||
FxHashSet<NodeId>, // traversed binders, to ignore
|
|
||||||
)>,
|
|
||||||
|
|
||||||
current_hir_id_owner: LocalDefId,
|
current_hir_id_owner: LocalDefId,
|
||||||
item_local_id_counter: hir::ItemLocalId,
|
item_local_id_counter: hir::ItemLocalId,
|
||||||
|
@ -179,6 +164,9 @@ pub enum LifetimeRes {
|
||||||
/// - a TraitRef's ref_id, identifying the `for<...>` binder;
|
/// - a TraitRef's ref_id, identifying the `for<...>` binder;
|
||||||
/// - a BareFn type's id;
|
/// - a BareFn type's id;
|
||||||
/// - a Path's id when this path has parenthesized generic args.
|
/// - a Path's id when this path has parenthesized generic args.
|
||||||
|
///
|
||||||
|
/// This information is used for impl-trait lifetime captures, to know when to or not to
|
||||||
|
/// capture any given lifetime.
|
||||||
binder: NodeId,
|
binder: NodeId,
|
||||||
},
|
},
|
||||||
/// Created a generic parameter for an anonymous lifetime.
|
/// Created a generic parameter for an anonymous lifetime.
|
||||||
|
@ -206,6 +194,28 @@ pub enum LifetimeRes {
|
||||||
ElidedAnchor { start: NodeId, end: NodeId },
|
ElidedAnchor { start: NodeId, end: NodeId },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// When we lower a lifetime, it is inserted in `captures`, and the resolution is modified so
|
||||||
|
/// to point to the lifetime parameter impl-trait will generate.
|
||||||
|
/// When traversing `for<...>` binders, they are inserted in `binders_to_ignore` so we know *not*
|
||||||
|
/// to rebind the introduced lifetimes.
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct LifetimeCaptureContext {
|
||||||
|
/// parent def_id for new definitions
|
||||||
|
parent_def_id: LocalDefId,
|
||||||
|
/// Set of lifetimes to rebind.
|
||||||
|
captures: FxHashMap<
|
||||||
|
LocalDefId, // original parameter id
|
||||||
|
(
|
||||||
|
Span, // Span
|
||||||
|
NodeId, // synthetized parameter id
|
||||||
|
ParamName, // parameter name
|
||||||
|
LifetimeRes, // original resolution
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
/// Traversed binders. The ids in this set should *not* be rebound.
|
||||||
|
binders_to_ignore: FxHashSet<NodeId>,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ResolverAstLowering {
|
pub trait ResolverAstLowering {
|
||||||
fn def_key(&self, id: DefId) -> DefKey;
|
fn def_key(&self, id: DefId) -> DefKey;
|
||||||
|
|
||||||
|
@ -790,6 +800,45 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
(lowered_generics, res)
|
(lowered_generics, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Setup lifetime capture for and impl-trait.
|
||||||
|
/// The captures will be added to `captures`.
|
||||||
|
fn while_capturing_lifetimes<T>(
|
||||||
|
&mut self,
|
||||||
|
parent_def_id: LocalDefId,
|
||||||
|
captures: &mut FxHashMap<LocalDefId, (Span, NodeId, ParamName, LifetimeRes)>,
|
||||||
|
f: impl FnOnce(&mut Self) -> T,
|
||||||
|
) -> T {
|
||||||
|
let lifetime_stash = std::mem::replace(
|
||||||
|
&mut self.captured_lifetimes,
|
||||||
|
Some(LifetimeCaptureContext {
|
||||||
|
parent_def_id,
|
||||||
|
captures: std::mem::take(captures),
|
||||||
|
binders_to_ignore: Default::default(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
let ret = f(self);
|
||||||
|
|
||||||
|
let ctxt = std::mem::replace(&mut self.captured_lifetimes, lifetime_stash).unwrap();
|
||||||
|
*captures = ctxt.captures;
|
||||||
|
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register a binder to be ignored for lifetime capture.
|
||||||
|
#[tracing::instrument(level = "debug", skip(self, f))]
|
||||||
|
#[inline]
|
||||||
|
fn with_lifetime_binder<T>(&mut self, binder: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
|
||||||
|
if let Some(ctxt) = &mut self.captured_lifetimes {
|
||||||
|
ctxt.binders_to_ignore.insert(binder);
|
||||||
|
}
|
||||||
|
let ret = f(self);
|
||||||
|
if let Some(ctxt) = &mut self.captured_lifetimes {
|
||||||
|
ctxt.binders_to_ignore.remove(&binder);
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
fn with_dyn_type_scope<T>(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T {
|
fn with_dyn_type_scope<T>(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T {
|
||||||
let was_in_dyn_type = self.is_in_dyn_type;
|
let was_in_dyn_type = self.is_in_dyn_type;
|
||||||
self.is_in_dyn_type = in_scope;
|
self.is_in_dyn_type = in_scope;
|
||||||
|
@ -1197,25 +1246,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
|
hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
|
||||||
}
|
}
|
||||||
TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(&f.generic_params, |this| {
|
TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(&f.generic_params, |this| {
|
||||||
if let Some((_, _, binders)) = &mut this.captured_lifetimes {
|
this.with_lifetime_binder(t.id, |this| {
|
||||||
binders.insert(t.id);
|
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
|
||||||
}
|
generic_params: this.lower_generic_params(
|
||||||
|
&f.generic_params,
|
||||||
let ret = hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
generic_params: this.lower_generic_params(
|
),
|
||||||
&f.generic_params,
|
unsafety: this.lower_unsafety(f.unsafety),
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
abi: this.lower_extern(f.ext),
|
||||||
),
|
decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
|
||||||
unsafety: this.lower_unsafety(f.unsafety),
|
param_names: this.lower_fn_params_to_names(&f.decl),
|
||||||
abi: this.lower_extern(f.ext),
|
}))
|
||||||
decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
|
})
|
||||||
param_names: this.lower_fn_params_to_names(&f.decl),
|
|
||||||
}));
|
|
||||||
|
|
||||||
if let Some((_, _, binders)) = &mut this.captured_lifetimes {
|
|
||||||
binders.remove(&t.id);
|
|
||||||
}
|
|
||||||
ret
|
|
||||||
}),
|
}),
|
||||||
TyKind::Never => hir::TyKind::Never,
|
TyKind::Never => hir::TyKind::Never,
|
||||||
TyKind::Tup(ref tys) => {
|
TyKind::Tup(ref tys) => {
|
||||||
|
@ -1366,15 +1408,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
|
|
||||||
let mut collected_lifetimes = FxHashMap::default();
|
let mut collected_lifetimes = FxHashMap::default();
|
||||||
self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
|
self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
|
||||||
let capture_framework = if origin == hir::OpaqueTyOrigin::TyAlias {
|
let hir_bounds = if origin == hir::OpaqueTyOrigin::TyAlias {
|
||||||
None
|
lower_bounds(lctx)
|
||||||
} else {
|
} else {
|
||||||
Some((opaque_ty_def_id, FxHashMap::default(), FxHashSet::default()))
|
lctx.while_capturing_lifetimes(
|
||||||
|
opaque_ty_def_id,
|
||||||
|
&mut collected_lifetimes,
|
||||||
|
lower_bounds,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
let lifetime_stash = std::mem::replace(&mut lctx.captured_lifetimes, capture_framework);
|
|
||||||
let hir_bounds = lower_bounds(lctx);
|
|
||||||
collected_lifetimes = std::mem::replace(&mut lctx.captured_lifetimes, lifetime_stash)
|
|
||||||
.map_or_else(FxHashMap::default, |c| c.1);
|
|
||||||
debug!(?collected_lifetimes);
|
debug!(?collected_lifetimes);
|
||||||
|
|
||||||
let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map(
|
let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map(
|
||||||
|
@ -1716,24 +1758,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
debug!(?captures);
|
debug!(?captures);
|
||||||
|
|
||||||
self.with_hir_id_owner(opaque_ty_node_id, |this| {
|
self.with_hir_id_owner(opaque_ty_node_id, |this| {
|
||||||
let lifetime_stash = std::mem::replace(
|
|
||||||
&mut this.captured_lifetimes,
|
|
||||||
Some((opaque_ty_def_id, std::mem::take(&mut captures), FxHashSet::default())),
|
|
||||||
);
|
|
||||||
debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define);
|
debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define);
|
||||||
|
|
||||||
// We have to be careful to get elision right here. The
|
|
||||||
// idea is that we create a lifetime parameter for each
|
|
||||||
// lifetime in the return type. So, given a return type
|
|
||||||
// like `async fn foo(..) -> &[&u32]`, we lower to `impl
|
|
||||||
// Future<Output = &'1 [ &'2 u32 ]>`.
|
|
||||||
//
|
|
||||||
// Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
|
|
||||||
// hence the elision takes place at the fn site.
|
|
||||||
let future_bound =
|
let future_bound =
|
||||||
this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span);
|
this.while_capturing_lifetimes(opaque_ty_def_id, &mut captures, |this| {
|
||||||
|
// We have to be careful to get elision right here. The
|
||||||
|
// idea is that we create a lifetime parameter for each
|
||||||
|
// lifetime in the return type. So, given a return type
|
||||||
|
// like `async fn foo(..) -> &[&u32]`, we lower to `impl
|
||||||
|
// Future<Output = &'1 [ &'2 u32 ]>`.
|
||||||
|
//
|
||||||
|
// Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
|
||||||
|
// hence the elision takes place at the fn site.
|
||||||
|
this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span)
|
||||||
|
});
|
||||||
debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound);
|
debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound);
|
||||||
captures = std::mem::replace(&mut this.captured_lifetimes, lifetime_stash).unwrap().1;
|
|
||||||
debug!("lower_async_fn_ret_ty: captures={:#?}", captures);
|
debug!("lower_async_fn_ret_ty: captures={:#?}", captures);
|
||||||
|
|
||||||
let generic_params =
|
let generic_params =
|
||||||
|
@ -1882,22 +1920,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
LifetimeRes::Param { param, binder } => {
|
LifetimeRes::Param { param, binder } => {
|
||||||
debug_assert_ne!(ident.name, kw::UnderscoreLifetime);
|
debug_assert_ne!(ident.name, kw::UnderscoreLifetime);
|
||||||
let p_name = ParamName::Plain(ident);
|
let p_name = ParamName::Plain(ident);
|
||||||
if let Some((parent_def_id, captures, binders)) = &mut self.captured_lifetimes {
|
if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) =
|
||||||
|
&mut self.captured_lifetimes
|
||||||
|
&& !binders_to_ignore.contains(&binder)
|
||||||
|
{
|
||||||
match captures.entry(param) {
|
match captures.entry(param) {
|
||||||
Entry::Occupied(_) => {}
|
Entry::Occupied(_) => {}
|
||||||
Entry::Vacant(v) => {
|
Entry::Vacant(v) => {
|
||||||
if !binders.contains(&binder) {
|
let p_id = self.resolver.next_node_id();
|
||||||
let p_id = self.resolver.next_node_id();
|
self.resolver.create_def(
|
||||||
self.resolver.create_def(
|
*parent_def_id,
|
||||||
*parent_def_id,
|
p_id,
|
||||||
p_id,
|
DefPathData::LifetimeNs(p_name.ident().name),
|
||||||
DefPathData::LifetimeNs(p_name.ident().name),
|
ExpnId::root(),
|
||||||
ExpnId::root(),
|
span.with_parent(None),
|
||||||
span.with_parent(None),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
v.insert((span, p_id, p_name, res));
|
v.insert((span, p_id, p_name, res));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1908,24 +1947,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
// Only items are allowed to introduce fresh lifetimes,
|
// Only items are allowed to introduce fresh lifetimes,
|
||||||
// so we know `binder` has a `LocalDefId`.
|
// so we know `binder` has a `LocalDefId`.
|
||||||
let binder_def_id = self.resolver.local_def_id(binder);
|
let binder_def_id = self.resolver.local_def_id(binder);
|
||||||
if let Some((parent_def_id, captures, binders)) = &mut self.captured_lifetimes {
|
if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) =
|
||||||
|
&mut self.captured_lifetimes
|
||||||
|
&& !binders_to_ignore.contains(&binder)
|
||||||
|
{
|
||||||
match captures.entry(param) {
|
match captures.entry(param) {
|
||||||
Entry::Occupied(o) => param = self.resolver.local_def_id(o.get().1),
|
Entry::Occupied(o) => param = self.resolver.local_def_id(o.get().1),
|
||||||
Entry::Vacant(v) => {
|
Entry::Vacant(v) => {
|
||||||
if !binders.contains(&binder) {
|
let p_id = self.resolver.next_node_id();
|
||||||
let p_id = self.resolver.next_node_id();
|
let p_def_id = self.resolver.create_def(
|
||||||
let p_def_id = self.resolver.create_def(
|
*parent_def_id,
|
||||||
*parent_def_id,
|
p_id,
|
||||||
p_id,
|
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
|
||||||
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
|
ExpnId::root(),
|
||||||
ExpnId::root(),
|
span.with_parent(None),
|
||||||
span.with_parent(None),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
let p_name = ParamName::Fresh(param);
|
let p_name = ParamName::Fresh(param);
|
||||||
v.insert((span, p_id, p_name, res));
|
v.insert((span, p_id, p_name, res));
|
||||||
param = p_def_id;
|
param = p_def_id;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(introducer) = introducer {
|
} else if let Some(introducer) = introducer {
|
||||||
|
@ -1948,21 +1988,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
} else {
|
} else {
|
||||||
hir::LifetimeName::Underscore
|
hir::LifetimeName::Underscore
|
||||||
};
|
};
|
||||||
match &mut self.captured_lifetimes {
|
if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) =
|
||||||
Some((parent_def_id, captures, binders)) if !binders.contains(&binder) => {
|
&mut self.captured_lifetimes
|
||||||
let p_id = self.resolver.next_node_id();
|
&& !binders_to_ignore.contains(&binder)
|
||||||
let p_def_id = self.resolver.create_def(
|
{
|
||||||
*parent_def_id,
|
let p_id = self.resolver.next_node_id();
|
||||||
p_id,
|
let p_def_id = self.resolver.create_def(
|
||||||
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
|
*parent_def_id,
|
||||||
ExpnId::root(),
|
p_id,
|
||||||
span.with_parent(None),
|
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
|
||||||
);
|
ExpnId::root(),
|
||||||
let p_name = ParamName::Fresh(p_def_id);
|
span.with_parent(None),
|
||||||
captures.insert(p_def_id, (span, p_id, p_name, res));
|
);
|
||||||
hir::LifetimeName::Param(p_name)
|
let p_name = ParamName::Fresh(p_def_id);
|
||||||
}
|
captures.insert(p_def_id, (span, p_id, p_name, res));
|
||||||
_ => l_name,
|
hir::LifetimeName::Param(p_name)
|
||||||
|
} else {
|
||||||
|
l_name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LifetimeRes::Static => hir::LifetimeName::Static,
|
LifetimeRes::Static => hir::LifetimeName::Static,
|
||||||
|
@ -2069,16 +2111,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
self.lower_generic_params(&p.bound_generic_params, itctx.reborrow());
|
self.lower_generic_params(&p.bound_generic_params, itctx.reborrow());
|
||||||
|
|
||||||
let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
|
let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
|
||||||
if let Some((_, _, binders)) = &mut this.captured_lifetimes {
|
this.with_lifetime_binder(p.trait_ref.ref_id, |this| {
|
||||||
binders.insert(p.trait_ref.ref_id);
|
this.lower_trait_ref(&p.trait_ref, itctx.reborrow())
|
||||||
}
|
})
|
||||||
|
|
||||||
let trait_ref = this.lower_trait_ref(&p.trait_ref, itctx.reborrow());
|
|
||||||
|
|
||||||
if let Some((_, _, binders)) = &mut this.captured_lifetimes {
|
|
||||||
binders.remove(&p.trait_ref.ref_id);
|
|
||||||
}
|
|
||||||
trait_ref
|
|
||||||
});
|
});
|
||||||
|
|
||||||
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
|
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
|
||||||
|
|
|
@ -353,33 +353,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
// a hidden lifetime parameter. This is needed for backwards
|
// a hidden lifetime parameter. This is needed for backwards
|
||||||
// compatibility, even in contexts like an impl header where
|
// compatibility, even in contexts like an impl header where
|
||||||
// we generally don't permit such things (see #51008).
|
// we generally don't permit such things (see #51008).
|
||||||
if let Some((_, _, binders)) = &mut self.captured_lifetimes {
|
self.with_lifetime_binder(id, |this| {
|
||||||
binders.insert(id);
|
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
|
||||||
}
|
let inputs = this.arena.alloc_from_iter(inputs.iter().map(|ty| {
|
||||||
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
|
this.lower_ty_direct(
|
||||||
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| {
|
ty,
|
||||||
self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam))
|
ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam),
|
||||||
}));
|
)
|
||||||
let output_ty = match output {
|
}));
|
||||||
FnRetTy::Ty(ty) => {
|
let output_ty = match output {
|
||||||
self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
|
FnRetTy::Ty(ty) => this
|
||||||
}
|
.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)),
|
||||||
FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
|
FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(*span, &[])),
|
||||||
};
|
};
|
||||||
let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))];
|
let args = smallvec![GenericArg::Type(this.ty_tup(*inputs_span, inputs))];
|
||||||
let binding = self.output_ty_binding(output_ty.span, output_ty);
|
let binding = this.output_ty_binding(output_ty.span, output_ty);
|
||||||
if let Some((_, _, binders)) = &mut self.captured_lifetimes {
|
(
|
||||||
binders.remove(&id);
|
GenericArgsCtor {
|
||||||
}
|
args,
|
||||||
(
|
bindings: arena_vec![this; binding],
|
||||||
GenericArgsCtor {
|
parenthesized: true,
|
||||||
args,
|
span: data.inputs_span,
|
||||||
bindings: arena_vec![self; binding],
|
},
|
||||||
parenthesized: true,
|
false,
|
||||||
span: data.inputs_span,
|
)
|
||||||
},
|
})
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An associated type binding `Output = $ty`.
|
/// An associated type binding `Output = $ty`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue