/// written at all (e.g., `&T` or `std::cell::Ref<T>`).
anonymous_lifetime_mode: AnonymousLifetimeMode,
- // This is a list of in-band type definitions being generated by
- // Argument-position `impl Trait`.
- // When traversing a signature such as `fn foo(x: impl Trait)`,
- // we record `impl Trait` as a new type parameter, then later
- // add it on to `foo`s generics.
- in_band_ty_params: Vec<hir::GenericParam>,
-
// Used to create lifetime definitions from in-band lifetime usages.
// e.g. `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8`
// When a named lifetime is encountered in a function or impl header and
) -> hir::Path;
}
-#[derive(Clone, Copy, Debug)]
-enum ImplTraitContext {
+#[derive(Debug)]
+enum ImplTraitContext<'a> {
/// Treat `impl Trait` as shorthand for a new universal generic parameter.
/// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually
/// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.
- Universal,
+ ///
+ /// Newly generated parameters should be inserted into the given `Vec`
+ Universal(&'a mut Vec<hir::GenericParam>),
/// Treat `impl Trait` as shorthand for a new universal existential parameter.
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
Disallowed,
}
+impl<'a> ImplTraitContext<'a> {
+ fn reborrow(&'b mut self) -> ImplTraitContext<'b> {
+ use self::ImplTraitContext::*;
+ match self {
+ Universal(params) => Universal(params),
+ Existential(did) => Existential(*did),
+ Disallowed => Disallowed,
+ }
+ }
+}
+
pub fn lower_crate(
sess: &Session,
cstore: &CrateStore,
node_id_to_hir_id: IndexVec::new(),
is_generator: false,
is_in_trait_impl: false,
- in_band_ty_params: Vec::new(),
lifetimes_to_define: Vec::new(),
is_collecting_in_band_lifetimes: false,
in_scope_lifetimes: Vec::new(),
f: F,
) -> (Vec<hir::GenericParam>, T)
where
- F: FnOnce(&mut LoweringContext) -> T,
+ F: FnOnce(&mut LoweringContext) -> (Vec<hir::GenericParam>, T),
{
assert!(!self.is_collecting_in_band_lifetimes);
assert!(self.lifetimes_to_define.is_empty());
self.anonymous_lifetime_mode = anonymous_lifetime_mode;
}
- assert!(self.in_band_ty_params.is_empty());
- let res = f(self);
+ let (in_band_ty_params, res) = f(self);
self.is_collecting_in_band_lifetimes = false;
self.anonymous_lifetime_mode = old_anonymous_lifetime_mode;
- let in_band_ty_params = self.in_band_ty_params.split_off(0);
let lifetimes_to_define = self.lifetimes_to_define.split_off(0);
let params = lifetimes_to_define
f: F,
) -> (hir::Generics, T)
where
- F: FnOnce(&mut LoweringContext) -> T,
+ F: FnOnce(&mut LoweringContext, &mut Vec<hir::GenericParam>) -> T,
{
let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs(
&generics.params,
|this| {
- let itctx = ImplTraitContext::Universal;
this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| {
- (this.lower_generics(generics, itctx), f(this))
+ let mut params = Vec::new();
+ let generics = this.lower_generics(
+ generics,
+ ImplTraitContext::Universal(&mut params),
+ );
+ let res = f(this, &mut params);
+ (params, (generics, res))
})
},
);
P(self.lower_ty_direct(t, itctx))
}
- fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty {
+ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext) -> hir::Ty {
let kind = match t.node {
TyKind::Infer => hir::TyInfer,
TyKind::Err => hir::TyErr,
),
TyKind::Never => hir::TyNever,
TyKind::Tup(ref tys) => {
- hir::TyTup(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx)).collect())
+ hir::TyTup(tys.iter().map(|ty| {
+ self.lower_ty_direct(ty, itctx.reborrow())
+ }).collect())
}
TyKind::Paren(ref ty) => {
return self.lower_ty_direct(ty, itctx);
.iter()
.filter_map(|bound| match *bound {
GenericBound::Trait(ref ty, TraitBoundModifier::None) => {
- Some(self.lower_poly_trait_ref(ty, itctx))
+ Some(self.lower_poly_trait_ref(ty, itctx.reborrow()))
}
GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
GenericBound::Outlives(ref lifetime) => {
|this| this.lower_param_bounds(bounds, itctx),
)
}
- ImplTraitContext::Universal => {
+ ImplTraitContext::Universal(in_band_ty_params) => {
self.lower_node_id(def_node_id);
// Add a definition for the in-band TyParam
let def_index = self
.opt_def_index(def_node_id)
.unwrap();
- let hir_bounds = self.lower_param_bounds(bounds, itctx);
+ let hir_bounds = self.lower_param_bounds(
+ bounds,
+ ImplTraitContext::Universal(in_band_ty_params),
+ );
// Set the name to `impl Bound1 + Bound2`
let ident = Ident::from_str(&pprust::ty_to_string(t)).with_span_pos(span);
- self.in_band_ty_params.push(hir::GenericParam {
+ in_band_ty_params.push(hir::GenericParam {
id: def_node_id,
name: ParamName::Plain(ident),
pure_wrt_drop: false,
qself: &Option<QSelf>,
p: &Path,
param_mode: ParamMode,
- itctx: ImplTraitContext,
+ mut itctx: ImplTraitContext,
) -> hir::QPath {
let qself_position = qself.as_ref().map(|q| q.position);
- let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
+ let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow()));
let resolution = self.resolver
.get_resolution(id)
param_mode,
num_lifetimes,
parenthesized_generic_args,
- itctx,
+ itctx.reborrow(),
)
})
.collect(),
param_mode,
0,
ParenthesizedGenericArgs::Warn,
- itctx,
+ itctx.reborrow(),
));
let qpath = hir::QPath::TypeRelative(ty, segment);
&mut self,
data: &AngleBracketedArgs,
param_mode: ParamMode,
- itctx: ImplTraitContext,
+ mut itctx: ImplTraitContext,
) -> (hir::GenericArgs, bool) {
let &AngleBracketedArgs { ref args, ref bindings, .. } = data;
let has_types = args.iter().any(|arg| match arg {
_ => false,
});
(hir::GenericArgs {
- args: args.iter().map(|a| self.lower_generic_arg(a, itctx)).collect(),
- bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx)).collect(),
+ args: args.iter().map(|a| self.lower_generic_arg(a, itctx.reborrow())).collect(),
+ bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx.reborrow())).collect(),
parenthesized: false,
},
!has_types && param_mode == ParamMode::Optional)
fn lower_fn_decl(
&mut self,
decl: &FnDecl,
- fn_def_id: Option<DefId>,
+ mut in_band_ty_params: Option<(DefId, &mut Vec<hir::GenericParam>)>,
impl_trait_return_allow: bool,
make_ret_async: Option<NodeId>,
) -> P<hir::FnDecl> {
let inputs = decl.inputs
.iter()
.map(|arg| {
- if fn_def_id.is_some() {
- self.lower_ty_direct(&arg.ty, ImplTraitContext::Universal)
+ if let Some((_, ref mut ibty)) = in_band_ty_params {
+ self.lower_ty_direct(&arg.ty, ImplTraitContext::Universal(ibty))
} else {
self.lower_ty_direct(&arg.ty, ImplTraitContext::Disallowed)
}
let output = if let Some(ret_id) = make_ret_async {
self.lower_async_fn_ret_ty(
- &inputs, &decl.output, fn_def_id.expect("make_ret_async but no fn_def_id"), ret_id)
+ &inputs,
+ &decl.output,
+ in_band_ty_params.expect("make_ret_async but no fn_def_id").0,
+ ret_id,
+ )
} else {
match decl.output {
- FunctionRetTy::Ty(ref ty) => match fn_def_id {
- Some(def_id) if impl_trait_return_allow => {
+ FunctionRetTy::Ty(ref ty) => match in_band_ty_params {
+ Some((def_id, _)) if impl_trait_return_allow => {
hir::Return(self.lower_ty(ty, ImplTraitContext::Existential(def_id)))
}
_ => hir::Return(self.lower_ty(ty, ImplTraitContext::Disallowed)),
&mut self,
params: &Vec<GenericParam>,
add_bounds: &NodeMap<Vec<GenericBound>>,
- itctx: ImplTraitContext,
+ mut itctx: ImplTraitContext,
) -> hir::HirVec<hir::GenericParam> {
- params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect()
+ params.iter().map(|param| {
+ self.lower_generic_param(param, add_bounds, itctx.reborrow())
+ }).collect()
}
fn lower_generic_param(&mut self,
param: &GenericParam,
add_bounds: &NodeMap<Vec<GenericBound>>,
- itctx: ImplTraitContext)
+ mut itctx: ImplTraitContext)
-> hir::GenericParam {
- let mut bounds = self.lower_param_bounds(¶m.bounds, itctx);
+ let mut bounds = self.lower_param_bounds(¶m.bounds, itctx.reborrow());
match param.kind {
GenericParamKind::Lifetime => {
let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
let add_bounds = add_bounds.get(¶m.id).map_or(&[][..], |x| &x);
if !add_bounds.is_empty() {
+ let params = self.lower_param_bounds(add_bounds, itctx.reborrow()).into_iter();
bounds = bounds.into_iter()
- .chain(self.lower_param_bounds(add_bounds, itctx).into_iter())
+ .chain(params)
.collect();
}
fn lower_poly_trait_ref(
&mut self,
p: &PolyTraitRef,
- itctx: ImplTraitContext,
+ mut itctx: ImplTraitContext,
) -> hir::PolyTraitRef {
let bound_generic_params =
- self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx);
+ self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx.reborrow());
let trait_ref = self.with_parent_impl_lifetime_defs(
&bound_generic_params,
|this| this.lower_trait_ref(&p.trait_ref, itctx),
}
}
- fn lower_param_bounds(&mut self, bounds: &[GenericBound], itctx: ImplTraitContext)
+ fn lower_param_bounds(&mut self, bounds: &[GenericBound], mut itctx: ImplTraitContext)
-> hir::GenericBounds {
- bounds.iter().map(|bound| self.lower_param_bound(bound, itctx)).collect()
+ bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect()
}
fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
generics,
fn_def_id,
AnonymousLifetimeMode::PassThrough,
- |this| this.lower_fn_decl(
- decl, Some(fn_def_id), true, header.asyncness.opt_return_id())
+ |this, idty| this.lower_fn_decl(
+ decl, Some((fn_def_id, idty)), true, header.asyncness.opt_return_id()),
);
hir::ItemFn(
ast_generics,
def_id,
AnonymousLifetimeMode::CreateParameter,
- |this| {
+ |this, _| {
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
this.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed)
});
generics,
def_id,
AnonymousLifetimeMode::PassThrough,
- |this| {
+ |this, _| {
(
// Disallow impl Trait in foreign items
this.lower_fn_decl(fdec, None, false, None),
generics,
fn_def_id,
AnonymousLifetimeMode::PassThrough,
- |cx| cx.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow, is_async),
+ |this, idty| this.lower_fn_decl(
+ &sig.decl,
+ Some((fn_def_id, idty)),
+ impl_trait_return_allow,
+ is_async,
+ ),
);
(generics, hir::MethodSig { header, decl })
}