Skip to content

Commit 254022c

Browse files
bors[bot]Veykril
andauthored
Merge #10304
10304: internal: Generate ast nodes for each ast trait r=Veykril a=Veykril Generate a `DynTrait` node per ast trait that implements the trait itself as well as conversions via the `AstNode` trait. This is a trick already employed in `hir_def::attr` with `AttrsOwner` where it was manually implemented for. This basically gives us stack trait objects for these(only useful for `hir_def::attr` currently) as well as simple conversions of `SyntaxNode` to a trait, in cases where only a result of a function call of such a trait is of interest. It doesn't have many uses yet but as its autogenerated it doesn't add any maintenance costs. bors r+ Co-authored-by: Lukas Wirth <[email protected]>
2 parents 168b00f + 83e97ad commit 254022c

File tree

6 files changed

+331
-75
lines changed

6 files changed

+331
-75
lines changed

crates/hir/src/semantics.rs

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ impl<'db> SemanticsImpl<'db> {
481481
)
482482
}
483483

484-
// This might not be the correct way to due this, but it works for now
484+
// This might not be the correct way to do this, but it works for now
485485
fn descend_node_into_attributes<N: AstNode>(&self, node: N) -> SmallVec<[N; 1]> {
486486
let mut res = smallvec![];
487487
let tokens = (|| {
@@ -682,20 +682,7 @@ impl<'db> SemanticsImpl<'db> {
682682
fn resolve_lifetime_param(&self, lifetime: &ast::Lifetime) -> Option<LifetimeParam> {
683683
let text = lifetime.text();
684684
let lifetime_param = lifetime.syntax().ancestors().find_map(|syn| {
685-
let gpl = match_ast! {
686-
match syn {
687-
ast::Fn(it) => it.generic_param_list()?,
688-
ast::TypeAlias(it) => it.generic_param_list()?,
689-
ast::Struct(it) => it.generic_param_list()?,
690-
ast::Enum(it) => it.generic_param_list()?,
691-
ast::Union(it) => it.generic_param_list()?,
692-
ast::Trait(it) => it.generic_param_list()?,
693-
ast::Impl(it) => it.generic_param_list()?,
694-
ast::WherePred(it) => it.generic_param_list()?,
695-
ast::ForType(it) => it.generic_param_list()?,
696-
_ => return None,
697-
}
698-
};
685+
let gpl = ast::DynGenericParamsOwner::cast(syn)?.generic_param_list()?;
699686
gpl.lifetime_params()
700687
.find(|tp| tp.lifetime().as_ref().map(|lt| lt.text()).as_ref() == Some(&text))
701688
})?;

crates/hir_def/src/attr.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -411,47 +411,47 @@ impl AttrsWithOwner {
411411
let file_id = id.parent.file_id(db);
412412
let root = db.parse_or_expand(file_id).unwrap();
413413
let owner = match &map[id.local_id] {
414-
Either::Left(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
415-
Either::Right(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
414+
Either::Left(it) => ast::DynAttrsOwner::new(it.to_node(&root)),
415+
Either::Right(it) => ast::DynAttrsOwner::new(it.to_node(&root)),
416416
};
417417
InFile::new(file_id, owner)
418418
}
419419
AttrDefId::AdtId(adt) => match adt {
420-
AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
421-
AdtId::UnionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
422-
AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
420+
AdtId::StructId(id) => id.lookup(db).source(db).map(ast::DynAttrsOwner::new),
421+
AdtId::UnionId(id) => id.lookup(db).source(db).map(ast::DynAttrsOwner::new),
422+
AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::DynAttrsOwner::new),
423423
},
424-
AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
424+
AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::DynAttrsOwner::new),
425425
AttrDefId::EnumVariantId(id) => {
426426
let map = db.variants_attrs_source_map(id.parent);
427427
let file_id = id.parent.lookup(db).id.file_id();
428428
let root = db.parse_or_expand(file_id).unwrap();
429-
InFile::new(file_id, ast::AttrsOwnerNode::new(map[id.local_id].to_node(&root)))
429+
InFile::new(file_id, ast::DynAttrsOwner::new(map[id.local_id].to_node(&root)))
430430
}
431-
AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
432-
AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
433-
AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
434-
AttrDefId::TypeAliasId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
431+
AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::DynAttrsOwner::new),
432+
AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::DynAttrsOwner::new),
433+
AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::DynAttrsOwner::new),
434+
AttrDefId::TypeAliasId(id) => id.lookup(db).source(db).map(ast::DynAttrsOwner::new),
435435
AttrDefId::MacroDefId(id) => id.ast_id().either(
436-
|it| it.with_value(ast::AttrsOwnerNode::new(it.to_node(db.upcast()))),
437-
|it| it.with_value(ast::AttrsOwnerNode::new(it.to_node(db.upcast()))),
436+
|it| it.with_value(ast::DynAttrsOwner::new(it.to_node(db.upcast()))),
437+
|it| it.with_value(ast::DynAttrsOwner::new(it.to_node(db.upcast()))),
438438
),
439-
AttrDefId::ImplId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
439+
AttrDefId::ImplId(id) => id.lookup(db).source(db).map(ast::DynAttrsOwner::new),
440440
AttrDefId::GenericParamId(id) => match id {
441441
GenericParamId::TypeParamId(id) => {
442442
id.parent.child_source(db).map(|source| match &source[id.local_id] {
443-
Either::Left(id) => ast::AttrsOwnerNode::new(id.clone()),
444-
Either::Right(id) => ast::AttrsOwnerNode::new(id.clone()),
443+
Either::Left(id) => ast::DynAttrsOwner::new(id.clone()),
444+
Either::Right(id) => ast::DynAttrsOwner::new(id.clone()),
445445
})
446446
}
447447
GenericParamId::LifetimeParamId(id) => id
448448
.parent
449449
.child_source(db)
450-
.map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())),
450+
.map(|source| ast::DynAttrsOwner::new(source[id.local_id].clone())),
451451
GenericParamId::ConstParamId(id) => id
452452
.parent
453453
.child_source(db)
454-
.map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())),
454+
.map(|source| ast::DynAttrsOwner::new(source[id.local_id].clone())),
455455
},
456456
};
457457

