implement creating generics for impl traits in associated types

This commit is contained in:
dfireBird 2024-04-29 23:55:02 +05:30
parent f216be4a07
commit 40a677ddf0
No known key found for this signature in database
GPG key ID: 26D522CA5FC2B93D
6 changed files with 102 additions and 17 deletions

View file

@ -339,6 +339,7 @@ impl GenericParamsCollector {
target: Either<TypeRef, LifetimeRef>,
) {
let bound = TypeBound::from_ast(lower_ctx, bound);
self.fill_impl_trait_bounds(lower_ctx.take_impl_traits_bounds());
let predicate = match (target, bound) {
(Either::Left(type_ref), bound) => match hrtb_lifetimes {
Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
@ -359,6 +360,23 @@ impl GenericParamsCollector {
self.where_predicates.push(predicate);
}
fn fill_impl_trait_bounds(&mut self, impl_bounds: Vec<Vec<Interned<TypeBound>>>) {
for bounds in impl_bounds {
let param = TypeParamData {
name: None,
default: None,
provenance: TypeParamProvenance::ArgumentImplTrait,
};
let param_id = self.type_or_consts.alloc(param.into());
for bound in bounds {
self.where_predicates.push(WherePredicate::TypeBound {
target: WherePredicateTypeTarget::TypeOrConstParam(param_id),
bound,
});
}
}
}
pub(crate) fn fill_implicit_impl_trait_args(
&mut self,
db: &dyn DefDatabase,

View file

@ -1,26 +1,34 @@
//! Context for lowering paths.
use std::cell::OnceCell;
use std::cell::{OnceCell, RefCell};
use hir_expand::{
span_map::{SpanMap, SpanMapRef},
AstId, HirFileId, InFile,
};
use intern::Interned;
use span::{AstIdMap, AstIdNode};
use syntax::ast;
use triomphe::Arc;
use crate::{db::DefDatabase, path::Path};
use crate::{db::DefDatabase, path::Path, type_ref::TypeBound};
pub struct LowerCtx<'a> {
pub db: &'a dyn DefDatabase,
file_id: HirFileId,
span_map: OnceCell<SpanMap>,
ast_id_map: OnceCell<Arc<AstIdMap>>,
impl_trait_bounds: RefCell<Vec<Vec<Interned<TypeBound>>>>,
}
impl<'a> LowerCtx<'a> {
pub fn new(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
LowerCtx { db, file_id, span_map: OnceCell::new(), ast_id_map: OnceCell::new() }
LowerCtx {
db,
file_id,
span_map: OnceCell::new(),
ast_id_map: OnceCell::new(),
impl_trait_bounds: RefCell::new(Vec::new()),
}
}
pub fn with_span_map_cell(
@ -28,7 +36,13 @@ impl<'a> LowerCtx<'a> {
file_id: HirFileId,
span_map: OnceCell<SpanMap>,
) -> Self {
LowerCtx { db, file_id, span_map, ast_id_map: OnceCell::new() }
LowerCtx {
db,
file_id,
span_map,
ast_id_map: OnceCell::new(),
impl_trait_bounds: RefCell::new(Vec::new()),
}
}
pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
@ -45,4 +59,12 @@ impl<'a> LowerCtx<'a> {
self.ast_id_map.get_or_init(|| self.db.ast_id_map(self.file_id)).ast_id(item),
)
}
pub fn update_impl_traits_bounds(&self, bounds: Vec<Interned<TypeBound>>) {
self.impl_trait_bounds.borrow_mut().push(bounds);
}
pub fn take_impl_traits_bounds(&self) -> Vec<Vec<Interned<TypeBound>>> {
self.impl_trait_bounds.borrow_mut().drain(..).collect()
}
}

View file

@ -208,6 +208,13 @@ pub(super) fn lower_generic_args(
.and_then(|args| lower_generic_args(lower_ctx, args))
.map(Interned::new);
let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it));
let type_ref = type_ref.inspect(|tr| {
tr.walk(&mut |tr| {
if let TypeRef::ImplTrait(bounds) = tr {
lower_ctx.update_impl_traits_bounds(bounds.clone());
}
});
});
let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
l.bounds()
.map(|it| Interned::new(TypeBound::from_ast(lower_ctx, it)))

View file

@ -1,5 +1,5 @@
//! Name resolution façade.
use std::{fmt, hash::BuildHasherDefault, mem};
use std::{fmt, hash::BuildHasherDefault, iter, mem};
use base_db::CrateId;
use hir_expand::{
@ -591,13 +591,13 @@ impl Resolver {
pub fn where_predicates_in_scope(
&self,
) -> impl Iterator<Item = &crate::generics::WherePredicate> {
) -> impl Iterator<Item = (&crate::generics::WherePredicate, &GenericDefId)> {
self.scopes()
.filter_map(|scope| match scope {
Scope::GenericParams { params, .. } => Some(params),
Scope::GenericParams { params, def } => Some((params, def)),
_ => None,
})
.flat_map(|params| params.where_predicates.iter())
.flat_map(|(params, def)| params.where_predicates.iter().zip(iter::repeat(def)))
}
pub fn generic_def(&self) -> Option<GenericDefId> {