From 56dc1fdbfa3cfe61a60d7d8a067a0582c7f78ac4 Mon Sep 17 00:00:00 2001 From: Dinu Blanovschi Date: Fri, 7 Feb 2025 16:36:55 +0100 Subject: [PATCH] feat: be a bit smarter about hir lowering, store hir ids in the elements they point to --- crates/narxia-hir-typechk/src/sema/mod.rs | 24 +- crates/narxia-hir/src/hir/hir_debug.rs | 14 +- crates/narxia-hir/src/hir/mod.rs | 40 +- crates/narxia-hir/src/hir_map.rs | 82 +++ crates/narxia-hir/src/lower.rs | 157 +++-- crates/narxia-hir/src/visitor.rs | 636 ++++++------------ tests/narxia-test-runner/Cargo.toml | 5 + .../tests/no_allocated_and_unused_hirids.rs | 31 + .../tests/no_orphans_after_parent_compute.rs | 10 +- .../visitor_visits_all_non_whitespace_text.rs | 6 +- 10 files changed, 477 insertions(+), 528 deletions(-) create mode 100644 tests/narxia-test-runner/tests/no_allocated_and_unused_hirids.rs diff --git a/crates/narxia-hir-typechk/src/sema/mod.rs b/crates/narxia-hir-typechk/src/sema/mod.rs index e4f0a42..d1c9562 100644 --- a/crates/narxia-hir-typechk/src/sema/mod.rs +++ b/crates/narxia-hir-typechk/src/sema/mod.rs @@ -160,15 +160,15 @@ struct ProgramStructureVisitor<'hir> { } macro_rules! scope_creating_elements { - ($($vis_name:ident ($id:ty, $t:ty) => $walk_name:ident $($id_use:expr)? ;)*) => { + ($($vis_name:ident ($t:ty) => $walk_name:ident;)*) => { $( - fn $vis_name(&mut self, id: $id, t: &'hir $t) { + fn $vis_name(&mut self, t: &'hir $t) { let last_scope = self.stack.last().copied(); - let self_elem = self.program_structure.scope_tree.push_scope_element(None, scope_elem(id)); + let self_elem = self.program_structure.scope_tree.push_scope_element(None, scope_elem(t.hir_id)); let scope = self.program_structure.scope_tree.push_scope(last_scope, Some(self_elem)); self.stack.push(scope); - vis::$walk_name(self, $(if $id_use == () {id}else{id},)? t); + vis::$walk_name(self, t); let s = self.stack.pop(); @@ -179,13 +179,13 @@ macro_rules! scope_creating_elements { } macro_rules! scope_adding_elements { - ($($vis_name:ident ($id:ty, $t:ty) => $walk_name:ident $($id_use:expr)? ;)*) => { + ($($vis_name:ident ($t:ty) => $walk_name:ident;)*) => { $( - fn $vis_name(&mut self, id: $id, t: &'hir $t) { + fn $vis_name(&mut self, t: &'hir $t) { let last_scope = self.stack.last().copied(); - let _self_elem = self.program_structure.scope_tree.push_scope_element(last_scope, scope_elem(id)); + let _self_elem = self.program_structure.scope_tree.push_scope_element(last_scope, scope_elem(t.hir_id)); - vis::$walk_name(self, $(if $id_use == () {id}else{id},)? t); + vis::$walk_name(self, t); } )* }; @@ -197,13 +197,13 @@ impl<'hir> vis::HirVisitor<'hir> for ProgramStructureVisitor<'hir> { } scope_creating_elements! { - visit_mod_def(hir::ModId, hir::ModDef) => walk_mod_def; - visit_fn_def(hir::FnId, hir::FnDef) => walk_fn_def; - visit_block(hir::BlockId, hir::Block) => walk_block; + visit_mod_def(hir::ModDef) => walk_mod_def; + visit_fn_def(hir::FnDef) => walk_fn_def; + visit_block(hir::Block) => walk_block; } scope_adding_elements! { - visit_use_stmt(hir::UseStmtId, hir::UseStmt) => walk_use_stmt; + visit_use_stmt(hir::UseStmt) => walk_use_stmt; } } diff --git a/crates/narxia-hir/src/hir/hir_debug.rs b/crates/narxia-hir/src/hir/hir_debug.rs index e882ebe..604ca4f 100644 --- a/crates/narxia-hir/src/hir/hir_debug.rs +++ b/crates/narxia-hir/src/hir/hir_debug.rs @@ -179,7 +179,7 @@ pub fn display_mod_def( write!(f, "{:indent$}", "", indent = hdc.depth)?; write!(f, "{} {}", "module".keyword(), mod_def.name.text,)?; if let Some(body) = &mod_def.body { - writeln!(f, "{}", "{".punctuation()); + writeln!(f, "{}", "{".punctuation())?; display_item_list(f, &body.items, hdc.make_child())?; writeln!(f)?; write!(f, "{:indent$}", "", indent = hdc.depth)?; @@ -614,7 +614,7 @@ fn display_ty(f: &mut fmt::Formatter, ty: &TyRef, hdc: HirDisplayContext) -> fmt write!(f, "{} ", ",".punctuation())?; } - display_ty_generic_arg(f, arg, hdc.make_child())?; + display_ty_generic_arg_id(f, *arg, hdc.make_child())?; } write!(f, "{}", ">".punctuation())?; } @@ -649,6 +649,16 @@ impl fmt::Display for TyRef { } } +fn display_ty_generic_arg_id( + f: &mut fmt::Formatter, + id: TyGenericArgId, + hdc: HirDisplayContext, +) -> fmt::Result { + write!(f, "{}", id.0)?; + + Ok(()) +} + fn display_ty_generic_arg( f: &mut fmt::Formatter, arg: &TyGenericArg, diff --git a/crates/narxia-hir/src/hir/mod.rs b/crates/narxia-hir/src/hir/mod.rs index 37a8fb7..55c98c9 100644 --- a/crates/narxia-hir/src/hir/mod.rs +++ b/crates/narxia-hir/src/hir/mod.rs @@ -14,10 +14,19 @@ mod hir_debug; pub use hir_debug::*; pub trait HirIdNewtype { + fn new(hir_id: HirId) -> Self + where + Self: Sized; fn hir_id(&self) -> HirId; } impl HirIdNewtype for HirId { + fn new(hir_id: HirId) -> Self + where + Self: Sized, + { + hir_id + } fn hir_id(&self) -> HirId { *self } @@ -29,6 +38,13 @@ macro_rules! hir_id_newtype { pub struct $name(pub HirId); impl HirIdNewtype for $name { + fn new(hir_id: HirId) -> Self + where + Self: Sized, + { + Self(hir_id) + } + fn hir_id(&self) -> HirId { self.0 } @@ -104,6 +120,8 @@ pub struct ModDef { pub mod_kw: ModuleKw, pub name: Ident, pub body: Option, + + pub hir_id: ModId, } #[derive(Debug, Eq, PartialEq, Clone)] @@ -117,6 +135,7 @@ pub struct ModBody { pub struct Item { pub attrs: AttrList, pub kind: ItemKind, + pub hir_id: ItemId, } #[derive(Debug, Eq, PartialEq, Clone)] @@ -192,6 +211,7 @@ pub struct UseStmt { pub use_kw: UseKw, pub span: HirSpan, pub path: UsePath, + pub hir_id: UseStmtId, } #[derive(Debug, Eq, PartialEq, Clone)] @@ -211,6 +231,7 @@ hir_id_newtype!(UsePathSegmentId, UsePathSegment); #[derive(Debug, Eq, PartialEq, Clone)] pub struct UsePathSegment { pub ident: Ident, + pub hir_id: UsePathSegmentId, } #[derive(Eq, PartialEq, PartialOrd, Ord, Clone)] @@ -256,6 +277,8 @@ pub struct FnDef { pub params: Option, pub ret_ty: Option, pub body: BlockId, + + pub hir_id: FnId, } hir_id_newtype!(BlockId, Block); @@ -330,6 +353,7 @@ hir_id_newtype!(ExprId, Expr); #[derive(Debug, Eq, PartialEq, Clone)] pub struct Expr { pub kind: ExprKind, + pub hir_id: ExprId, } #[derive(Debug, Eq, PartialEq, Clone)] @@ -405,6 +429,13 @@ pub struct LambdaExpr { pub struct LambdaExprId(pub ExprId); impl HirIdNewtype for LambdaExprId { + fn new(hir_id: HirId) -> Self + where + Self: Sized, + { + Self(ExprId::new(hir_id)) + } + fn hir_id(&self) -> HirId { self.0.hir_id() } @@ -733,6 +764,8 @@ pub struct Block { pub lbrace: LBrace, pub items: ItemList, pub rbrace: RBrace, + + pub hir_id: BlockId, } #[derive(Debug, Eq, PartialEq, Clone)] @@ -747,6 +780,7 @@ hir_id_newtype!(StmtId, Stmt); #[derive(Debug, Eq, PartialEq, Clone)] pub struct Stmt { pub kind: StmtKind, + pub hir_id: StmtId, } #[derive(Debug, Eq, PartialEq, Clone)] @@ -832,6 +866,7 @@ pub enum PatKind { pub struct TyRef { pub span: HirSpan, pub kind: TyRefKind, + pub hir_id: TyRefId, } hir_id_newtype!(TyRefId, TyRef); @@ -870,13 +905,16 @@ pub enum PrimitiveTyKind { #[derive(Debug, Eq, PartialEq, Clone)] pub struct TyGenericArgs { - pub args: Vec, + pub args: Vec, } +hir_id_newtype!(TyGenericArgId, TyGenericArg); + #[derive(Debug, Eq, PartialEq, Clone)] pub struct TyGenericArg { pub kind: TyGenericArgKind, pub span: HirSpan, + pub hir_id: TyGenericArgId, } #[derive(Debug, Eq, PartialEq, Clone)] diff --git a/crates/narxia-hir/src/hir_map.rs b/crates/narxia-hir/src/hir_map.rs index 096772f..857939b 100644 --- a/crates/narxia-hir/src/hir_map.rs +++ b/crates/narxia-hir/src/hir_map.rs @@ -34,6 +34,41 @@ pub enum HirElem { StrLiteral(StrLiteral), StrLiteralDisplayFragment(StrLiteralDisplayFragment), StrLiteralDebugFragment(StrLiteralDebugFragment), + #[doc(hidden)] + __Allocated(HirSpan), +} + +impl HirElem { + fn get_hir_id_in_self(&self) -> HirId { + match self { + HirElem::Mod(mod_def) => mod_def.hir_id.hir_id(), + HirElem::Item(item) => item.hir_id.hir_id(), + HirElem::Ident(ident) => todo!(), + HirElem::Fn(fn_def) => fn_def.hir_id.hir_id(), + HirElem::FnParam(fn_param) => todo!(), + HirElem::FnRetTy(fn_ret_ty) => todo!(), + HirElem::Expr(expr) => expr.hir_id.hir_id(), + HirElem::LoopExpr(loop_expr) => todo!(), + HirElem::BreakExpr(break_expr) => todo!(), + HirElem::ContinueExpr(continue_expr) => todo!(), + HirElem::ReturnExpr(return_expr) => todo!(), + HirElem::Pat(pat) => todo!(), + HirElem::Stmt(stmt) => stmt.hir_id.hir_id(), + HirElem::ForStmt(for_stmt) => todo!(), + HirElem::WhileStmt(while_stmt) => todo!(), + HirElem::UseStmt(use_stmt) => use_stmt.hir_id.hir_id(), + HirElem::UsePathSegment(use_path_segment) => use_path_segment.hir_id.hir_id(), + HirElem::Block(block) => block.hir_id.hir_id(), + HirElem::TyRef(ty_ref) => ty_ref.hir_id.hir_id(), + HirElem::TyGenericArg(ty_generic_arg) => ty_generic_arg.hir_id.hir_id(), + HirElem::LetStmt(let_stmt) => todo!(), + HirElem::AssignmentStmt(assignment_stmt) => todo!(), + HirElem::StrLiteral(str_literal) => todo!(), + HirElem::StrLiteralDisplayFragment(str_literal_display_fragment) => todo!(), + HirElem::StrLiteralDebugFragment(str_literal_debug_fragment) => todo!(), + HirElem::__Allocated(_) => unreachable!(), + } + } } impl fmt::Display for HirElem { @@ -64,6 +99,7 @@ impl fmt::Display for HirElem { Self::StrLiteral(s) => write!(f, "{}", s), Self::StrLiteralDisplayFragment(s) => write!(f, "{}", s), Self::StrLiteralDebugFragment(s) => write!(f, "{}", s), + Self::__Allocated(_) => write!(f, ""), } } } @@ -94,6 +130,18 @@ impl HirMap { HirId::new(self.buffer.len()) } + pub fn allocate_hir_id(&mut self, span: HirSpan) -> HirId { + let mut id = self.next_hir_id(); + #[cfg(hir_id_span)] + { + id.span = span; + } + self.buffer.push(HirElem::__Allocated(span)); + self.parents.push(HirId::ORPHAN_HIRID); + self.files.push(self.current_file.unwrap()); + id + } + pub fn push_ref(&mut self, r: HirElem, span: HirSpan) -> HirId { let mut id = self.next_hir_id(); #[cfg(hir_id_span)] @@ -106,6 +154,12 @@ impl HirMap { id } + pub fn push_ref_at_allocation(&mut self, r: HirElem, allocation: HirId) { + debug_assert_eq!(self.buffer[allocation.id], HirElem::__Allocated(allocation.span)); + debug_assert_eq!(r.get_hir_id_in_self(), allocation); + self.buffer[allocation.id] = r; + } + pub fn get(&self, at: HirId) -> &HirElem { &self.buffer[at.id] } @@ -184,6 +238,13 @@ impl HirMap { } } + pub fn get_ty_generic_arg(&self, at: TyGenericArgId) -> &TyGenericArg { + match self.get(at.0) { + HirElem::TyGenericArg(t) => t, + x => panic!("Expected TyGenericArg, found {x:?}"), + } + } + fn update_parent(&mut self, at: HirId, parent: HirId) { self.parents[at.id] = parent; } @@ -195,6 +256,27 @@ impl HirMap { pub fn get_file(&self, at: HirId) -> SrcFile { self.files[at.id] } + + pub fn __get_allocated_hirids(&self) -> Vec { + self.buffer + .iter() + .enumerate() + .filter_map(|(i, x)| { + if let HirElem::__Allocated(span) = x { + let mut hir_id = HirId::new(i); + + #[cfg(hir_id_span)] + { + hir_id.span = *span; + } + + Some(hir_id) + } else { + None + } + }) + .collect() + } } struct ParentUpdateVisitor<'hir> { diff --git a/crates/narxia-hir/src/lower.rs b/crates/narxia-hir/src/lower.rs index 648fe77..5b96cef 100644 --- a/crates/narxia-hir/src/lower.rs +++ b/crates/narxia-hir/src/lower.rs @@ -10,7 +10,6 @@ //! This module contains the code that lowers the syntax tree to the HIR. use narxia_src_db::SrcFile; -use narxia_syn::syntax_kind::SyntaxKind; use narxia_syn::syntree; use narxia_syn::syntree::{Token, TreeNode}; @@ -46,6 +45,16 @@ impl<'arena> HirLowerCtxt<'arena> { fn push_ref(&mut self, elem: HirElem, span: HirSpan) -> HirId { self.hir_ref_arena.push_ref(elem, span) } + + fn allocate_hir_id(&mut self, span: HirSpan) -> T { + T::new(self.hir_ref_arena.allocate_hir_id(span)) + } + + fn push_ref_at_allocation(&mut self, allocation: T, elem: HirElem) -> T { + let hir_id = allocation.hir_id(); + self.hir_ref_arena.push_ref_at_allocation(elem, hir_id); + allocation + } } fn lower_binop(binop: &syntree::BinOp) -> BinOp { @@ -114,6 +123,7 @@ fn lower_mod_def_from_item_list( name: Ident, span: HirSpan, ) -> ModId { + let hir_id = hir_lower_ctxt.allocate_hir_id(span); let mod_def = ModDef { mod_kw, name, @@ -122,9 +132,10 @@ fn lower_mod_def_from_item_list( items: lower_item_list(hir_lower_ctxt, item_list), rbrace, }), + hir_id, }; - ModId(hir_lower_ctxt.push_ref(HirElem::Mod(mod_def), span)) + hir_lower_ctxt.push_ref_at_allocation(hir_id, HirElem::Mod(mod_def)) } fn lower_mod_def_to_include( @@ -133,37 +144,48 @@ fn lower_mod_def_to_include( name: Ident, span: HirSpan, ) -> ModId { + let hir_id = hir_lower_ctxt.allocate_hir_id(span); let mod_def = ModDef { mod_kw, name, body: None, + hir_id, }; - ModId(hir_lower_ctxt.push_ref(HirElem::Mod(mod_def), span)) + hir_lower_ctxt.push_ref_at_allocation(hir_id, HirElem::Mod(mod_def)) } fn lower_item(hir_lower_ctxt: &mut HirLowerCtxt, item: &syntree::Item) -> Vec { let attrs = lower_attr_list(hir_lower_ctxt, item.get_attr_list().as_ref()); let hir_items = if let Some(fn_def) = item.get_fn_def() { + let hir_id = hir_lower_ctxt.allocate_hir_id(item.span()); vec![Item { attrs, kind: ItemKind::FnDef(lower_fn_def(hir_lower_ctxt, &fn_def)), + hir_id, }] } else if let Some(stmt) = item.get_stmt() { + let hir_id = hir_lower_ctxt.allocate_hir_id(item.span()); vec![Item { attrs, kind: ItemKind::Stmt(lower_stmt(hir_lower_ctxt, &stmt)), + hir_id, }] } else if let Some(use_stmt) = item.get_use_stmt() { lower_use_stmt(hir_lower_ctxt, &use_stmt) .into_iter() - .map(|it| Item { - attrs: AttrList::new(), - kind: ItemKind::UseStmt(it), + .map(|it| { + let hir_id = hir_lower_ctxt.allocate_hir_id(item.span()); + Item { + attrs: AttrList::new(), + kind: ItemKind::UseStmt(it), + hir_id, + } }) .collect() } else if let Some(mod_def) = item.get_module() { + let hir_id = hir_lower_ctxt.allocate_hir_id(item.span()); let mod_kw = ModuleKw::from_token(&mod_def.get_module_kw()); let name = lower_ident( hir_lower_ctxt, @@ -192,13 +214,16 @@ fn lower_item(hir_lower_ctxt: &mut HirLowerCtxt, item: &syntree::Item) -> Vec LBrace { - if lbrace.kind() != SyntaxKind::L_BRACE { - panic!("Expected '{{', found {:?}", lbrace); - } - - LBrace::from_token(lbrace) -} - -fn lower_rbrace(rbrace: &Token) -> RBrace { - if rbrace.kind() != SyntaxKind::R_BRACE { - panic!("Expected '}}', found {:?}", rbrace); - } - - RBrace::from_token(rbrace) -} - -fn lower_colon2(colon2: &Token) -> Colon2 { - if colon2.kind() != SyntaxKind::COLON2 { - panic!("Expected '::', found {:?}", colon2); - } - - Colon2::from_token(colon2) -} - fn lower_fn_def(hir_lower_ctxt: &mut HirLowerCtxt, fn_def: &syntree::FnDef) -> FnId { + let hir_id = hir_lower_ctxt.allocate_hir_id(fn_def.span()); let head = fn_def.get_fn_head(); let fn_kw = FnKw::from_token(&head.get_fn_kw()); let name = lower_ident(hir_lower_ctxt, &head.get_fn_name().unwrap().get_ident()); @@ -396,9 +403,10 @@ fn lower_fn_def(hir_lower_ctxt: &mut HirLowerCtxt, fn_def: &syntree::FnDef) -> F params, ret_ty, body, + hir_id, }; - FnId(hir_lower_ctxt.push_ref(HirElem::Fn(hir_fn_def), fn_def.span())) + hir_lower_ctxt.push_ref_at_allocation(hir_id, HirElem::Fn(hir_fn_def)) } fn lower_generic_param_list( @@ -543,9 +551,11 @@ fn lower_fn_def_param(hir_lower_ctxt: &mut HirLowerCtxt, fn_param: &syntree::FnP } fn lower_expr(hir_lower_ctxt: &mut HirLowerCtxt, expr: &syntree::Expr) -> ExprId { + let hir_id = hir_lower_ctxt.allocate_hir_id(expr.span()); let hir_expr = match expr { syntree::Expr::ExprAtom(atom) => Expr { kind: ExprKind::Atom(lower_expr_atom(hir_lower_ctxt, atom)), + hir_id, }, syntree::Expr::ExprNode(node) => return lower_expr_node(hir_lower_ctxt, node), syntree::Expr::BinaryOpExpr(binary_op_expr) => { @@ -556,19 +566,24 @@ fn lower_expr(hir_lower_ctxt: &mut HirLowerCtxt, expr: &syntree::Expr) -> ExprId op, rhs: right, }), + hir_id, } } syntree::Expr::CallExpr(call_expr) => Expr { kind: ExprKind::CallExpr(lower_call_expr(hir_lower_ctxt, call_expr)), + hir_id, }, syntree::Expr::IndexExpr(index_expr) => Expr { kind: ExprKind::IndexExpr(lower_index_expr(hir_lower_ctxt, index_expr)), + hir_id, }, syntree::Expr::FieldAccess(field_access) => Expr { kind: ExprKind::FieldAccess(lower_field_access(hir_lower_ctxt, field_access)), + hir_id, }, syntree::Expr::MethodCall(method_call) => Expr { kind: ExprKind::MethodCall(lower_method_call(hir_lower_ctxt, method_call)), + hir_id, }, syntree::Expr::Block(block) => { let block = lower_block(hir_lower_ctxt, block); @@ -576,6 +591,7 @@ fn lower_expr(hir_lower_ctxt: &mut HirLowerCtxt, expr: &syntree::Expr) -> ExprId kind: ExprKind::Atom(ExprAtom { kind: ExprAtomKind::BlockExpr(BlockExpr { block }), }), + hir_id, } } syntree::Expr::CustomInfixExpr(e) => { @@ -596,11 +612,12 @@ fn lower_expr(hir_lower_ctxt: &mut HirLowerCtxt, expr: &syntree::Expr) -> ExprId name: op, arg, }), + hir_id, } } }; - ExprId(hir_lower_ctxt.push_ref(HirElem::Expr(hir_expr), expr.span())) + hir_lower_ctxt.push_ref_at_allocation(hir_id, HirElem::Expr(hir_expr)) } fn lower_call_expr(hir_lower_ctxt: &mut HirLowerCtxt, call_expr: &syntree::CallExpr) -> CallExpr { @@ -636,6 +653,7 @@ fn lower_call_expr_args( .collect::>(); args.extend(call_expr_args.get_call_expr_arg_lambda().map(|it| { + let hir_id = hir_lower_ctxt.allocate_hir_id(it.span()); let expr = Expr { kind: ExprKind::Atom(ExprAtom { kind: ExprAtomKind::LambdaExpr(lower_lambda_expr( @@ -643,8 +661,9 @@ fn lower_call_expr_args( &it.get_lambda_expr(), )), }), + hir_id, }; - ExprId(hir_lower_ctxt.push_ref(HirElem::Expr(expr), it.span())) + hir_lower_ctxt.push_ref_at_allocation(hir_id, HirElem::Expr(expr)) })); CallExprArgs { lparen, @@ -850,6 +869,7 @@ fn lower_block_extra_items( block: &syntree::Block, f: impl FnOnce(&mut HirLowerCtxt, &mut ItemList), ) -> BlockId { + let hir_id = hir_lower_ctxt.allocate_hir_id(block.span()); let lbrace = LBrace::from_token(&block.get_lbrace()); let mut items = lower_item_list(hir_lower_ctxt, block.get_item_list()); let rbrace = RBrace::from_token(&block.get_rbrace().unwrap()); @@ -860,9 +880,10 @@ fn lower_block_extra_items( lbrace, items, rbrace, + hir_id, }; - BlockId(hir_lower_ctxt.push_ref(HirElem::Block(hir_block), block.span())) + hir_lower_ctxt.push_ref_at_allocation(hir_id, HirElem::Block(hir_block)) } fn lower_block(hir_lower_ctxt: &mut HirLowerCtxt, block: &syntree::Block) -> BlockId { @@ -870,31 +891,37 @@ fn lower_block(hir_lower_ctxt: &mut HirLowerCtxt, block: &syntree::Block) -> Blo } fn lower_stmt(hir_lower_ctxt: &mut HirLowerCtxt, stmt: &syntree::Stmt) -> StmtId { + let hir_id = hir_lower_ctxt.allocate_hir_id(stmt.span()); let hir_stmt = if let Some(expr) = stmt.get_expr_node() { Stmt { kind: StmtKind::ExprStmt(lower_expr_node(hir_lower_ctxt, &expr)), + hir_id, } } else if let Some(let_stmt) = stmt.get_let_stmt() { Stmt { kind: StmtKind::LetStmt(lower_let_stmt(hir_lower_ctxt, &let_stmt)), + hir_id, } } else if let Some(for_stmt) = stmt.get_for_stmt() { Stmt { kind: StmtKind::ForStmt(lower_for_stmt(hir_lower_ctxt, &for_stmt)), + hir_id, } } else if let Some(while_stmt) = stmt.get_while_stmt() { Stmt { kind: StmtKind::WhileStmt(lower_while_stmt(hir_lower_ctxt, &while_stmt)), + hir_id, } } else if let Some(assignment_stmt) = stmt.get_assignment_stmt() { Stmt { kind: StmtKind::AssignmentStmt(lower_assignment_stmt(hir_lower_ctxt, &assignment_stmt)), + hir_id, } } else { todo!() }; - StmtId(hir_lower_ctxt.push_ref(HirElem::Stmt(hir_stmt), stmt.span())) + hir_lower_ctxt.push_ref_at_allocation(hir_id, HirElem::Stmt(hir_stmt)) } fn lower_let_stmt(hir_lower_ctxt: &mut HirLowerCtxt, let_stmt: &syntree::LetStmt) -> LetStmt { @@ -1079,22 +1106,30 @@ fn lower_displayable_to_expr( displayable: &syntree::StringLiteralFragDisplayable, ) -> ExprId { let expr = match displayable { - syntree::StringLiteralFragDisplayable::StringLiteralFragExpr(e) => Expr { - kind: ExprKind::Atom(ExprAtom { - kind: ExprAtomKind::BlockExpr(lower_block_expr( - hir_lower_ctxt, - &e.get_block_expr(), - )), - }), - }, - syntree::StringLiteralFragDisplayable::StringLiteralFragIdent(e) => Expr { - kind: ExprKind::Atom(ExprAtom { - kind: ExprAtomKind::Ident(lower_ident(hir_lower_ctxt, &e.get_ident())), - }), - }, + syntree::StringLiteralFragDisplayable::StringLiteralFragExpr(e) => { + let hir_id = hir_lower_ctxt.allocate_hir_id(e.span()); + Expr { + kind: ExprKind::Atom(ExprAtom { + kind: ExprAtomKind::BlockExpr(lower_block_expr( + hir_lower_ctxt, + &e.get_block_expr(), + )), + }), + hir_id, + } + } + syntree::StringLiteralFragDisplayable::StringLiteralFragIdent(e) => { + let hir_id = hir_lower_ctxt.allocate_hir_id(e.span()); + Expr { + kind: ExprKind::Atom(ExprAtom { + kind: ExprAtomKind::Ident(lower_ident(hir_lower_ctxt, &e.get_ident())), + }), + hir_id, + } + } }; - ExprId(hir_lower_ctxt.push_ref(HirElem::Expr(expr), displayable.span())) + hir_lower_ctxt.push_ref_at_allocation(expr.hir_id, HirElem::Expr(expr)) } fn lower_pat(hir_lower_ctxt: &mut HirLowerCtxt, pat: &syntree::Pat) -> Pat { @@ -1112,6 +1147,7 @@ fn lower_pat(hir_lower_ctxt: &mut HirLowerCtxt, pat: &syntree::Pat) -> Pat { fn lower_ty_ref(hir_lower_ctxt: &mut HirLowerCtxt, ty_ref: &syntree::TyRef) -> TyRefId { let span = HirSpan::of_node(ty_ref); + let hir_id = hir_lower_ctxt.allocate_hir_id(span); let ty_ref = if let Some(name) = ty_ref.get_ident() { let name = lower_ident(hir_lower_ctxt, &name); macro_rules! ty_refp { @@ -1141,18 +1177,19 @@ fn lower_ty_ref(hir_lower_ctxt: &mut HirLowerCtxt, ty_ref: &syntree::TyRef) -> T _ => TyRefKind::Named(name, TyGenericArgs { args: vec![] }), // TODO: do }; - TyRef { kind, span } + TyRef { kind, span, hir_id } } else if let Some(fn_ty) = ty_ref.get_fn_ty() { let fn_ty = lower_fn_ty(hir_lower_ctxt, &fn_ty); TyRef { kind: TyRefKind::Fn(fn_ty), span, + hir_id, } } else { todo!() }; - TyRefId(hir_lower_ctxt.push_ref(HirElem::TyRef(ty_ref), span)) + hir_lower_ctxt.push_ref_at_allocation(ty_ref.hir_id, HirElem::TyRef(ty_ref)) } fn lower_fn_ty(hir_lower_ctxt: &mut HirLowerCtxt, fn_ty: &syntree::FnTy) -> FnTy { diff --git a/crates/narxia-hir/src/visitor.rs b/crates/narxia-hir/src/visitor.rs index bd56195..8ea0461 100644 --- a/crates/narxia-hir/src/visitor.rs +++ b/crates/narxia-hir/src/visitor.rs @@ -1,5 +1,3 @@ -use std::default; - use crate::hir::HirIdNewtype; use crate::hir_map::HirMap; use crate::{hir, HirId, HirSpan}; @@ -37,7 +35,7 @@ macro_rules! const_token_visit_fns { }; } - macro_rules! implement_acceptors { + macro_rules! const_token_implement_acceptors { () => { impl_visitable! { $($visit_name($kw_ty)),* @@ -47,6 +45,74 @@ macro_rules! const_token_visit_fns { }; } +macro_rules! hir_visitor_fns { + ($($fn_name:ident($hir_ty:ty) -> $walk_name:ident),* $(,)?) => { + macro_rules! visitor_fns_decl_visit_fns { + () => { + $( + fn $fn_name(&mut self, hir: &'hir $hir_ty) { + $walk_name(self, hir) + } + )* + }; + } + + macro_rules! visitor_fns_impl_visitable { + () => { + impl_visitable! { + $($fn_name($hir_ty)),* + } + }; + } + }; +} + +macro_rules! hir_visitor_hir_ids { + ($($visit_name:ident($hir_id_newtype:ty) -> $hm_getter:ident),* $(,)?) => { + macro_rules! hir_visitor_hir_ids_visitor_fn_decls { + () => { + $( + fn $visit_name(&mut self, id: $hir_id_newtype) { + self.visit_hir_id(id.hir_id()); + self.q_id_strategy(|v, hm| hm.$hm_getter(id).accept(v)); + self.end_visit_hir_id(id.hir_id()); + } + )* + }; + } + + macro_rules! hir_visitor_hir_ids_impl_visitable { + () => { + impl_visitable_id! { + $($visit_name($hir_id_newtype)),* + } + }; + } + }; +} + +macro_rules! contextualised_hir_visitors { + ($($visit_name:ident ($context_ty_id:ty, $hir_ty:ty) -> $walk_name:ident),* $(,)?) => { + macro_rules! contextualised_hir_visitors_fn_decls { + () => { + $( + fn $visit_name(&mut self, id: $context_ty_id, hir: &'hir $hir_ty) { + $walk_name(self, id, hir) + } + )* + }; + } + + macro_rules! contextualised_hir_visitors_impl_acceptors { + () => { + impl_id_visitable! { + $($visit_name [$context_ty_id] ($hir_ty)),* + } + }; + } + }; +} + const_token_visit_fns! { visit_if_kw -> walk_if_kw -> hir::IfKw, visit_else_kw -> walk_else_kw -> hir::ElseKw, @@ -111,275 +177,97 @@ const_token_visit_fns! { visit_pipe2 -> walk_pipe2 -> hir::Pipe2, } +hir_visitor_fns! { + visit_mod_def(hir::ModDef) -> walk_mod_def, + visit_mod_body(hir::ModBody) -> walk_mod_body, + visit_attr_list(hir::AttrList) -> walk_attr_list, + visit_attr(hir::Attr) -> walk_attr, + visit_attr_meta(hir::AttrMeta) -> walk_attr_meta, + visit_attr_meta_item(hir::AttrMetaItem) -> walk_attr_meta_item, + visit_attr_meta_item_eq(hir::AttrMetaItemEq) -> walk_attr_meta_item_eq, + visit_attr_meta_item_call(hir::AttrMetaItemCall) -> walk_attr_meta_item_call, + visit_item(hir::Item) -> walk_item, + visit_stmt(hir::Stmt) -> walk_stmt, + visit_expr(hir::Expr) -> walk_expr, + visit_block(hir::Block) -> walk_block, + visit_ident(hir::Ident) -> walk_ident, + visit_num_literal(hir::NumLit) -> walk_num_literal, + visit_item_list(hir::ItemList) -> walk_item_list, + visit_assignment_op(hir::AssignmentOp) -> walk_assignment_op, + visit_generic_params(hir::GenericParams) -> walk_generic_params, + visit_generic_param(hir::GenericParam) -> walk_generic_param, + visit_generic_param_ty(hir::GenericParamTy) -> walk_generic_param_ty, + visit_generic_param_ty_bounds(hir::GenericParamTyBounds) -> walk_generic_param_ty_bounds, + visit_generic_param_const(hir::GenericParamConst) -> walk_generic_param_const, + visit_fn_def(hir::FnDef) -> walk_fn_def, + visit_fn_param_list(hir::FnParamList) -> walk_fn_param_list, + visit_fn_param(hir::FnParam) -> walk_fn_param, + visit_fn_ret_ty(hir::FnRetTy) -> walk_fn_ret_ty, + visit_pat(hir::Pat) -> walk_pat, + visit_ty_ref(hir::TyRef) -> walk_ty_ref, + visit_ty_generic_args(hir::TyGenericArgs) -> walk_ty_generic_args, + visit_ty_generic_arg(hir::TyGenericArg) -> walk_ty_generic_arg, + visit_fn_ty_ref(hir::FnTy) -> walk_fn_ty_ref, + visit_str_literal(hir::StrLiteral) -> walk_str_literal, + visit_str_literal_fragment(hir::StrLiteralFragment) -> walk_str_literal_fragment, + visit_str_literal_text_fragment(hir::StrLiteralTextFragment) -> walk_str_literal_text_fragment, + visit_str_literal_display_fragment(hir::StrLiteralDisplayFragment) -> walk_str_literal_display_fragment, + visit_str_literal_debug_fragment(hir::StrLiteralDebugFragment) -> walk_str_literal_debug_fragment, + + visit_call_args(hir::CallExprArgs) -> walk_call_args, + visit_lambda_param_list(hir::LambdaParamList) -> walk_lambda_param_list, + visit_lambda_param(hir::LambdaParam) -> walk_lambda_param, + + visit_use_stmt(hir::UseStmt) -> walk_use_stmt, + visit_use_path(hir::UsePath) -> walk_use_path, + visit_use_path_segment(hir::UsePathSegment) -> walk_use_path_segment, + visit_use_alias(hir::UseAlias) -> walk_use_alias, +} + +hir_visitor_hir_ids! { + visit_item_id(hir::ItemId) -> get_item, + visit_stmt_id(hir::StmtId) -> get_stmt, + visit_block_id(hir::BlockId) -> get_block, + visit_fn_id(hir::FnId) -> get_fn, + visit_mod_id(hir::ModId) -> get_mod, + visit_ty_ref_id(hir::TyRefId) -> get_ty_ref, + visit_use_stmt_id(hir::UseStmtId) -> get_use_stmt, + visit_use_path_segment_id(hir::UsePathSegmentId) -> get_use_segment, + visit_expr_id(hir::ExprId) -> get_expr, + visit_ty_generic_arg_id(hir::TyGenericArgId) -> get_ty_generic_arg, +} + +contextualised_hir_visitors! { + visit_let_stmt(hir::StmtId, hir::LetStmt) -> walk_let_stmt, + visit_for_stmt(hir::StmtId, hir::ForStmt) -> walk_for_stmt, + visit_while_stmt(hir::StmtId, hir::WhileStmt) -> walk_while_stmt, + visit_assignment_stmt(hir::StmtId, hir::AssignmentStmt) -> walk_assignment_stmt, + // + visit_block_expr(hir::ExprId, hir::BlockExpr) -> walk_block_expr, + visit_expr_atom(hir::ExprId, hir::ExprAtom) -> walk_expr_atom, + visit_expr_binary_expr(hir::ExprId, hir::BinaryOpExpr) -> walk_expr_binary_expr, + visit_expr_call_expr(hir::ExprId, hir::CallExpr) -> walk_expr_call_expr, + visit_expr_index_expr(hir::ExprId, hir::IndexExpr) -> walk_expr_index_expr, + visit_expr_field_access(hir::ExprId, hir::FieldAccess) -> walk_expr_field_access, + visit_expr_method_call(hir::ExprId, hir::MethodCall) -> walk_expr_method_call, + visit_custom_infix_expr(hir::ExprId, hir::CustomInfixExpr) -> walk_custom_infix_expr, + visit_return_expr(hir::ExprId, hir::ReturnExpr) -> walk_return_expr, + visit_break_expr(hir::ExprId, hir::BreakExpr) -> walk_break_expr, + visit_continue_expr(hir::ExprId, hir::ContinueExpr) -> walk_continue_expr, + visit_loop_expr(hir::ExprId, hir::LoopExpr) -> walk_loop_expr, + visit_if_expr(hir::ExprId, hir::IfExpr) -> walk_if_expr, + visit_if_expr_else_clause(hir::ExprId, hir::IfExprElseClause) -> walk_if_expr_else_clause, + visit_tuple_like_expr(hir::ExprId, hir::TupleExpr) -> walk_tuple_like_expr, + visit_lambda_expr(hir::ExprId, hir::LambdaExpr) -> walk_lambda_expr, +} + #[allow(unused_variables)] pub trait HirVisitor<'hir> { fn q_id_strategy(&mut self, q: Q); - fn visit_mod_def(&mut self, mod_id: hir::ModId, mod_def: &'hir hir::ModDef) { - walk_mod_def(self, mod_def) - } - - fn visit_mod_body(&mut self, mod_body: &'hir hir::ModBody) { - walk_mod_body(self, mod_body) - } - - fn visit_item(&mut self, item_id: hir::ItemId, item: &'hir hir::Item) { - walk_item(self, item) - } - - fn visit_attr_list(&mut self, attr_list: &'hir hir::AttrList) { - walk_attr_list(self, attr_list) - } + visitor_fns_decl_visit_fns!(); - fn visit_attr(&mut self, attr: &'hir hir::Attr) { - walk_attr(self, attr) - } - - fn visit_attr_meta(&mut self, attr_meta: &'hir hir::AttrMeta) { - walk_attr_meta(self, attr_meta) - } - - fn visit_attr_meta_item(&mut self, attr_meta_item: &'hir hir::AttrMetaItem) { - walk_attr_meta_item(self, attr_meta_item) - } - - fn visit_attr_meta_item_eq(&mut self, attr_meta_item_eq: &'hir hir::AttrMetaItemEq) { - walk_attr_meta_item_eq(self, attr_meta_item_eq) - } - - fn visit_attr_meta_item_call(&mut self, attr_meta_item_call: &'hir hir::AttrMetaItemCall) { - walk_attr_meta_item_call(self, attr_meta_item_call) - } - - fn visit_ident(&mut self, ident: &'hir hir::Ident) { - walk_ident(self, ident) - } - - fn visit_num_literal(&mut self, num: &'hir hir::NumLit) { - walk_num_literal(self, num) - } - - fn visit_item_list(&mut self, item_list: &'hir hir::ItemList) { - walk_item_list(self, item_list) - } - - fn visit_fn_def(&mut self, fn_id: hir::FnId, fn_def: &'hir hir::FnDef) { - walk_fn_def(self, fn_def) - } - - fn visit_stmt(&mut self, stmt_id: hir::StmtId, stmt: &'hir hir::Stmt) { - walk_stmt(self, stmt_id, stmt) - } - - fn visit_expr(&mut self, expr_id: hir::ExprId, expr: &'hir hir::Expr) { - walk_expr(self, expr_id, expr) - } - - fn visit_let_stmt(&mut self, stmt_id: hir::StmtId, let_stmt: &'hir hir::LetStmt) { - walk_let_stmt(self, let_stmt) - } - - fn visit_for_stmt(&mut self, stmt_id: hir::StmtId, for_stmt: &'hir hir::ForStmt) { - walk_for_stmt(self, for_stmt) - } - - fn visit_while_stmt(&mut self, stmt_id: hir::StmtId, while_stmt: &'hir hir::WhileStmt) { - walk_while_stmt(self, while_stmt) - } - - fn visit_assignment_stmt( - &mut self, - stmt_id: hir::StmtId, - assignment_stmt: &'hir hir::AssignmentStmt, - ) { - walk_assignment_stmt(self, assignment_stmt) - } - - fn visit_assignment_op(&mut self, assignment_op: &'hir hir::AssignmentOp) { - walk_assignment_op(self, assignment_op) - } - - fn visit_generic_params(&mut self, gparams: &'hir hir::GenericParams) { - walk_generic_params(self, gparams) - } - - fn visit_generic_param(&mut self, gparam: &'hir hir::GenericParam) { - walk_generic_param(self, gparam) - } - - fn visit_generic_param_ty(&mut self, generic_param_ty: &'hir hir::GenericParamTy) { - walk_generic_param_ty(self, generic_param_ty) - } - - fn visit_generic_param_const(&mut self, generic_param_const: &'hir hir::GenericParamConst) { - walk_generic_param_const(self, generic_param_const) - } - - fn visit_generic_param_ty_bounds(&mut self, ty_bounds: &'hir hir::GenericParamTyBounds) { - walk_generic_param_ty_bounds(self, ty_bounds) - } - - fn visit_fn_param_list(&mut self, param_list: &'hir hir::FnParamList) { - walk_fn_param_list(self, param_list) - } - - fn visit_fn_param(&mut self, fn_param: &'hir hir::FnParam) { - walk_fn_param(self, fn_param) - } - - fn visit_fn_ret_ty(&mut self, fn_ret_ty: &'hir hir::FnRetTy) { - walk_fn_ret_ty(self, fn_ret_ty) - } - - fn visit_block(&mut self, block_id: hir::BlockId, block: &'hir hir::Block) { - walk_block(self, block) - } - - fn visit_block_expr(&mut self, expr_id: hir::ExprId, block_expr: &'hir hir::BlockExpr) { - walk_block_expr(self, block_expr) - } - - fn visit_ty_ref(&mut self, ty_ref_id: hir::TyRefId, ty_ref: &'hir hir::TyRef) { - walk_ty_ref(self, ty_ref) - } - - fn visit_pat(&mut self, pat: &'hir hir::Pat) { - walk_pat(self, pat) - } - - fn visit_ty_generic_args(&mut self, generic_args: &'hir hir::TyGenericArgs) { - walk_ty_generic_args(self, generic_args) - } - - fn visit_ty_generic_arg(&mut self, generic_arg: &'hir hir::TyGenericArg) { - walk_ty_generic_arg(self, generic_arg) - } - - fn visit_fn_ty_ref(&mut self, fn_ty: &'hir hir::FnTy) { - walk_fn_ty_ref(self, fn_ty) - } - - fn visit_expr_atom(&mut self, expr_id: hir::ExprId, atom: &'hir hir::ExprAtom) { - walk_expr_atom(self, expr_id, atom) - } - - fn visit_str_literal(&mut self, str_literal: &'hir hir::StrLiteral) { - walk_str_literal(self, str_literal) - } - - fn visit_str_literal_fragment(&mut self, str_literal_fragment: &'hir hir::StrLiteralFragment) { - walk_str_literal_fragment(self, str_literal_fragment) - } - - fn visit_str_literal_text_fragment( - &mut self, - str_literal_text_fragment: &'hir hir::StrLiteralTextFragment, - ) { - walk_str_literal_text_fragment(self, str_literal_text_fragment) - } - - fn visit_str_display_fragment( - &mut self, - str_display_fragment: &'hir hir::StrLiteralDisplayFragment, - ) { - walk_str_display_fragment(self, str_display_fragment) - } - - fn visit_str_debug_fragment(&mut self, str_debug_fragment: &'hir hir::StrLiteralDebugFragment) { - walk_str_debug_fragment(self, str_debug_fragment) - } - - fn visit_expr_binary_expr( - &mut self, - expr_id: hir::ExprId, - binary_expr: &'hir hir::BinaryOpExpr, - ) { - walk_expr_binary_expr(self, binary_expr) - } - - fn visit_expr_call_expr(&mut self, expr_id: hir::ExprId, call_expr: &'hir hir::CallExpr) { - walk_expr_call_expr(self, call_expr) - } - - fn visit_expr_index_expr(&mut self, expr_id: hir::ExprId, index_expr: &'hir hir::IndexExpr) { - walk_expr_index_expr(self, index_expr) - } - - fn visit_expr_field_access( - &mut self, - expr_id: hir::ExprId, - field_access: &'hir hir::FieldAccess, - ) { - walk_expr_field_access(self, field_access) - } - - fn visit_expr_method_call(&mut self, expr_id: hir::ExprId, method_call: &'hir hir::MethodCall) { - walk_expr_method_call(self, method_call) - } - - fn visit_custom_infix_expr( - &mut self, - expr_id: hir::ExprId, - custom_infix: &'hir hir::CustomInfixExpr, - ) { - walk_custom_infix_expr(self, custom_infix) - } - - fn visit_return_expr(&mut self, expr_id: hir::ExprId, ret: &'hir hir::ReturnExpr) { - walk_return_expr(self, ret) - } - - fn visit_break_expr(&mut self, expr_id: hir::ExprId, break_expr: &'hir hir::BreakExpr) { - walk_break_expr(self, break_expr) - } - - fn visit_continue_expr( - &mut self, - expr_id: hir::ExprId, - continue_expr: &'hir hir::ContinueExpr, - ) { - walk_continue_expr(self, continue_expr) - } - - fn visit_loop_expr(&mut self, expr_id: hir::ExprId, loop_expr: &'hir hir::LoopExpr) { - walk_loop_expr(self, loop_expr) - } - - fn visit_if_expr(&mut self, expr_id: hir::ExprId, if_expr: &'hir hir::IfExpr) { - walk_if_expr(self, expr_id, if_expr) - } - - fn visit_if_expr_else_clause( - &mut self, - expr_id: hir::ExprId, - else_clause: &'hir hir::IfExprElseClause, - ) { - walk_if_expr_else_clause(self, else_clause) - } - - fn visit_tuple_like_expr( - &mut self, - expr_id: hir::ExprId, - tuple_like_expr: &'hir hir::TupleExpr, - ) { - walk_tuple_like_expr(self, tuple_like_expr) - } - - fn visit_call_args(&mut self, call_args: &'hir hir::CallExprArgs) { - walk_call_args(self, call_args) - } - - fn visit_lambda_expr(&mut self, expr_id: hir::ExprId, lambda_expr: &'hir hir::LambdaExpr) { - walk_lambda_expr(self, lambda_expr) - } - - fn visit_lambda_param_list(&mut self, lambda_param_list: &'hir hir::LambdaParamList) { - walk_lambda_param_list(self, lambda_param_list) - } - - fn visit_lambda_param(&mut self, lambda_param: &'hir hir::LambdaParam) { - walk_lambda_param(self, lambda_param) - } + contextualised_hir_visitors_fn_decls!(); fn visit_hir_id(&mut self, hir_id: HirId) { // Nothing to do. @@ -409,81 +297,8 @@ pub trait HirVisitor<'hir> { self.visit_token_span(token.span); } - fn visit_expr_id(&mut self, expr_id: hir::ExprId) { - self.visit_hir_id(expr_id.hir_id()); - self.q_id_strategy(|v, hm| hm.get_expr(expr_id).accept(expr_id, v)); - self.end_visit_hir_id(expr_id.hir_id()); - } - - fn visit_use_stmt(&mut self, use_stmt_id: hir::UseStmtId, use_stmt: &'hir hir::UseStmt) { - walk_use_stmt(self, use_stmt) - } - - fn visit_use_path_segment( - &mut self, - use_path_segment_id: hir::UsePathSegmentId, - use_path_segment: &'hir hir::UsePathSegment, - ) { - walk_use_path_segment(self, use_path_segment) - } - - fn visit_use_path(&mut self, use_path: &'hir hir::UsePath) { - walk_use_path(self, use_path) - } - - fn visit_use_alias(&mut self, use_alias: &'hir hir::UseAlias) { - walk_use_alias(self, use_alias) - } - + hir_visitor_hir_ids_visitor_fn_decls! {} const_token_visit_fns_decl_visits! {} - - fn visit_item_id(&mut self, item_id: hir::ItemId) { - self.visit_hir_id(item_id.hir_id()); - self.q_id_strategy(|v, hm| hm.get_item(item_id).accept(item_id, v)); - self.end_visit_hir_id(item_id.hir_id()); - } - - fn visit_stmt_id(&mut self, stmt_id: hir::StmtId) { - self.visit_hir_id(stmt_id.hir_id()); - self.q_id_strategy(|v, hm| hm.get_stmt(stmt_id).accept(stmt_id, v)); - self.end_visit_hir_id(stmt_id.hir_id()); - } - - fn visit_block_id(&mut self, block_id: hir::BlockId) { - self.visit_hir_id(block_id.hir_id()); - self.q_id_strategy(|v, hm| hm.get_block(block_id).accept(block_id, v)); - self.end_visit_hir_id(block_id.hir_id()); - } - - fn visit_fn_id(&mut self, fn_id: hir::FnId) { - self.visit_hir_id(fn_id.hir_id()); - self.q_id_strategy(|v, hm| hm.get_fn(fn_id).accept(fn_id, v)); - self.end_visit_hir_id(fn_id.hir_id()); - } - - fn visit_mod_id(&mut self, mod_id: hir::ModId) { - self.visit_hir_id(mod_id.hir_id()); - self.q_id_strategy(|v, hm| hm.get_mod(mod_id).accept(mod_id, v)); - self.end_visit_hir_id(mod_id.hir_id()); - } - - fn visit_ty_ref_id(&mut self, ty_ref_id: hir::TyRefId) { - self.visit_hir_id(ty_ref_id.hir_id()); - self.q_id_strategy(|v, hm| hm.get_ty_ref(ty_ref_id).accept(ty_ref_id, v)); - self.end_visit_hir_id(ty_ref_id.hir_id()); - } - - fn visit_use_stmt_id(&mut self, use_stmt_id: hir::UseStmtId) { - self.visit_hir_id(use_stmt_id.hir_id()); - self.q_id_strategy(|v, hm| hm.get_use_stmt(use_stmt_id).accept(use_stmt_id, v)); - self.end_visit_hir_id(use_stmt_id.hir_id()); - } - - fn visit_use_path_segment_id(&mut self, use_segment_id: hir::UsePathSegmentId) { - self.visit_hir_id(use_segment_id.hir_id()); - self.q_id_strategy(|v, hm| hm.get_use_segment(use_segment_id).accept(use_segment_id, v)); - self.end_visit_hir_id(use_segment_id.hir_id()); - } } const_token_visit_fns_decl_walks!(); @@ -683,56 +498,48 @@ pub fn walk_fn_param_list<'hir, V: HirVisitor<'hir> + ?Sized>( param_list.rparen.accept(visitor); } -pub fn walk_stmt<'hir, V: HirVisitor<'hir> + ?Sized>( - visitor: &mut V, - stmt_id: hir::StmtId, - stmt: &'hir hir::Stmt, -) { +pub fn walk_stmt<'hir, V: HirVisitor<'hir> + ?Sized>(visitor: &mut V, stmt: &'hir hir::Stmt) { match &stmt.kind { hir::StmtKind::ExprStmt(expr) => { expr.accept(visitor); } hir::StmtKind::LetStmt(let_stmt) => { - let_stmt.accept(stmt_id, visitor); + let_stmt.accept(stmt.hir_id, visitor); } hir::StmtKind::ForStmt(for_stmt) => { - for_stmt.accept(stmt_id, visitor); + for_stmt.accept(stmt.hir_id, visitor); } hir::StmtKind::WhileStmt(while_stmt) => { - while_stmt.accept(stmt_id, visitor); + while_stmt.accept(stmt.hir_id, visitor); } hir::StmtKind::AssignmentStmt(assignment_stmt) => { - assignment_stmt.accept(stmt_id, visitor); + assignment_stmt.accept(stmt.hir_id, visitor); } } } -pub fn walk_expr<'hir, V: HirVisitor<'hir> + ?Sized>( - visitor: &mut V, - expr_id: hir::ExprId, - expr: &'hir hir::Expr, -) { +pub fn walk_expr<'hir, V: HirVisitor<'hir> + ?Sized>(visitor: &mut V, expr: &'hir hir::Expr) { match &expr.kind { hir::ExprKind::Atom(atom) => { - atom.accept(expr_id, visitor); + atom.accept(expr.hir_id, visitor); } hir::ExprKind::Binary(binary_expr) => { - binary_expr.accept(expr_id, visitor); + binary_expr.accept(expr.hir_id, visitor); } hir::ExprKind::CallExpr(call_expr) => { - call_expr.accept(expr_id, visitor); + call_expr.accept(expr.hir_id, visitor); } hir::ExprKind::IndexExpr(index_expr) => { - index_expr.accept(expr_id, visitor); + index_expr.accept(expr.hir_id, visitor); } hir::ExprKind::FieldAccess(field_access) => { - field_access.accept(expr_id, visitor); + field_access.accept(expr.hir_id, visitor); } hir::ExprKind::MethodCall(method_call) => { - method_call.accept(expr_id, visitor); + method_call.accept(expr.hir_id, visitor); } hir::ExprKind::CustomInfix(custom_infix) => { - custom_infix.accept(expr_id, visitor); + custom_infix.accept(expr.hir_id, visitor); } } } @@ -841,6 +648,7 @@ pub fn walk_fn_ret_ty<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_let_stmt<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::StmtId, let_stmt: &'hir hir::LetStmt, ) { let_stmt.let_kw.accept(visitor); @@ -863,6 +671,7 @@ pub fn walk_let_stmt<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_for_stmt<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::StmtId, for_stmt: &'hir hir::ForStmt, ) { for_stmt.for_kw.accept(visitor); @@ -876,6 +685,7 @@ pub fn walk_for_stmt<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_while_stmt<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::StmtId, while_stmt: &'hir hir::WhileStmt, ) { while_stmt.while_kw.accept(visitor); @@ -887,6 +697,7 @@ pub fn walk_while_stmt<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_assignment_stmt<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::StmtId, assignment_stmt: &'hir hir::AssignmentStmt, ) { assignment_stmt.lhs.accept(visitor); @@ -919,6 +730,7 @@ pub fn walk_block<'hir, V: HirVisitor<'hir> + ?Sized>(visitor: &mut V, block: &' pub fn walk_block_expr<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, block_expr: &'hir hir::BlockExpr, ) { block_expr.block.accept(visitor); @@ -926,6 +738,7 @@ pub fn walk_block_expr<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_expr_binary_expr<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, binary_expr: &'hir hir::BinaryOpExpr, ) { binary_expr.lhs.accept(visitor); @@ -952,6 +765,7 @@ pub fn walk_expr_binary_expr<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_expr_call_expr<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, call_expr: &'hir hir::CallExpr, ) { call_expr.callee.accept(visitor); @@ -960,6 +774,7 @@ pub fn walk_expr_call_expr<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_expr_index_expr<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, index_expr: &'hir hir::IndexExpr, ) { index_expr.base.accept(visitor); @@ -970,6 +785,7 @@ pub fn walk_expr_index_expr<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_expr_field_access<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, field_access: &'hir hir::FieldAccess, ) { field_access.base.accept(visitor); @@ -979,6 +795,7 @@ pub fn walk_expr_field_access<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_expr_method_call<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, method_call: &'hir hir::MethodCall, ) { method_call.base.accept(visitor); @@ -989,6 +806,7 @@ pub fn walk_expr_method_call<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_return_expr<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, ret: &'hir hir::ReturnExpr, ) { ret.return_kw.accept(visitor); @@ -997,6 +815,7 @@ pub fn walk_return_expr<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_break_expr<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, break_expr: &'hir hir::BreakExpr, ) { break_expr.break_kw.accept(visitor); @@ -1005,6 +824,7 @@ pub fn walk_break_expr<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_continue_expr<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, continue_expr: &'hir hir::ContinueExpr, ) { continue_expr.continue_kw.accept(visitor); @@ -1012,6 +832,7 @@ pub fn walk_continue_expr<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_custom_infix_expr<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, custom_infix: &'hir hir::CustomInfixExpr, ) { custom_infix.base.accept(visitor); @@ -1021,6 +842,7 @@ pub fn walk_custom_infix_expr<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_loop_expr<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, loop_expr: &'hir hir::LoopExpr, ) { loop_expr.loop_kw.accept(visitor); @@ -1044,6 +866,7 @@ pub fn walk_if_expr<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_if_expr_else_clause<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, else_clause: &'hir hir::IfExprElseClause, ) { else_clause.else_kw.accept(visitor); @@ -1052,6 +875,7 @@ pub fn walk_if_expr_else_clause<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_tuple_like_expr<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, tuple_like_expr: &'hir hir::TupleExpr, ) { tuple_like_expr.lparen.accept(visitor); @@ -1090,6 +914,7 @@ pub fn walk_call_args<'hir, V: HirVisitor<'hir> + ?Sized>( pub fn walk_lambda_expr<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, + _: hir::ExprId, lambda_expr: &'hir hir::LambdaExpr, ) { lambda_expr.lbrace.accept(visitor); @@ -1162,14 +987,14 @@ pub fn walk_str_literal_text_fragment<'hir, V: HirVisitor<'hir> + ?Sized>( str_literal_text_fragment.token.accept(visitor); } -pub fn walk_str_display_fragment<'hir, V: HirVisitor<'hir> + ?Sized>( +pub fn walk_str_literal_display_fragment<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, str_display_fragment: &'hir hir::StrLiteralDisplayFragment, ) { str_display_fragment.expr.accept(visitor); } -pub fn walk_str_debug_fragment<'hir, V: HirVisitor<'hir> + ?Sized>( +pub fn walk_str_literal_debug_fragment<'hir, V: HirVisitor<'hir> + ?Sized>( visitor: &mut V, str_debug_fragment: &'hir hir::StrLiteralDebugFragment, ) { @@ -1285,46 +1110,13 @@ macro_rules! impl_visitable { }; } +visitor_fns_impl_visitable!(); + impl_visitable! { - visit_mod_body(hir::ModBody), - visit_ident(hir::Ident), - visit_num_literal(hir::NumLit), - visit_item_list(hir::ItemList), - - visit_attr_list(hir::AttrList), - visit_attr(hir::Attr), - visit_attr_meta(hir::AttrMeta), - visit_attr_meta_item(hir::AttrMetaItem), - visit_attr_meta_item_eq(hir::AttrMetaItemEq), - visit_attr_meta_item_call(hir::AttrMetaItemCall), - - visit_generic_params(hir::GenericParams), - visit_generic_param(hir::GenericParam), - visit_generic_param_ty(hir::GenericParamTy), - visit_generic_param_const(hir::GenericParamConst), - visit_generic_param_ty_bounds(hir::GenericParamTyBounds), - visit_fn_param_list(hir::FnParamList), - visit_fn_param(hir::FnParam), - visit_fn_ret_ty(hir::FnRetTy), - visit_pat(hir::Pat), - visit_ty_generic_args(hir::TyGenericArgs), - visit_ty_generic_arg(hir::TyGenericArg), - visit_fn_ty_ref(hir::FnTy), - visit_str_literal(hir::StrLiteral), - visit_str_literal_fragment(hir::StrLiteralFragment), - visit_str_literal_text_fragment(hir::StrLiteralTextFragment), - visit_str_display_fragment(hir::StrLiteralDisplayFragment), - visit_str_debug_fragment(hir::StrLiteralDebugFragment), - visit_call_args(hir::CallExprArgs), - visit_lambda_param_list(hir::LambdaParamList), - visit_lambda_param(hir::LambdaParam), - visit_use_path(hir::UsePath), - visit_use_alias(hir::UseAlias), - visit_assignment_op(hir::AssignmentOp), visit_generic_token(hir::Tk), } -implement_acceptors!(); +const_token_implement_acceptors!(); macro_rules! impl_visitable_id { ($($visit_name:ident ($ty:ty)),* $(,)?) => { @@ -1346,17 +1138,9 @@ macro_rules! impl_visitable_id { } } -impl_visitable_id! { - visit_expr_id(hir::ExprId), - visit_item_id(hir::ItemId), - visit_stmt_id(hir::StmtId), - visit_block_id(hir::BlockId), - visit_fn_id(hir::FnId), - visit_mod_id(hir::ModId), - visit_ty_ref_id(hir::TyRefId), - visit_use_stmt_id(hir::UseStmtId), - visit_use_path_segment_id(hir::UsePathSegmentId), +hir_visitor_hir_ids_impl_visitable!(); +impl_visitable_id! { visit_hir_id(HirId), visit_span(HirSpan), } @@ -1374,34 +1158,4 @@ macro_rules! impl_id_visitable { }; } -impl_id_visitable! { - visit_mod_def [hir::ModId] (hir::ModDef), - visit_item [hir::ItemId] (hir::Item), - visit_fn_def [hir::FnId] (hir::FnDef), - visit_stmt [hir::StmtId] (hir::Stmt), - visit_expr [hir::ExprId] (hir::Expr), - visit_let_stmt [hir::StmtId] (hir::LetStmt), - visit_for_stmt [hir::StmtId] (hir::ForStmt), - visit_while_stmt [hir::StmtId] (hir::WhileStmt), - visit_assignment_stmt [hir::StmtId] (hir::AssignmentStmt), - visit_block [hir::BlockId] (hir::Block), - visit_block_expr [hir::ExprId] (hir::BlockExpr), - visit_expr_atom [hir::ExprId] (hir::ExprAtom), - visit_expr_binary_expr [hir::ExprId] (hir::BinaryOpExpr), - visit_expr_call_expr [hir::ExprId] (hir::CallExpr), - visit_expr_index_expr [hir::ExprId] (hir::IndexExpr), - visit_expr_field_access [hir::ExprId] (hir::FieldAccess), - visit_expr_method_call [hir::ExprId] (hir::MethodCall), - visit_custom_infix_expr [hir::ExprId] (hir::CustomInfixExpr), - visit_return_expr [hir::ExprId] (hir::ReturnExpr), - visit_break_expr [hir::ExprId] (hir::BreakExpr), - visit_continue_expr [hir::ExprId] (hir::ContinueExpr), - visit_loop_expr [hir::ExprId] (hir::LoopExpr), - visit_if_expr [hir::ExprId] (hir::IfExpr), - visit_if_expr_else_clause [hir::ExprId] (hir::IfExprElseClause), - visit_tuple_like_expr [hir::ExprId] (hir::TupleExpr), - visit_lambda_expr [hir::ExprId] (hir::LambdaExpr), - visit_ty_ref [hir::TyRefId] (hir::TyRef), - visit_use_stmt [hir::UseStmtId] (hir::UseStmt), - visit_use_path_segment [hir::UsePathSegmentId] (hir::UsePathSegment), -} +contextualised_hir_visitors_impl_acceptors!(); \ No newline at end of file diff --git a/tests/narxia-test-runner/Cargo.toml b/tests/narxia-test-runner/Cargo.toml index 08bffcb..8ebd1ea 100644 --- a/tests/narxia-test-runner/Cargo.toml +++ b/tests/narxia-test-runner/Cargo.toml @@ -46,3 +46,8 @@ harness = false name = "visitor_visits_all_non_whitespace_text_nxtimq" path = "tests/visitor_visits_all_non_whitespace_text.rs" harness = false + +[[test]] +name = "no_allocated_and_unused_hirids_nxtimq" +path = "tests/no_allocated_and_unused_hirids.rs" +harness = false diff --git a/tests/narxia-test-runner/tests/no_allocated_and_unused_hirids.rs b/tests/narxia-test-runner/tests/no_allocated_and_unused_hirids.rs new file mode 100644 index 0000000..b0c03a8 --- /dev/null +++ b/tests/narxia-test-runner/tests/no_allocated_and_unused_hirids.rs @@ -0,0 +1,31 @@ +use miette::bail; +use narxia_dir_structures::ParserTestSingleFolder; +use narxia_driver::HirDbg; +use narxia_test_runner::parser_tests::lower_to_hir; + +fn run_test(mut test: ParserTestSingleFolder) -> miette::Result<()> { + let ctx = narxia_driver::DriverCtx::initialize_in_test(); + let hir = lower_to_hir(&mut test, &ctx)?; + + let mod_def = hir.mod_def(&ctx.db); + + let hir_map = ctx.db.get_global_ty_ctxt().make_ty_ctxt().hir_map(); + + let alloc_ids = hir_map.__get_allocated_hirids(); + if !alloc_ids.is_empty() { + for hir_id in alloc_ids { + eprintln!("Allocated and unused hir_id: {:?}", hir_id); + eprintln!("At: {}", hir_id.span()); + eprintln!("In:"); + eprintln!("{}", hir_map.get_mod(mod_def).hir_dbg(&ctx)); + } + + bail!("Allocated and unused hir_ids"); + } + + Ok(()) +} + +narxia_test_runner::test_main_parser_tests_foreach! { + |test| { run_test(test) } +} \ No newline at end of file diff --git a/tests/narxia-test-runner/tests/no_orphans_after_parent_compute.rs b/tests/narxia-test-runner/tests/no_orphans_after_parent_compute.rs index 05f85ea..8002e0e 100644 --- a/tests/narxia-test-runner/tests/no_orphans_after_parent_compute.rs +++ b/tests/narxia-test-runner/tests/no_orphans_after_parent_compute.rs @@ -28,17 +28,13 @@ impl<'hir> HirVisitor<'hir> for OrphanHirIdVisitor<'hir> { fn visit_mod_id(&mut self, mod_id: narxia_hir::hir::ModId) { self.q_id_strategy(|this, hir_map| { - this.visit_mod_def(mod_id, hir_map.get_mod(mod_id)); + this.visit_mod_def(hir_map.get_mod(mod_id)); }); } - fn visit_mod_def( - &mut self, - mod_id: narxia_hir::hir::ModId, - mod_def: &'hir narxia_hir::hir::ModDef, - ) { + fn visit_mod_def(&mut self, mod_def: &'hir narxia_hir::hir::ModDef) { if mod_def.name.text != SpecialIdents::ROOT_MODULE { - self.visit_hir_id(mod_id.hir_id()); + self.visit_hir_id(mod_def.hir_id.hir_id()); } } } diff --git a/tests/narxia-test-runner/tests/visitor_visits_all_non_whitespace_text.rs b/tests/narxia-test-runner/tests/visitor_visits_all_non_whitespace_text.rs index 72d2e5e..0e9d6e5 100644 --- a/tests/narxia-test-runner/tests/visitor_visits_all_non_whitespace_text.rs +++ b/tests/narxia-test-runner/tests/visitor_visits_all_non_whitespace_text.rs @@ -58,11 +58,7 @@ impl<'hir> HirVisitor<'hir> for OrphanSpanVisitor<'hir> { self.visit_token_span(ident.span); } - fn visit_use_stmt( - &mut self, - _: narxia_hir::hir::UseStmtId, - use_stmt: &'hir narxia_hir::hir::UseStmt, - ) { + fn visit_use_stmt(&mut self, use_stmt: &'hir narxia_hir::hir::UseStmt) { // due to the way we construct use statements, we need to ignore these self.ignore_sets.push((use_stmt.span.get_range(), ':')); self.ignore_sets.push((use_stmt.span.get_range(), '{'));