]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/ide-db/src/defs.rs
Rollup merge of #102890 - camsteffen:adt-sized-representability, r=cjgillot
[rust.git] / src / tools / rust-analyzer / crates / ide-db / src / defs.rs
1 //! `NameDefinition` keeps information about the element we want to search references for.
2 //! The element is represented by `NameKind`. It's located inside some `container` and
3 //! has a `visibility`, which defines a search scope.
4 //! Note that the reference search is possible for not all of the classified items.
5
6 // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
7
8 use arrayvec::ArrayVec;
9 use hir::{
10     Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Crate, DeriveHelper, Field,
11     Function, GenericParam, HasVisibility, Impl, ItemInNs, Label, Local, Macro, Module, ModuleDef,
12     Name, PathResolution, Semantics, Static, ToolModule, Trait, TypeAlias, Variant, Visibility,
13 };
14 use stdx::impl_from;
15 use syntax::{
16     ast::{self, AstNode},
17     match_ast, SyntaxKind, SyntaxNode, SyntaxToken,
18 };
19
20 use crate::RootDatabase;
21
22 // FIXME: a more precise name would probably be `Symbol`?
23 #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
24 pub enum Definition {
25     Macro(Macro),
26     Field(Field),
27     Module(Module),
28     Function(Function),
29     Adt(Adt),
30     Variant(Variant),
31     Const(Const),
32     Static(Static),
33     Trait(Trait),
34     TypeAlias(TypeAlias),
35     BuiltinType(BuiltinType),
36     SelfType(Impl),
37     Local(Local),
38     GenericParam(GenericParam),
39     Label(Label),
40     DeriveHelper(DeriveHelper),
41     BuiltinAttr(BuiltinAttr),
42     ToolModule(ToolModule),
43 }
44
45 impl Definition {
46     pub fn canonical_module_path(&self, db: &RootDatabase) -> Option<impl Iterator<Item = Module>> {
47         self.module(db).map(|it| it.path_to_root(db).into_iter().rev())
48     }
49
50     pub fn krate(&self, db: &RootDatabase) -> Option<Crate> {
51         Some(match self {
52             Definition::Module(m) => m.krate(),
53             _ => self.module(db)?.krate(),
54         })
55     }
56
57     pub fn module(&self, db: &RootDatabase) -> Option<Module> {
58         let module = match self {
59             Definition::Macro(it) => it.module(db),
60             Definition::Module(it) => it.parent(db)?,
61             Definition::Field(it) => it.parent_def(db).module(db),
62             Definition::Function(it) => it.module(db),
63             Definition::Adt(it) => it.module(db),
64             Definition::Const(it) => it.module(db),
65             Definition::Static(it) => it.module(db),
66             Definition::Trait(it) => it.module(db),
67             Definition::TypeAlias(it) => it.module(db),
68             Definition::Variant(it) => it.module(db),
69             Definition::SelfType(it) => it.module(db),
70             Definition::Local(it) => it.module(db),
71             Definition::GenericParam(it) => it.module(db),
72             Definition::Label(it) => it.module(db),
73             Definition::DeriveHelper(it) => it.derive().module(db),
74             Definition::BuiltinAttr(_) | Definition::BuiltinType(_) | Definition::ToolModule(_) => {
75                 return None
76             }
77         };
78         Some(module)
79     }
80
81     pub fn visibility(&self, db: &RootDatabase) -> Option<Visibility> {
82         let vis = match self {
83             Definition::Field(sf) => sf.visibility(db),
84             Definition::Module(it) => it.visibility(db),
85             Definition::Function(it) => it.visibility(db),
86             Definition::Adt(it) => it.visibility(db),
87             Definition::Const(it) => it.visibility(db),
88             Definition::Static(it) => it.visibility(db),
89             Definition::Trait(it) => it.visibility(db),
90             Definition::TypeAlias(it) => it.visibility(db),
91             Definition::Variant(it) => it.visibility(db),
92             Definition::BuiltinType(_) => Visibility::Public,
93             Definition::Macro(_) => return None,
94             Definition::BuiltinAttr(_)
95             | Definition::ToolModule(_)
96             | Definition::SelfType(_)
97             | Definition::Local(_)
98             | Definition::GenericParam(_)
99             | Definition::Label(_)
100             | Definition::DeriveHelper(_) => return None,
101         };
102         Some(vis)
103     }
104
105     pub fn name(&self, db: &RootDatabase) -> Option<Name> {
106         let name = match self {
107             Definition::Macro(it) => it.name(db),
108             Definition::Field(it) => it.name(db),
109             Definition::Module(it) => it.name(db)?,
110             Definition::Function(it) => it.name(db),
111             Definition::Adt(it) => it.name(db),
112             Definition::Variant(it) => it.name(db),
113             Definition::Const(it) => it.name(db)?,
114             Definition::Static(it) => it.name(db),
115             Definition::Trait(it) => it.name(db),
116             Definition::TypeAlias(it) => it.name(db),
117             Definition::BuiltinType(it) => it.name(),
118             Definition::SelfType(_) => return None,
119             Definition::Local(it) => it.name(db),
120             Definition::GenericParam(it) => it.name(db),
121             Definition::Label(it) => it.name(db),
122             Definition::BuiltinAttr(_) => return None, // FIXME
123             Definition::ToolModule(_) => return None,  // FIXME
124             Definition::DeriveHelper(it) => it.name(db),
125         };
126         Some(name)
127     }
128 }
129
130 // FIXME: IdentClass as a name no longer fits
131 #[derive(Debug)]
132 pub enum IdentClass {
133     NameClass(NameClass),
134     NameRefClass(NameRefClass),
135     Operator(OperatorClass),
136 }
137
138 impl IdentClass {
139     pub fn classify_node(
140         sema: &Semantics<'_, RootDatabase>,
141         node: &SyntaxNode,
142     ) -> Option<IdentClass> {
143         match_ast! {
144             match node {
145                 ast::Name(name) => NameClass::classify(sema, &name).map(IdentClass::NameClass),
146                 ast::NameRef(name_ref) => NameRefClass::classify(sema, &name_ref).map(IdentClass::NameRefClass),
147                 ast::Lifetime(lifetime) => {
148                     NameClass::classify_lifetime(sema, &lifetime)
149                         .map(IdentClass::NameClass)
150                         .or_else(|| NameRefClass::classify_lifetime(sema, &lifetime).map(IdentClass::NameRefClass))
151                 },
152                 ast::AwaitExpr(await_expr) => OperatorClass::classify_await(sema, &await_expr).map(IdentClass::Operator),
153                 ast::BinExpr(bin_expr) => OperatorClass::classify_bin(sema, &bin_expr).map(IdentClass::Operator),
154                 ast::IndexExpr(index_expr) => OperatorClass::classify_index(sema, &index_expr).map(IdentClass::Operator),
155                 ast::PrefixExpr(prefix_expr) => OperatorClass::classify_prefix(sema,&prefix_expr).map(IdentClass::Operator),
156                 ast::TryExpr(try_expr) => OperatorClass::classify_try(sema,&try_expr).map(IdentClass::Operator),
157                 _ => None,
158             }
159         }
160     }
161
162     pub fn classify_token(
163         sema: &Semantics<'_, RootDatabase>,
164         token: &SyntaxToken,
165     ) -> Option<IdentClass> {
166         let parent = token.parent()?;
167         Self::classify_node(sema, &parent)
168     }
169
170     pub fn classify_lifetime(
171         sema: &Semantics<'_, RootDatabase>,
172         lifetime: &ast::Lifetime,
173     ) -> Option<IdentClass> {
174         NameRefClass::classify_lifetime(sema, lifetime)
175             .map(IdentClass::NameRefClass)
176             .or_else(|| NameClass::classify_lifetime(sema, lifetime).map(IdentClass::NameClass))
177     }
178
179     pub fn definitions(self) -> ArrayVec<Definition, 2> {
180         let mut res = ArrayVec::new();
181         match self {
182             IdentClass::NameClass(NameClass::Definition(it) | NameClass::ConstReference(it)) => {
183                 res.push(it)
184             }
185             IdentClass::NameClass(NameClass::PatFieldShorthand { local_def, field_ref }) => {
186                 res.push(Definition::Local(local_def));
187                 res.push(Definition::Field(field_ref));
188             }
189             IdentClass::NameRefClass(NameRefClass::Definition(it)) => res.push(it),
190             IdentClass::NameRefClass(NameRefClass::FieldShorthand { local_ref, field_ref }) => {
191                 res.push(Definition::Local(local_ref));
192                 res.push(Definition::Field(field_ref));
193             }
194             IdentClass::Operator(
195                 OperatorClass::Await(func)
196                 | OperatorClass::Prefix(func)
197                 | OperatorClass::Bin(func)
198                 | OperatorClass::Index(func)
199                 | OperatorClass::Try(func),
200             ) => res.push(Definition::Function(func)),
201         }
202         res
203     }
204
205     pub fn definitions_no_ops(self) -> ArrayVec<Definition, 2> {
206         let mut res = ArrayVec::new();
207         match self {
208             IdentClass::NameClass(NameClass::Definition(it) | NameClass::ConstReference(it)) => {
209                 res.push(it)
210             }
211             IdentClass::NameClass(NameClass::PatFieldShorthand { local_def, field_ref }) => {
212                 res.push(Definition::Local(local_def));
213                 res.push(Definition::Field(field_ref));
214             }
215             IdentClass::NameRefClass(NameRefClass::Definition(it)) => res.push(it),
216             IdentClass::NameRefClass(NameRefClass::FieldShorthand { local_ref, field_ref }) => {
217                 res.push(Definition::Local(local_ref));
218                 res.push(Definition::Field(field_ref));
219             }
220             IdentClass::Operator(_) => (),
221         }
222         res
223     }
224 }
225
226 /// On a first blush, a single `ast::Name` defines a single definition at some
227 /// scope. That is, that, by just looking at the syntactical category, we can
228 /// unambiguously define the semantic category.
229 ///
230 /// Sadly, that's not 100% true, there are special cases. To make sure that
231 /// callers handle all the special cases correctly via exhaustive matching, we
232 /// add a [`NameClass`] enum which lists all of them!
233 ///
234 /// A model special case is `None` constant in pattern.
235 #[derive(Debug)]
236 pub enum NameClass {
237     Definition(Definition),
238     /// `None` in `if let None = Some(82) {}`.
239     /// Syntactically, it is a name, but semantically it is a reference.
240     ConstReference(Definition),
241     /// `field` in `if let Foo { field } = foo`. Here, `ast::Name` both introduces
242     /// a definition into a local scope, and refers to an existing definition.
243     PatFieldShorthand {
244         local_def: Local,
245         field_ref: Field,
246     },
247 }
248
249 impl NameClass {
250     /// `Definition` defined by this name.
251     pub fn defined(self) -> Option<Definition> {
252         let res = match self {
253             NameClass::Definition(it) => it,
254             NameClass::ConstReference(_) => return None,
255             NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
256                 Definition::Local(local_def)
257             }
258         };
259         Some(res)
260     }
261
262     pub fn classify(sema: &Semantics<'_, RootDatabase>, name: &ast::Name) -> Option<NameClass> {
263         let _p = profile::span("classify_name");
264
265         let parent = name.syntax().parent()?;
266
267         let definition = match_ast! {
268             match parent {
269                 ast::Item(it) => classify_item(sema, it)?,
270                 ast::IdentPat(it) => return classify_ident_pat(sema, it),
271                 ast::Rename(it) => classify_rename(sema, it)?,
272                 ast::SelfParam(it) => Definition::Local(sema.to_def(&it)?),
273                 ast::RecordField(it) => Definition::Field(sema.to_def(&it)?),
274                 ast::Variant(it) => Definition::Variant(sema.to_def(&it)?),
275                 ast::TypeParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()),
276                 ast::ConstParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()),
277                 _ => return None,
278             }
279         };
280         return Some(NameClass::Definition(definition));
281
282         fn classify_item(
283             sema: &Semantics<'_, RootDatabase>,
284             item: ast::Item,
285         ) -> Option<Definition> {
286             let definition = match item {
287                 ast::Item::MacroRules(it) => {
288                     Definition::Macro(sema.to_def(&ast::Macro::MacroRules(it))?)
289                 }
290                 ast::Item::MacroDef(it) => {
291                     Definition::Macro(sema.to_def(&ast::Macro::MacroDef(it))?)
292                 }
293                 ast::Item::Const(it) => Definition::Const(sema.to_def(&it)?),
294                 ast::Item::Fn(it) => {
295                     let def = sema.to_def(&it)?;
296                     def.as_proc_macro(sema.db)
297                         .map(Definition::Macro)
298                         .unwrap_or(Definition::Function(def))
299                 }
300                 ast::Item::Module(it) => Definition::Module(sema.to_def(&it)?),
301                 ast::Item::Static(it) => Definition::Static(sema.to_def(&it)?),
302                 ast::Item::Trait(it) => Definition::Trait(sema.to_def(&it)?),
303                 ast::Item::TypeAlias(it) => Definition::TypeAlias(sema.to_def(&it)?),
304                 ast::Item::Enum(it) => Definition::Adt(hir::Adt::Enum(sema.to_def(&it)?)),
305                 ast::Item::Struct(it) => Definition::Adt(hir::Adt::Struct(sema.to_def(&it)?)),
306                 ast::Item::Union(it) => Definition::Adt(hir::Adt::Union(sema.to_def(&it)?)),
307                 _ => return None,
308             };
309             Some(definition)
310         }
311
312         fn classify_ident_pat(
313             sema: &Semantics<'_, RootDatabase>,
314             ident_pat: ast::IdentPat,
315         ) -> Option<NameClass> {
316             if let Some(def) = sema.resolve_bind_pat_to_const(&ident_pat) {
317                 return Some(NameClass::ConstReference(Definition::from(def)));
318             }
319
320             let local = sema.to_def(&ident_pat)?;
321             let pat_parent = ident_pat.syntax().parent();
322             if let Some(record_pat_field) = pat_parent.and_then(ast::RecordPatField::cast) {
323                 if record_pat_field.name_ref().is_none() {
324                     if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) {
325                         return Some(NameClass::PatFieldShorthand {
326                             local_def: local,
327                             field_ref: field,
328                         });
329                     }
330                 }
331             }
332             Some(NameClass::Definition(Definition::Local(local)))
333         }
334
335         fn classify_rename(
336             sema: &Semantics<'_, RootDatabase>,
337             rename: ast::Rename,
338         ) -> Option<Definition> {
339             if let Some(use_tree) = rename.syntax().parent().and_then(ast::UseTree::cast) {
340                 let path = use_tree.path()?;
341                 sema.resolve_path(&path).map(Definition::from)
342             } else {
343                 let extern_crate = rename.syntax().parent().and_then(ast::ExternCrate::cast)?;
344                 let krate = sema.resolve_extern_crate(&extern_crate)?;
345                 let root_module = krate.root_module(sema.db);
346                 Some(Definition::Module(root_module))
347             }
348         }
349     }
350
351     pub fn classify_lifetime(
352         sema: &Semantics<'_, RootDatabase>,
353         lifetime: &ast::Lifetime,
354     ) -> Option<NameClass> {
355         let _p = profile::span("classify_lifetime").detail(|| lifetime.to_string());
356         let parent = lifetime.syntax().parent()?;
357
358         if let Some(it) = ast::LifetimeParam::cast(parent.clone()) {
359             sema.to_def(&it).map(Into::into).map(Definition::GenericParam)
360         } else if let Some(it) = ast::Label::cast(parent) {
361             sema.to_def(&it).map(Definition::Label)
362         } else {
363             None
364         }
365         .map(NameClass::Definition)
366     }
367 }
368
369 #[derive(Debug)]
370 pub enum OperatorClass {
371     Await(Function),
372     Prefix(Function),
373     Index(Function),
374     Try(Function),
375     Bin(Function),
376 }
377
378 impl OperatorClass {
379     pub fn classify_await(
380         sema: &Semantics<'_, RootDatabase>,
381         await_expr: &ast::AwaitExpr,
382     ) -> Option<OperatorClass> {
383         sema.resolve_await_to_poll(await_expr).map(OperatorClass::Await)
384     }
385
386     pub fn classify_prefix(
387         sema: &Semantics<'_, RootDatabase>,
388         prefix_expr: &ast::PrefixExpr,
389     ) -> Option<OperatorClass> {
390         sema.resolve_prefix_expr(prefix_expr).map(OperatorClass::Prefix)
391     }
392
393     pub fn classify_try(
394         sema: &Semantics<'_, RootDatabase>,
395         try_expr: &ast::TryExpr,
396     ) -> Option<OperatorClass> {
397         sema.resolve_try_expr(try_expr).map(OperatorClass::Try)
398     }
399
400     pub fn classify_index(
401         sema: &Semantics<'_, RootDatabase>,
402         index_expr: &ast::IndexExpr,
403     ) -> Option<OperatorClass> {
404         sema.resolve_index_expr(index_expr).map(OperatorClass::Index)
405     }
406
407     pub fn classify_bin(
408         sema: &Semantics<'_, RootDatabase>,
409         bin_expr: &ast::BinExpr,
410     ) -> Option<OperatorClass> {
411         sema.resolve_bin_expr(bin_expr).map(OperatorClass::Bin)
412     }
413 }
414
415 /// This is similar to [`NameClass`], but works for [`ast::NameRef`] rather than
416 /// for [`ast::Name`]. Similarly, what looks like a reference in syntax is a
417 /// reference most of the time, but there are a couple of annoying exceptions.
418 ///
419 /// A model special case is field shorthand syntax, which uses a single
420 /// reference to point to two different defs.
421 #[derive(Debug)]
422 pub enum NameRefClass {
423     Definition(Definition),
424     FieldShorthand { local_ref: Local, field_ref: Field },
425 }
426
427 impl NameRefClass {
428     // Note: we don't have unit-tests for this rather important function.
429     // It is primarily exercised via goto definition tests in `ide`.
430     pub fn classify(
431         sema: &Semantics<'_, RootDatabase>,
432         name_ref: &ast::NameRef,
433     ) -> Option<NameRefClass> {
434         let _p = profile::span("classify_name_ref").detail(|| name_ref.to_string());
435
436         let parent = name_ref.syntax().parent()?;
437
438         if let Some(record_field) = ast::RecordExprField::for_field_name(name_ref) {
439             if let Some((field, local, _)) = sema.resolve_record_field(&record_field) {
440                 let res = match local {
441                     None => NameRefClass::Definition(Definition::Field(field)),
442                     Some(local) => {
443                         NameRefClass::FieldShorthand { field_ref: field, local_ref: local }
444                     }
445                 };
446                 return Some(res);
447             }
448         }
449
450         if let Some(path) = ast::PathSegment::cast(parent.clone()).map(|it| it.parent_path()) {
451             if path.parent_path().is_none() {
452                 if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
453                     // Only use this to resolve to macro calls for last segments as qualifiers resolve
454                     // to modules below.
455                     if let Some(macro_def) = sema.resolve_macro_call(&macro_call) {
456                         return Some(NameRefClass::Definition(Definition::Macro(macro_def)));
457                     }
458                 }
459             }
460             return sema.resolve_path(&path).map(Into::into).map(NameRefClass::Definition);
461         }
462
463         match_ast! {
464             match parent {
465                 ast::MethodCallExpr(method_call) => {
466                     sema.resolve_method_call(&method_call)
467                         .map(Definition::Function)
468                         .map(NameRefClass::Definition)
469                 },
470                 ast::FieldExpr(field_expr) => {
471                     sema.resolve_field(&field_expr)
472                         .map(Definition::Field)
473                         .map(NameRefClass::Definition)
474                 },
475                 ast::RecordPatField(record_pat_field) => {
476                     sema.resolve_record_pat_field(&record_pat_field)
477                         .map(Definition::Field)
478                         .map(NameRefClass::Definition)
479                 },
480                 ast::AssocTypeArg(_) => {
481                     // `Trait<Assoc = Ty>`
482                     //        ^^^^^
483                     let containing_path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
484                     let resolved = sema.resolve_path(&containing_path)?;
485                     if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved {
486                         if let Some(ty) = tr
487                             .items_with_supertraits(sema.db)
488                             .iter()
489                             .filter_map(|&assoc| match assoc {
490                                 hir::AssocItem::TypeAlias(it) => Some(it),
491                                 _ => None,
492                             })
493                             .find(|alias| alias.name(sema.db).to_smol_str() == name_ref.text().as_str())
494                         {
495                             return Some(NameRefClass::Definition(Definition::TypeAlias(ty)));
496                         }
497                     }
498                     None
499                 },
500                 ast::ExternCrate(extern_crate) => {
501                     let krate = sema.resolve_extern_crate(&extern_crate)?;
502                     let root_module = krate.root_module(sema.db);
503                     Some(NameRefClass::Definition(Definition::Module(root_module)))
504                 },
505                 _ => None
506             }
507         }
508     }
509
510     pub fn classify_lifetime(
511         sema: &Semantics<'_, RootDatabase>,
512         lifetime: &ast::Lifetime,
513     ) -> Option<NameRefClass> {
514         let _p = profile::span("classify_lifetime_ref").detail(|| lifetime.to_string());
515         let parent = lifetime.syntax().parent()?;
516         match parent.kind() {
517             SyntaxKind::BREAK_EXPR | SyntaxKind::CONTINUE_EXPR => {
518                 sema.resolve_label(lifetime).map(Definition::Label).map(NameRefClass::Definition)
519             }
520             SyntaxKind::LIFETIME_ARG
521             | SyntaxKind::SELF_PARAM
522             | SyntaxKind::TYPE_BOUND
523             | SyntaxKind::WHERE_PRED
524             | SyntaxKind::REF_TYPE => sema
525                 .resolve_lifetime_param(lifetime)
526                 .map(GenericParam::LifetimeParam)
527                 .map(Definition::GenericParam)
528                 .map(NameRefClass::Definition),
529             // lifetime bounds, as in the 'b in 'a: 'b aren't wrapped in TypeBound nodes so we gotta check
530             // if our lifetime is in a LifetimeParam without being the constrained lifetime
531             _ if ast::LifetimeParam::cast(parent).and_then(|param| param.lifetime()).as_ref()
532                 != Some(lifetime) =>
533             {
534                 sema.resolve_lifetime_param(lifetime)
535                     .map(GenericParam::LifetimeParam)
536                     .map(Definition::GenericParam)
537                     .map(NameRefClass::Definition)
538             }
539             _ => None,
540         }
541     }
542 }
543
544 impl_from!(
545     Field, Module, Function, Adt, Variant, Const, Static, Trait, TypeAlias, BuiltinType, Local,
546     GenericParam, Label, Macro
547     for Definition
548 );
549
550 impl From<Impl> for Definition {
551     fn from(impl_: Impl) -> Self {
552         Definition::SelfType(impl_)
553     }
554 }
555
556 impl AsAssocItem for Definition {
557     fn as_assoc_item(self, db: &dyn hir::db::HirDatabase) -> Option<AssocItem> {
558         match self {
559             Definition::Function(it) => it.as_assoc_item(db),
560             Definition::Const(it) => it.as_assoc_item(db),
561             Definition::TypeAlias(it) => it.as_assoc_item(db),
562             _ => None,
563         }
564     }
565 }
566
567 impl From<AssocItem> for Definition {
568     fn from(assoc_item: AssocItem) -> Self {
569         match assoc_item {
570             AssocItem::Function(it) => Definition::Function(it),
571             AssocItem::Const(it) => Definition::Const(it),
572             AssocItem::TypeAlias(it) => Definition::TypeAlias(it),
573         }
574     }
575 }
576
577 impl From<PathResolution> for Definition {
578     fn from(path_resolution: PathResolution) -> Self {
579         match path_resolution {
580             PathResolution::Def(def) => def.into(),
581             PathResolution::Local(local) => Definition::Local(local),
582             PathResolution::TypeParam(par) => Definition::GenericParam(par.into()),
583             PathResolution::ConstParam(par) => Definition::GenericParam(par.into()),
584             PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def),
585             PathResolution::BuiltinAttr(attr) => Definition::BuiltinAttr(attr),
586             PathResolution::ToolModule(tool) => Definition::ToolModule(tool),
587             PathResolution::DeriveHelper(helper) => Definition::DeriveHelper(helper),
588         }
589     }
590 }
591
592 impl From<ModuleDef> for Definition {
593     fn from(def: ModuleDef) -> Self {
594         match def {
595             ModuleDef::Module(it) => Definition::Module(it),
596             ModuleDef::Function(it) => Definition::Function(it),
597             ModuleDef::Adt(it) => Definition::Adt(it),
598             ModuleDef::Variant(it) => Definition::Variant(it),
599             ModuleDef::Const(it) => Definition::Const(it),
600             ModuleDef::Static(it) => Definition::Static(it),
601             ModuleDef::Trait(it) => Definition::Trait(it),
602             ModuleDef::TypeAlias(it) => Definition::TypeAlias(it),
603             ModuleDef::Macro(it) => Definition::Macro(it),
604             ModuleDef::BuiltinType(it) => Definition::BuiltinType(it),
605         }
606     }
607 }
608
609 impl From<Definition> for Option<ItemInNs> {
610     fn from(def: Definition) -> Self {
611         let item = match def {
612             Definition::Module(it) => ModuleDef::Module(it),
613             Definition::Function(it) => ModuleDef::Function(it),
614             Definition::Adt(it) => ModuleDef::Adt(it),
615             Definition::Variant(it) => ModuleDef::Variant(it),
616             Definition::Const(it) => ModuleDef::Const(it),
617             Definition::Static(it) => ModuleDef::Static(it),
618             Definition::Trait(it) => ModuleDef::Trait(it),
619             Definition::TypeAlias(it) => ModuleDef::TypeAlias(it),
620             Definition::BuiltinType(it) => ModuleDef::BuiltinType(it),
621             _ => return None,
622         };
623         Some(ItemInNs::from(item))
624     }
625 }