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