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