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.rs1713
1 files changed, 0 insertions, 1713 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
deleted file mode 100644
index 0007d7fa8..000000000
--- a/crates/ra_hir/src/code_model.rs
+++ /dev/null
@@ -1,1713 +0,0 @@
1//! FIXME: write short doc here
2use std::{iter, sync::Arc};
3
4use arrayvec::ArrayVec;
5use either::Either;
6use hir_def::{
7 adt::ReprKind,
8 adt::StructKind,
9 adt::VariantData,
10 builtin_type::BuiltinType,
11 docs::Documentation,
12 expr::{BindingAnnotation, Pat, PatId},
13 import_map,
14 per_ns::PerNs,
15 resolver::{HasResolver, Resolver},
16 src::HasSource as _,
17 type_ref::{Mutability, TypeRef},
18 AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule,
19 ImplId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId,
20 TraitId, TypeAliasId, TypeParamId, UnionId,
21};
22use hir_expand::{
23 diagnostics::DiagnosticSink,
24 name::{name, AsName},
25 MacroDefId, MacroDefKind,
26};
27use hir_ty::{
28 autoderef,
29 display::{HirDisplayError, HirFormatter},
30 method_resolution, ApplicationTy, CallableDefId, Canonical, FnSig, GenericPredicate,
31 InEnvironment, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor,
32};
33use ra_db::{CrateId, Edition, FileId};
34use ra_prof::profile;
35use ra_syntax::{
36 ast::{self, AttrsOwner, NameOwner},
37 AstNode,
38};
39use rustc_hash::FxHashSet;
40use stdx::impl_from;
41
42use crate::{
43 db::{DefDatabase, HirDatabase},
44 has_source::HasSource,
45 HirDisplay, InFile, Name,
46};
47
48/// hir::Crate describes a single crate. It's the main interface with which
49/// a crate's dependencies interact. Mostly, it should be just a proxy for the
50/// root module.
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
52pub struct Crate {
53 pub(crate) id: CrateId,
54}
55
56#[derive(Debug)]
57pub struct CrateDependency {
58 pub krate: Crate,
59 pub name: Name,
60}
61
62impl Crate {
63 pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
64 db.crate_graph()[self.id]
65 .dependencies
66 .iter()
67 .map(|dep| {
68 let krate = Crate { id: dep.crate_id };
69 let name = dep.as_name();
70 CrateDependency { krate, name }
71 })
72 .collect()
73 }
74
75 // FIXME: add `transitive_reverse_dependencies`.
76 pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
77 let crate_graph = db.crate_graph();
78 crate_graph
79 .iter()
80 .filter(|&krate| {
81 crate_graph[krate].dependencies.iter().any(|it| it.crate_id == self.id)
82 })
83 .map(|id| Crate { id })
84 .collect()
85 }
86
87 pub fn root_module(self, db: &dyn HirDatabase) -> Module {
88 let module_id = db.crate_def_map(self.id).root;
89 Module::new(self, module_id)
90 }
91
92 pub fn root_file(self, db: &dyn HirDatabase) -> FileId {
93 db.crate_graph()[self.id].root_file_id
94 }
95
96 pub fn edition(self, db: &dyn HirDatabase) -> Edition {
97 db.crate_graph()[self.id].edition
98 }
99
100 pub fn display_name(self, db: &dyn HirDatabase) -> Option<String> {
101 db.crate_graph()[self.id].display_name.clone()
102 }
103
104 pub fn query_external_importables(
105 self,
106 db: &dyn DefDatabase,
107 query: &str,
108 ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
109 import_map::search_dependencies(
110 db,
111 self.into(),
112 import_map::Query::new(query).anchor_end().case_sensitive().limit(40),
113 )
114 .into_iter()
115 .map(|item| match item {
116 ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()),
117 ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()),
118 })
119 }
120
121 pub fn all(db: &dyn HirDatabase) -> Vec<Crate> {
122 db.crate_graph().iter().map(|id| Crate { id }).collect()
123 }
124}
125
126#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
127pub struct Module {
128 pub(crate) id: ModuleId,
129}
130
131/// The defs which can be visible in the module.
132#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
133pub enum ModuleDef {
134 Module(Module),
135 Function(Function),
136 Adt(Adt),
137 // Can't be directly declared, but can be imported.
138 EnumVariant(EnumVariant),
139 Const(Const),
140 Static(Static),
141 Trait(Trait),
142 TypeAlias(TypeAlias),
143 BuiltinType(BuiltinType),
144}
145impl_from!(
146 Module,
147 Function,
148 Adt(Struct, Enum, Union),
149 EnumVariant,
150 Const,
151 Static,
152 Trait,
153 TypeAlias,
154 BuiltinType
155 for ModuleDef
156);
157
158impl ModuleDef {
159 pub fn module(self, db: &dyn HirDatabase) -> Option<Module> {
160 match self {
161 ModuleDef::Module(it) => it.parent(db),
162 ModuleDef::Function(it) => Some(it.module(db)),
163 ModuleDef::Adt(it) => Some(it.module(db)),
164 ModuleDef::EnumVariant(it) => Some(it.module(db)),
165 ModuleDef::Const(it) => Some(it.module(db)),
166 ModuleDef::Static(it) => Some(it.module(db)),
167 ModuleDef::Trait(it) => Some(it.module(db)),
168 ModuleDef::TypeAlias(it) => Some(it.module(db)),
169 ModuleDef::BuiltinType(_) => None,
170 }
171 }
172
173 pub fn definition_visibility(&self, db: &dyn HirDatabase) -> Option<Visibility> {
174 let module = match self {
175 ModuleDef::Module(it) => it.parent(db)?,
176 ModuleDef::Function(it) => return Some(it.visibility(db)),
177 ModuleDef::Adt(it) => it.module(db),
178 ModuleDef::EnumVariant(it) => {
179 let parent = it.parent_enum(db);
180 let module = it.module(db);
181 return module.visibility_of(db, &ModuleDef::Adt(Adt::Enum(parent)));
182 }
183 ModuleDef::Const(it) => return Some(it.visibility(db)),
184 ModuleDef::Static(it) => it.module(db),
185 ModuleDef::Trait(it) => it.module(db),
186 ModuleDef::TypeAlias(it) => return Some(it.visibility(db)),
187 ModuleDef::BuiltinType(_) => return None,
188 };
189
190 module.visibility_of(db, self)
191 }
192
193 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
194 match self {
195 ModuleDef::Adt(it) => Some(it.name(db)),
196 ModuleDef::Trait(it) => Some(it.name(db)),
197 ModuleDef::Function(it) => Some(it.name(db)),
198 ModuleDef::EnumVariant(it) => Some(it.name(db)),
199 ModuleDef::TypeAlias(it) => Some(it.name(db)),
200
201 ModuleDef::Module(it) => it.name(db),
202 ModuleDef::Const(it) => it.name(db),
203 ModuleDef::Static(it) => it.name(db),
204
205 ModuleDef::BuiltinType(it) => Some(it.as_name()),
206 }
207 }
208}
209
210pub use hir_def::{
211 attr::Attrs, item_scope::ItemInNs, item_tree::ItemTreeNode, visibility::Visibility,
212 AssocItemId, AssocItemLoc,
213};
214
215impl Module {
216 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module {
217 Module { id: ModuleId { krate: krate.id, local_id: crate_module_id } }
218 }
219
220 /// Name of this module.
221 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
222 let def_map = db.crate_def_map(self.id.krate);
223 let parent = def_map[self.id.local_id].parent?;
224 def_map[parent].children.iter().find_map(|(name, module_id)| {
225 if *module_id == self.id.local_id {
226 Some(name.clone())
227 } else {
228 None
229 }
230 })
231 }
232
233 /// Returns the crate this module is part of.
234 pub fn krate(self) -> Crate {
235 Crate { id: self.id.krate }
236 }
237
238 /// Topmost parent of this module. Every module has a `crate_root`, but some
239 /// might be missing `krate`. This can happen if a module's file is not included
240 /// in the module tree of any target in `Cargo.toml`.
241 pub fn crate_root(self, db: &dyn HirDatabase) -> Module {
242 let def_map = db.crate_def_map(self.id.krate);
243 self.with_module_id(def_map.root)
244 }
245
246 /// Iterates over all child modules.
247 pub fn children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module> {
248 let def_map = db.crate_def_map(self.id.krate);
249 let children = def_map[self.id.local_id]
250 .children
251 .iter()
252 .map(|(_, module_id)| self.with_module_id(*module_id))
253 .collect::<Vec<_>>();
254 children.into_iter()
255 }
256
257 /// Finds a parent module.
258 pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> {
259 let def_map = db.crate_def_map(self.id.krate);
260 let parent_id = def_map[self.id.local_id].parent?;
261 Some(self.with_module_id(parent_id))
262 }
263
264 pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> {
265 let mut res = vec![self];
266 let mut curr = self;
267 while let Some(next) = curr.parent(db) {
268 res.push(next);
269 curr = next
270 }
271 res
272 }
273
274 /// Returns a `ModuleScope`: a set of items, visible in this module.
275 pub fn scope(
276 self,
277 db: &dyn HirDatabase,
278 visible_from: Option<Module>,
279 ) -> Vec<(Name, ScopeDef)> {
280 db.crate_def_map(self.id.krate)[self.id.local_id]
281 .scope
282 .entries()
283 .filter_map(|(name, def)| {
284 if let Some(m) = visible_from {
285 let filtered =
286 def.filter_visibility(|vis| vis.is_visible_from(db.upcast(), m.id));
287 if filtered.is_none() && !def.is_none() {
288 None
289 } else {
290 Some((name, filtered))
291 }
292 } else {
293 Some((name, def))
294 }
295 })
296 .flat_map(|(name, def)| {
297 ScopeDef::all_items(def).into_iter().map(move |item| (name.clone(), item))
298 })
299 .collect()
300 }
301
302 pub fn visibility_of(self, db: &dyn HirDatabase, def: &ModuleDef) -> Option<Visibility> {
303 db.crate_def_map(self.id.krate)[self.id.local_id].scope.visibility_of(def.clone().into())
304 }
305
306 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
307 let _p = profile("Module::diagnostics");
308 let crate_def_map = db.crate_def_map(self.id.krate);
309 crate_def_map.add_diagnostics(db.upcast(), self.id.local_id, sink);
310 for decl in self.declarations(db) {
311 match decl {
312 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
313 crate::ModuleDef::Module(m) => {
314 // Only add diagnostics from inline modules
315 if crate_def_map[m.id.local_id].origin.is_inline() {
316 m.diagnostics(db, sink)
317 }
318 }
319 _ => (),
320 }
321 }
322
323 for impl_def in self.impl_defs(db) {
324 for item in impl_def.items(db) {
325 if let AssocItem::Function(f) = item {
326 f.diagnostics(db, sink);
327 }
328 }
329 }
330 }
331
332 pub fn declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef> {
333 let def_map = db.crate_def_map(self.id.krate);
334 def_map[self.id.local_id].scope.declarations().map(ModuleDef::from).collect()
335 }
336
337 pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<ImplDef> {
338 let def_map = db.crate_def_map(self.id.krate);
339 def_map[self.id.local_id].scope.impls().map(ImplDef::from).collect()
340 }
341
342 pub(crate) fn with_module_id(self, module_id: LocalModuleId) -> Module {
343 Module::new(self.krate(), module_id)
344 }
345
346 /// Finds a path that can be used to refer to the given item from within
347 /// this module, if possible.
348 pub fn find_use_path(
349 self,
350 db: &dyn DefDatabase,
351 item: impl Into<ItemInNs>,
352 ) -> Option<hir_def::path::ModPath> {
353 hir_def::find_path::find_path(db, item.into(), self.into())
354 }
355}
356
357#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
358pub struct Field {
359 pub(crate) parent: VariantDef,
360 pub(crate) id: LocalFieldId,
361}
362
363#[derive(Debug, PartialEq, Eq)]
364pub enum FieldSource {
365 Named(ast::RecordField),
366 Pos(ast::TupleField),
367}
368
369impl Field {
370 pub fn name(&self, db: &dyn HirDatabase) -> Name {
371 self.parent.variant_data(db).fields()[self.id].name.clone()
372 }
373
374 /// Returns the type as in the signature of the struct (i.e., with
375 /// placeholder types for type parameters). This is good for showing
376 /// signature help, but not so good to actually get the type of the field
377 /// when you actually have a variable of the struct.
378 pub fn signature_ty(&self, db: &dyn HirDatabase) -> Type {
379 let var_id = self.parent.into();
380 let generic_def_id: GenericDefId = match self.parent {
381 VariantDef::Struct(it) => it.id.into(),
382 VariantDef::Union(it) => it.id.into(),
383 VariantDef::EnumVariant(it) => it.parent.id.into(),
384 };
385 let substs = Substs::type_params(db, generic_def_id);
386 let ty = db.field_types(var_id)[self.id].clone().subst(&substs);
387 Type::new(db, self.parent.module(db).id.krate, var_id, ty)
388 }
389
390 pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
391 self.parent
392 }
393}
394
395impl HasVisibility for Field {
396 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
397 let variant_data = self.parent.variant_data(db);
398 let visibility = &variant_data.fields()[self.id].visibility;
399 let parent_id: hir_def::VariantId = self.parent.into();
400 visibility.resolve(db.upcast(), &parent_id.resolver(db.upcast()))
401 }
402}
403
404#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
405pub struct Struct {
406 pub(crate) id: StructId,
407}
408
409impl Struct {
410 pub fn module(self, db: &dyn HirDatabase) -> Module {
411 Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) }
412 }
413
414 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
415 Some(self.module(db).krate())
416 }
417
418 pub fn name(self, db: &dyn HirDatabase) -> Name {
419 db.struct_data(self.id).name.clone()
420 }
421
422 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
423 db.struct_data(self.id)
424 .variant_data
425 .fields()
426 .iter()
427 .map(|(id, _)| Field { parent: self.into(), id })
428 .collect()
429 }
430
431 pub fn ty(self, db: &dyn HirDatabase) -> Type {
432 Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id)
433 }
434
435 pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> {
436 db.struct_data(self.id).repr.clone()
437 }
438
439 fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
440 db.struct_data(self.id).variant_data.clone()
441 }
442}
443
444#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
445pub struct Union {
446 pub(crate) id: UnionId,
447}
448
449impl Union {
450 pub fn name(self, db: &dyn HirDatabase) -> Name {
451 db.union_data(self.id).name.clone()
452 }
453
454 pub fn module(self, db: &dyn HirDatabase) -> Module {
455 Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) }
456 }
457
458 pub fn ty(self, db: &dyn HirDatabase) -> Type {
459 Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id)
460 }
461
462 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
463 db.union_data(self.id)
464 .variant_data
465 .fields()
466 .iter()
467 .map(|(id, _)| Field { parent: self.into(), id })
468 .collect()
469 }
470
471 fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
472 db.union_data(self.id).variant_data.clone()
473 }
474}
475
476#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
477pub struct Enum {
478 pub(crate) id: EnumId,
479}
480
481impl Enum {
482 pub fn module(self, db: &dyn HirDatabase) -> Module {
483 Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) }
484 }
485
486 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
487 Some(self.module(db).krate())
488 }
489
490 pub fn name(self, db: &dyn HirDatabase) -> Name {
491 db.enum_data(self.id).name.clone()
492 }
493
494 pub fn variants(self, db: &dyn HirDatabase) -> Vec<EnumVariant> {
495 db.enum_data(self.id)
496 .variants
497 .iter()
498 .map(|(id, _)| EnumVariant { parent: self, id })
499 .collect()
500 }
501
502 pub fn ty(self, db: &dyn HirDatabase) -> Type {
503 Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id)
504 }
505}
506
507#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
508pub struct EnumVariant {
509 pub(crate) parent: Enum,
510 pub(crate) id: LocalEnumVariantId,
511}
512
513impl EnumVariant {
514 pub fn module(self, db: &dyn HirDatabase) -> Module {
515 self.parent.module(db)
516 }
517 pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum {
518 self.parent
519 }
520
521 pub fn name(self, db: &dyn HirDatabase) -> Name {
522 db.enum_data(self.parent.id).variants[self.id].name.clone()
523 }
524
525 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
526 self.variant_data(db)
527 .fields()
528 .iter()
529 .map(|(id, _)| Field { parent: self.into(), id })
530 .collect()
531 }
532
533 pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
534 self.variant_data(db).kind()
535 }
536
537 pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
538 db.enum_data(self.parent.id).variants[self.id].variant_data.clone()
539 }
540}
541
542/// A Data Type
543#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
544pub enum Adt {
545 Struct(Struct),
546 Union(Union),
547 Enum(Enum),
548}
549impl_from!(Struct, Union, Enum for Adt);
550
551impl Adt {
552 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
553 let subst = db.generic_defaults(self.into());
554 subst.iter().any(|ty| &ty.value == &Ty::Unknown)
555 }
556
557 /// Turns this ADT into a type. Any type parameters of the ADT will be
558 /// turned into unknown types, which is good for e.g. finding the most
559 /// general set of completions, but will not look very nice when printed.
560 pub fn ty(self, db: &dyn HirDatabase) -> Type {
561 let id = AdtId::from(self);
562 Type::from_def(db, id.module(db.upcast()).krate, id)
563 }
564
565 pub fn module(self, db: &dyn HirDatabase) -> Module {
566 match self {
567 Adt::Struct(s) => s.module(db),
568 Adt::Union(s) => s.module(db),
569 Adt::Enum(e) => e.module(db),
570 }
571 }
572
573 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
574 Some(self.module(db).krate())
575 }
576
577 pub fn name(self, db: &dyn HirDatabase) -> Name {
578 match self {
579 Adt::Struct(s) => s.name(db),
580 Adt::Union(u) => u.name(db),
581 Adt::Enum(e) => e.name(db),
582 }
583 }
584}
585
586#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
587pub enum VariantDef {
588 Struct(Struct),
589 Union(Union),
590 EnumVariant(EnumVariant),
591}
592impl_from!(Struct, Union, EnumVariant for VariantDef);
593
594impl VariantDef {
595 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
596 match self {
597 VariantDef::Struct(it) => it.fields(db),
598 VariantDef::Union(it) => it.fields(db),
599 VariantDef::EnumVariant(it) => it.fields(db),
600 }
601 }
602
603 pub fn module(self, db: &dyn HirDatabase) -> Module {
604 match self {
605 VariantDef::Struct(it) => it.module(db),
606 VariantDef::Union(it) => it.module(db),
607 VariantDef::EnumVariant(it) => it.module(db),
608 }
609 }
610
611 pub fn name(&self, db: &dyn HirDatabase) -> Name {
612 match self {
613 VariantDef::Struct(s) => s.name(db),
614 VariantDef::Union(u) => u.name(db),
615 VariantDef::EnumVariant(e) => e.name(db),
616 }
617 }
618
619 pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
620 match self {
621 VariantDef::Struct(it) => it.variant_data(db),
622 VariantDef::Union(it) => it.variant_data(db),
623 VariantDef::EnumVariant(it) => it.variant_data(db),
624 }
625 }
626}
627
628/// The defs which have a body.
629#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
630pub enum DefWithBody {
631 Function(Function),
632 Static(Static),
633 Const(Const),
634}
635impl_from!(Function, Const, Static for DefWithBody);
636
637impl DefWithBody {
638 pub fn module(self, db: &dyn HirDatabase) -> Module {
639 match self {
640 DefWithBody::Const(c) => c.module(db),
641 DefWithBody::Function(f) => f.module(db),
642 DefWithBody::Static(s) => s.module(db),
643 }
644 }
645
646 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
647 match self {
648 DefWithBody::Function(f) => Some(f.name(db)),
649 DefWithBody::Static(s) => s.name(db),
650 DefWithBody::Const(c) => c.name(db),
651 }
652 }
653}
654
655#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
656pub struct Function {
657 pub(crate) id: FunctionId,
658}
659
660impl Function {
661 pub fn module(self, db: &dyn HirDatabase) -> Module {
662 self.id.lookup(db.upcast()).module(db.upcast()).into()
663 }
664
665 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
666 Some(self.module(db).krate())
667 }
668
669 pub fn name(self, db: &dyn HirDatabase) -> Name {
670 db.function_data(self.id).name.clone()
671 }
672
673 pub fn has_self_param(self, db: &dyn HirDatabase) -> bool {
674 db.function_data(self.id).has_self_param
675 }
676
677 pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeRef> {
678 db.function_data(self.id).params.clone()
679 }
680
681 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
682 db.function_data(self.id).is_unsafe
683 }
684
685 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
686 hir_ty::diagnostics::validate_body(db, self.id.into(), sink)
687 }
688}
689
690impl HasVisibility for Function {
691 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
692 let function_data = db.function_data(self.id);
693 let visibility = &function_data.visibility;
694 visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
695 }
696}
697
698#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
699pub struct Const {
700 pub(crate) id: ConstId,
701}
702
703impl Const {
704 pub fn module(self, db: &dyn HirDatabase) -> Module {
705 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
706 }
707
708 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
709 Some(self.module(db).krate())
710 }
711
712 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
713 db.const_data(self.id).name.clone()
714 }
715}
716
717impl HasVisibility for Const {
718 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
719 let function_data = db.const_data(self.id);
720 let visibility = &function_data.visibility;
721 visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
722 }
723}
724
725#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
726pub struct Static {
727 pub(crate) id: StaticId,
728}
729
730impl Static {
731 pub fn module(self, db: &dyn HirDatabase) -> Module {
732 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
733 }
734
735 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
736 Some(self.module(db).krate())
737 }
738
739 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
740 db.static_data(self.id).name.clone()
741 }
742
743 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
744 db.static_data(self.id).mutable
745 }
746}
747
748#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
749pub struct Trait {
750 pub(crate) id: TraitId,
751}
752
753impl Trait {
754 pub fn module(self, db: &dyn HirDatabase) -> Module {
755 Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) }
756 }
757
758 pub fn name(self, db: &dyn HirDatabase) -> Name {
759 db.trait_data(self.id).name.clone()
760 }
761
762 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
763 db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
764 }
765
766 pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
767 db.trait_data(self.id).auto
768 }
769}
770
771#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
772pub struct TypeAlias {
773 pub(crate) id: TypeAliasId,
774}
775
776impl TypeAlias {
777 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
778 let subst = db.generic_defaults(self.id.into());
779 subst.iter().any(|ty| &ty.value == &Ty::Unknown)
780 }
781
782 pub fn module(self, db: &dyn HirDatabase) -> Module {
783 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
784 }
785
786 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
787 Some(self.module(db).krate())
788 }
789
790 pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> {
791 db.type_alias_data(self.id).type_ref.clone()
792 }
793
794 pub fn ty(self, db: &dyn HirDatabase) -> Type {
795 Type::from_def(db, self.id.lookup(db.upcast()).module(db.upcast()).krate, self.id)
796 }
797
798 pub fn name(self, db: &dyn HirDatabase) -> Name {
799 db.type_alias_data(self.id).name.clone()
800 }
801}
802
803impl HasVisibility for TypeAlias {
804 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
805 let function_data = db.type_alias_data(self.id);
806 let visibility = &function_data.visibility;
807 visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
808 }
809}
810
811#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
812pub struct MacroDef {
813 pub(crate) id: MacroDefId,
814}
815
816impl MacroDef {
817 /// FIXME: right now, this just returns the root module of the crate that
818 /// defines this macro. The reasons for this is that macros are expanded
819 /// early, in `ra_hir_expand`, where modules simply do not exist yet.
820 pub fn module(self, db: &dyn HirDatabase) -> Option<Module> {
821 let krate = self.id.krate?;
822 let module_id = db.crate_def_map(krate).root;
823 Some(Module::new(Crate { id: krate }, module_id))
824 }
825
826 /// XXX: this parses the file
827 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
828 self.source(db).value.name().map(|it| it.as_name())
829 }
830
831 /// Indicate it is a proc-macro
832 pub fn is_proc_macro(&self) -> bool {
833 matches!(self.id.kind, MacroDefKind::CustomDerive(_))
834 }
835
836 /// Indicate it is a derive macro
837 pub fn is_derive_macro(&self) -> bool {
838 matches!(self.id.kind, MacroDefKind::CustomDerive(_) | MacroDefKind::BuiltInDerive(_))
839 }
840}
841
842/// Invariant: `inner.as_assoc_item(db).is_some()`
843/// We do not actively enforce this invariant.
844#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
845pub enum AssocItem {
846 Function(Function),
847 Const(Const),
848 TypeAlias(TypeAlias),
849}
850pub enum AssocItemContainer {
851 Trait(Trait),
852 ImplDef(ImplDef),
853}
854pub trait AsAssocItem {
855 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>;
856}
857
858impl AsAssocItem for Function {
859 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
860 as_assoc_item(db, AssocItem::Function, self.id)
861 }
862}
863impl AsAssocItem for Const {
864 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
865 as_assoc_item(db, AssocItem::Const, self.id)
866 }
867}
868impl AsAssocItem for TypeAlias {
869 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
870 as_assoc_item(db, AssocItem::TypeAlias, self.id)
871 }
872}
873fn as_assoc_item<ID, DEF, CTOR, AST>(db: &dyn HirDatabase, ctor: CTOR, id: ID) -> Option<AssocItem>
874where
875 ID: Lookup<Data = AssocItemLoc<AST>>,
876 DEF: From<ID>,
877 CTOR: FnOnce(DEF) -> AssocItem,
878 AST: ItemTreeNode,
879{
880 match id.lookup(db.upcast()).container {
881 AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
882 AssocContainerId::ContainerId(_) => None,
883 }
884}
885
886impl AssocItem {
887 pub fn module(self, db: &dyn HirDatabase) -> Module {
888 match self {
889 AssocItem::Function(f) => f.module(db),
890 AssocItem::Const(c) => c.module(db),
891 AssocItem::TypeAlias(t) => t.module(db),
892 }
893 }
894 pub fn container(self, db: &dyn HirDatabase) -> AssocItemContainer {
895 let container = match self {
896 AssocItem::Function(it) => it.id.lookup(db.upcast()).container,
897 AssocItem::Const(it) => it.id.lookup(db.upcast()).container,
898 AssocItem::TypeAlias(it) => it.id.lookup(db.upcast()).container,
899 };
900 match container {
901 AssocContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()),
902 AssocContainerId::ImplId(id) => AssocItemContainer::ImplDef(id.into()),
903 AssocContainerId::ContainerId(_) => panic!("invalid AssocItem"),
904 }
905 }
906}
907
908impl HasVisibility for AssocItem {
909 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
910 match self {
911 AssocItem::Function(f) => f.visibility(db),
912 AssocItem::Const(c) => c.visibility(db),
913 AssocItem::TypeAlias(t) => t.visibility(db),
914 }
915 }
916}
917
918#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
919pub enum GenericDef {
920 Function(Function),
921 Adt(Adt),
922 Trait(Trait),
923 TypeAlias(TypeAlias),
924 ImplDef(ImplDef),
925 // enum variants cannot have generics themselves, but their parent enums
926 // can, and this makes some code easier to write
927 EnumVariant(EnumVariant),
928 // consts can have type parameters from their parents (i.e. associated consts of traits)
929 Const(Const),
930}
931impl_from!(
932 Function,
933 Adt(Struct, Enum, Union),
934 Trait,
935 TypeAlias,
936 ImplDef,
937 EnumVariant,
938 Const
939 for GenericDef
940);
941
942impl GenericDef {
943 pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeParam> {
944 let generics: Arc<hir_def::generics::GenericParams> = db.generic_params(self.into());
945 generics
946 .types
947 .iter()
948 .map(|(local_id, _)| TypeParam { id: TypeParamId { parent: self.into(), local_id } })
949 .collect()
950 }
951}
952
953#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
954pub struct Local {
955 pub(crate) parent: DefWithBodyId,
956 pub(crate) pat_id: PatId,
957}
958
959impl Local {
960 pub fn is_param(self, db: &dyn HirDatabase) -> bool {
961 let src = self.source(db);
962 match src.value {
963 Either::Left(bind_pat) => {
964 bind_pat.syntax().ancestors().any(|it| ast::Param::can_cast(it.kind()))
965 }
966 Either::Right(_self_param) => true,
967 }
968 }
969
970 // FIXME: why is this an option? It shouldn't be?
971 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
972 let body = db.body(self.parent.into());
973 match &body[self.pat_id] {
974 Pat::Bind { name, .. } => Some(name.clone()),
975 _ => None,
976 }
977 }
978
979 pub fn is_self(self, db: &dyn HirDatabase) -> bool {
980 self.name(db) == Some(name![self])
981 }
982
983 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
984 let body = db.body(self.parent.into());
985 match &body[self.pat_id] {
986 Pat::Bind { mode, .. } => match mode {
987 BindingAnnotation::Mutable | BindingAnnotation::RefMut => true,
988 _ => false,
989 },
990 _ => false,
991 }
992 }
993
994 pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
995 self.parent.into()
996 }
997
998 pub fn module(self, db: &dyn HirDatabase) -> Module {
999 self.parent(db).module(db)
1000 }
1001
1002 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1003 let def = DefWithBodyId::from(self.parent);
1004 let infer = db.infer(def);
1005 let ty = infer[self.pat_id].clone();
1006 let krate = def.module(db.upcast()).krate;
1007 Type::new(db, krate, def, ty)
1008 }
1009
1010 pub fn source(self, db: &dyn HirDatabase) -> InFile<Either<ast::IdentPat, ast::SelfParam>> {
1011 let (_body, source_map) = db.body_with_source_map(self.parent.into());
1012 let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm...
1013 let root = src.file_syntax(db.upcast());
1014 src.map(|ast| {
1015 ast.map_left(|it| it.cast().unwrap().to_node(&root)).map_right(|it| it.to_node(&root))
1016 })
1017 }
1018}
1019
1020#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1021pub struct TypeParam {
1022 pub(crate) id: TypeParamId,
1023}
1024
1025impl TypeParam {
1026 pub fn name(self, db: &dyn HirDatabase) -> Name {
1027 let params = db.generic_params(self.id.parent);
1028 params.types[self.id.local_id].name.clone().unwrap_or_else(Name::missing)
1029 }
1030
1031 pub fn module(self, db: &dyn HirDatabase) -> Module {
1032 self.id.parent.module(db.upcast()).into()
1033 }
1034
1035 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1036 let resolver = self.id.parent.resolver(db.upcast());
1037 let environment = TraitEnvironment::lower(db, &resolver);
1038 let ty = Ty::Placeholder(self.id);
1039 Type {
1040 krate: self.id.parent.module(db.upcast()).krate,
1041 ty: InEnvironment { value: ty, environment },
1042 }
1043 }
1044
1045 pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
1046 let params = db.generic_defaults(self.id.parent);
1047 let local_idx = hir_ty::param_idx(db, self.id)?;
1048 let resolver = self.id.parent.resolver(db.upcast());
1049 let environment = TraitEnvironment::lower(db, &resolver);
1050 let ty = params.get(local_idx)?.clone();
1051 let subst = Substs::type_params(db, self.id.parent);
1052 let ty = ty.subst(&subst.prefix(local_idx));
1053 Some(Type {
1054 krate: self.id.parent.module(db.upcast()).krate,
1055 ty: InEnvironment { value: ty, environment },
1056 })
1057 }
1058}
1059
1060// FIXME: rename from `ImplDef` to `Impl`
1061#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1062pub struct ImplDef {
1063 pub(crate) id: ImplId,
1064}
1065
1066impl ImplDef {
1067 pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<ImplDef> {
1068 let inherent = db.inherent_impls_in_crate(krate.id);
1069 let trait_ = db.trait_impls_in_crate(krate.id);
1070
1071 inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect()
1072 }
1073 pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplDef> {
1074 let impls = db.trait_impls_in_crate(krate.id);
1075 impls.for_trait(trait_.id).map(Self::from).collect()
1076 }
1077
1078 pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> {
1079 db.impl_data(self.id).target_trait.clone()
1080 }
1081
1082 pub fn target_type(self, db: &dyn HirDatabase) -> TypeRef {
1083 db.impl_data(self.id).target_type.clone()
1084 }
1085
1086 pub fn target_ty(self, db: &dyn HirDatabase) -> Type {
1087 let impl_data = db.impl_data(self.id);
1088 let resolver = self.id.resolver(db.upcast());
1089 let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
1090 let environment = TraitEnvironment::lower(db, &resolver);
1091 let ty = Ty::from_hir(&ctx, &impl_data.target_type);
1092 Type {
1093 krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate,
1094 ty: InEnvironment { value: ty, environment },
1095 }
1096 }
1097
1098 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
1099 db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect()
1100 }
1101
1102 pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
1103 db.impl_data(self.id).is_negative
1104 }
1105
1106 pub fn module(self, db: &dyn HirDatabase) -> Module {
1107 self.id.lookup(db.upcast()).container.module(db.upcast()).into()
1108 }
1109
1110 pub fn krate(self, db: &dyn HirDatabase) -> Crate {
1111 Crate { id: self.module(db).id.krate }
1112 }
1113
1114 pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
1115 let src = self.source(db);
1116 let item = src.file_id.is_builtin_derive(db.upcast())?;
1117 let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id);
1118
1119 let attr = item
1120 .value
1121 .attrs()
1122 .filter_map(|it| {
1123 let path = hir_def::path::ModPath::from_src(it.path()?, &hygenic)?;
1124 if path.as_ident()?.to_string() == "derive" {
1125 Some(it)
1126 } else {
1127 None
1128 }
1129 })
1130 .last()?;
1131
1132 Some(item.with_value(attr))
1133 }
1134}
1135
1136#[derive(Clone, PartialEq, Eq, Debug)]
1137pub struct Type {
1138 krate: CrateId,
1139 ty: InEnvironment<Ty>,
1140}
1141
1142impl Type {
1143 pub(crate) fn new_with_resolver(
1144 db: &dyn HirDatabase,
1145 resolver: &Resolver,
1146 ty: Ty,
1147 ) -> Option<Type> {
1148 let krate = resolver.krate()?;
1149 Some(Type::new_with_resolver_inner(db, krate, resolver, ty))
1150 }
1151 pub(crate) fn new_with_resolver_inner(
1152 db: &dyn HirDatabase,
1153 krate: CrateId,
1154 resolver: &Resolver,
1155 ty: Ty,
1156 ) -> Type {
1157 let environment = TraitEnvironment::lower(db, &resolver);
1158 Type { krate, ty: InEnvironment { value: ty, environment } }
1159 }
1160
1161 fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type {
1162 let resolver = lexical_env.resolver(db.upcast());
1163 let environment = TraitEnvironment::lower(db, &resolver);
1164 Type { krate, ty: InEnvironment { value: ty, environment } }
1165 }
1166
1167 fn from_def(
1168 db: &dyn HirDatabase,
1169 krate: CrateId,
1170 def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>,
1171 ) -> Type {
1172 let substs = Substs::build_for_def(db, def).fill_with_unknown().build();
1173 let ty = db.ty(def.into()).subst(&substs);
1174 Type::new(db, krate, def, ty)
1175 }
1176
1177 pub fn is_unit(&self) -> bool {
1178 matches!(
1179 self.ty.value,
1180 Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { cardinality: 0 }, .. })
1181 )
1182 }
1183 pub fn is_bool(&self) -> bool {
1184 matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. }))
1185 }
1186
1187 pub fn is_mutable_reference(&self) -> bool {
1188 matches!(
1189 self.ty.value,
1190 Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(Mutability::Mut), .. })
1191 )
1192 }
1193
1194 pub fn is_unknown(&self) -> bool {
1195 matches!(self.ty.value, Ty::Unknown)
1196 }
1197
1198 /// Checks that particular type `ty` implements `std::future::Future`.
1199 /// This function is used in `.await` syntax completion.
1200 pub fn impls_future(&self, db: &dyn HirDatabase) -> bool {
1201 let krate = self.krate;
1202
1203 let std_future_trait =
1204 db.lang_item(krate, "future_trait".into()).and_then(|it| it.as_trait());
1205 let std_future_trait = match std_future_trait {
1206 Some(it) => it,
1207 None => return false,
1208 };
1209
1210 let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
1211 method_resolution::implements_trait(
1212 &canonical_ty,
1213 db,
1214 self.ty.environment.clone(),
1215 krate,
1216 std_future_trait,
1217 )
1218 }
1219
1220 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
1221 let trait_ref = hir_ty::TraitRef {
1222 trait_: trait_.id,
1223 substs: Substs::build_for_def(db, trait_.id)
1224 .push(self.ty.value.clone())
1225 .fill(args.iter().map(|t| t.ty.value.clone()))
1226 .build(),
1227 };
1228
1229 let goal = Canonical {
1230 value: hir_ty::InEnvironment::new(
1231 self.ty.environment.clone(),
1232 hir_ty::Obligation::Trait(trait_ref),
1233 ),
1234 kinds: Arc::new([]),
1235 };
1236
1237 db.trait_solve(self.krate, goal).is_some()
1238 }
1239
1240 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
1241 let def = match self.ty.value {
1242 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def),
1243 _ => None,
1244 };
1245
1246 let sig = self.ty.value.callable_sig(db)?;
1247 Some(Callable { ty: self.clone(), sig, def, is_bound_method: false })
1248 }
1249
1250 pub fn is_closure(&self) -> bool {
1251 matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { .. }, .. }))
1252 }
1253
1254 pub fn is_fn(&self) -> bool {
1255 matches!(&self.ty.value,
1256 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(..), .. }) |
1257 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnPtr { .. }, .. })
1258 )
1259 }
1260
1261 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
1262 let adt_id = match self.ty.value {
1263 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_id), .. }) => adt_id,
1264 _ => return false,
1265 };
1266
1267 let adt = adt_id.into();
1268 match adt {
1269 Adt::Struct(s) => matches!(s.repr(db), Some(ReprKind::Packed)),
1270 _ => false,
1271 }
1272 }
1273
1274 pub fn is_raw_ptr(&self) -> bool {
1275 matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }))
1276 }
1277
1278 pub fn contains_unknown(&self) -> bool {
1279 return go(&self.ty.value);
1280
1281 fn go(ty: &Ty) -> bool {
1282 match ty {
1283 Ty::Unknown => true,
1284 Ty::Apply(a_ty) => a_ty.parameters.iter().any(go),
1285 _ => false,
1286 }
1287 }
1288 }
1289
1290 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
1291 if let Ty::Apply(a_ty) = &self.ty.value {
1292 let variant_id = match a_ty.ctor {
1293 TypeCtor::Adt(AdtId::StructId(s)) => s.into(),
1294 TypeCtor::Adt(AdtId::UnionId(u)) => u.into(),
1295 _ => return Vec::new(),
1296 };
1297
1298 return db
1299 .field_types(variant_id)
1300 .iter()
1301 .map(|(local_id, ty)| {
1302 let def = Field { parent: variant_id.into(), id: local_id };
1303 let ty = ty.clone().subst(&a_ty.parameters);
1304 (def, self.derived(ty))
1305 })
1306 .collect();
1307 };
1308 Vec::new()
1309 }
1310
1311 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
1312 let mut res = Vec::new();
1313 if let Ty::Apply(a_ty) = &self.ty.value {
1314 if let TypeCtor::Tuple { .. } = a_ty.ctor {
1315 for ty in a_ty.parameters.iter() {
1316 let ty = ty.clone();
1317 res.push(self.derived(ty));
1318 }
1319 }
1320 };
1321 res
1322 }
1323
1324 pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a {
1325 // There should be no inference vars in types passed here
1326 // FIXME check that?
1327 let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
1328 let environment = self.ty.environment.clone();
1329 let ty = InEnvironment { value: canonical, environment };
1330 autoderef(db, Some(self.krate), ty)
1331 .map(|canonical| canonical.value)
1332 .map(move |ty| self.derived(ty))
1333 }
1334
1335 // This would be nicer if it just returned an iterator, but that runs into
1336 // lifetime problems, because we need to borrow temp `CrateImplDefs`.
1337 pub fn iterate_assoc_items<T>(
1338 self,
1339 db: &dyn HirDatabase,
1340 krate: Crate,
1341 mut callback: impl FnMut(AssocItem) -> Option<T>,
1342 ) -> Option<T> {
1343 for krate in self.ty.value.def_crates(db, krate.id)? {
1344 let impls = db.inherent_impls_in_crate(krate);
1345
1346 for impl_def in impls.for_self_ty(&self.ty.value) {
1347 for &item in db.impl_data(*impl_def).items.iter() {
1348 if let Some(result) = callback(item.into()) {
1349 return Some(result);
1350 }
1351 }
1352 }
1353 }
1354 None
1355 }
1356
1357 pub fn iterate_method_candidates<T>(
1358 &self,
1359 db: &dyn HirDatabase,
1360 krate: Crate,
1361 traits_in_scope: &FxHashSet<TraitId>,
1362 name: Option<&Name>,
1363 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
1364 ) -> Option<T> {
1365 // There should be no inference vars in types passed here
1366 // FIXME check that?
1367 // FIXME replace Unknown by bound vars here
1368 let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
1369
1370 let env = self.ty.environment.clone();
1371 let krate = krate.id;
1372
1373 method_resolution::iterate_method_candidates(
1374 &canonical,
1375 db,
1376 env,
1377 krate,
1378 traits_in_scope,
1379 name,
1380 method_resolution::LookupMode::MethodCall,
1381 |ty, it| match it {
1382 AssocItemId::FunctionId(f) => callback(ty, f.into()),
1383 _ => None,
1384 },
1385 )
1386 }
1387
1388 pub fn iterate_path_candidates<T>(
1389 &self,
1390 db: &dyn HirDatabase,
1391 krate: Crate,
1392 traits_in_scope: &FxHashSet<TraitId>,
1393 name: Option<&Name>,
1394 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
1395 ) -> Option<T> {
1396 // There should be no inference vars in types passed here
1397 // FIXME check that?
1398 // FIXME replace Unknown by bound vars here
1399 let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
1400
1401 let env = self.ty.environment.clone();
1402 let krate = krate.id;
1403
1404 method_resolution::iterate_method_candidates(
1405 &canonical,
1406 db,
1407 env,
1408 krate,
1409 traits_in_scope,
1410 name,
1411 method_resolution::LookupMode::Path,
1412 |ty, it| callback(ty, it.into()),
1413 )
1414 }
1415
1416 pub fn as_adt(&self) -> Option<Adt> {
1417 let (adt, _subst) = self.ty.value.as_adt()?;
1418 Some(adt.into())
1419 }
1420
1421 pub fn as_dyn_trait(&self) -> Option<Trait> {
1422 self.ty.value.dyn_trait().map(Into::into)
1423 }
1424
1425 pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> {
1426 self.ty.value.impl_trait_bounds(db).map(|it| {
1427 it.into_iter()
1428 .filter_map(|pred| match pred {
1429 hir_ty::GenericPredicate::Implemented(trait_ref) => {
1430 Some(Trait::from(trait_ref.trait_))
1431 }
1432 _ => None,
1433 })
1434 .collect()
1435 })
1436 }
1437
1438 pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> {
1439 self.ty.value.associated_type_parent_trait(db).map(Into::into)
1440 }
1441
1442 // FIXME: provide required accessors such that it becomes implementable from outside.
1443 pub fn is_equal_for_find_impls(&self, other: &Type) -> bool {
1444 match (&self.ty.value, &other.ty.value) {
1445 (Ty::Apply(a_original_ty), Ty::Apply(ApplicationTy { ctor, parameters })) => match ctor
1446 {
1447 TypeCtor::Ref(..) => match parameters.as_single() {
1448 Ty::Apply(a_ty) => a_original_ty.ctor == a_ty.ctor,
1449 _ => false,
1450 },
1451 _ => a_original_ty.ctor == *ctor,
1452 },
1453 _ => false,
1454 }
1455 }
1456
1457 fn derived(&self, ty: Ty) -> Type {
1458 Type {
1459 krate: self.krate,
1460 ty: InEnvironment { value: ty, environment: self.ty.environment.clone() },
1461 }
1462 }
1463
1464 pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
1465 // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself.
1466 // We need a different order here.
1467
1468 fn walk_substs(
1469 db: &dyn HirDatabase,
1470 type_: &Type,
1471 substs: &Substs,
1472 cb: &mut impl FnMut(Type),
1473 ) {
1474 for ty in substs.iter() {
1475 walk_type(db, &type_.derived(ty.clone()), cb);
1476 }
1477 }
1478
1479 fn walk_bounds(
1480 db: &dyn HirDatabase,
1481 type_: &Type,
1482 bounds: &[GenericPredicate],
1483 cb: &mut impl FnMut(Type),
1484 ) {
1485 for pred in bounds {
1486 match pred {
1487 GenericPredicate::Implemented(trait_ref) => {
1488 cb(type_.clone());
1489 walk_substs(db, type_, &trait_ref.substs, cb);
1490 }
1491 _ => (),
1492 }
1493 }
1494 }
1495
1496 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
1497 let ty = type_.ty.value.strip_references();
1498 match ty {
1499 Ty::Apply(ApplicationTy { ctor, parameters }) => {
1500 match ctor {
1501 TypeCtor::Adt(_) => {
1502 cb(type_.derived(ty.clone()));
1503 }
1504 TypeCtor::AssociatedType(_) => {
1505 if let Some(_) = ty.associated_type_parent_trait(db) {
1506 cb(type_.derived(ty.clone()));
1507 }
1508 }
1509 _ => (),
1510 }
1511
1512 // adt params, tuples, etc...
1513 walk_substs(db, type_, parameters, cb);
1514 }
1515 Ty::Opaque(opaque_ty) => {
1516 if let Some(bounds) = ty.impl_trait_bounds(db) {
1517 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1518 }
1519
1520 walk_substs(db, type_, &opaque_ty.parameters, cb);
1521 }
1522 Ty::Placeholder(_) => {
1523 if let Some(bounds) = ty.impl_trait_bounds(db) {
1524 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1525 }
1526 }
1527 Ty::Dyn(bounds) => {
1528 walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
1529 }
1530
1531 _ => (),
1532 }
1533 }
1534
1535 walk_type(db, self, &mut cb);
1536 }
1537}
1538
1539impl HirDisplay for Type {
1540 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
1541 self.ty.value.hir_fmt(f)
1542 }
1543}
1544
1545// FIXME: closures
1546#[derive(Debug)]
1547pub struct Callable {
1548 ty: Type,
1549 sig: FnSig,
1550 def: Option<CallableDefId>,
1551 pub(crate) is_bound_method: bool,
1552}
1553
1554pub enum CallableKind {
1555 Function(Function),
1556 TupleStruct(Struct),
1557 TupleEnumVariant(EnumVariant),
1558 Closure,
1559}
1560
1561impl Callable {
1562 pub fn kind(&self) -> CallableKind {
1563 match self.def {
1564 Some(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
1565 Some(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
1566 Some(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
1567 None => CallableKind::Closure,
1568 }
1569 }
1570 pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> {
1571 let func = match self.def {
1572 Some(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
1573 _ => return None,
1574 };
1575 let src = func.lookup(db.upcast()).source(db.upcast());
1576 let param_list = src.value.param_list()?;
1577 param_list.self_param()
1578 }
1579 pub fn n_params(&self) -> usize {
1580 self.sig.params().len() - if self.is_bound_method { 1 } else { 0 }
1581 }
1582 pub fn params(
1583 &self,
1584 db: &dyn HirDatabase,
1585 ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> {
1586 let types = self
1587 .sig
1588 .params()
1589 .iter()
1590 .skip(if self.is_bound_method { 1 } else { 0 })
1591 .map(|ty| self.ty.derived(ty.clone()));
1592 let patterns = match self.def {
1593 Some(CallableDefId::FunctionId(func)) => {
1594 let src = func.lookup(db.upcast()).source(db.upcast());
1595 src.value.param_list().map(|param_list| {
1596 param_list
1597 .self_param()
1598 .map(|it| Some(Either::Left(it)))
1599 .filter(|_| !self.is_bound_method)
1600 .into_iter()
1601 .chain(param_list.params().map(|it| it.pat().map(Either::Right)))
1602 })
1603 }
1604 _ => None,
1605 };
1606 patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
1607 }
1608 pub fn return_type(&self) -> Type {
1609 self.ty.derived(self.sig.ret().clone())
1610 }
1611}
1612
1613/// For IDE only
1614#[derive(Debug)]
1615pub enum ScopeDef {
1616 ModuleDef(ModuleDef),
1617 MacroDef(MacroDef),
1618 GenericParam(TypeParam),
1619 ImplSelfType(ImplDef),
1620 AdtSelfType(Adt),
1621 Local(Local),
1622 Unknown,
1623}
1624
1625impl ScopeDef {
1626 pub fn all_items(def: PerNs) -> ArrayVec<[Self; 3]> {
1627 let mut items = ArrayVec::new();
1628
1629 match (def.take_types(), def.take_values()) {
1630 (Some(m1), None) => items.push(ScopeDef::ModuleDef(m1.into())),
1631 (None, Some(m2)) => items.push(ScopeDef::ModuleDef(m2.into())),
1632 (Some(m1), Some(m2)) => {
1633 // Some items, like unit structs and enum variants, are
1634 // returned as both a type and a value. Here we want
1635 // to de-duplicate them.
1636 if m1 != m2 {
1637 items.push(ScopeDef::ModuleDef(m1.into()));
1638 items.push(ScopeDef::ModuleDef(m2.into()));
1639 } else {
1640 items.push(ScopeDef::ModuleDef(m1.into()));
1641 }
1642 }
1643 (None, None) => {}
1644 };
1645
1646 if let Some(macro_def_id) = def.take_macros() {
1647 items.push(ScopeDef::MacroDef(macro_def_id.into()));
1648 }
1649
1650 if items.is_empty() {
1651 items.push(ScopeDef::Unknown);
1652 }
1653
1654 items
1655 }
1656}
1657
1658#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1659pub enum AttrDef {
1660 Module(Module),
1661 Field(Field),
1662 Adt(Adt),
1663 Function(Function),
1664 EnumVariant(EnumVariant),
1665 Static(Static),
1666 Const(Const),
1667 Trait(Trait),
1668 TypeAlias(TypeAlias),
1669 MacroDef(MacroDef),
1670}
1671
1672impl_from!(
1673 Module,
1674 Field,
1675 Adt(Struct, Enum, Union),
1676 EnumVariant,
1677 Static,
1678 Const,
1679 Function,
1680 Trait,
1681 TypeAlias,
1682 MacroDef
1683 for AttrDef
1684);
1685
1686pub trait HasAttrs {
1687 fn attrs(self, db: &dyn HirDatabase) -> Attrs;
1688}
1689
1690impl<T: Into<AttrDef>> HasAttrs for T {
1691 fn attrs(self, db: &dyn HirDatabase) -> Attrs {
1692 let def: AttrDef = self.into();
1693 db.attrs(def.into())
1694 }
1695}
1696
1697pub trait Docs {
1698 fn docs(&self, db: &dyn HirDatabase) -> Option<Documentation>;
1699}
1700impl<T: Into<AttrDef> + Copy> Docs for T {
1701 fn docs(&self, db: &dyn HirDatabase) -> Option<Documentation> {
1702 let def: AttrDef = (*self).into();
1703 db.documentation(def.into())
1704 }
1705}
1706
1707pub trait HasVisibility {
1708 fn visibility(&self, db: &dyn HirDatabase) -> Visibility;
1709 fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool {
1710 let vis = self.visibility(db);
1711 vis.is_visible_from(db.upcast(), module.id)
1712 }
1713}