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