1 //! HIR (previously known as descriptors) provides a high-level object oriented
2 //! access to Rust code.
4 //! The principal difference between HIR and syntax trees is that HIR is bound
5 //! to a particular crate instance. That is, it has cfg flags and features
6 //! applied. So, the relation between syntax and HIR is many-to-one.
8 //! HIR is the public API of the all of the compiler logic above syntax trees.
9 //! It is written in "OO" style. Each type is self contained (as in, it knows it's
10 //! parents and full context). It should be "clean code".
12 //! `hir_*` crates are the implementation of the compiler logic.
13 //! They are written in "ECS" style, with relatively little abstractions.
14 //! Many types are not self-contained, and explicitly use local indexes, arenas, etc.
16 //! `hir` is what insulates the "we don't know how to actually write an incremental compiler"
17 //! from the ide with completions, hovers, etc. It is a (soft, internal) boundary:
18 //! <https://www.tedinski.com/2018/02/06/system-boundaries.html>.
20 #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
21 #![recursion_limit = "512"]
36 use std::{iter, ops::ControlFlow, sync::Arc};
38 use arrayvec::ArrayVec;
39 use base_db::{CrateDisplayName, CrateId, CrateOrigin, Edition, FileId, ProcMacroKind};
42 adt::{ReprData, VariantData},
43 body::{BodyDiagnostic, SyntheticSyntax},
44 expr::{BindingAnnotation, LabelId, Pat, PatId},
45 generics::{TypeOrConstParamData, TypeParamProvenance},
46 item_tree::ItemTreeNode,
47 lang_item::LangItemTarget,
48 nameres::{self, diagnostics::DefDiagnostic},
50 resolver::{HasResolver, Resolver},
52 AdtId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
53 EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
54 LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId,
55 TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
57 use hir_expand::{name::name, MacroCallKind};
59 all_super_traits, autoderef,
60 consteval::{unknown_const_as_generic, ComputedExpr, ConstEvalError, ConstExt},
61 diagnostics::BodyValidationDiagnostic,
62 method_resolution::{self, TyFingerprint},
65 AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId,
66 GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
67 TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, WhereClause,
69 use itertools::Itertools;
70 use nameres::diagnostics::DefDiagnosticKind;
71 use once_cell::unsync::Lazy;
72 use rustc_hash::FxHashSet;
73 use stdx::{impl_from, never};
75 ast::{self, Expr, HasAttrs as _, HasDocComments, HasName},
76 AstNode, AstPtr, SmolStr, SyntaxNodePtr, TextRange, T,
79 use crate::db::{DefDatabase, HirDatabase};
82 attrs::{HasAttrs, Namespace},
84 AnyDiagnostic, BreakOutsideOfLoop, InactiveCode, IncorrectCase, InvalidDeriveTarget,
85 MacroError, MalformedDerive, MismatchedArgCount, MissingFields, MissingMatchArms,
86 MissingUnsafe, NoSuchField, ReplaceFilterMapNextWithFindMap, TypeMismatch,
87 UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall,
88 UnresolvedModule, UnresolvedProcMacro,
90 has_source::HasSource,
91 semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo, VisibleTraits},
94 // Be careful with these re-exports.
96 // `hir` is the boundary between the compiler and the IDE. It should try hard to
97 // isolate the compiler from the ide, to allow the two to be refactored
98 // independently. Re-exporting something from the compiler is the sure way to
99 // breach the boundary.
101 // Generally, a refactoring which *removes* a name from this list is a good
104 cfg::{CfgAtom, CfgExpr, CfgOptions},
107 attr::{Attr, Attrs, AttrsWithOwner, Documentation},
108 builtin_attr::AttributeTemplate,
109 find_path::PrefixKind,
111 nameres::ModuleSource,
112 path::{ModPath, PathKind},
113 type_ref::{Mutability, TypeRef},
114 visibility::Visibility,
118 ExpandResult, HirFileId, InFile, MacroFile, Origin,
120 hir_ty::display::HirDisplay,
123 // These are negative re-exports: pub using these names is forbidden, they
124 // should remain private to hir internals.
128 hir_expand::{hygiene::Hygiene, name::AsName},
131 /// hir::Crate describes a single crate. It's the main interface with which
132 /// a crate's dependencies interact. Mostly, it should be just a proxy for the
134 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
136 pub(crate) id: CrateId,
140 pub struct CrateDependency {
146 pub fn origin(self, db: &dyn HirDatabase) -> CrateOrigin {
147 db.crate_graph()[self.id].origin.clone()
150 pub fn is_builtin(self, db: &dyn HirDatabase) -> bool {
151 matches!(self.origin(db), CrateOrigin::Lang(_))
154 pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
155 db.crate_graph()[self.id]
159 let krate = Crate { id: dep.crate_id };
160 let name = dep.as_name();
161 CrateDependency { krate, name }
166 pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
167 let crate_graph = db.crate_graph();
171 crate_graph[krate].dependencies.iter().any(|it| it.crate_id == self.id)
173 .map(|id| Crate { id })
177 pub fn transitive_reverse_dependencies(
179 db: &dyn HirDatabase,
180 ) -> impl Iterator<Item = Crate> {
181 db.crate_graph().transitive_rev_deps(self.id).map(|id| Crate { id })
184 pub fn root_module(self, db: &dyn HirDatabase) -> Module {
185 let def_map = db.crate_def_map(self.id);
186 Module { id: def_map.module_id(def_map.root()) }
189 pub fn modules(self, db: &dyn HirDatabase) -> Vec<Module> {
190 let def_map = db.crate_def_map(self.id);
191 def_map.modules().map(|(id, _)| def_map.module_id(id).into()).collect()
194 pub fn root_file(self, db: &dyn HirDatabase) -> FileId {
195 db.crate_graph()[self.id].root_file_id
198 pub fn edition(self, db: &dyn HirDatabase) -> Edition {
199 db.crate_graph()[self.id].edition
202 pub fn version(self, db: &dyn HirDatabase) -> Option<String> {
203 db.crate_graph()[self.id].version.clone()
206 pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateDisplayName> {
207 db.crate_graph()[self.id].display_name.clone()
210 pub fn query_external_importables(
212 db: &dyn DefDatabase,
213 query: import_map::Query,
214 ) -> impl Iterator<Item = Either<ModuleDef, Macro>> {
215 let _p = profile::span("query_external_importables");
216 import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| {
217 match ItemInNs::from(item) {
218 ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id),
219 ItemInNs::Macros(mac_id) => Either::Right(mac_id),
224 pub fn all(db: &dyn HirDatabase) -> Vec<Crate> {
225 db.crate_graph().iter().map(|id| Crate { id }).collect()
228 /// Try to get the root URL of the documentation of a crate.
229 pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
230 // Look for #![doc(html_root_url = "...")]
231 let attrs = db.attrs(AttrDefId::ModuleId(self.root_module(db).into()));
232 let doc_url = attrs.by_key("doc").find_string_value_in_tt("html_root_url");
233 doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
236 pub fn cfg(&self, db: &dyn HirDatabase) -> CfgOptions {
237 db.crate_graph()[self.id].cfg_options.clone()
240 pub fn potential_cfg(&self, db: &dyn HirDatabase) -> CfgOptions {
241 db.crate_graph()[self.id].potential_cfg_options.clone()
245 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
247 pub(crate) id: ModuleId,
250 /// The defs which can be visible in the module.
251 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
256 // Can't be directly declared, but can be imported.
261 TypeAlias(TypeAlias),
262 BuiltinType(BuiltinType),
268 Adt(Struct, Enum, Union),
279 impl From<VariantDef> for ModuleDef {
280 fn from(var: VariantDef) -> Self {
282 VariantDef::Struct(t) => Adt::from(t).into(),
283 VariantDef::Union(t) => Adt::from(t).into(),
284 VariantDef::Variant(t) => t.into(),
290 pub fn module(self, db: &dyn HirDatabase) -> Option<Module> {
292 ModuleDef::Module(it) => it.parent(db),
293 ModuleDef::Function(it) => Some(it.module(db)),
294 ModuleDef::Adt(it) => Some(it.module(db)),
295 ModuleDef::Variant(it) => Some(it.module(db)),
296 ModuleDef::Const(it) => Some(it.module(db)),
297 ModuleDef::Static(it) => Some(it.module(db)),
298 ModuleDef::Trait(it) => Some(it.module(db)),
299 ModuleDef::TypeAlias(it) => Some(it.module(db)),
300 ModuleDef::Macro(it) => Some(it.module(db)),
301 ModuleDef::BuiltinType(_) => None,
305 pub fn canonical_path(&self, db: &dyn HirDatabase) -> Option<String> {
306 let mut segments = vec![self.name(db)?];
307 for m in self.module(db)?.path_to_root(db) {
308 segments.extend(m.name(db))
311 Some(segments.into_iter().join("::"))
314 pub fn canonical_module_path(
316 db: &dyn HirDatabase,
317 ) -> Option<impl Iterator<Item = Module>> {
318 self.module(db).map(|it| it.path_to_root(db).into_iter().rev())
321 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
322 let name = match self {
323 ModuleDef::Module(it) => it.name(db)?,
324 ModuleDef::Const(it) => it.name(db)?,
325 ModuleDef::Adt(it) => it.name(db),
326 ModuleDef::Trait(it) => it.name(db),
327 ModuleDef::Function(it) => it.name(db),
328 ModuleDef::Variant(it) => it.name(db),
329 ModuleDef::TypeAlias(it) => it.name(db),
330 ModuleDef::Static(it) => it.name(db),
331 ModuleDef::Macro(it) => it.name(db),
332 ModuleDef::BuiltinType(it) => it.name(),
337 pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec<AnyDiagnostic> {
338 let id = match self {
339 ModuleDef::Adt(it) => match it {
340 Adt::Struct(it) => it.id.into(),
341 Adt::Enum(it) => it.id.into(),
342 Adt::Union(it) => it.id.into(),
344 ModuleDef::Trait(it) => it.id.into(),
345 ModuleDef::Function(it) => it.id.into(),
346 ModuleDef::TypeAlias(it) => it.id.into(),
347 ModuleDef::Module(it) => it.id.into(),
348 ModuleDef::Const(it) => it.id.into(),
349 ModuleDef::Static(it) => it.id.into(),
350 ModuleDef::Variant(it) => {
351 EnumVariantId { parent: it.parent.into(), local_id: it.id }.into()
353 ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(),
356 let module = match self.module(db) {
358 None => return Vec::new(),
361 let mut acc = Vec::new();
363 match self.as_def_with_body() {
365 def.diagnostics(db, &mut acc);
368 for diag in hir_ty::diagnostics::incorrect_case(db, module.id.krate(), id) {
369 acc.push(diag.into())
377 pub fn as_def_with_body(self) -> Option<DefWithBody> {
379 ModuleDef::Function(it) => Some(it.into()),
380 ModuleDef::Const(it) => Some(it.into()),
381 ModuleDef::Static(it) => Some(it.into()),
382 ModuleDef::Variant(it) => Some(it.into()),
386 | ModuleDef::Trait(_)
387 | ModuleDef::TypeAlias(_)
388 | ModuleDef::Macro(_)
389 | ModuleDef::BuiltinType(_) => None,
393 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
395 ModuleDef::Module(it) => it.attrs(db),
396 ModuleDef::Function(it) => it.attrs(db),
397 ModuleDef::Adt(it) => it.attrs(db),
398 ModuleDef::Variant(it) => it.attrs(db),
399 ModuleDef::Const(it) => it.attrs(db),
400 ModuleDef::Static(it) => it.attrs(db),
401 ModuleDef::Trait(it) => it.attrs(db),
402 ModuleDef::TypeAlias(it) => it.attrs(db),
403 ModuleDef::Macro(it) => it.attrs(db),
404 ModuleDef::BuiltinType(_) => return None,
409 impl HasVisibility for ModuleDef {
410 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
412 ModuleDef::Module(it) => it.visibility(db),
413 ModuleDef::Function(it) => it.visibility(db),
414 ModuleDef::Adt(it) => it.visibility(db),
415 ModuleDef::Const(it) => it.visibility(db),
416 ModuleDef::Static(it) => it.visibility(db),
417 ModuleDef::Trait(it) => it.visibility(db),
418 ModuleDef::TypeAlias(it) => it.visibility(db),
419 ModuleDef::Variant(it) => it.visibility(db),
420 ModuleDef::Macro(it) => it.visibility(db),
421 ModuleDef::BuiltinType(_) => Visibility::Public,
427 /// Name of this module.
428 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
429 let def_map = self.id.def_map(db.upcast());
430 let parent = def_map[self.id.local_id].parent?;
431 def_map[parent].children.iter().find_map(|(name, module_id)| {
432 if *module_id == self.id.local_id {
440 /// Returns the crate this module is part of.
441 pub fn krate(self) -> Crate {
442 Crate { id: self.id.krate() }
445 /// Topmost parent of this module. Every module has a `crate_root`, but some
446 /// might be missing `krate`. This can happen if a module's file is not included
447 /// in the module tree of any target in `Cargo.toml`.
448 pub fn crate_root(self, db: &dyn HirDatabase) -> Module {
449 let def_map = db.crate_def_map(self.id.krate());
450 Module { id: def_map.module_id(def_map.root()) }
453 pub fn is_crate_root(self, db: &dyn HirDatabase) -> bool {
454 let def_map = db.crate_def_map(self.id.krate());
455 def_map.root() == self.id.local_id
458 /// Iterates over all child modules.
459 pub fn children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module> {
460 let def_map = self.id.def_map(db.upcast());
461 let children = def_map[self.id.local_id]
464 .map(|(_, module_id)| Module { id: def_map.module_id(*module_id) })
465 .collect::<Vec<_>>();
469 /// Finds a parent module.
470 pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> {
471 // FIXME: handle block expressions as modules (their parent is in a different DefMap)
472 let def_map = self.id.def_map(db.upcast());
473 let parent_id = def_map[self.id.local_id].parent?;
474 Some(Module { id: def_map.module_id(parent_id) })
477 pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> {
478 let mut res = vec![self];
480 while let Some(next) = curr.parent(db) {
487 /// Returns a `ModuleScope`: a set of items, visible in this module.
490 db: &dyn HirDatabase,
491 visible_from: Option<Module>,
492 ) -> Vec<(Name, ScopeDef)> {
493 self.id.def_map(db.upcast())[self.id.local_id]
496 .filter_map(|(name, def)| {
497 if let Some(m) = visible_from {
499 def.filter_visibility(|vis| vis.is_visible_from(db.upcast(), m.id));
500 if filtered.is_none() && !def.is_none() {
503 Some((name, filtered))
509 .flat_map(|(name, def)| {
510 ScopeDef::all_items(def).into_iter().map(move |item| (name.clone(), item))
515 /// Fills `acc` with the module's diagnostics.
516 pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
517 let _p = profile::span("Module::diagnostics").detail(|| {
518 format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string()))
520 let def_map = self.id.def_map(db.upcast());
521 for diag in def_map.diagnostics() {
522 if diag.in_module != self.id.local_id {
523 // FIXME: This is accidentally quadratic.
526 emit_def_diagnostic(db, acc, diag);
528 for decl in self.declarations(db) {
530 ModuleDef::Module(m) => {
531 // Only add diagnostics from inline modules
532 if def_map[m.id.local_id].origin.is_inline() {
533 m.diagnostics(db, acc)
536 ModuleDef::Trait(t) => {
537 for diag in db.trait_data_with_diagnostics(t.id).1.iter() {
538 emit_def_diagnostic(db, acc, diag);
540 acc.extend(decl.diagnostics(db))
542 ModuleDef::Adt(adt) => {
545 for diag in db.struct_data_with_diagnostics(s.id).1.iter() {
546 emit_def_diagnostic(db, acc, diag);
550 for diag in db.union_data_with_diagnostics(u.id).1.iter() {
551 emit_def_diagnostic(db, acc, diag);
555 for v in e.variants(db) {
556 acc.extend(ModuleDef::Variant(v).diagnostics(db));
559 for diag in db.enum_data_with_diagnostics(e.id).1.iter() {
560 emit_def_diagnostic(db, acc, diag);
564 acc.extend(decl.diagnostics(db))
566 _ => acc.extend(decl.diagnostics(db)),
570 for impl_def in self.impl_defs(db) {
571 for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() {
572 emit_def_diagnostic(db, acc, diag);
575 for item in impl_def.items(db) {
576 let def: DefWithBody = match item {
577 AssocItem::Function(it) => it.into(),
578 AssocItem::Const(it) => it.into(),
579 AssocItem::TypeAlias(_) => continue,
582 def.diagnostics(db, acc);
587 pub fn declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef> {
588 let def_map = self.id.def_map(db.upcast());
589 let scope = &def_map[self.id.local_id].scope;
592 .map(ModuleDef::from)
593 .chain(scope.unnamed_consts().map(|id| ModuleDef::Const(Const::from(id))))
597 pub fn legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro> {
598 let def_map = self.id.def_map(db.upcast());
599 let scope = &def_map[self.id.local_id].scope;
600 scope.legacy_macros().flat_map(|(_, it)| it).map(|&it| MacroId::from(it).into()).collect()
603 pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {
604 let def_map = self.id.def_map(db.upcast());
605 def_map[self.id.local_id].scope.impls().map(Impl::from).collect()
608 /// Finds a path that can be used to refer to the given item from within
609 /// this module, if possible.
610 pub fn find_use_path(
612 db: &dyn DefDatabase,
613 item: impl Into<ItemInNs>,
615 ) -> Option<ModPath> {
616 hir_def::find_path::find_path(db, item.into().into(), self.into(), prefer_no_std)
619 /// Finds a path that can be used to refer to the given item from within
620 /// this module, if possible. This is used for returning import paths for use-statements.
621 pub fn find_use_path_prefixed(
623 db: &dyn DefDatabase,
624 item: impl Into<ItemInNs>,
625 prefix_kind: PrefixKind,
627 ) -> Option<ModPath> {
628 hir_def::find_path::find_path_prefixed(
638 fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag: &DefDiagnostic) {
640 DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates } => {
641 let decl = declaration.to_node(db.upcast());
644 decl: InFile::new(declaration.file_id, AstPtr::new(&decl)),
645 candidates: candidates.clone(),
650 DefDiagnosticKind::UnresolvedExternCrate { ast } => {
651 let item = ast.to_node(db.upcast());
653 UnresolvedExternCrate { decl: InFile::new(ast.file_id, AstPtr::new(&item)) }.into(),
657 DefDiagnosticKind::UnresolvedImport { id, index } => {
658 let file_id = id.file_id();
659 let item_tree = id.item_tree(db.upcast());
660 let import = &item_tree[id.value];
662 let use_tree = import.use_tree_to_ast(db.upcast(), file_id, *index);
664 UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) }.into(),
668 DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
669 let item = ast.to_node(db.upcast());
672 node: ast.with_value(AstPtr::new(&item).into()),
680 DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => {
681 let (node, precise_location, macro_name, kind) = precise_macro_call_location(ast, db);
683 UnresolvedProcMacro { node, precise_location, macro_name, kind, krate: *krate }
688 DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
689 let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
691 UnresolvedMacroCall {
695 is_bang: matches!(ast, MacroCallKind::FnLike { .. }),
701 DefDiagnosticKind::MacroError { ast, message } => {
702 let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
703 acc.push(MacroError { node, precise_location, message: message.clone() }.into());
706 DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
707 let node = ast.to_node(db.upcast());
708 // Must have a name, otherwise we wouldn't emit it.
709 let name = node.name().expect("unimplemented builtin macro with no name");
711 UnimplementedBuiltinMacro {
712 node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&name))),
717 DefDiagnosticKind::InvalidDeriveTarget { ast, id } => {
718 let node = ast.to_node(db.upcast());
719 let derive = node.attrs().nth(*id as usize);
723 InvalidDeriveTarget {
724 node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
729 None => stdx::never!("derive diagnostic on item without derive attribute"),
732 DefDiagnosticKind::MalformedDerive { ast, id } => {
733 let node = ast.to_node(db.upcast());
734 let derive = node.attrs().nth(*id as usize);
739 node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
744 None => stdx::never!("derive diagnostic on item without derive attribute"),
750 fn precise_macro_call_location(
752 db: &dyn HirDatabase,
753 ) -> (InFile<SyntaxNodePtr>, Option<TextRange>, Option<String>, MacroKind) {
754 // FIXME: maaybe we actually want slightly different ranges for the different macro diagnostics
755 // - e.g. the full attribute for macro errors, but only the name for name resolution
757 MacroCallKind::FnLike { ast_id, .. } => {
758 let node = ast_id.to_node(db.upcast());
760 ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
762 .and_then(|it| it.segment())
763 .and_then(|it| it.name_ref())
764 .map(|it| it.syntax().text_range()),
765 node.path().and_then(|it| it.segment()).map(|it| it.to_string()),
766 MacroKind::ProcMacro,
769 MacroCallKind::Derive { ast_id, derive_attr_index, derive_index } => {
770 let node = ast_id.to_node(db.upcast());
771 // Compute the precise location of the macro name's token in the derive
774 let derive_attr = node
775 .doc_comments_and_attrs()
776 .nth(*derive_attr_index as usize)
777 .and_then(Either::left)?;
778 let token_tree = derive_attr.meta()?.token_tree()?;
779 let group_by = token_tree
781 .children_with_tokens()
782 .filter_map(|elem| match elem {
783 syntax::NodeOrToken::Token(tok) => Some(tok),
786 .group_by(|t| t.kind() == T![,]);
787 let (_, mut group) = group_by
789 .filter(|&(comma, _)| !comma)
790 .nth(*derive_index as usize)?;
791 group.find(|t| t.kind() == T![ident])
794 ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
795 token.as_ref().map(|tok| tok.text_range()),
796 token.as_ref().map(ToString::to_string),
800 MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
801 let node = ast_id.to_node(db.upcast());
803 .doc_comments_and_attrs()
804 .nth((*invoc_attr_index) as usize)
805 .and_then(Either::left)
806 .unwrap_or_else(|| panic!("cannot find attribute #{}", invoc_attr_index));
809 ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
810 Some(attr.syntax().text_range()),
812 .and_then(|path| path.segment())
813 .and_then(|seg| seg.name_ref())
815 .map(ToString::to_string),
822 impl HasVisibility for Module {
823 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
824 let def_map = self.id.def_map(db.upcast());
825 let module_data = &def_map[self.id.local_id];
826 module_data.visibility
830 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
832 pub(crate) parent: VariantDef,
833 pub(crate) id: LocalFieldId,
836 #[derive(Debug, PartialEq, Eq)]
837 pub enum FieldSource {
838 Named(ast::RecordField),
839 Pos(ast::TupleField),
843 pub fn name(&self, db: &dyn HirDatabase) -> Name {
844 self.parent.variant_data(db).fields()[self.id].name.clone()
847 /// Returns the type as in the signature of the struct (i.e., with
848 /// placeholder types for type parameters). Only use this in the context of
849 /// the field definition.
850 pub fn ty(&self, db: &dyn HirDatabase) -> Type {
851 let var_id = self.parent.into();
852 let generic_def_id: GenericDefId = match self.parent {
853 VariantDef::Struct(it) => it.id.into(),
854 VariantDef::Union(it) => it.id.into(),
855 VariantDef::Variant(it) => it.parent.id.into(),
857 let substs = TyBuilder::placeholder_subst(db, generic_def_id);
858 let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs);
859 Type::new(db, var_id, ty)
862 pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
867 impl HasVisibility for Field {
868 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
869 let variant_data = self.parent.variant_data(db);
870 let visibility = &variant_data.fields()[self.id].visibility;
871 let parent_id: hir_def::VariantId = self.parent.into();
872 visibility.resolve(db.upcast(), &parent_id.resolver(db.upcast()))
876 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
878 pub(crate) id: StructId,
882 pub fn module(self, db: &dyn HirDatabase) -> Module {
883 Module { id: self.id.lookup(db.upcast()).container }
886 pub fn name(self, db: &dyn HirDatabase) -> Name {
887 db.struct_data(self.id).name.clone()
890 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
891 db.struct_data(self.id)
895 .map(|(id, _)| Field { parent: self.into(), id })
899 pub fn ty(self, db: &dyn HirDatabase) -> Type {
900 Type::from_def(db, self.id)
903 pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprData> {
904 db.struct_data(self.id).repr.clone()
907 pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
908 self.variant_data(db).kind()
911 fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
912 db.struct_data(self.id).variant_data.clone()
916 impl HasVisibility for Struct {
917 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
918 db.struct_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
922 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
924 pub(crate) id: UnionId,
928 pub fn name(self, db: &dyn HirDatabase) -> Name {
929 db.union_data(self.id).name.clone()
932 pub fn module(self, db: &dyn HirDatabase) -> Module {
933 Module { id: self.id.lookup(db.upcast()).container }
936 pub fn ty(self, db: &dyn HirDatabase) -> Type {
937 Type::from_def(db, self.id)
940 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
941 db.union_data(self.id)
945 .map(|(id, _)| Field { parent: self.into(), id })
949 fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
950 db.union_data(self.id).variant_data.clone()
954 impl HasVisibility for Union {
955 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
956 db.union_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
960 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
962 pub(crate) id: EnumId,
966 pub fn module(self, db: &dyn HirDatabase) -> Module {
967 Module { id: self.id.lookup(db.upcast()).container }
970 pub fn name(self, db: &dyn HirDatabase) -> Name {
971 db.enum_data(self.id).name.clone()
974 pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> {
975 db.enum_data(self.id).variants.iter().map(|(id, _)| Variant { parent: self, id }).collect()
978 pub fn ty(self, db: &dyn HirDatabase) -> Type {
979 Type::from_def(db, self.id)
982 /// The type of the enum variant bodies.
983 pub fn variant_body_ty(self, db: &dyn HirDatabase) -> Type {
985 self.id.lookup(db.upcast()).container.krate(),
986 TyBuilder::builtin(match db.enum_data(self.id).variant_body_type() {
987 Either::Left(builtin) => hir_def::builtin_type::BuiltinType::Int(builtin),
988 Either::Right(builtin) => hir_def::builtin_type::BuiltinType::Uint(builtin),
993 pub fn is_data_carrying(self, db: &dyn HirDatabase) -> bool {
994 self.variants(db).iter().any(|v| !matches!(v.kind(db), StructKind::Unit))
998 impl HasVisibility for Enum {
999 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1000 db.enum_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1004 impl From<&Variant> for DefWithBodyId {
1005 fn from(&v: &Variant) -> Self {
1006 DefWithBodyId::VariantId(v.into())
1010 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1011 pub struct Variant {
1012 pub(crate) parent: Enum,
1013 pub(crate) id: LocalEnumVariantId,
1017 pub fn module(self, db: &dyn HirDatabase) -> Module {
1018 self.parent.module(db)
1021 pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum {
1025 pub fn name(self, db: &dyn HirDatabase) -> Name {
1026 db.enum_data(self.parent.id).variants[self.id].name.clone()
1029 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
1030 self.variant_data(db)
1033 .map(|(id, _)| Field { parent: self.into(), id })
1037 pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
1038 self.variant_data(db).kind()
1041 pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
1042 db.enum_data(self.parent.id).variants[self.id].variant_data.clone()
1045 pub fn value(self, db: &dyn HirDatabase) -> Option<Expr> {
1046 self.source(db)?.value.expr()
1049 pub fn eval(self, db: &dyn HirDatabase) -> Result<ComputedExpr, ConstEvalError> {
1050 db.const_eval_variant(self.into())
1054 /// Variants inherit visibility from the parent enum.
1055 impl HasVisibility for Variant {
1056 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1057 self.parent_enum(db).visibility(db)
1062 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1068 impl_from!(Struct, Union, Enum for Adt);
1071 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
1072 let subst = db.generic_defaults(self.into());
1073 subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
1074 GenericArgData::Ty(x) => x.is_unknown(),
1079 /// Turns this ADT into a type. Any type parameters of the ADT will be
1080 /// turned into unknown types, which is good for e.g. finding the most
1081 /// general set of completions, but will not look very nice when printed.
1082 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1083 let id = AdtId::from(self);
1084 Type::from_def(db, id)
1087 /// Turns this ADT into a type with the given type parameters. This isn't
1088 /// the greatest API, FIXME find a better one.
1089 pub fn ty_with_args(self, db: &dyn HirDatabase, args: &[Type]) -> Type {
1090 let id = AdtId::from(self);
1091 let mut it = args.iter().map(|t| t.ty.clone());
1092 let ty = TyBuilder::def_ty(db, id.into(), None)
1094 let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
1096 ParamKind::Type => GenericArgData::Ty(r).intern(Interner),
1097 ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
1101 Type::new(db, id, ty)
1104 pub fn module(self, db: &dyn HirDatabase) -> Module {
1106 Adt::Struct(s) => s.module(db),
1107 Adt::Union(s) => s.module(db),
1108 Adt::Enum(e) => e.module(db),
1112 pub fn name(self, db: &dyn HirDatabase) -> Name {
1114 Adt::Struct(s) => s.name(db),
1115 Adt::Union(u) => u.name(db),
1116 Adt::Enum(e) => e.name(db),
1120 pub fn as_enum(&self) -> Option<Enum> {
1121 if let Self::Enum(v) = self {
1129 impl HasVisibility for Adt {
1130 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1132 Adt::Struct(it) => it.visibility(db),
1133 Adt::Union(it) => it.visibility(db),
1134 Adt::Enum(it) => it.visibility(db),
1139 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1140 pub enum VariantDef {
1145 impl_from!(Struct, Union, Variant for VariantDef);
1148 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
1150 VariantDef::Struct(it) => it.fields(db),
1151 VariantDef::Union(it) => it.fields(db),
1152 VariantDef::Variant(it) => it.fields(db),
1156 pub fn module(self, db: &dyn HirDatabase) -> Module {
1158 VariantDef::Struct(it) => it.module(db),
1159 VariantDef::Union(it) => it.module(db),
1160 VariantDef::Variant(it) => it.module(db),
1164 pub fn name(&self, db: &dyn HirDatabase) -> Name {
1166 VariantDef::Struct(s) => s.name(db),
1167 VariantDef::Union(u) => u.name(db),
1168 VariantDef::Variant(e) => e.name(db),
1172 pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
1174 VariantDef::Struct(it) => it.variant_data(db),
1175 VariantDef::Union(it) => it.variant_data(db),
1176 VariantDef::Variant(it) => it.variant_data(db),
1181 /// The defs which have a body.
1182 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1183 pub enum DefWithBody {
1189 impl_from!(Function, Const, Static, Variant for DefWithBody);
1192 pub fn module(self, db: &dyn HirDatabase) -> Module {
1194 DefWithBody::Const(c) => c.module(db),
1195 DefWithBody::Function(f) => f.module(db),
1196 DefWithBody::Static(s) => s.module(db),
1197 DefWithBody::Variant(v) => v.module(db),
1201 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
1203 DefWithBody::Function(f) => Some(f.name(db)),
1204 DefWithBody::Static(s) => Some(s.name(db)),
1205 DefWithBody::Const(c) => c.name(db),
1206 DefWithBody::Variant(v) => Some(v.name(db)),
1210 /// Returns the type this def's body has to evaluate to.
1211 pub fn body_type(self, db: &dyn HirDatabase) -> Type {
1213 DefWithBody::Function(it) => it.ret_type(db),
1214 DefWithBody::Static(it) => it.ty(db),
1215 DefWithBody::Const(it) => it.ty(db),
1216 DefWithBody::Variant(it) => it.parent.variant_body_ty(db),
1220 fn id(&self) -> DefWithBodyId {
1222 DefWithBody::Function(it) => it.id.into(),
1223 DefWithBody::Static(it) => it.id.into(),
1224 DefWithBody::Const(it) => it.id.into(),
1225 DefWithBody::Variant(it) => it.into(),
1229 /// A textual representation of the HIR of this def's body for debugging purposes.
1230 pub fn debug_hir(self, db: &dyn HirDatabase) -> String {
1231 let body = db.body(self.id());
1232 body.pretty_print(db.upcast(), self.id())
1235 pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
1236 let krate = self.module(db).id.krate();
1238 let (body, source_map) = db.body_with_source_map(self.into());
1240 for (_, def_map) in body.blocks(db.upcast()) {
1241 for diag in def_map.diagnostics() {
1242 emit_def_diagnostic(db, acc, diag);
1246 for diag in source_map.diagnostics() {
1248 BodyDiagnostic::InactiveCode { node, cfg, opts } => acc.push(
1249 InactiveCode { node: node.clone(), cfg: cfg.clone(), opts: opts.clone() }
1252 BodyDiagnostic::MacroError { node, message } => acc.push(
1254 node: node.clone().map(|it| it.into()),
1255 precise_location: None,
1256 message: message.to_string(),
1260 BodyDiagnostic::UnresolvedProcMacro { node, krate } => acc.push(
1261 UnresolvedProcMacro {
1262 node: node.clone().map(|it| it.into()),
1263 precise_location: None,
1265 kind: MacroKind::ProcMacro,
1270 BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push(
1271 UnresolvedMacroCall {
1272 macro_call: node.clone().map(|ast_ptr| ast_ptr.into()),
1273 precise_location: None,
1282 let infer = db.infer(self.into());
1283 let source_map = Lazy::new(|| db.body_with_source_map(self.into()).1);
1284 for d in &infer.diagnostics {
1286 hir_ty::InferenceDiagnostic::NoSuchField { expr } => {
1287 let field = source_map.field_syntax(*expr);
1288 acc.push(NoSuchField { field }.into())
1290 &hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break } => {
1291 let expr = source_map
1293 .expect("break outside of loop in synthetic syntax");
1294 acc.push(BreakOutsideOfLoop { expr, is_break }.into())
1296 hir_ty::InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => {
1297 match source_map.expr_syntax(*call_expr) {
1298 Ok(source_ptr) => acc.push(
1299 MismatchedArgCount {
1300 call_expr: source_ptr,
1301 expected: *expected,
1306 Err(SyntheticSyntax) => (),
1311 for (expr, mismatch) in infer.expr_type_mismatches() {
1312 let expr = match source_map.expr_syntax(expr) {
1314 Err(SyntheticSyntax) => continue,
1319 expected: Type::new(db, DefWithBodyId::from(self), mismatch.expected.clone()),
1320 actual: Type::new(db, DefWithBodyId::from(self), mismatch.actual.clone()),
1326 for expr in hir_ty::diagnostics::missing_unsafe(db, self.into()) {
1327 match source_map.expr_syntax(expr) {
1328 Ok(expr) => acc.push(MissingUnsafe { expr }.into()),
1329 Err(SyntheticSyntax) => {
1330 // FIXME: Here and eslwhere in this file, the `expr` was
1331 // desugared, report or assert that this doesn't happen.
1336 for diagnostic in BodyValidationDiagnostic::collect(db, self.into()) {
1338 BodyValidationDiagnostic::RecordMissingFields {
1343 let variant_data = variant.variant_data(db.upcast());
1344 let missed_fields = missed_fields
1346 .map(|idx| variant_data.fields()[idx].name.clone())
1350 Either::Left(record_expr) => match source_map.expr_syntax(record_expr) {
1352 let root = source_ptr.file_syntax(db.upcast());
1353 if let ast::Expr::RecordExpr(record_expr) =
1354 &source_ptr.value.to_node(&root)
1356 if record_expr.record_expr_field_list().is_some() {
1359 file: source_ptr.file_id,
1360 field_list_parent: Either::Left(AstPtr::new(
1363 field_list_parent_path: record_expr
1365 .map(|path| AstPtr::new(&path)),
1373 Err(SyntheticSyntax) => (),
1375 Either::Right(record_pat) => match source_map.pat_syntax(record_pat) {
1377 if let Some(expr) = source_ptr.value.as_ref().left() {
1378 let root = source_ptr.file_syntax(db.upcast());
1379 if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) {
1380 if record_pat.record_pat_field_list().is_some() {
1383 file: source_ptr.file_id,
1384 field_list_parent: Either::Right(AstPtr::new(
1387 field_list_parent_path: record_pat
1389 .map(|path| AstPtr::new(&path)),
1398 Err(SyntheticSyntax) => (),
1402 BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap { method_call_expr } => {
1403 if let Ok(next_source_ptr) = source_map.expr_syntax(method_call_expr) {
1405 ReplaceFilterMapNextWithFindMap {
1406 file: next_source_ptr.file_id,
1407 next_expr: next_source_ptr.value,
1413 BodyValidationDiagnostic::MissingMatchArms { match_expr, uncovered_patterns } => {
1414 match source_map.expr_syntax(match_expr) {
1416 let root = source_ptr.file_syntax(db.upcast());
1417 if let ast::Expr::MatchExpr(match_expr) =
1418 &source_ptr.value.to_node(&root)
1420 if let Some(match_expr) = match_expr.expr() {
1423 file: source_ptr.file_id,
1424 match_expr: AstPtr::new(&match_expr),
1432 Err(SyntheticSyntax) => (),
1438 let def: ModuleDef = match self {
1439 DefWithBody::Function(it) => it.into(),
1440 DefWithBody::Static(it) => it.into(),
1441 DefWithBody::Const(it) => it.into(),
1442 DefWithBody::Variant(it) => it.into(),
1444 for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) {
1445 acc.push(diag.into())
1450 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1451 pub struct Function {
1452 pub(crate) id: FunctionId,
1456 pub fn module(self, db: &dyn HirDatabase) -> Module {
1457 self.id.lookup(db.upcast()).module(db.upcast()).into()
1460 pub fn name(self, db: &dyn HirDatabase) -> Name {
1461 db.function_data(self.id).name.clone()
1464 /// Get this function's return type
1465 pub fn ret_type(self, db: &dyn HirDatabase) -> Type {
1466 let resolver = self.id.resolver(db.upcast());
1467 let substs = TyBuilder::placeholder_subst(db, self.id);
1468 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
1469 let ty = callable_sig.ret().clone();
1470 Type::new_with_resolver_inner(db, &resolver, ty)
1473 pub fn async_ret_type(self, db: &dyn HirDatabase) -> Option<Type> {
1474 if !self.is_async(db) {
1477 let resolver = self.id.resolver(db.upcast());
1478 let substs = TyBuilder::placeholder_subst(db, self.id);
1479 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
1480 let ret_ty = callable_sig.ret().clone();
1481 for pred in ret_ty.impl_trait_bounds(db).into_iter().flatten() {
1482 if let WhereClause::AliasEq(output_eq) = pred.into_value_and_skipped_binders().0 {
1483 return Type::new_with_resolver_inner(db, &resolver, output_eq.ty).into();
1486 never!("Async fn ret_type should be impl Future");
1490 pub fn has_self_param(self, db: &dyn HirDatabase) -> bool {
1491 db.function_data(self.id).has_self_param()
1494 pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
1495 self.has_self_param(db).then(|| SelfParam { func: self.id })
1498 pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param> {
1499 let environment = db.trait_environment(self.id.into());
1500 let substs = TyBuilder::placeholder_subst(db, self.id);
1501 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
1507 let ty = Type { env: environment.clone(), ty: ty.clone() };
1508 Param { func: self, ty, idx }
1513 pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> {
1514 if self.self_param(db).is_none() {
1517 Some(self.params_without_self(db))
1520 pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec<Param> {
1521 let environment = db.trait_environment(self.id.into());
1522 let substs = TyBuilder::placeholder_subst(db, self.id);
1523 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
1524 let skip = if db.function_data(self.id).has_self_param() { 1 } else { 0 };
1531 let ty = Type { env: environment.clone(), ty: ty.clone() };
1532 Param { func: self, ty, idx }
1537 pub fn is_const(self, db: &dyn HirDatabase) -> bool {
1538 db.function_data(self.id).has_const_kw()
1541 pub fn is_async(self, db: &dyn HirDatabase) -> bool {
1542 db.function_data(self.id).has_async_kw()
1545 pub fn is_unsafe_to_call(self, db: &dyn HirDatabase) -> bool {
1546 hir_ty::is_fn_unsafe_to_call(db, self.id)
1549 /// Whether this function declaration has a definition.
1551 /// This is false in the case of required (not provided) trait methods.
1552 pub fn has_body(self, db: &dyn HirDatabase) -> bool {
1553 db.function_data(self.id).has_body()
1556 pub fn as_proc_macro(self, db: &dyn HirDatabase) -> Option<Macro> {
1557 let function_data = db.function_data(self.id);
1558 let attrs = &function_data.attrs;
1559 // FIXME: Store this in FunctionData flags?
1560 if !(attrs.is_proc_macro()
1561 || attrs.is_proc_macro_attribute()
1562 || attrs.is_proc_macro_derive())
1566 let loc = self.id.lookup(db.upcast());
1567 let def_map = db.crate_def_map(loc.krate(db).into());
1568 def_map.fn_as_proc_macro(self.id).map(|id| Macro { id: id.into() })
1572 // Note: logically, this belongs to `hir_ty`, but we are not using it there yet.
1573 #[derive(Clone, Copy, PartialEq, Eq)]
1580 impl From<hir_ty::Mutability> for Access {
1581 fn from(mutability: hir_ty::Mutability) -> Access {
1583 hir_ty::Mutability::Not => Access::Shared,
1584 hir_ty::Mutability::Mut => Access::Exclusive,
1589 #[derive(Clone, Debug)]
1592 /// The index in parameter list, including self parameter.
1598 pub fn ty(&self) -> &Type {
1602 pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
1603 db.function_data(self.func.id).params[self.idx].0.clone()
1606 pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
1607 let parent = DefWithBodyId::FunctionId(self.func.into());
1608 let body = db.body(parent);
1609 let pat_id = body.params[self.idx];
1610 if let Pat::Bind { .. } = &body[pat_id] {
1611 Some(Local { parent, pat_id: body.params[self.idx] })
1617 pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
1618 self.source(db).and_then(|p| p.value.pat())
1621 pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::Param>> {
1622 let InFile { file_id, value } = self.func.source(db)?;
1623 let params = value.param_list()?;
1624 if params.self_param().is_some() {
1625 params.params().nth(self.idx.checked_sub(1)?)
1627 params.params().nth(self.idx)
1629 .map(|value| InFile { file_id, value })
1633 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1634 pub struct SelfParam {
1639 pub fn access(self, db: &dyn HirDatabase) -> Access {
1640 let func_data = db.function_data(self.func);
1644 .map(|(_, param)| match &**param {
1645 TypeRef::Reference(.., mutability) => match mutability {
1646 hir_def::type_ref::Mutability::Shared => Access::Shared,
1647 hir_def::type_ref::Mutability::Mut => Access::Exclusive,
1651 .unwrap_or(Access::Owned)
1654 pub fn display(self, db: &dyn HirDatabase) -> &'static str {
1655 match self.access(db) {
1656 Access::Shared => "&self",
1657 Access::Exclusive => "&mut self",
1658 Access::Owned => "self",
1662 pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::SelfParam>> {
1663 let InFile { file_id, value } = Function::from(self.func).source(db)?;
1666 .and_then(|params| params.self_param())
1667 .map(|value| InFile { file_id, value })
1670 pub fn ty(&self, db: &dyn HirDatabase) -> Type {
1671 let substs = TyBuilder::placeholder_subst(db, self.func);
1673 db.callable_item_signature(self.func.into()).substitute(Interner, &substs);
1674 let environment = db.trait_environment(self.func.into());
1675 let ty = callable_sig.params()[0].clone();
1676 Type { env: environment, ty }
1680 impl HasVisibility for Function {
1681 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1682 db.function_visibility(self.id)
1686 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1688 pub(crate) id: ConstId,
1692 pub fn module(self, db: &dyn HirDatabase) -> Module {
1693 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
1696 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
1697 db.const_data(self.id).name.clone()
1700 pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
1701 self.source(db)?.value.body()
1704 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1705 let data = db.const_data(self.id);
1706 let resolver = self.id.resolver(db.upcast());
1707 let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
1708 let ty = ctx.lower_ty(&data.type_ref);
1709 Type::new_with_resolver_inner(db, &resolver, ty)
1712 pub fn eval(self, db: &dyn HirDatabase) -> Result<ComputedExpr, ConstEvalError> {
1713 db.const_eval(self.id)
1717 impl HasVisibility for Const {
1718 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1719 db.const_visibility(self.id)
1723 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1725 pub(crate) id: StaticId,
1729 pub fn module(self, db: &dyn HirDatabase) -> Module {
1730 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
1733 pub fn name(self, db: &dyn HirDatabase) -> Name {
1734 db.static_data(self.id).name.clone()
1737 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
1738 db.static_data(self.id).mutable
1741 pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
1742 self.source(db)?.value.body()
1745 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1746 let data = db.static_data(self.id);
1747 let resolver = self.id.resolver(db.upcast());
1748 let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
1749 let ty = ctx.lower_ty(&data.type_ref);
1750 Type::new_with_resolver_inner(db, &resolver, ty)
1754 impl HasVisibility for Static {
1755 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1756 db.static_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1760 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1762 pub(crate) id: TraitId,
1766 pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option<Trait> {
1767 db.lang_item(krate.into(), name.to_smol_str())
1768 .and_then(LangItemTarget::as_trait)
1772 pub fn module(self, db: &dyn HirDatabase) -> Module {
1773 Module { id: self.id.lookup(db.upcast()).container }
1776 pub fn name(self, db: &dyn HirDatabase) -> Name {
1777 db.trait_data(self.id).name.clone()
1780 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
1781 db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
1784 pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
1785 let traits = all_super_traits(db.upcast(), self.into());
1786 traits.iter().flat_map(|tr| Trait::from(*tr).items(db)).collect()
1789 pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
1790 db.trait_data(self.id).is_auto
1793 pub fn is_unsafe(&self, db: &dyn HirDatabase) -> bool {
1794 db.trait_data(self.id).is_unsafe
1797 pub fn type_or_const_param_count(
1799 db: &dyn HirDatabase,
1800 count_required_only: bool,
1802 db.generic_params(GenericDefId::from(self.id))
1805 .filter(|(_, ty)| match ty {
1806 TypeOrConstParamData::TypeParamData(ty)
1807 if ty.provenance != TypeParamProvenance::TypeParamList =>
1813 .filter(|(_, ty)| !count_required_only || !ty.has_default())
1818 impl HasVisibility for Trait {
1819 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1820 db.trait_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1824 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1825 pub struct TypeAlias {
1826 pub(crate) id: TypeAliasId,
1830 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
1831 let subst = db.generic_defaults(self.id.into());
1832 subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
1833 GenericArgData::Ty(x) => x.is_unknown(),
1838 pub fn module(self, db: &dyn HirDatabase) -> Module {
1839 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
1842 pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> {
1843 db.type_alias_data(self.id).type_ref.as_deref().cloned()
1846 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1847 Type::from_def(db, self.id)
1850 pub fn name(self, db: &dyn HirDatabase) -> Name {
1851 db.type_alias_data(self.id).name.clone()
1855 impl HasVisibility for TypeAlias {
1856 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1857 let function_data = db.type_alias_data(self.id);
1858 let visibility = &function_data.visibility;
1859 visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1863 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1864 pub struct BuiltinType {
1865 pub(crate) inner: hir_def::builtin_type::BuiltinType,
1869 pub fn str() -> BuiltinType {
1870 BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
1873 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1874 Type::new_for_crate(db.crate_graph().iter().next().unwrap(), TyBuilder::builtin(self.inner))
1877 pub fn name(self) -> Name {
1878 self.inner.as_name()
1881 pub fn is_int(&self) -> bool {
1882 matches!(self.inner, hir_def::builtin_type::BuiltinType::Int(_))
1885 pub fn is_uint(&self) -> bool {
1886 matches!(self.inner, hir_def::builtin_type::BuiltinType::Uint(_))
1889 pub fn is_float(&self) -> bool {
1890 matches!(self.inner, hir_def::builtin_type::BuiltinType::Float(_))
1893 pub fn is_char(&self) -> bool {
1894 matches!(self.inner, hir_def::builtin_type::BuiltinType::Char)
1897 pub fn is_bool(&self) -> bool {
1898 matches!(self.inner, hir_def::builtin_type::BuiltinType::Bool)
1901 pub fn is_str(&self) -> bool {
1902 matches!(self.inner, hir_def::builtin_type::BuiltinType::Str)
1906 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1907 pub enum MacroKind {
1908 /// `macro_rules!` or Macros 2.0 macro.
1910 /// A built-in or custom derive.
1912 /// A built-in function-like macro.
1914 /// A procedural attribute macro.
1916 /// A function-like procedural macro.
1920 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1922 pub(crate) id: MacroId,
1926 pub fn module(self, db: &dyn HirDatabase) -> Module {
1927 Module { id: self.id.module(db.upcast()) }
1930 pub fn name(self, db: &dyn HirDatabase) -> Name {
1932 MacroId::Macro2Id(id) => db.macro2_data(id).name.clone(),
1933 MacroId::MacroRulesId(id) => db.macro_rules_data(id).name.clone(),
1934 MacroId::ProcMacroId(id) => db.proc_macro_data(id).name.clone(),
1938 pub fn is_macro_export(self, db: &dyn HirDatabase) -> bool {
1939 matches!(self.id, MacroId::MacroRulesId(id) if db.macro_rules_data(id).macro_export)
1942 pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind {
1944 MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander {
1945 MacroExpander::Declarative => MacroKind::Declarative,
1946 MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
1947 MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
1948 MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
1950 MacroId::MacroRulesId(it) => match it.lookup(db.upcast()).expander {
1951 MacroExpander::Declarative => MacroKind::Declarative,
1952 MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
1953 MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
1954 MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
1956 MacroId::ProcMacroId(it) => match it.lookup(db.upcast()).kind {
1957 ProcMacroKind::CustomDerive => MacroKind::Derive,
1958 ProcMacroKind::FuncLike => MacroKind::ProcMacro,
1959 ProcMacroKind::Attr => MacroKind::Attr,
1964 pub fn is_fn_like(&self, db: &dyn HirDatabase) -> bool {
1965 match self.kind(db) {
1966 MacroKind::Declarative | MacroKind::BuiltIn | MacroKind::ProcMacro => true,
1967 MacroKind::Attr | MacroKind::Derive => false,
1971 pub fn is_builtin_derive(&self, db: &dyn HirDatabase) -> bool {
1973 MacroId::Macro2Id(it) => {
1974 matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInDerive(_))
1976 MacroId::MacroRulesId(it) => {
1977 matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInDerive(_))
1979 MacroId::ProcMacroId(_) => false,
1983 pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
1984 matches!(self.kind(db), MacroKind::Attr)
1987 pub fn is_derive(&self, db: &dyn HirDatabase) -> bool {
1988 matches!(self.kind(db), MacroKind::Derive)
1992 impl HasVisibility for Macro {
1993 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1995 MacroId::Macro2Id(id) => {
1996 let data = db.macro2_data(id);
1997 let visibility = &data.visibility;
1998 visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
2000 MacroId::MacroRulesId(_) => Visibility::Public,
2001 MacroId::ProcMacroId(_) => Visibility::Public,
2006 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
2013 impl From<Macro> for ItemInNs {
2014 fn from(it: Macro) -> Self {
2019 impl From<ModuleDef> for ItemInNs {
2020 fn from(module_def: ModuleDef) -> Self {
2022 ModuleDef::Static(_) | ModuleDef::Const(_) | ModuleDef::Function(_) => {
2023 ItemInNs::Values(module_def)
2025 _ => ItemInNs::Types(module_def),
2031 pub fn as_module_def(self) -> Option<ModuleDef> {
2033 ItemInNs::Types(id) | ItemInNs::Values(id) => Some(id),
2034 ItemInNs::Macros(_) => None,
2038 /// Returns the crate defining this item (or `None` if `self` is built-in).
2039 pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
2041 ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate()),
2042 ItemInNs::Macros(id) => Some(id.module(db).krate()),
2046 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
2048 ItemInNs::Types(it) | ItemInNs::Values(it) => it.attrs(db),
2049 ItemInNs::Macros(it) => Some(it.attrs(db)),
2054 /// Invariant: `inner.as_assoc_item(db).is_some()`
2055 /// We do not actively enforce this invariant.
2056 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2057 pub enum AssocItem {
2060 TypeAlias(TypeAlias),
2063 pub enum AssocItemContainer {
2067 pub trait AsAssocItem {
2068 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>;
2071 impl AsAssocItem for Function {
2072 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2073 as_assoc_item(db, AssocItem::Function, self.id)
2076 impl AsAssocItem for Const {
2077 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2078 as_assoc_item(db, AssocItem::Const, self.id)
2081 impl AsAssocItem for TypeAlias {
2082 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2083 as_assoc_item(db, AssocItem::TypeAlias, self.id)
2086 impl AsAssocItem for ModuleDef {
2087 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2089 ModuleDef::Function(it) => it.as_assoc_item(db),
2090 ModuleDef::Const(it) => it.as_assoc_item(db),
2091 ModuleDef::TypeAlias(it) => it.as_assoc_item(db),
2096 fn as_assoc_item<ID, DEF, CTOR, AST>(db: &dyn HirDatabase, ctor: CTOR, id: ID) -> Option<AssocItem>
2098 ID: Lookup<Data = AssocItemLoc<AST>>,
2100 CTOR: FnOnce(DEF) -> AssocItem,
2103 match id.lookup(db.upcast()).container {
2104 ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
2105 ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
2110 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
2112 AssocItem::Function(it) => Some(it.name(db)),
2113 AssocItem::Const(it) => it.name(db),
2114 AssocItem::TypeAlias(it) => Some(it.name(db)),
2117 pub fn module(self, db: &dyn HirDatabase) -> Module {
2119 AssocItem::Function(f) => f.module(db),
2120 AssocItem::Const(c) => c.module(db),
2121 AssocItem::TypeAlias(t) => t.module(db),
2124 pub fn container(self, db: &dyn HirDatabase) -> AssocItemContainer {
2125 let container = match self {
2126 AssocItem::Function(it) => it.id.lookup(db.upcast()).container,
2127 AssocItem::Const(it) => it.id.lookup(db.upcast()).container,
2128 AssocItem::TypeAlias(it) => it.id.lookup(db.upcast()).container,
2131 ItemContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()),
2132 ItemContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()),
2133 ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
2134 panic!("invalid AssocItem")
2139 pub fn containing_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
2140 match self.container(db) {
2141 AssocItemContainer::Trait(t) => Some(t),
2146 pub fn containing_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait> {
2147 match self.container(db) {
2148 AssocItemContainer::Impl(i) => i.trait_(db),
2153 pub fn containing_trait_or_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait> {
2154 match self.container(db) {
2155 AssocItemContainer::Trait(t) => Some(t),
2156 AssocItemContainer::Impl(i) => i.trait_(db),
2161 impl HasVisibility for AssocItem {
2162 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2164 AssocItem::Function(f) => f.visibility(db),
2165 AssocItem::Const(c) => c.visibility(db),
2166 AssocItem::TypeAlias(t) => t.visibility(db),
2171 impl From<AssocItem> for ModuleDef {
2172 fn from(assoc: AssocItem) -> Self {
2174 AssocItem::Function(it) => ModuleDef::Function(it),
2175 AssocItem::Const(it) => ModuleDef::Const(it),
2176 AssocItem::TypeAlias(it) => ModuleDef::TypeAlias(it),
2181 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
2182 pub enum GenericDef {
2186 TypeAlias(TypeAlias),
2188 // enum variants cannot have generics themselves, but their parent enums
2189 // can, and this makes some code easier to write
2191 // consts can have type parameters from their parents (i.e. associated consts of traits)
2196 Adt(Struct, Enum, Union),
2206 pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
2207 let generics = db.generic_params(self.into());
2208 let ty_params = generics.type_or_consts.iter().map(|(local_id, _)| {
2209 let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } };
2210 match toc.split(db) {
2211 Either::Left(x) => GenericParam::ConstParam(x),
2212 Either::Right(x) => GenericParam::TypeParam(x),
2215 let lt_params = generics
2218 .map(|(local_id, _)| LifetimeParam {
2219 id: LifetimeParamId { parent: self.into(), local_id },
2221 .map(GenericParam::LifetimeParam);
2222 lt_params.chain(ty_params).collect()
2225 pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
2226 let generics = db.generic_params(self.into());
2230 .map(|(local_id, _)| TypeOrConstParam {
2231 id: TypeOrConstParamId { parent: self.into(), local_id },
2237 /// A single local definition.
2239 /// If the definition of this is part of a "MultiLocal", that is a local that has multiple declarations due to or-patterns
2240 /// then this only references a single one of those.
2241 /// To retrieve the other locals you should use [`Local::associated_locals`]
2242 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2244 pub(crate) parent: DefWithBodyId,
2245 pub(crate) pat_id: PatId,
2249 pub fn is_param(self, db: &dyn HirDatabase) -> bool {
2250 let src = self.source(db);
2252 Either::Left(pat) => pat
2255 .map(|it| it.kind())
2256 .take_while(|&kind| ast::Pat::can_cast(kind) || ast::Param::can_cast(kind))
2257 .any(ast::Param::can_cast),
2258 Either::Right(_) => true,
2262 pub fn as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
2264 DefWithBodyId::FunctionId(func) if self.is_self(db) => Some(SelfParam { func }),
2269 pub fn name(self, db: &dyn HirDatabase) -> Name {
2270 let body = db.body(self.parent);
2271 match &body[self.pat_id] {
2272 Pat::Bind { name, .. } => name.clone(),
2274 stdx::never!("hir::Local is missing a name!");
2280 pub fn is_self(self, db: &dyn HirDatabase) -> bool {
2281 self.name(db) == name![self]
2284 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
2285 let body = db.body(self.parent);
2286 matches!(&body[self.pat_id], Pat::Bind { mode: BindingAnnotation::Mutable, .. })
2289 pub fn is_ref(self, db: &dyn HirDatabase) -> bool {
2290 let body = db.body(self.parent);
2293 Pat::Bind { mode: BindingAnnotation::Ref | BindingAnnotation::RefMut, .. }
2297 pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
2301 pub fn module(self, db: &dyn HirDatabase) -> Module {
2302 self.parent(db).module(db)
2305 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2306 let def = self.parent;
2307 let infer = db.infer(def);
2308 let ty = infer[self.pat_id].clone();
2309 Type::new(db, def, ty)
2312 pub fn associated_locals(self, db: &dyn HirDatabase) -> Box<[Local]> {
2313 let body = db.body(self.parent);
2314 body.ident_patterns_for(&self.pat_id)
2316 .map(|&pat_id| Local { parent: self.parent, pat_id })
2320 /// If this local is part of a multi-local, retrieve the representative local.
2321 /// That is the local that references are being resolved to.
2322 pub fn representative(self, db: &dyn HirDatabase) -> Local {
2323 let body = db.body(self.parent);
2324 Local { pat_id: body.pattern_representative(self.pat_id), ..self }
2327 pub fn source(self, db: &dyn HirDatabase) -> InFile<Either<ast::IdentPat, ast::SelfParam>> {
2328 let (_body, source_map) = db.body_with_source_map(self.parent);
2329 let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm...
2330 let root = src.file_syntax(db.upcast());
2331 src.map(|ast| match ast {
2332 // Suspicious unwrap
2333 Either::Left(it) => Either::Left(it.cast().unwrap().to_node(&root)),
2334 Either::Right(it) => Either::Right(it.to_node(&root)),
2339 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2340 pub struct DeriveHelper {
2341 pub(crate) derive: MacroId,
2342 pub(crate) idx: usize,
2346 pub fn derive(&self) -> Macro {
2347 Macro { id: self.derive.into() }
2350 pub fn name(&self, db: &dyn HirDatabase) -> Name {
2352 MacroId::Macro2Id(_) => None,
2353 MacroId::MacroRulesId(_) => None,
2354 MacroId::ProcMacroId(proc_macro) => db
2355 .proc_macro_data(proc_macro)
2358 .and_then(|it| it.get(self.idx))
2361 .unwrap_or_else(|| Name::missing())
2365 // FIXME: Wrong name? This is could also be a registered attribute
2366 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2367 pub struct BuiltinAttr {
2368 krate: Option<CrateId>,
2373 // FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs?
2374 pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
2375 if let builtin @ Some(_) = Self::builtin(name) {
2378 let idx = db.crate_def_map(krate.id).registered_attrs().iter().position(|it| it == name)?;
2379 Some(BuiltinAttr { krate: Some(krate.id), idx })
2382 fn builtin(name: &str) -> Option<Self> {
2383 hir_def::builtin_attr::INERT_ATTRIBUTES
2385 .position(|tool| tool.name == name)
2386 .map(|idx| BuiltinAttr { krate: None, idx })
2389 pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
2390 // FIXME: Return a `Name` here
2392 Some(krate) => db.crate_def_map(krate).registered_attrs()[self.idx].clone(),
2393 None => SmolStr::new(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx].name),
2397 pub fn template(&self, _: &dyn HirDatabase) -> Option<AttributeTemplate> {
2400 None => Some(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx].template),
2405 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2406 pub struct ToolModule {
2407 krate: Option<CrateId>,
2412 // FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs?
2413 pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
2414 if let builtin @ Some(_) = Self::builtin(name) {
2417 let idx = db.crate_def_map(krate.id).registered_tools().iter().position(|it| it == name)?;
2418 Some(ToolModule { krate: Some(krate.id), idx })
2421 fn builtin(name: &str) -> Option<Self> {
2422 hir_def::builtin_attr::TOOL_MODULES
2424 .position(|&tool| tool == name)
2425 .map(|idx| ToolModule { krate: None, idx })
2428 pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
2429 // FIXME: Return a `Name` here
2431 Some(krate) => db.crate_def_map(krate).registered_tools()[self.idx].clone(),
2432 None => SmolStr::new(hir_def::builtin_attr::TOOL_MODULES[self.idx]),
2437 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2439 pub(crate) parent: DefWithBodyId,
2440 pub(crate) label_id: LabelId,
2444 pub fn module(self, db: &dyn HirDatabase) -> Module {
2445 self.parent(db).module(db)
2448 pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
2452 pub fn name(self, db: &dyn HirDatabase) -> Name {
2453 let body = db.body(self.parent);
2454 body[self.label_id].name.clone()
2457 pub fn source(self, db: &dyn HirDatabase) -> InFile<ast::Label> {
2458 let (_body, source_map) = db.body_with_source_map(self.parent);
2459 let src = source_map.label_syntax(self.label_id);
2460 let root = src.file_syntax(db.upcast());
2461 src.map(|ast| ast.to_node(&root))
2465 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2466 pub enum GenericParam {
2467 TypeParam(TypeParam),
2468 ConstParam(ConstParam),
2469 LifetimeParam(LifetimeParam),
2471 impl_from!(TypeParam, ConstParam, LifetimeParam for GenericParam);
2474 pub fn module(self, db: &dyn HirDatabase) -> Module {
2476 GenericParam::TypeParam(it) => it.module(db),
2477 GenericParam::ConstParam(it) => it.module(db),
2478 GenericParam::LifetimeParam(it) => it.module(db),
2482 pub fn name(self, db: &dyn HirDatabase) -> Name {
2484 GenericParam::TypeParam(it) => it.name(db),
2485 GenericParam::ConstParam(it) => it.name(db),
2486 GenericParam::LifetimeParam(it) => it.name(db),
2491 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2492 pub struct TypeParam {
2493 pub(crate) id: TypeParamId,
2497 pub fn merge(self) -> TypeOrConstParam {
2498 TypeOrConstParam { id: self.id.into() }
2501 pub fn name(self, db: &dyn HirDatabase) -> Name {
2502 self.merge().name(db)
2505 pub fn module(self, db: &dyn HirDatabase) -> Module {
2506 self.id.parent().module(db.upcast()).into()
2509 /// Is this type parameter implicitly introduced (eg. `Self` in a trait or an `impl Trait`
2511 pub fn is_implicit(self, db: &dyn HirDatabase) -> bool {
2512 let params = db.generic_params(self.id.parent());
2513 let data = ¶ms.type_or_consts[self.id.local_id()];
2514 match data.type_param().unwrap().provenance {
2515 hir_def::generics::TypeParamProvenance::TypeParamList => false,
2516 hir_def::generics::TypeParamProvenance::TraitSelf
2517 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => true,
2521 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2522 let resolver = self.id.parent().resolver(db.upcast());
2524 TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id.into())).intern(Interner);
2525 Type::new_with_resolver_inner(db, &resolver, ty)
2528 /// FIXME: this only lists trait bounds from the item defining the type
2529 /// parameter, not additional bounds that might be added e.g. by a method if
2530 /// the parameter comes from an impl!
2531 pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
2532 db.generic_predicates_for_param(self.id.parent(), self.id.into(), None)
2534 .filter_map(|pred| match &pred.skip_binders().skip_binders() {
2535 hir_ty::WhereClause::Implemented(trait_ref) => {
2536 Some(Trait::from(trait_ref.hir_trait_id()))
2543 pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
2544 let params = db.generic_defaults(self.id.parent());
2545 let local_idx = hir_ty::param_idx(db, self.id.into())?;
2546 let resolver = self.id.parent().resolver(db.upcast());
2547 let ty = params.get(local_idx)?.clone();
2548 let subst = TyBuilder::placeholder_subst(db, self.id.parent());
2549 let ty = ty.substitute(Interner, &subst);
2550 match ty.data(Interner) {
2551 GenericArgData::Ty(x) => Some(Type::new_with_resolver_inner(db, &resolver, x.clone())),
2557 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2558 pub struct LifetimeParam {
2559 pub(crate) id: LifetimeParamId,
2562 impl LifetimeParam {
2563 pub fn name(self, db: &dyn HirDatabase) -> Name {
2564 let params = db.generic_params(self.id.parent);
2565 params.lifetimes[self.id.local_id].name.clone()
2568 pub fn module(self, db: &dyn HirDatabase) -> Module {
2569 self.id.parent.module(db.upcast()).into()
2572 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
2573 self.id.parent.into()
2577 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2578 pub struct ConstParam {
2579 pub(crate) id: ConstParamId,
2583 pub fn merge(self) -> TypeOrConstParam {
2584 TypeOrConstParam { id: self.id.into() }
2587 pub fn name(self, db: &dyn HirDatabase) -> Name {
2588 let params = db.generic_params(self.id.parent());
2589 match params.type_or_consts[self.id.local_id()].name() {
2590 Some(x) => x.clone(),
2598 pub fn module(self, db: &dyn HirDatabase) -> Module {
2599 self.id.parent().module(db.upcast()).into()
2602 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
2603 self.id.parent().into()
2606 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2607 Type::new(db, self.id.parent(), db.const_param_ty(self.id))
2611 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2612 pub struct TypeOrConstParam {
2613 pub(crate) id: TypeOrConstParamId,
2616 impl TypeOrConstParam {
2617 pub fn name(self, db: &dyn HirDatabase) -> Name {
2618 let params = db.generic_params(self.id.parent);
2619 match params.type_or_consts[self.id.local_id].name() {
2620 Some(n) => n.clone(),
2621 _ => Name::missing(),
2625 pub fn module(self, db: &dyn HirDatabase) -> Module {
2626 self.id.parent.module(db.upcast()).into()
2629 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
2630 self.id.parent.into()
2633 pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
2634 let params = db.generic_params(self.id.parent);
2635 match ¶ms.type_or_consts[self.id.local_id] {
2636 hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
2637 Either::Right(TypeParam { id: TypeParamId::from_unchecked(self.id) })
2639 hir_def::generics::TypeOrConstParamData::ConstParamData(_) => {
2640 Either::Left(ConstParam { id: ConstParamId::from_unchecked(self.id) })
2645 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2646 match self.split(db) {
2647 Either::Left(x) => x.ty(db),
2648 Either::Right(x) => x.ty(db),
2653 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2655 pub(crate) id: ImplId,
2659 pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<Impl> {
2660 let inherent = db.inherent_impls_in_crate(krate.id);
2661 let trait_ = db.trait_impls_in_crate(krate.id);
2663 inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect()
2666 pub fn all_for_type(db: &dyn HirDatabase, Type { ty, env }: Type) -> Vec<Impl> {
2667 let def_crates = match method_resolution::def_crates(db, &ty, env.krate) {
2668 Some(def_crates) => def_crates,
2669 None => return Vec::new(),
2672 let filter = |impl_def: &Impl| {
2673 let self_ty = impl_def.self_ty(db);
2674 let rref = self_ty.remove_ref();
2675 ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
2678 let fp = TyFingerprint::for_inherent_impl(&ty);
2681 None => return Vec::new(),
2684 let mut all = Vec::new();
2685 def_crates.iter().for_each(|&id| {
2687 db.inherent_impls_in_crate(id)
2695 for id in def_crates
2697 .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
2698 .map(|Crate { id }| id)
2699 .chain(def_crates.iter().copied())
2703 db.trait_impls_in_crate(id)
2704 .for_self_ty_without_blanket_impls(fp)
2712 pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
2713 let krate = trait_.module(db).krate();
2714 let mut all = Vec::new();
2715 for Crate { id } in krate.transitive_reverse_dependencies(db).into_iter() {
2716 let impls = db.trait_impls_in_crate(id);
2717 all.extend(impls.for_trait(trait_.id).map(Self::from))
2722 // FIXME: the return type is wrong. This should be a hir version of
2723 // `TraitRef` (to account for parameters and qualifiers)
2724 pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> {
2725 let trait_ref = db.impl_trait(self.id)?.skip_binders().clone();
2726 let id = hir_ty::from_chalk_trait_id(trait_ref.trait_id);
2730 pub fn self_ty(self, db: &dyn HirDatabase) -> Type {
2731 let resolver = self.id.resolver(db.upcast());
2732 let substs = TyBuilder::placeholder_subst(db, self.id);
2733 let ty = db.impl_self_ty(self.id).substitute(Interner, &substs);
2734 Type::new_with_resolver_inner(db, &resolver, ty)
2737 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
2738 db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect()
2741 pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
2742 db.impl_data(self.id).is_negative
2745 pub fn module(self, db: &dyn HirDatabase) -> Module {
2746 self.id.lookup(db.upcast()).container.into()
2749 pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
2750 let src = self.source(db)?;
2751 src.file_id.is_builtin_derive(db.upcast())
2755 #[derive(Clone, PartialEq, Eq, Debug)]
2757 env: Arc<TraitEnvironment>,
2762 pub(crate) fn new_with_resolver(db: &dyn HirDatabase, resolver: &Resolver, ty: Ty) -> Type {
2763 Type::new_with_resolver_inner(db, resolver, ty)
2766 pub(crate) fn new_with_resolver_inner(
2767 db: &dyn HirDatabase,
2768 resolver: &Resolver,
2771 let environment = resolver.generic_def().map_or_else(
2772 || Arc::new(TraitEnvironment::empty(resolver.krate())),
2773 |d| db.trait_environment(d),
2775 Type { env: environment, ty }
2778 pub(crate) fn new_for_crate(krate: CrateId, ty: Ty) -> Type {
2779 Type { env: Arc::new(TraitEnvironment::empty(krate)), ty }
2782 pub fn reference(inner: &Type, m: Mutability) -> Type {
2785 if m.is_mut() { hir_ty::Mutability::Mut } else { hir_ty::Mutability::Not },
2786 hir_ty::static_lifetime(),
2793 fn new(db: &dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty) -> Type {
2794 let resolver = lexical_env.resolver(db.upcast());
2795 let environment = resolver.generic_def().map_or_else(
2796 || Arc::new(TraitEnvironment::empty(resolver.krate())),
2797 |d| db.trait_environment(d),
2799 Type { env: environment, ty }
2802 fn from_def(db: &dyn HirDatabase, def: impl HasResolver + Into<TyDefId>) -> Type {
2803 let ty_def = def.into();
2804 let parent_subst = match ty_def {
2805 TyDefId::TypeAliasId(id) => match id.lookup(db.upcast()).container {
2806 ItemContainerId::TraitId(id) => {
2807 let subst = TyBuilder::subst_for_def(db, id, None).fill_with_unknown().build();
2814 let ty = TyBuilder::def_ty(db, ty_def, parent_subst).fill_with_unknown().build();
2815 Type::new(db, def, ty)
2818 pub fn new_slice(ty: Type) -> Type {
2819 Type { env: ty.env, ty: TyBuilder::slice(ty.ty) }
2822 pub fn is_unit(&self) -> bool {
2823 matches!(self.ty.kind(Interner), TyKind::Tuple(0, ..))
2826 pub fn is_bool(&self) -> bool {
2827 matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Bool))
2830 pub fn is_never(&self) -> bool {
2831 matches!(self.ty.kind(Interner), TyKind::Never)
2834 pub fn is_mutable_reference(&self) -> bool {
2835 matches!(self.ty.kind(Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
2838 pub fn is_reference(&self) -> bool {
2839 matches!(self.ty.kind(Interner), TyKind::Ref(..))
2842 pub fn as_reference(&self) -> Option<(Type, Mutability)> {
2843 let (ty, _lt, m) = self.ty.as_reference()?;
2844 let m = Mutability::from_mutable(matches!(m, hir_ty::Mutability::Mut));
2845 Some((self.derived(ty.clone()), m))
2848 pub fn is_slice(&self) -> bool {
2849 matches!(self.ty.kind(Interner), TyKind::Slice(..))
2852 pub fn is_usize(&self) -> bool {
2853 matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
2856 pub fn remove_ref(&self) -> Option<Type> {
2857 match &self.ty.kind(Interner) {
2858 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
2863 pub fn strip_references(&self) -> Type {
2864 self.derived(self.ty.strip_references().clone())
2867 pub fn strip_reference(&self) -> Type {
2868 self.derived(self.ty.strip_reference().clone())
2871 pub fn is_unknown(&self) -> bool {
2872 self.ty.is_unknown()
2875 /// Checks that particular type `ty` implements `std::future::IntoFuture` or
2876 /// `std::future::Future`.
2877 /// This function is used in `.await` syntax completion.
2878 pub fn impls_into_future(&self, db: &dyn HirDatabase) -> bool {
2880 .lang_item(self.env.krate, SmolStr::new_inline("into_future"))
2882 let into_future_fn = it.as_function()?;
2883 let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?;
2884 let into_future_trait = assoc_item.containing_trait_or_trait_impl(db)?;
2885 Some(into_future_trait.id)
2889 db.lang_item(self.env.krate, SmolStr::new_inline("future_trait"))?;
2890 future_trait.as_trait()
2893 let trait_ = match trait_ {
2895 None => return false,
2899 Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
2900 method_resolution::implements_trait(&canonical_ty, db, self.env.clone(), trait_)
2903 /// Checks that particular type `ty` implements `std::ops::FnOnce`.
2905 /// This function can be used to check if a particular type is callable, since FnOnce is a
2906 /// supertrait of Fn and FnMut, so all callable types implements at least FnOnce.
2907 pub fn impls_fnonce(&self, db: &dyn HirDatabase) -> bool {
2908 let fnonce_trait = match FnTrait::FnOnce.get_id(db, self.env.krate) {
2910 None => return false,
2914 Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
2915 method_resolution::implements_trait_unique(
2923 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
2924 let mut it = args.iter().map(|t| t.ty.clone());
2925 let trait_ref = TyBuilder::trait_ref(db, trait_.id)
2926 .push(self.ty.clone())
2928 let r = it.next().unwrap();
2930 ParamKind::Type => GenericArgData::Ty(r).intern(Interner),
2931 ParamKind::Const(ty) => {
2932 // FIXME: this code is not covered in tests.
2933 unknown_const_as_generic(ty.clone())
2939 let goal = Canonical {
2940 value: hir_ty::InEnvironment::new(&self.env.env, trait_ref.cast(Interner)),
2941 binders: CanonicalVarKinds::empty(Interner),
2944 db.trait_solve(self.env.krate, goal).is_some()
2947 pub fn normalize_trait_assoc_type(
2949 db: &dyn HirDatabase,
2953 let mut args = args.iter();
2954 let trait_id = match alias.id.lookup(db.upcast()).container {
2955 ItemContainerId::TraitId(id) => id,
2956 _ => unreachable!("non assoc type alias reached in normalize_trait_assoc_type()"),
2958 let parent_subst = TyBuilder::subst_for_def(db, trait_id, None)
2959 .push(self.ty.clone())
2961 // FIXME: this code is not covered in tests.
2963 ParamKind::Type => {
2964 GenericArgData::Ty(args.next().unwrap().ty.clone()).intern(Interner)
2966 ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
2970 // FIXME: We don't handle GATs yet.
2971 let projection = TyBuilder::assoc_type_projection(db, alias.id, Some(parent_subst)).build();
2973 let ty = db.normalize_projection(projection, self.env.clone());
2974 if ty.is_unknown() {
2977 Some(self.derived(ty))
2981 pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
2982 let lang_item = db.lang_item(self.env.krate, SmolStr::new_inline("copy"));
2983 let copy_trait = match lang_item {
2984 Some(LangItemTarget::TraitId(it)) => it,
2987 self.impls_trait(db, copy_trait.into(), &[])
2990 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
2991 let callee = match self.ty.kind(Interner) {
2992 TyKind::Closure(id, _) => Callee::Closure(*id),
2993 TyKind::Function(_) => Callee::FnPtr,
2994 _ => Callee::Def(self.ty.callable_def(db)?),
2997 let sig = self.ty.callable_sig(db)?;
2998 Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
3001 pub fn is_closure(&self) -> bool {
3002 matches!(&self.ty.kind(Interner), TyKind::Closure { .. })
3005 pub fn is_fn(&self) -> bool {
3006 matches!(&self.ty.kind(Interner), TyKind::FnDef(..) | TyKind::Function { .. })
3009 pub fn is_array(&self) -> bool {
3010 matches!(&self.ty.kind(Interner), TyKind::Array(..))
3013 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
3014 let adt_id = match *self.ty.kind(Interner) {
3015 TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
3019 let adt = adt_id.into();
3021 Adt::Struct(s) => matches!(s.repr(db), Some(ReprData { packed: true, .. })),
3026 pub fn is_raw_ptr(&self) -> bool {
3027 matches!(&self.ty.kind(Interner), TyKind::Raw(..))
3030 pub fn contains_unknown(&self) -> bool {
3031 return go(&self.ty);
3033 fn go(ty: &Ty) -> bool {
3034 match ty.kind(Interner) {
3035 TyKind::Error => true,
3037 TyKind::Adt(_, substs)
3038 | TyKind::AssociatedType(_, substs)
3039 | TyKind::Tuple(_, substs)
3040 | TyKind::OpaqueType(_, substs)
3041 | TyKind::FnDef(_, substs)
3042 | TyKind::Closure(_, substs) => {
3043 substs.iter(Interner).filter_map(|a| a.ty(Interner)).any(go)
3046 TyKind::Array(_ty, len) if len.is_unknown() => true,
3047 TyKind::Array(ty, _)
3049 | TyKind::Raw(_, ty)
3050 | TyKind::Ref(_, _, ty) => go(ty),
3055 | TyKind::Placeholder(_)
3056 | TyKind::BoundVar(_)
3057 | TyKind::InferenceVar(_, _)
3059 | TyKind::Function(_)
3061 | TyKind::Foreign(_)
3062 | TyKind::Generator(..)
3063 | TyKind::GeneratorWitness(..) => false,
3068 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
3069 let (variant_id, substs) = match self.ty.kind(Interner) {
3070 TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), substs) => ((*s).into(), substs),
3071 TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), substs) => ((*u).into(), substs),
3072 _ => return Vec::new(),
3075 db.field_types(variant_id)
3077 .map(|(local_id, ty)| {
3078 let def = Field { parent: variant_id.into(), id: local_id };
3079 let ty = ty.clone().substitute(Interner, substs);
3080 (def, self.derived(ty))
3085 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
3086 if let TyKind::Tuple(_, substs) = &self.ty.kind(Interner) {
3089 .map(|ty| self.derived(ty.assert_ty_ref(Interner).clone()))
3096 pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a {
3097 self.autoderef_(db).map(move |ty| self.derived(ty))
3100 fn autoderef_<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Ty> + 'a {
3101 // There should be no inference vars in types passed here
3102 let canonical = hir_ty::replace_errors_with_variables(&self.ty);
3103 let environment = self.env.clone();
3104 autoderef(db, environment, canonical).map(|canonical| canonical.value)
3107 // This would be nicer if it just returned an iterator, but that runs into
3108 // lifetime problems, because we need to borrow temp `CrateImplDefs`.
3109 pub fn iterate_assoc_items<T>(
3111 db: &dyn HirDatabase,
3113 mut callback: impl FnMut(AssocItem) -> Option<T>,
3115 let mut slot = None;
3116 self.iterate_assoc_items_dyn(db, krate, &mut |assoc_item_id| {
3117 slot = callback(assoc_item_id.into());
3123 fn iterate_assoc_items_dyn(
3125 db: &dyn HirDatabase,
3127 callback: &mut dyn FnMut(AssocItemId) -> bool,
3129 let def_crates = match method_resolution::def_crates(db, &self.ty, krate.id) {
3133 for krate in def_crates {
3134 let impls = db.inherent_impls_in_crate(krate);
3136 for impl_def in impls.for_self_ty(&self.ty) {
3137 for &item in db.impl_data(*impl_def).items.iter() {
3146 pub fn type_arguments(&self) -> impl Iterator<Item = Type> + '_ {
3151 .flat_map(|(_, substs)| substs.iter(Interner))
3152 .filter_map(|arg| arg.ty(Interner).cloned())
3153 .map(move |ty| self.derived(ty))
3156 pub fn iterate_method_candidates<T>(
3158 db: &dyn HirDatabase,
3159 scope: &SemanticsScope<'_>,
3160 // FIXME this can be retrieved from `scope`, except autoimport uses this
3161 // to specify a different set, so the method needs to be split
3162 traits_in_scope: &FxHashSet<TraitId>,
3163 with_local_impls: Option<Module>,
3164 name: Option<&Name>,
3165 mut callback: impl FnMut(Function) -> Option<T>,
3167 let _p = profile::span("iterate_method_candidates");
3168 let mut slot = None;
3170 self.iterate_method_candidates_dyn(
3176 &mut |assoc_item_id| {
3177 if let AssocItemId::FunctionId(func) = assoc_item_id {
3178 if let Some(res) = callback(func.into()) {
3180 return ControlFlow::Break(());
3183 ControlFlow::Continue(())
3189 fn iterate_method_candidates_dyn(
3191 db: &dyn HirDatabase,
3192 scope: &SemanticsScope<'_>,
3193 traits_in_scope: &FxHashSet<TraitId>,
3194 with_local_impls: Option<Module>,
3195 name: Option<&Name>,
3196 callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>,
3198 // There should be no inference vars in types passed here
3199 let canonical = hir_ty::replace_errors_with_variables(&self.ty);
3201 let krate = scope.krate();
3202 let environment = scope.resolver().generic_def().map_or_else(
3203 || Arc::new(TraitEnvironment::empty(krate.id)),
3204 |d| db.trait_environment(d),
3207 method_resolution::iterate_method_candidates_dyn(
3212 with_local_impls.and_then(|b| b.id.containing_block()).into(),
3214 method_resolution::LookupMode::MethodCall,
3215 &mut |_adj, id| callback(id),
3219 pub fn iterate_path_candidates<T>(
3221 db: &dyn HirDatabase,
3222 scope: &SemanticsScope<'_>,
3223 traits_in_scope: &FxHashSet<TraitId>,
3224 with_local_impls: Option<Module>,
3225 name: Option<&Name>,
3226 mut callback: impl FnMut(AssocItem) -> Option<T>,
3228 let _p = profile::span("iterate_path_candidates");
3229 let mut slot = None;
3230 self.iterate_path_candidates_dyn(
3236 &mut |assoc_item_id| {
3237 if let Some(res) = callback(assoc_item_id.into()) {
3239 return ControlFlow::Break(());
3241 ControlFlow::Continue(())
3247 fn iterate_path_candidates_dyn(
3249 db: &dyn HirDatabase,
3250 scope: &SemanticsScope<'_>,
3251 traits_in_scope: &FxHashSet<TraitId>,
3252 with_local_impls: Option<Module>,
3253 name: Option<&Name>,
3254 callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>,
3256 let canonical = hir_ty::replace_errors_with_variables(&self.ty);
3258 let krate = scope.krate();
3259 let environment = scope.resolver().generic_def().map_or_else(
3260 || Arc::new(TraitEnvironment::empty(krate.id)),
3261 |d| db.trait_environment(d),
3264 method_resolution::iterate_path_candidates(
3269 with_local_impls.and_then(|b| b.id.containing_block()).into(),
3271 &mut |id| callback(id),
3275 pub fn as_adt(&self) -> Option<Adt> {
3276 let (adt, _subst) = self.ty.as_adt()?;
3280 pub fn as_builtin(&self) -> Option<BuiltinType> {
3281 self.ty.as_builtin().map(|inner| BuiltinType { inner })
3284 pub fn as_dyn_trait(&self) -> Option<Trait> {
3285 self.ty.dyn_trait().map(Into::into)
3288 /// If a type can be represented as `dyn Trait`, returns all traits accessible via this type,
3289 /// or an empty iterator otherwise.
3290 pub fn applicable_inherent_traits<'a>(
3292 db: &'a dyn HirDatabase,
3293 ) -> impl Iterator<Item = Trait> + 'a {
3294 let _p = profile::span("applicable_inherent_traits");
3296 .filter_map(|ty| ty.dyn_trait())
3297 .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
3301 pub fn env_traits<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Trait> + 'a {
3302 let _p = profile::span("env_traits");
3304 .filter(|ty| matches!(ty.kind(Interner), TyKind::Placeholder(_)))
3307 .traits_in_scope_from_clauses(ty)
3308 .flat_map(|t| hir_ty::all_super_traits(db.upcast(), t))
3313 pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<impl Iterator<Item = Trait>> {
3314 self.ty.impl_trait_bounds(db).map(|it| {
3315 it.into_iter().filter_map(|pred| match pred.skip_binders() {
3316 hir_ty::WhereClause::Implemented(trait_ref) => {
3317 Some(Trait::from(trait_ref.hir_trait_id()))
3324 pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> {
3325 self.ty.associated_type_parent_trait(db).map(Into::into)
3328 fn derived(&self, ty: Ty) -> Type {
3329 Type { env: self.env.clone(), ty }
3332 pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
3333 // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself.
3334 // We need a different order here.
3337 db: &dyn HirDatabase,
3339 substs: &Substitution,
3340 cb: &mut impl FnMut(Type),
3342 for ty in substs.iter(Interner).filter_map(|a| a.ty(Interner)) {
3343 walk_type(db, &type_.derived(ty.clone()), cb);
3348 db: &dyn HirDatabase,
3350 bounds: &[QuantifiedWhereClause],
3351 cb: &mut impl FnMut(Type),
3353 for pred in bounds {
3354 if let WhereClause::Implemented(trait_ref) = pred.skip_binders() {
3356 // skip the self type. it's likely the type we just got the bounds from
3358 trait_ref.substitution.iter(Interner).skip(1).filter_map(|a| a.ty(Interner))
3360 walk_type(db, &type_.derived(ty.clone()), cb);
3366 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
3367 let ty = type_.ty.strip_references();
3368 match ty.kind(Interner) {
3369 TyKind::Adt(_, substs) => {
3370 cb(type_.derived(ty.clone()));
3371 walk_substs(db, type_, substs, cb);
3373 TyKind::AssociatedType(_, substs) => {
3374 if ty.associated_type_parent_trait(db).is_some() {
3375 cb(type_.derived(ty.clone()));
3377 walk_substs(db, type_, substs, cb);
3379 TyKind::OpaqueType(_, subst) => {
3380 if let Some(bounds) = ty.impl_trait_bounds(db) {
3381 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
3384 walk_substs(db, type_, subst, cb);
3386 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
3387 if let Some(bounds) = ty.impl_trait_bounds(db) {
3388 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
3391 walk_substs(db, type_, &opaque_ty.substitution, cb);
3393 TyKind::Placeholder(_) => {
3394 if let Some(bounds) = ty.impl_trait_bounds(db) {
3395 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
3398 TyKind::Dyn(bounds) => {
3401 &type_.derived(ty.clone()),
3402 bounds.bounds.skip_binders().interned(),
3407 TyKind::Ref(_, _, ty)
3408 | TyKind::Raw(_, ty)
3409 | TyKind::Array(ty, _)
3410 | TyKind::Slice(ty) => {
3411 walk_type(db, &type_.derived(ty.clone()), cb);
3414 TyKind::FnDef(_, substs)
3415 | TyKind::Tuple(_, substs)
3416 | TyKind::Closure(.., substs) => {
3417 walk_substs(db, type_, substs, cb);
3419 TyKind::Function(hir_ty::FnPointer { substitution, .. }) => {
3420 walk_substs(db, type_, &substitution.0, cb);
3427 walk_type(db, self, &mut cb);
3430 pub fn could_unify_with(&self, db: &dyn HirDatabase, other: &Type) -> bool {
3431 let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone()));
3432 hir_ty::could_unify(db, self.env.clone(), &tys)
3435 pub fn could_coerce_to(&self, db: &dyn HirDatabase, to: &Type) -> bool {
3436 let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), to.ty.clone()));
3437 hir_ty::could_coerce(db, self.env.clone(), &tys)
3440 pub fn as_type_param(&self, db: &dyn HirDatabase) -> Option<TypeParam> {
3441 match self.ty.kind(Interner) {
3442 TyKind::Placeholder(p) => Some(TypeParam {
3443 id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p)),
3451 pub struct Callable {
3455 pub(crate) is_bound_method: bool,
3465 pub enum CallableKind {
3467 TupleStruct(Struct),
3468 TupleEnumVariant(Variant),
3474 pub fn kind(&self) -> CallableKind {
3477 Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
3478 Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
3479 Def(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
3480 Closure(_) => CallableKind::Closure,
3481 FnPtr => CallableKind::FnPtr,
3484 pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> {
3485 let func = match self.callee {
3486 Callee::Def(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
3489 let src = func.lookup(db.upcast()).source(db.upcast());
3490 let param_list = src.value.param_list()?;
3491 param_list.self_param()
3493 pub fn n_params(&self) -> usize {
3494 self.sig.params().len() - if self.is_bound_method { 1 } else { 0 }
3498 db: &dyn HirDatabase,
3499 ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> {
3504 .skip(if self.is_bound_method { 1 } else { 0 })
3505 .map(|ty| self.ty.derived(ty.clone()));
3506 let map_param = |it: ast::Param| it.pat().map(Either::Right);
3507 let patterns = match self.callee {
3508 Callee::Def(CallableDefId::FunctionId(func)) => {
3509 let src = func.lookup(db.upcast()).source(db.upcast());
3510 src.value.param_list().map(|param_list| {
3513 .map(|it| Some(Either::Left(it)))
3514 .filter(|_| !self.is_bound_method)
3516 .chain(param_list.params().map(map_param))
3519 Callee::Closure(closure_id) => match closure_source(db, closure_id) {
3520 Some(src) => src.param_list().map(|param_list| {
3523 .map(|it| Some(Either::Left(it)))
3524 .filter(|_| !self.is_bound_method)
3526 .chain(param_list.params().map(map_param))
3532 patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
3534 pub fn return_type(&self) -> Type {
3535 self.ty.derived(self.sig.ret().clone())
3539 fn closure_source(db: &dyn HirDatabase, closure: ClosureId) -> Option<ast::ClosureExpr> {
3540 let (owner, expr_id) = db.lookup_intern_closure(closure.into());
3541 let (_, source_map) = db.body_with_source_map(owner);
3542 let ast = source_map.expr_syntax(expr_id).ok()?;
3543 let root = ast.file_syntax(db.upcast());
3544 let expr = ast.value.to_node(&root);
3546 ast::Expr::ClosureExpr(it) => Some(it),
3551 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
3552 pub enum BindingMode {
3558 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
3560 ModuleDef(ModuleDef),
3561 GenericParam(GenericParam),
3570 pub fn all_items(def: PerNs) -> ArrayVec<Self, 3> {
3571 let mut items = ArrayVec::new();
3573 match (def.take_types(), def.take_values()) {
3574 (Some(m1), None) => items.push(ScopeDef::ModuleDef(m1.into())),
3575 (None, Some(m2)) => items.push(ScopeDef::ModuleDef(m2.into())),
3576 (Some(m1), Some(m2)) => {
3577 // Some items, like unit structs and enum variants, are
3578 // returned as both a type and a value. Here we want
3579 // to de-duplicate them.
3581 items.push(ScopeDef::ModuleDef(m1.into()));
3582 items.push(ScopeDef::ModuleDef(m2.into()));
3584 items.push(ScopeDef::ModuleDef(m1.into()));
3590 if let Some(macro_def_id) = def.take_macros() {
3591 items.push(ScopeDef::ModuleDef(ModuleDef::Macro(macro_def_id.into())));
3594 if items.is_empty() {
3595 items.push(ScopeDef::Unknown);
3601 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
3603 ScopeDef::ModuleDef(it) => it.attrs(db),
3604 ScopeDef::GenericParam(it) => Some(it.attrs(db)),
3605 ScopeDef::ImplSelfType(_)
3606 | ScopeDef::AdtSelfType(_)
3607 | ScopeDef::Local(_)
3608 | ScopeDef::Label(_)
3609 | ScopeDef::Unknown => None,
3613 pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
3615 ScopeDef::ModuleDef(it) => it.module(db).map(|m| m.krate()),
3616 ScopeDef::GenericParam(it) => Some(it.module(db).krate()),
3617 ScopeDef::ImplSelfType(_) => None,
3618 ScopeDef::AdtSelfType(it) => Some(it.module(db).krate()),
3619 ScopeDef::Local(it) => Some(it.module(db).krate()),
3620 ScopeDef::Label(it) => Some(it.module(db).krate()),
3621 ScopeDef::Unknown => None,
3626 impl From<ItemInNs> for ScopeDef {
3627 fn from(item: ItemInNs) -> Self {
3629 ItemInNs::Types(id) => ScopeDef::ModuleDef(id),
3630 ItemInNs::Values(id) => ScopeDef::ModuleDef(id),
3631 ItemInNs::Macros(id) => ScopeDef::ModuleDef(ModuleDef::Macro(id)),
3636 pub trait HasVisibility {
3637 fn visibility(&self, db: &dyn HirDatabase) -> Visibility;
3638 fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool {
3639 let vis = self.visibility(db);
3640 vis.is_visible_from(db.upcast(), module.id)
3644 /// Trait for obtaining the defining crate of an item.
3645 pub trait HasCrate {
3646 fn krate(&self, db: &dyn HirDatabase) -> Crate;
3649 impl<T: hir_def::HasModule> HasCrate for T {
3650 fn krate(&self, db: &dyn HirDatabase) -> Crate {
3651 self.module(db.upcast()).krate().into()
3655 impl HasCrate for AssocItem {
3656 fn krate(&self, db: &dyn HirDatabase) -> Crate {
3657 self.module(db).krate()
3661 impl HasCrate for Struct {
3662 fn krate(&self, db: &dyn HirDatabase) -> Crate {
3663 self.module(db).krate()
3667 impl HasCrate for Union {
3668 fn krate(&self, db: &dyn HirDatabase) -> Crate {
3669 self.module(db).krate()
3673 impl HasCrate for Field {
3674 fn krate(&self, db: &dyn HirDatabase) -> Crate {
3675 self.parent_def(db).module(db).krate()
3679 impl HasCrate for Variant {
3680 fn krate(&self, db: &dyn HirDatabase) -> Crate {
3681 self.module(db).krate()
3685 impl HasCrate for Function {
3686 fn krate(&self, db: &dyn HirDatabase) -> Crate {
3687 self.module(db).krate()
3691 impl HasCrate for Const {
3692 fn krate(&self, db: &dyn HirDatabase) -> Crate {
3693 self.module(db).krate()
3697 impl HasCrate for TypeAlias {
3698 fn krate(&self, db: &dyn HirDatabase) -> Crate {
3699 self.module(db).krate()
3703 impl HasCrate for Type {
3704 fn krate(&self, _db: &dyn HirDatabase) -> Crate {
3705 self.env.krate.into()
3709 impl HasCrate for Macro {
3710 fn krate(&self, db: &dyn HirDatabase) -> Crate {
3711 self.module(db).krate()
3715 impl HasCrate for Trait {
3716 fn krate(&self, db: &dyn HirDatabase) -> Crate {
3717 self.module(db).krate()
3721 impl HasCrate for Static {
3722 fn krate(&self, db: &dyn HirDatabase) -> Crate {
3723 self.module(db).krate()
3727 impl HasCrate for Adt {
3728 fn krate(&self, db: &dyn HirDatabase) -> Crate {
3729 self.module(db).krate()
3733 impl HasCrate for Module {
3734 fn krate(&self, _: &dyn HirDatabase) -> Crate {
3735 Module::krate(*self)