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