Auto merge of #97598 - spastorino:simplify-universal-impl-trait-lowering, r=cjgillot
Simplify universal impl trait lowering Closes #96644 r? `@cjgillot`
This commit is contained in:
commit
42bcd41d4d
@ -83,6 +83,8 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||
task_context: None,
|
||||
current_item: None,
|
||||
captured_lifetimes: None,
|
||||
impl_trait_defs: Vec::new(),
|
||||
impl_trait_bounds: Vec::new(),
|
||||
allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
|
||||
allow_gen_future: Some([sym::gen_future][..].into()),
|
||||
allow_into_future: Some([sym::into_future][..].into()),
|
||||
@ -264,16 +266,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let body_id =
|
||||
this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref());
|
||||
|
||||
let (generics, decl) =
|
||||
this.add_implicit_generics(generics, id, |this, idty, idpb| {
|
||||
let ret_id = asyncness.opt_return_id();
|
||||
this.lower_fn_decl(
|
||||
&decl,
|
||||
Some((id, idty, idpb)),
|
||||
FnDeclKind::Fn,
|
||||
ret_id,
|
||||
)
|
||||
});
|
||||
let itctx = ImplTraitContext::Universal(this.current_hir_id_owner);
|
||||
let (generics, decl) = this.lower_generics(generics, id, itctx, |this| {
|
||||
let ret_id = asyncness.opt_return_id();
|
||||
this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, ret_id)
|
||||
});
|
||||
let sig = hir::FnSig {
|
||||
decl,
|
||||
header: this.lower_fn_header(header),
|
||||
@ -311,57 +308,59 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
//
|
||||
// type Foo = Foo1
|
||||
// opaque type Foo1: Trait
|
||||
let ty = self.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy);
|
||||
let mut generics = generics.clone();
|
||||
add_ty_alias_where_clause(&mut generics, where_clauses, true);
|
||||
let generics = self.lower_generics(
|
||||
let (generics, ty) = self.lower_generics(
|
||||
&generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy),
|
||||
);
|
||||
hir::ItemKind::TyAlias(ty, generics)
|
||||
}
|
||||
ItemKind::TyAlias(box TyAlias {
|
||||
ref generics, ref where_clauses, ty: None, ..
|
||||
}) => {
|
||||
let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
|
||||
let mut generics = generics.clone();
|
||||
add_ty_alias_where_clause(&mut generics, *where_clauses, true);
|
||||
let generics = self.lower_generics(
|
||||
let (generics, ty) = self.lower_generics(
|
||||
&generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.arena.alloc(this.ty(span, hir::TyKind::Err)),
|
||||
);
|
||||
hir::ItemKind::TyAlias(ty, generics)
|
||||
}
|
||||
ItemKind::Enum(ref enum_definition, ref generics) => hir::ItemKind::Enum(
|
||||
hir::EnumDef {
|
||||
variants: self.arena.alloc_from_iter(
|
||||
enum_definition.variants.iter().map(|x| self.lower_variant(x)),
|
||||
),
|
||||
},
|
||||
self.lower_generics(
|
||||
ItemKind::Enum(ref enum_definition, ref generics) => {
|
||||
let (generics, variants) = self.lower_generics(
|
||||
generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
),
|
||||
),
|
||||
|this| {
|
||||
this.arena.alloc_from_iter(
|
||||
enum_definition.variants.iter().map(|x| this.lower_variant(x)),
|
||||
)
|
||||
},
|
||||
);
|
||||
hir::ItemKind::Enum(hir::EnumDef { variants }, generics)
|
||||
}
|
||||
ItemKind::Struct(ref struct_def, ref generics) => {
|
||||
let struct_def = self.lower_variant_data(hir_id, struct_def);
|
||||
hir::ItemKind::Struct(
|
||||
struct_def,
|
||||
self.lower_generics(
|
||||
generics,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
),
|
||||
)
|
||||
let (generics, struct_def) = self.lower_generics(
|
||||
generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_variant_data(hir_id, struct_def),
|
||||
);
|
||||
hir::ItemKind::Struct(struct_def, generics)
|
||||
}
|
||||
ItemKind::Union(ref vdata, ref generics) => {
|
||||
let vdata = self.lower_variant_data(hir_id, vdata);
|
||||
hir::ItemKind::Union(
|
||||
vdata,
|
||||
self.lower_generics(
|
||||
generics,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
),
|
||||
)
|
||||
let (generics, vdata) = self.lower_generics(
|
||||
generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_variant_data(hir_id, vdata),
|
||||
);
|
||||
hir::ItemKind::Union(vdata, generics)
|
||||
}
|
||||
ItemKind::Impl(box Impl {
|
||||
unsafety,
|
||||
@ -386,8 +385,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// method, it will not be considered an in-band
|
||||
// lifetime to be added, but rather a reference to a
|
||||
// parent lifetime.
|
||||
let itctx = ImplTraitContext::Universal(self.current_hir_id_owner);
|
||||
let (generics, (trait_ref, lowered_ty)) =
|
||||
self.add_implicit_generics(ast_generics, id, |this, _, _| {
|
||||
self.lower_generics(ast_generics, id, itctx, |this| {
|
||||
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
|
||||
this.lower_trait_ref(
|
||||
trait_ref,
|
||||
@ -432,34 +432,38 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
ref bounds,
|
||||
ref items,
|
||||
}) => {
|
||||
let bounds = self.lower_param_bounds(
|
||||
bounds,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
);
|
||||
let items = self
|
||||
.arena
|
||||
.alloc_from_iter(items.iter().map(|item| self.lower_trait_item_ref(item)));
|
||||
hir::ItemKind::Trait(
|
||||
is_auto,
|
||||
self.lower_unsafety(unsafety),
|
||||
self.lower_generics(
|
||||
generics,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
),
|
||||
bounds,
|
||||
items,
|
||||
)
|
||||
}
|
||||
ItemKind::TraitAlias(ref generics, ref bounds) => hir::ItemKind::TraitAlias(
|
||||
self.lower_generics(
|
||||
let (generics, (unsafety, items, bounds)) = self.lower_generics(
|
||||
generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
),
|
||||
self.lower_param_bounds(
|
||||
bounds,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
),
|
||||
),
|
||||
|this| {
|
||||
let bounds = this.lower_param_bounds(
|
||||
bounds,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
);
|
||||
let items = this.arena.alloc_from_iter(
|
||||
items.iter().map(|item| this.lower_trait_item_ref(item)),
|
||||
);
|
||||
let unsafety = this.lower_unsafety(unsafety);
|
||||
(unsafety, items, bounds)
|
||||
},
|
||||
);
|
||||
hir::ItemKind::Trait(is_auto, unsafety, generics, bounds, items)
|
||||
}
|
||||
ItemKind::TraitAlias(ref generics, ref bounds) => {
|
||||
let (generics, bounds) = self.lower_generics(
|
||||
generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
this.lower_param_bounds(
|
||||
bounds,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
)
|
||||
},
|
||||
);
|
||||
hir::ItemKind::TraitAlias(generics, bounds)
|
||||
}
|
||||
ItemKind::MacroDef(MacroDef { ref body, macro_rules }) => {
|
||||
let body = P(self.lower_mac_args(body));
|
||||
let macro_kind = self.resolver.decl_macro_kind(self.resolver.local_def_id(id));
|
||||
@ -651,8 +655,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
kind: match i.kind {
|
||||
ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
|
||||
let fdec = &sig.decl;
|
||||
let itctx = ImplTraitContext::Universal(self.current_hir_id_owner);
|
||||
let (generics, (fn_dec, fn_args)) =
|
||||
self.add_implicit_generics(generics, i.id, |this, _, _| {
|
||||
self.lower_generics(generics, i.id, itctx, |this| {
|
||||
(
|
||||
// Disallow `impl Trait` in foreign items.
|
||||
this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None),
|
||||
@ -789,24 +794,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
ref ty,
|
||||
..
|
||||
}) => {
|
||||
let ty = ty.as_ref().map(|x| {
|
||||
self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type))
|
||||
});
|
||||
let mut generics = generics.clone();
|
||||
add_ty_alias_where_clause(&mut generics, where_clauses, false);
|
||||
let generics = self.lower_generics(
|
||||
self.lower_generics(
|
||||
&generics,
|
||||
i.id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
);
|
||||
let kind = hir::TraitItemKind::Type(
|
||||
self.lower_param_bounds(
|
||||
bounds,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
),
|
||||
ty,
|
||||
);
|
||||
|
||||
(generics, kind)
|
||||
|this| {
|
||||
let ty = ty.as_ref().map(|x| {
|
||||
this.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type))
|
||||
});
|
||||
hir::TraitItemKind::Type(
|
||||
this.lower_param_bounds(
|
||||
bounds,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
),
|
||||
ty,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
|
||||
};
|
||||
@ -876,21 +882,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
AssocItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
|
||||
let mut generics = generics.clone();
|
||||
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
|
||||
let generics = self.lower_generics(
|
||||
self.lower_generics(
|
||||
&generics,
|
||||
i.id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
);
|
||||
let kind = match ty {
|
||||
None => {
|
||||
let ty = self.arena.alloc(self.ty(i.span, hir::TyKind::Err));
|
||||
hir::ImplItemKind::TyAlias(ty)
|
||||
}
|
||||
Some(ty) => {
|
||||
let ty = self.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy);
|
||||
hir::ImplItemKind::TyAlias(ty)
|
||||
}
|
||||
};
|
||||
(generics, kind)
|
||||
|this| match ty {
|
||||
None => {
|
||||
let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err));
|
||||
hir::ImplItemKind::TyAlias(ty)
|
||||
}
|
||||
Some(ty) => {
|
||||
let ty = this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy);
|
||||
hir::ImplItemKind::TyAlias(ty)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
|
||||
};
|
||||
@ -1231,8 +1237,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
is_async: Option<NodeId>,
|
||||
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
||||
let header = self.lower_fn_header(sig.header);
|
||||
let (generics, decl) = self.add_implicit_generics(generics, id, |this, idty, idpb| {
|
||||
this.lower_fn_decl(&sig.decl, Some((id, idty, idpb)), kind, is_async)
|
||||
let itctx = ImplTraitContext::Universal(self.current_hir_id_owner);
|
||||
let (generics, decl) = self.lower_generics(generics, id, itctx, |this| {
|
||||
this.lower_fn_decl(&sig.decl, Some(id), kind, is_async)
|
||||
});
|
||||
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
||||
}
|
||||
@ -1289,11 +1296,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn lower_generics_mut(
|
||||
/// Return the pair of the lowered `generics` as `hir::Generics` and the evaluation of `f` with
|
||||
/// the carried impl trait definitions and bounds.
|
||||
fn lower_generics<T>(
|
||||
&mut self,
|
||||
generics: &Generics,
|
||||
mut itctx: ImplTraitContext<'_, 'hir>,
|
||||
) -> GenericsCtor<'hir> {
|
||||
parent_node_id: NodeId,
|
||||
itctx: ImplTraitContext,
|
||||
f: impl FnOnce(&mut Self) -> T,
|
||||
) -> (&'hir hir::Generics<'hir>, T) {
|
||||
debug_assert!(self.impl_trait_defs.is_empty());
|
||||
debug_assert!(self.impl_trait_bounds.is_empty());
|
||||
|
||||
// Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
|
||||
// Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
|
||||
// these into hir when we lower thee where clauses), but this makes it quite difficult to
|
||||
@ -1341,9 +1355,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
let mut predicates = SmallVec::new();
|
||||
let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
|
||||
predicates.extend(generics.params.iter().filter_map(|param| {
|
||||
let bounds = self.lower_param_bounds(¶m.bounds, itctx.reborrow());
|
||||
let bounds = self.lower_param_bounds(¶m.bounds, itctx);
|
||||
self.lower_generic_bound_predicate(
|
||||
param.ident,
|
||||
param.id,
|
||||
@ -1360,22 +1374,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
.map(|predicate| self.lower_where_predicate(predicate)),
|
||||
);
|
||||
|
||||
GenericsCtor {
|
||||
params: self.lower_generic_params_mut(&generics.params).collect(),
|
||||
predicates,
|
||||
has_where_clause: !generics.where_clause.predicates.is_empty(),
|
||||
where_clause_span: self.lower_span(generics.where_clause.span),
|
||||
span: self.lower_span(generics.span),
|
||||
}
|
||||
}
|
||||
let mut params: Vec<_> = self.lower_generic_params_mut(&generics.params).collect();
|
||||
let has_where_clause = !generics.where_clause.predicates.is_empty();
|
||||
let where_clause_span = self.lower_span(generics.where_clause.span);
|
||||
let span = self.lower_span(generics.span);
|
||||
let res = f(self);
|
||||
|
||||
pub(super) fn lower_generics(
|
||||
&mut self,
|
||||
generics: &Generics,
|
||||
itctx: ImplTraitContext<'_, 'hir>,
|
||||
) -> &'hir hir::Generics<'hir> {
|
||||
let generics_ctor = self.lower_generics_mut(generics, itctx);
|
||||
generics_ctor.into_generics(self.arena)
|
||||
let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
|
||||
let impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
|
||||
params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
|
||||
self.lifetime_res_to_generic_param(ident, node_id, res)
|
||||
}));
|
||||
params.extend(impl_trait_defs.into_iter());
|
||||
|
||||
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
|
||||
predicates.extend(impl_trait_bounds.into_iter());
|
||||
|
||||
let lowered_generics = self.arena.alloc(hir::Generics {
|
||||
params: self.arena.alloc_from_iter(params),
|
||||
predicates: self.arena.alloc_from_iter(predicates),
|
||||
has_where_clause,
|
||||
where_clause_span,
|
||||
span,
|
||||
});
|
||||
|
||||
(lowered_generics, res)
|
||||
}
|
||||
|
||||
pub(super) fn lower_generic_bound_predicate(
|
||||
@ -1491,24 +1514,3 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper struct for delayed construction of Generics.
|
||||
pub(super) struct GenericsCtor<'hir> {
|
||||
pub(super) params: SmallVec<[hir::GenericParam<'hir>; 4]>,
|
||||
pub(super) predicates: SmallVec<[hir::WherePredicate<'hir>; 4]>,
|
||||
has_where_clause: bool,
|
||||
where_clause_span: Span,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
impl<'hir> GenericsCtor<'hir> {
|
||||
pub(super) fn into_generics(self, arena: &'hir Arena<'hir>) -> &'hir hir::Generics<'hir> {
|
||||
arena.alloc(hir::Generics {
|
||||
params: arena.alloc_from_iter(self.params),
|
||||
predicates: arena.alloc_from_iter(self.predicates),
|
||||
has_where_clause: self.has_where_clause,
|
||||
where_clause_span: self.where_clause_span,
|
||||
span: self.span,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +121,9 @@ struct LoweringContext<'a, 'hir: 'a> {
|
||||
local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>,
|
||||
trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>,
|
||||
|
||||
impl_trait_defs: Vec<hir::GenericParam<'hir>>,
|
||||
impl_trait_bounds: Vec<hir::WherePredicate<'hir>>,
|
||||
|
||||
/// NodeIds that are lowered inside the current HIR owner.
|
||||
node_id_to_local_id: FxHashMap<NodeId, hir::ItemLocalId>,
|
||||
|
||||
@ -243,14 +246,14 @@ pub trait ResolverAstLowering {
|
||||
|
||||
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
|
||||
/// and if so, what meaning it has.
|
||||
#[derive(Debug)]
|
||||
enum ImplTraitContext<'b, 'a> {
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
enum ImplTraitContext {
|
||||
/// 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)`.
|
||||
///
|
||||
/// Newly generated parameters should be inserted into the given `Vec`.
|
||||
Universal(&'b mut Vec<hir::GenericParam<'a>>, &'b mut Vec<hir::WherePredicate<'a>>, LocalDefId),
|
||||
Universal(LocalDefId),
|
||||
|
||||
/// Treat `impl Trait` as shorthand for a new opaque type.
|
||||
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
|
||||
@ -290,18 +293,6 @@ enum ImplTraitPosition {
|
||||
ImplReturn,
|
||||
}
|
||||
|
||||
impl<'a> ImplTraitContext<'_, 'a> {
|
||||
fn reborrow<'this>(&'this mut self) -> ImplTraitContext<'this, 'a> {
|
||||
use self::ImplTraitContext::*;
|
||||
match self {
|
||||
Universal(params, bounds, parent) => Universal(params, bounds, *parent),
|
||||
ReturnPositionOpaqueTy { origin } => ReturnPositionOpaqueTy { origin: *origin },
|
||||
TypeAliasesOpaqueTy => TypeAliasesOpaqueTy,
|
||||
Disallowed(pos) => Disallowed(*pos),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ImplTraitPosition {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let name = match self {
|
||||
@ -479,6 +470,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id);
|
||||
let current_local_counter =
|
||||
std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));
|
||||
let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
|
||||
let current_impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
|
||||
|
||||
// Always allocate the first `HirId` for the owner itself.
|
||||
let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::new(0));
|
||||
@ -486,6 +479,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
let item = f(self);
|
||||
debug_assert_eq!(def_id, item.def_id());
|
||||
// `f` should have consumed all the elements in these vectors when constructing `item`.
|
||||
debug_assert!(self.impl_trait_defs.is_empty());
|
||||
debug_assert!(self.impl_trait_bounds.is_empty());
|
||||
let info = self.make_owner_info(item);
|
||||
|
||||
self.attrs = current_attrs;
|
||||
@ -495,6 +491,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
self.trait_map = current_trait_map;
|
||||
self.current_hir_id_owner = current_owner;
|
||||
self.item_local_id_counter = current_local_counter;
|
||||
self.impl_trait_defs = current_impl_trait_defs;
|
||||
self.impl_trait_bounds = current_impl_trait_bounds;
|
||||
|
||||
let _old = self.children.insert(def_id, hir::MaybeOwner::Owner(info));
|
||||
debug_assert!(_old.is_none())
|
||||
@ -694,46 +692,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new `hir::GenericParam` for every new `Fresh` lifetime and
|
||||
/// universal `impl Trait` type parameter encountered while evaluating `f`.
|
||||
/// Definitions are created with the provided `parent_def_id`.
|
||||
fn add_implicit_generics<T>(
|
||||
&mut self,
|
||||
generics: &Generics,
|
||||
parent_node_id: NodeId,
|
||||
f: impl FnOnce(
|
||||
&mut Self,
|
||||
&mut Vec<hir::GenericParam<'hir>>,
|
||||
&mut Vec<hir::WherePredicate<'hir>>,
|
||||
) -> T,
|
||||
) -> (&'hir hir::Generics<'hir>, T) {
|
||||
let mut impl_trait_defs = Vec::new();
|
||||
let mut impl_trait_bounds = Vec::new();
|
||||
let mut lowered_generics = self.lower_generics_mut(
|
||||
generics,
|
||||
ImplTraitContext::Universal(
|
||||
&mut impl_trait_defs,
|
||||
&mut impl_trait_bounds,
|
||||
self.current_hir_id_owner,
|
||||
),
|
||||
);
|
||||
let res = f(self, &mut impl_trait_defs, &mut impl_trait_bounds);
|
||||
|
||||
let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
|
||||
lowered_generics.params.extend(
|
||||
extra_lifetimes
|
||||
.into_iter()
|
||||
.filter_map(|(ident, node_id, res)| {
|
||||
self.lifetime_res_to_generic_param(ident, node_id, res)
|
||||
})
|
||||
.chain(impl_trait_defs),
|
||||
);
|
||||
lowered_generics.predicates.extend(impl_trait_bounds);
|
||||
|
||||
let lowered_generics = lowered_generics.into_generics(self.arena);
|
||||
(lowered_generics, res)
|
||||
}
|
||||
|
||||
/// Setup lifetime capture for and impl-trait.
|
||||
/// The captures will be added to `captures`.
|
||||
fn while_capturing_lifetimes<T>(
|
||||
@ -898,7 +856,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
fn lower_assoc_ty_constraint(
|
||||
&mut self,
|
||||
constraint: &AssocConstraint,
|
||||
mut itctx: ImplTraitContext<'_, 'hir>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::TypeBinding<'hir> {
|
||||
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
|
||||
|
||||
@ -906,12 +864,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let gen_args = if let Some(ref gen_args) = constraint.gen_args {
|
||||
let gen_args_ctor = match gen_args {
|
||||
GenericArgs::AngleBracketed(ref data) => {
|
||||
self.lower_angle_bracketed_parameter_data(
|
||||
data,
|
||||
ParamMode::Explicit,
|
||||
itctx.reborrow(),
|
||||
)
|
||||
.0
|
||||
self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
|
||||
}
|
||||
GenericArgs::Parenthesized(ref data) => {
|
||||
let mut err = self.sess.struct_span_err(
|
||||
@ -923,7 +876,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
self.lower_angle_bracketed_parameter_data(
|
||||
&data.as_angle_bracketed_args(),
|
||||
ParamMode::Explicit,
|
||||
itctx.reborrow(),
|
||||
itctx,
|
||||
)
|
||||
.0
|
||||
}
|
||||
@ -962,7 +915,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
// so desugar to
|
||||
//
|
||||
// fn foo(x: dyn Iterator<Item = impl Debug>)
|
||||
ImplTraitContext::Universal(_, _, parent) if self.is_in_dyn_type => {
|
||||
ImplTraitContext::Universal(parent) if self.is_in_dyn_type => {
|
||||
parent_def_id = parent;
|
||||
(true, itctx)
|
||||
}
|
||||
@ -1036,7 +989,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
fn lower_generic_arg(
|
||||
&mut self,
|
||||
arg: &ast::GenericArg,
|
||||
itctx: ImplTraitContext<'_, 'hir>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::GenericArg<'hir> {
|
||||
match arg {
|
||||
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)),
|
||||
@ -1103,7 +1056,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext<'_, 'hir>) -> &'hir hir::Ty<'hir> {
|
||||
fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> {
|
||||
self.arena.alloc(self.lower_ty_direct(t, itctx))
|
||||
}
|
||||
|
||||
@ -1113,7 +1066,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
qself: &Option<QSelf>,
|
||||
path: &Path,
|
||||
param_mode: ParamMode,
|
||||
itctx: ImplTraitContext<'_, 'hir>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::Ty<'hir> {
|
||||
let id = self.lower_node_id(t.id);
|
||||
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
|
||||
@ -1128,7 +1081,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
self.ty(span, hir::TyKind::Tup(tys))
|
||||
}
|
||||
|
||||
fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) -> hir::Ty<'hir> {
|
||||
fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> {
|
||||
let kind = match t.kind {
|
||||
TyKind::Infer => hir::TyKind::Infer,
|
||||
TyKind::Err => hir::TyKind::Err,
|
||||
@ -1160,11 +1113,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
}))
|
||||
}),
|
||||
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.reborrow())),
|
||||
))
|
||||
}
|
||||
TyKind::Tup(ref tys) => hir::TyKind::Tup(
|
||||
self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))),
|
||||
),
|
||||
TyKind::Paren(ref ty) => {
|
||||
return self.lower_ty_direct(ty, itctx);
|
||||
}
|
||||
@ -1198,7 +1149,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
GenericBound::Trait(
|
||||
ref ty,
|
||||
TraitBoundModifier::None | TraitBoundModifier::MaybeConst,
|
||||
) => Some(this.lower_poly_trait_ref(ty, itctx.reborrow())),
|
||||
) => Some(this.lower_poly_trait_ref(ty, itctx)),
|
||||
// `~const ?Bound` will cause an error during AST validation
|
||||
// anyways, so treat it like `?Bound` as compilation proceeds.
|
||||
GenericBound::Trait(
|
||||
@ -1235,32 +1186,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|this| this.lower_param_bounds(bounds, nested_itctx),
|
||||
)
|
||||
}
|
||||
ImplTraitContext::Universal(
|
||||
in_band_ty_params,
|
||||
in_band_ty_bounds,
|
||||
parent_def_id,
|
||||
) => {
|
||||
ImplTraitContext::Universal(parent_def_id) => {
|
||||
// Add a definition for the in-band `Param`.
|
||||
let def_id = self.resolver.local_def_id(def_node_id);
|
||||
|
||||
let hir_bounds = self.lower_param_bounds(
|
||||
bounds,
|
||||
ImplTraitContext::Universal(
|
||||
in_band_ty_params,
|
||||
in_band_ty_bounds,
|
||||
parent_def_id,
|
||||
),
|
||||
);
|
||||
let hir_bounds = self
|
||||
.lower_param_bounds(bounds, ImplTraitContext::Universal(parent_def_id));
|
||||
// Set the name to `impl Bound1 + Bound2`.
|
||||
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
|
||||
in_band_ty_params.push(hir::GenericParam {
|
||||
let param = hir::GenericParam {
|
||||
hir_id: self.lower_node_id(def_node_id),
|
||||
name: ParamName::Plain(self.lower_ident(ident)),
|
||||
pure_wrt_drop: false,
|
||||
span: self.lower_span(span),
|
||||
kind: hir::GenericParamKind::Type { default: None, synthetic: true },
|
||||
colon_span: None,
|
||||
});
|
||||
};
|
||||
self.impl_trait_defs.push(param);
|
||||
|
||||
if let Some(preds) = self.lower_generic_bound_predicate(
|
||||
ident,
|
||||
def_node_id,
|
||||
@ -1268,7 +1211,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
hir_bounds,
|
||||
hir::PredicateOrigin::ImplTrait,
|
||||
) {
|
||||
in_band_ty_bounds.push(preds)
|
||||
self.impl_trait_bounds.push(preds)
|
||||
}
|
||||
|
||||
hir::TyKind::Path(hir::QPath::Resolved(
|
||||
@ -1439,26 +1382,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
// `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the
|
||||
// return type. This is used for `async fn` declarations. The `NodeId` is the ID of the
|
||||
// return type `impl Trait` item.
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
fn lower_fn_decl(
|
||||
&mut self,
|
||||
decl: &FnDecl,
|
||||
mut in_band_ty_params: Option<(
|
||||
NodeId,
|
||||
&mut Vec<hir::GenericParam<'hir>>,
|
||||
&mut Vec<hir::WherePredicate<'hir>>,
|
||||
)>,
|
||||
fn_node_id: Option<NodeId>,
|
||||
kind: FnDeclKind,
|
||||
make_ret_async: Option<NodeId>,
|
||||
) -> &'hir hir::FnDecl<'hir> {
|
||||
debug!(
|
||||
"lower_fn_decl(\
|
||||
fn_decl: {:?}, \
|
||||
in_band_ty_params: {:?}, \
|
||||
kind: {:?}, \
|
||||
make_ret_async: {:?})",
|
||||
decl, in_band_ty_params, kind, make_ret_async,
|
||||
);
|
||||
|
||||
let c_variadic = decl.c_variadic();
|
||||
|
||||
// Skip the `...` (`CVarArgs`) trailing arguments from the AST,
|
||||
@ -1469,10 +1400,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
inputs = &inputs[..inputs.len() - 1];
|
||||
}
|
||||
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
|
||||
if let Some((_, ibty, ibpb)) = &mut in_band_ty_params {
|
||||
if fn_node_id.is_some() {
|
||||
self.lower_ty_direct(
|
||||
¶m.ty,
|
||||
ImplTraitContext::Universal(ibty, ibpb, self.current_hir_id_owner),
|
||||
ImplTraitContext::Universal(self.current_hir_id_owner),
|
||||
)
|
||||
} else {
|
||||
self.lower_ty_direct(
|
||||
@ -1494,15 +1425,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let output = if let Some(ret_id) = make_ret_async {
|
||||
self.lower_async_fn_ret_ty(
|
||||
&decl.output,
|
||||
in_band_ty_params.expect("`make_ret_async` but no `fn_def_id`").0,
|
||||
fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
|
||||
ret_id,
|
||||
)
|
||||
} else {
|
||||
match decl.output {
|
||||
FnRetTy::Ty(ref ty) => {
|
||||
let context = match in_band_ty_params {
|
||||
Some((node_id, _, _)) if kind.impl_trait_return_allowed() => {
|
||||
let fn_def_id = self.resolver.local_def_id(node_id);
|
||||
let context = match fn_node_id {
|
||||
Some(fn_node_id) if kind.impl_trait_return_allowed() => {
|
||||
let fn_def_id = self.resolver.local_def_id(fn_node_id);
|
||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||
}
|
||||
@ -1788,7 +1719,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
fn lower_param_bound(
|
||||
&mut self,
|
||||
tpb: &GenericBound,
|
||||
itctx: ImplTraitContext<'_, 'hir>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::GenericBound<'hir> {
|
||||
match tpb {
|
||||
GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
|
||||
@ -1966,11 +1897,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_trait_ref(
|
||||
&mut self,
|
||||
p: &TraitRef,
|
||||
itctx: ImplTraitContext<'_, 'hir>,
|
||||
) -> hir::TraitRef<'hir> {
|
||||
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) {
|
||||
hir::QPath::Resolved(None, path) => path,
|
||||
qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
|
||||
@ -1982,25 +1909,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
fn lower_poly_trait_ref(
|
||||
&mut self,
|
||||
p: &PolyTraitRef,
|
||||
mut itctx: ImplTraitContext<'_, 'hir>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::PolyTraitRef<'hir> {
|
||||
let bound_generic_params = self.lower_generic_params(&p.bound_generic_params);
|
||||
|
||||
let trait_ref = self.with_lifetime_binder(p.trait_ref.ref_id, |this| {
|
||||
this.lower_trait_ref(&p.trait_ref, itctx.reborrow())
|
||||
this.lower_trait_ref(&p.trait_ref, itctx)
|
||||
});
|
||||
|
||||
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
|
||||
}
|
||||
|
||||
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext<'_, 'hir>) -> hir::MutTy<'hir> {
|
||||
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> {
|
||||
hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl }
|
||||
}
|
||||
|
||||
fn lower_param_bounds(
|
||||
&mut self,
|
||||
bounds: &[GenericBound],
|
||||
itctx: ImplTraitContext<'_, 'hir>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::GenericBounds<'hir> {
|
||||
self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx))
|
||||
}
|
||||
@ -2008,9 +1935,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
fn lower_param_bounds_mut<'s>(
|
||||
&'s mut self,
|
||||
bounds: &'s [GenericBound],
|
||||
mut itctx: ImplTraitContext<'s, 'hir>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> impl Iterator<Item = hir::GenericBound<'hir>> + Captures<'s> + Captures<'a> {
|
||||
bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx.reborrow()))
|
||||
bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx))
|
||||
}
|
||||
|
||||
/// Lowers a block directly to an expression, presuming that it
|
||||
|
@ -21,11 +21,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
qself: &Option<QSelf>,
|
||||
p: &Path,
|
||||
param_mode: ParamMode,
|
||||
mut itctx: ImplTraitContext<'_, 'hir>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::QPath<'hir> {
|
||||
debug!("lower_qpath(id: {:?}, qself: {:?}, p: {:?})", id, qself, p);
|
||||
let qself_position = qself.as_ref().map(|q| q.position);
|
||||
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow()));
|
||||
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
|
||||
|
||||
let partial_res =
|
||||
self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
|
||||
@ -70,7 +70,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
segment,
|
||||
param_mode,
|
||||
parenthesized_generic_args,
|
||||
itctx.reborrow(),
|
||||
itctx,
|
||||
)
|
||||
},
|
||||
)),
|
||||
@ -116,7 +116,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
segment,
|
||||
param_mode,
|
||||
ParenthesizedGenericArgs::Err,
|
||||
itctx.reborrow(),
|
||||
itctx,
|
||||
));
|
||||
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
|
||||
|
||||
@ -180,7 +180,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
segment: &PathSegment,
|
||||
param_mode: ParamMode,
|
||||
parenthesized_generic_args: ParenthesizedGenericArgs,
|
||||
itctx: ImplTraitContext<'_, 'hir>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::PathSegment<'hir> {
|
||||
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,);
|
||||
let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
|
||||
@ -318,7 +318,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
&mut self,
|
||||
data: &AngleBracketedArgs,
|
||||
param_mode: ParamMode,
|
||||
mut itctx: ImplTraitContext<'_, 'hir>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> (GenericArgsCtor<'hir>, bool) {
|
||||
let has_non_lt_args = data.args.iter().any(|arg| match arg {
|
||||
AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_))
|
||||
@ -329,14 +329,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
.args
|
||||
.iter()
|
||||
.filter_map(|arg| match arg {
|
||||
AngleBracketedArg::Arg(arg) => Some(self.lower_generic_arg(arg, itctx.reborrow())),
|
||||
AngleBracketedArg::Arg(arg) => Some(self.lower_generic_arg(arg, itctx)),
|
||||
AngleBracketedArg::Constraint(_) => None,
|
||||
})
|
||||
.collect();
|
||||
let bindings = self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg {
|
||||
AngleBracketedArg::Constraint(c) => {
|
||||
Some(self.lower_assoc_ty_constraint(c, itctx.reborrow()))
|
||||
}
|
||||
AngleBracketedArg::Constraint(c) => Some(self.lower_assoc_ty_constraint(c, itctx)),
|
||||
AngleBracketedArg::Arg(_) => None,
|
||||
}));
|
||||
let ctor = GenericArgsCtor { args, bindings, parenthesized: false, span: data.span };
|
||||
|
Loading…
x
Reference in New Issue
Block a user