aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/adt.rs70
-rw-r--r--crates/ra_hir/src/code_model_api.rs16
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/ty.rs55
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs34
-rw-r--r--crates/ra_ide_api/src/marks.rs6
-rw-r--r--crates/ra_ide_api/src/navigation_target.rs13
7 files changed, 150 insertions, 46 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index ec6a10353..22bbad964 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -11,7 +11,7 @@ use ra_syntax::{
11 11
12use crate::{ 12use crate::{
13 Name, AsName, Struct, Enum, EnumVariant, Crate, 13 Name, AsName, Struct, Enum, EnumVariant, Crate,
14 HirDatabase, HirFileId, 14 HirDatabase, HirFileId, StructField, FieldSource,
15 type_ref::TypeRef, 15 type_ref::TypeRef,
16}; 16};
17 17
@@ -150,7 +150,7 @@ impl VariantData {
150impl VariantData { 150impl VariantData {
151 fn new(flavor: StructFlavor) -> Self { 151 fn new(flavor: StructFlavor) -> Self {
152 let inner = match flavor { 152 let inner = match flavor {
153 StructFlavor::Tuple(fl) => { 153 ast::StructFlavor::Tuple(fl) => {
154 let fields = fl 154 let fields = fl
155 .fields() 155 .fields()
156 .enumerate() 156 .enumerate()
@@ -161,7 +161,7 @@ impl VariantData {
161 .collect(); 161 .collect();
162 VariantDataInner::Tuple(fields) 162 VariantDataInner::Tuple(fields)
163 } 163 }
164 StructFlavor::Named(fl) => { 164 ast::StructFlavor::Named(fl) => {
165 let fields = fl 165 let fields = fl
166 .fields() 166 .fields()
167 .map(|fd| StructFieldData { 167 .map(|fd| StructFieldData {
@@ -171,8 +171,70 @@ impl VariantData {
171 .collect(); 171 .collect();
172 VariantDataInner::Struct(fields) 172 VariantDataInner::Struct(fields)
173 } 173 }
174 StructFlavor::Unit => VariantDataInner::Unit, 174 ast::StructFlavor::Unit => VariantDataInner::Unit,
175 }; 175 };
176 VariantData(inner) 176 VariantData(inner)
177 } 177 }
178} 178}
179
180#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
181pub enum VariantDef {
182 Struct(Struct),
183 EnumVariant(EnumVariant),
184}
185impl_froms!(VariantDef: Struct, EnumVariant);
186
187impl VariantDef {
188 pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
189 match self {
190 VariantDef::Struct(it) => it.field(db, name),
191 VariantDef::EnumVariant(it) => it.field(db, name),
192 }
193 }
194 pub(crate) fn variant_data(self, db: &impl HirDatabase) -> Arc<VariantData> {
195 match self {
196 VariantDef::Struct(it) => it.variant_data(db),
197 VariantDef::EnumVariant(it) => it.variant_data(db),
198 }
199 }
200}
201
202impl StructField {
203 pub(crate) fn source_impl(&self, db: &impl HirDatabase) -> (HirFileId, FieldSource) {
204 let var_data = self.parent.variant_data(db);
205 let fields = var_data.fields().unwrap();
206 let ss;
207 let es;
208 let (file_id, struct_flavor) = match self.parent {
209 VariantDef::Struct(s) => {
210 let (file_id, source) = s.source(db);
211 ss = source;
212 (file_id, ss.flavor())
213 }
214 VariantDef::EnumVariant(e) => {
215 let (file_id, source) = e.source(db);
216 es = source;
217 (file_id, es.flavor())
218 }
219 };
220
221 let field_sources = match struct_flavor {
222 ast::StructFlavor::Tuple(fl) => fl
223 .fields()
224 .map(|it| FieldSource::Pos(it.to_owned()))
225 .collect(),
226 ast::StructFlavor::Named(fl) => fl
227 .fields()
228 .map(|it| FieldSource::Named(it.to_owned()))
229 .collect(),
230 ast::StructFlavor::Unit => Vec::new(),
231 };
232 let field = field_sources
233 .into_iter()
234 .zip(fields.iter())
235 .find(|(_syntax, (id, _))| *id == self.id)
236 .unwrap()
237 .0;
238 (file_id, field)
239 }
240}
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 118562984..fdea5be57 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -10,8 +10,8 @@ use crate::{
10 nameres::{ModuleScope, lower::ImportId}, 10 nameres::{ModuleScope, lower::ImportId},
11 db::HirDatabase, 11 db::HirDatabase,
12 expr::BodySyntaxMapping, 12 expr::BodySyntaxMapping,
13 ty::{InferenceResult, VariantDef}, 13 ty::InferenceResult,
14 adt::{EnumVariantId, StructFieldId}, 14 adt::{EnumVariantId, StructFieldId, VariantDef},
15 generics::GenericParams, 15 generics::GenericParams,
16 docs::{Documentation, Docs, docs_from_ast}, 16 docs::{Documentation, Docs, docs_from_ast},
17 module_tree::ModuleId, 17 module_tree::ModuleId,
@@ -179,10 +179,16 @@ impl Module {
179 179
180#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 180#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
181pub struct StructField { 181pub struct StructField {
182 parent: VariantDef, 182 pub(crate) parent: VariantDef,
183 pub(crate) id: StructFieldId, 183 pub(crate) id: StructFieldId,
184} 184}
185 185
186#[derive(Debug)]
187pub enum FieldSource {
188 Named(TreeArc<ast::NamedFieldDef>),
189 Pos(TreeArc<ast::PosField>),
190}
191
186impl StructField { 192impl StructField {
187 pub fn name(&self, db: &impl HirDatabase) -> Name { 193 pub fn name(&self, db: &impl HirDatabase) -> Name {
188 self.parent.variant_data(db).fields().unwrap()[self.id] 194 self.parent.variant_data(db).fields().unwrap()[self.id]
@@ -190,6 +196,10 @@ impl StructField {
190 .clone() 196 .clone()
191 } 197 }
192 198
199 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, FieldSource) {
200 self.source_impl(db)
201 }
202
193 pub fn ty(&self, db: &impl HirDatabase) -> Ty { 203 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
194 db.type_for_field(*self) 204 db.type_for_field(*self)
195 } 205 }
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 596f9c38c..eaf8565ee 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -68,7 +68,7 @@ pub use self::code_model_api::{
68 Module, ModuleDef, ModuleSource, Problem, 68 Module, ModuleDef, ModuleSource, Problem,
69 Struct, Enum, EnumVariant, 69 Struct, Enum, EnumVariant,
70 Function, FnSignature, ScopeEntryWithSyntax, 70 Function, FnSignature, ScopeEntryWithSyntax,
71 StructField, 71 StructField, FieldSource,
72 Static, Const, 72 Static, Const,
73 Trait, Type, 73 Trait, Type,
74}; 74};
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index c57e222dd..714eaaae5 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -38,7 +38,7 @@ use crate::{
38 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, 38 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat},
39 generics::GenericParams, 39 generics::GenericParams,
40 path::GenericArg, 40 path::GenericArg,
41 adt::VariantData, 41 adt::VariantDef,
42}; 42};
43 43
44/// The ID of a type variable. 44/// The ID of a type variable.
@@ -696,28 +696,6 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty {
696 } 696 }
697} 697}
698 698
699#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
700pub enum VariantDef {
701 Struct(Struct),
702 EnumVariant(EnumVariant),
703}
704impl_froms!(VariantDef: Struct, EnumVariant);
705
706impl VariantDef {
707 pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
708 match self {
709 VariantDef::Struct(it) => it.field(db, name),
710 VariantDef::EnumVariant(it) => it.field(db, name),
711 }
712 }
713 pub(crate) fn variant_data(self, db: &impl HirDatabase) -> Arc<VariantData> {
714 match self {
715 VariantDef::Struct(it) => it.variant_data(db),
716 VariantDef::EnumVariant(it) => it.variant_data(db),
717 }
718 }
719}
720
721pub(super) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { 699pub(super) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty {
722 let parent_def = field.parent_def(db); 700 let parent_def = field.parent_def(db);
723 let (generics, module) = match parent_def { 701 let (generics, module) = match parent_def {
@@ -732,8 +710,10 @@ pub(super) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty {
732/// The result of type inference: A mapping from expressions and patterns to types. 710/// The result of type inference: A mapping from expressions and patterns to types.
733#[derive(Clone, PartialEq, Eq, Debug)] 711#[derive(Clone, PartialEq, Eq, Debug)]
734pub struct InferenceResult { 712pub struct InferenceResult {
735 /// For each method call expr, record the function it resolved to. 713 /// For each method call expr, records the function it resolves to.
736 method_resolutions: FxHashMap<ExprId, Function>, 714 method_resolutions: FxHashMap<ExprId, Function>,
715 /// For each field access expr, records the field it resolves to.
716 field_resolutions: FxHashMap<ExprId, StructField>,
737 type_of_expr: ArenaMap<ExprId, Ty>, 717 type_of_expr: ArenaMap<ExprId, Ty>,
738 type_of_pat: ArenaMap<PatId, Ty>, 718 type_of_pat: ArenaMap<PatId, Ty>,
739} 719}
@@ -742,6 +722,9 @@ impl InferenceResult {
742 pub fn method_resolution(&self, expr: ExprId) -> Option<Function> { 722 pub fn method_resolution(&self, expr: ExprId) -> Option<Function> {
743 self.method_resolutions.get(&expr).map(|it| *it) 723 self.method_resolutions.get(&expr).map(|it| *it)
744 } 724 }
725 pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> {
726 self.field_resolutions.get(&expr).map(|it| *it)
727 }
745} 728}
746 729
747impl Index<ExprId> for InferenceResult { 730impl Index<ExprId> for InferenceResult {
@@ -770,6 +753,7 @@ struct InferenceContext<'a, D: HirDatabase> {
770 impl_block: Option<ImplBlock>, 753 impl_block: Option<ImplBlock>,
771 var_unification_table: InPlaceUnificationTable<TypeVarId>, 754 var_unification_table: InPlaceUnificationTable<TypeVarId>,
772 method_resolutions: FxHashMap<ExprId, Function>, 755 method_resolutions: FxHashMap<ExprId, Function>,
756 field_resolutions: FxHashMap<ExprId, StructField>,
773 type_of_expr: ArenaMap<ExprId, Ty>, 757 type_of_expr: ArenaMap<ExprId, Ty>,
774 type_of_pat: ArenaMap<PatId, Ty>, 758 type_of_pat: ArenaMap<PatId, Ty>,
775 /// The return type of the function being inferred. 759 /// The return type of the function being inferred.
@@ -861,6 +845,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
861 ) -> Self { 845 ) -> Self {
862 InferenceContext { 846 InferenceContext {
863 method_resolutions: FxHashMap::default(), 847 method_resolutions: FxHashMap::default(),
848 field_resolutions: FxHashMap::default(),
864 type_of_expr: ArenaMap::default(), 849 type_of_expr: ArenaMap::default(),
865 type_of_pat: ArenaMap::default(), 850 type_of_pat: ArenaMap::default(),
866 var_unification_table: InPlaceUnificationTable::new(), 851 var_unification_table: InPlaceUnificationTable::new(),
@@ -886,6 +871,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
886 } 871 }
887 InferenceResult { 872 InferenceResult {
888 method_resolutions: mem::replace(&mut self.method_resolutions, Default::default()), 873 method_resolutions: mem::replace(&mut self.method_resolutions, Default::default()),
874 field_resolutions: mem::replace(&mut self.field_resolutions, Default::default()),
889 type_of_expr: expr_types, 875 type_of_expr: expr_types,
890 type_of_pat: pat_types, 876 type_of_pat: pat_types,
891 } 877 }
@@ -899,6 +885,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
899 self.method_resolutions.insert(expr, func); 885 self.method_resolutions.insert(expr, func);
900 } 886 }
901 887
888 fn write_field_resolution(&mut self, expr: ExprId, field: StructField) {
889 self.field_resolutions.insert(expr, field);
890 }
891
902 fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { 892 fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
903 self.type_of_pat.insert(pat, ty); 893 self.type_of_pat.insert(pat, ty);
904 } 894 }
@@ -1251,9 +1241,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1251 ty 1241 ty
1252 } 1242 }
1253 1243
1254 fn infer_expr(&mut self, expr: ExprId, expected: &Expectation) -> Ty { 1244 fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
1255 let body = Arc::clone(&self.body); // avoid borrow checker problem 1245 let body = Arc::clone(&self.body); // avoid borrow checker problem
1256 let ty = match &body[expr] { 1246 let ty = match &body[tgt_expr] {
1257 Expr::Missing => Ty::Unknown, 1247 Expr::Missing => Ty::Unknown,
1258 Expr::If { 1248 Expr::If {
1259 condition, 1249 condition,
@@ -1344,7 +1334,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1344 let resolved = receiver_ty.clone().lookup_method(self.db, method_name); 1334 let resolved = receiver_ty.clone().lookup_method(self.db, method_name);
1345 let method_ty = match resolved { 1335 let method_ty = match resolved {
1346 Some(func) => { 1336 Some(func) => {
1347 self.write_method_resolution(expr, func); 1337 self.write_method_resolution(tgt_expr, func);
1348 self.db.type_for_def(func.into()) 1338 self.db.type_for_def(func.into())
1349 } 1339 }
1350 None => Ty::Unknown, 1340 None => Ty::Unknown,
@@ -1389,7 +1379,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1389 1379
1390 expected.ty 1380 expected.ty
1391 } 1381 }
1392 Expr::Path(p) => self.infer_path_expr(expr, p).unwrap_or(Ty::Unknown), 1382 Expr::Path(p) => self.infer_path_expr(tgt_expr, p).unwrap_or(Ty::Unknown),
1393 Expr::Continue => Ty::Never, 1383 Expr::Continue => Ty::Never,
1394 Expr::Break { expr } => { 1384 Expr::Break { expr } => {
1395 if let Some(expr) = expr { 1385 if let Some(expr) = expr {
@@ -1436,9 +1426,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1436 def_id: AdtDef::Struct(s), 1426 def_id: AdtDef::Struct(s),
1437 ref substs, 1427 ref substs,
1438 .. 1428 ..
1439 } => s 1429 } => s.field(self.db, name).map(|field| {
1440 .field(self.db, name) 1430 self.write_field_resolution(tgt_expr, field);
1441 .map(|field| field.ty(self.db).subst(substs)), 1431 field.ty(self.db).subst(substs)
1432 }),
1442 _ => None, 1433 _ => None,
1443 }) 1434 })
1444 .unwrap_or(Ty::Unknown); 1435 .unwrap_or(Ty::Unknown);
@@ -1545,7 +1536,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1545 let ty = self.insert_type_vars_shallow(ty); 1536 let ty = self.insert_type_vars_shallow(ty);
1546 self.unify(&ty, &expected.ty); 1537 self.unify(&ty, &expected.ty);
1547 let ty = self.resolve_ty_as_possible(ty); 1538 let ty = self.resolve_ty_as_possible(ty);
1548 self.write_expr_ty(expr, ty.clone()); 1539 self.write_expr_ty(tgt_expr, ty.clone());
1549 ty 1540 ty
1550 } 1541 }
1551 1542
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 46bdde00d..45b4c56ef 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -3,6 +3,7 @@ use ra_syntax::{
3 AstNode, ast, 3 AstNode, ast,
4 algo::find_node_at_offset, 4 algo::find_node_at_offset,
5}; 5};
6use test_utils::tested_by;
6 7
7use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; 8use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo};
8 9
@@ -60,6 +61,7 @@ pub(crate) fn reference_definition(
60 .parent() 61 .parent()
61 .and_then(ast::MethodCallExpr::cast) 62 .and_then(ast::MethodCallExpr::cast)
62 { 63 {
64 tested_by!(goto_definition_works_for_methods);
63 let infer_result = function.infer(db); 65 let infer_result = function.infer(db);
64 let syntax_mapping = function.body_syntax_mapping(db); 66 let syntax_mapping = function.body_syntax_mapping(db);
65 let expr = ast::Expr::cast(method_call.syntax()).unwrap(); 67 let expr = ast::Expr::cast(method_call.syntax()).unwrap();
@@ -70,6 +72,19 @@ pub(crate) fn reference_definition(
70 return Exact(NavigationTarget::from_function(db, func)); 72 return Exact(NavigationTarget::from_function(db, func));
71 }; 73 };
72 } 74 }
75 // It could also be a field access
76 if let Some(field_expr) = name_ref.syntax().parent().and_then(ast::FieldExpr::cast) {
77 tested_by!(goto_definition_works_for_fields);
78 let infer_result = function.infer(db);
79 let syntax_mapping = function.body_syntax_mapping(db);
80 let expr = ast::Expr::cast(field_expr.syntax()).unwrap();
81 if let Some(field) = syntax_mapping
82 .node_expr(expr)
83 .and_then(|it| infer_result.field_resolution(it))
84 {
85 return Exact(NavigationTarget::from_field(db, field));
86 };
87 }
73 } 88 }
74 // Then try module name resolution 89 // Then try module name resolution
75 if let Some(module) = hir::source_binder::module_from_child_node(db, file_id, name_ref.syntax()) 90 if let Some(module) = hir::source_binder::module_from_child_node(db, file_id, name_ref.syntax())
@@ -117,6 +132,8 @@ fn name_definition(
117 132
118#[cfg(test)] 133#[cfg(test)]
119mod tests { 134mod tests {
135 use test_utils::covers;
136
120 use crate::mock_analysis::analysis_and_position; 137 use crate::mock_analysis::analysis_and_position;
121 138
122 fn check_goto(fixuture: &str, expected: &str) { 139 fn check_goto(fixuture: &str, expected: &str) {
@@ -183,6 +200,7 @@ mod tests {
183 200
184 #[test] 201 #[test]
185 fn goto_definition_works_for_methods() { 202 fn goto_definition_works_for_methods() {
203 covers!(goto_definition_works_for_methods);
186 check_goto( 204 check_goto(
187 " 205 "
188 //- /lib.rs 206 //- /lib.rs
@@ -197,15 +215,23 @@ mod tests {
197 ", 215 ",
198 "frobnicate FN_DEF FileId(1) [27; 52) [30; 40)", 216 "frobnicate FN_DEF FileId(1) [27; 52) [30; 40)",
199 ); 217 );
218 }
200 219
220 #[test]
221 fn goto_definition_works_for_fields() {
222 covers!(goto_definition_works_for_fields);
201 check_goto( 223 check_goto(
202 " 224 "
203 //- /lib.rs 225 //- /lib.rs
204 mod <|>foo; 226 struct Foo {
205 //- /foo/mod.rs 227 spam: u32,
206 // empty 228 }
229
230 fn bar(foo: &Foo) {
231 foo.spam<|>;
232 }
207 ", 233 ",
208 "foo SOURCE_FILE FileId(2) [0; 10)", 234 "spam NAMED_FIELD_DEF FileId(1) [17; 26) [17; 21)",
209 ); 235 );
210 } 236 }
211} 237}
diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide_api/src/marks.rs
index dc5b2702a..e33bf6c91 100644
--- a/crates/ra_ide_api/src/marks.rs
+++ b/crates/ra_ide_api/src/marks.rs
@@ -1 +1,5 @@
1test_utils::marks!(inserts_parens_for_function_calls); 1test_utils::marks!(
2 inserts_parens_for_function_calls
3 goto_definition_works_for_methods
4 goto_definition_works_for_fields
5);
diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs
index c5be8e01b..ae2175dbc 100644
--- a/crates/ra_ide_api/src/navigation_target.rs
+++ b/crates/ra_ide_api/src/navigation_target.rs
@@ -3,7 +3,7 @@ use ra_syntax::{
3 SyntaxNode, AstNode, SmolStr, TextRange, ast, 3 SyntaxNode, AstNode, SmolStr, TextRange, ast,
4 SyntaxKind::{self, NAME}, 4 SyntaxKind::{self, NAME},
5}; 5};
6use hir::{ModuleSource}; 6use hir::{ModuleSource, FieldSource};
7 7
8use crate::{FileSymbol, db::RootDatabase}; 8use crate::{FileSymbol, db::RootDatabase};
9 9
@@ -101,6 +101,17 @@ impl NavigationTarget {
101 NavigationTarget::from_named(file_id.original_file(db), &*fn_def) 101 NavigationTarget::from_named(file_id.original_file(db), &*fn_def)
102 } 102 }
103 103
104 pub(crate) fn from_field(db: &RootDatabase, field: hir::StructField) -> NavigationTarget {
105 let (file_id, field) = field.source(db);
106 let file_id = file_id.original_file(db);
107 match field {
108 FieldSource::Named(it) => NavigationTarget::from_named(file_id, &*it),
109 FieldSource::Pos(it) => {
110 NavigationTarget::from_syntax(file_id, "".into(), None, it.syntax())
111 }
112 }
113 }
114
104 // TODO once Def::Item is gone, this should be able to always return a NavigationTarget 115 // TODO once Def::Item is gone, this should be able to always return a NavigationTarget
105 pub(crate) fn from_def( 116 pub(crate) fn from_def(
106 db: &RootDatabase, 117 db: &RootDatabase,