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