let kind = match constraint.kind {
AssocConstraintKind::Equality { ref term } => {
let term = match term {
- Term::Ty(ref ty) => self.lower_ty(ty, itctx).into(),
+ Term::Ty(ref ty) => self.lower_ty(ty, itctx, true).into(),
Term::Const(ref c) => self.lower_anon_const(c).into(),
};
hir::TypeBindingKind::Equality { term }
tokens: None,
},
itctx,
+ true,
);
hir::TypeBindingKind::Equality { term: ty.into() }
} else {
// Desugar `AssocTy: Bounds` into a type binding where the
// later desugars into a trait predicate.
- let bounds = self.lower_param_bounds(bounds, itctx);
+ let bounds = self.lower_param_bounds(bounds, itctx, true);
hir::TypeBindingKind::Constraint { bounds }
}
itctx: ImplTraitContext,
) -> hir::GenericArg<'hir> {
match arg {
- ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)),
+ ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<, true)),
ast::GenericArg::Type(ty) => {
match ty.kind {
TyKind::Infer if self.tcx.features().generic_arg_infer => {
}
_ => {}
}
- GenericArg::Type(self.lower_ty_direct(&ty, itctx))
+ GenericArg::Type(self.lower_ty_direct(&ty, itctx, true))
}
ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg {
value: self.lower_anon_const(&ct),
}
#[instrument(level = "debug", skip(self))]
- fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> {
- self.arena.alloc(self.lower_ty_direct(t, itctx))
+ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext, captures: bool) -> &'hir hir::Ty<'hir> {
+ self.arena.alloc(self.lower_ty_direct(t, itctx, captures))
}
fn lower_path_ty(
path: &Path,
param_mode: ParamMode,
itctx: ImplTraitContext,
+ captures: bool,
) -> hir::Ty<'hir> {
// Check whether we should interpret this as a bare trait object.
// This check mirrors the one in late resolution. We only introduce this special case in
span: t.span
},
itctx,
+ captures,
);
let bounds = this.arena.alloc_from_iter([bound]);
let lifetime_bound = this.elided_dyn_bound(t.span);
}
let id = self.lower_node_id(t.id);
- let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
+ let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx, true);
self.ty_path(id, t.span, qpath)
}
self.ty(span, hir::TyKind::Tup(tys))
}
- fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> {
+ fn lower_ty_direct(
+ &mut self,
+ t: &Ty,
+ itctx: ImplTraitContext,
+ captures: bool,
+ ) -> hir::Ty<'hir> {
let kind = match t.kind {
TyKind::Infer => hir::TyKind::Infer,
TyKind::Err => hir::TyKind::Err,
- TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
+ TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx, captures)),
TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
TyKind::Rptr(ref region, ref mt) => {
let region = region.unwrap_or_else(|| {
let span = self.tcx.sess.source_map().next_point(t.span.shrink_to_lo());
Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id }
});
- let lifetime = self.lower_lifetime(®ion);
+ let lifetime = self.lower_lifetime(®ion, captures);
hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
}
TyKind::BareFn(ref f) => {
})
}
TyKind::Never => hir::TyKind::Never,
- TyKind::Tup(ref tys) => hir::TyKind::Tup(
- self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))),
- ),
+ TyKind::Tup(ref tys) => {
+ hir::TyKind::Tup(self.arena.alloc_from_iter(
+ tys.iter().map(|ty| self.lower_ty_direct(ty, itctx, captures)),
+ ))
+ }
TyKind::Paren(ref ty) => {
- return self.lower_ty_direct(ty, itctx);
+ return self.lower_ty_direct(ty, itctx, captures);
}
TyKind::Path(ref qself, ref path) => {
- return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx);
+ return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx, captures);
}
TyKind::ImplicitSelf => {
let res = self.expect_full_res(t.id);
}),
))
}
- TyKind::Array(ref ty, ref length) => {
- hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length))
- }
+ TyKind::Array(ref ty, ref length) => hir::TyKind::Array(
+ self.lower_ty(ty, itctx, captures),
+ self.lower_array_length(length),
+ ),
TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
TyKind::TraitObject(ref bounds, kind) => {
let mut lifetime_bound = None;
GenericBound::Trait(
ref ty,
TraitBoundModifier::None | TraitBoundModifier::MaybeConst,
- ) => Some(this.lower_poly_trait_ref(ty, itctx)),
+ ) => Some(this.lower_poly_trait_ref(ty, itctx, captures)),
// `~const ?Bound` will cause an error during AST validation
// anyways, so treat it like `?Bound` as compilation proceeds.
GenericBound::Trait(
) => None,
GenericBound::Outlives(ref lifetime) => {
if lifetime_bound.is_none() {
- lifetime_bound = Some(this.lower_lifetime(lifetime));
+ lifetime_bound = Some(this.lower_lifetime(lifetime, true));
}
None
}
TyKind::ImplTrait(def_node_id, ref bounds) => {
let span = t.span;
match itctx {
- ImplTraitContext::ReturnPositionOpaqueTy { origin } => self
- .lower_opaque_impl_trait(span, origin, def_node_id, |this| {
- this.lower_param_bounds(bounds, itctx)
- }),
+ ImplTraitContext::ReturnPositionOpaqueTy { origin } => {
+ self.lower_opaque_impl_trait(span, origin, def_node_id, bounds, itctx)
+ }
ImplTraitContext::TypeAliasesOpaqueTy => {
let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy;
self.lower_opaque_impl_trait(
span,
hir::OpaqueTyOrigin::TyAlias,
def_node_id,
- |this| this.lower_param_bounds(bounds, nested_itctx),
+ bounds,
+ nested_itctx,
)
}
ImplTraitContext::Universal => {
hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) }
}
- #[tracing::instrument(level = "debug", skip(self, lower_bounds))]
+ #[tracing::instrument(level = "debug", skip(self))]
fn lower_opaque_impl_trait(
&mut self,
span: Span,
origin: hir::OpaqueTyOrigin,
opaque_ty_node_id: NodeId,
- lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>,
+ bounds: &GenericBounds,
+ itctx: ImplTraitContext,
) -> hir::TyKind<'hir> {
// Make sure we know that some funky desugaring has been going on here.
// This is a first: there is code in other places like for loop
let mut collected_lifetimes = FxHashMap::default();
self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
let hir_bounds = if origin == hir::OpaqueTyOrigin::TyAlias {
- lower_bounds(lctx)
+ lctx.lower_param_bounds(bounds, itctx, true)
} else {
- lctx.while_capturing_lifetimes(
- opaque_ty_def_id,
- &mut collected_lifetimes,
- lower_bounds,
- )
+ debug!(?lctx.captured_lifetimes);
+
+ let lifetime_stash = std::mem::replace(
+ &mut lctx.captured_lifetimes,
+ Some(LifetimeCaptureContext {
+ parent_def_id: opaque_ty_def_id,
+ captures: std::mem::take(&mut collected_lifetimes),
+ binders_to_ignore: Default::default(),
+ }),
+ );
+
+ let (lifetimes_in_bounds, binders_to_ignore) = ast::lifetimes_in_bounds(bounds);
+ debug!(?lifetimes_in_bounds);
+ debug!(?binders_to_ignore);
+
+ lctx.create_and_capture_lifetime_defs(&lifetimes_in_bounds, &binders_to_ignore);
+
+ let ret = lctx.lower_param_bounds(bounds, itctx, false);
+
+ let ctxt = std::mem::replace(&mut lctx.captured_lifetimes, lifetime_stash).unwrap();
+
+ collected_lifetimes = ctxt.captures;
+
+ ret
};
debug!(?collected_lifetimes);
|(_, (span, _, p_name, res))| {
let id = self.next_node_id();
let ident = Ident::new(p_name.ident().name, span);
- let l = self.new_named_lifetime_with_res(id, span, ident, res);
+ let l = self.new_named_lifetime_with_res(id, span, ident, res, true);
hir::GenericArg::Lifetime(l)
},
));
hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
}
+ fn create_and_capture_lifetime_defs(
+ &mut self,
+ lifetimes_in_bounds: &[&Lifetime],
+ binders_to_ignore: &FxHashMap<NodeId, Vec<NodeId>>,
+ ) {
+ for lifetime in lifetimes_in_bounds {
+ let ident = lifetime.ident;
+ let span = ident.span;
+
+ let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error);
+ debug!(?res);
+
+ if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() {
+ match res {
+ LifetimeRes::Param { param, binder } => {
+ if !captured_lifetimes.binders_to_ignore.contains(&binder)
+ && !binders_to_ignore
+ .get(&lifetime.id)
+ .unwrap_or(&Vec::new())
+ .contains(&binder)
+ {
+ match captured_lifetimes.captures.entry(param) {
+ Entry::Occupied(_) => {}
+ Entry::Vacant(v) => {
+ let node_id = self.next_node_id();
+ let name = ParamName::Plain(ident);
+
+ self.create_def(
+ captured_lifetimes.parent_def_id,
+ node_id,
+ DefPathData::LifetimeNs(name.ident().name),
+ );
+
+ v.insert((span, node_id, name, res));
+ }
+ }
+ }
+ }
+
+ LifetimeRes::Fresh { param, binder } => {
+ debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
+ if !captured_lifetimes.binders_to_ignore.contains(&binder)
+ && !binders_to_ignore
+ .get(&lifetime.id)
+ .unwrap_or(&Vec::new())
+ .contains(&binder)
+ {
+ let param = self.local_def_id(param);
+ match captured_lifetimes.captures.entry(param) {
+ Entry::Occupied(_) => {}
+ Entry::Vacant(v) => {
+ let node_id = self.next_node_id();
+
+ let name = ParamName::Fresh;
+
+ self.create_def(
+ captured_lifetimes.parent_def_id,
+ node_id,
+ DefPathData::LifetimeNs(kw::UnderscoreLifetime),
+ );
+
+ v.insert((span, node_id, name, res));
+ }
+ }
+ }
+ }
+
+ LifetimeRes::Infer | LifetimeRes::Static | LifetimeRes::Error => {}
+
+ res => panic!(
+ "Unexpected lifetime resolution {:?} for {:?} at {:?}",
+ res, lifetime.ident, lifetime.ident.span
+ ),
+ }
+
+ self.captured_lifetimes = Some(captured_lifetimes);
+ }
+ }
+ }
+
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
// Skip the `...` (`CVarArgs`) trailing arguments from the AST,
// as they are not explicit in HIR/Ty function signatures.
}
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
if fn_node_id.is_some() {
- self.lower_ty_direct(¶m.ty, ImplTraitContext::Universal)
+ self.lower_ty_direct(¶m.ty, ImplTraitContext::Universal, true)
} else {
self.lower_ty_direct(
¶m.ty,
FnDeclKind::Trait => ImplTraitPosition::TraitParam,
FnDeclKind::Impl => ImplTraitPosition::ImplParam,
}),
+ true,
)
}
}));
FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
}),
};
- hir::FnRetTy::Return(self.lower_ty(ty, context))
+ hir::FnRetTy::Return(self.lower_ty(ty, context, true))
}
FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)),
}
//
// type OpaqueTy<generics_from_parent_fn> = impl Future<Output = T>;
//
- // `inputs`: lowered types of parameters to the function (used to collect lifetimes)
// `output`: unlowered output type (`T` in `-> T`)
// `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition)
// `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created
- // `elided_lt_replacement`: replacement for elided lifetimes in the return type
#[tracing::instrument(level = "debug", skip(self))]
fn lower_async_fn_ret_ty(
&mut self,
self.arena.alloc_from_iter(captures.into_iter().map(|(_, (span, _, p_name, res))| {
let id = self.next_node_id();
let ident = Ident::new(p_name.ident().name, span);
- let l = self.new_named_lifetime_with_res(id, span, ident, res);
+ let l = self.new_named_lifetime_with_res(id, span, ident, res, true);
hir::GenericArg::Lifetime(l)
}));
let context = ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
};
- self.lower_ty(ty, context)
+ self.lower_ty(ty, context, true)
}
FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
};
&mut self,
tpb: &GenericBound,
itctx: ImplTraitContext,
+ captures: bool,
) -> hir::GenericBound<'hir> {
match tpb {
GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
- self.lower_poly_trait_ref(p, itctx),
+ self.lower_poly_trait_ref(p, itctx, captures),
self.lower_trait_bound_modifier(*modifier),
),
GenericBound::Outlives(lifetime) => {
- hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
+ hir::GenericBound::Outlives(self.lower_lifetime(lifetime, captures))
}
}
}
- fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
+ fn lower_lifetime(&mut self, l: &Lifetime, captures: bool) -> hir::Lifetime {
let span = self.lower_span(l.ident.span);
let ident = self.lower_ident(l.ident);
let res = self.resolver.get_lifetime_res(l.id).unwrap_or(LifetimeRes::Error);
- self.new_named_lifetime_with_res(l.id, span, ident, res)
+ self.new_named_lifetime_with_res(l.id, span, ident, res, captures)
}
#[tracing::instrument(level = "debug", skip(self))]
span: Span,
ident: Ident,
res: LifetimeRes,
+ captures: bool,
) -> hir::Lifetime {
debug!(?self.captured_lifetimes);
+
let name = match res {
LifetimeRes::Param { mut param, binder } => {
let p_name = ParamName::Plain(ident);
if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() {
- if !captured_lifetimes.binders_to_ignore.contains(&binder) {
- match captured_lifetimes.captures.entry(param) {
- Entry::Occupied(o) => param = self.local_def_id(o.get().1),
- Entry::Vacant(v) => {
- let p_id = self.next_node_id();
- let p_def_id = self.create_def(
- captured_lifetimes.parent_def_id,
- p_id,
- DefPathData::LifetimeNs(p_name.ident().name),
- );
-
- v.insert((span, p_id, p_name, res));
- param = p_def_id;
+ if captures {
+ if !captured_lifetimes.binders_to_ignore.contains(&binder) {
+ match captured_lifetimes.captures.entry(param) {
+ Entry::Occupied(o) => param = self.local_def_id(o.get().1),
+ Entry::Vacant(v) => {
+ let p_id = self.next_node_id();
+
+ let p_def_id = self.create_def(
+ captured_lifetimes.parent_def_id,
+ p_id,
+ DefPathData::LifetimeNs(p_name.ident().name),
+ );
+
+ v.insert((span, p_id, p_name, res));
+ param = p_def_id;
+ }
}
}
+ } else {
+ if let Entry::Occupied(o) = captured_lifetimes.captures.entry(param) {
+ param = self.local_def_id(o.get().1);
+ }
}
-
self.captured_lifetimes = Some(captured_lifetimes);
}
+
hir::LifetimeName::Param(param, p_name)
}
LifetimeRes::Fresh { param, binder } => {
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
+
let mut param = self.local_def_id(param);
if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() {
if !captured_lifetimes.binders_to_ignore.contains(&binder) {
Entry::Occupied(o) => param = self.local_def_id(o.get().1),
Entry::Vacant(v) => {
let p_id = self.next_node_id();
+
let p_def_id = self.create_def(
captured_lifetimes.parent_def_id,
p_id,
GenericParamKind::Type { ref default, .. } => {
let kind = hir::GenericParamKind::Type {
default: default.as_ref().map(|x| {
- self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type))
+ self.lower_ty(
+ x,
+ ImplTraitContext::Disallowed(ImplTraitPosition::Type),
+ true,
+ )
}),
synthetic: false,
};
(hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
}
GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
- let ty = self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
+ let ty =
+ self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type), true);
let default = default.as_ref().map(|def| self.lower_anon_const(def));
(
hir::ParamName::Plain(self.lower_ident(param.ident)),
}
}
- fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::TraitRef<'hir> {
- let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
+ fn lower_trait_ref(
+ &mut self,
+ p: &TraitRef,
+ itctx: ImplTraitContext,
+ captures: bool,
+ ) -> hir::TraitRef<'hir> {
+ let path = match self.lower_qpath(
+ p.ref_id,
+ &None,
+ &p.path,
+ ParamMode::Explicit,
+ itctx,
+ captures,
+ ) {
hir::QPath::Resolved(None, path) => path,
qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
};
&mut self,
p: &PolyTraitRef,
itctx: ImplTraitContext,
+ captures: bool,
) -> hir::PolyTraitRef<'hir> {
self.with_lifetime_binder(
p.trait_ref.ref_id,
&p.bound_generic_params,
|this, bound_generic_params| {
- let trait_ref = this.lower_trait_ref(&p.trait_ref, itctx);
+ let trait_ref = this.lower_trait_ref(&p.trait_ref, itctx, captures);
hir::PolyTraitRef { bound_generic_params, trait_ref, span: this.lower_span(p.span) }
},
)
}
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> {
- hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl }
+ hir::MutTy { ty: self.lower_ty(&mt.ty, itctx, true), mutbl: mt.mutbl }
}
fn lower_param_bounds(
&mut self,
bounds: &[GenericBound],
itctx: ImplTraitContext,
+ captures: bool,
) -> hir::GenericBounds<'hir> {
- self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx))
+ self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx, captures))
}
fn lower_param_bounds_mut<'s>(
&'s mut self,
bounds: &'s [GenericBound],
itctx: ImplTraitContext,
+ captures: bool,
) -> impl Iterator<Item = hir::GenericBound<'hir>> + Captures<'s> + Captures<'a> {
- bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx))
+ bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx, captures))
}
fn lower_generic_and_bounds(
// Add a definition for the in-band `Param`.
let def_id = self.local_def_id(node_id);
- let hir_bounds = self.lower_param_bounds(bounds, ImplTraitContext::Universal);
// Set the name to `impl Bound1 + Bound2`.
let param = hir::GenericParam {
hir_id: self.lower_node_id(node_id),
ident,
node_id,
&GenericParamKind::Type { default: None },
- hir_bounds,
+ bounds,
+ ImplTraitContext::Universal,
hir::PredicateOrigin::ImplTrait,
);