1 //! HIR (previously known as descriptors) provides a high-level object oriented
2 //! access to Rust code.
3 //!
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.
7 //!
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 its
10 //! parents and full context). It should be "clean code".
11 //!
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.
15 //!
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>.
19
20 #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
21 #![recursion_limit = "512"]
22
23 mod semantics;
24 mod source_analyzer;
25
26 mod from_id;
27 mod attrs;
28 mod has_source;
29
30 pub mod diagnostics;
31 pub mod db;
32 pub mod symbols;
33
34 mod display;
35
36 use std::{iter, ops::ControlFlow};
37
38 use arrayvec::ArrayVec;
39 use base_db::{CrateDisplayName, CrateId, CrateOrigin, Edition, FileId, ProcMacroKind};
40 use either::Either;
41 use hir_def::{
42 body::{BodyDiagnostic, SyntheticSyntax},
43 data::adt::VariantData,
44 generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
45 hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat},
46 item_tree::ItemTreeNode,
47 lang_item::LangItemTarget,
48 layout::{self, ReprOptions, TargetDataLayout},
49 macro_id_to_def_id,
50 nameres::{self, diagnostics::DefDiagnostic, ModuleOrigin},
51 per_ns::PerNs,
52 resolver::{HasResolver, Resolver},
53 src::HasSource as _,
54 AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
55 EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, InTypeConstId, ItemContainerId,
56 LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId,
57 StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
58 UnionId,
59 };
60 use hir_expand::{name::name, MacroCallKind};
61 use hir_ty::{
62 all_super_traits, autoderef,
63 consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt},
64 diagnostics::BodyValidationDiagnostic,
65 display::HexifiedConst,
66 layout::{Layout as TyLayout, RustcEnumVariantIdx, TagEncoding},
67 method_resolution::{self, TyFingerprint},
68 mir::{self, interpret_mir},
69 primitive::UintTy,
70 traits::FnTrait,
71 AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId,
72 GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
73 TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId,
74 WhereClause,
75 };
76 use itertools::Itertools;
77 use nameres::diagnostics::DefDiagnosticKind;
78 use once_cell::unsync::Lazy;
79 use rustc_hash::FxHashSet;
80 use stdx::{impl_from, never};
81 use syntax::{
82 ast::{self, HasAttrs as _, HasDocComments, HasName},
83 AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, T,
84 };
85 use triomphe::Arc;
86
87 use crate::db::{DefDatabase, HirDatabase};
88
89 pub use crate::{
90 attrs::{HasAttrs, Namespace},
91 diagnostics::{
92 AnyDiagnostic, BreakOutsideOfLoop, ExpectedFunction, InactiveCode, IncoherentImpl,
93 IncorrectCase, InvalidDeriveTarget, MacroDefError, MacroError, MacroExpansionParseError,
94 MalformedDerive, MismatchedArgCount, MissingFields, MissingMatchArms, MissingUnsafe,
95 MovedOutOfRef, NeedMut, NoSuchField, PrivateAssocItem, PrivateField,
96 ReplaceFilterMapNextWithFindMap, TypeMismatch, TypedHole, UndeclaredLabel,
97 UnimplementedBuiltinMacro, UnreachableLabel, UnresolvedExternCrate, UnresolvedField,
98 UnresolvedImport, UnresolvedMacroCall, UnresolvedMethodCall, UnresolvedModule,
99 UnresolvedProcMacro, UnusedMut,
100 },
101 has_source::HasSource,
102 semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo, VisibleTraits},
103 };
104
105 // Be careful with these re-exports.
106 //
107 // `hir` is the boundary between the compiler and the IDE. It should try hard to
108 // isolate the compiler from the ide, to allow the two to be refactored
109 // independently. Re-exporting something from the compiler is the sure way to
110 // breach the boundary.
111 //
112 // Generally, a refactoring which *removes* a name from this list is a good
113 // idea!
114 pub use {
115 cfg::{CfgAtom, CfgExpr, CfgOptions},
116 hir_def::{
117 attr::{builtin::AttributeTemplate, Attrs, AttrsWithOwner, Documentation},
118 data::adt::StructKind,
119 find_path::PrefixKind,
120 import_map,
121 lang_item::LangItem,
122 nameres::{DefMap, ModuleSource},
123 path::{ModPath, PathKind},
124 type_ref::{Mutability, TypeRef},
125 visibility::Visibility,
126 // FIXME: This is here since some queries take it as input that are used
127 // outside of hir.
128 {AdtId, ModuleDefId},
129 },
130 hir_expand::{
131 attrs::Attr,
132 name::{known, Name},
133 ExpandResult, HirFileId, InFile, MacroFile, Origin,
134 },
135 hir_ty::{
136 display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
137 layout::LayoutError,
138 mir::MirEvalError,
139 PointerCast, Safety,
140 },
141 };
142
143 // These are negative re-exports: pub using these names is forbidden, they
144 // should remain private to hir internals.
145 #[allow(unused)]
146 use {
147 hir_def::path::Path,
148 hir_expand::{hygiene::Hygiene, name::AsName},
149 };
150
151 /// hir::Crate describes a single crate. It's the main interface with which
152 /// a crate's dependencies interact. Mostly, it should be just a proxy for the
153 /// root module.
154 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
155 pub struct Crate {
156 pub(crate) id: CrateId,
157 }
158
159 #[derive(Debug)]
160 pub struct CrateDependency {
161 pub krate: Crate,
162 pub name: Name,
163 }
164
165 impl Crate {
origin(self, db: &dyn HirDatabase) -> CrateOrigin166 pub fn origin(self, db: &dyn HirDatabase) -> CrateOrigin {
167 db.crate_graph()[self.id].origin.clone()
168 }
169
is_builtin(self, db: &dyn HirDatabase) -> bool170 pub fn is_builtin(self, db: &dyn HirDatabase) -> bool {
171 matches!(self.origin(db), CrateOrigin::Lang(_))
172 }
173
dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency>174 pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
175 db.crate_graph()[self.id]
176 .dependencies
177 .iter()
178 .map(|dep| {
179 let krate = Crate { id: dep.crate_id };
180 let name = dep.as_name();
181 CrateDependency { krate, name }
182 })
183 .collect()
184 }
185
reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate>186 pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
187 let crate_graph = db.crate_graph();
188 crate_graph
189 .iter()
190 .filter(|&krate| {
191 crate_graph[krate].dependencies.iter().any(|it| it.crate_id == self.id)
192 })
193 .map(|id| Crate { id })
194 .collect()
195 }
196
transitive_reverse_dependencies( self, db: &dyn HirDatabase, ) -> impl Iterator<Item = Crate>197 pub fn transitive_reverse_dependencies(
198 self,
199 db: &dyn HirDatabase,
200 ) -> impl Iterator<Item = Crate> {
201 db.crate_graph().transitive_rev_deps(self.id).map(|id| Crate { id })
202 }
203
root_module(self, db: &dyn HirDatabase) -> Module204 pub fn root_module(self, db: &dyn HirDatabase) -> Module {
205 let def_map = db.crate_def_map(self.id);
206 Module { id: def_map.crate_root().into() }
207 }
208
modules(self, db: &dyn HirDatabase) -> Vec<Module>209 pub fn modules(self, db: &dyn HirDatabase) -> Vec<Module> {
210 let def_map = db.crate_def_map(self.id);
211 def_map.modules().map(|(id, _)| def_map.module_id(id).into()).collect()
212 }
213
root_file(self, db: &dyn HirDatabase) -> FileId214 pub fn root_file(self, db: &dyn HirDatabase) -> FileId {
215 db.crate_graph()[self.id].root_file_id
216 }
217
edition(self, db: &dyn HirDatabase) -> Edition218 pub fn edition(self, db: &dyn HirDatabase) -> Edition {
219 db.crate_graph()[self.id].edition
220 }
221
version(self, db: &dyn HirDatabase) -> Option<String>222 pub fn version(self, db: &dyn HirDatabase) -> Option<String> {
223 db.crate_graph()[self.id].version.clone()
224 }
225
display_name(self, db: &dyn HirDatabase) -> Option<CrateDisplayName>226 pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateDisplayName> {
227 db.crate_graph()[self.id].display_name.clone()
228 }
229
query_external_importables( self, db: &dyn DefDatabase, query: import_map::Query, ) -> impl Iterator<Item = Either<ModuleDef, Macro>>230 pub fn query_external_importables(
231 self,
232 db: &dyn DefDatabase,
233 query: import_map::Query,
234 ) -> impl Iterator<Item = Either<ModuleDef, Macro>> {
235 let _p = profile::span("query_external_importables");
236 import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| {
237 match ItemInNs::from(item) {
238 ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id),
239 ItemInNs::Macros(mac_id) => Either::Right(mac_id),
240 }
241 })
242 }
243
all(db: &dyn HirDatabase) -> Vec<Crate>244 pub fn all(db: &dyn HirDatabase) -> Vec<Crate> {
245 db.crate_graph().iter().map(|id| Crate { id }).collect()
246 }
247
248 /// Try to get the root URL of the documentation of a crate.
get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String>249 pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
250 // Look for #![doc(html_root_url = "...")]
251 let attrs = db.attrs(AttrDefId::ModuleId(self.root_module(db).into()));
252 let doc_url = attrs.by_key("doc").find_string_value_in_tt("html_root_url");
253 doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
254 }
255
cfg(&self, db: &dyn HirDatabase) -> CfgOptions256 pub fn cfg(&self, db: &dyn HirDatabase) -> CfgOptions {
257 db.crate_graph()[self.id].cfg_options.clone()
258 }
259
potential_cfg(&self, db: &dyn HirDatabase) -> CfgOptions260 pub fn potential_cfg(&self, db: &dyn HirDatabase) -> CfgOptions {
261 let data = &db.crate_graph()[self.id];
262 data.potential_cfg_options.clone().unwrap_or_else(|| data.cfg_options.clone())
263 }
264 }
265
266 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
267 pub struct Module {
268 pub(crate) id: ModuleId,
269 }
270
271 /// The defs which can be visible in the module.
272 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
273 pub enum ModuleDef {
274 Module(Module),
275 Function(Function),
276 Adt(Adt),
277 // Can't be directly declared, but can be imported.
278 Variant(Variant),
279 Const(Const),
280 Static(Static),
281 Trait(Trait),
282 TraitAlias(TraitAlias),
283 TypeAlias(TypeAlias),
284 BuiltinType(BuiltinType),
285 Macro(Macro),
286 }
287 impl_from!(
288 Module,
289 Function,
290 Adt(Struct, Enum, Union),
291 Variant,
292 Const,
293 Static,
294 Trait,
295 TraitAlias,
296 TypeAlias,
297 BuiltinType,
298 Macro
299 for ModuleDef
300 );
301
302 impl From<VariantDef> for ModuleDef {
from(var: VariantDef) -> Self303 fn from(var: VariantDef) -> Self {
304 match var {
305 VariantDef::Struct(t) => Adt::from(t).into(),
306 VariantDef::Union(t) => Adt::from(t).into(),
307 VariantDef::Variant(t) => t.into(),
308 }
309 }
310 }
311
312 impl ModuleDef {
module(self, db: &dyn HirDatabase) -> Option<Module>313 pub fn module(self, db: &dyn HirDatabase) -> Option<Module> {
314 match self {
315 ModuleDef::Module(it) => it.parent(db),
316 ModuleDef::Function(it) => Some(it.module(db)),
317 ModuleDef::Adt(it) => Some(it.module(db)),
318 ModuleDef::Variant(it) => Some(it.module(db)),
319 ModuleDef::Const(it) => Some(it.module(db)),
320 ModuleDef::Static(it) => Some(it.module(db)),
321 ModuleDef::Trait(it) => Some(it.module(db)),
322 ModuleDef::TraitAlias(it) => Some(it.module(db)),
323 ModuleDef::TypeAlias(it) => Some(it.module(db)),
324 ModuleDef::Macro(it) => Some(it.module(db)),
325 ModuleDef::BuiltinType(_) => None,
326 }
327 }
328
canonical_path(&self, db: &dyn HirDatabase) -> Option<String>329 pub fn canonical_path(&self, db: &dyn HirDatabase) -> Option<String> {
330 let mut segments = vec![self.name(db)?];
331 for m in self.module(db)?.path_to_root(db) {
332 segments.extend(m.name(db))
333 }
334 segments.reverse();
335 Some(segments.iter().map(|it| it.display(db.upcast())).join("::"))
336 }
337
canonical_module_path( &self, db: &dyn HirDatabase, ) -> Option<impl Iterator<Item = Module>>338 pub fn canonical_module_path(
339 &self,
340 db: &dyn HirDatabase,
341 ) -> Option<impl Iterator<Item = Module>> {
342 self.module(db).map(|it| it.path_to_root(db).into_iter().rev())
343 }
344
name(self, db: &dyn HirDatabase) -> Option<Name>345 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
346 let name = match self {
347 ModuleDef::Module(it) => it.name(db)?,
348 ModuleDef::Const(it) => it.name(db)?,
349 ModuleDef::Adt(it) => it.name(db),
350 ModuleDef::Trait(it) => it.name(db),
351 ModuleDef::TraitAlias(it) => it.name(db),
352 ModuleDef::Function(it) => it.name(db),
353 ModuleDef::Variant(it) => it.name(db),
354 ModuleDef::TypeAlias(it) => it.name(db),
355 ModuleDef::Static(it) => it.name(db),
356 ModuleDef::Macro(it) => it.name(db),
357 ModuleDef::BuiltinType(it) => it.name(),
358 };
359 Some(name)
360 }
361
diagnostics(self, db: &dyn HirDatabase) -> Vec<AnyDiagnostic>362 pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec<AnyDiagnostic> {
363 let id = match self {
364 ModuleDef::Adt(it) => match it {
365 Adt::Struct(it) => it.id.into(),
366 Adt::Enum(it) => it.id.into(),
367 Adt::Union(it) => it.id.into(),
368 },
369 ModuleDef::Trait(it) => it.id.into(),
370 ModuleDef::TraitAlias(it) => it.id.into(),
371 ModuleDef::Function(it) => it.id.into(),
372 ModuleDef::TypeAlias(it) => it.id.into(),
373 ModuleDef::Module(it) => it.id.into(),
374 ModuleDef::Const(it) => it.id.into(),
375 ModuleDef::Static(it) => it.id.into(),
376 ModuleDef::Variant(it) => {
377 EnumVariantId { parent: it.parent.into(), local_id: it.id }.into()
378 }
379 ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(),
380 };
381
382 let module = match self.module(db) {
383 Some(it) => it,
384 None => return Vec::new(),
385 };
386
387 let mut acc = Vec::new();
388
389 match self.as_def_with_body() {
390 Some(def) => {
391 def.diagnostics(db, &mut acc);
392 }
393 None => {
394 for diag in hir_ty::diagnostics::incorrect_case(db, module.id.krate(), id) {
395 acc.push(diag.into())
396 }
397 }
398 }
399
400 acc
401 }
402
as_def_with_body(self) -> Option<DefWithBody>403 pub fn as_def_with_body(self) -> Option<DefWithBody> {
404 match self {
405 ModuleDef::Function(it) => Some(it.into()),
406 ModuleDef::Const(it) => Some(it.into()),
407 ModuleDef::Static(it) => Some(it.into()),
408 ModuleDef::Variant(it) => Some(it.into()),
409
410 ModuleDef::Module(_)
411 | ModuleDef::Adt(_)
412 | ModuleDef::Trait(_)
413 | ModuleDef::TraitAlias(_)
414 | ModuleDef::TypeAlias(_)
415 | ModuleDef::Macro(_)
416 | ModuleDef::BuiltinType(_) => None,
417 }
418 }
419
attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner>420 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
421 Some(match self {
422 ModuleDef::Module(it) => it.attrs(db),
423 ModuleDef::Function(it) => it.attrs(db),
424 ModuleDef::Adt(it) => it.attrs(db),
425 ModuleDef::Variant(it) => it.attrs(db),
426 ModuleDef::Const(it) => it.attrs(db),
427 ModuleDef::Static(it) => it.attrs(db),
428 ModuleDef::Trait(it) => it.attrs(db),
429 ModuleDef::TraitAlias(it) => it.attrs(db),
430 ModuleDef::TypeAlias(it) => it.attrs(db),
431 ModuleDef::Macro(it) => it.attrs(db),
432 ModuleDef::BuiltinType(_) => return None,
433 })
434 }
435 }
436
437 impl HasVisibility for ModuleDef {
visibility(&self, db: &dyn HirDatabase) -> Visibility438 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
439 match *self {
440 ModuleDef::Module(it) => it.visibility(db),
441 ModuleDef::Function(it) => it.visibility(db),
442 ModuleDef::Adt(it) => it.visibility(db),
443 ModuleDef::Const(it) => it.visibility(db),
444 ModuleDef::Static(it) => it.visibility(db),
445 ModuleDef::Trait(it) => it.visibility(db),
446 ModuleDef::TraitAlias(it) => it.visibility(db),
447 ModuleDef::TypeAlias(it) => it.visibility(db),
448 ModuleDef::Variant(it) => it.visibility(db),
449 ModuleDef::Macro(it) => it.visibility(db),
450 ModuleDef::BuiltinType(_) => Visibility::Public,
451 }
452 }
453 }
454
455 impl Module {
456 /// Name of this module.
name(self, db: &dyn HirDatabase) -> Option<Name>457 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
458 let def_map = self.id.def_map(db.upcast());
459 let parent = def_map[self.id.local_id].parent?;
460 def_map[parent].children.iter().find_map(|(name, module_id)| {
461 if *module_id == self.id.local_id {
462 Some(name.clone())
463 } else {
464 None
465 }
466 })
467 }
468
469 /// Returns the crate this module is part of.
krate(self) -> Crate470 pub fn krate(self) -> Crate {
471 Crate { id: self.id.krate() }
472 }
473
474 /// Topmost parent of this module. Every module has a `crate_root`, but some
475 /// might be missing `krate`. This can happen if a module's file is not included
476 /// in the module tree of any target in `Cargo.toml`.
crate_root(self, db: &dyn HirDatabase) -> Module477 pub fn crate_root(self, db: &dyn HirDatabase) -> Module {
478 let def_map = db.crate_def_map(self.id.krate());
479 Module { id: def_map.crate_root().into() }
480 }
481
is_crate_root(self) -> bool482 pub fn is_crate_root(self) -> bool {
483 DefMap::ROOT == self.id.local_id
484 }
485
486 /// Iterates over all child modules.
children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module>487 pub fn children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module> {
488 let def_map = self.id.def_map(db.upcast());
489 let children = def_map[self.id.local_id]
490 .children
491 .values()
492 .map(|module_id| Module { id: def_map.module_id(*module_id) })
493 .collect::<Vec<_>>();
494 children.into_iter()
495 }
496
497 /// Finds a parent module.
parent(self, db: &dyn HirDatabase) -> Option<Module>498 pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> {
499 // FIXME: handle block expressions as modules (their parent is in a different DefMap)
500 let def_map = self.id.def_map(db.upcast());
501 let parent_id = def_map[self.id.local_id].parent?;
502 Some(Module { id: def_map.module_id(parent_id) })
503 }
504
505 /// Finds nearest non-block ancestor `Module` (`self` included).
nearest_non_block_module(self, db: &dyn HirDatabase) -> Module506 pub fn nearest_non_block_module(self, db: &dyn HirDatabase) -> Module {
507 let mut id = self.id;
508 loop {
509 let def_map = id.def_map(db.upcast());
510 let origin = def_map[id.local_id].origin;
511 if matches!(origin, ModuleOrigin::BlockExpr { .. }) {
512 id = id.containing_module(db.upcast()).expect("block without parent module")
513 } else {
514 return Module { id };
515 }
516 }
517 }
518
path_to_root(self, db: &dyn HirDatabase) -> Vec<Module>519 pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> {
520 let mut res = vec![self];
521 let mut curr = self;
522 while let Some(next) = curr.parent(db) {
523 res.push(next);
524 curr = next
525 }
526 res
527 }
528
529 /// Returns a `ModuleScope`: a set of items, visible in this module.
scope( self, db: &dyn HirDatabase, visible_from: Option<Module>, ) -> Vec<(Name, ScopeDef)>530 pub fn scope(
531 self,
532 db: &dyn HirDatabase,
533 visible_from: Option<Module>,
534 ) -> Vec<(Name, ScopeDef)> {
535 self.id.def_map(db.upcast())[self.id.local_id]
536 .scope
537 .entries()
538 .filter_map(|(name, def)| {
539 if let Some(m) = visible_from {
540 let filtered =
541 def.filter_visibility(|vis| vis.is_visible_from(db.upcast(), m.id));
542 if filtered.is_none() && !def.is_none() {
543 None
544 } else {
545 Some((name, filtered))
546 }
547 } else {
548 Some((name, def))
549 }
550 })
551 .flat_map(|(name, def)| {
552 ScopeDef::all_items(def).into_iter().map(move |item| (name.clone(), item))
553 })
554 .collect()
555 }
556
557 /// Fills `acc` with the module's diagnostics.
diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>)558 pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
559 let _p = profile::span("Module::diagnostics").detail(|| {
560 format!(
561 "{:?}",
562 self.name(db)
563 .map_or("<unknown>".into(), |name| name.display(db.upcast()).to_string())
564 )
565 });
566 let def_map = self.id.def_map(db.upcast());
567 for diag in def_map.diagnostics() {
568 if diag.in_module != self.id.local_id {
569 // FIXME: This is accidentally quadratic.
570 continue;
571 }
572 emit_def_diagnostic(db, acc, diag);
573 }
574
575 for decl in self.declarations(db) {
576 match decl {
577 ModuleDef::Module(m) => {
578 // Only add diagnostics from inline modules
579 if def_map[m.id.local_id].origin.is_inline() {
580 m.diagnostics(db, acc)
581 }
582 }
583 ModuleDef::Trait(t) => {
584 for diag in db.trait_data_with_diagnostics(t.id).1.iter() {
585 emit_def_diagnostic(db, acc, diag);
586 }
587 acc.extend(decl.diagnostics(db))
588 }
589 ModuleDef::Adt(adt) => {
590 match adt {
591 Adt::Struct(s) => {
592 for diag in db.struct_data_with_diagnostics(s.id).1.iter() {
593 emit_def_diagnostic(db, acc, diag);
594 }
595 }
596 Adt::Union(u) => {
597 for diag in db.union_data_with_diagnostics(u.id).1.iter() {
598 emit_def_diagnostic(db, acc, diag);
599 }
600 }
601 Adt::Enum(e) => {
602 for v in e.variants(db) {
603 acc.extend(ModuleDef::Variant(v).diagnostics(db));
604 }
605
606 for diag in db.enum_data_with_diagnostics(e.id).1.iter() {
607 emit_def_diagnostic(db, acc, diag);
608 }
609 }
610 }
611 acc.extend(decl.diagnostics(db))
612 }
613 ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m),
614 _ => acc.extend(decl.diagnostics(db)),
615 }
616 }
617 self.legacy_macros(db).into_iter().for_each(|m| emit_macro_def_diagnostics(db, acc, m));
618
619 let inherent_impls = db.inherent_impls_in_crate(self.id.krate());
620
621 for impl_def in self.impl_defs(db) {
622 for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() {
623 emit_def_diagnostic(db, acc, diag);
624 }
625
626 if inherent_impls.invalid_impls().contains(&impl_def.id) {
627 let loc = impl_def.id.lookup(db.upcast());
628 let tree = loc.id.item_tree(db.upcast());
629 let node = &tree[loc.id.value];
630 let file_id = loc.id.file_id();
631 let ast_id_map = db.ast_id_map(file_id);
632
633 acc.push(IncoherentImpl { impl_: ast_id_map.get(node.ast_id()), file_id }.into())
634 }
635
636 for item in impl_def.items(db) {
637 let def: DefWithBody = match item {
638 AssocItem::Function(it) => it.into(),
639 AssocItem::Const(it) => it.into(),
640 AssocItem::TypeAlias(_) => continue,
641 };
642
643 def.diagnostics(db, acc);
644 }
645 }
646 }
647
declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef>648 pub fn declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef> {
649 let def_map = self.id.def_map(db.upcast());
650 let scope = &def_map[self.id.local_id].scope;
651 scope
652 .declarations()
653 .map(ModuleDef::from)
654 .chain(scope.unnamed_consts().map(|id| ModuleDef::Const(Const::from(id))))
655 .collect()
656 }
657
legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro>658 pub fn legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro> {
659 let def_map = self.id.def_map(db.upcast());
660 let scope = &def_map[self.id.local_id].scope;
661 scope.legacy_macros().flat_map(|(_, it)| it).map(|&it| it.into()).collect()
662 }
663
impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl>664 pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {
665 let def_map = self.id.def_map(db.upcast());
666 def_map[self.id.local_id].scope.impls().map(Impl::from).collect()
667 }
668
669 /// Finds a path that can be used to refer to the given item from within
670 /// this module, if possible.
find_use_path( self, db: &dyn DefDatabase, item: impl Into<ItemInNs>, prefer_no_std: bool, ) -> Option<ModPath>671 pub fn find_use_path(
672 self,
673 db: &dyn DefDatabase,
674 item: impl Into<ItemInNs>,
675 prefer_no_std: bool,
676 ) -> Option<ModPath> {
677 hir_def::find_path::find_path(db, item.into().into(), self.into(), prefer_no_std)
678 }
679
680 /// Finds a path that can be used to refer to the given item from within
681 /// this module, if possible. This is used for returning import paths for use-statements.
find_use_path_prefixed( self, db: &dyn DefDatabase, item: impl Into<ItemInNs>, prefix_kind: PrefixKind, prefer_no_std: bool, ) -> Option<ModPath>682 pub fn find_use_path_prefixed(
683 self,
684 db: &dyn DefDatabase,
685 item: impl Into<ItemInNs>,
686 prefix_kind: PrefixKind,
687 prefer_no_std: bool,
688 ) -> Option<ModPath> {
689 hir_def::find_path::find_path_prefixed(
690 db,
691 item.into().into(),
692 self.into(),
693 prefix_kind,
694 prefer_no_std,
695 )
696 }
697 }
698
emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, m: Macro)699 fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, m: Macro) {
700 let id = macro_id_to_def_id(db.upcast(), m.id);
701 if let Err(e) = db.macro_def(id) {
702 let Some(ast) = id.ast_id().left() else {
703 never!("MacroDefError for proc-macro: {:?}", e);
704 return;
705 };
706 emit_def_diagnostic_(
707 db,
708 acc,
709 &DefDiagnosticKind::MacroDefError { ast, message: e.to_string() },
710 );
711 }
712 }
713
emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag: &DefDiagnostic)714 fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag: &DefDiagnostic) {
715 emit_def_diagnostic_(db, acc, &diag.kind)
716 }
717
emit_def_diagnostic_( db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag: &DefDiagnosticKind, )718 fn emit_def_diagnostic_(
719 db: &dyn HirDatabase,
720 acc: &mut Vec<AnyDiagnostic>,
721 diag: &DefDiagnosticKind,
722 ) {
723 match diag {
724 DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates } => {
725 let decl = declaration.to_node(db.upcast());
726 acc.push(
727 UnresolvedModule {
728 decl: InFile::new(declaration.file_id, AstPtr::new(&decl)),
729 candidates: candidates.clone(),
730 }
731 .into(),
732 )
733 }
734 DefDiagnosticKind::UnresolvedExternCrate { ast } => {
735 let item = ast.to_node(db.upcast());
736 acc.push(
737 UnresolvedExternCrate { decl: InFile::new(ast.file_id, AstPtr::new(&item)) }.into(),
738 );
739 }
740
741 DefDiagnosticKind::UnresolvedImport { id, index } => {
742 let file_id = id.file_id();
743 let item_tree = id.item_tree(db.upcast());
744 let import = &item_tree[id.value];
745
746 let use_tree = import.use_tree_to_ast(db.upcast(), file_id, *index);
747 acc.push(
748 UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) }.into(),
749 );
750 }
751
752 DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
753 let item = ast.to_node(db.upcast());
754 acc.push(
755 InactiveCode {
756 node: ast.with_value(AstPtr::new(&item).into()),
757 cfg: cfg.clone(),
758 opts: opts.clone(),
759 }
760 .into(),
761 );
762 }
763 DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => {
764 let (node, precise_location, macro_name, kind) = precise_macro_call_location(ast, db);
765 acc.push(
766 UnresolvedProcMacro { node, precise_location, macro_name, kind, krate: *krate }
767 .into(),
768 );
769 }
770 DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
771 let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
772 acc.push(
773 UnresolvedMacroCall {
774 macro_call: node,
775 precise_location,
776 path: path.clone(),
777 is_bang: matches!(ast, MacroCallKind::FnLike { .. }),
778 }
779 .into(),
780 );
781 }
782 DefDiagnosticKind::MacroError { ast, message } => {
783 let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
784 acc.push(MacroError { node, precise_location, message: message.clone() }.into());
785 }
786 DefDiagnosticKind::MacroExpansionParseError { ast, errors } => {
787 let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
788 acc.push(
789 MacroExpansionParseError { node, precise_location, errors: errors.clone() }.into(),
790 );
791 }
792 DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
793 let node = ast.to_node(db.upcast());
794 // Must have a name, otherwise we wouldn't emit it.
795 let name = node.name().expect("unimplemented builtin macro with no name");
796 acc.push(
797 UnimplementedBuiltinMacro {
798 node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&name))),
799 }
800 .into(),
801 );
802 }
803 DefDiagnosticKind::InvalidDeriveTarget { ast, id } => {
804 let node = ast.to_node(db.upcast());
805 let derive = node.attrs().nth(*id as usize);
806 match derive {
807 Some(derive) => {
808 acc.push(
809 InvalidDeriveTarget {
810 node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
811 }
812 .into(),
813 );
814 }
815 None => stdx::never!("derive diagnostic on item without derive attribute"),
816 }
817 }
818 DefDiagnosticKind::MalformedDerive { ast, id } => {
819 let node = ast.to_node(db.upcast());
820 let derive = node.attrs().nth(*id as usize);
821 match derive {
822 Some(derive) => {
823 acc.push(
824 MalformedDerive {
825 node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
826 }
827 .into(),
828 );
829 }
830 None => stdx::never!("derive diagnostic on item without derive attribute"),
831 }
832 }
833 DefDiagnosticKind::MacroDefError { ast, message } => {
834 let node = ast.to_node(db.upcast());
835 acc.push(
836 MacroDefError {
837 node: InFile::new(ast.file_id, AstPtr::new(&node)),
838 name: node.name().map(|it| it.syntax().text_range()),
839 message: message.clone(),
840 }
841 .into(),
842 );
843 }
844 }
845 }
846
precise_macro_call_location( ast: &MacroCallKind, db: &dyn HirDatabase, ) -> (InFile<SyntaxNodePtr>, Option<TextRange>, Option<String>, MacroKind)847 fn precise_macro_call_location(
848 ast: &MacroCallKind,
849 db: &dyn HirDatabase,
850 ) -> (InFile<SyntaxNodePtr>, Option<TextRange>, Option<String>, MacroKind) {
851 // FIXME: maybe we actually want slightly different ranges for the different macro diagnostics
852 // - e.g. the full attribute for macro errors, but only the name for name resolution
853 match ast {
854 MacroCallKind::FnLike { ast_id, .. } => {
855 let node = ast_id.to_node(db.upcast());
856 (
857 ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
858 node.path()
859 .and_then(|it| it.segment())
860 .and_then(|it| it.name_ref())
861 .map(|it| it.syntax().text_range()),
862 node.path().and_then(|it| it.segment()).map(|it| it.to_string()),
863 MacroKind::ProcMacro,
864 )
865 }
866 MacroCallKind::Derive { ast_id, derive_attr_index, derive_index } => {
867 let node = ast_id.to_node(db.upcast());
868 // Compute the precise location of the macro name's token in the derive
869 // list.
870 let token = (|| {
871 let derive_attr = node
872 .doc_comments_and_attrs()
873 .nth(derive_attr_index.ast_index())
874 .and_then(Either::left)?;
875 let token_tree = derive_attr.meta()?.token_tree()?;
876 let group_by = token_tree
877 .syntax()
878 .children_with_tokens()
879 .filter_map(|elem| match elem {
880 syntax::NodeOrToken::Token(tok) => Some(tok),
881 _ => None,
882 })
883 .group_by(|t| t.kind() == T![,]);
884 let (_, mut group) = group_by
885 .into_iter()
886 .filter(|&(comma, _)| !comma)
887 .nth(*derive_index as usize)?;
888 group.find(|t| t.kind() == T![ident])
889 })();
890 (
891 ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
892 token.as_ref().map(|tok| tok.text_range()),
893 token.as_ref().map(ToString::to_string),
894 MacroKind::Derive,
895 )
896 }
897 MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
898 let node = ast_id.to_node(db.upcast());
899 let attr = node
900 .doc_comments_and_attrs()
901 .nth(invoc_attr_index.ast_index())
902 .and_then(Either::left)
903 .unwrap_or_else(|| {
904 panic!("cannot find attribute #{}", invoc_attr_index.ast_index())
905 });
906
907 (
908 ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
909 Some(attr.syntax().text_range()),
910 attr.path()
911 .and_then(|path| path.segment())
912 .and_then(|seg| seg.name_ref())
913 .as_ref()
914 .map(ToString::to_string),
915 MacroKind::Attr,
916 )
917 }
918 }
919 }
920
921 impl HasVisibility for Module {
visibility(&self, db: &dyn HirDatabase) -> Visibility922 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
923 let def_map = self.id.def_map(db.upcast());
924 let module_data = &def_map[self.id.local_id];
925 module_data.visibility
926 }
927 }
928
929 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
930 pub struct Field {
931 pub(crate) parent: VariantDef,
932 pub(crate) id: LocalFieldId,
933 }
934
935 #[derive(Debug, PartialEq, Eq)]
936 pub enum FieldSource {
937 Named(ast::RecordField),
938 Pos(ast::TupleField),
939 }
940
941 impl Field {
name(&self, db: &dyn HirDatabase) -> Name942 pub fn name(&self, db: &dyn HirDatabase) -> Name {
943 self.parent.variant_data(db).fields()[self.id].name.clone()
944 }
945
index(&self) -> usize946 pub fn index(&self) -> usize {
947 u32::from(self.id.into_raw()) as usize
948 }
949
950 /// Returns the type as in the signature of the struct (i.e., with
951 /// placeholder types for type parameters). Only use this in the context of
952 /// the field definition.
ty(&self, db: &dyn HirDatabase) -> Type953 pub fn ty(&self, db: &dyn HirDatabase) -> Type {
954 let var_id = self.parent.into();
955 let generic_def_id: GenericDefId = match self.parent {
956 VariantDef::Struct(it) => it.id.into(),
957 VariantDef::Union(it) => it.id.into(),
958 VariantDef::Variant(it) => it.parent.id.into(),
959 };
960 let substs = TyBuilder::placeholder_subst(db, generic_def_id);
961 let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs);
962 Type::new(db, var_id, ty)
963 }
964
layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError>965 pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
966 db.layout_of_ty(self.ty(db).ty.clone(), self.parent.module(db).krate().into())
967 .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
968 }
969
parent_def(&self, _db: &dyn HirDatabase) -> VariantDef970 pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
971 self.parent
972 }
973 }
974
975 impl HasVisibility for Field {
visibility(&self, db: &dyn HirDatabase) -> Visibility976 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
977 let variant_data = self.parent.variant_data(db);
978 let visibility = &variant_data.fields()[self.id].visibility;
979 let parent_id: hir_def::VariantId = self.parent.into();
980 visibility.resolve(db.upcast(), &parent_id.resolver(db.upcast()))
981 }
982 }
983
984 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
985 pub struct Struct {
986 pub(crate) id: StructId,
987 }
988
989 impl Struct {
module(self, db: &dyn HirDatabase) -> Module990 pub fn module(self, db: &dyn HirDatabase) -> Module {
991 Module { id: self.id.lookup(db.upcast()).container }
992 }
993
name(self, db: &dyn HirDatabase) -> Name994 pub fn name(self, db: &dyn HirDatabase) -> Name {
995 db.struct_data(self.id).name.clone()
996 }
997
fields(self, db: &dyn HirDatabase) -> Vec<Field>998 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
999 db.struct_data(self.id)
1000 .variant_data
1001 .fields()
1002 .iter()
1003 .map(|(id, _)| Field { parent: self.into(), id })
1004 .collect()
1005 }
1006
ty(self, db: &dyn HirDatabase) -> Type1007 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1008 Type::from_def(db, self.id)
1009 }
1010
constructor_ty(self, db: &dyn HirDatabase) -> Type1011 pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
1012 Type::from_value_def(db, self.id)
1013 }
1014
repr(self, db: &dyn HirDatabase) -> Option<ReprOptions>1015 pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
1016 db.struct_data(self.id).repr
1017 }
1018
kind(self, db: &dyn HirDatabase) -> StructKind1019 pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
1020 self.variant_data(db).kind()
1021 }
1022
variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData>1023 fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
1024 db.struct_data(self.id).variant_data.clone()
1025 }
1026 }
1027
1028 impl HasVisibility for Struct {
visibility(&self, db: &dyn HirDatabase) -> Visibility1029 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1030 db.struct_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1031 }
1032 }
1033
1034 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1035 pub struct Union {
1036 pub(crate) id: UnionId,
1037 }
1038
1039 impl Union {
name(self, db: &dyn HirDatabase) -> Name1040 pub fn name(self, db: &dyn HirDatabase) -> Name {
1041 db.union_data(self.id).name.clone()
1042 }
1043
module(self, db: &dyn HirDatabase) -> Module1044 pub fn module(self, db: &dyn HirDatabase) -> Module {
1045 Module { id: self.id.lookup(db.upcast()).container }
1046 }
1047
ty(self, db: &dyn HirDatabase) -> Type1048 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1049 Type::from_def(db, self.id)
1050 }
1051
constructor_ty(self, db: &dyn HirDatabase) -> Type1052 pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
1053 Type::from_value_def(db, self.id)
1054 }
1055
fields(self, db: &dyn HirDatabase) -> Vec<Field>1056 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
1057 db.union_data(self.id)
1058 .variant_data
1059 .fields()
1060 .iter()
1061 .map(|(id, _)| Field { parent: self.into(), id })
1062 .collect()
1063 }
1064
variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData>1065 fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
1066 db.union_data(self.id).variant_data.clone()
1067 }
1068 }
1069
1070 impl HasVisibility for Union {
visibility(&self, db: &dyn HirDatabase) -> Visibility1071 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1072 db.union_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1073 }
1074 }
1075
1076 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1077 pub struct Enum {
1078 pub(crate) id: EnumId,
1079 }
1080
1081 impl Enum {
module(self, db: &dyn HirDatabase) -> Module1082 pub fn module(self, db: &dyn HirDatabase) -> Module {
1083 Module { id: self.id.lookup(db.upcast()).container }
1084 }
1085
name(self, db: &dyn HirDatabase) -> Name1086 pub fn name(self, db: &dyn HirDatabase) -> Name {
1087 db.enum_data(self.id).name.clone()
1088 }
1089
variants(self, db: &dyn HirDatabase) -> Vec<Variant>1090 pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> {
1091 db.enum_data(self.id).variants.iter().map(|(id, _)| Variant { parent: self, id }).collect()
1092 }
1093
repr(self, db: &dyn HirDatabase) -> Option<ReprOptions>1094 pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
1095 db.enum_data(self.id).repr
1096 }
1097
ty(self, db: &dyn HirDatabase) -> Type1098 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1099 Type::from_def(db, self.id)
1100 }
1101
1102 /// The type of the enum variant bodies.
variant_body_ty(self, db: &dyn HirDatabase) -> Type1103 pub fn variant_body_ty(self, db: &dyn HirDatabase) -> Type {
1104 Type::new_for_crate(
1105 self.id.lookup(db.upcast()).container.krate(),
1106 TyBuilder::builtin(match db.enum_data(self.id).variant_body_type() {
1107 layout::IntegerType::Pointer(sign) => match sign {
1108 true => hir_def::builtin_type::BuiltinType::Int(
1109 hir_def::builtin_type::BuiltinInt::Isize,
1110 ),
1111 false => hir_def::builtin_type::BuiltinType::Uint(
1112 hir_def::builtin_type::BuiltinUint::Usize,
1113 ),
1114 },
1115 layout::IntegerType::Fixed(i, sign) => match sign {
1116 true => hir_def::builtin_type::BuiltinType::Int(match i {
1117 layout::Integer::I8 => hir_def::builtin_type::BuiltinInt::I8,
1118 layout::Integer::I16 => hir_def::builtin_type::BuiltinInt::I16,
1119 layout::Integer::I32 => hir_def::builtin_type::BuiltinInt::I32,
1120 layout::Integer::I64 => hir_def::builtin_type::BuiltinInt::I64,
1121 layout::Integer::I128 => hir_def::builtin_type::BuiltinInt::I128,
1122 }),
1123 false => hir_def::builtin_type::BuiltinType::Uint(match i {
1124 layout::Integer::I8 => hir_def::builtin_type::BuiltinUint::U8,
1125 layout::Integer::I16 => hir_def::builtin_type::BuiltinUint::U16,
1126 layout::Integer::I32 => hir_def::builtin_type::BuiltinUint::U32,
1127 layout::Integer::I64 => hir_def::builtin_type::BuiltinUint::U64,
1128 layout::Integer::I128 => hir_def::builtin_type::BuiltinUint::U128,
1129 }),
1130 },
1131 }),
1132 )
1133 }
1134
1135 /// Returns true if at least one variant of this enum is a non-unit variant.
is_data_carrying(self, db: &dyn HirDatabase) -> bool1136 pub fn is_data_carrying(self, db: &dyn HirDatabase) -> bool {
1137 self.variants(db).iter().any(|v| !matches!(v.kind(db), StructKind::Unit))
1138 }
1139
layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError>1140 pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
1141 Adt::from(self).layout(db)
1142 }
1143 }
1144
1145 impl HasVisibility for Enum {
visibility(&self, db: &dyn HirDatabase) -> Visibility1146 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1147 db.enum_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1148 }
1149 }
1150
1151 impl From<&Variant> for DefWithBodyId {
from(&v: &Variant) -> Self1152 fn from(&v: &Variant) -> Self {
1153 DefWithBodyId::VariantId(v.into())
1154 }
1155 }
1156
1157 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1158 pub struct Variant {
1159 pub(crate) parent: Enum,
1160 pub(crate) id: LocalEnumVariantId,
1161 }
1162
1163 impl Variant {
module(self, db: &dyn HirDatabase) -> Module1164 pub fn module(self, db: &dyn HirDatabase) -> Module {
1165 self.parent.module(db)
1166 }
1167
parent_enum(self, _db: &dyn HirDatabase) -> Enum1168 pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum {
1169 self.parent
1170 }
1171
constructor_ty(self, db: &dyn HirDatabase) -> Type1172 pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
1173 Type::from_value_def(db, EnumVariantId { parent: self.parent.id, local_id: self.id })
1174 }
1175
name(self, db: &dyn HirDatabase) -> Name1176 pub fn name(self, db: &dyn HirDatabase) -> Name {
1177 db.enum_data(self.parent.id).variants[self.id].name.clone()
1178 }
1179
fields(self, db: &dyn HirDatabase) -> Vec<Field>1180 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
1181 self.variant_data(db)
1182 .fields()
1183 .iter()
1184 .map(|(id, _)| Field { parent: self.into(), id })
1185 .collect()
1186 }
1187
kind(self, db: &dyn HirDatabase) -> StructKind1188 pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
1189 self.variant_data(db).kind()
1190 }
1191
variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData>1192 pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
1193 db.enum_data(self.parent.id).variants[self.id].variant_data.clone()
1194 }
1195
value(self, db: &dyn HirDatabase) -> Option<ast::Expr>1196 pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
1197 self.source(db)?.value.expr()
1198 }
1199
eval(self, db: &dyn HirDatabase) -> Result<i128, ConstEvalError>1200 pub fn eval(self, db: &dyn HirDatabase) -> Result<i128, ConstEvalError> {
1201 db.const_eval_discriminant(self.into())
1202 }
1203
layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError>1204 pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
1205 let parent_enum = self.parent_enum(db);
1206 let parent_layout = parent_enum.layout(db)?;
1207 Ok(match &parent_layout.0.variants {
1208 layout::Variants::Multiple { variants, .. } => Layout(
1209 Arc::new(variants[RustcEnumVariantIdx(self.id)].clone()),
1210 db.target_data_layout(parent_enum.krate(db).into()).unwrap(),
1211 ),
1212 _ => parent_layout,
1213 })
1214 }
1215 }
1216
1217 /// Variants inherit visibility from the parent enum.
1218 impl HasVisibility for Variant {
visibility(&self, db: &dyn HirDatabase) -> Visibility1219 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1220 self.parent_enum(db).visibility(db)
1221 }
1222 }
1223
1224 /// A Data Type
1225 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1226 pub enum Adt {
1227 Struct(Struct),
1228 Union(Union),
1229 Enum(Enum),
1230 }
1231 impl_from!(Struct, Union, Enum for Adt);
1232
1233 impl Adt {
has_non_default_type_params(self, db: &dyn HirDatabase) -> bool1234 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
1235 let subst = db.generic_defaults(self.into());
1236 subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
1237 GenericArgData::Ty(x) => x.is_unknown(),
1238 _ => false,
1239 })
1240 }
1241
layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError>1242 pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
1243 if db.generic_params(self.into()).iter().count() != 0 {
1244 return Err(LayoutError::HasPlaceholder);
1245 }
1246 let krate = self.krate(db).id;
1247 db.layout_of_adt(self.into(), Substitution::empty(Interner), krate)
1248 .map(|layout| Layout(layout, db.target_data_layout(krate).unwrap()))
1249 }
1250
1251 /// Turns this ADT into a type. Any type parameters of the ADT will be
1252 /// turned into unknown types, which is good for e.g. finding the most
1253 /// general set of completions, but will not look very nice when printed.
ty(self, db: &dyn HirDatabase) -> Type1254 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1255 let id = AdtId::from(self);
1256 Type::from_def(db, id)
1257 }
1258
1259 /// Turns this ADT into a type with the given type parameters. This isn't
1260 /// the greatest API, FIXME find a better one.
ty_with_args(self, db: &dyn HirDatabase, args: &[Type]) -> Type1261 pub fn ty_with_args(self, db: &dyn HirDatabase, args: &[Type]) -> Type {
1262 let id = AdtId::from(self);
1263 let mut it = args.iter().map(|t| t.ty.clone());
1264 let ty = TyBuilder::def_ty(db, id.into(), None)
1265 .fill(|x| {
1266 let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
1267 match x {
1268 ParamKind::Type => GenericArgData::Ty(r).intern(Interner),
1269 ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
1270 }
1271 })
1272 .build();
1273 Type::new(db, id, ty)
1274 }
1275
module(self, db: &dyn HirDatabase) -> Module1276 pub fn module(self, db: &dyn HirDatabase) -> Module {
1277 match self {
1278 Adt::Struct(s) => s.module(db),
1279 Adt::Union(s) => s.module(db),
1280 Adt::Enum(e) => e.module(db),
1281 }
1282 }
1283
name(self, db: &dyn HirDatabase) -> Name1284 pub fn name(self, db: &dyn HirDatabase) -> Name {
1285 match self {
1286 Adt::Struct(s) => s.name(db),
1287 Adt::Union(u) => u.name(db),
1288 Adt::Enum(e) => e.name(db),
1289 }
1290 }
1291
1292 /// Returns the lifetime of the DataType
lifetime(&self, db: &dyn HirDatabase) -> Option<LifetimeParamData>1293 pub fn lifetime(&self, db: &dyn HirDatabase) -> Option<LifetimeParamData> {
1294 let resolver = match self {
1295 Adt::Struct(s) => s.id.resolver(db.upcast()),
1296 Adt::Union(u) => u.id.resolver(db.upcast()),
1297 Adt::Enum(e) => e.id.resolver(db.upcast()),
1298 };
1299 resolver
1300 .generic_params()
1301 .and_then(|gp| {
1302 (&gp.lifetimes)
1303 .iter()
1304 // there should only be a single lifetime
1305 // but `Arena` requires to use an iterator
1306 .nth(0)
1307 })
1308 .map(|arena| arena.1.clone())
1309 }
1310
as_enum(&self) -> Option<Enum>1311 pub fn as_enum(&self) -> Option<Enum> {
1312 if let Self::Enum(v) = self {
1313 Some(*v)
1314 } else {
1315 None
1316 }
1317 }
1318 }
1319
1320 impl HasVisibility for Adt {
visibility(&self, db: &dyn HirDatabase) -> Visibility1321 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1322 match self {
1323 Adt::Struct(it) => it.visibility(db),
1324 Adt::Union(it) => it.visibility(db),
1325 Adt::Enum(it) => it.visibility(db),
1326 }
1327 }
1328 }
1329
1330 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1331 pub enum VariantDef {
1332 Struct(Struct),
1333 Union(Union),
1334 Variant(Variant),
1335 }
1336 impl_from!(Struct, Union, Variant for VariantDef);
1337
1338 impl VariantDef {
fields(self, db: &dyn HirDatabase) -> Vec<Field>1339 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
1340 match self {
1341 VariantDef::Struct(it) => it.fields(db),
1342 VariantDef::Union(it) => it.fields(db),
1343 VariantDef::Variant(it) => it.fields(db),
1344 }
1345 }
1346
module(self, db: &dyn HirDatabase) -> Module1347 pub fn module(self, db: &dyn HirDatabase) -> Module {
1348 match self {
1349 VariantDef::Struct(it) => it.module(db),
1350 VariantDef::Union(it) => it.module(db),
1351 VariantDef::Variant(it) => it.module(db),
1352 }
1353 }
1354
name(&self, db: &dyn HirDatabase) -> Name1355 pub fn name(&self, db: &dyn HirDatabase) -> Name {
1356 match self {
1357 VariantDef::Struct(s) => s.name(db),
1358 VariantDef::Union(u) => u.name(db),
1359 VariantDef::Variant(e) => e.name(db),
1360 }
1361 }
1362
variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData>1363 pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
1364 match self {
1365 VariantDef::Struct(it) => it.variant_data(db),
1366 VariantDef::Union(it) => it.variant_data(db),
1367 VariantDef::Variant(it) => it.variant_data(db),
1368 }
1369 }
1370 }
1371
1372 /// The defs which have a body.
1373 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1374 pub enum DefWithBody {
1375 Function(Function),
1376 Static(Static),
1377 Const(Const),
1378 Variant(Variant),
1379 InTypeConst(InTypeConst),
1380 }
1381 impl_from!(Function, Const, Static, Variant, InTypeConst for DefWithBody);
1382
1383 impl DefWithBody {
module(self, db: &dyn HirDatabase) -> Module1384 pub fn module(self, db: &dyn HirDatabase) -> Module {
1385 match self {
1386 DefWithBody::Const(c) => c.module(db),
1387 DefWithBody::Function(f) => f.module(db),
1388 DefWithBody::Static(s) => s.module(db),
1389 DefWithBody::Variant(v) => v.module(db),
1390 DefWithBody::InTypeConst(c) => c.module(db),
1391 }
1392 }
1393
name(self, db: &dyn HirDatabase) -> Option<Name>1394 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
1395 match self {
1396 DefWithBody::Function(f) => Some(f.name(db)),
1397 DefWithBody::Static(s) => Some(s.name(db)),
1398 DefWithBody::Const(c) => c.name(db),
1399 DefWithBody::Variant(v) => Some(v.name(db)),
1400 DefWithBody::InTypeConst(_) => None,
1401 }
1402 }
1403
1404 /// Returns the type this def's body has to evaluate to.
body_type(self, db: &dyn HirDatabase) -> Type1405 pub fn body_type(self, db: &dyn HirDatabase) -> Type {
1406 match self {
1407 DefWithBody::Function(it) => it.ret_type(db),
1408 DefWithBody::Static(it) => it.ty(db),
1409 DefWithBody::Const(it) => it.ty(db),
1410 DefWithBody::Variant(it) => it.parent.variant_body_ty(db),
1411 DefWithBody::InTypeConst(it) => Type::new_with_resolver_inner(
1412 db,
1413 &DefWithBodyId::from(it.id).resolver(db.upcast()),
1414 TyKind::Error.intern(Interner),
1415 ),
1416 }
1417 }
1418
id(&self) -> DefWithBodyId1419 fn id(&self) -> DefWithBodyId {
1420 match self {
1421 DefWithBody::Function(it) => it.id.into(),
1422 DefWithBody::Static(it) => it.id.into(),
1423 DefWithBody::Const(it) => it.id.into(),
1424 DefWithBody::Variant(it) => it.into(),
1425 DefWithBody::InTypeConst(it) => it.id.into(),
1426 }
1427 }
1428
1429 /// A textual representation of the HIR of this def's body for debugging purposes.
debug_hir(self, db: &dyn HirDatabase) -> String1430 pub fn debug_hir(self, db: &dyn HirDatabase) -> String {
1431 let body = db.body(self.id());
1432 body.pretty_print(db.upcast(), self.id())
1433 }
1434
1435 /// A textual representation of the MIR of this def's body for debugging purposes.
debug_mir(self, db: &dyn HirDatabase) -> String1436 pub fn debug_mir(self, db: &dyn HirDatabase) -> String {
1437 let body = db.mir_body(self.id());
1438 match body {
1439 Ok(body) => body.pretty_print(db),
1440 Err(e) => format!("error:\n{e:?}"),
1441 }
1442 }
1443
diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>)1444 pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
1445 let krate = self.module(db).id.krate();
1446
1447 let (body, source_map) = db.body_with_source_map(self.into());
1448
1449 for (_, def_map) in body.blocks(db.upcast()) {
1450 for diag in def_map.diagnostics() {
1451 emit_def_diagnostic(db, acc, diag);
1452 }
1453 }
1454
1455 for diag in source_map.diagnostics() {
1456 match diag {
1457 BodyDiagnostic::InactiveCode { node, cfg, opts } => acc.push(
1458 InactiveCode { node: node.clone(), cfg: cfg.clone(), opts: opts.clone() }
1459 .into(),
1460 ),
1461 BodyDiagnostic::MacroError { node, message } => acc.push(
1462 MacroError {
1463 node: node.clone().map(|it| it.into()),
1464 precise_location: None,
1465 message: message.to_string(),
1466 }
1467 .into(),
1468 ),
1469 BodyDiagnostic::UnresolvedProcMacro { node, krate } => acc.push(
1470 UnresolvedProcMacro {
1471 node: node.clone().map(|it| it.into()),
1472 precise_location: None,
1473 macro_name: None,
1474 kind: MacroKind::ProcMacro,
1475 krate: *krate,
1476 }
1477 .into(),
1478 ),
1479 BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push(
1480 UnresolvedMacroCall {
1481 macro_call: node.clone().map(|ast_ptr| ast_ptr.into()),
1482 precise_location: None,
1483 path: path.clone(),
1484 is_bang: true,
1485 }
1486 .into(),
1487 ),
1488 BodyDiagnostic::UnreachableLabel { node, name } => {
1489 acc.push(UnreachableLabel { node: node.clone(), name: name.clone() }.into())
1490 }
1491 BodyDiagnostic::UndeclaredLabel { node, name } => {
1492 acc.push(UndeclaredLabel { node: node.clone(), name: name.clone() }.into())
1493 }
1494 }
1495 }
1496
1497 let infer = db.infer(self.into());
1498 let source_map = Lazy::new(|| db.body_with_source_map(self.into()).1);
1499 let expr_syntax = |expr| source_map.expr_syntax(expr).expect("unexpected synthetic");
1500 for d in &infer.diagnostics {
1501 match d {
1502 &hir_ty::InferenceDiagnostic::NoSuchField { expr } => {
1503 let field = source_map.field_syntax(expr);
1504 acc.push(NoSuchField { field }.into())
1505 }
1506 &hir_ty::InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => {
1507 acc.push(
1508 MismatchedArgCount { call_expr: expr_syntax(call_expr), expected, found }
1509 .into(),
1510 )
1511 }
1512 &hir_ty::InferenceDiagnostic::PrivateField { expr, field } => {
1513 let expr = expr_syntax(expr);
1514 let field = field.into();
1515 acc.push(PrivateField { expr, field }.into())
1516 }
1517 &hir_ty::InferenceDiagnostic::PrivateAssocItem { id, item } => {
1518 let expr_or_pat = match id {
1519 ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(Either::Left),
1520 ExprOrPatId::PatId(pat) => source_map
1521 .pat_syntax(pat)
1522 .expect("unexpected synthetic")
1523 .map(Either::Right),
1524 };
1525 let item = item.into();
1526 acc.push(PrivateAssocItem { expr_or_pat, item }.into())
1527 }
1528 hir_ty::InferenceDiagnostic::ExpectedFunction { call_expr, found } => {
1529 let call_expr = expr_syntax(*call_expr);
1530
1531 acc.push(
1532 ExpectedFunction {
1533 call: call_expr,
1534 found: Type::new(db, DefWithBodyId::from(self), found.clone()),
1535 }
1536 .into(),
1537 )
1538 }
1539 hir_ty::InferenceDiagnostic::UnresolvedField {
1540 expr,
1541 receiver,
1542 name,
1543 method_with_same_name_exists,
1544 } => {
1545 let expr = expr_syntax(*expr);
1546
1547 acc.push(
1548 UnresolvedField {
1549 expr,
1550 name: name.clone(),
1551 receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()),
1552 method_with_same_name_exists: *method_with_same_name_exists,
1553 }
1554 .into(),
1555 )
1556 }
1557 hir_ty::InferenceDiagnostic::UnresolvedMethodCall {
1558 expr,
1559 receiver,
1560 name,
1561 field_with_same_name,
1562 } => {
1563 let expr = expr_syntax(*expr);
1564
1565 acc.push(
1566 UnresolvedMethodCall {
1567 expr,
1568 name: name.clone(),
1569 receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()),
1570 field_with_same_name: field_with_same_name
1571 .clone()
1572 .map(|ty| Type::new(db, DefWithBodyId::from(self), ty)),
1573 }
1574 .into(),
1575 )
1576 }
1577 &hir_ty::InferenceDiagnostic::BreakOutsideOfLoop {
1578 expr,
1579 is_break,
1580 bad_value_break,
1581 } => {
1582 let expr = expr_syntax(expr);
1583 acc.push(BreakOutsideOfLoop { expr, is_break, bad_value_break }.into())
1584 }
1585 hir_ty::InferenceDiagnostic::TypedHole { expr, expected } => {
1586 let expr = expr_syntax(*expr);
1587 acc.push(
1588 TypedHole {
1589 expr,
1590 expected: Type::new(db, DefWithBodyId::from(self), expected.clone()),
1591 }
1592 .into(),
1593 )
1594 }
1595 }
1596 }
1597 for (pat_or_expr, mismatch) in infer.type_mismatches() {
1598 let expr_or_pat = match pat_or_expr {
1599 ExprOrPatId::ExprId(expr) => source_map.expr_syntax(expr).map(Either::Left),
1600 ExprOrPatId::PatId(pat) => source_map.pat_syntax(pat).map(Either::Right),
1601 };
1602 let expr_or_pat = match expr_or_pat {
1603 Ok(Either::Left(expr)) => Either::Left(expr),
1604 Ok(Either::Right(InFile { file_id, value: Either::Left(pat) })) => {
1605 Either::Right(InFile { file_id, value: pat })
1606 }
1607 Ok(Either::Right(_)) | Err(SyntheticSyntax) => continue,
1608 };
1609
1610 acc.push(
1611 TypeMismatch {
1612 expr_or_pat,
1613 expected: Type::new(db, DefWithBodyId::from(self), mismatch.expected.clone()),
1614 actual: Type::new(db, DefWithBodyId::from(self), mismatch.actual.clone()),
1615 }
1616 .into(),
1617 );
1618 }
1619
1620 for expr in hir_ty::diagnostics::missing_unsafe(db, self.into()) {
1621 match source_map.expr_syntax(expr) {
1622 Ok(expr) => acc.push(MissingUnsafe { expr }.into()),
1623 Err(SyntheticSyntax) => {
1624 // FIXME: Here and elsewhere in this file, the `expr` was
1625 // desugared, report or assert that this doesn't happen.
1626 }
1627 }
1628 }
1629
1630 let hir_body = db.body(self.into());
1631
1632 if let Ok(borrowck_results) = db.borrowck(self.into()) {
1633 for borrowck_result in borrowck_results.iter() {
1634 let mir_body = &borrowck_result.mir_body;
1635 for moof in &borrowck_result.moved_out_of_ref {
1636 let span: InFile<SyntaxNodePtr> = match moof.span {
1637 mir::MirSpan::ExprId(e) => match source_map.expr_syntax(e) {
1638 Ok(s) => s.map(|x| x.into()),
1639 Err(_) => continue,
1640 },
1641 mir::MirSpan::PatId(p) => match source_map.pat_syntax(p) {
1642 Ok(s) => s.map(|x| match x {
1643 Either::Left(e) => e.into(),
1644 Either::Right(e) => e.into(),
1645 }),
1646 Err(_) => continue,
1647 },
1648 mir::MirSpan::Unknown => continue,
1649 };
1650 acc.push(
1651 MovedOutOfRef { ty: Type::new_for_crate(krate, moof.ty.clone()), span }
1652 .into(),
1653 )
1654 }
1655 let mol = &borrowck_result.mutability_of_locals;
1656 for (binding_id, binding_data) in hir_body.bindings.iter() {
1657 if binding_data.problems.is_some() {
1658 // We should report specific diagnostics for these problems, not `need-mut` and `unused-mut`.
1659 continue;
1660 }
1661 let Some(&local) = mir_body.binding_locals.get(binding_id) else {
1662 continue;
1663 };
1664 let need_mut = &mol[local];
1665 let local = Local { parent: self.into(), binding_id };
1666 match (need_mut, local.is_mut(db)) {
1667 (mir::MutabilityReason::Mut { .. }, true)
1668 | (mir::MutabilityReason::Not, false) => (),
1669 (mir::MutabilityReason::Mut { spans }, false) => {
1670 for span in spans {
1671 let span: InFile<SyntaxNodePtr> = match span {
1672 mir::MirSpan::ExprId(e) => match source_map.expr_syntax(*e) {
1673 Ok(s) => s.map(|x| x.into()),
1674 Err(_) => continue,
1675 },
1676 mir::MirSpan::PatId(p) => match source_map.pat_syntax(*p) {
1677 Ok(s) => s.map(|x| match x {
1678 Either::Left(e) => e.into(),
1679 Either::Right(e) => e.into(),
1680 }),
1681 Err(_) => continue,
1682 },
1683 mir::MirSpan::Unknown => continue,
1684 };
1685 acc.push(NeedMut { local, span }.into());
1686 }
1687 }
1688 (mir::MutabilityReason::Not, true) => {
1689 if !infer.mutated_bindings_in_closure.contains(&binding_id) {
1690 let should_ignore = matches!(body[binding_id].name.as_str(), Some(x) if x.starts_with("_"));
1691 if !should_ignore {
1692 acc.push(UnusedMut { local }.into())
1693 }
1694 }
1695 }
1696 }
1697 }
1698 }
1699 }
1700
1701 for diagnostic in BodyValidationDiagnostic::collect(db, self.into()) {
1702 match diagnostic {
1703 BodyValidationDiagnostic::RecordMissingFields {
1704 record,
1705 variant,
1706 missed_fields,
1707 } => {
1708 let variant_data = variant.variant_data(db.upcast());
1709 let missed_fields = missed_fields
1710 .into_iter()
1711 .map(|idx| variant_data.fields()[idx].name.clone())
1712 .collect();
1713
1714 match record {
1715 Either::Left(record_expr) => match source_map.expr_syntax(record_expr) {
1716 Ok(source_ptr) => {
1717 let root = source_ptr.file_syntax(db.upcast());
1718 if let ast::Expr::RecordExpr(record_expr) =
1719 &source_ptr.value.to_node(&root)
1720 {
1721 if record_expr.record_expr_field_list().is_some() {
1722 acc.push(
1723 MissingFields {
1724 file: source_ptr.file_id,
1725 field_list_parent: Either::Left(AstPtr::new(
1726 record_expr,
1727 )),
1728 field_list_parent_path: record_expr
1729 .path()
1730 .map(|path| AstPtr::new(&path)),
1731 missed_fields,
1732 }
1733 .into(),
1734 )
1735 }
1736 }
1737 }
1738 Err(SyntheticSyntax) => (),
1739 },
1740 Either::Right(record_pat) => match source_map.pat_syntax(record_pat) {
1741 Ok(source_ptr) => {
1742 if let Some(expr) = source_ptr.value.as_ref().left() {
1743 let root = source_ptr.file_syntax(db.upcast());
1744 if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) {
1745 if record_pat.record_pat_field_list().is_some() {
1746 acc.push(
1747 MissingFields {
1748 file: source_ptr.file_id,
1749 field_list_parent: Either::Right(AstPtr::new(
1750 &record_pat,
1751 )),
1752 field_list_parent_path: record_pat
1753 .path()
1754 .map(|path| AstPtr::new(&path)),
1755 missed_fields,
1756 }
1757 .into(),
1758 )
1759 }
1760 }
1761 }
1762 }
1763 Err(SyntheticSyntax) => (),
1764 },
1765 }
1766 }
1767 BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap { method_call_expr } => {
1768 if let Ok(next_source_ptr) = source_map.expr_syntax(method_call_expr) {
1769 acc.push(
1770 ReplaceFilterMapNextWithFindMap {
1771 file: next_source_ptr.file_id,
1772 next_expr: next_source_ptr.value,
1773 }
1774 .into(),
1775 );
1776 }
1777 }
1778 BodyValidationDiagnostic::MissingMatchArms { match_expr, uncovered_patterns } => {
1779 match source_map.expr_syntax(match_expr) {
1780 Ok(source_ptr) => {
1781 let root = source_ptr.file_syntax(db.upcast());
1782 if let ast::Expr::MatchExpr(match_expr) =
1783 &source_ptr.value.to_node(&root)
1784 {
1785 if let Some(scrut_expr) = match_expr.expr() {
1786 acc.push(
1787 MissingMatchArms {
1788 scrutinee_expr: InFile::new(
1789 source_ptr.file_id,
1790 AstPtr::new(&scrut_expr),
1791 ),
1792 uncovered_patterns,
1793 }
1794 .into(),
1795 );
1796 }
1797 }
1798 }
1799 Err(SyntheticSyntax) => (),
1800 }
1801 }
1802 }
1803 }
1804
1805 let def: ModuleDef = match self {
1806 DefWithBody::Function(it) => it.into(),
1807 DefWithBody::Static(it) => it.into(),
1808 DefWithBody::Const(it) => it.into(),
1809 DefWithBody::Variant(it) => it.into(),
1810 // FIXME: don't ignore diagnostics for in type const
1811 DefWithBody::InTypeConst(_) => return,
1812 };
1813 for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) {
1814 acc.push(diag.into())
1815 }
1816 }
1817 }
1818
1819 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1820 pub struct Function {
1821 pub(crate) id: FunctionId,
1822 }
1823
1824 impl Function {
module(self, db: &dyn HirDatabase) -> Module1825 pub fn module(self, db: &dyn HirDatabase) -> Module {
1826 self.id.lookup(db.upcast()).module(db.upcast()).into()
1827 }
1828
name(self, db: &dyn HirDatabase) -> Name1829 pub fn name(self, db: &dyn HirDatabase) -> Name {
1830 db.function_data(self.id).name.clone()
1831 }
1832
ty(self, db: &dyn HirDatabase) -> Type1833 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1834 Type::from_value_def(db, self.id)
1835 }
1836
1837 /// Get this function's return type
ret_type(self, db: &dyn HirDatabase) -> Type1838 pub fn ret_type(self, db: &dyn HirDatabase) -> Type {
1839 let resolver = self.id.resolver(db.upcast());
1840 let substs = TyBuilder::placeholder_subst(db, self.id);
1841 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
1842 let ty = callable_sig.ret().clone();
1843 Type::new_with_resolver_inner(db, &resolver, ty)
1844 }
1845
async_ret_type(self, db: &dyn HirDatabase) -> Option<Type>1846 pub fn async_ret_type(self, db: &dyn HirDatabase) -> Option<Type> {
1847 if !self.is_async(db) {
1848 return None;
1849 }
1850 let resolver = self.id.resolver(db.upcast());
1851 let substs = TyBuilder::placeholder_subst(db, self.id);
1852 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
1853 let ret_ty = callable_sig.ret().clone();
1854 for pred in ret_ty.impl_trait_bounds(db).into_iter().flatten() {
1855 if let WhereClause::AliasEq(output_eq) = pred.into_value_and_skipped_binders().0 {
1856 return Type::new_with_resolver_inner(db, &resolver, output_eq.ty).into();
1857 }
1858 }
1859 never!("Async fn ret_type should be impl Future");
1860 None
1861 }
1862
has_self_param(self, db: &dyn HirDatabase) -> bool1863 pub fn has_self_param(self, db: &dyn HirDatabase) -> bool {
1864 db.function_data(self.id).has_self_param()
1865 }
1866
self_param(self, db: &dyn HirDatabase) -> Option<SelfParam>1867 pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
1868 self.has_self_param(db).then_some(SelfParam { func: self.id })
1869 }
1870
assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param>1871 pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param> {
1872 let environment = db.trait_environment(self.id.into());
1873 let substs = TyBuilder::placeholder_subst(db, self.id);
1874 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
1875 callable_sig
1876 .params()
1877 .iter()
1878 .enumerate()
1879 .map(|(idx, ty)| {
1880 let ty = Type { env: environment.clone(), ty: ty.clone() };
1881 Param { func: self, ty, idx }
1882 })
1883 .collect()
1884 }
1885
num_params(self, db: &dyn HirDatabase) -> usize1886 pub fn num_params(self, db: &dyn HirDatabase) -> usize {
1887 db.function_data(self.id).params.len()
1888 }
1889
method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>>1890 pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> {
1891 if self.self_param(db).is_none() {
1892 return None;
1893 }
1894 Some(self.params_without_self(db))
1895 }
1896
params_without_self(self, db: &dyn HirDatabase) -> Vec<Param>1897 pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec<Param> {
1898 let environment = db.trait_environment(self.id.into());
1899 let substs = TyBuilder::placeholder_subst(db, self.id);
1900 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
1901 let skip = if db.function_data(self.id).has_self_param() { 1 } else { 0 };
1902 callable_sig
1903 .params()
1904 .iter()
1905 .enumerate()
1906 .skip(skip)
1907 .map(|(idx, ty)| {
1908 let ty = Type { env: environment.clone(), ty: ty.clone() };
1909 Param { func: self, ty, idx }
1910 })
1911 .collect()
1912 }
1913
is_const(self, db: &dyn HirDatabase) -> bool1914 pub fn is_const(self, db: &dyn HirDatabase) -> bool {
1915 db.function_data(self.id).has_const_kw()
1916 }
1917
is_async(self, db: &dyn HirDatabase) -> bool1918 pub fn is_async(self, db: &dyn HirDatabase) -> bool {
1919 db.function_data(self.id).has_async_kw()
1920 }
1921
is_unsafe_to_call(self, db: &dyn HirDatabase) -> bool1922 pub fn is_unsafe_to_call(self, db: &dyn HirDatabase) -> bool {
1923 hir_ty::is_fn_unsafe_to_call(db, self.id)
1924 }
1925
1926 /// Whether this function declaration has a definition.
1927 ///
1928 /// This is false in the case of required (not provided) trait methods.
has_body(self, db: &dyn HirDatabase) -> bool1929 pub fn has_body(self, db: &dyn HirDatabase) -> bool {
1930 db.function_data(self.id).has_body()
1931 }
1932
as_proc_macro(self, db: &dyn HirDatabase) -> Option<Macro>1933 pub fn as_proc_macro(self, db: &dyn HirDatabase) -> Option<Macro> {
1934 let function_data = db.function_data(self.id);
1935 let attrs = &function_data.attrs;
1936 // FIXME: Store this in FunctionData flags?
1937 if !(attrs.is_proc_macro()
1938 || attrs.is_proc_macro_attribute()
1939 || attrs.is_proc_macro_derive())
1940 {
1941 return None;
1942 }
1943 let loc = self.id.lookup(db.upcast());
1944 let def_map = db.crate_def_map(loc.krate(db).into());
1945 def_map.fn_as_proc_macro(self.id).map(|id| Macro { id: id.into() })
1946 }
1947
eval( self, db: &dyn HirDatabase, span_formatter: impl Fn(FileId, TextRange) -> String, ) -> String1948 pub fn eval(
1949 self,
1950 db: &dyn HirDatabase,
1951 span_formatter: impl Fn(FileId, TextRange) -> String,
1952 ) -> String {
1953 let body = match db.monomorphized_mir_body(
1954 self.id.into(),
1955 Substitution::empty(Interner),
1956 db.trait_environment(self.id.into()),
1957 ) {
1958 Ok(body) => body,
1959 Err(e) => {
1960 let mut r = String::new();
1961 _ = e.pretty_print(&mut r, db, &span_formatter);
1962 return r;
1963 }
1964 };
1965 let (result, stdout, stderr) = interpret_mir(db, &body, false);
1966 let mut text = match result {
1967 Ok(_) => "pass".to_string(),
1968 Err(e) => {
1969 let mut r = String::new();
1970 _ = e.pretty_print(&mut r, db, &span_formatter);
1971 r
1972 }
1973 };
1974 if !stdout.is_empty() {
1975 text += "\n--------- stdout ---------\n";
1976 text += &stdout;
1977 }
1978 if !stderr.is_empty() {
1979 text += "\n--------- stderr ---------\n";
1980 text += &stderr;
1981 }
1982 text
1983 }
1984 }
1985
1986 // Note: logically, this belongs to `hir_ty`, but we are not using it there yet.
1987 #[derive(Clone, Copy, PartialEq, Eq)]
1988 pub enum Access {
1989 Shared,
1990 Exclusive,
1991 Owned,
1992 }
1993
1994 impl From<hir_ty::Mutability> for Access {
from(mutability: hir_ty::Mutability) -> Access1995 fn from(mutability: hir_ty::Mutability) -> Access {
1996 match mutability {
1997 hir_ty::Mutability::Not => Access::Shared,
1998 hir_ty::Mutability::Mut => Access::Exclusive,
1999 }
2000 }
2001 }
2002
2003 #[derive(Clone, Debug)]
2004 pub struct Param {
2005 func: Function,
2006 /// The index in parameter list, including self parameter.
2007 idx: usize,
2008 ty: Type,
2009 }
2010
2011 impl Param {
ty(&self) -> &Type2012 pub fn ty(&self) -> &Type {
2013 &self.ty
2014 }
2015
name(&self, db: &dyn HirDatabase) -> Option<Name>2016 pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
2017 Some(self.as_local(db)?.name(db))
2018 }
2019
as_local(&self, db: &dyn HirDatabase) -> Option<Local>2020 pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
2021 let parent = DefWithBodyId::FunctionId(self.func.into());
2022 let body = db.body(parent);
2023 let pat_id = body.params[self.idx];
2024 if let Pat::Bind { id, .. } = &body[pat_id] {
2025 Some(Local { parent, binding_id: *id })
2026 } else {
2027 None
2028 }
2029 }
2030
pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat>2031 pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
2032 self.source(db).and_then(|p| p.value.pat())
2033 }
2034
source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::Param>>2035 pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::Param>> {
2036 let InFile { file_id, value } = self.func.source(db)?;
2037 let params = value.param_list()?;
2038 if params.self_param().is_some() {
2039 params.params().nth(self.idx.checked_sub(1)?)
2040 } else {
2041 params.params().nth(self.idx)
2042 }
2043 .map(|value| InFile { file_id, value })
2044 }
2045 }
2046
2047 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2048 pub struct SelfParam {
2049 func: FunctionId,
2050 }
2051
2052 impl SelfParam {
access(self, db: &dyn HirDatabase) -> Access2053 pub fn access(self, db: &dyn HirDatabase) -> Access {
2054 let func_data = db.function_data(self.func);
2055 func_data
2056 .params
2057 .first()
2058 .map(|param| match &**param {
2059 TypeRef::Reference(.., mutability) => match mutability {
2060 hir_def::type_ref::Mutability::Shared => Access::Shared,
2061 hir_def::type_ref::Mutability::Mut => Access::Exclusive,
2062 },
2063 _ => Access::Owned,
2064 })
2065 .unwrap_or(Access::Owned)
2066 }
2067
display(self, db: &dyn HirDatabase) -> &'static str2068 pub fn display(self, db: &dyn HirDatabase) -> &'static str {
2069 match self.access(db) {
2070 Access::Shared => "&self",
2071 Access::Exclusive => "&mut self",
2072 Access::Owned => "self",
2073 }
2074 }
2075
source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::SelfParam>>2076 pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::SelfParam>> {
2077 let InFile { file_id, value } = Function::from(self.func).source(db)?;
2078 value
2079 .param_list()
2080 .and_then(|params| params.self_param())
2081 .map(|value| InFile { file_id, value })
2082 }
2083
ty(&self, db: &dyn HirDatabase) -> Type2084 pub fn ty(&self, db: &dyn HirDatabase) -> Type {
2085 let substs = TyBuilder::placeholder_subst(db, self.func);
2086 let callable_sig =
2087 db.callable_item_signature(self.func.into()).substitute(Interner, &substs);
2088 let environment = db.trait_environment(self.func.into());
2089 let ty = callable_sig.params()[0].clone();
2090 Type { env: environment, ty }
2091 }
2092 }
2093
2094 impl HasVisibility for Function {
visibility(&self, db: &dyn HirDatabase) -> Visibility2095 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2096 db.function_visibility(self.id)
2097 }
2098 }
2099
2100 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2101 pub struct InTypeConst {
2102 pub(crate) id: InTypeConstId,
2103 }
2104
2105 impl InTypeConst {
module(self, db: &dyn HirDatabase) -> Module2106 pub fn module(self, db: &dyn HirDatabase) -> Module {
2107 Module { id: self.id.lookup(db.upcast()).owner.module(db.upcast()) }
2108 }
2109 }
2110
2111 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2112 pub struct Const {
2113 pub(crate) id: ConstId,
2114 }
2115
2116 impl Const {
module(self, db: &dyn HirDatabase) -> Module2117 pub fn module(self, db: &dyn HirDatabase) -> Module {
2118 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
2119 }
2120
name(self, db: &dyn HirDatabase) -> Option<Name>2121 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
2122 db.const_data(self.id).name.clone()
2123 }
2124
value(self, db: &dyn HirDatabase) -> Option<ast::Expr>2125 pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
2126 self.source(db)?.value.body()
2127 }
2128
ty(self, db: &dyn HirDatabase) -> Type2129 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2130 Type::from_value_def(db, self.id)
2131 }
2132
render_eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError>2133 pub fn render_eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> {
2134 let c = db.const_eval(self.id.into(), Substitution::empty(Interner))?;
2135 let r = format!("{}", HexifiedConst(c).display(db));
2136 return Ok(r);
2137 }
2138 }
2139
2140 impl HasVisibility for Const {
visibility(&self, db: &dyn HirDatabase) -> Visibility2141 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2142 db.const_visibility(self.id)
2143 }
2144 }
2145
2146 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2147 pub struct Static {
2148 pub(crate) id: StaticId,
2149 }
2150
2151 impl Static {
module(self, db: &dyn HirDatabase) -> Module2152 pub fn module(self, db: &dyn HirDatabase) -> Module {
2153 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
2154 }
2155
name(self, db: &dyn HirDatabase) -> Name2156 pub fn name(self, db: &dyn HirDatabase) -> Name {
2157 db.static_data(self.id).name.clone()
2158 }
2159
is_mut(self, db: &dyn HirDatabase) -> bool2160 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
2161 db.static_data(self.id).mutable
2162 }
2163
value(self, db: &dyn HirDatabase) -> Option<ast::Expr>2164 pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
2165 self.source(db)?.value.body()
2166 }
2167
ty(self, db: &dyn HirDatabase) -> Type2168 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2169 Type::from_value_def(db, self.id)
2170 }
2171 }
2172
2173 impl HasVisibility for Static {
visibility(&self, db: &dyn HirDatabase) -> Visibility2174 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2175 db.static_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
2176 }
2177 }
2178
2179 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2180 pub struct Trait {
2181 pub(crate) id: TraitId,
2182 }
2183
2184 impl Trait {
lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option<Trait>2185 pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option<Trait> {
2186 db.lang_item(krate.into(), LangItem::from_name(name)?)
2187 .and_then(LangItemTarget::as_trait)
2188 .map(Into::into)
2189 }
2190
module(self, db: &dyn HirDatabase) -> Module2191 pub fn module(self, db: &dyn HirDatabase) -> Module {
2192 Module { id: self.id.lookup(db.upcast()).container }
2193 }
2194
name(self, db: &dyn HirDatabase) -> Name2195 pub fn name(self, db: &dyn HirDatabase) -> Name {
2196 db.trait_data(self.id).name.clone()
2197 }
2198
items(self, db: &dyn HirDatabase) -> Vec<AssocItem>2199 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
2200 db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
2201 }
2202
items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem>2203 pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
2204 let traits = all_super_traits(db.upcast(), self.into());
2205 traits.iter().flat_map(|tr| Trait::from(*tr).items(db)).collect()
2206 }
2207
is_auto(self, db: &dyn HirDatabase) -> bool2208 pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
2209 db.trait_data(self.id).is_auto
2210 }
2211
is_unsafe(&self, db: &dyn HirDatabase) -> bool2212 pub fn is_unsafe(&self, db: &dyn HirDatabase) -> bool {
2213 db.trait_data(self.id).is_unsafe
2214 }
2215
type_or_const_param_count( &self, db: &dyn HirDatabase, count_required_only: bool, ) -> usize2216 pub fn type_or_const_param_count(
2217 &self,
2218 db: &dyn HirDatabase,
2219 count_required_only: bool,
2220 ) -> usize {
2221 db.generic_params(GenericDefId::from(self.id))
2222 .type_or_consts
2223 .iter()
2224 .filter(|(_, ty)| match ty {
2225 TypeOrConstParamData::TypeParamData(ty)
2226 if ty.provenance != TypeParamProvenance::TypeParamList =>
2227 {
2228 false
2229 }
2230 _ => true,
2231 })
2232 .filter(|(_, ty)| !count_required_only || !ty.has_default())
2233 .count()
2234 }
2235 }
2236
2237 impl HasVisibility for Trait {
visibility(&self, db: &dyn HirDatabase) -> Visibility2238 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2239 db.trait_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
2240 }
2241 }
2242
2243 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2244 pub struct TraitAlias {
2245 pub(crate) id: TraitAliasId,
2246 }
2247
2248 impl TraitAlias {
module(self, db: &dyn HirDatabase) -> Module2249 pub fn module(self, db: &dyn HirDatabase) -> Module {
2250 Module { id: self.id.lookup(db.upcast()).container }
2251 }
2252
name(self, db: &dyn HirDatabase) -> Name2253 pub fn name(self, db: &dyn HirDatabase) -> Name {
2254 db.trait_alias_data(self.id).name.clone()
2255 }
2256 }
2257
2258 impl HasVisibility for TraitAlias {
visibility(&self, db: &dyn HirDatabase) -> Visibility2259 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2260 db.trait_alias_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
2261 }
2262 }
2263
2264 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2265 pub struct TypeAlias {
2266 pub(crate) id: TypeAliasId,
2267 }
2268
2269 impl TypeAlias {
has_non_default_type_params(self, db: &dyn HirDatabase) -> bool2270 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
2271 let subst = db.generic_defaults(self.id.into());
2272 subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
2273 GenericArgData::Ty(x) => x.is_unknown(),
2274 _ => false,
2275 })
2276 }
2277
module(self, db: &dyn HirDatabase) -> Module2278 pub fn module(self, db: &dyn HirDatabase) -> Module {
2279 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
2280 }
2281
type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef>2282 pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> {
2283 db.type_alias_data(self.id).type_ref.as_deref().cloned()
2284 }
2285
ty(self, db: &dyn HirDatabase) -> Type2286 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2287 Type::from_def(db, self.id)
2288 }
2289
name(self, db: &dyn HirDatabase) -> Name2290 pub fn name(self, db: &dyn HirDatabase) -> Name {
2291 db.type_alias_data(self.id).name.clone()
2292 }
2293 }
2294
2295 impl HasVisibility for TypeAlias {
visibility(&self, db: &dyn HirDatabase) -> Visibility2296 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2297 let function_data = db.type_alias_data(self.id);
2298 let visibility = &function_data.visibility;
2299 visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
2300 }
2301 }
2302
2303 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2304 pub struct BuiltinType {
2305 pub(crate) inner: hir_def::builtin_type::BuiltinType,
2306 }
2307
2308 impl BuiltinType {
str() -> BuiltinType2309 pub fn str() -> BuiltinType {
2310 BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
2311 }
2312
ty(self, db: &dyn HirDatabase) -> Type2313 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2314 Type::new_for_crate(db.crate_graph().iter().next().unwrap(), TyBuilder::builtin(self.inner))
2315 }
2316
name(self) -> Name2317 pub fn name(self) -> Name {
2318 self.inner.as_name()
2319 }
2320
is_int(&self) -> bool2321 pub fn is_int(&self) -> bool {
2322 matches!(self.inner, hir_def::builtin_type::BuiltinType::Int(_))
2323 }
2324
is_uint(&self) -> bool2325 pub fn is_uint(&self) -> bool {
2326 matches!(self.inner, hir_def::builtin_type::BuiltinType::Uint(_))
2327 }
2328
is_float(&self) -> bool2329 pub fn is_float(&self) -> bool {
2330 matches!(self.inner, hir_def::builtin_type::BuiltinType::Float(_))
2331 }
2332
is_char(&self) -> bool2333 pub fn is_char(&self) -> bool {
2334 matches!(self.inner, hir_def::builtin_type::BuiltinType::Char)
2335 }
2336
is_bool(&self) -> bool2337 pub fn is_bool(&self) -> bool {
2338 matches!(self.inner, hir_def::builtin_type::BuiltinType::Bool)
2339 }
2340
is_str(&self) -> bool2341 pub fn is_str(&self) -> bool {
2342 matches!(self.inner, hir_def::builtin_type::BuiltinType::Str)
2343 }
2344 }
2345
2346 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2347 pub enum MacroKind {
2348 /// `macro_rules!` or Macros 2.0 macro.
2349 Declarative,
2350 /// A built-in or custom derive.
2351 Derive,
2352 /// A built-in function-like macro.
2353 BuiltIn,
2354 /// A procedural attribute macro.
2355 Attr,
2356 /// A function-like procedural macro.
2357 ProcMacro,
2358 }
2359
2360 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2361 pub struct Macro {
2362 pub(crate) id: MacroId,
2363 }
2364
2365 impl Macro {
module(self, db: &dyn HirDatabase) -> Module2366 pub fn module(self, db: &dyn HirDatabase) -> Module {
2367 Module { id: self.id.module(db.upcast()) }
2368 }
2369
name(self, db: &dyn HirDatabase) -> Name2370 pub fn name(self, db: &dyn HirDatabase) -> Name {
2371 match self.id {
2372 MacroId::Macro2Id(id) => db.macro2_data(id).name.clone(),
2373 MacroId::MacroRulesId(id) => db.macro_rules_data(id).name.clone(),
2374 MacroId::ProcMacroId(id) => db.proc_macro_data(id).name.clone(),
2375 }
2376 }
2377
is_macro_export(self, db: &dyn HirDatabase) -> bool2378 pub fn is_macro_export(self, db: &dyn HirDatabase) -> bool {
2379 matches!(self.id, MacroId::MacroRulesId(id) if db.macro_rules_data(id).macro_export)
2380 }
2381
kind(&self, db: &dyn HirDatabase) -> MacroKind2382 pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind {
2383 match self.id {
2384 MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander {
2385 MacroExpander::Declarative => MacroKind::Declarative,
2386 MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
2387 MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
2388 MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
2389 },
2390 MacroId::MacroRulesId(it) => match it.lookup(db.upcast()).expander {
2391 MacroExpander::Declarative => MacroKind::Declarative,
2392 MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
2393 MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
2394 MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
2395 },
2396 MacroId::ProcMacroId(it) => match it.lookup(db.upcast()).kind {
2397 ProcMacroKind::CustomDerive => MacroKind::Derive,
2398 ProcMacroKind::FuncLike => MacroKind::ProcMacro,
2399 ProcMacroKind::Attr => MacroKind::Attr,
2400 },
2401 }
2402 }
2403
is_fn_like(&self, db: &dyn HirDatabase) -> bool2404 pub fn is_fn_like(&self, db: &dyn HirDatabase) -> bool {
2405 match self.kind(db) {
2406 MacroKind::Declarative | MacroKind::BuiltIn | MacroKind::ProcMacro => true,
2407 MacroKind::Attr | MacroKind::Derive => false,
2408 }
2409 }
2410
is_builtin_derive(&self, db: &dyn HirDatabase) -> bool2411 pub fn is_builtin_derive(&self, db: &dyn HirDatabase) -> bool {
2412 match self.id {
2413 MacroId::Macro2Id(it) => {
2414 matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInDerive(_))
2415 }
2416 MacroId::MacroRulesId(it) => {
2417 matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInDerive(_))
2418 }
2419 MacroId::ProcMacroId(_) => false,
2420 }
2421 }
2422
is_attr(&self, db: &dyn HirDatabase) -> bool2423 pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
2424 matches!(self.kind(db), MacroKind::Attr)
2425 }
2426
is_derive(&self, db: &dyn HirDatabase) -> bool2427 pub fn is_derive(&self, db: &dyn HirDatabase) -> bool {
2428 matches!(self.kind(db), MacroKind::Derive)
2429 }
2430 }
2431
2432 impl HasVisibility for Macro {
visibility(&self, db: &dyn HirDatabase) -> Visibility2433 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2434 match self.id {
2435 MacroId::Macro2Id(id) => {
2436 let data = db.macro2_data(id);
2437 let visibility = &data.visibility;
2438 visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
2439 }
2440 MacroId::MacroRulesId(_) => Visibility::Public,
2441 MacroId::ProcMacroId(_) => Visibility::Public,
2442 }
2443 }
2444 }
2445
2446 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
2447 pub enum ItemInNs {
2448 Types(ModuleDef),
2449 Values(ModuleDef),
2450 Macros(Macro),
2451 }
2452
2453 impl From<Macro> for ItemInNs {
from(it: Macro) -> Self2454 fn from(it: Macro) -> Self {
2455 Self::Macros(it)
2456 }
2457 }
2458
2459 impl From<ModuleDef> for ItemInNs {
from(module_def: ModuleDef) -> Self2460 fn from(module_def: ModuleDef) -> Self {
2461 match module_def {
2462 ModuleDef::Static(_) | ModuleDef::Const(_) | ModuleDef::Function(_) => {
2463 ItemInNs::Values(module_def)
2464 }
2465 _ => ItemInNs::Types(module_def),
2466 }
2467 }
2468 }
2469
2470 impl ItemInNs {
as_module_def(self) -> Option<ModuleDef>2471 pub fn as_module_def(self) -> Option<ModuleDef> {
2472 match self {
2473 ItemInNs::Types(id) | ItemInNs::Values(id) => Some(id),
2474 ItemInNs::Macros(_) => None,
2475 }
2476 }
2477
2478 /// Returns the crate defining this item (or `None` if `self` is built-in).
krate(&self, db: &dyn HirDatabase) -> Option<Crate>2479 pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
2480 match self {
2481 ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate()),
2482 ItemInNs::Macros(id) => Some(id.module(db).krate()),
2483 }
2484 }
2485
attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner>2486 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
2487 match self {
2488 ItemInNs::Types(it) | ItemInNs::Values(it) => it.attrs(db),
2489 ItemInNs::Macros(it) => Some(it.attrs(db)),
2490 }
2491 }
2492 }
2493
2494 /// Invariant: `inner.as_assoc_item(db).is_some()`
2495 /// We do not actively enforce this invariant.
2496 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2497 pub enum AssocItem {
2498 Function(Function),
2499 Const(Const),
2500 TypeAlias(TypeAlias),
2501 }
2502 #[derive(Debug, Clone)]
2503 pub enum AssocItemContainer {
2504 Trait(Trait),
2505 Impl(Impl),
2506 }
2507 pub trait AsAssocItem {
as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>2508 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>;
2509 }
2510
2511 impl AsAssocItem for Function {
as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>2512 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2513 as_assoc_item(db, AssocItem::Function, self.id)
2514 }
2515 }
2516 impl AsAssocItem for Const {
as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>2517 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2518 as_assoc_item(db, AssocItem::Const, self.id)
2519 }
2520 }
2521 impl AsAssocItem for TypeAlias {
as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>2522 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2523 as_assoc_item(db, AssocItem::TypeAlias, self.id)
2524 }
2525 }
2526 impl AsAssocItem for ModuleDef {
as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>2527 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2528 match self {
2529 ModuleDef::Function(it) => it.as_assoc_item(db),
2530 ModuleDef::Const(it) => it.as_assoc_item(db),
2531 ModuleDef::TypeAlias(it) => it.as_assoc_item(db),
2532 _ => None,
2533 }
2534 }
2535 }
2536 impl AsAssocItem for DefWithBody {
as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>2537 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2538 match self {
2539 DefWithBody::Function(it) => it.as_assoc_item(db),
2540 DefWithBody::Const(it) => it.as_assoc_item(db),
2541 DefWithBody::Static(_) | DefWithBody::Variant(_) | DefWithBody::InTypeConst(_) => None,
2542 }
2543 }
2544 }
2545
as_assoc_item<ID, DEF, CTOR, AST>(db: &dyn HirDatabase, ctor: CTOR, id: ID) -> Option<AssocItem> where ID: Lookup<Data = AssocItemLoc<AST>>, DEF: From<ID>, CTOR: FnOnce(DEF) -> AssocItem, AST: ItemTreeNode,2546 fn as_assoc_item<ID, DEF, CTOR, AST>(db: &dyn HirDatabase, ctor: CTOR, id: ID) -> Option<AssocItem>
2547 where
2548 ID: Lookup<Data = AssocItemLoc<AST>>,
2549 DEF: From<ID>,
2550 CTOR: FnOnce(DEF) -> AssocItem,
2551 AST: ItemTreeNode,
2552 {
2553 match id.lookup(db.upcast()).container {
2554 ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
2555 ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
2556 }
2557 }
2558
2559 impl AssocItem {
name(self, db: &dyn HirDatabase) -> Option<Name>2560 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
2561 match self {
2562 AssocItem::Function(it) => Some(it.name(db)),
2563 AssocItem::Const(it) => it.name(db),
2564 AssocItem::TypeAlias(it) => Some(it.name(db)),
2565 }
2566 }
module(self, db: &dyn HirDatabase) -> Module2567 pub fn module(self, db: &dyn HirDatabase) -> Module {
2568 match self {
2569 AssocItem::Function(f) => f.module(db),
2570 AssocItem::Const(c) => c.module(db),
2571 AssocItem::TypeAlias(t) => t.module(db),
2572 }
2573 }
container(self, db: &dyn HirDatabase) -> AssocItemContainer2574 pub fn container(self, db: &dyn HirDatabase) -> AssocItemContainer {
2575 let container = match self {
2576 AssocItem::Function(it) => it.id.lookup(db.upcast()).container,
2577 AssocItem::Const(it) => it.id.lookup(db.upcast()).container,
2578 AssocItem::TypeAlias(it) => it.id.lookup(db.upcast()).container,
2579 };
2580 match container {
2581 ItemContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()),
2582 ItemContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()),
2583 ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
2584 panic!("invalid AssocItem")
2585 }
2586 }
2587 }
2588
containing_trait(self, db: &dyn HirDatabase) -> Option<Trait>2589 pub fn containing_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
2590 match self.container(db) {
2591 AssocItemContainer::Trait(t) => Some(t),
2592 _ => None,
2593 }
2594 }
2595
containing_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait>2596 pub fn containing_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait> {
2597 match self.container(db) {
2598 AssocItemContainer::Impl(i) => i.trait_(db),
2599 _ => None,
2600 }
2601 }
2602
containing_trait_or_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait>2603 pub fn containing_trait_or_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait> {
2604 match self.container(db) {
2605 AssocItemContainer::Trait(t) => Some(t),
2606 AssocItemContainer::Impl(i) => i.trait_(db),
2607 }
2608 }
2609 }
2610
2611 impl HasVisibility for AssocItem {
visibility(&self, db: &dyn HirDatabase) -> Visibility2612 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2613 match self {
2614 AssocItem::Function(f) => f.visibility(db),
2615 AssocItem::Const(c) => c.visibility(db),
2616 AssocItem::TypeAlias(t) => t.visibility(db),
2617 }
2618 }
2619 }
2620
2621 impl From<AssocItem> for ModuleDef {
from(assoc: AssocItem) -> Self2622 fn from(assoc: AssocItem) -> Self {
2623 match assoc {
2624 AssocItem::Function(it) => ModuleDef::Function(it),
2625 AssocItem::Const(it) => ModuleDef::Const(it),
2626 AssocItem::TypeAlias(it) => ModuleDef::TypeAlias(it),
2627 }
2628 }
2629 }
2630
2631 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
2632 pub enum GenericDef {
2633 Function(Function),
2634 Adt(Adt),
2635 Trait(Trait),
2636 TraitAlias(TraitAlias),
2637 TypeAlias(TypeAlias),
2638 Impl(Impl),
2639 // enum variants cannot have generics themselves, but their parent enums
2640 // can, and this makes some code easier to write
2641 Variant(Variant),
2642 // consts can have type parameters from their parents (i.e. associated consts of traits)
2643 Const(Const),
2644 }
2645 impl_from!(
2646 Function,
2647 Adt(Struct, Enum, Union),
2648 Trait,
2649 TraitAlias,
2650 TypeAlias,
2651 Impl,
2652 Variant,
2653 Const
2654 for GenericDef
2655 );
2656
2657 impl GenericDef {
params(self, db: &dyn HirDatabase) -> Vec<GenericParam>2658 pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
2659 let generics = db.generic_params(self.into());
2660 let ty_params = generics.type_or_consts.iter().map(|(local_id, _)| {
2661 let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } };
2662 match toc.split(db) {
2663 Either::Left(x) => GenericParam::ConstParam(x),
2664 Either::Right(x) => GenericParam::TypeParam(x),
2665 }
2666 });
2667 self.lifetime_params(db)
2668 .into_iter()
2669 .map(GenericParam::LifetimeParam)
2670 .chain(ty_params)
2671 .collect()
2672 }
2673
lifetime_params(self, db: &dyn HirDatabase) -> Vec<LifetimeParam>2674 pub fn lifetime_params(self, db: &dyn HirDatabase) -> Vec<LifetimeParam> {
2675 let generics = db.generic_params(self.into());
2676 generics
2677 .lifetimes
2678 .iter()
2679 .map(|(local_id, _)| LifetimeParam {
2680 id: LifetimeParamId { parent: self.into(), local_id },
2681 })
2682 .collect()
2683 }
2684
type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam>2685 pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
2686 let generics = db.generic_params(self.into());
2687 generics
2688 .type_or_consts
2689 .iter()
2690 .map(|(local_id, _)| TypeOrConstParam {
2691 id: TypeOrConstParamId { parent: self.into(), local_id },
2692 })
2693 .collect()
2694 }
2695 }
2696
2697 /// A single local definition.
2698 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2699 pub struct Local {
2700 pub(crate) parent: DefWithBodyId,
2701 pub(crate) binding_id: BindingId,
2702 }
2703
2704 pub struct LocalSource {
2705 pub local: Local,
2706 pub source: InFile<Either<ast::IdentPat, ast::SelfParam>>,
2707 }
2708
2709 impl LocalSource {
as_ident_pat(&self) -> Option<&ast::IdentPat>2710 pub fn as_ident_pat(&self) -> Option<&ast::IdentPat> {
2711 match &self.source.value {
2712 Either::Left(x) => Some(x),
2713 Either::Right(_) => None,
2714 }
2715 }
2716
into_ident_pat(self) -> Option<ast::IdentPat>2717 pub fn into_ident_pat(self) -> Option<ast::IdentPat> {
2718 match self.source.value {
2719 Either::Left(x) => Some(x),
2720 Either::Right(_) => None,
2721 }
2722 }
2723
original_file(&self, db: &dyn HirDatabase) -> FileId2724 pub fn original_file(&self, db: &dyn HirDatabase) -> FileId {
2725 self.source.file_id.original_file(db.upcast())
2726 }
2727
file(&self) -> HirFileId2728 pub fn file(&self) -> HirFileId {
2729 self.source.file_id
2730 }
2731
name(&self) -> Option<InFile<ast::Name>>2732 pub fn name(&self) -> Option<InFile<ast::Name>> {
2733 self.source.as_ref().map(|it| it.name()).transpose()
2734 }
2735
syntax(&self) -> &SyntaxNode2736 pub fn syntax(&self) -> &SyntaxNode {
2737 self.source.value.syntax()
2738 }
2739
syntax_ptr(self) -> InFile<SyntaxNodePtr>2740 pub fn syntax_ptr(self) -> InFile<SyntaxNodePtr> {
2741 self.source.map(|x| SyntaxNodePtr::new(x.syntax()))
2742 }
2743 }
2744
2745 impl Local {
is_param(self, db: &dyn HirDatabase) -> bool2746 pub fn is_param(self, db: &dyn HirDatabase) -> bool {
2747 let src = self.primary_source(db);
2748 match src.source.value {
2749 Either::Left(pat) => pat
2750 .syntax()
2751 .ancestors()
2752 .map(|it| it.kind())
2753 .take_while(|&kind| ast::Pat::can_cast(kind) || ast::Param::can_cast(kind))
2754 .any(ast::Param::can_cast),
2755 Either::Right(_) => true,
2756 }
2757 }
2758
as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam>2759 pub fn as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
2760 match self.parent {
2761 DefWithBodyId::FunctionId(func) if self.is_self(db) => Some(SelfParam { func }),
2762 _ => None,
2763 }
2764 }
2765
name(self, db: &dyn HirDatabase) -> Name2766 pub fn name(self, db: &dyn HirDatabase) -> Name {
2767 let body = db.body(self.parent);
2768 body[self.binding_id].name.clone()
2769 }
2770
is_self(self, db: &dyn HirDatabase) -> bool2771 pub fn is_self(self, db: &dyn HirDatabase) -> bool {
2772 self.name(db) == name![self]
2773 }
2774
is_mut(self, db: &dyn HirDatabase) -> bool2775 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
2776 let body = db.body(self.parent);
2777 body[self.binding_id].mode == BindingAnnotation::Mutable
2778 }
2779
is_ref(self, db: &dyn HirDatabase) -> bool2780 pub fn is_ref(self, db: &dyn HirDatabase) -> bool {
2781 let body = db.body(self.parent);
2782 matches!(body[self.binding_id].mode, BindingAnnotation::Ref | BindingAnnotation::RefMut)
2783 }
2784
parent(self, _db: &dyn HirDatabase) -> DefWithBody2785 pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
2786 self.parent.into()
2787 }
2788
module(self, db: &dyn HirDatabase) -> Module2789 pub fn module(self, db: &dyn HirDatabase) -> Module {
2790 self.parent(db).module(db)
2791 }
2792
ty(self, db: &dyn HirDatabase) -> Type2793 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2794 let def = self.parent;
2795 let infer = db.infer(def);
2796 let ty = infer[self.binding_id].clone();
2797 Type::new(db, def, ty)
2798 }
2799
2800 /// All definitions for this local. Example: `let (a$0, _) | (_, a$0) = x;`
sources(self, db: &dyn HirDatabase) -> Vec<LocalSource>2801 pub fn sources(self, db: &dyn HirDatabase) -> Vec<LocalSource> {
2802 let (body, source_map) = db.body_with_source_map(self.parent);
2803 self.sources_(db, &body, &source_map).collect()
2804 }
2805
2806 /// The leftmost definition for this local. Example: `let (a$0, _) | (_, a) = x;`
primary_source(self, db: &dyn HirDatabase) -> LocalSource2807 pub fn primary_source(self, db: &dyn HirDatabase) -> LocalSource {
2808 let (body, source_map) = db.body_with_source_map(self.parent);
2809 let src = self.sources_(db, &body, &source_map).next().unwrap();
2810 src
2811 }
2812
sources_<'a>( self, db: &'a dyn HirDatabase, body: &'a hir_def::body::Body, source_map: &'a hir_def::body::BodySourceMap, ) -> impl Iterator<Item = LocalSource> + 'a2813 fn sources_<'a>(
2814 self,
2815 db: &'a dyn HirDatabase,
2816 body: &'a hir_def::body::Body,
2817 source_map: &'a hir_def::body::BodySourceMap,
2818 ) -> impl Iterator<Item = LocalSource> + 'a {
2819 body[self.binding_id]
2820 .definitions
2821 .iter()
2822 .map(|&definition| {
2823 let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
2824 let root = src.file_syntax(db.upcast());
2825 src.map(|ast| match ast {
2826 // Suspicious unwrap
2827 Either::Left(it) => Either::Left(it.cast().unwrap().to_node(&root)),
2828 Either::Right(it) => Either::Right(it.to_node(&root)),
2829 })
2830 })
2831 .map(move |source| LocalSource { local: self, source })
2832 }
2833 }
2834
2835 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2836 pub struct DeriveHelper {
2837 pub(crate) derive: MacroId,
2838 pub(crate) idx: u32,
2839 }
2840
2841 impl DeriveHelper {
derive(&self) -> Macro2842 pub fn derive(&self) -> Macro {
2843 Macro { id: self.derive }
2844 }
2845
name(&self, db: &dyn HirDatabase) -> Name2846 pub fn name(&self, db: &dyn HirDatabase) -> Name {
2847 match self.derive {
2848 MacroId::Macro2Id(it) => db
2849 .macro2_data(it)
2850 .helpers
2851 .as_deref()
2852 .and_then(|it| it.get(self.idx as usize))
2853 .cloned(),
2854 MacroId::MacroRulesId(_) => None,
2855 MacroId::ProcMacroId(proc_macro) => db
2856 .proc_macro_data(proc_macro)
2857 .helpers
2858 .as_deref()
2859 .and_then(|it| it.get(self.idx as usize))
2860 .cloned(),
2861 }
2862 .unwrap_or_else(|| Name::missing())
2863 }
2864 }
2865
2866 // FIXME: Wrong name? This is could also be a registered attribute
2867 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2868 pub struct BuiltinAttr {
2869 krate: Option<CrateId>,
2870 idx: u32,
2871 }
2872
2873 impl BuiltinAttr {
2874 // FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs?
by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self>2875 pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
2876 if let builtin @ Some(_) = Self::builtin(name) {
2877 return builtin;
2878 }
2879 let idx =
2880 db.crate_def_map(krate.id).registered_attrs().iter().position(|it| it == name)? as u32;
2881 Some(BuiltinAttr { krate: Some(krate.id), idx })
2882 }
2883
builtin(name: &str) -> Option<Self>2884 fn builtin(name: &str) -> Option<Self> {
2885 hir_def::attr::builtin::find_builtin_attr_idx(name)
2886 .map(|idx| BuiltinAttr { krate: None, idx: idx as u32 })
2887 }
2888
name(&self, db: &dyn HirDatabase) -> SmolStr2889 pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
2890 // FIXME: Return a `Name` here
2891 match self.krate {
2892 Some(krate) => db.crate_def_map(krate).registered_attrs()[self.idx as usize].clone(),
2893 None => SmolStr::new(hir_def::attr::builtin::INERT_ATTRIBUTES[self.idx as usize].name),
2894 }
2895 }
2896
template(&self, _: &dyn HirDatabase) -> Option<AttributeTemplate>2897 pub fn template(&self, _: &dyn HirDatabase) -> Option<AttributeTemplate> {
2898 match self.krate {
2899 Some(_) => None,
2900 None => Some(hir_def::attr::builtin::INERT_ATTRIBUTES[self.idx as usize].template),
2901 }
2902 }
2903 }
2904
2905 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2906 pub struct ToolModule {
2907 krate: Option<CrateId>,
2908 idx: u32,
2909 }
2910
2911 impl ToolModule {
2912 // FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs?
by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self>2913 pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
2914 if let builtin @ Some(_) = Self::builtin(name) {
2915 return builtin;
2916 }
2917 let idx =
2918 db.crate_def_map(krate.id).registered_tools().iter().position(|it| it == name)? as u32;
2919 Some(ToolModule { krate: Some(krate.id), idx })
2920 }
2921
builtin(name: &str) -> Option<Self>2922 fn builtin(name: &str) -> Option<Self> {
2923 hir_def::attr::builtin::TOOL_MODULES
2924 .iter()
2925 .position(|&tool| tool == name)
2926 .map(|idx| ToolModule { krate: None, idx: idx as u32 })
2927 }
2928
name(&self, db: &dyn HirDatabase) -> SmolStr2929 pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
2930 // FIXME: Return a `Name` here
2931 match self.krate {
2932 Some(krate) => db.crate_def_map(krate).registered_tools()[self.idx as usize].clone(),
2933 None => SmolStr::new(hir_def::attr::builtin::TOOL_MODULES[self.idx as usize]),
2934 }
2935 }
2936 }
2937
2938 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2939 pub struct Label {
2940 pub(crate) parent: DefWithBodyId,
2941 pub(crate) label_id: LabelId,
2942 }
2943
2944 impl Label {
module(self, db: &dyn HirDatabase) -> Module2945 pub fn module(self, db: &dyn HirDatabase) -> Module {
2946 self.parent(db).module(db)
2947 }
2948
parent(self, _db: &dyn HirDatabase) -> DefWithBody2949 pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
2950 self.parent.into()
2951 }
2952
name(self, db: &dyn HirDatabase) -> Name2953 pub fn name(self, db: &dyn HirDatabase) -> Name {
2954 let body = db.body(self.parent);
2955 body[self.label_id].name.clone()
2956 }
2957
source(self, db: &dyn HirDatabase) -> InFile<ast::Label>2958 pub fn source(self, db: &dyn HirDatabase) -> InFile<ast::Label> {
2959 let (_body, source_map) = db.body_with_source_map(self.parent);
2960 let src = source_map.label_syntax(self.label_id);
2961 let root = src.file_syntax(db.upcast());
2962 src.map(|ast| ast.to_node(&root))
2963 }
2964 }
2965
2966 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2967 pub enum GenericParam {
2968 TypeParam(TypeParam),
2969 ConstParam(ConstParam),
2970 LifetimeParam(LifetimeParam),
2971 }
2972 impl_from!(TypeParam, ConstParam, LifetimeParam for GenericParam);
2973
2974 impl GenericParam {
module(self, db: &dyn HirDatabase) -> Module2975 pub fn module(self, db: &dyn HirDatabase) -> Module {
2976 match self {
2977 GenericParam::TypeParam(it) => it.module(db),
2978 GenericParam::ConstParam(it) => it.module(db),
2979 GenericParam::LifetimeParam(it) => it.module(db),
2980 }
2981 }
2982
name(self, db: &dyn HirDatabase) -> Name2983 pub fn name(self, db: &dyn HirDatabase) -> Name {
2984 match self {
2985 GenericParam::TypeParam(it) => it.name(db),
2986 GenericParam::ConstParam(it) => it.name(db),
2987 GenericParam::LifetimeParam(it) => it.name(db),
2988 }
2989 }
2990
parent(self) -> GenericDef2991 pub fn parent(self) -> GenericDef {
2992 match self {
2993 GenericParam::TypeParam(it) => it.id.parent().into(),
2994 GenericParam::ConstParam(it) => it.id.parent().into(),
2995 GenericParam::LifetimeParam(it) => it.id.parent.into(),
2996 }
2997 }
2998 }
2999
3000 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3001 pub struct TypeParam {
3002 pub(crate) id: TypeParamId,
3003 }
3004
3005 impl TypeParam {
merge(self) -> TypeOrConstParam3006 pub fn merge(self) -> TypeOrConstParam {
3007 TypeOrConstParam { id: self.id.into() }
3008 }
3009
name(self, db: &dyn HirDatabase) -> Name3010 pub fn name(self, db: &dyn HirDatabase) -> Name {
3011 self.merge().name(db)
3012 }
3013
module(self, db: &dyn HirDatabase) -> Module3014 pub fn module(self, db: &dyn HirDatabase) -> Module {
3015 self.id.parent().module(db.upcast()).into()
3016 }
3017
3018 /// Is this type parameter implicitly introduced (eg. `Self` in a trait or an `impl Trait`
3019 /// argument)?
is_implicit(self, db: &dyn HirDatabase) -> bool3020 pub fn is_implicit(self, db: &dyn HirDatabase) -> bool {
3021 let params = db.generic_params(self.id.parent());
3022 let data = ¶ms.type_or_consts[self.id.local_id()];
3023 match data.type_param().unwrap().provenance {
3024 hir_def::generics::TypeParamProvenance::TypeParamList => false,
3025 hir_def::generics::TypeParamProvenance::TraitSelf
3026 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => true,
3027 }
3028 }
3029
ty(self, db: &dyn HirDatabase) -> Type3030 pub fn ty(self, db: &dyn HirDatabase) -> Type {
3031 let resolver = self.id.parent().resolver(db.upcast());
3032 let ty =
3033 TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id.into())).intern(Interner);
3034 Type::new_with_resolver_inner(db, &resolver, ty)
3035 }
3036
3037 /// FIXME: this only lists trait bounds from the item defining the type
3038 /// parameter, not additional bounds that might be added e.g. by a method if
3039 /// the parameter comes from an impl!
trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait>3040 pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
3041 db.generic_predicates_for_param(self.id.parent(), self.id.into(), None)
3042 .iter()
3043 .filter_map(|pred| match &pred.skip_binders().skip_binders() {
3044 hir_ty::WhereClause::Implemented(trait_ref) => {
3045 Some(Trait::from(trait_ref.hir_trait_id()))
3046 }
3047 _ => None,
3048 })
3049 .collect()
3050 }
3051
default(self, db: &dyn HirDatabase) -> Option<Type>3052 pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
3053 let params = db.generic_defaults(self.id.parent());
3054 let local_idx = hir_ty::param_idx(db, self.id.into())?;
3055 let resolver = self.id.parent().resolver(db.upcast());
3056 let ty = params.get(local_idx)?.clone();
3057 let subst = TyBuilder::placeholder_subst(db, self.id.parent());
3058 let ty = ty.substitute(Interner, &subst);
3059 match ty.data(Interner) {
3060 GenericArgData::Ty(x) => Some(Type::new_with_resolver_inner(db, &resolver, x.clone())),
3061 _ => None,
3062 }
3063 }
3064 }
3065
3066 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3067 pub struct LifetimeParam {
3068 pub(crate) id: LifetimeParamId,
3069 }
3070
3071 impl LifetimeParam {
name(self, db: &dyn HirDatabase) -> Name3072 pub fn name(self, db: &dyn HirDatabase) -> Name {
3073 let params = db.generic_params(self.id.parent);
3074 params.lifetimes[self.id.local_id].name.clone()
3075 }
3076
module(self, db: &dyn HirDatabase) -> Module3077 pub fn module(self, db: &dyn HirDatabase) -> Module {
3078 self.id.parent.module(db.upcast()).into()
3079 }
3080
parent(self, _db: &dyn HirDatabase) -> GenericDef3081 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
3082 self.id.parent.into()
3083 }
3084 }
3085
3086 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3087 pub struct ConstParam {
3088 pub(crate) id: ConstParamId,
3089 }
3090
3091 impl ConstParam {
merge(self) -> TypeOrConstParam3092 pub fn merge(self) -> TypeOrConstParam {
3093 TypeOrConstParam { id: self.id.into() }
3094 }
3095
name(self, db: &dyn HirDatabase) -> Name3096 pub fn name(self, db: &dyn HirDatabase) -> Name {
3097 let params = db.generic_params(self.id.parent());
3098 match params.type_or_consts[self.id.local_id()].name() {
3099 Some(x) => x.clone(),
3100 None => {
3101 never!();
3102 Name::missing()
3103 }
3104 }
3105 }
3106
module(self, db: &dyn HirDatabase) -> Module3107 pub fn module(self, db: &dyn HirDatabase) -> Module {
3108 self.id.parent().module(db.upcast()).into()
3109 }
3110
parent(self, _db: &dyn HirDatabase) -> GenericDef3111 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
3112 self.id.parent().into()
3113 }
3114
ty(self, db: &dyn HirDatabase) -> Type3115 pub fn ty(self, db: &dyn HirDatabase) -> Type {
3116 Type::new(db, self.id.parent(), db.const_param_ty(self.id))
3117 }
3118 }
3119
3120 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3121 pub struct TypeOrConstParam {
3122 pub(crate) id: TypeOrConstParamId,
3123 }
3124
3125 impl TypeOrConstParam {
name(self, db: &dyn HirDatabase) -> Name3126 pub fn name(self, db: &dyn HirDatabase) -> Name {
3127 let params = db.generic_params(self.id.parent);
3128 match params.type_or_consts[self.id.local_id].name() {
3129 Some(n) => n.clone(),
3130 _ => Name::missing(),
3131 }
3132 }
3133
module(self, db: &dyn HirDatabase) -> Module3134 pub fn module(self, db: &dyn HirDatabase) -> Module {
3135 self.id.parent.module(db.upcast()).into()
3136 }
3137
parent(self, _db: &dyn HirDatabase) -> GenericDef3138 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
3139 self.id.parent.into()
3140 }
3141
split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam>3142 pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
3143 let params = db.generic_params(self.id.parent);
3144 match ¶ms.type_or_consts[self.id.local_id] {
3145 hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
3146 Either::Right(TypeParam { id: TypeParamId::from_unchecked(self.id) })
3147 }
3148 hir_def::generics::TypeOrConstParamData::ConstParamData(_) => {
3149 Either::Left(ConstParam { id: ConstParamId::from_unchecked(self.id) })
3150 }
3151 }
3152 }
3153
ty(self, db: &dyn HirDatabase) -> Type3154 pub fn ty(self, db: &dyn HirDatabase) -> Type {
3155 match self.split(db) {
3156 Either::Left(x) => x.ty(db),
3157 Either::Right(x) => x.ty(db),
3158 }
3159 }
3160 }
3161
3162 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3163 pub struct Impl {
3164 pub(crate) id: ImplId,
3165 }
3166
3167 impl Impl {
all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<Impl>3168 pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<Impl> {
3169 let inherent = db.inherent_impls_in_crate(krate.id);
3170 let trait_ = db.trait_impls_in_crate(krate.id);
3171
3172 inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect()
3173 }
3174
3175 pub fn all_for_type(db: &dyn HirDatabase, Type { ty, env }: Type) -> Vec<Impl> {
3176 let def_crates = match method_resolution::def_crates(db, &ty, env.krate) {
3177 Some(def_crates) => def_crates,
3178 None => return Vec::new(),
3179 };
3180
3181 let filter = |impl_def: &Impl| {
3182 let self_ty = impl_def.self_ty(db);
3183 let rref = self_ty.remove_ref();
3184 ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
3185 };
3186
3187 let fp = TyFingerprint::for_inherent_impl(&ty);
3188 let fp = match fp {
3189 Some(fp) => fp,
3190 None => return Vec::new(),
3191 };
3192
3193 let mut all = Vec::new();
3194 def_crates.iter().for_each(|&id| {
3195 all.extend(
3196 db.inherent_impls_in_crate(id)
3197 .for_self_ty(&ty)
3198 .iter()
3199 .cloned()
3200 .map(Self::from)
3201 .filter(filter),
3202 )
3203 });
3204 for id in def_crates
3205 .iter()
3206 .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
3207 .map(|Crate { id }| id)
3208 .chain(def_crates.iter().copied())
3209 .unique()
3210 {
3211 all.extend(
3212 db.trait_impls_in_crate(id)
3213 .for_self_ty_without_blanket_impls(fp)
3214 .map(Self::from)
3215 .filter(filter),
3216 );
3217 }
3218 all
3219 }
3220
all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl>3221 pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
3222 let krate = trait_.module(db).krate();
3223 let mut all = Vec::new();
3224 for Crate { id } in krate.transitive_reverse_dependencies(db) {
3225 let impls = db.trait_impls_in_crate(id);
3226 all.extend(impls.for_trait(trait_.id).map(Self::from))
3227 }
3228 all
3229 }
3230
trait_(self, db: &dyn HirDatabase) -> Option<Trait>3231 pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> {
3232 let trait_ref = db.impl_trait(self.id)?;
3233 let id = trait_ref.skip_binders().hir_trait_id();
3234 Some(Trait { id })
3235 }
3236
trait_ref(self, db: &dyn HirDatabase) -> Option<TraitRef>3237 pub fn trait_ref(self, db: &dyn HirDatabase) -> Option<TraitRef> {
3238 let substs = TyBuilder::placeholder_subst(db, self.id);
3239 let trait_ref = db.impl_trait(self.id)?.substitute(Interner, &substs);
3240 let resolver = self.id.resolver(db.upcast());
3241 Some(TraitRef::new_with_resolver(db, &resolver, trait_ref))
3242 }
3243
self_ty(self, db: &dyn HirDatabase) -> Type3244 pub fn self_ty(self, db: &dyn HirDatabase) -> Type {
3245 let resolver = self.id.resolver(db.upcast());
3246 let substs = TyBuilder::placeholder_subst(db, self.id);
3247 let ty = db.impl_self_ty(self.id).substitute(Interner, &substs);
3248 Type::new_with_resolver_inner(db, &resolver, ty)
3249 }
3250
items(self, db: &dyn HirDatabase) -> Vec<AssocItem>3251 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
3252 db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect()
3253 }
3254
is_negative(self, db: &dyn HirDatabase) -> bool3255 pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
3256 db.impl_data(self.id).is_negative
3257 }
3258
module(self, db: &dyn HirDatabase) -> Module3259 pub fn module(self, db: &dyn HirDatabase) -> Module {
3260 self.id.lookup(db.upcast()).container.into()
3261 }
3262
is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>>3263 pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
3264 let src = self.source(db)?;
3265 src.file_id.is_builtin_derive(db.upcast())
3266 }
3267 }
3268
3269 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
3270 pub struct TraitRef {
3271 env: Arc<TraitEnvironment>,
3272 trait_ref: hir_ty::TraitRef,
3273 }
3274
3275 impl TraitRef {
new_with_resolver( db: &dyn HirDatabase, resolver: &Resolver, trait_ref: hir_ty::TraitRef, ) -> TraitRef3276 pub(crate) fn new_with_resolver(
3277 db: &dyn HirDatabase,
3278 resolver: &Resolver,
3279 trait_ref: hir_ty::TraitRef,
3280 ) -> TraitRef {
3281 let env = resolver.generic_def().map_or_else(
3282 || Arc::new(TraitEnvironment::empty(resolver.krate())),
3283 |d| db.trait_environment(d),
3284 );
3285 TraitRef { env, trait_ref }
3286 }
3287
trait_(&self) -> Trait3288 pub fn trait_(&self) -> Trait {
3289 let id = self.trait_ref.hir_trait_id();
3290 Trait { id }
3291 }
3292
self_ty(&self) -> Type3293 pub fn self_ty(&self) -> Type {
3294 let ty = self.trait_ref.self_type_parameter(Interner);
3295 Type { env: self.env.clone(), ty }
3296 }
3297
3298 /// Returns `idx`-th argument of this trait reference if it is a type argument. Note that the
3299 /// first argument is the `Self` type.
get_type_argument(&self, idx: usize) -> Option<Type>3300 pub fn get_type_argument(&self, idx: usize) -> Option<Type> {
3301 self.trait_ref
3302 .substitution
3303 .as_slice(Interner)
3304 .get(idx)
3305 .and_then(|arg| arg.ty(Interner))
3306 .cloned()
3307 .map(|ty| Type { env: self.env.clone(), ty })
3308 }
3309 }
3310
3311 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
3312 pub struct Closure {
3313 id: ClosureId,
3314 subst: Substitution,
3315 }
3316
3317 impl From<Closure> for ClosureId {
from(value: Closure) -> Self3318 fn from(value: Closure) -> Self {
3319 value.id
3320 }
3321 }
3322
3323 impl Closure {
as_ty(self) -> Ty3324 fn as_ty(self) -> Ty {
3325 TyKind::Closure(self.id, self.subst).intern(Interner)
3326 }
3327
display_with_id(&self, db: &dyn HirDatabase) -> String3328 pub fn display_with_id(&self, db: &dyn HirDatabase) -> String {
3329 self.clone().as_ty().display(db).with_closure_style(ClosureStyle::ClosureWithId).to_string()
3330 }
3331
display_with_impl(&self, db: &dyn HirDatabase) -> String3332 pub fn display_with_impl(&self, db: &dyn HirDatabase) -> String {
3333 self.clone().as_ty().display(db).with_closure_style(ClosureStyle::ImplFn).to_string()
3334 }
3335
captured_items(&self, db: &dyn HirDatabase) -> Vec<ClosureCapture>3336 pub fn captured_items(&self, db: &dyn HirDatabase) -> Vec<ClosureCapture> {
3337 let owner = db.lookup_intern_closure((self.id).into()).0;
3338 let infer = &db.infer(owner);
3339 let info = infer.closure_info(&self.id);
3340 info.0
3341 .iter()
3342 .cloned()
3343 .map(|capture| ClosureCapture { owner, closure: self.id, capture })
3344 .collect()
3345 }
3346
capture_types(&self, db: &dyn HirDatabase) -> Vec<Type>3347 pub fn capture_types(&self, db: &dyn HirDatabase) -> Vec<Type> {
3348 let owner = db.lookup_intern_closure((self.id).into()).0;
3349 let infer = &db.infer(owner);
3350 let (captures, _) = infer.closure_info(&self.id);
3351 captures
3352 .iter()
3353 .cloned()
3354 .map(|capture| Type {
3355 env: db.trait_environment_for_body(owner),
3356 ty: capture.ty(&self.subst),
3357 })
3358 .collect()
3359 }
3360
fn_trait(&self, db: &dyn HirDatabase) -> FnTrait3361 pub fn fn_trait(&self, db: &dyn HirDatabase) -> FnTrait {
3362 let owner = db.lookup_intern_closure((self.id).into()).0;
3363 let infer = &db.infer(owner);
3364 let info = infer.closure_info(&self.id);
3365 info.1
3366 }
3367 }
3368
3369 #[derive(Clone, Debug, PartialEq, Eq)]
3370 pub struct ClosureCapture {
3371 owner: DefWithBodyId,
3372 closure: ClosureId,
3373 capture: hir_ty::CapturedItem,
3374 }
3375
3376 impl ClosureCapture {
local(&self) -> Local3377 pub fn local(&self) -> Local {
3378 Local { parent: self.owner, binding_id: self.capture.local() }
3379 }
3380
kind(&self) -> CaptureKind3381 pub fn kind(&self) -> CaptureKind {
3382 match self.capture.kind() {
3383 hir_ty::CaptureKind::ByRef(
3384 hir_ty::mir::BorrowKind::Shallow | hir_ty::mir::BorrowKind::Shared,
3385 ) => CaptureKind::SharedRef,
3386 hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Unique) => {
3387 CaptureKind::UniqueSharedRef
3388 }
3389 hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Mut { .. }) => {
3390 CaptureKind::MutableRef
3391 }
3392 hir_ty::CaptureKind::ByValue => CaptureKind::Move,
3393 }
3394 }
3395
display_place(&self, db: &dyn HirDatabase) -> String3396 pub fn display_place(&self, db: &dyn HirDatabase) -> String {
3397 self.capture.display_place(self.owner, db)
3398 }
3399 }
3400
3401 pub enum CaptureKind {
3402 SharedRef,
3403 UniqueSharedRef,
3404 MutableRef,
3405 Move,
3406 }
3407
3408 #[derive(Clone, PartialEq, Eq, Debug)]
3409 pub struct Type {
3410 env: Arc<TraitEnvironment>,
3411 ty: Ty,
3412 }
3413
3414 impl Type {
new_with_resolver(db: &dyn HirDatabase, resolver: &Resolver, ty: Ty) -> Type3415 pub(crate) fn new_with_resolver(db: &dyn HirDatabase, resolver: &Resolver, ty: Ty) -> Type {
3416 Type::new_with_resolver_inner(db, resolver, ty)
3417 }
3418
new_with_resolver_inner( db: &dyn HirDatabase, resolver: &Resolver, ty: Ty, ) -> Type3419 pub(crate) fn new_with_resolver_inner(
3420 db: &dyn HirDatabase,
3421 resolver: &Resolver,
3422 ty: Ty,
3423 ) -> Type {
3424 let environment = resolver.generic_def().map_or_else(
3425 || Arc::new(TraitEnvironment::empty(resolver.krate())),
3426 |d| db.trait_environment(d),
3427 );
3428 Type { env: environment, ty }
3429 }
3430
new_for_crate(krate: CrateId, ty: Ty) -> Type3431 pub(crate) fn new_for_crate(krate: CrateId, ty: Ty) -> Type {
3432 Type { env: Arc::new(TraitEnvironment::empty(krate)), ty }
3433 }
3434
reference(inner: &Type, m: Mutability) -> Type3435 pub fn reference(inner: &Type, m: Mutability) -> Type {
3436 inner.derived(
3437 TyKind::Ref(
3438 if m.is_mut() { hir_ty::Mutability::Mut } else { hir_ty::Mutability::Not },
3439 hir_ty::static_lifetime(),
3440 inner.ty.clone(),
3441 )
3442 .intern(Interner),
3443 )
3444 }
3445
new(db: &dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty) -> Type3446 fn new(db: &dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty) -> Type {
3447 let resolver = lexical_env.resolver(db.upcast());
3448 let environment = resolver.generic_def().map_or_else(
3449 || Arc::new(TraitEnvironment::empty(resolver.krate())),
3450 |d| db.trait_environment(d),
3451 );
3452 Type { env: environment, ty }
3453 }
3454
from_def(db: &dyn HirDatabase, def: impl Into<TyDefId> + HasResolver) -> Type3455 fn from_def(db: &dyn HirDatabase, def: impl Into<TyDefId> + HasResolver) -> Type {
3456 let ty = db.ty(def.into());
3457 let substs = TyBuilder::unknown_subst(
3458 db,
3459 match def.into() {
3460 TyDefId::AdtId(it) => GenericDefId::AdtId(it),
3461 TyDefId::TypeAliasId(it) => GenericDefId::TypeAliasId(it),
3462 TyDefId::BuiltinType(_) => return Type::new(db, def, ty.skip_binders().clone()),
3463 },
3464 );
3465 Type::new(db, def, ty.substitute(Interner, &substs))
3466 }
3467
from_value_def(db: &dyn HirDatabase, def: impl Into<ValueTyDefId> + HasResolver) -> Type3468 fn from_value_def(db: &dyn HirDatabase, def: impl Into<ValueTyDefId> + HasResolver) -> Type {
3469 let ty = db.value_ty(def.into());
3470 let substs = TyBuilder::unknown_subst(
3471 db,
3472 match def.into() {
3473 ValueTyDefId::ConstId(it) => GenericDefId::ConstId(it),
3474 ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it),
3475 ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)),
3476 ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)),
3477 ValueTyDefId::EnumVariantId(it) => GenericDefId::EnumVariantId(it),
3478 ValueTyDefId::StaticId(_) => return Type::new(db, def, ty.skip_binders().clone()),
3479 },
3480 );
3481 Type::new(db, def, ty.substitute(Interner, &substs))
3482 }
3483
new_slice(ty: Type) -> Type3484 pub fn new_slice(ty: Type) -> Type {
3485 Type { env: ty.env, ty: TyBuilder::slice(ty.ty) }
3486 }
3487
is_unit(&self) -> bool3488 pub fn is_unit(&self) -> bool {
3489 matches!(self.ty.kind(Interner), TyKind::Tuple(0, ..))
3490 }
3491
is_bool(&self) -> bool3492 pub fn is_bool(&self) -> bool {
3493 matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Bool))
3494 }
3495
is_never(&self) -> bool3496 pub fn is_never(&self) -> bool {
3497 matches!(self.ty.kind(Interner), TyKind::Never)
3498 }
3499
is_mutable_reference(&self) -> bool3500 pub fn is_mutable_reference(&self) -> bool {
3501 matches!(self.ty.kind(Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
3502 }
3503
is_reference(&self) -> bool3504 pub fn is_reference(&self) -> bool {
3505 matches!(self.ty.kind(Interner), TyKind::Ref(..))
3506 }
3507
as_reference(&self) -> Option<(Type, Mutability)>3508 pub fn as_reference(&self) -> Option<(Type, Mutability)> {
3509 let (ty, _lt, m) = self.ty.as_reference()?;
3510 let m = Mutability::from_mutable(matches!(m, hir_ty::Mutability::Mut));
3511 Some((self.derived(ty.clone()), m))
3512 }
3513
is_slice(&self) -> bool3514 pub fn is_slice(&self) -> bool {
3515 matches!(self.ty.kind(Interner), TyKind::Slice(..))
3516 }
3517
is_usize(&self) -> bool3518 pub fn is_usize(&self) -> bool {
3519 matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
3520 }
3521
is_float(&self) -> bool3522 pub fn is_float(&self) -> bool {
3523 matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Float(_)))
3524 }
3525
is_char(&self) -> bool3526 pub fn is_char(&self) -> bool {
3527 matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Char))
3528 }
3529
is_int_or_uint(&self) -> bool3530 pub fn is_int_or_uint(&self) -> bool {
3531 match self.ty.kind(Interner) {
3532 TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)) => true,
3533 _ => false,
3534 }
3535 }
3536
is_scalar(&self) -> bool3537 pub fn is_scalar(&self) -> bool {
3538 matches!(self.ty.kind(Interner), TyKind::Scalar(_))
3539 }
3540
is_tuple(&self) -> bool3541 pub fn is_tuple(&self) -> bool {
3542 matches!(self.ty.kind(Interner), TyKind::Tuple(..))
3543 }
3544
remove_ref(&self) -> Option<Type>3545 pub fn remove_ref(&self) -> Option<Type> {
3546 match &self.ty.kind(Interner) {
3547 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
3548 _ => None,
3549 }
3550 }
3551
as_slice(&self) -> Option<Type>3552 pub fn as_slice(&self) -> Option<Type> {
3553 match &self.ty.kind(Interner) {
3554 TyKind::Slice(ty) => Some(self.derived(ty.clone())),
3555 _ => None,
3556 }
3557 }
3558
strip_references(&self) -> Type3559 pub fn strip_references(&self) -> Type {
3560 self.derived(self.ty.strip_references().clone())
3561 }
3562
strip_reference(&self) -> Type3563 pub fn strip_reference(&self) -> Type {
3564 self.derived(self.ty.strip_reference().clone())
3565 }
3566
is_unknown(&self) -> bool3567 pub fn is_unknown(&self) -> bool {
3568 self.ty.is_unknown()
3569 }
3570
3571 /// Checks that particular type `ty` implements `std::future::IntoFuture` or
3572 /// `std::future::Future`.
3573 /// This function is used in `.await` syntax completion.
impls_into_future(&self, db: &dyn HirDatabase) -> bool3574 pub fn impls_into_future(&self, db: &dyn HirDatabase) -> bool {
3575 let trait_ = db
3576 .lang_item(self.env.krate, LangItem::IntoFutureIntoFuture)
3577 .and_then(|it| {
3578 let into_future_fn = it.as_function()?;
3579 let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?;
3580 let into_future_trait = assoc_item.containing_trait_or_trait_impl(db)?;
3581 Some(into_future_trait.id)
3582 })
3583 .or_else(|| {
3584 let future_trait = db.lang_item(self.env.krate, LangItem::Future)?;
3585 future_trait.as_trait()
3586 });
3587
3588 let trait_ = match trait_ {
3589 Some(it) => it,
3590 None => return false,
3591 };
3592
3593 let canonical_ty =
3594 Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
3595 method_resolution::implements_trait(&canonical_ty, db, self.env.clone(), trait_)
3596 }
3597
3598 /// Checks that particular type `ty` implements `std::ops::FnOnce`.
3599 ///
3600 /// This function can be used to check if a particular type is callable, since FnOnce is a
3601 /// supertrait of Fn and FnMut, so all callable types implements at least FnOnce.
impls_fnonce(&self, db: &dyn HirDatabase) -> bool3602 pub fn impls_fnonce(&self, db: &dyn HirDatabase) -> bool {
3603 let fnonce_trait = match FnTrait::FnOnce.get_id(db, self.env.krate) {
3604 Some(it) => it,
3605 None => return false,
3606 };
3607
3608 let canonical_ty =
3609 Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
3610 method_resolution::implements_trait_unique(
3611 &canonical_ty,
3612 db,
3613 self.env.clone(),
3614 fnonce_trait,
3615 )
3616 }
3617
impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool3618 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
3619 let mut it = args.iter().map(|t| t.ty.clone());
3620 let trait_ref = TyBuilder::trait_ref(db, trait_.id)
3621 .push(self.ty.clone())
3622 .fill(|x| {
3623 let r = it.next().unwrap();
3624 match x {
3625 ParamKind::Type => GenericArgData::Ty(r).intern(Interner),
3626 ParamKind::Const(ty) => {
3627 // FIXME: this code is not covered in tests.
3628 unknown_const_as_generic(ty.clone())
3629 }
3630 }
3631 })
3632 .build();
3633
3634 let goal = Canonical {
3635 value: hir_ty::InEnvironment::new(&self.env.env, trait_ref.cast(Interner)),
3636 binders: CanonicalVarKinds::empty(Interner),
3637 };
3638
3639 db.trait_solve(self.env.krate, self.env.block, goal).is_some()
3640 }
3641
normalize_trait_assoc_type( &self, db: &dyn HirDatabase, args: &[Type], alias: TypeAlias, ) -> Option<Type>3642 pub fn normalize_trait_assoc_type(
3643 &self,
3644 db: &dyn HirDatabase,
3645 args: &[Type],
3646 alias: TypeAlias,
3647 ) -> Option<Type> {
3648 let mut args = args.iter();
3649 let trait_id = match alias.id.lookup(db.upcast()).container {
3650 ItemContainerId::TraitId(id) => id,
3651 _ => unreachable!("non assoc type alias reached in normalize_trait_assoc_type()"),
3652 };
3653 let parent_subst = TyBuilder::subst_for_def(db, trait_id, None)
3654 .push(self.ty.clone())
3655 .fill(|x| {
3656 // FIXME: this code is not covered in tests.
3657 match x {
3658 ParamKind::Type => {
3659 GenericArgData::Ty(args.next().unwrap().ty.clone()).intern(Interner)
3660 }
3661 ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
3662 }
3663 })
3664 .build();
3665 // FIXME: We don't handle GATs yet.
3666 let projection = TyBuilder::assoc_type_projection(db, alias.id, Some(parent_subst)).build();
3667
3668 let ty = db.normalize_projection(projection, self.env.clone());
3669 if ty.is_unknown() {
3670 None
3671 } else {
3672 Some(self.derived(ty))
3673 }
3674 }
3675
is_copy(&self, db: &dyn HirDatabase) -> bool3676 pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
3677 let lang_item = db.lang_item(self.env.krate, LangItem::Copy);
3678 let copy_trait = match lang_item {
3679 Some(LangItemTarget::Trait(it)) => it,
3680 _ => return false,
3681 };
3682 self.impls_trait(db, copy_trait.into(), &[])
3683 }
3684
as_callable(&self, db: &dyn HirDatabase) -> Option<Callable>3685 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
3686 let mut the_ty = &self.ty;
3687 let callee = match self.ty.kind(Interner) {
3688 TyKind::Ref(_, _, ty) if ty.as_closure().is_some() => {
3689 the_ty = ty;
3690 Callee::Closure(ty.as_closure().unwrap())
3691 }
3692 TyKind::Closure(id, _) => Callee::Closure(*id),
3693 TyKind::Function(_) => Callee::FnPtr,
3694 TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(db)?),
3695 _ => {
3696 let sig = hir_ty::callable_sig_from_fnonce(&self.ty, self.env.clone(), db)?;
3697 return Some(Callable {
3698 ty: self.clone(),
3699 sig,
3700 callee: Callee::Other,
3701 is_bound_method: false,
3702 });
3703 }
3704 };
3705
3706 let sig = the_ty.callable_sig(db)?;
3707 Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
3708 }
3709
is_closure(&self) -> bool3710 pub fn is_closure(&self) -> bool {
3711 matches!(self.ty.kind(Interner), TyKind::Closure { .. })
3712 }
3713
as_closure(&self) -> Option<Closure>3714 pub fn as_closure(&self) -> Option<Closure> {
3715 match self.ty.kind(Interner) {
3716 TyKind::Closure(id, subst) => Some(Closure { id: *id, subst: subst.clone() }),
3717 _ => None,
3718 }
3719 }
3720
is_fn(&self) -> bool3721 pub fn is_fn(&self) -> bool {
3722 matches!(self.ty.kind(Interner), TyKind::FnDef(..) | TyKind::Function { .. })
3723 }
3724
is_array(&self) -> bool3725 pub fn is_array(&self) -> bool {
3726 matches!(self.ty.kind(Interner), TyKind::Array(..))
3727 }
3728
is_packed(&self, db: &dyn HirDatabase) -> bool3729 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
3730 let adt_id = match *self.ty.kind(Interner) {
3731 TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
3732 _ => return false,
3733 };
3734
3735 let adt = adt_id.into();
3736 match adt {
3737 Adt::Struct(s) => s.repr(db).unwrap_or_default().pack.is_some(),
3738 _ => false,
3739 }
3740 }
3741
is_raw_ptr(&self) -> bool3742 pub fn is_raw_ptr(&self) -> bool {
3743 matches!(self.ty.kind(Interner), TyKind::Raw(..))
3744 }
3745
remove_raw_ptr(&self) -> Option<Type>3746 pub fn remove_raw_ptr(&self) -> Option<Type> {
3747 if let TyKind::Raw(_, ty) = self.ty.kind(Interner) {
3748 Some(self.derived(ty.clone()))
3749 } else {
3750 None
3751 }
3752 }
3753
contains_unknown(&self) -> bool3754 pub fn contains_unknown(&self) -> bool {
3755 // FIXME: When we get rid of `ConstScalar::Unknown`, we can just look at precomputed
3756 // `TypeFlags` in `TyData`.
3757 return go(&self.ty);
3758
3759 fn go(ty: &Ty) -> bool {
3760 match ty.kind(Interner) {
3761 TyKind::Error => true,
3762
3763 TyKind::Adt(_, substs)
3764 | TyKind::AssociatedType(_, substs)
3765 | TyKind::Tuple(_, substs)
3766 | TyKind::OpaqueType(_, substs)
3767 | TyKind::FnDef(_, substs)
3768 | TyKind::Closure(_, substs) => {
3769 substs.iter(Interner).filter_map(|a| a.ty(Interner)).any(go)
3770 }
3771
3772 TyKind::Array(_ty, len) if len.is_unknown() => true,
3773 TyKind::Array(ty, _)
3774 | TyKind::Slice(ty)
3775 | TyKind::Raw(_, ty)
3776 | TyKind::Ref(_, _, ty) => go(ty),
3777
3778 TyKind::Scalar(_)
3779 | TyKind::Str
3780 | TyKind::Never
3781 | TyKind::Placeholder(_)
3782 | TyKind::BoundVar(_)
3783 | TyKind::InferenceVar(_, _)
3784 | TyKind::Dyn(_)
3785 | TyKind::Function(_)
3786 | TyKind::Alias(_)
3787 | TyKind::Foreign(_)
3788 | TyKind::Generator(..)
3789 | TyKind::GeneratorWitness(..) => false,
3790 }
3791 }
3792 }
3793
fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)>3794 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
3795 let (variant_id, substs) = match self.ty.kind(Interner) {
3796 TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), substs) => ((*s).into(), substs),
3797 TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), substs) => ((*u).into(), substs),
3798 _ => return Vec::new(),
3799 };
3800
3801 db.field_types(variant_id)
3802 .iter()
3803 .map(|(local_id, ty)| {
3804 let def = Field { parent: variant_id.into(), id: local_id };
3805 let ty = ty.clone().substitute(Interner, substs);
3806 (def, self.derived(ty))
3807 })
3808 .collect()
3809 }
3810
tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type>3811 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
3812 if let TyKind::Tuple(_, substs) = &self.ty.kind(Interner) {
3813 substs
3814 .iter(Interner)
3815 .map(|ty| self.derived(ty.assert_ty_ref(Interner).clone()))
3816 .collect()
3817 } else {
3818 Vec::new()
3819 }
3820 }
3821
as_array(&self, db: &dyn HirDatabase) -> Option<(Type, usize)>3822 pub fn as_array(&self, db: &dyn HirDatabase) -> Option<(Type, usize)> {
3823 if let TyKind::Array(ty, len) = &self.ty.kind(Interner) {
3824 try_const_usize(db, len).map(|x| (self.derived(ty.clone()), x as usize))
3825 } else {
3826 None
3827 }
3828 }
3829
3830 /// Returns types that this type dereferences to (including this type itself). The returned
3831 /// iterator won't yield the same type more than once even if the deref chain contains a cycle.
autoderef(&self, db: &dyn HirDatabase) -> impl Iterator<Item = Type> + '_3832 pub fn autoderef(&self, db: &dyn HirDatabase) -> impl Iterator<Item = Type> + '_ {
3833 self.autoderef_(db).map(move |ty| self.derived(ty))
3834 }
3835
autoderef_(&self, db: &dyn HirDatabase) -> impl Iterator<Item = Ty>3836 fn autoderef_(&self, db: &dyn HirDatabase) -> impl Iterator<Item = Ty> {
3837 // There should be no inference vars in types passed here
3838 let canonical = hir_ty::replace_errors_with_variables(&self.ty);
3839 autoderef(db, self.env.clone(), canonical)
3840 }
3841
3842 // This would be nicer if it just returned an iterator, but that runs into
3843 // lifetime problems, because we need to borrow temp `CrateImplDefs`.
iterate_assoc_items<T>( &self, db: &dyn HirDatabase, krate: Crate, mut callback: impl FnMut(AssocItem) -> Option<T>, ) -> Option<T>3844 pub fn iterate_assoc_items<T>(
3845 &self,
3846 db: &dyn HirDatabase,
3847 krate: Crate,
3848 mut callback: impl FnMut(AssocItem) -> Option<T>,
3849 ) -> Option<T> {
3850 let mut slot = None;
3851 self.iterate_assoc_items_dyn(db, krate, &mut |assoc_item_id| {
3852 slot = callback(assoc_item_id.into());
3853 slot.is_some()
3854 });
3855 slot
3856 }
3857
iterate_assoc_items_dyn( &self, db: &dyn HirDatabase, krate: Crate, callback: &mut dyn FnMut(AssocItemId) -> bool, )3858 fn iterate_assoc_items_dyn(
3859 &self,
3860 db: &dyn HirDatabase,
3861 krate: Crate,
3862 callback: &mut dyn FnMut(AssocItemId) -> bool,
3863 ) {
3864 let def_crates = match method_resolution::def_crates(db, &self.ty, krate.id) {
3865 Some(it) => it,
3866 None => return,
3867 };
3868 for krate in def_crates {
3869 let impls = db.inherent_impls_in_crate(krate);
3870
3871 for impl_def in impls.for_self_ty(&self.ty) {
3872 for &item in db.impl_data(*impl_def).items.iter() {
3873 if callback(item) {
3874 return;
3875 }
3876 }
3877 }
3878 }
3879 }
3880
3881 /// Iterates its type arguments
3882 ///
3883 /// It iterates the actual type arguments when concrete types are used
3884 /// and otherwise the generic names.
3885 /// It does not include `const` arguments.
3886 ///
3887 /// For code, such as:
3888 /// ```text
3889 /// struct Foo<T, U>
3890 ///
3891 /// impl<U> Foo<String, U>
3892 /// ```
3893 ///
3894 /// It iterates:
3895 /// ```text
3896 /// - "String"
3897 /// - "U"
3898 /// ```
type_arguments(&self) -> impl Iterator<Item = Type> + '_3899 pub fn type_arguments(&self) -> impl Iterator<Item = Type> + '_ {
3900 self.ty
3901 .strip_references()
3902 .as_adt()
3903 .into_iter()
3904 .flat_map(|(_, substs)| substs.iter(Interner))
3905 .filter_map(|arg| arg.ty(Interner).cloned())
3906 .map(move |ty| self.derived(ty))
3907 }
3908
3909 /// Iterates its type and const arguments
3910 ///
3911 /// It iterates the actual type and const arguments when concrete types
3912 /// are used and otherwise the generic names.
3913 ///
3914 /// For code, such as:
3915 /// ```text
3916 /// struct Foo<T, const U: usize, const X: usize>
3917 ///
3918 /// impl<U> Foo<String, U, 12>
3919 /// ```
3920 ///
3921 /// It iterates:
3922 /// ```text
3923 /// - "String"
3924 /// - "U"
3925 /// - "12"
3926 /// ```
type_and_const_arguments<'a>( &'a self, db: &'a dyn HirDatabase, ) -> impl Iterator<Item = SmolStr> + 'a3927 pub fn type_and_const_arguments<'a>(
3928 &'a self,
3929 db: &'a dyn HirDatabase,
3930 ) -> impl Iterator<Item = SmolStr> + 'a {
3931 self.ty
3932 .strip_references()
3933 .as_adt()
3934 .into_iter()
3935 .flat_map(|(_, substs)| substs.iter(Interner))
3936 .filter_map(|arg| {
3937 // arg can be either a `Ty` or `constant`
3938 if let Some(ty) = arg.ty(Interner) {
3939 Some(SmolStr::new(ty.display(db).to_string()))
3940 } else if let Some(const_) = arg.constant(Interner) {
3941 Some(SmolStr::new_inline(&const_.display(db).to_string()))
3942 } else {
3943 None
3944 }
3945 })
3946 }
3947
3948 /// Combines lifetime indicators, type and constant parameters into a single `Iterator`
generic_parameters<'a>( &'a self, db: &'a dyn HirDatabase, ) -> impl Iterator<Item = SmolStr> + 'a3949 pub fn generic_parameters<'a>(
3950 &'a self,
3951 db: &'a dyn HirDatabase,
3952 ) -> impl Iterator<Item = SmolStr> + 'a {
3953 // iterate the lifetime
3954 self.as_adt()
3955 .and_then(|a| a.lifetime(db).and_then(|lt| Some((<.name).to_smol_str())))
3956 .into_iter()
3957 // add the type and const parameters
3958 .chain(self.type_and_const_arguments(db))
3959 }
3960
iterate_method_candidates_with_traits<T>( &self, db: &dyn HirDatabase, scope: &SemanticsScope<'_>, traits_in_scope: &FxHashSet<TraitId>, with_local_impls: Option<Module>, name: Option<&Name>, mut callback: impl FnMut(Function) -> Option<T>, ) -> Option<T>3961 pub fn iterate_method_candidates_with_traits<T>(
3962 &self,
3963 db: &dyn HirDatabase,
3964 scope: &SemanticsScope<'_>,
3965 traits_in_scope: &FxHashSet<TraitId>,
3966 with_local_impls: Option<Module>,
3967 name: Option<&Name>,
3968 mut callback: impl FnMut(Function) -> Option<T>,
3969 ) -> Option<T> {
3970 let _p = profile::span("iterate_method_candidates");
3971 let mut slot = None;
3972
3973 self.iterate_method_candidates_dyn(
3974 db,
3975 scope,
3976 traits_in_scope,
3977 with_local_impls,
3978 name,
3979 &mut |assoc_item_id| {
3980 if let AssocItemId::FunctionId(func) = assoc_item_id {
3981 if let Some(res) = callback(func.into()) {
3982 slot = Some(res);
3983 return ControlFlow::Break(());
3984 }
3985 }
3986 ControlFlow::Continue(())
3987 },
3988 );
3989 slot
3990 }
3991
iterate_method_candidates<T>( &self, db: &dyn HirDatabase, scope: &SemanticsScope<'_>, with_local_impls: Option<Module>, name: Option<&Name>, callback: impl FnMut(Function) -> Option<T>, ) -> Option<T>3992 pub fn iterate_method_candidates<T>(
3993 &self,
3994 db: &dyn HirDatabase,
3995 scope: &SemanticsScope<'_>,
3996 with_local_impls: Option<Module>,
3997 name: Option<&Name>,
3998 callback: impl FnMut(Function) -> Option<T>,
3999 ) -> Option<T> {
4000 self.iterate_method_candidates_with_traits(
4001 db,
4002 scope,
4003 &scope.visible_traits().0,
4004 with_local_impls,
4005 name,
4006 callback,
4007 )
4008 }
4009
iterate_method_candidates_dyn( &self, db: &dyn HirDatabase, scope: &SemanticsScope<'_>, traits_in_scope: &FxHashSet<TraitId>, with_local_impls: Option<Module>, name: Option<&Name>, callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>, )4010 fn iterate_method_candidates_dyn(
4011 &self,
4012 db: &dyn HirDatabase,
4013 scope: &SemanticsScope<'_>,
4014 traits_in_scope: &FxHashSet<TraitId>,
4015 with_local_impls: Option<Module>,
4016 name: Option<&Name>,
4017 callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>,
4018 ) {
4019 // There should be no inference vars in types passed here
4020 let canonical = hir_ty::replace_errors_with_variables(&self.ty);
4021
4022 let krate = scope.krate();
4023 let environment = scope.resolver().generic_def().map_or_else(
4024 || Arc::new(TraitEnvironment::empty(krate.id)),
4025 |d| db.trait_environment(d),
4026 );
4027
4028 method_resolution::iterate_method_candidates_dyn(
4029 &canonical,
4030 db,
4031 environment,
4032 traits_in_scope,
4033 with_local_impls.and_then(|b| b.id.containing_block()).into(),
4034 name,
4035 method_resolution::LookupMode::MethodCall,
4036 &mut |_adj, id, _| callback(id),
4037 );
4038 }
4039
iterate_path_candidates<T>( &self, db: &dyn HirDatabase, scope: &SemanticsScope<'_>, traits_in_scope: &FxHashSet<TraitId>, with_local_impls: Option<Module>, name: Option<&Name>, mut callback: impl FnMut(AssocItem) -> Option<T>, ) -> Option<T>4040 pub fn iterate_path_candidates<T>(
4041 &self,
4042 db: &dyn HirDatabase,
4043 scope: &SemanticsScope<'_>,
4044 traits_in_scope: &FxHashSet<TraitId>,
4045 with_local_impls: Option<Module>,
4046 name: Option<&Name>,
4047 mut callback: impl FnMut(AssocItem) -> Option<T>,
4048 ) -> Option<T> {
4049 let _p = profile::span("iterate_path_candidates");
4050 let mut slot = None;
4051 self.iterate_path_candidates_dyn(
4052 db,
4053 scope,
4054 traits_in_scope,
4055 with_local_impls,
4056 name,
4057 &mut |assoc_item_id| {
4058 if let Some(res) = callback(assoc_item_id.into()) {
4059 slot = Some(res);
4060 return ControlFlow::Break(());
4061 }
4062 ControlFlow::Continue(())
4063 },
4064 );
4065 slot
4066 }
4067
iterate_path_candidates_dyn( &self, db: &dyn HirDatabase, scope: &SemanticsScope<'_>, traits_in_scope: &FxHashSet<TraitId>, with_local_impls: Option<Module>, name: Option<&Name>, callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>, )4068 fn iterate_path_candidates_dyn(
4069 &self,
4070 db: &dyn HirDatabase,
4071 scope: &SemanticsScope<'_>,
4072 traits_in_scope: &FxHashSet<TraitId>,
4073 with_local_impls: Option<Module>,
4074 name: Option<&Name>,
4075 callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>,
4076 ) {
4077 let canonical = hir_ty::replace_errors_with_variables(&self.ty);
4078
4079 let krate = scope.krate();
4080 let environment = scope.resolver().generic_def().map_or_else(
4081 || Arc::new(TraitEnvironment::empty(krate.id)),
4082 |d| db.trait_environment(d),
4083 );
4084
4085 method_resolution::iterate_path_candidates(
4086 &canonical,
4087 db,
4088 environment,
4089 traits_in_scope,
4090 with_local_impls.and_then(|b| b.id.containing_block()).into(),
4091 name,
4092 &mut |id| callback(id),
4093 );
4094 }
4095
as_adt(&self) -> Option<Adt>4096 pub fn as_adt(&self) -> Option<Adt> {
4097 let (adt, _subst) = self.ty.as_adt()?;
4098 Some(adt.into())
4099 }
4100
as_builtin(&self) -> Option<BuiltinType>4101 pub fn as_builtin(&self) -> Option<BuiltinType> {
4102 self.ty.as_builtin().map(|inner| BuiltinType { inner })
4103 }
4104
as_dyn_trait(&self) -> Option<Trait>4105 pub fn as_dyn_trait(&self) -> Option<Trait> {
4106 self.ty.dyn_trait().map(Into::into)
4107 }
4108
4109 /// If a type can be represented as `dyn Trait`, returns all traits accessible via this type,
4110 /// or an empty iterator otherwise.
applicable_inherent_traits<'a>( &'a self, db: &'a dyn HirDatabase, ) -> impl Iterator<Item = Trait> + 'a4111 pub fn applicable_inherent_traits<'a>(
4112 &'a self,
4113 db: &'a dyn HirDatabase,
4114 ) -> impl Iterator<Item = Trait> + 'a {
4115 let _p = profile::span("applicable_inherent_traits");
4116 self.autoderef_(db)
4117 .filter_map(|ty| ty.dyn_trait())
4118 .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
4119 .map(Trait::from)
4120 }
4121
env_traits<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Trait> + 'a4122 pub fn env_traits<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Trait> + 'a {
4123 let _p = profile::span("env_traits");
4124 self.autoderef_(db)
4125 .filter(|ty| matches!(ty.kind(Interner), TyKind::Placeholder(_)))
4126 .flat_map(|ty| {
4127 self.env
4128 .traits_in_scope_from_clauses(ty)
4129 .flat_map(|t| hir_ty::all_super_traits(db.upcast(), t))
4130 })
4131 .map(Trait::from)
4132 }
4133
as_impl_traits(&self, db: &dyn HirDatabase) -> Option<impl Iterator<Item = Trait>>4134 pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<impl Iterator<Item = Trait>> {
4135 self.ty.impl_trait_bounds(db).map(|it| {
4136 it.into_iter().filter_map(|pred| match pred.skip_binders() {
4137 hir_ty::WhereClause::Implemented(trait_ref) => {
4138 Some(Trait::from(trait_ref.hir_trait_id()))
4139 }
4140 _ => None,
4141 })
4142 })
4143 }
4144
as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait>4145 pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> {
4146 self.ty.associated_type_parent_trait(db).map(Into::into)
4147 }
4148
derived(&self, ty: Ty) -> Type4149 fn derived(&self, ty: Ty) -> Type {
4150 Type { env: self.env.clone(), ty }
4151 }
4152
4153 /// Visits every type, including generic arguments, in this type. `cb` is called with type
4154 /// itself first, and then with its generic arguments.
walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type))4155 pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
4156 fn walk_substs(
4157 db: &dyn HirDatabase,
4158 type_: &Type,
4159 substs: &Substitution,
4160 cb: &mut impl FnMut(Type),
4161 ) {
4162 for ty in substs.iter(Interner).filter_map(|a| a.ty(Interner)) {
4163 walk_type(db, &type_.derived(ty.clone()), cb);
4164 }
4165 }
4166
4167 fn walk_bounds(
4168 db: &dyn HirDatabase,
4169 type_: &Type,
4170 bounds: &[QuantifiedWhereClause],
4171 cb: &mut impl FnMut(Type),
4172 ) {
4173 for pred in bounds {
4174 if let WhereClause::Implemented(trait_ref) = pred.skip_binders() {
4175 cb(type_.clone());
4176 // skip the self type. it's likely the type we just got the bounds from
4177 for ty in
4178 trait_ref.substitution.iter(Interner).skip(1).filter_map(|a| a.ty(Interner))
4179 {
4180 walk_type(db, &type_.derived(ty.clone()), cb);
4181 }
4182 }
4183 }
4184 }
4185
4186 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
4187 let ty = type_.ty.strip_references();
4188 match ty.kind(Interner) {
4189 TyKind::Adt(_, substs) => {
4190 cb(type_.derived(ty.clone()));
4191 walk_substs(db, type_, substs, cb);
4192 }
4193 TyKind::AssociatedType(_, substs) => {
4194 if ty.associated_type_parent_trait(db).is_some() {
4195 cb(type_.derived(ty.clone()));
4196 }
4197 walk_substs(db, type_, substs, cb);
4198 }
4199 TyKind::OpaqueType(_, subst) => {
4200 if let Some(bounds) = ty.impl_trait_bounds(db) {
4201 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
4202 }
4203
4204 walk_substs(db, type_, subst, cb);
4205 }
4206 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
4207 if let Some(bounds) = ty.impl_trait_bounds(db) {
4208 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
4209 }
4210
4211 walk_substs(db, type_, &opaque_ty.substitution, cb);
4212 }
4213 TyKind::Placeholder(_) => {
4214 if let Some(bounds) = ty.impl_trait_bounds(db) {
4215 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
4216 }
4217 }
4218 TyKind::Dyn(bounds) => {
4219 walk_bounds(
4220 db,
4221 &type_.derived(ty.clone()),
4222 bounds.bounds.skip_binders().interned(),
4223 cb,
4224 );
4225 }
4226
4227 TyKind::Ref(_, _, ty)
4228 | TyKind::Raw(_, ty)
4229 | TyKind::Array(ty, _)
4230 | TyKind::Slice(ty) => {
4231 walk_type(db, &type_.derived(ty.clone()), cb);
4232 }
4233
4234 TyKind::FnDef(_, substs)
4235 | TyKind::Tuple(_, substs)
4236 | TyKind::Closure(.., substs) => {
4237 walk_substs(db, type_, substs, cb);
4238 }
4239 TyKind::Function(hir_ty::FnPointer { substitution, .. }) => {
4240 walk_substs(db, type_, &substitution.0, cb);
4241 }
4242
4243 _ => {}
4244 }
4245 }
4246
4247 walk_type(db, self, &mut cb);
4248 }
4249
could_unify_with(&self, db: &dyn HirDatabase, other: &Type) -> bool4250 pub fn could_unify_with(&self, db: &dyn HirDatabase, other: &Type) -> bool {
4251 let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone()));
4252 hir_ty::could_unify(db, self.env.clone(), &tys)
4253 }
4254
could_coerce_to(&self, db: &dyn HirDatabase, to: &Type) -> bool4255 pub fn could_coerce_to(&self, db: &dyn HirDatabase, to: &Type) -> bool {
4256 let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), to.ty.clone()));
4257 hir_ty::could_coerce(db, self.env.clone(), &tys)
4258 }
4259
as_type_param(&self, db: &dyn HirDatabase) -> Option<TypeParam>4260 pub fn as_type_param(&self, db: &dyn HirDatabase) -> Option<TypeParam> {
4261 match self.ty.kind(Interner) {
4262 TyKind::Placeholder(p) => Some(TypeParam {
4263 id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p)),
4264 }),
4265 _ => None,
4266 }
4267 }
4268
4269 /// Returns unique `GenericParam`s contained in this type.
generic_params(&self, db: &dyn HirDatabase) -> FxHashSet<GenericParam>4270 pub fn generic_params(&self, db: &dyn HirDatabase) -> FxHashSet<GenericParam> {
4271 hir_ty::collect_placeholders(&self.ty, db)
4272 .into_iter()
4273 .map(|id| TypeOrConstParam { id }.split(db).either_into())
4274 .collect()
4275 }
4276
layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError>4277 pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
4278 db.layout_of_ty(self.ty.clone(), self.env.krate)
4279 .map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap()))
4280 }
4281 }
4282
4283 // FIXME: Document this
4284 #[derive(Debug)]
4285 pub struct Callable {
4286 ty: Type,
4287 sig: CallableSig,
4288 callee: Callee,
4289 /// Whether this is a method that was called with method call syntax.
4290 pub(crate) is_bound_method: bool,
4291 }
4292
4293 #[derive(Debug)]
4294 enum Callee {
4295 Def(CallableDefId),
4296 Closure(ClosureId),
4297 FnPtr,
4298 Other,
4299 }
4300
4301 pub enum CallableKind {
4302 Function(Function),
4303 TupleStruct(Struct),
4304 TupleEnumVariant(Variant),
4305 Closure,
4306 FnPtr,
4307 /// Some other type that implements `FnOnce`.
4308 Other,
4309 }
4310
4311 impl Callable {
kind(&self) -> CallableKind4312 pub fn kind(&self) -> CallableKind {
4313 use Callee::*;
4314 match self.callee {
4315 Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
4316 Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
4317 Def(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
4318 Closure(_) => CallableKind::Closure,
4319 FnPtr => CallableKind::FnPtr,
4320 Other => CallableKind::Other,
4321 }
4322 }
receiver_param(&self, db: &dyn HirDatabase) -> Option<(ast::SelfParam, Type)>4323 pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(ast::SelfParam, Type)> {
4324 let func = match self.callee {
4325 Callee::Def(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
4326 _ => return None,
4327 };
4328 let src = func.lookup(db.upcast()).source(db.upcast());
4329 let param_list = src.value.param_list()?;
4330 Some((param_list.self_param()?, self.ty.derived(self.sig.params()[0].clone())))
4331 }
n_params(&self) -> usize4332 pub fn n_params(&self) -> usize {
4333 self.sig.params().len() - if self.is_bound_method { 1 } else { 0 }
4334 }
params( &self, db: &dyn HirDatabase, ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)>4335 pub fn params(
4336 &self,
4337 db: &dyn HirDatabase,
4338 ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> {
4339 let types = self
4340 .sig
4341 .params()
4342 .iter()
4343 .skip(if self.is_bound_method { 1 } else { 0 })
4344 .map(|ty| self.ty.derived(ty.clone()));
4345 let map_param = |it: ast::Param| it.pat().map(Either::Right);
4346 let patterns = match self.callee {
4347 Callee::Def(CallableDefId::FunctionId(func)) => {
4348 let src = func.lookup(db.upcast()).source(db.upcast());
4349 src.value.param_list().map(|param_list| {
4350 param_list
4351 .self_param()
4352 .map(|it| Some(Either::Left(it)))
4353 .filter(|_| !self.is_bound_method)
4354 .into_iter()
4355 .chain(param_list.params().map(map_param))
4356 })
4357 }
4358 Callee::Closure(closure_id) => match closure_source(db, closure_id) {
4359 Some(src) => src.param_list().map(|param_list| {
4360 param_list
4361 .self_param()
4362 .map(|it| Some(Either::Left(it)))
4363 .filter(|_| !self.is_bound_method)
4364 .into_iter()
4365 .chain(param_list.params().map(map_param))
4366 }),
4367 None => None,
4368 },
4369 _ => None,
4370 };
4371 patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
4372 }
return_type(&self) -> Type4373 pub fn return_type(&self) -> Type {
4374 self.ty.derived(self.sig.ret().clone())
4375 }
4376 }
4377
closure_source(db: &dyn HirDatabase, closure: ClosureId) -> Option<ast::ClosureExpr>4378 fn closure_source(db: &dyn HirDatabase, closure: ClosureId) -> Option<ast::ClosureExpr> {
4379 let (owner, expr_id) = db.lookup_intern_closure(closure.into());
4380 let (_, source_map) = db.body_with_source_map(owner);
4381 let ast = source_map.expr_syntax(expr_id).ok()?;
4382 let root = ast.file_syntax(db.upcast());
4383 let expr = ast.value.to_node(&root);
4384 match expr {
4385 ast::Expr::ClosureExpr(it) => Some(it),
4386 _ => None,
4387 }
4388 }
4389
4390 #[derive(Clone, Debug, Eq, PartialEq)]
4391 pub struct Layout(Arc<TyLayout>, Arc<TargetDataLayout>);
4392
4393 impl Layout {
size(&self) -> u644394 pub fn size(&self) -> u64 {
4395 self.0.size.bytes()
4396 }
4397
align(&self) -> u644398 pub fn align(&self) -> u64 {
4399 self.0.align.abi.bytes()
4400 }
4401
niches(&self) -> Option<u128>4402 pub fn niches(&self) -> Option<u128> {
4403 Some(self.0.largest_niche?.available(&*self.1))
4404 }
4405
field_offset(&self, idx: usize) -> Option<u64>4406 pub fn field_offset(&self, idx: usize) -> Option<u64> {
4407 match self.0.fields {
4408 layout::FieldsShape::Primitive => None,
4409 layout::FieldsShape::Union(_) => Some(0),
4410 layout::FieldsShape::Array { stride, count } => {
4411 let i = u64::try_from(idx).ok()?;
4412 (i < count).then_some((stride * i).bytes())
4413 }
4414 layout::FieldsShape::Arbitrary { ref offsets, .. } => Some(offsets.get(idx)?.bytes()),
4415 }
4416 }
4417
enum_tag_size(&self) -> Option<usize>4418 pub fn enum_tag_size(&self) -> Option<usize> {
4419 let tag_size =
4420 if let layout::Variants::Multiple { tag, tag_encoding, .. } = &self.0.variants {
4421 match tag_encoding {
4422 TagEncoding::Direct => tag.size(&*self.1).bytes_usize(),
4423 TagEncoding::Niche { .. } => 0,
4424 }
4425 } else {
4426 return None;
4427 };
4428 Some(tag_size)
4429 }
4430 }
4431
4432 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
4433 pub enum BindingMode {
4434 Move,
4435 Ref(Mutability),
4436 }
4437
4438 /// For IDE only
4439 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
4440 pub enum ScopeDef {
4441 ModuleDef(ModuleDef),
4442 GenericParam(GenericParam),
4443 ImplSelfType(Impl),
4444 AdtSelfType(Adt),
4445 Local(Local),
4446 Label(Label),
4447 Unknown,
4448 }
4449
4450 impl ScopeDef {
all_items(def: PerNs) -> ArrayVec<Self, 3>4451 pub fn all_items(def: PerNs) -> ArrayVec<Self, 3> {
4452 let mut items = ArrayVec::new();
4453
4454 match (def.take_types(), def.take_values()) {
4455 (Some(m1), None) => items.push(ScopeDef::ModuleDef(m1.into())),
4456 (None, Some(m2)) => items.push(ScopeDef::ModuleDef(m2.into())),
4457 (Some(m1), Some(m2)) => {
4458 // Some items, like unit structs and enum variants, are
4459 // returned as both a type and a value. Here we want
4460 // to de-duplicate them.
4461 if m1 != m2 {
4462 items.push(ScopeDef::ModuleDef(m1.into()));
4463 items.push(ScopeDef::ModuleDef(m2.into()));
4464 } else {
4465 items.push(ScopeDef::ModuleDef(m1.into()));
4466 }
4467 }
4468 (None, None) => {}
4469 };
4470
4471 if let Some(macro_def_id) = def.take_macros() {
4472 items.push(ScopeDef::ModuleDef(ModuleDef::Macro(macro_def_id.into())));
4473 }
4474
4475 if items.is_empty() {
4476 items.push(ScopeDef::Unknown);
4477 }
4478
4479 items
4480 }
4481
attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner>4482 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
4483 match self {
4484 ScopeDef::ModuleDef(it) => it.attrs(db),
4485 ScopeDef::GenericParam(it) => Some(it.attrs(db)),
4486 ScopeDef::ImplSelfType(_)
4487 | ScopeDef::AdtSelfType(_)
4488 | ScopeDef::Local(_)
4489 | ScopeDef::Label(_)
4490 | ScopeDef::Unknown => None,
4491 }
4492 }
4493
krate(&self, db: &dyn HirDatabase) -> Option<Crate>4494 pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
4495 match self {
4496 ScopeDef::ModuleDef(it) => it.module(db).map(|m| m.krate()),
4497 ScopeDef::GenericParam(it) => Some(it.module(db).krate()),
4498 ScopeDef::ImplSelfType(_) => None,
4499 ScopeDef::AdtSelfType(it) => Some(it.module(db).krate()),
4500 ScopeDef::Local(it) => Some(it.module(db).krate()),
4501 ScopeDef::Label(it) => Some(it.module(db).krate()),
4502 ScopeDef::Unknown => None,
4503 }
4504 }
4505 }
4506
4507 impl From<ItemInNs> for ScopeDef {
from(item: ItemInNs) -> Self4508 fn from(item: ItemInNs) -> Self {
4509 match item {
4510 ItemInNs::Types(id) => ScopeDef::ModuleDef(id),
4511 ItemInNs::Values(id) => ScopeDef::ModuleDef(id),
4512 ItemInNs::Macros(id) => ScopeDef::ModuleDef(ModuleDef::Macro(id)),
4513 }
4514 }
4515 }
4516
4517 #[derive(Clone, Debug, PartialEq, Eq)]
4518 pub struct Adjustment {
4519 pub source: Type,
4520 pub target: Type,
4521 pub kind: Adjust,
4522 }
4523
4524 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4525 pub enum Adjust {
4526 /// Go from ! to any type.
4527 NeverToAny,
4528 /// Dereference once, producing a place.
4529 Deref(Option<OverloadedDeref>),
4530 /// Take the address and produce either a `&` or `*` pointer.
4531 Borrow(AutoBorrow),
4532 Pointer(PointerCast),
4533 }
4534
4535 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4536 pub enum AutoBorrow {
4537 /// Converts from T to &T.
4538 Ref(Mutability),
4539 /// Converts from T to *T.
4540 RawPtr(Mutability),
4541 }
4542
4543 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4544 pub struct OverloadedDeref(pub Mutability);
4545
4546 pub trait HasVisibility {
visibility(&self, db: &dyn HirDatabase) -> Visibility4547 fn visibility(&self, db: &dyn HirDatabase) -> Visibility;
is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool4548 fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool {
4549 let vis = self.visibility(db);
4550 vis.is_visible_from(db.upcast(), module.id)
4551 }
4552 }
4553
4554 /// Trait for obtaining the defining crate of an item.
4555 pub trait HasCrate {
krate(&self, db: &dyn HirDatabase) -> Crate4556 fn krate(&self, db: &dyn HirDatabase) -> Crate;
4557 }
4558
4559 impl<T: hir_def::HasModule> HasCrate for T {
krate(&self, db: &dyn HirDatabase) -> Crate4560 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4561 self.module(db.upcast()).krate().into()
4562 }
4563 }
4564
4565 impl HasCrate for AssocItem {
krate(&self, db: &dyn HirDatabase) -> Crate4566 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4567 self.module(db).krate()
4568 }
4569 }
4570
4571 impl HasCrate for Struct {
krate(&self, db: &dyn HirDatabase) -> Crate4572 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4573 self.module(db).krate()
4574 }
4575 }
4576
4577 impl HasCrate for Union {
krate(&self, db: &dyn HirDatabase) -> Crate4578 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4579 self.module(db).krate()
4580 }
4581 }
4582
4583 impl HasCrate for Enum {
krate(&self, db: &dyn HirDatabase) -> Crate4584 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4585 self.module(db).krate()
4586 }
4587 }
4588
4589 impl HasCrate for Field {
krate(&self, db: &dyn HirDatabase) -> Crate4590 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4591 self.parent_def(db).module(db).krate()
4592 }
4593 }
4594
4595 impl HasCrate for Variant {
krate(&self, db: &dyn HirDatabase) -> Crate4596 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4597 self.module(db).krate()
4598 }
4599 }
4600
4601 impl HasCrate for Function {
krate(&self, db: &dyn HirDatabase) -> Crate4602 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4603 self.module(db).krate()
4604 }
4605 }
4606
4607 impl HasCrate for Const {
krate(&self, db: &dyn HirDatabase) -> Crate4608 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4609 self.module(db).krate()
4610 }
4611 }
4612
4613 impl HasCrate for TypeAlias {
krate(&self, db: &dyn HirDatabase) -> Crate4614 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4615 self.module(db).krate()
4616 }
4617 }
4618
4619 impl HasCrate for Type {
krate(&self, _db: &dyn HirDatabase) -> Crate4620 fn krate(&self, _db: &dyn HirDatabase) -> Crate {
4621 self.env.krate.into()
4622 }
4623 }
4624
4625 impl HasCrate for Macro {
krate(&self, db: &dyn HirDatabase) -> Crate4626 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4627 self.module(db).krate()
4628 }
4629 }
4630
4631 impl HasCrate for Trait {
krate(&self, db: &dyn HirDatabase) -> Crate4632 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4633 self.module(db).krate()
4634 }
4635 }
4636
4637 impl HasCrate for TraitAlias {
krate(&self, db: &dyn HirDatabase) -> Crate4638 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4639 self.module(db).krate()
4640 }
4641 }
4642
4643 impl HasCrate for Static {
krate(&self, db: &dyn HirDatabase) -> Crate4644 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4645 self.module(db).krate()
4646 }
4647 }
4648
4649 impl HasCrate for Adt {
krate(&self, db: &dyn HirDatabase) -> Crate4650 fn krate(&self, db: &dyn HirDatabase) -> Crate {
4651 self.module(db).krate()
4652 }
4653 }
4654
4655 impl HasCrate for Module {
krate(&self, _: &dyn HirDatabase) -> Crate4656 fn krate(&self, _: &dyn HirDatabase) -> Crate {
4657 Module::krate(*self)
4658 }
4659 }
4660
4661 pub trait HasContainer {
container(&self, db: &dyn HirDatabase) -> ItemContainer4662 fn container(&self, db: &dyn HirDatabase) -> ItemContainer;
4663 }
4664
4665 impl HasContainer for Module {
container(&self, db: &dyn HirDatabase) -> ItemContainer4666 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
4667 // FIXME: handle block expressions as modules (their parent is in a different DefMap)
4668 let def_map = self.id.def_map(db.upcast());
4669 match def_map[self.id.local_id].parent {
4670 Some(parent_id) => ItemContainer::Module(Module { id: def_map.module_id(parent_id) }),
4671 None => ItemContainer::Crate(def_map.krate()),
4672 }
4673 }
4674 }
4675
4676 impl HasContainer for Function {
container(&self, db: &dyn HirDatabase) -> ItemContainer4677 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
4678 container_id_to_hir(self.id.lookup(db.upcast()).container)
4679 }
4680 }
4681
4682 impl HasContainer for Struct {
container(&self, db: &dyn HirDatabase) -> ItemContainer4683 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
4684 ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
4685 }
4686 }
4687
4688 impl HasContainer for Union {
container(&self, db: &dyn HirDatabase) -> ItemContainer4689 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
4690 ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
4691 }
4692 }
4693
4694 impl HasContainer for Enum {
container(&self, db: &dyn HirDatabase) -> ItemContainer4695 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
4696 ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
4697 }
4698 }
4699
4700 impl HasContainer for TypeAlias {
container(&self, db: &dyn HirDatabase) -> ItemContainer4701 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
4702 container_id_to_hir(self.id.lookup(db.upcast()).container)
4703 }
4704 }
4705
4706 impl HasContainer for Const {
container(&self, db: &dyn HirDatabase) -> ItemContainer4707 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
4708 container_id_to_hir(self.id.lookup(db.upcast()).container)
4709 }
4710 }
4711
4712 impl HasContainer for Static {
container(&self, db: &dyn HirDatabase) -> ItemContainer4713 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
4714 container_id_to_hir(self.id.lookup(db.upcast()).container)
4715 }
4716 }
4717
4718 impl HasContainer for Trait {
container(&self, db: &dyn HirDatabase) -> ItemContainer4719 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
4720 ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
4721 }
4722 }
4723
4724 impl HasContainer for TraitAlias {
container(&self, db: &dyn HirDatabase) -> ItemContainer4725 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
4726 ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
4727 }
4728 }
4729
container_id_to_hir(c: ItemContainerId) -> ItemContainer4730 fn container_id_to_hir(c: ItemContainerId) -> ItemContainer {
4731 match c {
4732 ItemContainerId::ExternBlockId(_id) => ItemContainer::ExternBlock(),
4733 ItemContainerId::ModuleId(id) => ItemContainer::Module(Module { id }),
4734 ItemContainerId::ImplId(id) => ItemContainer::Impl(Impl { id }),
4735 ItemContainerId::TraitId(id) => ItemContainer::Trait(Trait { id }),
4736 }
4737 }
4738
4739 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4740 pub enum ItemContainer {
4741 Trait(Trait),
4742 Impl(Impl),
4743 Module(Module),
4744 ExternBlock(),
4745 Crate(CrateId),
4746 }
4747