aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r--crates/ra_hir/src/code_model.rs954
1 files changed, 954 insertions, 0 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
new file mode 100644
index 000000000..49030ce67
--- /dev/null
+++ b/crates/ra_hir/src/code_model.rs
@@ -0,0 +1,954 @@
1use std::sync::Arc;
2
3use ra_db::{CrateId, SourceRootId, Edition, FileId};
4use ra_syntax::{ast::{self, NameOwner, TypeAscriptionOwner}, TreeArc};
5
6use crate::{
7 Name, AsName, AstId, Ty, HirFileId, Either,
8 HirDatabase, DefDatabase,
9 type_ref::TypeRef,
10 nameres::{ModuleScope, Namespace, ImportId, CrateModuleId},
11 expr::{Body, BodySourceMap, validation::ExprValidator},
12 ty::{TraitRef, InferenceResult},
13 adt::{EnumVariantId, StructFieldId, VariantDef},
14 generics::HasGenericParams,
15 docs::{Documentation, Docs, docs_from_ast},
16 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeAliasId},
17 impl_block::ImplBlock,
18 resolve::Resolver,
19 diagnostics::{DiagnosticSink},
20 traits::{TraitItem, TraitData},
21 type_ref::Mutability,
22};
23
24/// hir::Crate describes a single crate. It's the main interface with which
25/// a crate's dependencies interact. Mostly, it should be just a proxy for the
26/// root module.
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
28pub struct Crate {
29 pub(crate) crate_id: CrateId,
30}
31
32#[derive(Debug)]
33pub struct CrateDependency {
34 pub krate: Crate,
35 pub name: Name,
36}
37
38impl Crate {
39 pub fn crate_id(self) -> CrateId {
40 self.crate_id
41 }
42
43 pub fn dependencies(self, db: &impl DefDatabase) -> Vec<CrateDependency> {
44 db.crate_graph()
45 .dependencies(self.crate_id)
46 .map(|dep| {
47 let krate = Crate { crate_id: dep.crate_id() };
48 let name = dep.as_name();
49 CrateDependency { krate, name }
50 })
51 .collect()
52 }
53
54 pub fn root_module(self, db: &impl DefDatabase) -> Option<Module> {
55 let module_id = db.crate_def_map(self).root();
56 let module = Module { krate: self, module_id };
57 Some(module)
58 }
59
60 pub fn edition(self, db: &impl DefDatabase) -> Edition {
61 let crate_graph = db.crate_graph();
62 crate_graph.edition(self.crate_id)
63 }
64
65 // FIXME: should this be in source_binder?
66 pub fn source_root_crates(db: &impl DefDatabase, source_root: SourceRootId) -> Vec<Crate> {
67 let crate_ids = db.source_root_crates(source_root);
68 crate_ids.iter().map(|&crate_id| Crate { crate_id }).collect()
69 }
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
73pub struct Module {
74 pub(crate) krate: Crate,
75 pub(crate) module_id: CrateModuleId,
76}
77
78/// The defs which can be visible in the module.
79#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
80pub enum ModuleDef {
81 Module(Module),
82 Function(Function),
83 Struct(Struct),
84 Union(Union),
85 Enum(Enum),
86 // Can't be directly declared, but can be imported.
87 EnumVariant(EnumVariant),
88 Const(Const),
89 Static(Static),
90 Trait(Trait),
91 TypeAlias(TypeAlias),
92}
93impl_froms!(
94 ModuleDef: Module,
95 Function,
96 Struct,
97 Union,
98 Enum,
99 EnumVariant,
100 Const,
101 Static,
102 Trait,
103 TypeAlias
104);
105
106pub enum ModuleSource {
107 SourceFile(TreeArc<ast::SourceFile>),
108 Module(TreeArc<ast::Module>),
109}
110
111impl ModuleSource {
112 pub(crate) fn new(
113 db: &impl DefDatabase,
114 file_id: Option<FileId>,
115 decl_id: Option<AstId<ast::Module>>,
116 ) -> ModuleSource {
117 match (file_id, decl_id) {
118 (Some(file_id), _) => {
119 let source_file = db.parse(file_id);
120 ModuleSource::SourceFile(source_file)
121 }
122 (None, Some(item_id)) => {
123 let module = item_id.to_node(db);
124 assert!(module.item_list().is_some(), "expected inline module");
125 ModuleSource::Module(module.to_owned())
126 }
127 (None, None) => panic!(),
128 }
129 }
130}
131
132impl Module {
133 /// Name of this module.
134 pub fn name(self, db: &impl HirDatabase) -> Option<Name> {
135 let def_map = db.crate_def_map(self.krate);
136 let parent = def_map[self.module_id].parent?;
137 def_map[parent].children.iter().find_map(|(name, module_id)| {
138 if *module_id == self.module_id {
139 Some(name.clone())
140 } else {
141 None
142 }
143 })
144 }
145
146 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
147 pub fn definition_source(self, db: &impl DefDatabase) -> (HirFileId, ModuleSource) {
148 let def_map = db.crate_def_map(self.krate);
149 let decl_id = def_map[self.module_id].declaration;
150 let file_id = def_map[self.module_id].definition;
151 let module_source = ModuleSource::new(db, file_id, decl_id);
152 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id());
153 (file_id, module_source)
154 }
155
156 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
157 /// `None` for the crate root.
158 pub fn declaration_source(
159 self,
160 db: &impl HirDatabase,
161 ) -> Option<(HirFileId, TreeArc<ast::Module>)> {
162 let def_map = db.crate_def_map(self.krate);
163 let decl = def_map[self.module_id].declaration?;
164 let ast = decl.to_node(db);
165 Some((decl.file_id(), ast))
166 }
167
168 /// Returns the syntax of the last path segment corresponding to this import
169 pub fn import_source(
170 self,
171 db: &impl HirDatabase,
172 import: ImportId,
173 ) -> Either<TreeArc<ast::UseTree>, TreeArc<ast::ExternCrateItem>> {
174 let (file_id, source) = self.definition_source(db);
175 let (_, source_map) = db.raw_items_with_source_map(file_id);
176 source_map.get(&source, import)
177 }
178
179 /// Returns the crate this module is part of.
180 pub fn krate(self, _db: &impl DefDatabase) -> Option<Crate> {
181 Some(self.krate)
182 }
183
184 /// Topmost parent of this module. Every module has a `crate_root`, but some
185 /// might be missing `krate`. This can happen if a module's file is not included
186 /// in the module tree of any target in `Cargo.toml`.
187 pub fn crate_root(self, db: &impl DefDatabase) -> Module {
188 let def_map = db.crate_def_map(self.krate);
189 self.with_module_id(def_map.root())
190 }
191
192 /// Finds a child module with the specified name.
193 pub fn child(self, db: &impl HirDatabase, name: &Name) -> Option<Module> {
194 let def_map = db.crate_def_map(self.krate);
195 let child_id = def_map[self.module_id].children.get(name)?;
196 Some(self.with_module_id(*child_id))
197 }
198
199 /// Iterates over all child modules.
200 pub fn children(self, db: &impl DefDatabase) -> impl Iterator<Item = Module> {
201 let def_map = db.crate_def_map(self.krate);
202 let children = def_map[self.module_id]
203 .children
204 .iter()
205 .map(|(_, module_id)| self.with_module_id(*module_id))
206 .collect::<Vec<_>>();
207 children.into_iter()
208 }
209
210 /// Finds a parent module.
211 pub fn parent(self, db: &impl DefDatabase) -> Option<Module> {
212 let def_map = db.crate_def_map(self.krate);
213 let parent_id = def_map[self.module_id].parent?;
214 Some(self.with_module_id(parent_id))
215 }
216
217 pub fn path_to_root(self, db: &impl HirDatabase) -> Vec<Module> {
218 let mut res = vec![self.clone()];
219 let mut curr = self.clone();
220 while let Some(next) = curr.parent(db) {
221 res.push(next.clone());
222 curr = next
223 }
224 res
225 }
226
227 /// Returns a `ModuleScope`: a set of items, visible in this module.
228 pub fn scope(self, db: &impl HirDatabase) -> ModuleScope {
229 db.crate_def_map(self.krate)[self.module_id].scope.clone()
230 }
231
232 pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) {
233 db.crate_def_map(self.krate).add_diagnostics(db, self.module_id, sink);
234 for decl in self.declarations(db) {
235 match decl {
236 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
237 crate::ModuleDef::Module(f) => f.diagnostics(db, sink),
238 _ => (),
239 }
240 }
241
242 for impl_block in self.impl_blocks(db) {
243 for item in impl_block.items(db) {
244 match item {
245 crate::ImplItem::Method(f) => f.diagnostics(db, sink),
246 _ => (),
247 }
248 }
249 }
250 }
251
252 pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver {
253 let def_map = db.crate_def_map(self.krate);
254 Resolver::default().push_module_scope(def_map, self.module_id)
255 }
256
257 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> {
258 let def_map = db.crate_def_map(self.krate);
259 def_map[self.module_id]
260 .scope
261 .entries()
262 .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
263 .flat_map(|per_ns| {
264 per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
265 })
266 .collect()
267 }
268
269 pub fn impl_blocks(self, db: &impl HirDatabase) -> Vec<ImplBlock> {
270 let module_impl_blocks = db.impls_in_module(self);
271 module_impl_blocks
272 .impls
273 .iter()
274 .map(|(impl_id, _)| ImplBlock::from_id(self, impl_id))
275 .collect()
276 }
277
278 fn with_module_id(&self, module_id: CrateModuleId) -> Module {
279 Module { module_id, krate: self.krate }
280 }
281}
282
283impl Docs for Module {
284 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
285 self.declaration_source(db).and_then(|it| docs_from_ast(&*it.1))
286 }
287}
288
289#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
290pub struct StructField {
291 pub(crate) parent: VariantDef,
292 pub(crate) id: StructFieldId,
293}
294
295#[derive(Debug)]
296pub enum FieldSource {
297 Named(TreeArc<ast::NamedFieldDef>),
298 Pos(TreeArc<ast::PosFieldDef>),
299}
300
301impl StructField {
302 pub fn name(&self, db: &impl HirDatabase) -> Name {
303 self.parent.variant_data(db).fields().unwrap()[self.id].name.clone()
304 }
305
306 pub fn source(&self, db: &impl DefDatabase) -> (HirFileId, FieldSource) {
307 self.source_impl(db)
308 }
309
310 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
311 db.type_for_field(*self)
312 }
313
314 pub fn parent_def(&self, _db: &impl HirDatabase) -> VariantDef {
315 self.parent
316 }
317}
318
319impl Docs for StructField {
320 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
321 match self.source(db).1 {
322 FieldSource::Named(named) => docs_from_ast(&*named),
323 FieldSource::Pos(..) => return None,
324 }
325 }
326}
327
328#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
329pub struct Struct {
330 pub(crate) id: StructId,
331}
332
333impl Struct {
334 pub fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::StructDef>) {
335 self.id.source(db)
336 }
337
338 pub fn module(self, db: &impl HirDatabase) -> Module {
339 self.id.module(db)
340 }
341
342 pub fn name(self, db: &impl HirDatabase) -> Option<Name> {
343 db.struct_data(self).name.clone()
344 }
345
346 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
347 db.struct_data(self)
348 .variant_data
349 .fields()
350 .into_iter()
351 .flat_map(|it| it.iter())
352 .map(|(id, _)| StructField { parent: self.into(), id })
353 .collect()
354 }
355
356 pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
357 db.struct_data(self)
358 .variant_data
359 .fields()
360 .into_iter()
361 .flat_map(|it| it.iter())
362 .find(|(_id, data)| data.name == *name)
363 .map(|(id, _)| StructField { parent: self.into(), id })
364 }
365
366 pub fn ty(self, db: &impl HirDatabase) -> Ty {
367 db.type_for_def(self.into(), Namespace::Types)
368 }
369
370 pub fn constructor_ty(self, db: &impl HirDatabase) -> Ty {
371 db.type_for_def(self.into(), Namespace::Values)
372 }
373
374 // FIXME move to a more general type
375 /// Builds a resolver for type references inside this struct.
376 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
377 // take the outer scope...
378 let r = self.module(db).resolver(db);
379 // ...and add generic params, if present
380 let p = self.generic_params(db);
381 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
382 r
383 }
384}
385
386impl Docs for Struct {
387 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
388 docs_from_ast(&*self.source(db).1)
389 }
390}
391
392#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
393pub struct Union {
394 pub(crate) id: StructId,
395}
396
397impl Union {
398 pub fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::StructDef>) {
399 self.id.source(db)
400 }
401
402 pub fn name(self, db: &impl HirDatabase) -> Option<Name> {
403 db.struct_data(Struct { id: self.id }).name.clone()
404 }
405
406 pub fn module(self, db: &impl HirDatabase) -> Module {
407 self.id.module(db)
408 }
409
410 // FIXME move to a more general type
411 /// Builds a resolver for type references inside this union.
412 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
413 // take the outer scope...
414 let r = self.module(db).resolver(db);
415 // ...and add generic params, if present
416 let p = self.generic_params(db);
417 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
418 r
419 }
420}
421
422impl Docs for Union {
423 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
424 docs_from_ast(&*self.source(db).1)
425 }
426}
427
428#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
429pub struct Enum {
430 pub(crate) id: EnumId,
431}
432
433impl Enum {
434 pub fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) {
435 self.id.source(db)
436 }
437
438 pub fn module(self, db: &impl HirDatabase) -> Module {
439 self.id.module(db)
440 }
441
442 pub fn name(self, db: &impl HirDatabase) -> Option<Name> {
443 db.enum_data(self).name.clone()
444 }
445
446 pub fn variants(self, db: &impl DefDatabase) -> Vec<EnumVariant> {
447 db.enum_data(self).variants.iter().map(|(id, _)| EnumVariant { parent: self, id }).collect()
448 }
449
450 pub fn variant(self, db: &impl DefDatabase, name: &Name) -> Option<EnumVariant> {
451 db.enum_data(self)
452 .variants
453 .iter()
454 .find(|(_id, data)| data.name.as_ref() == Some(name))
455 .map(|(id, _)| EnumVariant { parent: self, id })
456 }
457
458 pub fn ty(self, db: &impl HirDatabase) -> Ty {
459 db.type_for_def(self.into(), Namespace::Types)
460 }
461
462 // FIXME: move to a more general type
463 /// Builds a resolver for type references inside this struct.
464 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
465 // take the outer scope...
466 let r = self.module(db).resolver(db);
467 // ...and add generic params, if present
468 let p = self.generic_params(db);
469 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
470 r
471 }
472}
473
474impl Docs for Enum {
475 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
476 docs_from_ast(&*self.source(db).1)
477 }
478}
479
480#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
481pub struct EnumVariant {
482 pub(crate) parent: Enum,
483 pub(crate) id: EnumVariantId,
484}
485
486impl EnumVariant {
487 pub fn source(&self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::EnumVariant>) {
488 self.source_impl(db)
489 }
490 pub fn module(&self, db: &impl HirDatabase) -> Module {
491 self.parent.module(db)
492 }
493 pub fn parent_enum(&self, _db: &impl DefDatabase) -> Enum {
494 self.parent
495 }
496
497 pub fn name(&self, db: &impl DefDatabase) -> Option<Name> {
498 db.enum_data(self.parent).variants[self.id].name.clone()
499 }
500
501 pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> {
502 self.variant_data(db)
503 .fields()
504 .into_iter()
505 .flat_map(|it| it.iter())
506 .map(|(id, _)| StructField { parent: (*self).into(), id })
507 .collect()
508 }
509
510 pub fn field(&self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
511 self.variant_data(db)
512 .fields()
513 .into_iter()
514 .flat_map(|it| it.iter())
515 .find(|(_id, data)| data.name == *name)
516 .map(|(id, _)| StructField { parent: (*self).into(), id })
517 }
518}
519
520impl Docs for EnumVariant {
521 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
522 docs_from_ast(&*self.source(db).1)
523 }
524}
525
526/// The defs which have a body.
527#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
528pub enum DefWithBody {
529 Function(Function),
530 Static(Static),
531 Const(Const),
532}
533
534impl_froms!(DefWithBody: Function, Const, Static);
535
536impl DefWithBody {
537 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
538 db.infer(self)
539 }
540
541 pub fn body(self, db: &impl HirDatabase) -> Arc<Body> {
542 db.body_hir(self)
543 }
544
545 pub fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
546 db.body_with_source_map(self).1
547 }
548
549 /// Builds a resolver for code inside this item.
550 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
551 match *self {
552 DefWithBody::Const(ref c) => c.resolver(db),
553 DefWithBody::Function(ref f) => f.resolver(db),
554 DefWithBody::Static(ref s) => s.resolver(db),
555 }
556 }
557}
558
559#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
560pub struct Function {
561 pub(crate) id: FunctionId,
562}
563
564/// The declared signature of a function.
565#[derive(Debug, Clone, PartialEq, Eq)]
566pub struct FnSignature {
567 pub(crate) name: Name,
568 pub(crate) params: Vec<TypeRef>,
569 pub(crate) ret_type: TypeRef,
570 /// True if the first param is `self`. This is relevant to decide whether this
571 /// can be called as a method.
572 pub(crate) has_self_param: bool,
573}
574
575impl FnSignature {
576 pub(crate) fn fn_signature_query(db: &impl DefDatabase, func: Function) -> Arc<FnSignature> {
577 let (_, node) = func.source(db);
578 let name = node.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
579 let mut params = Vec::new();
580 let mut has_self_param = false;
581 if let Some(param_list) = node.param_list() {
582 if let Some(self_param) = param_list.self_param() {
583 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
584 TypeRef::from_ast(type_ref)
585 } else {
586 let self_type = TypeRef::Path(Name::self_type().into());
587 match self_param.kind() {
588 ast::SelfParamKind::Owned => self_type,
589 ast::SelfParamKind::Ref => {
590 TypeRef::Reference(Box::new(self_type), Mutability::Shared)
591 }
592 ast::SelfParamKind::MutRef => {
593 TypeRef::Reference(Box::new(self_type), Mutability::Mut)
594 }
595 }
596 };
597 params.push(self_type);
598 has_self_param = true;
599 }
600 for param in param_list.params() {
601 let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
602 params.push(type_ref);
603 }
604 }
605 let ret_type = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) {
606 TypeRef::from_ast(type_ref)
607 } else {
608 TypeRef::unit()
609 };
610
611 let sig = FnSignature { name, params, ret_type, has_self_param };
612 Arc::new(sig)
613 }
614 pub fn name(&self) -> &Name {
615 &self.name
616 }
617
618 pub fn params(&self) -> &[TypeRef] {
619 &self.params
620 }
621
622 pub fn ret_type(&self) -> &TypeRef {
623 &self.ret_type
624 }
625
626 /// True if the first arg is `self`. This is relevant to decide whether this
627 /// can be called as a method.
628 pub fn has_self_param(&self) -> bool {
629 self.has_self_param
630 }
631}
632
633impl Function {
634 pub fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::FnDef>) {
635 self.id.source(db)
636 }
637
638 pub fn module(self, db: &impl DefDatabase) -> Module {
639 self.id.module(db)
640 }
641
642 pub fn name(self, db: &impl HirDatabase) -> Name {
643 self.signature(db).name.clone()
644 }
645
646 pub(crate) fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
647 db.body_with_source_map(self.into()).1
648 }
649
650 pub fn body(self, db: &impl HirDatabase) -> Arc<Body> {
651 db.body_hir(self.into())
652 }
653
654 pub fn ty(self, db: &impl HirDatabase) -> Ty {
655 db.type_for_def(self.into(), Namespace::Values)
656 }
657
658 pub fn signature(self, db: &impl HirDatabase) -> Arc<FnSignature> {
659 db.fn_signature(self)
660 }
661
662 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
663 db.infer(self.into())
664 }
665
666 /// The containing impl block, if this is a method.
667 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
668 let module_impls = db.impls_in_module(self.module(db));
669 ImplBlock::containing(module_impls, self.into())
670 }
671
672 /// The containing trait, if this is a trait method definition.
673 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
674 db.trait_items_index(self.module(db)).get_parent_trait(self.into())
675 }
676
677 pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
678 if let Some(impl_block) = self.impl_block(db) {
679 Some(impl_block.into())
680 } else if let Some(trait_) = self.parent_trait(db) {
681 Some(trait_.into())
682 } else {
683 None
684 }
685 }
686
687 // FIXME: move to a more general type for 'body-having' items
688 /// Builds a resolver for code inside this item.
689 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
690 // take the outer scope...
691 let r = self.container(db).map_or_else(|| self.module(db).resolver(db), |c| c.resolver(db));
692 // ...and add generic params, if present
693 let p = self.generic_params(db);
694 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
695 r
696 }
697
698 pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) {
699 let infer = self.infer(db);
700 infer.add_diagnostics(db, self, sink);
701 let mut validator = ExprValidator::new(self, infer, sink);
702 validator.validate_body(db);
703 }
704}
705
706impl Docs for Function {
707 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
708 docs_from_ast(&*self.source(db).1)
709 }
710}
711
712#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
713pub struct Const {
714 pub(crate) id: ConstId,
715}
716
717impl Const {
718 pub fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::ConstDef>) {
719 self.id.source(db)
720 }
721
722 pub fn module(self, db: &impl DefDatabase) -> Module {
723 self.id.module(db)
724 }
725
726 pub fn signature(self, db: &impl HirDatabase) -> Arc<ConstSignature> {
727 db.const_signature(self)
728 }
729
730 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
731 db.infer(self.into())
732 }
733
734 /// The containing impl block, if this is a method.
735 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
736 let module_impls = db.impls_in_module(self.module(db));
737 ImplBlock::containing(module_impls, self.into())
738 }
739
740 // FIXME: move to a more general type for 'body-having' items
741 /// Builds a resolver for code inside this item.
742 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
743 // take the outer scope...
744 let r = self
745 .impl_block(db)
746 .map(|ib| ib.resolver(db))
747 .unwrap_or_else(|| self.module(db).resolver(db));
748 r
749 }
750}
751
752impl Docs for Const {
753 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
754 docs_from_ast(&*self.source(db).1)
755 }
756}
757
758/// The declared signature of a const.
759#[derive(Debug, Clone, PartialEq, Eq)]
760pub struct ConstSignature {
761 pub(crate) name: Name,
762 pub(crate) type_ref: TypeRef,
763}
764
765impl ConstSignature {
766 pub fn name(&self) -> &Name {
767 &self.name
768 }
769
770 pub fn type_ref(&self) -> &TypeRef {
771 &self.type_ref
772 }
773
774 pub(crate) fn const_signature_query(
775 db: &impl DefDatabase,
776 konst: Const,
777 ) -> Arc<ConstSignature> {
778 let (_, node) = konst.source(db);
779 const_signature_for(&*node)
780 }
781
782 pub(crate) fn static_signature_query(
783 db: &impl DefDatabase,
784 konst: Static,
785 ) -> Arc<ConstSignature> {
786 let (_, node) = konst.source(db);
787 const_signature_for(&*node)
788 }
789}
790
791fn const_signature_for<N: NameOwner + TypeAscriptionOwner>(node: &N) -> Arc<ConstSignature> {
792 let name = node.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
793 let type_ref = TypeRef::from_ast_opt(node.ascribed_type());
794 let sig = ConstSignature { name, type_ref };
795 Arc::new(sig)
796}
797
798#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
799pub struct Static {
800 pub(crate) id: StaticId,
801}
802
803impl Static {
804 pub fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::StaticDef>) {
805 self.id.source(db)
806 }
807
808 pub fn module(self, db: &impl DefDatabase) -> Module {
809 self.id.module(db)
810 }
811
812 pub fn signature(self, db: &impl HirDatabase) -> Arc<ConstSignature> {
813 db.static_signature(self)
814 }
815
816 /// Builds a resolver for code inside this item.
817 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
818 // take the outer scope...
819 self.module(db).resolver(db)
820 }
821
822 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
823 db.infer(self.into())
824 }
825}
826
827impl Docs for Static {
828 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
829 docs_from_ast(&*self.source(db).1)
830 }
831}
832
833#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
834pub struct Trait {
835 pub(crate) id: TraitId,
836}
837
838impl Trait {
839 pub fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::TraitDef>) {
840 self.id.source(db)
841 }
842
843 pub fn module(self, db: &impl DefDatabase) -> Module {
844 self.id.module(db)
845 }
846
847 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
848 self.trait_data(db).name().clone()
849 }
850
851 pub fn items(self, db: &impl DefDatabase) -> Vec<TraitItem> {
852 self.trait_data(db).items().to_vec()
853 }
854
855 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {
856 db.trait_data(self)
857 }
858
859 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef {
860 TraitRef::for_trait(db, self)
861 }
862
863 pub fn is_auto(self, db: &impl DefDatabase) -> bool {
864 self.trait_data(db).is_auto()
865 }
866
867 pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver {
868 let r = self.module(db).resolver(db);
869 // add generic params, if present
870 let p = self.generic_params(db);
871 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
872 r
873 }
874}
875
876impl Docs for Trait {
877 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
878 docs_from_ast(&*self.source(db).1)
879 }
880}
881
882#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
883pub struct TypeAlias {
884 pub(crate) id: TypeAliasId,
885}
886
887impl TypeAlias {
888 pub fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::TypeAliasDef>) {
889 self.id.source(db)
890 }
891
892 pub fn module(self, db: &impl DefDatabase) -> Module {
893 self.id.module(db)
894 }
895
896 /// The containing impl block, if this is a method.
897 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
898 let module_impls = db.impls_in_module(self.module(db));
899 ImplBlock::containing(module_impls, self.into())
900 }
901
902 /// The containing trait, if this is a trait method definition.
903 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
904 db.trait_items_index(self.module(db)).get_parent_trait(self.into())
905 }
906
907 pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
908 if let Some(impl_block) = self.impl_block(db) {
909 Some(impl_block.into())
910 } else if let Some(trait_) = self.parent_trait(db) {
911 Some(trait_.into())
912 } else {
913 None
914 }
915 }
916
917 pub fn type_ref(self, db: &impl DefDatabase) -> Arc<TypeRef> {
918 db.type_alias_ref(self)
919 }
920
921 /// Builds a resolver for the type references in this type alias.
922 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
923 // take the outer scope...
924 let r = self
925 .impl_block(db)
926 .map(|ib| ib.resolver(db))
927 .unwrap_or_else(|| self.module(db).resolver(db));
928 // ...and add generic params, if present
929 let p = self.generic_params(db);
930 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
931 r
932 }
933}
934
935impl Docs for TypeAlias {
936 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
937 docs_from_ast(&*self.source(db).1)
938 }
939}
940
941pub enum Container {
942 Trait(Trait),
943 ImplBlock(ImplBlock),
944}
945impl_froms!(Container: Trait, ImplBlock);
946
947impl Container {
948 pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver {
949 match self {
950 Container::Trait(trait_) => trait_.resolver(db),
951 Container::ImplBlock(impl_block) => impl_block.resolver(db),
952 }
953 }
954}