Lower generics
This commit is contained in:
parent
864b650f92
commit
c12f7b610b
crates/ra_hir_def/src
@ -42,7 +42,7 @@ pub enum TypeParamProvenance {
|
||||
}
|
||||
|
||||
/// Data about the generic parameters of a function, struct, impl, etc.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Default)]
|
||||
pub struct GenericParams {
|
||||
pub types: Arena<TypeParamData>,
|
||||
// lifetimes: Arena<LocalLifetimeParamId, LifetimeParamData>,
|
||||
@ -156,7 +156,12 @@ impl GenericParams {
|
||||
(generics, InFile::new(file_id, sm))
|
||||
}
|
||||
|
||||
fn fill(&mut self, lower_ctx: &LowerCtx, sm: &mut SourceMap, node: &dyn TypeParamsOwner) {
|
||||
pub(crate) fn fill(
|
||||
&mut self,
|
||||
lower_ctx: &LowerCtx,
|
||||
sm: &mut SourceMap,
|
||||
node: &dyn TypeParamsOwner,
|
||||
) {
|
||||
if let Some(params) = node.type_param_list() {
|
||||
self.fill_params(lower_ctx, sm, params)
|
||||
}
|
||||
@ -165,7 +170,7 @@ impl GenericParams {
|
||||
}
|
||||
}
|
||||
|
||||
fn fill_bounds(
|
||||
pub(crate) fn fill_bounds(
|
||||
&mut self,
|
||||
lower_ctx: &LowerCtx,
|
||||
node: &dyn ast::TypeBoundsOwner,
|
||||
@ -229,7 +234,7 @@ impl GenericParams {
|
||||
.push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound });
|
||||
}
|
||||
|
||||
fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) {
|
||||
pub(crate) fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) {
|
||||
type_ref.walk(&mut |type_ref| {
|
||||
if let TypeRef::ImplTrait(bounds) = type_ref {
|
||||
let param = TypeParamData {
|
||||
|
@ -26,7 +26,7 @@ use test_utils::mark;
|
||||
use crate::{
|
||||
attr::Attrs,
|
||||
db::DefDatabase,
|
||||
generics,
|
||||
generics::GenericParams,
|
||||
path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path},
|
||||
type_ref::{Mutability, TypeBound, TypeRef},
|
||||
visibility::RawVisibility,
|
||||
@ -230,7 +230,7 @@ pub struct Function {
|
||||
pub name: Name,
|
||||
pub attrs: Attrs,
|
||||
pub visibility: RawVisibility,
|
||||
pub generic_params: generics::GenericParams,
|
||||
pub generic_params: GenericParams,
|
||||
pub has_self_param: bool,
|
||||
pub params: Vec<TypeRef>,
|
||||
pub ret_type: TypeRef,
|
||||
@ -243,7 +243,7 @@ pub struct Struct {
|
||||
pub name: Name,
|
||||
pub attrs: Attrs,
|
||||
pub visibility: RawVisibility,
|
||||
pub generic_params: generics::GenericParams,
|
||||
pub generic_params: GenericParams,
|
||||
pub fields: Fields,
|
||||
pub ast_id: FileAstId<ast::StructDef>,
|
||||
pub kind: StructDefKind,
|
||||
@ -264,7 +264,7 @@ pub struct Union {
|
||||
pub name: Name,
|
||||
pub attrs: Attrs,
|
||||
pub visibility: RawVisibility,
|
||||
pub generic_params: generics::GenericParams,
|
||||
pub generic_params: GenericParams,
|
||||
pub fields: Fields,
|
||||
pub ast_id: FileAstId<ast::UnionDef>,
|
||||
}
|
||||
@ -274,7 +274,7 @@ pub struct Enum {
|
||||
pub name: Name,
|
||||
pub attrs: Attrs,
|
||||
pub visibility: RawVisibility,
|
||||
pub generic_params: generics::GenericParams,
|
||||
pub generic_params: GenericParams,
|
||||
pub variants: Range<Idx<Variant>>,
|
||||
pub ast_id: FileAstId<ast::EnumDef>,
|
||||
}
|
||||
@ -300,7 +300,7 @@ pub struct Static {
|
||||
pub struct Trait {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibility,
|
||||
pub generic_params: generics::GenericParams,
|
||||
pub generic_params: GenericParams,
|
||||
pub auto: bool,
|
||||
pub items: Vec<AssocItem>,
|
||||
pub ast_id: FileAstId<ast::TraitDef>,
|
||||
@ -308,7 +308,7 @@ pub struct Trait {
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Impl {
|
||||
pub generic_params: generics::GenericParams,
|
||||
pub generic_params: GenericParams,
|
||||
pub target_trait: Option<TypeRef>,
|
||||
pub target_type: TypeRef,
|
||||
pub is_negative: bool,
|
||||
@ -320,7 +320,7 @@ pub struct Impl {
|
||||
pub struct TypeAlias {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibility,
|
||||
pub generic_params: generics::GenericParams,
|
||||
pub generic_params: GenericParams,
|
||||
pub type_ref: Option<TypeRef>,
|
||||
pub ast_id: FileAstId<ast::TypeAliasDef>,
|
||||
}
|
||||
|
@ -1,6 +1,12 @@
|
||||
//! AST -> `ItemTree` lowering code.
|
||||
|
||||
use super::*;
|
||||
use crate::attr::Attrs;
|
||||
use crate::{
|
||||
attr::Attrs,
|
||||
generics::{GenericParams, TypeParamData, TypeParamProvenance},
|
||||
};
|
||||
use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId};
|
||||
use ra_arena::map::ArenaMap;
|
||||
use ra_syntax::ast::{self, ModuleItemOwner};
|
||||
use smallvec::SmallVec;
|
||||
use std::sync::Arc;
|
||||
@ -123,7 +129,7 @@ impl Ctx {
|
||||
let attrs = self.lower_attrs(strukt);
|
||||
let visibility = self.lower_visibility(strukt);
|
||||
let name = strukt.name()?.as_name();
|
||||
let generic_params = self.lower_generic_params(strukt);
|
||||
let generic_params = self.lower_generic_params(GenericsOwner::Struct, strukt);
|
||||
let fields = self.lower_fields(&strukt.kind());
|
||||
let ast_id = self.source_ast_id_map.ast_id(strukt);
|
||||
let kind = match strukt.kind() {
|
||||
@ -191,7 +197,7 @@ impl Ctx {
|
||||
let attrs = self.lower_attrs(union);
|
||||
let visibility = self.lower_visibility(union);
|
||||
let name = union.name()?.as_name();
|
||||
let generic_params = self.lower_generic_params(union);
|
||||
let generic_params = self.lower_generic_params(GenericsOwner::Union, union);
|
||||
let fields = match union.record_field_def_list() {
|
||||
Some(record_field_def_list) => {
|
||||
self.lower_fields(&StructKind::Record(record_field_def_list))
|
||||
@ -207,7 +213,7 @@ impl Ctx {
|
||||
let attrs = self.lower_attrs(enum_);
|
||||
let visibility = self.lower_visibility(enum_);
|
||||
let name = enum_.name()?.as_name();
|
||||
let generic_params = self.lower_generic_params(enum_);
|
||||
let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_);
|
||||
let variants = match &enum_.variant_list() {
|
||||
Some(variant_list) => self.lower_variants(variant_list),
|
||||
None => self.next_variant_idx()..self.next_variant_idx(),
|
||||
@ -239,7 +245,6 @@ impl Ctx {
|
||||
let attrs = self.lower_attrs(func);
|
||||
let visibility = self.lower_visibility(func);
|
||||
let name = func.name()?.as_name();
|
||||
let generic_params = self.lower_generic_params(func);
|
||||
|
||||
let mut params = Vec::new();
|
||||
let mut has_self_param = false;
|
||||
@ -281,16 +286,17 @@ impl Ctx {
|
||||
};
|
||||
|
||||
let ast_id = self.source_ast_id_map.ast_id(func);
|
||||
let res = Function {
|
||||
let mut res = Function {
|
||||
name,
|
||||
attrs,
|
||||
visibility,
|
||||
generic_params,
|
||||
generic_params: GenericParams::default(),
|
||||
has_self_param,
|
||||
params,
|
||||
ret_type,
|
||||
ast_id,
|
||||
};
|
||||
res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func);
|
||||
Some(res)
|
||||
}
|
||||
|
||||
@ -298,7 +304,7 @@ impl Ctx {
|
||||
let name = type_alias.name()?.as_name();
|
||||
let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it));
|
||||
let visibility = self.lower_visibility(type_alias);
|
||||
let generic_params = self.lower_generic_params(type_alias);
|
||||
let generic_params = self.lower_generic_params(GenericsOwner::TypeAlias, type_alias);
|
||||
let ast_id = self.source_ast_id_map.ast_id(type_alias);
|
||||
let res = TypeAlias { name, visibility, generic_params, type_ref, ast_id };
|
||||
Some(res)
|
||||
@ -349,7 +355,7 @@ impl Ctx {
|
||||
fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<Trait> {
|
||||
let name = trait_def.name()?.as_name();
|
||||
let visibility = self.lower_visibility(trait_def);
|
||||
let generic_params = self.lower_generic_params(trait_def);
|
||||
let generic_params = self.lower_generic_params(GenericsOwner::Trait(trait_def), trait_def);
|
||||
let auto = trait_def.auto_token().is_some();
|
||||
let items = trait_def.item_list().map(|list| {
|
||||
// FIXME: Does not handle macros
|
||||
@ -367,7 +373,7 @@ impl Ctx {
|
||||
}
|
||||
|
||||
fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option<Impl> {
|
||||
let generic_params = self.lower_generic_params(impl_def);
|
||||
let generic_params = self.lower_generic_params(GenericsOwner::Impl, impl_def);
|
||||
let target_trait = impl_def.target_trait().map(|tr| self.lower_type_ref(&tr));
|
||||
let target_type = self.lower_type_ref(&impl_def.target_type()?);
|
||||
let is_negative = impl_def.excl_token().is_some();
|
||||
@ -465,10 +471,43 @@ impl Ctx {
|
||||
|
||||
fn lower_generic_params(
|
||||
&mut self,
|
||||
_item: &impl ast::TypeParamsOwner,
|
||||
) -> generics::GenericParams {
|
||||
// TODO
|
||||
generics::GenericParams { types: Arena::new(), where_predicates: Vec::new() }
|
||||
owner: GenericsOwner<'_>,
|
||||
node: &impl ast::TypeParamsOwner,
|
||||
) -> GenericParams {
|
||||
let mut sm = &mut ArenaMap::default();
|
||||
let mut generics = GenericParams::default();
|
||||
match owner {
|
||||
GenericsOwner::Function(func) => {
|
||||
generics.fill(&self.body_ctx, sm, node);
|
||||
// lower `impl Trait` in arguments
|
||||
for param in &func.params {
|
||||
generics.fill_implicit_impl_trait_args(param);
|
||||
}
|
||||
}
|
||||
GenericsOwner::Struct
|
||||
| GenericsOwner::Enum
|
||||
| GenericsOwner::Union
|
||||
| GenericsOwner::TypeAlias => {
|
||||
generics.fill(&self.body_ctx, sm, node);
|
||||
}
|
||||
GenericsOwner::Trait(trait_def) => {
|
||||
// traits get the Self type as an implicit first type parameter
|
||||
let self_param_id = generics.types.alloc(TypeParamData {
|
||||
name: Some(name![Self]),
|
||||
default: None,
|
||||
provenance: TypeParamProvenance::TraitSelf,
|
||||
});
|
||||
sm.insert(self_param_id, Either::Left(trait_def.clone()));
|
||||
// add super traits as bounds on Self
|
||||
// i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
|
||||
let self_param = TypeRef::Path(name![Self].into());
|
||||
generics.fill_bounds(&self.body_ctx, trait_def, self_param);
|
||||
|
||||
generics.fill(&self.body_ctx, &mut sm, node);
|
||||
}
|
||||
GenericsOwner::Impl => {}
|
||||
}
|
||||
generics
|
||||
}
|
||||
|
||||
fn lower_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
|
||||
@ -503,3 +542,16 @@ fn desugar_future_path(orig: TypeRef) -> Path {
|
||||
|
||||
Path::from_known_path(path, generic_args)
|
||||
}
|
||||
|
||||
enum GenericsOwner<'a> {
|
||||
/// We need access to the partially-lowered `Function` for lowering `impl Trait` in argument
|
||||
/// position.
|
||||
Function(&'a Function),
|
||||
Struct,
|
||||
Enum,
|
||||
Union,
|
||||
/// The `TraitDef` is needed to fill the source map for the implicit `Self` parameter.
|
||||
Trait(&'a ast::TraitDef),
|
||||
TypeAlias,
|
||||
Impl,
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user