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