aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-12-04 20:44:00 +0000
committerAleksey Kladov <[email protected]>2018-12-04 20:44:00 +0000
commitd8b0379e1063941331253905795699a918233ef9 (patch)
tree18a7ef94cdf6575ed1954648287b284c3ace6451 /crates
parent947e3350e045aab1db9b232542425a3faa856907 (diff)
Add functions to DefId
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_analysis/src/completion/reference_completion.rs2
-rw-r--r--crates/ra_analysis/src/db.rs9
-rw-r--r--crates/ra_analysis/src/imp.rs41
-rw-r--r--crates/ra_analysis/src/lib.rs2
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/function/mod.rs41
-rw-r--r--crates/ra_hir/src/lib.rs20
-rw-r--r--crates/ra_hir/src/mock.rs9
-rw-r--r--crates/ra_hir/src/module/mod.rs23
-rw-r--r--crates/ra_hir/src/query_definitions.rs22
10 files changed, 90 insertions, 83 deletions
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs
index 8ea7478a8..f483ed045 100644
--- a/crates/ra_analysis/src/completion/reference_completion.rs
+++ b/crates/ra_analysis/src/completion/reference_completion.rs
@@ -163,7 +163,7 @@ fn complete_path(
163 }; 163 };
164 let target_module = match def_id.resolve(db)? { 164 let target_module = match def_id.resolve(db)? {
165 Def::Module(it) => it, 165 Def::Module(it) => it,
166 Def::Item => return Ok(()), 166 _ => return Ok(()),
167 }; 167 };
168 let module_scope = target_module.scope(db)?; 168 let module_scope = target_module.scope(db)?;
169 let completions = module_scope.entries().map(|(name, _res)| CompletionItem { 169 let completions = module_scope.entries().map(|(name, _res)| CompletionItem {
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index df2ef293d..b8d774eb5 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -1,7 +1,7 @@
1use std::sync::Arc; 1use std::sync::Arc;
2use salsa::{self, Database}; 2use salsa::{self, Database};
3use ra_db::{LocationIntener, BaseDatabase}; 3use ra_db::{LocationIntener, BaseDatabase};
4use hir::{self, DefId, DefLoc, FnId, SourceItemId}; 4use hir::{self, DefId, DefLoc};
5 5
6use crate::{ 6use crate::{
7 symbol_index, 7 symbol_index,
@@ -15,7 +15,6 @@ pub(crate) struct RootDatabase {
15 15
16#[derive(Debug, Default)] 16#[derive(Debug, Default)]
17struct IdMaps { 17struct IdMaps {
18 fns: LocationIntener<SourceItemId, FnId>,
19 defs: LocationIntener<DefLoc, DefId>, 18 defs: LocationIntener<DefLoc, DefId>,
20} 19}
21 20
@@ -58,12 +57,6 @@ impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase {
58 } 57 }
59} 58}
60 59
61impl AsRef<LocationIntener<hir::SourceItemId, FnId>> for RootDatabase {
62 fn as_ref(&self) -> &LocationIntener<hir::SourceItemId, FnId> {
63 &self.id_maps.fns
64 }
65}
66
67salsa::database_storage! { 60salsa::database_storage! {
68 pub(crate) struct RootDatabaseStorage for RootDatabase { 61 pub(crate) struct RootDatabaseStorage for RootDatabase {
69 impl ra_db::FilesDatabase { 62 impl ra_db::FilesDatabase {
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index 942b5b945..fe1dfefea 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -210,7 +210,7 @@ impl AnalysisImpl {
210 let syntax = file.syntax(); 210 let syntax = file.syntax();
211 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { 211 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
212 if let Some(fn_descr) = 212 if let Some(fn_descr) =
213 hir::Function::guess_for_name_ref(&*self.db, position.file_id, name_ref) 213 hir::Function::guess_for_name_ref(&*self.db, position.file_id, name_ref)?
214 { 214 {
215 let scope = fn_descr.scope(&*self.db); 215 let scope = fn_descr.scope(&*self.db);
216 // First try to resolve the symbol locally 216 // First try to resolve the symbol locally
@@ -257,11 +257,11 @@ impl AnalysisImpl {
257 Ok(vec![]) 257 Ok(vec![])
258 } 258 }
259 259
260 pub fn find_all_refs(&self, position: FilePosition) -> Vec<(FileId, TextRange)> { 260 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
261 let file = self.db.source_file(position.file_id); 261 let file = self.db.source_file(position.file_id);
262 // Find the binding associated with the offset 262 // Find the binding associated with the offset
263 let (binding, descr) = match find_binding(&self.db, &file, position) { 263 let (binding, descr) = match find_binding(&self.db, &file, position)? {
264 None => return Vec::new(), 264 None => return Ok(Vec::new()),
265 Some(it) => it, 265 Some(it) => it,
266 }; 266 };
267 267
@@ -274,25 +274,36 @@ impl AnalysisImpl {
274 .map(|ref_desc| (position.file_id, ref_desc.range)), 274 .map(|ref_desc| (position.file_id, ref_desc.range)),
275 ); 275 );
276 276
277 return ret; 277 return Ok(ret);
278 278
279 fn find_binding<'a>( 279 fn find_binding<'a>(
280 db: &db::RootDatabase, 280 db: &db::RootDatabase,
281 source_file: &'a SourceFileNode, 281 source_file: &'a SourceFileNode,
282 position: FilePosition, 282 position: FilePosition,
283 ) -> Option<(ast::BindPat<'a>, hir::Function)> { 283 ) -> Cancelable<Option<(ast::BindPat<'a>, hir::Function)>> {
284 let syntax = source_file.syntax(); 284 let syntax = source_file.syntax();
285 if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) { 285 if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) {
286 let descr = hir::Function::guess_for_bind_pat(db, position.file_id, binding)?; 286 let descr = ctry!(hir::Function::guess_for_bind_pat(
287 return Some((binding, descr)); 287 db,
288 position.file_id,
289 binding
290 )?);
291 return Ok(Some((binding, descr)));
288 }; 292 };
289 let name_ref = find_node_at_offset::<ast::NameRef>(syntax, position.offset)?; 293 let name_ref = ctry!(find_node_at_offset::<ast::NameRef>(syntax, position.offset));
290 let descr = hir::Function::guess_for_name_ref(db, position.file_id, name_ref)?; 294 let descr = ctry!(hir::Function::guess_for_name_ref(
295 db,
296 position.file_id,
297 name_ref
298 )?);
291 let scope = descr.scope(db); 299 let scope = descr.scope(db);
292 let resolved = scope.resolve_local_name(name_ref)?; 300 let resolved = ctry!(scope.resolve_local_name(name_ref));
293 let resolved = resolved.ptr().resolve(source_file); 301 let resolved = resolved.ptr().resolve(source_file);
294 let binding = find_node_at_offset::<ast::BindPat>(syntax, resolved.range().end())?; 302 let binding = ctry!(find_node_at_offset::<ast::BindPat>(
295 Some((binding, descr)) 303 syntax,
304 resolved.range().end()
305 ));
306 Ok(Some((binding, descr)))
296 } 307 }
297 } 308 }
298 309
@@ -408,7 +419,9 @@ impl AnalysisImpl {
408 if fs.kind == FN_DEF { 419 if fs.kind == FN_DEF {
409 let fn_file = self.db.source_file(fn_file_id); 420 let fn_file = self.db.source_file(fn_file_id);
410 if let Some(fn_def) = find_node_at_offset(fn_file.syntax(), fs.node_range.start()) { 421 if let Some(fn_def) = find_node_at_offset(fn_file.syntax(), fs.node_range.start()) {
411 let descr = hir::Function::guess_from_source(&*self.db, fn_file_id, fn_def); 422 let descr = ctry!(hir::Function::guess_from_source(
423 &*self.db, fn_file_id, fn_def
424 )?);
412 if let Some(descriptor) = descr.signature_info(&*self.db) { 425 if let Some(descriptor) = descr.signature_info(&*self.db) {
413 // If we have a calling expression let's find which argument we are on 426 // If we have a calling expression let's find which argument we are on
414 let mut current_parameter = None; 427 let mut current_parameter = None;
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index 12df580ba..90528edfd 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -248,7 +248,7 @@ impl Analysis {
248 self.imp.approximately_resolve_symbol(position) 248 self.imp.approximately_resolve_symbol(position)
249 } 249 }
250 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { 250 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
251 Ok(self.imp.find_all_refs(position)) 251 self.imp.find_all_refs(position)
252 } 252 }
253 pub fn doc_comment_for( 253 pub fn doc_comment_for(
254 &self, 254 &self,
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 2f01bae6d..ff41fd326 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -7,10 +7,11 @@ use ra_syntax::{
7use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, FileId, Cancelable}; 7use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, FileId, Cancelable};
8 8
9use crate::{ 9use crate::{
10 DefLoc, DefId, FnId, 10 DefLoc, DefId,
11 SourceFileItems, SourceItemId, 11 SourceFileItems, SourceItemId,
12 query_definitions, 12 query_definitions,
13 FnScopes, 13 FnScopes,
14 function::FnId,
14 module::{ModuleId, ModuleTree, ModuleSource, 15 module::{ModuleId, ModuleTree, ModuleSource,
15 nameres::{ItemMap, InputModuleItems}}, 16 nameres::{ItemMap, InputModuleItems}},
16}; 17};
@@ -19,7 +20,6 @@ salsa::query_group! {
19 20
20pub trait HirDatabase: SyntaxDatabase 21pub trait HirDatabase: SyntaxDatabase
21 + AsRef<LocationIntener<DefLoc, DefId>> 22 + AsRef<LocationIntener<DefLoc, DefId>>
22 + AsRef<LocationIntener<SourceItemId, FnId>>
23{ 23{
24 fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> { 24 fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> {
25 type FnScopesQuery; 25 type FnScopesQuery;
diff --git a/crates/ra_hir/src/function/mod.rs b/crates/ra_hir/src/function/mod.rs
index c8af2e54f..a6757601e 100644
--- a/crates/ra_hir/src/function/mod.rs
+++ b/crates/ra_hir/src/function/mod.rs
@@ -12,19 +12,15 @@ use ra_syntax::{
12use ra_db::FileId; 12use ra_db::FileId;
13 13
14use crate::{ 14use crate::{
15 FnId, HirDatabase, SourceItemId, 15 Cancelable,
16 DefLoc, DefKind, DefId, HirDatabase, SourceItemId,
17 Module,
16}; 18};
17 19
18pub use self::scope::FnScopes; 20pub use self::scope::FnScopes;
19 21
20impl FnId { 22#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
21 pub fn get(db: &impl HirDatabase, file_id: FileId, fn_def: ast::FnDef) -> FnId { 23pub struct FnId(pub(crate) DefId);
22 let file_items = db.file_items(file_id);
23 let item_id = file_items.id_of(fn_def.syntax());
24 let item_id = SourceItemId { file_id, item_id };
25 FnId::from_loc(db, &item_id)
26 }
27}
28 24
29pub struct Function { 25pub struct Function {
30 fn_id: FnId, 26 fn_id: FnId,
@@ -35,16 +31,26 @@ impl Function {
35 db: &impl HirDatabase, 31 db: &impl HirDatabase,
36 file_id: FileId, 32 file_id: FileId,
37 fn_def: ast::FnDef, 33 fn_def: ast::FnDef,
38 ) -> Function { 34 ) -> Cancelable<Option<Function>> {
39 let fn_id = FnId::get(db, file_id, fn_def); 35 let module = ctry!(Module::guess_from_child_node(db, file_id, fn_def.syntax())?);
40 Function { fn_id } 36 let file_items = db.file_items(file_id);
37 let item_id = file_items.id_of(fn_def.syntax());
38 let source_item_id = SourceItemId { file_id, item_id };
39 let def_loc = DefLoc {
40 kind: DefKind::Function,
41 source_root_id: module.source_root_id,
42 module_id: module.module_id,
43 source_item_id,
44 };
45 let fn_id = FnId(def_loc.id(db));
46 Ok(Some(Function { fn_id }))
41 } 47 }
42 48
43 pub fn guess_for_name_ref( 49 pub fn guess_for_name_ref(
44 db: &impl HirDatabase, 50 db: &impl HirDatabase,
45 file_id: FileId, 51 file_id: FileId,
46 name_ref: ast::NameRef, 52 name_ref: ast::NameRef,
47 ) -> Option<Function> { 53 ) -> Cancelable<Option<Function>> {
48 Function::guess_for_node(db, file_id, name_ref.syntax()) 54 Function::guess_for_node(db, file_id, name_ref.syntax())
49 } 55 }
50 56
@@ -52,7 +58,7 @@ impl Function {
52 db: &impl HirDatabase, 58 db: &impl HirDatabase,
53 file_id: FileId, 59 file_id: FileId,
54 bind_pat: ast::BindPat, 60 bind_pat: ast::BindPat,
55 ) -> Option<Function> { 61 ) -> Cancelable<Option<Function>> {
56 Function::guess_for_node(db, file_id, bind_pat.syntax()) 62 Function::guess_for_node(db, file_id, bind_pat.syntax())
57 } 63 }
58 64
@@ -60,10 +66,9 @@ impl Function {
60 db: &impl HirDatabase, 66 db: &impl HirDatabase,
61 file_id: FileId, 67 file_id: FileId,
62 node: SyntaxNodeRef, 68 node: SyntaxNodeRef,
63 ) -> Option<Function> { 69 ) -> Cancelable<Option<Function>> {
64 let fn_def = node.ancestors().find_map(ast::FnDef::cast)?; 70 let fn_def = ctry!(node.ancestors().find_map(ast::FnDef::cast));
65 let res = Function::guess_from_source(db, file_id, fn_def); 71 Function::guess_from_source(db, file_id, fn_def)
66 Some(res)
67 } 72 }
68 73
69 pub fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> { 74 pub fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> {
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index ffc99fd5f..dbcc5e46d 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -42,28 +42,13 @@ pub use self::{
42pub use self::function::FnSignatureInfo; 42pub use self::function::FnSignatureInfo;
43 43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
45pub struct FnId(u32);
46ra_db::impl_numeric_id!(FnId);
47
48impl FnId {
49 pub fn from_loc(
50 db: &impl AsRef<LocationIntener<SourceItemId, FnId>>,
51 loc: &SourceItemId,
52 ) -> FnId {
53 db.as_ref().loc2id(loc)
54 }
55 pub fn loc(self, db: &impl AsRef<LocationIntener<SourceItemId, FnId>>) -> SourceItemId {
56 db.as_ref().id2loc(self)
57 }
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
61pub struct DefId(u32); 45pub struct DefId(u32);
62ra_db::impl_numeric_id!(DefId); 46ra_db::impl_numeric_id!(DefId);
63 47
64#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 48#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
65pub(crate) enum DefKind { 49pub(crate) enum DefKind {
66 Module, 50 Module,
51 Function,
67 Item, 52 Item,
68} 53}
69 54
@@ -89,6 +74,7 @@ impl DefLoc {
89 74
90pub enum Def { 75pub enum Def {
91 Module(Module), 76 Module(Module),
77 Function(Function),
92 Item, 78 Item,
93} 79}
94 80
@@ -100,7 +86,7 @@ impl DefId {
100 let descr = Module::new(db, loc.source_root_id, loc.module_id)?; 86 let descr = Module::new(db, loc.source_root_id, loc.module_id)?;
101 Def::Module(descr) 87 Def::Module(descr)
102 } 88 }
103 DefKind::Item => Def::Item, 89 DefKind::Item | DefKind::Function => Def::Item,
104 }; 90 };
105 Ok(res) 91 Ok(res)
106 } 92 }
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index 8e256b89f..e855df11d 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -6,7 +6,7 @@ use ra_db::{LocationIntener, BaseDatabase, FilePosition, mock::FileMap, FileId,
6use relative_path::RelativePathBuf; 6use relative_path::RelativePathBuf;
7use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset}; 7use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset};
8 8
9use crate::{db, DefId, DefLoc, FnId, SourceItemId}; 9use crate::{db, DefId, DefLoc};
10 10
11#[derive(Debug)] 11#[derive(Debug)]
12pub(crate) struct MockDatabase { 12pub(crate) struct MockDatabase {
@@ -65,7 +65,6 @@ impl MockDatabase {
65 65
66#[derive(Debug, Default)] 66#[derive(Debug, Default)]
67struct IdMaps { 67struct IdMaps {
68 fns: LocationIntener<SourceItemId, FnId>,
69 defs: LocationIntener<DefLoc, DefId>, 68 defs: LocationIntener<DefLoc, DefId>,
70} 69}
71 70
@@ -117,12 +116,6 @@ impl AsRef<LocationIntener<DefLoc, DefId>> for MockDatabase {
117 } 116 }
118} 117}
119 118
120impl AsRef<LocationIntener<SourceItemId, FnId>> for MockDatabase {
121 fn as_ref(&self) -> &LocationIntener<SourceItemId, FnId> {
122 &self.id_maps.fns
123 }
124}
125
126impl MockDatabase { 119impl MockDatabase {
127 pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> { 120 pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> {
128 *self.events.lock() = Some(Vec::new()); 121 *self.events.lock() = Some(Vec::new());
diff --git a/crates/ra_hir/src/module/mod.rs b/crates/ra_hir/src/module/mod.rs
index 08ce7c8d1..11e6e8e75 100644
--- a/crates/ra_hir/src/module/mod.rs
+++ b/crates/ra_hir/src/module/mod.rs
@@ -8,7 +8,7 @@ use ra_editor::find_node_at_offset;
8use ra_syntax::{ 8use ra_syntax::{
9 algo::generate, 9 algo::generate,
10 ast::{self, AstNode, NameOwner}, 10 ast::{self, AstNode, NameOwner},
11 SmolStr, SyntaxNode, 11 SmolStr, SyntaxNode, SyntaxNodeRef,
12}; 12};
13use ra_db::{SourceRootId, FileId, FilePosition, Cancelable}; 13use ra_db::{SourceRootId, FileId, FilePosition, Cancelable};
14use relative_path::RelativePathBuf; 14use relative_path::RelativePathBuf;
@@ -25,8 +25,8 @@ pub use self::nameres::ModuleScope;
25#[derive(Debug, Clone)] 25#[derive(Debug, Clone)]
26pub struct Module { 26pub struct Module {
27 tree: Arc<ModuleTree>, 27 tree: Arc<ModuleTree>,
28 source_root_id: SourceRootId, 28 pub(crate) source_root_id: SourceRootId,
29 module_id: ModuleId, 29 pub(crate) module_id: ModuleId,
30} 30}
31 31
32impl Module { 32impl Module {
@@ -57,6 +57,23 @@ impl Module {
57 Module::guess_from_source(db, module_source) 57 Module::guess_from_source(db, module_source)
58 } 58 }
59 59
60 pub fn guess_from_child_node(
61 db: &impl HirDatabase,
62 file_id: FileId,
63 node: SyntaxNodeRef,
64 ) -> Cancelable<Option<Module>> {
65 let module_source = if let Some(m) = node
66 .ancestors()
67 .filter_map(ast::Module::cast)
68 .find(|it| !it.has_semi())
69 {
70 ModuleSource::new_inline(db, file_id, m)
71 } else {
72 ModuleSource::new_file(db, file_id)
73 };
74 Module::guess_from_source(db, module_source)
75 }
76
60 fn guess_from_source( 77 fn guess_from_source(
61 db: &impl HirDatabase, 78 db: &impl HirDatabase,
62 module_source: ModuleSource, 79 module_source: ModuleSource,
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs
index 59318f307..e4d721601 100644
--- a/crates/ra_hir/src/query_definitions.rs
+++ b/crates/ra_hir/src/query_definitions.rs
@@ -11,21 +11,21 @@ use ra_syntax::{
11use ra_db::{SourceRootId, FileId, Cancelable,}; 11use ra_db::{SourceRootId, FileId, Cancelable,};
12 12
13use crate::{ 13use crate::{
14 FnId, 14 SourceFileItems, SourceItemId, DefKind,
15 SourceFileItems, SourceItemId, 15 db::HirDatabase,
16 db::HirDatabase, 16 function::{FnScopes, FnId},
17 function::FnScopes, 17 module::{
18 module::{ 18 ModuleSource, ModuleSourceNode, ModuleId,
19 ModuleSource, ModuleSourceNode, ModuleId, 19 imp::Submodule,
20 imp::Submodule, 20 nameres::{InputModuleItems, ItemMap, Resolver},
21 nameres::{InputModuleItems, ItemMap, Resolver}, 21 },
22 },
23}; 22};
24 23
25/// Resolve `FnId` to the corresponding `SyntaxNode` 24/// Resolve `FnId` to the corresponding `SyntaxNode`
26pub(super) fn fn_syntax(db: &impl HirDatabase, fn_id: FnId) -> FnDefNode { 25pub(super) fn fn_syntax(db: &impl HirDatabase, fn_id: FnId) -> FnDefNode {
27 let item_id = fn_id.loc(db); 26 let def_loc = fn_id.0.loc(db);
28 let syntax = db.file_item(item_id); 27 assert!(def_loc.kind == DefKind::Function);
28 let syntax = db.file_item(def_loc.source_item_id);
29 FnDef::cast(syntax.borrowed()).unwrap().owned() 29 FnDef::cast(syntax.borrowed()).unwrap().owned()
30} 30}
31 31