crates/syntax/src/ast.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ pub use self::{
2121
expr_ext::{ArrayExprKind, Effect, ElseBranch, LiteralKind},
2222
generated::{nodes::*, tokens::*},
2323
node_ext::{
24-
AttrKind, AttrsOwnerNode, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind,
25-
SelfParamKind, SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind,
24+
AttrKind, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, SelfParamKind,
25+
SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind,
2626
},
2727
operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp},
2828
token_ext::{

crates/syntax/src/ast/generated/nodes.rs

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,6 +1445,46 @@ pub enum GenericParam {
14451445
TypeParam(TypeParam),
14461446
}
14471447
impl ast::AttrsOwner for GenericParam {}
1448+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1449+
pub struct DynArgListOwner {
1450+
pub(crate) syntax: SyntaxNode,
1451+
}
1452+
impl ast::ArgListOwner for DynArgListOwner {}
1453+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1454+
pub struct DynAttrsOwner {
1455+
pub(crate) syntax: SyntaxNode,
1456+
}
1457+
impl ast::AttrsOwner for DynAttrsOwner {}
1458+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1459+
pub struct DynGenericParamsOwner {
1460+
pub(crate) syntax: SyntaxNode,
1461+
}
1462+
impl ast::GenericParamsOwner for DynGenericParamsOwner {}
1463+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1464+
pub struct DynLoopBodyOwner {
1465+
pub(crate) syntax: SyntaxNode,
1466+
}
1467+
impl ast::LoopBodyOwner for DynLoopBodyOwner {}
1468+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1469+
pub struct DynModuleItemOwner {
1470+
pub(crate) syntax: SyntaxNode,
1471+
}
1472+
impl ast::ModuleItemOwner for DynModuleItemOwner {}
1473+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1474+
pub struct DynNameOwner {
1475+
pub(crate) syntax: SyntaxNode,
1476+
}
1477+
impl ast::NameOwner for DynNameOwner {}
1478+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1479+
pub struct DynTypeBoundsOwner {
1480+
pub(crate) syntax: SyntaxNode,
1481+
}
1482+
impl ast::TypeBoundsOwner for DynTypeBoundsOwner {}
1483+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1484+
pub struct DynVisibilityOwner {
1485+
pub(crate) syntax: SyntaxNode,
1486+
}
1487+
impl ast::VisibilityOwner for DynVisibilityOwner {}
14481488
impl AstNode for Name {
14491489
fn can_cast(kind: SyntaxKind) -> bool { kind == NAME }
14501490
fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3564,6 +3604,219 @@ impl AstNode for GenericParam {
35643604
}
35653605
}
35663606
}
3607+
impl DynArgListOwner {
3608+
#[inline]
3609+
pub fn new<T: ast::ArgListOwner>(node: T) -> DynArgListOwner {
3610+
DynArgListOwner { syntax: node.syntax().clone() }
3611+
}
3612+
}
3613+
impl AstNode for DynArgListOwner {
3614+
fn can_cast(kind: SyntaxKind) -> bool {
3615+
match kind {
3616+
CALL_EXPR | METHOD_CALL_EXPR => true,
3617+
_ => false,
3618+
}
3619+
}
3620+
fn cast(syntax: SyntaxNode) -> Option<Self> {
3621+
Self::can_cast(syntax.kind()).then(|| DynArgListOwner { syntax })
3622+
}
3623+
fn syntax(&self) -> &SyntaxNode { &self.syntax }
3624+
}
3625+
impl DynAttrsOwner {
3626+
#[inline]
3627+
pub fn new<T: ast::AttrsOwner>(node: T) -> DynAttrsOwner {
3628+
DynAttrsOwner { syntax: node.syntax().clone() }
3629+
}
3630+
}
3631+
impl AstNode for DynAttrsOwner {
3632+
fn can_cast(kind: SyntaxKind) -> bool {
3633+
match kind {
3634+
MACRO_CALL
3635+
| SOURCE_FILE
3636+
| CONST
3637+
| ENUM
3638+
| EXTERN_BLOCK
3639+
| EXTERN_CRATE
3640+
| FN
3641+
| IMPL
3642+
| MACRO_RULES
3643+
| MACRO_DEF
3644+
| MODULE
3645+
| STATIC
3646+
| STRUCT
3647+
| TRAIT
3648+
| TYPE_ALIAS
3649+
| UNION
3650+
| USE
3651+
| ITEM_LIST
3652+
| BLOCK_EXPR
3653+
| SELF_PARAM
3654+
| PARAM
3655+
| RECORD_FIELD
3656+
| TUPLE_FIELD
3657+
| VARIANT
3658+
| ASSOC_ITEM_LIST
3659+
| EXTERN_ITEM_LIST
3660+
| CONST_PARAM
3661+
| LIFETIME_PARAM
3662+
| TYPE_PARAM
3663+
| EXPR_STMT
3664+
| LET_STMT
3665+
| ARRAY_EXPR
3666+
| AWAIT_EXPR
3667+
| BIN_EXPR
3668+
| BOX_EXPR
3669+
| BREAK_EXPR
3670+
| CALL_EXPR
3671+
| CAST_EXPR
3672+
| CLOSURE_EXPR
3673+
| CONTINUE_EXPR
3674+
| EFFECT_EXPR
3675+
| FIELD_EXPR
3676+
| FOR_EXPR
3677+
| IF_EXPR
3678+
| INDEX_EXPR
3679+
| LITERAL
3680+
| LOOP_EXPR
3681+
| MATCH_EXPR
3682+
| METHOD_CALL_EXPR
3683+
| PAREN_EXPR
3684+
| PATH_EXPR
3685+
| PREFIX_EXPR
3686+
| RANGE_EXPR
3687+
| REF_EXPR
3688+
| RETURN_EXPR
3689+
| TRY_EXPR
3690+
| TUPLE_EXPR
3691+
| WHILE_EXPR
3692+
| YIELD_EXPR
3693+
| RECORD_EXPR_FIELD_LIST
3694+
| RECORD_EXPR_FIELD
3695+
| MATCH_ARM_LIST
3696+
| MATCH_ARM
3697+
| IDENT_PAT
3698+
| RECORD_PAT_FIELD => true,
3699+
_ => false,
3700+
}
3701+
}
3702+
fn cast(syntax: SyntaxNode) -> Option<Self> {
3703+
Self::can_cast(syntax.kind()).then(|| DynAttrsOwner { syntax })
3704+
}
3705+
fn syntax(&self) -> &SyntaxNode { &self.syntax }
3706+
}
3707+
impl DynGenericParamsOwner {
3708+
#[inline]
3709+
pub fn new<T: ast::GenericParamsOwner>(node: T) -> DynGenericParamsOwner {
3710+
DynGenericParamsOwner { syntax: node.syntax().clone() }
3711+
}
3712+
}
3713+
impl AstNode for DynGenericParamsOwner {
3714+
fn can_cast(kind: SyntaxKind) -> bool {
3715+
match kind {
3716+
ENUM | FN | IMPL | STRUCT | TRAIT | TYPE_ALIAS | UNION => true,
3717+
_ => false,
3718+
}
3719+
}
3720+
fn cast(syntax: SyntaxNode) -> Option<Self> {
3721+
Self::can_cast(syntax.kind()).then(|| DynGenericParamsOwner { syntax })
3722+
}
3723+
fn syntax(&self) -> &SyntaxNode { &self.syntax }
3724+
}
3725+
impl DynLoopBodyOwner {
3726+
#[inline]
3727+
pub fn new<T: ast::LoopBodyOwner>(node: T) -> DynLoopBodyOwner {
3728+
DynLoopBodyOwner { syntax: node.syntax().clone() }
3729+
}
3730+
}
3731+
impl AstNode for DynLoopBodyOwner {
3732+
fn can_cast(kind: SyntaxKind) -> bool {
3733+
match kind {
3734+
FOR_EXPR | LOOP_EXPR | WHILE_EXPR => true,
3735+
_ => false,
3736+
}
3737+
}
3738+
fn cast(syntax: SyntaxNode) -> Option<Self> {
3739+
Self::can_cast(syntax.kind()).then(|| DynLoopBodyOwner { syntax })
3740+
}
3741+
fn syntax(&self) -> &SyntaxNode { &self.syntax }
3742+
}
3743+
impl DynModuleItemOwner {
3744+
#[inline]
3745+
pub fn new<T: ast::ModuleItemOwner>(node: T) -> DynModuleItemOwner {
3746+
DynModuleItemOwner { syntax: node.syntax().clone() }
3747+
}
3748+
}
3749+
impl AstNode for DynModuleItemOwner {
3750+
fn can_cast(kind: SyntaxKind) -> bool {
3751+
match kind {
3752+
MACRO_ITEMS | SOURCE_FILE | ITEM_LIST => true,
3753+
_ => false,
3754+
}
3755+
}
3756+
fn cast(syntax: SyntaxNode) -> Option<Self> {
3757+
Self::can_cast(syntax.kind()).then(|| DynModuleItemOwner { syntax })
3758+
}
3759+
fn syntax(&self) -> &SyntaxNode { &self.syntax }
3760+
}
3761+
impl DynNameOwner {
3762+
#[inline]
3763+
pub fn new<T: ast::NameOwner>(node: T) -> DynNameOwner {
3764+
DynNameOwner { syntax: node.syntax().clone() }
3765+
}
3766+
}
3767+
impl AstNode for DynNameOwner {
3768+
fn can_cast(kind: SyntaxKind) -> bool {
3769+
match kind {
3770+
CONST | ENUM | FN | MACRO_RULES | MACRO_DEF | MODULE | STATIC | STRUCT | TRAIT
3771+
| TYPE_ALIAS | UNION | RENAME | SELF_PARAM | RECORD_FIELD | VARIANT | CONST_PARAM
3772+
| TYPE_PARAM | IDENT_PAT => true,
3773+
_ => false,
3774+
}
3775+
}
3776+
fn cast(syntax: SyntaxNode) -> Option<Self> {
3777+
Self::can_cast(syntax.kind()).then(|| DynNameOwner { syntax })
3778+
}
3779+
fn syntax(&self) -> &SyntaxNode { &self.syntax }
3780+
}
3781+
impl DynTypeBoundsOwner {
3782+
#[inline]
3783+
pub fn new<T: ast::TypeBoundsOwner>(node: T) -> DynTypeBoundsOwner {
3784+
DynTypeBoundsOwner { syntax: node.syntax().clone() }
3785+
}
3786+
}
3787+
impl AstNode for DynTypeBoundsOwner {
3788+
fn can_cast(kind: SyntaxKind) -> bool {
3789+
match kind {
3790+
ASSOC_TYPE_ARG | TRAIT | TYPE_ALIAS | LIFETIME_PARAM | TYPE_PARAM | WHERE_PRED => true,
3791+
_ => false,
3792+
}
3793+
}
3794+
fn cast(syntax: SyntaxNode) -> Option<Self> {
3795+
Self::can_cast(syntax.kind()).then(|| DynTypeBoundsOwner { syntax })
3796+
}
3797+
fn syntax(&self) -> &SyntaxNode { &self.syntax }
3798+
}
3799+
impl DynVisibilityOwner {
3800+
#[inline]
3801+
pub fn new<T: ast::VisibilityOwner>(node: T) -> DynVisibilityOwner {
3802+
DynVisibilityOwner { syntax: node.syntax().clone() }
3803+
}
3804+
}
3805+
impl AstNode for DynVisibilityOwner {
3806+
fn can_cast(kind: SyntaxKind) -> bool {
3807+
match kind {
3808+
CONST | ENUM | EXTERN_CRATE | FN | IMPL | MACRO_RULES | MACRO_DEF | MODULE | STATIC
3809+
| STRUCT | TRAIT | TYPE_ALIAS | UNION | USE | RECORD_FIELD | TUPLE_FIELD | VARIANT => {
3810+
true
3811+
}
3812+
_ => false,
3813+
}
3814+
}
3815+
fn cast(syntax: SyntaxNode) -> Option<Self> {
3816+
Self::can_cast(syntax.kind()).then(|| DynVisibilityOwner { syntax })
3817+
}
3818+
fn syntax(&self) -> &SyntaxNode { &self.syntax }
3819+
}
35673820
impl std::fmt::Display for GenericArg {
35683821
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35693822
std::fmt::Display::fmt(self.syntax(), f)

0 commit comments

Comments
 (0)