Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/expr_store/lower/generics.rs')
-rw-r--r--crates/hir-def/src/expr_store/lower/generics.rs230
1 files changed, 120 insertions, 110 deletions
diff --git a/crates/hir-def/src/expr_store/lower/generics.rs b/crates/hir-def/src/expr_store/lower/generics.rs
index 4f14a7f2d9..004bbe949f 100644
--- a/crates/hir-def/src/expr_store/lower/generics.rs
+++ b/crates/hir-def/src/expr_store/lower/generics.rs
@@ -15,73 +15,102 @@ use triomphe::Arc;
use crate::{
GenericDefId, TypeOrConstParamId, TypeParamId,
- expr_store::lower::ExprCollector,
+ expr_store::{TypePtr, lower::ExprCollector},
hir::generics::{
ConstParamData, GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamData,
- TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
+ TypeParamProvenance, WherePredicate,
},
type_ref::{LifetimeRef, TypeBound, TypeRef, TypeRefId},
};
-pub(crate) struct GenericParamsCollector<'db, 'c> {
- expr_collector: &'c mut ExprCollector<'db>,
+pub(crate) type ImplTraitLowerFn<'l> = &'l mut dyn for<'ec, 'db> FnMut(
+ &'ec mut ExprCollector<'db>,
+ TypePtr,
+ ThinVec<TypeBound>,
+) -> TypeRefId;
+
+pub(crate) struct GenericParamsCollector {
type_or_consts: Arena<TypeOrConstParamData>,
lifetimes: Arena<LifetimeParamData>,
where_predicates: Vec<WherePredicate>,
parent: GenericDefId,
}
-impl<'db, 'c> GenericParamsCollector<'db, 'c> {
- pub(crate) fn new(expr_collector: &'c mut ExprCollector<'db>, parent: GenericDefId) -> Self {
+impl GenericParamsCollector {
+ pub(crate) fn new(parent: GenericDefId) -> Self {
Self {
- expr_collector,
type_or_consts: Default::default(),
lifetimes: Default::default(),
where_predicates: Default::default(),
parent,
}
}
-
- pub(crate) fn fill_self_param(&mut self, bounds: Option<ast::TypeBoundList>) {
- let self_ = Name::new_symbol_root(sym::Self_);
- let idx = self.type_or_consts.alloc(
- TypeParamData {
- name: Some(self_.clone()),
- default: None,
- provenance: TypeParamProvenance::TraitSelf,
- }
- .into(),
- );
- let type_ref = TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
- parent: self.parent,
- local_id: idx,
- }));
- let self_ = self.expr_collector.alloc_type_ref_desugared(type_ref);
- if let Some(bounds) = bounds {
- self.lower_bounds(Some(bounds), Either::Left(self_));
- }
+ pub(crate) fn with_self_param(
+ ec: &mut ExprCollector<'_>,
+ parent: GenericDefId,
+ bounds: Option<ast::TypeBoundList>,
+ ) -> Self {
+ let mut this = Self::new(parent);
+ this.fill_self_param(ec, bounds);
+ this
}
pub(crate) fn lower(
&mut self,
+ ec: &mut ExprCollector<'_>,
generic_param_list: Option<ast::GenericParamList>,
where_clause: Option<ast::WhereClause>,
) {
if let Some(params) = generic_param_list {
- self.lower_param_list(params)
+ self.lower_param_list(ec, params)
}
if let Some(where_clause) = where_clause {
- self.lower_where_predicates(where_clause);
+ self.lower_where_predicates(ec, where_clause);
}
}
- fn lower_param_list(&mut self, params: ast::GenericParamList) {
+ pub(crate) fn collect_impl_trait<R>(
+ &mut self,
+ ec: &mut ExprCollector<'_>,
+ cb: impl FnOnce(&mut ExprCollector<'_>, ImplTraitLowerFn<'_>) -> R,
+ ) -> R {
+ cb(
+ ec,
+ &mut Self::lower_argument_impl_trait(
+ &mut self.type_or_consts,
+ &mut self.where_predicates,
+ self.parent,
+ ),
+ )
+ }
+
+ pub(crate) fn finish(self) -> Arc<GenericParams> {
+ let Self { mut lifetimes, mut type_or_consts, mut where_predicates, parent: _ } = self;
+
+ if lifetimes.is_empty() && type_or_consts.is_empty() && where_predicates.is_empty() {
+ static EMPTY: LazyLock<Arc<GenericParams>> = LazyLock::new(|| {
+ Arc::new(GenericParams {
+ lifetimes: Arena::new(),
+ type_or_consts: Arena::new(),
+ where_predicates: Box::default(),
+ })
+ });
+ return Arc::clone(&EMPTY);
+ }
+
+ lifetimes.shrink_to_fit();
+ type_or_consts.shrink_to_fit();
+ where_predicates.shrink_to_fit();
+ Arc::new(GenericParams {
+ type_or_consts,
+ lifetimes,
+ where_predicates: where_predicates.into_boxed_slice(),
+ })
+ }
+
+ fn lower_param_list(&mut self, ec: &mut ExprCollector<'_>, params: ast::GenericParamList) {
for generic_param in params.generic_params() {
- let enabled = self.expr_collector.expander.is_cfg_enabled(
- self.expr_collector.db,
- self.expr_collector.module.krate(),
- &generic_param,
- );
+ let enabled = ec.expander.is_cfg_enabled(ec.db, ec.module.krate(), &generic_param);
if !enabled {
continue;
}
@@ -89,9 +118,9 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
match generic_param {
ast::GenericParam::TypeParam(type_param) => {
let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
- let default = type_param
- .default_type()
- .map(|it| self.expr_collector.lower_type_ref(it, &mut |_| TypeRef::Error));
+ let default = type_param.default_type().map(|it| {
+ ec.lower_type_ref(it, &mut ExprCollector::impl_trait_error_allocator)
+ });
let param = TypeParamData {
name: Some(name.clone()),
default,
@@ -103,30 +132,29 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
parent: self.parent,
local_id: idx,
}));
- let type_ref = self.expr_collector.alloc_type_ref_desugared(type_ref);
- self.lower_bounds(type_param.type_bound_list(), Either::Left(type_ref));
+ let type_ref = ec.alloc_type_ref_desugared(type_ref);
+ self.lower_bounds(ec, type_param.type_bound_list(), Either::Left(type_ref));
}
ast::GenericParam::ConstParam(const_param) => {
let name = const_param.name().map_or_else(Name::missing, |it| it.as_name());
- let ty = self
- .expr_collector
- .lower_type_ref_opt(const_param.ty(), &mut |_| TypeRef::Error);
+ let ty = ec.lower_type_ref_opt(
+ const_param.ty(),
+ &mut ExprCollector::impl_trait_error_allocator,
+ );
let param = ConstParamData {
name,
ty,
- default: const_param
- .default_val()
- .map(|it| self.expr_collector.lower_const_arg(it)),
+ default: const_param.default_val().map(|it| ec.lower_const_arg(it)),
};
let _idx = self.type_or_consts.alloc(param.into());
}
ast::GenericParam::LifetimeParam(lifetime_param) => {
- let lifetime_ref =
- self.expr_collector.lower_lifetime_ref_opt(lifetime_param.lifetime());
+ let lifetime_ref = ec.lower_lifetime_ref_opt(lifetime_param.lifetime());
if let LifetimeRef::Named(name) = &lifetime_ref {
let param = LifetimeParamData { name: name.clone() };
let _idx = self.lifetimes.alloc(param);
self.lower_bounds(
+ ec,
lifetime_param.type_bound_list(),
Either::Right(lifetime_ref),
);
@@ -136,12 +164,18 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
}
}
- fn lower_where_predicates(&mut self, where_clause: ast::WhereClause) {
+ fn lower_where_predicates(
+ &mut self,
+ ec: &mut ExprCollector<'_>,
+ where_clause: ast::WhereClause,
+ ) {
for pred in where_clause.predicates() {
let target = if let Some(type_ref) = pred.ty() {
- Either::Left(self.expr_collector.lower_type_ref(type_ref, &mut |_| TypeRef::Error))
+ Either::Left(
+ ec.lower_type_ref(type_ref, &mut ExprCollector::impl_trait_error_allocator),
+ )
} else if let Some(lifetime) = pred.lifetime() {
- Either::Right(self.expr_collector.lower_lifetime_ref(lifetime))
+ Either::Right(ec.lower_lifetime_ref(lifetime))
} else {
continue;
};
@@ -158,28 +192,30 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
.collect()
});
for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
- self.lower_type_bound_as_predicate(bound, lifetimes.as_deref(), target.clone());
+ self.lower_type_bound_as_predicate(ec, bound, lifetimes.as_deref(), target.clone());
}
}
}
fn lower_bounds(
&mut self,
+ ec: &mut ExprCollector<'_>,
type_bounds: Option<ast::TypeBoundList>,
target: Either<TypeRefId, LifetimeRef>,
) {
for bound in type_bounds.iter().flat_map(|type_bound_list| type_bound_list.bounds()) {
- self.lower_type_bound_as_predicate(bound, None, target.clone());
+ self.lower_type_bound_as_predicate(ec, bound, None, target.clone());
}
}
fn lower_type_bound_as_predicate(
&mut self,
+ ec: &mut ExprCollector<'_>,
bound: ast::TypeBound,
hrtb_lifetimes: Option<&[Name]>,
target: Either<TypeRefId, LifetimeRef>,
) {
- let bound = self.expr_collector.lower_type_bound(
+ let bound = ec.lower_type_bound(
bound,
&mut Self::lower_argument_impl_trait(
&mut self.type_or_consts,
@@ -192,13 +228,10 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
(Either::Left(type_ref), bound) => match hrtb_lifetimes {
Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
lifetimes: hrtb_lifetimes.to_vec().into_boxed_slice(),
- target: WherePredicateTypeTarget::TypeRef(type_ref),
- bound,
- },
- None => WherePredicate::TypeBound {
- target: WherePredicateTypeTarget::TypeRef(type_ref),
+ target: type_ref,
bound,
},
+ None => WherePredicate::TypeBound { target: type_ref, bound },
},
(Either::Right(lifetime), TypeBound::Lifetime(bound)) => {
WherePredicate::Lifetime { target: lifetime, bound }
@@ -208,72 +241,49 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
self.where_predicates.push(predicate);
}
- pub(crate) fn collect_impl_trait<R>(
- &mut self,
- cb: impl FnOnce(&mut ExprCollector<'_>, &mut dyn FnMut(ThinVec<TypeBound>) -> TypeRef) -> R,
- ) -> R {
- cb(
- self.expr_collector,
- &mut Self::lower_argument_impl_trait(
- &mut self.type_or_consts,
- &mut self.where_predicates,
- self.parent,
- ),
- )
- }
-
fn lower_argument_impl_trait(
type_or_consts: &mut Arena<TypeOrConstParamData>,
where_predicates: &mut Vec<WherePredicate>,
parent: GenericDefId,
- ) -> impl FnMut(ThinVec<TypeBound>) -> TypeRef {
- move |impl_trait_bounds| {
+ ) -> impl for<'ec, 'db> FnMut(&'ec mut ExprCollector<'db>, TypePtr, ThinVec<TypeBound>) -> TypeRefId
+ {
+ move |ec, ptr, impl_trait_bounds| {
let param = TypeParamData {
name: None,
default: None,
provenance: TypeParamProvenance::ArgumentImplTrait,
};
- let param_id = type_or_consts.alloc(param.into());
+ let param_id = TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
+ parent,
+ local_id: type_or_consts.alloc(param.into()),
+ }));
+ let type_ref = ec.alloc_type_ref(param_id, ptr);
for bound in impl_trait_bounds {
- where_predicates.push(WherePredicate::TypeBound {
- target: WherePredicateTypeTarget::TypeOrConstParam(param_id),
- bound: bound.clone(),
- });
+ where_predicates
+ .push(WherePredicate::TypeBound { target: type_ref, bound: bound.clone() });
}
- TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
- parent,
- local_id: param_id,
- }))
+ type_ref
}
}
- pub(crate) fn finish(self) -> Arc<GenericParams> {
- let Self {
- mut lifetimes,
- mut type_or_consts,
- mut where_predicates,
- expr_collector: _,
- parent: _,
- } = self;
-
- if lifetimes.is_empty() && type_or_consts.is_empty() && where_predicates.is_empty() {
- static EMPTY: LazyLock<Arc<GenericParams>> = LazyLock::new(|| {
- Arc::new(GenericParams {
- lifetimes: Arena::new(),
- type_or_consts: Arena::new(),
- where_predicates: Box::default(),
- })
- });
- return Arc::clone(&EMPTY);
+ fn fill_self_param(&mut self, ec: &mut ExprCollector<'_>, bounds: Option<ast::TypeBoundList>) {
+ let self_ = Name::new_symbol_root(sym::Self_);
+ let idx = self.type_or_consts.alloc(
+ TypeParamData {
+ name: Some(self_.clone()),
+ default: None,
+ provenance: TypeParamProvenance::TraitSelf,
+ }
+ .into(),
+ );
+ debug_assert_eq!(idx, GenericParams::SELF_PARAM_ID_IN_SELF);
+ let type_ref = TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
+ parent: self.parent,
+ local_id: idx,
+ }));
+ let self_ = ec.alloc_type_ref_desugared(type_ref);
+ if let Some(bounds) = bounds {
+ self.lower_bounds(ec, Some(bounds), Either::Left(self_));
}
-
- lifetimes.shrink_to_fit();
- type_or_consts.shrink_to_fit();
- where_predicates.shrink_to_fit();
- Arc::new(GenericParams {
- type_or_consts,
- lifetimes,
- where_predicates: where_predicates.into_boxed_slice(),
- })
}
}