1#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
21#![recursion_limit = "512"]
22
23mod attrs;
24mod from_id;
25mod has_source;
26mod semantics;
27mod source_analyzer;
28
29pub mod db;
30pub mod diagnostics;
31pub mod symbols;
32pub mod term_search;
33
34mod display;
35
36use std::{
37 mem::discriminant,
38 ops::{ControlFlow, Not},
39};
40
41use arrayvec::ArrayVec;
42use base_db::{CrateDisplayName, CrateId, CrateOrigin};
43use either::Either;
44use hir_def::{
45 data::{adt::VariantData, TraitFlags},
46 expr_store::ExpressionStoreDiagnostics,
47 generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
48 hir::{BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat},
49 item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
50 lang_item::LangItemTarget,
51 layout::{self, ReprOptions, TargetDataLayout},
52 nameres::{self, diagnostics::DefDiagnostic},
53 path::ImportAlias,
54 per_ns::PerNs,
55 resolver::{HasResolver, Resolver},
56 type_ref::TypesSourceMap,
57 AdtId, AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId,
58 CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId,
59 FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId,
60 LifetimeParamId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId,
61 SyntheticSyntax, TraitAliasId, TupleId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
62};
63use hir_expand::{
64 attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, RenderedExpandError,
65 ValueResult,
66};
67use hir_ty::{
68 all_super_traits, autoderef, check_orphan_rules,
69 consteval::{try_const_usize, unknown_const_as_generic, ConstExt},
70 diagnostics::BodyValidationDiagnostic,
71 direct_super_traits, error_lifetime, known_const_to_ast,
72 layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
73 method_resolution,
74 mir::{interpret_mir, MutBorrowKind},
75 primitive::UintTy,
76 traits::FnTrait,
77 AliasTy, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg,
78 GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
79 TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyLoweringDiagnostic,
80 ValueTyDefId, WhereClause,
81};
82use itertools::Itertools;
83use nameres::diagnostics::DefDiagnosticKind;
84use rustc_hash::FxHashSet;
85use smallvec::SmallVec;
86use span::{Edition, EditionedFileId, FileId, MacroCallId};
87use stdx::{format_to, impl_from, never};
88use syntax::{
89 ast::{self, HasAttrs as _, HasGenericParams, HasName},
90 format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr, T,
91};
92use triomphe::{Arc, ThinArc};
93
94use crate::db::{DefDatabase, HirDatabase};
95
96pub use crate::{
97 attrs::{resolve_doc_path_on, HasAttrs},
98 diagnostics::*,
99 has_source::HasSource,
100 semantics::{
101 PathResolution, Semantics, SemanticsImpl, SemanticsScope, TypeInfo, VisibleTraits,
102 },
103};
104
105pub use {
115 cfg::{CfgAtom, CfgExpr, CfgOptions},
116 hir_def::{
117 attr::{AttrSourceMap, Attrs, AttrsWithOwner},
118 data::adt::StructKind,
119 find_path::PrefixKind,
120 import_map,
121 lang_item::LangItem,
122 nameres::{DefMap, ModuleSource},
123 path::{ModPath, PathKind},
124 per_ns::Namespace,
125 type_ref::{Mutability, TypeRef},
126 visibility::Visibility,
127 ImportPathConfig,
128 {ModuleDefId, TraitId},
131 },
132 hir_expand::{
133 attrs::{Attr, AttrId},
134 change::ChangeWithProcMacros,
135 files::{
136 FilePosition, FilePositionWrapper, FileRange, FileRangeWrapper, HirFilePosition,
137 HirFileRange, InFile, InFileWrapper, InMacroFile, InRealFile, MacroFilePosition,
138 MacroFileRange,
139 },
140 hygiene::{marks_rev, SyntaxContextExt},
141 inert_attr_macro::AttributeTemplate,
142 name::Name,
143 prettify_macro_expansion,
144 proc_macro::{ProcMacros, ProcMacrosBuilder},
145 tt, ExpandResult, HirFileId, HirFileIdExt, MacroFileId, MacroFileIdExt,
146 },
147 hir_ty::{
148 consteval::ConstEvalError,
149 diagnostics::UnsafetyReason,
150 display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
151 dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode},
152 layout::LayoutError,
153 method_resolution::TyFingerprint,
154 mir::{MirEvalError, MirLowerError},
155 CastError, FnAbi, PointerCast, Safety, Variance,
156 },
157 hir_ty::{mir, Interner as ChalkTyInterner},
159 intern::{sym, Symbol},
160};
161
162#[allow(unused)]
165use {
166 hir_def::path::Path,
167 hir_expand::{
168 name::AsName,
169 span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef},
170 },
171};
172
173#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
177pub struct Crate {
178 pub(crate) id: CrateId,
179}
180
181#[derive(Debug)]
182pub struct CrateDependency {
183 pub krate: Crate,
184 pub name: Name,
185}
186
187impl Crate {
188 pub fn origin(self, db: &dyn HirDatabase) -> CrateOrigin {
189 db.crate_graph()[self.id].origin.clone()
190 }
191
192 pub fn is_builtin(self, db: &dyn HirDatabase) -> bool {
193 matches!(self.origin(db), CrateOrigin::Lang(_))
194 }
195
196 pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
197 db.crate_graph()[self.id]
198 .dependencies
199 .iter()
200 .map(|dep| {
201 let krate = Crate { id: dep.crate_id };
202 let name = dep.as_name();
203 CrateDependency { krate, name }
204 })
205 .collect()
206 }
207
208 pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
209 let crate_graph = db.crate_graph();
210 crate_graph
211 .iter()
212 .filter(|&krate| {
213 crate_graph[krate].dependencies.iter().any(|it| it.crate_id == self.id)
214 })
215 .map(|id| Crate { id })
216 .collect()
217 }
218
219 pub fn transitive_reverse_dependencies(
220 self,
221 db: &dyn HirDatabase,
222 ) -> impl Iterator<Item = Crate> {
223 db.crate_graph().transitive_rev_deps(self.id).map(|id| Crate { id })
224 }
225
226 pub fn root_module(self) -> Module {
227 Module { id: CrateRootModuleId::from(self.id).into() }
228 }
229
230 pub fn modules(self, db: &dyn HirDatabase) -> Vec<Module> {
231 let def_map = db.crate_def_map(self.id);
232 def_map.modules().map(|(id, _)| def_map.module_id(id).into()).collect()
233 }
234
235 pub fn root_file(self, db: &dyn HirDatabase) -> FileId {
236 db.crate_graph()[self.id].root_file_id
237 }
238
239 pub fn edition(self, db: &dyn HirDatabase) -> Edition {
240 db.crate_graph()[self.id].edition
241 }
242
243 pub fn version(self, db: &dyn HirDatabase) -> Option<String> {
244 db.crate_graph()[self.id].version.clone()
245 }
246
247 pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateDisplayName> {
248 db.crate_graph()[self.id].display_name.clone()
249 }
250
251 pub fn query_external_importables(
252 self,
253 db: &dyn DefDatabase,
254 query: import_map::Query,
255 ) -> impl Iterator<Item = Either<ModuleDef, Macro>> {
256 let _p = tracing::info_span!("query_external_importables").entered();
257 import_map::search_dependencies(db, self.into(), &query).into_iter().map(|item| {
258 match ItemInNs::from(item) {
259 ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id),
260 ItemInNs::Macros(mac_id) => Either::Right(mac_id),
261 }
262 })
263 }
264
265 pub fn all(db: &dyn HirDatabase) -> Vec<Crate> {
266 db.crate_graph().iter().map(|id| Crate { id }).collect()
267 }
268
269 pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
271 let attrs = db.attrs(AttrDefId::ModuleId(self.root_module().into()));
273 let doc_url = attrs.by_key(&sym::doc).find_string_value_in_tt(&sym::html_root_url);
274 doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
275 }
276
277 pub fn cfg(&self, db: &dyn HirDatabase) -> Arc<CfgOptions> {
278 db.crate_graph()[self.id].cfg_options.clone()
279 }
280
281 pub fn potential_cfg(&self, db: &dyn HirDatabase) -> Arc<CfgOptions> {
282 let data = &db.crate_graph()[self.id];
283 data.potential_cfg_options.clone().unwrap_or_else(|| data.cfg_options.clone())
284 }
285}
286
287#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
288pub struct Module {
289 pub(crate) id: ModuleId,
290}
291
292#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
294pub enum ModuleDef {
295 Module(Module),
296 Function(Function),
297 Adt(Adt),
298 Variant(Variant),
300 Const(Const),
301 Static(Static),
302 Trait(Trait),
303 TraitAlias(TraitAlias),
304 TypeAlias(TypeAlias),
305 BuiltinType(BuiltinType),
306 Macro(Macro),
307}
308impl_from!(
309 Module,
310 Function,
311 Adt(Struct, Enum, Union),
312 Variant,
313 Const,
314 Static,
315 Trait,
316 TraitAlias,
317 TypeAlias,
318 BuiltinType,
319 Macro
320 for ModuleDef
321);
322
323impl From<VariantDef> for ModuleDef {
324 fn from(var: VariantDef) -> Self {
325 match var {
326 VariantDef::Struct(t) => Adt::from(t).into(),
327 VariantDef::Union(t) => Adt::from(t).into(),
328 VariantDef::Variant(t) => t.into(),
329 }
330 }
331}
332
333impl ModuleDef {
334 pub fn module(self, db: &dyn HirDatabase) -> Option<Module> {
335 match self {
336 ModuleDef::Module(it) => it.parent(db),
337 ModuleDef::Function(it) => Some(it.module(db)),
338 ModuleDef::Adt(it) => Some(it.module(db)),
339 ModuleDef::Variant(it) => Some(it.module(db)),
340 ModuleDef::Const(it) => Some(it.module(db)),
341 ModuleDef::Static(it) => Some(it.module(db)),
342 ModuleDef::Trait(it) => Some(it.module(db)),
343 ModuleDef::TraitAlias(it) => Some(it.module(db)),
344 ModuleDef::TypeAlias(it) => Some(it.module(db)),
345 ModuleDef::Macro(it) => Some(it.module(db)),
346 ModuleDef::BuiltinType(_) => None,
347 }
348 }
349
350 pub fn canonical_path(&self, db: &dyn HirDatabase, edition: Edition) -> Option<String> {
351 let mut segments = vec![self.name(db)?];
352 for m in self.module(db)?.path_to_root(db) {
353 segments.extend(m.name(db))
354 }
355 segments.reverse();
356 Some(segments.iter().map(|it| it.display(db.upcast(), edition)).join("::"))
357 }
358
359 pub fn canonical_module_path(
360 &self,
361 db: &dyn HirDatabase,
362 ) -> Option<impl Iterator<Item = Module>> {
363 self.module(db).map(|it| it.path_to_root(db).into_iter().rev())
364 }
365
366 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
367 let name = match self {
368 ModuleDef::Module(it) => it.name(db)?,
369 ModuleDef::Const(it) => it.name(db)?,
370 ModuleDef::Adt(it) => it.name(db),
371 ModuleDef::Trait(it) => it.name(db),
372 ModuleDef::TraitAlias(it) => it.name(db),
373 ModuleDef::Function(it) => it.name(db),
374 ModuleDef::Variant(it) => it.name(db),
375 ModuleDef::TypeAlias(it) => it.name(db),
376 ModuleDef::Static(it) => it.name(db),
377 ModuleDef::Macro(it) => it.name(db),
378 ModuleDef::BuiltinType(it) => it.name(),
379 };
380 Some(name)
381 }
382
383 pub fn diagnostics(self, db: &dyn HirDatabase, style_lints: bool) -> Vec<AnyDiagnostic> {
384 let id = match self {
385 ModuleDef::Adt(it) => match it {
386 Adt::Struct(it) => it.id.into(),
387 Adt::Enum(it) => it.id.into(),
388 Adt::Union(it) => it.id.into(),
389 },
390 ModuleDef::Trait(it) => it.id.into(),
391 ModuleDef::TraitAlias(it) => it.id.into(),
392 ModuleDef::Function(it) => it.id.into(),
393 ModuleDef::TypeAlias(it) => it.id.into(),
394 ModuleDef::Module(it) => it.id.into(),
395 ModuleDef::Const(it) => it.id.into(),
396 ModuleDef::Static(it) => it.id.into(),
397 ModuleDef::Variant(it) => it.id.into(),
398 ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(),
399 };
400
401 let mut acc = Vec::new();
402
403 match self.as_def_with_body() {
404 Some(def) => {
405 def.diagnostics(db, &mut acc, style_lints);
406 }
407 None => {
408 for diag in hir_ty::diagnostics::incorrect_case(db, id) {
409 acc.push(diag.into())
410 }
411 }
412 }
413
414 if let Some(def) = self.as_self_generic_def() {
415 def.diagnostics(db, &mut acc);
416 }
417
418 acc
419 }
420
421 pub fn as_def_with_body(self) -> Option<DefWithBody> {
422 match self {
423 ModuleDef::Function(it) => Some(it.into()),
424 ModuleDef::Const(it) => Some(it.into()),
425 ModuleDef::Static(it) => Some(it.into()),
426 ModuleDef::Variant(it) => Some(it.into()),
427
428 ModuleDef::Module(_)
429 | ModuleDef::Adt(_)
430 | ModuleDef::Trait(_)
431 | ModuleDef::TraitAlias(_)
432 | ModuleDef::TypeAlias(_)
433 | ModuleDef::Macro(_)
434 | ModuleDef::BuiltinType(_) => None,
435 }
436 }
437
438 pub fn as_self_generic_def(self) -> Option<GenericDef> {
440 match self {
441 ModuleDef::Function(it) => Some(it.into()),
442 ModuleDef::Adt(it) => Some(it.into()),
443 ModuleDef::Trait(it) => Some(it.into()),
444 ModuleDef::TraitAlias(it) => Some(it.into()),
445 ModuleDef::TypeAlias(it) => Some(it.into()),
446 ModuleDef::Module(_)
447 | ModuleDef::Variant(_)
448 | ModuleDef::Static(_)
449 | ModuleDef::Const(_)
450 | ModuleDef::BuiltinType(_)
451 | ModuleDef::Macro(_) => None,
452 }
453 }
454
455 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
456 Some(match self {
457 ModuleDef::Module(it) => it.attrs(db),
458 ModuleDef::Function(it) => it.attrs(db),
459 ModuleDef::Adt(it) => it.attrs(db),
460 ModuleDef::Variant(it) => it.attrs(db),
461 ModuleDef::Const(it) => it.attrs(db),
462 ModuleDef::Static(it) => it.attrs(db),
463 ModuleDef::Trait(it) => it.attrs(db),
464 ModuleDef::TraitAlias(it) => it.attrs(db),
465 ModuleDef::TypeAlias(it) => it.attrs(db),
466 ModuleDef::Macro(it) => it.attrs(db),
467 ModuleDef::BuiltinType(_) => return None,
468 })
469 }
470}
471
472impl HasVisibility for ModuleDef {
473 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
474 match *self {
475 ModuleDef::Module(it) => it.visibility(db),
476 ModuleDef::Function(it) => it.visibility(db),
477 ModuleDef::Adt(it) => it.visibility(db),
478 ModuleDef::Const(it) => it.visibility(db),
479 ModuleDef::Static(it) => it.visibility(db),
480 ModuleDef::Trait(it) => it.visibility(db),
481 ModuleDef::TraitAlias(it) => it.visibility(db),
482 ModuleDef::TypeAlias(it) => it.visibility(db),
483 ModuleDef::Variant(it) => it.visibility(db),
484 ModuleDef::Macro(it) => it.visibility(db),
485 ModuleDef::BuiltinType(_) => Visibility::Public,
486 }
487 }
488}
489
490impl Module {
491 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
493 self.id.name(db.upcast())
494 }
495
496 pub fn krate(self) -> Crate {
498 Crate { id: self.id.krate() }
499 }
500
501 pub fn crate_root(self, db: &dyn HirDatabase) -> Module {
505 let def_map = db.crate_def_map(self.id.krate());
506 Module { id: def_map.crate_root().into() }
507 }
508
509 pub fn is_crate_root(self) -> bool {
510 DefMap::ROOT == self.id.local_id
511 }
512
513 pub fn children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module> {
515 let def_map = self.id.def_map(db.upcast());
516 let children = def_map[self.id.local_id]
517 .children
518 .values()
519 .map(|module_id| Module { id: def_map.module_id(*module_id) })
520 .collect::<Vec<_>>();
521 children.into_iter()
522 }
523
524 pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> {
526 let def_map = self.id.def_map(db.upcast());
527 let parent_id = def_map.containing_module(self.id.local_id)?;
528 Some(Module { id: parent_id })
529 }
530
531 pub fn nearest_non_block_module(self, db: &dyn HirDatabase) -> Module {
533 let mut id = self.id;
534 while id.is_block_module() {
535 id = id.containing_module(db.upcast()).expect("block without parent module");
536 }
537 Module { id }
538 }
539
540 pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> {
541 let mut res = vec![self];
542 let mut curr = self;
543 while let Some(next) = curr.parent(db) {
544 res.push(next);
545 curr = next
546 }
547 res
548 }
549
550 pub fn scope(
552 self,
553 db: &dyn HirDatabase,
554 visible_from: Option<Module>,
555 ) -> Vec<(Name, ScopeDef)> {
556 self.id.def_map(db.upcast())[self.id.local_id]
557 .scope
558 .entries()
559 .filter_map(|(name, def)| {
560 if let Some(m) = visible_from {
561 let filtered =
562 def.filter_visibility(|vis| vis.is_visible_from(db.upcast(), m.id));
563 if filtered.is_none() && !def.is_none() {
564 None
565 } else {
566 Some((name, filtered))
567 }
568 } else {
569 Some((name, def))
570 }
571 })
572 .flat_map(|(name, def)| {
573 ScopeDef::all_items(def).into_iter().map(move |item| (name.clone(), item))
574 })
575 .collect()
576 }
577
578 pub fn diagnostics(
580 self,
581 db: &dyn HirDatabase,
582 acc: &mut Vec<AnyDiagnostic>,
583 style_lints: bool,
584 ) {
585 let _p = tracing::info_span!("diagnostics", name = ?self.name(db)).entered();
586 let edition = db.crate_graph()[self.id.krate()].edition;
587 let def_map = self.id.def_map(db.upcast());
588 for diag in def_map.diagnostics() {
589 if diag.in_module != self.id.local_id {
590 continue;
592 }
593 emit_def_diagnostic(db, acc, diag, edition);
594 }
595
596 if !self.id.is_block_module() {
597 let scope = &def_map[self.id.local_id].scope;
599 scope.all_macro_calls().for_each(|it| macro_call_diagnostics(db, it, acc));
600 }
601
602 for def in self.declarations(db) {
603 match def {
604 ModuleDef::Module(m) => {
605 if def_map[m.id.local_id].origin.is_inline() {
607 m.diagnostics(db, acc, style_lints)
608 }
609 acc.extend(def.diagnostics(db, style_lints))
610 }
611 ModuleDef::Trait(t) => {
612 for diag in db.trait_data_with_diagnostics(t.id).1.iter() {
613 emit_def_diagnostic(db, acc, diag, edition);
614 }
615
616 for item in t.items(db) {
617 item.diagnostics(db, acc, style_lints);
618 }
619
620 t.all_macro_calls(db)
621 .iter()
622 .for_each(|&(_ast, call_id)| macro_call_diagnostics(db, call_id, acc));
623
624 acc.extend(def.diagnostics(db, style_lints))
625 }
626 ModuleDef::Adt(adt) => {
627 match adt {
628 Adt::Struct(s) => {
629 let tree_id = s.id.lookup(db.upcast()).id;
630 let tree_source_maps = tree_id.item_tree_with_source_map(db.upcast()).1;
631 push_ty_diagnostics(
632 db,
633 acc,
634 db.field_types_with_diagnostics(s.id.into()).1,
635 tree_source_maps.strukt(tree_id.value).item(),
636 );
637 for diag in db.struct_data_with_diagnostics(s.id).1.iter() {
638 emit_def_diagnostic(db, acc, diag, edition);
639 }
640 }
641 Adt::Union(u) => {
642 let tree_id = u.id.lookup(db.upcast()).id;
643 let tree_source_maps = tree_id.item_tree_with_source_map(db.upcast()).1;
644 push_ty_diagnostics(
645 db,
646 acc,
647 db.field_types_with_diagnostics(u.id.into()).1,
648 tree_source_maps.union(tree_id.value).item(),
649 );
650 for diag in db.union_data_with_diagnostics(u.id).1.iter() {
651 emit_def_diagnostic(db, acc, diag, edition);
652 }
653 }
654 Adt::Enum(e) => {
655 for v in e.variants(db) {
656 let tree_id = v.id.lookup(db.upcast()).id;
657 let tree_source_maps =
658 tree_id.item_tree_with_source_map(db.upcast()).1;
659 push_ty_diagnostics(
660 db,
661 acc,
662 db.field_types_with_diagnostics(v.id.into()).1,
663 tree_source_maps.variant(tree_id.value),
664 );
665 acc.extend(ModuleDef::Variant(v).diagnostics(db, style_lints));
666 for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() {
667 emit_def_diagnostic(db, acc, diag, edition);
668 }
669 }
670 }
671 }
672 acc.extend(def.diagnostics(db, style_lints))
673 }
674 ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m),
675 ModuleDef::TypeAlias(type_alias) => {
676 let tree_id = type_alias.id.lookup(db.upcast()).id;
677 let tree_source_maps = tree_id.item_tree_with_source_map(db.upcast()).1;
678 push_ty_diagnostics(
679 db,
680 acc,
681 db.type_for_type_alias_with_diagnostics(type_alias.id).1,
682 tree_source_maps.type_alias(tree_id.value).item(),
683 );
684 acc.extend(def.diagnostics(db, style_lints));
685 }
686 _ => acc.extend(def.diagnostics(db, style_lints)),
687 }
688 }
689 self.legacy_macros(db).into_iter().for_each(|m| emit_macro_def_diagnostics(db, acc, m));
690
691 let inherent_impls = db.inherent_impls_in_crate(self.id.krate());
692
693 let mut impl_assoc_items_scratch = vec![];
694 for impl_def in self.impl_defs(db) {
695 GenericDef::Impl(impl_def).diagnostics(db, acc);
696
697 let loc = impl_def.id.lookup(db.upcast());
698 let (tree, tree_source_maps) = loc.id.item_tree_with_source_map(db.upcast());
699 let source_map = tree_source_maps.impl_(loc.id.value).item();
700 let node = &tree[loc.id.value];
701 let file_id = loc.id.file_id();
702 if file_id.macro_file().is_some_and(|it| it.is_builtin_derive(db.upcast())) {
703 continue;
706 }
707 impl_def
708 .all_macro_calls(db)
709 .iter()
710 .for_each(|&(_ast, call_id)| macro_call_diagnostics(db, call_id, acc));
711
712 let ast_id_map = db.ast_id_map(file_id);
713
714 for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() {
715 emit_def_diagnostic(db, acc, diag, edition);
716 }
717
718 if inherent_impls.invalid_impls().contains(&impl_def.id) {
719 acc.push(IncoherentImpl { impl_: ast_id_map.get(node.ast_id()), file_id }.into())
720 }
721
722 if !impl_def.check_orphan_rules(db) {
723 acc.push(TraitImplOrphan { impl_: ast_id_map.get(node.ast_id()), file_id }.into())
724 }
725
726 let trait_ = impl_def.trait_(db);
727 let trait_is_unsafe = trait_.is_some_and(|t| t.is_unsafe(db));
728 let impl_is_negative = impl_def.is_negative(db);
729 let impl_is_unsafe = impl_def.is_unsafe(db);
730
731 let drop_maybe_dangle = (|| {
732 let trait_ = trait_?;
734 let drop_trait = db.lang_item(self.krate().into(), LangItem::Drop)?.as_trait()?;
735 if drop_trait != trait_.into() {
736 return None;
737 }
738 let parent = impl_def.id.into();
739 let generic_params = db.generic_params(parent);
740 let lifetime_params = generic_params.iter_lt().map(|(local_id, _)| {
741 GenericParamId::LifetimeParamId(LifetimeParamId { parent, local_id })
742 });
743 let type_params = generic_params
744 .iter_type_or_consts()
745 .filter(|(_, it)| it.type_param().is_some())
746 .map(|(local_id, _)| {
747 GenericParamId::TypeParamId(TypeParamId::from_unchecked(
748 TypeOrConstParamId { parent, local_id },
749 ))
750 });
751 let res = type_params.chain(lifetime_params).any(|p| {
752 db.attrs(AttrDefId::GenericParamId(p)).by_key(&sym::may_dangle).exists()
753 });
754 Some(res)
755 })()
756 .unwrap_or(false);
757
758 match (impl_is_unsafe, trait_is_unsafe, impl_is_negative, drop_maybe_dangle) {
759 (true, _, true, _) |
761 (true, false, _, false) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(node.ast_id()), file_id, should_be_safe: true }.into()),
763 (false, true, false, _) |
765 (false, false, _, true) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(node.ast_id()), file_id, should_be_safe: false }.into()),
767 _ => (),
768 };
769
770 if let (false, Some(trait_)) = (impl_is_negative, trait_) {
772 let items = &db.trait_data(trait_.into()).items;
773 let required_items = items.iter().filter(|&(_, assoc)| match *assoc {
774 AssocItemId::FunctionId(it) => !db.function_data(it).has_body(),
775 AssocItemId::ConstId(id) => !db.const_data(id).has_body,
776 AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(),
777 });
778 impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().cloned());
779
780 let redundant = impl_assoc_items_scratch
781 .iter()
782 .filter(|(name, id)| {
783 !items.iter().any(|(impl_name, impl_item)| {
784 discriminant(impl_item) == discriminant(id) && impl_name == name
785 })
786 })
787 .map(|(name, item)| (name.clone(), AssocItem::from(*item)));
788 for (name, assoc_item) in redundant {
789 acc.push(
790 TraitImplRedundantAssocItems {
791 trait_,
792 file_id,
793 impl_: ast_id_map.get(node.ast_id()),
794 assoc_item: (name, assoc_item),
795 }
796 .into(),
797 )
798 }
799
800 let missing: Vec<_> = required_items
801 .filter(|(name, id)| {
802 !impl_assoc_items_scratch.iter().any(|(impl_name, impl_item)| {
803 discriminant(impl_item) == discriminant(id) && impl_name == name
804 })
805 })
806 .map(|(name, item)| (name.clone(), AssocItem::from(*item)))
807 .collect();
808 if !missing.is_empty() {
809 acc.push(
810 TraitImplMissingAssocItems {
811 impl_: ast_id_map.get(node.ast_id()),
812 file_id,
813 missing,
814 }
815 .into(),
816 )
817 }
818 impl_assoc_items_scratch.clear();
819 }
820
821 push_ty_diagnostics(
822 db,
823 acc,
824 db.impl_self_ty_with_diagnostics(impl_def.id).1,
825 source_map,
826 );
827 push_ty_diagnostics(
828 db,
829 acc,
830 db.impl_trait_with_diagnostics(impl_def.id).and_then(|it| it.1),
831 source_map,
832 );
833
834 for &(_, item) in db.impl_data(impl_def.id).items.iter() {
835 AssocItem::from(item).diagnostics(db, acc, style_lints);
836 }
837 }
838 }
839
840 pub fn declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef> {
841 let def_map = self.id.def_map(db.upcast());
842 let scope = &def_map[self.id.local_id].scope;
843 scope
844 .declarations()
845 .map(ModuleDef::from)
846 .chain(scope.unnamed_consts().map(|id| ModuleDef::Const(Const::from(id))))
847 .collect()
848 }
849
850 pub fn legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro> {
851 let def_map = self.id.def_map(db.upcast());
852 let scope = &def_map[self.id.local_id].scope;
853 scope.legacy_macros().flat_map(|(_, it)| it).map(|&it| it.into()).collect()
854 }
855
856 pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {
857 let def_map = self.id.def_map(db.upcast());
858 def_map[self.id.local_id].scope.impls().map(Impl::from).collect()
859 }
860
861 pub fn find_path(
864 self,
865 db: &dyn DefDatabase,
866 item: impl Into<ItemInNs>,
867 cfg: ImportPathConfig,
868 ) -> Option<ModPath> {
869 hir_def::find_path::find_path(
870 db,
871 item.into().into(),
872 self.into(),
873 PrefixKind::Plain,
874 false,
875 cfg,
876 )
877 }
878
879 pub fn find_use_path(
882 self,
883 db: &dyn DefDatabase,
884 item: impl Into<ItemInNs>,
885 prefix_kind: PrefixKind,
886 cfg: ImportPathConfig,
887 ) -> Option<ModPath> {
888 hir_def::find_path::find_path(db, item.into().into(), self.into(), prefix_kind, true, cfg)
889 }
890}
891
892fn macro_call_diagnostics(
893 db: &dyn HirDatabase,
894 macro_call_id: MacroCallId,
895 acc: &mut Vec<AnyDiagnostic>,
896) {
897 let Some(e) = db.parse_macro_expansion_error(macro_call_id) else {
898 return;
899 };
900 let ValueResult { value: parse_errors, err } = &*e;
901 if let Some(err) = err {
902 let loc = db.lookup_intern_macro_call(macro_call_id);
903 let file_id = loc.kind.file_id();
904 let node =
905 InFile::new(file_id, db.ast_id_map(file_id).get_erased(loc.kind.erased_ast_id()));
906 let RenderedExpandError { message, error, kind } = err.render_to_string(db.upcast());
907 let precise_location = if err.span().anchor.file_id == file_id {
908 Some(
909 err.span().range
910 + db.ast_id_map(err.span().anchor.file_id.into())
911 .get_erased(err.span().anchor.ast_id)
912 .text_range()
913 .start(),
914 )
915 } else {
916 None
917 };
918 acc.push(MacroError { node, precise_location, message, error, kind }.into());
919 }
920
921 if !parse_errors.is_empty() {
922 let loc = db.lookup_intern_macro_call(macro_call_id);
923 let (node, precise_location) = precise_macro_call_location(&loc.kind, db);
924 acc.push(
925 MacroExpansionParseError { node, precise_location, errors: parse_errors.clone() }
926 .into(),
927 )
928 }
929}
930
931fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, m: Macro) {
932 let id = db.macro_def(m.id);
933 if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_expander(id) {
934 if let Some(e) = expander.mac.err() {
935 let Some(ast) = id.ast_id().left() else {
936 never!("declarative expander for non decl-macro: {:?}", e);
937 return;
938 };
939 let krate = HasModule::krate(&m.id, db.upcast());
940 let edition = db.crate_graph()[krate].edition;
941 emit_def_diagnostic_(
942 db,
943 acc,
944 &DefDiagnosticKind::MacroDefError { ast, message: e.to_string() },
945 edition,
946 );
947 }
948 }
949}
950
951fn emit_def_diagnostic(
952 db: &dyn HirDatabase,
953 acc: &mut Vec<AnyDiagnostic>,
954 diag: &DefDiagnostic,
955 edition: Edition,
956) {
957 emit_def_diagnostic_(db, acc, &diag.kind, edition)
958}
959
960fn emit_def_diagnostic_(
961 db: &dyn HirDatabase,
962 acc: &mut Vec<AnyDiagnostic>,
963 diag: &DefDiagnosticKind,
964 edition: Edition,
965) {
966 match diag {
967 DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates } => {
968 let decl = declaration.to_ptr(db.upcast());
969 acc.push(
970 UnresolvedModule {
971 decl: InFile::new(declaration.file_id, decl),
972 candidates: candidates.clone(),
973 }
974 .into(),
975 )
976 }
977 DefDiagnosticKind::UnresolvedExternCrate { ast } => {
978 let item = ast.to_ptr(db.upcast());
979 acc.push(UnresolvedExternCrate { decl: InFile::new(ast.file_id, item) }.into());
980 }
981
982 DefDiagnosticKind::MacroError { ast, path, err } => {
983 let item = ast.to_ptr(db.upcast());
984 let RenderedExpandError { message, error, kind } = err.render_to_string(db.upcast());
985 acc.push(
986 MacroError {
987 node: InFile::new(ast.file_id, item.syntax_node_ptr()),
988 precise_location: None,
989 message: format!("{}: {message}", path.display(db.upcast(), edition)),
990 error,
991 kind,
992 }
993 .into(),
994 )
995 }
996 DefDiagnosticKind::UnresolvedImport { id, index } => {
997 let file_id = id.file_id();
998 let item_tree = id.item_tree(db.upcast());
999 let import = &item_tree[id.value];
1000
1001 let use_tree = import.use_tree_to_ast(db.upcast(), file_id, *index);
1002 acc.push(
1003 UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) }.into(),
1004 );
1005 }
1006
1007 DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts } => {
1008 let item_tree = tree.item_tree(db.upcast());
1009 let ast_id_map = db.ast_id_map(tree.file_id());
1010 (|| {
1013 let process_field_list =
1014 |field_list: Option<_>, idx: ItemTreeFieldId| match field_list? {
1015 ast::FieldList::RecordFieldList(it) => Some(SyntaxNodePtr::new(
1016 it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(),
1017 )),
1018 ast::FieldList::TupleFieldList(it) => Some(SyntaxNodePtr::new(
1019 it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(),
1020 )),
1021 };
1022 let ptr = match *item {
1023 AttrOwner::ModItem(it) => {
1024 ast_id_map.get(it.ast_id(&item_tree)).syntax_node_ptr()
1025 }
1026 AttrOwner::TopLevel => ast_id_map.root(),
1027 AttrOwner::Variant(it) => {
1028 ast_id_map.get(item_tree[it].ast_id).syntax_node_ptr()
1029 }
1030 AttrOwner::Field(FieldParent::Variant(parent), idx) => process_field_list(
1031 ast_id_map
1032 .get(item_tree[parent].ast_id)
1033 .to_node(&db.parse_or_expand(tree.file_id()))
1034 .field_list(),
1035 idx,
1036 )?,
1037 AttrOwner::Field(FieldParent::Struct(parent), idx) => process_field_list(
1038 ast_id_map
1039 .get(item_tree[parent.index()].ast_id)
1040 .to_node(&db.parse_or_expand(tree.file_id()))
1041 .field_list(),
1042 idx,
1043 )?,
1044 AttrOwner::Field(FieldParent::Union(parent), idx) => SyntaxNodePtr::new(
1045 ast_id_map
1046 .get(item_tree[parent.index()].ast_id)
1047 .to_node(&db.parse_or_expand(tree.file_id()))
1048 .record_field_list()?
1049 .fields()
1050 .nth(idx.into_raw().into_u32() as usize)?
1051 .syntax(),
1052 ),
1053 AttrOwner::Param(parent, idx) => SyntaxNodePtr::new(
1054 ast_id_map
1055 .get(item_tree[parent.index()].ast_id)
1056 .to_node(&db.parse_or_expand(tree.file_id()))
1057 .param_list()?
1058 .params()
1059 .nth(idx.into_raw().into_u32() as usize)?
1060 .syntax(),
1061 ),
1062 AttrOwner::TypeOrConstParamData(parent, idx) => SyntaxNodePtr::new(
1063 ast_id_map
1064 .get(parent.ast_id(&item_tree))
1065 .to_node(&db.parse_or_expand(tree.file_id()))
1066 .generic_param_list()?
1067 .type_or_const_params()
1068 .nth(idx.into_raw().into_u32() as usize)?
1069 .syntax(),
1070 ),
1071 AttrOwner::LifetimeParamData(parent, idx) => SyntaxNodePtr::new(
1072 ast_id_map
1073 .get(parent.ast_id(&item_tree))
1074 .to_node(&db.parse_or_expand(tree.file_id()))
1075 .generic_param_list()?
1076 .lifetime_params()
1077 .nth(idx.into_raw().into_u32() as usize)?
1078 .syntax(),
1079 ),
1080 };
1081 acc.push(
1082 InactiveCode {
1083 node: InFile::new(tree.file_id(), ptr),
1084 cfg: cfg.clone(),
1085 opts: opts.clone(),
1086 }
1087 .into(),
1088 );
1089 Some(())
1090 })();
1091 }
1092 DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
1093 let (node, precise_location) = precise_macro_call_location(ast, db);
1094 acc.push(
1095 UnresolvedMacroCall {
1096 macro_call: node,
1097 precise_location,
1098 path: path.clone(),
1099 is_bang: matches!(ast, MacroCallKind::FnLike { .. }),
1100 }
1101 .into(),
1102 );
1103 }
1104 DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
1105 let node = ast.to_node(db.upcast());
1106 let name = node.name().expect("unimplemented builtin macro with no name");
1108 acc.push(
1109 UnimplementedBuiltinMacro {
1110 node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&name))),
1111 }
1112 .into(),
1113 );
1114 }
1115 DefDiagnosticKind::InvalidDeriveTarget { ast, id } => {
1116 let node = ast.to_node(db.upcast());
1117 let derive = node.attrs().nth(*id);
1118 match derive {
1119 Some(derive) => {
1120 acc.push(
1121 InvalidDeriveTarget {
1122 node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
1123 }
1124 .into(),
1125 );
1126 }
1127 None => stdx::never!("derive diagnostic on item without derive attribute"),
1128 }
1129 }
1130 DefDiagnosticKind::MalformedDerive { ast, id } => {
1131 let node = ast.to_node(db.upcast());
1132 let derive = node.attrs().nth(*id);
1133 match derive {
1134 Some(derive) => {
1135 acc.push(
1136 MalformedDerive {
1137 node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
1138 }
1139 .into(),
1140 );
1141 }
1142 None => stdx::never!("derive diagnostic on item without derive attribute"),
1143 }
1144 }
1145 DefDiagnosticKind::MacroDefError { ast, message } => {
1146 let node = ast.to_node(db.upcast());
1147 acc.push(
1148 MacroDefError {
1149 node: InFile::new(ast.file_id, AstPtr::new(&node)),
1150 name: node.name().map(|it| it.syntax().text_range()),
1151 message: message.clone(),
1152 }
1153 .into(),
1154 );
1155 }
1156 }
1157}
1158
1159fn precise_macro_call_location(
1160 ast: &MacroCallKind,
1161 db: &dyn HirDatabase,
1162) -> (InFile<SyntaxNodePtr>, Option<TextRange>) {
1163 match ast {
1166 MacroCallKind::FnLike { ast_id, .. } => {
1167 let node = ast_id.to_node(db.upcast());
1168 (
1169 ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
1170 node.path()
1171 .and_then(|it| it.segment())
1172 .and_then(|it| it.name_ref())
1173 .map(|it| it.syntax().text_range()),
1174 )
1175 }
1176 MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
1177 let node = ast_id.to_node(db.upcast());
1178 let token = (|| {
1181 let derive_attr = collect_attrs(&node)
1182 .nth(derive_attr_index.ast_index())
1183 .and_then(|x| Either::left(x.1))?;
1184 let token_tree = derive_attr.meta()?.token_tree()?;
1185 let group_by = token_tree
1186 .syntax()
1187 .children_with_tokens()
1188 .filter_map(|elem| match elem {
1189 syntax::NodeOrToken::Token(tok) => Some(tok),
1190 _ => None,
1191 })
1192 .group_by(|t| t.kind() == T![,]);
1193 let (_, mut group) = group_by
1194 .into_iter()
1195 .filter(|&(comma, _)| !comma)
1196 .nth(*derive_index as usize)?;
1197 group.find(|t| t.kind() == T![ident])
1198 })();
1199 (
1200 ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
1201 token.as_ref().map(|tok| tok.text_range()),
1202 )
1203 }
1204 MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
1205 let node = ast_id.to_node(db.upcast());
1206 let attr = collect_attrs(&node)
1207 .nth(invoc_attr_index.ast_index())
1208 .and_then(|x| Either::left(x.1))
1209 .unwrap_or_else(|| {
1210 panic!("cannot find attribute #{}", invoc_attr_index.ast_index())
1211 });
1212
1213 (
1214 ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
1215 Some(attr.syntax().text_range()),
1216 )
1217 }
1218 }
1219}
1220
1221impl HasVisibility for Module {
1222 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1223 let def_map = self.id.def_map(db.upcast());
1224 let module_data = &def_map[self.id.local_id];
1225 module_data.visibility
1226 }
1227}
1228
1229#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1230pub struct Field {
1231 pub(crate) parent: VariantDef,
1232 pub(crate) id: LocalFieldId,
1233}
1234
1235#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
1236pub struct TupleField {
1237 pub owner: DefWithBodyId,
1238 pub tuple: TupleId,
1239 pub index: u32,
1240}
1241
1242impl TupleField {
1243 pub fn name(&self) -> Name {
1244 Name::new_tuple_field(self.index as usize)
1245 }
1246
1247 pub fn ty(&self, db: &dyn HirDatabase) -> Type {
1248 let ty = db.infer(self.owner).tuple_field_access_types[&self.tuple]
1249 .as_slice(Interner)
1250 .get(self.index as usize)
1251 .and_then(|arg| arg.ty(Interner))
1252 .cloned()
1253 .unwrap_or_else(|| TyKind::Error.intern(Interner));
1254 Type { env: db.trait_environment_for_body(self.owner), ty }
1255 }
1256}
1257
1258#[derive(Debug, PartialEq, Eq)]
1259pub enum FieldSource {
1260 Named(ast::RecordField),
1261 Pos(ast::TupleField),
1262}
1263
1264impl AstNode for FieldSource {
1265 fn can_cast(kind: syntax::SyntaxKind) -> bool
1266 where
1267 Self: Sized,
1268 {
1269 ast::RecordField::can_cast(kind) || ast::TupleField::can_cast(kind)
1270 }
1271
1272 fn cast(syntax: SyntaxNode) -> Option<Self>
1273 where
1274 Self: Sized,
1275 {
1276 if ast::RecordField::can_cast(syntax.kind()) {
1277 <ast::RecordField as AstNode>::cast(syntax).map(FieldSource::Named)
1278 } else if ast::TupleField::can_cast(syntax.kind()) {
1279 <ast::TupleField as AstNode>::cast(syntax).map(FieldSource::Pos)
1280 } else {
1281 None
1282 }
1283 }
1284
1285 fn syntax(&self) -> &SyntaxNode {
1286 match self {
1287 FieldSource::Named(it) => it.syntax(),
1288 FieldSource::Pos(it) => it.syntax(),
1289 }
1290 }
1291}
1292
1293impl Field {
1294 pub fn name(&self, db: &dyn HirDatabase) -> Name {
1295 self.parent.variant_data(db).fields()[self.id].name.clone()
1296 }
1297
1298 pub fn index(&self) -> usize {
1299 u32::from(self.id.into_raw()) as usize
1300 }
1301
1302 pub fn ty(&self, db: &dyn HirDatabase) -> Type {
1306 let var_id = self.parent.into();
1307 let generic_def_id: GenericDefId = match self.parent {
1308 VariantDef::Struct(it) => it.id.into(),
1309 VariantDef::Union(it) => it.id.into(),
1310 VariantDef::Variant(it) => it.id.lookup(db.upcast()).parent.into(),
1311 };
1312 let substs = TyBuilder::placeholder_subst(db, generic_def_id);
1313 let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs);
1314 Type::new(db, var_id, ty)
1315 }
1316
1317 pub fn ty_with_args(&self, db: &dyn HirDatabase, generics: impl Iterator<Item = Type>) -> Type {
1319 let var_id = self.parent.into();
1320 let def_id: AdtId = match self.parent {
1321 VariantDef::Struct(it) => it.id.into(),
1322 VariantDef::Union(it) => it.id.into(),
1323 VariantDef::Variant(it) => it.parent_enum(db).id.into(),
1324 };
1325 let mut generics = generics.map(|it| it.ty);
1326 let substs = TyBuilder::subst_for_def(db, def_id, None)
1327 .fill(|x| match x {
1328 ParamKind::Type => {
1329 generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
1330 }
1331 ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
1332 ParamKind::Lifetime => error_lifetime().cast(Interner),
1333 })
1334 .build();
1335 let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs);
1336 Type::new(db, var_id, ty)
1337 }
1338
1339 pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
1340 db.layout_of_ty(
1341 self.ty(db).ty,
1342 db.trait_environment(match hir_def::VariantId::from(self.parent) {
1343 hir_def::VariantId::EnumVariantId(id) => {
1344 GenericDefId::AdtId(id.lookup(db.upcast()).parent.into())
1345 }
1346 hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()),
1347 hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()),
1348 }),
1349 )
1350 .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
1351 }
1352
1353 pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
1354 self.parent
1355 }
1356}
1357
1358impl HasVisibility for Field {
1359 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1360 let variant_data = self.parent.variant_data(db);
1361 let visibility = &variant_data.fields()[self.id].visibility;
1362 let parent_id: hir_def::VariantId = self.parent.into();
1363 visibility.resolve(db.upcast(), &parent_id.resolver(db.upcast()))
1364 }
1365}
1366
1367#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1368pub struct Struct {
1369 pub(crate) id: StructId,
1370}
1371
1372impl Struct {
1373 pub fn module(self, db: &dyn HirDatabase) -> Module {
1374 Module { id: self.id.lookup(db.upcast()).container }
1375 }
1376
1377 pub fn name(self, db: &dyn HirDatabase) -> Name {
1378 db.struct_data(self.id).name.clone()
1379 }
1380
1381 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
1382 db.struct_data(self.id)
1383 .variant_data
1384 .fields()
1385 .iter()
1386 .map(|(id, _)| Field { parent: self.into(), id })
1387 .collect()
1388 }
1389
1390 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1391 Type::from_def(db, self.id)
1392 }
1393
1394 pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
1395 Type::from_value_def(db, self.id)
1396 }
1397
1398 pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
1399 db.struct_data(self.id).repr
1400 }
1401
1402 pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
1403 self.variant_data(db).kind()
1404 }
1405
1406 fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
1407 db.struct_data(self.id).variant_data.clone()
1408 }
1409
1410 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1411 db.attrs(self.id.into()).is_unstable()
1412 }
1413}
1414
1415impl HasVisibility for Struct {
1416 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1417 db.struct_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1418 }
1419}
1420
1421#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1422pub struct Union {
1423 pub(crate) id: UnionId,
1424}
1425
1426impl Union {
1427 pub fn name(self, db: &dyn HirDatabase) -> Name {
1428 db.union_data(self.id).name.clone()
1429 }
1430
1431 pub fn module(self, db: &dyn HirDatabase) -> Module {
1432 Module { id: self.id.lookup(db.upcast()).container }
1433 }
1434
1435 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1436 Type::from_def(db, self.id)
1437 }
1438
1439 pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
1440 Type::from_value_def(db, self.id)
1441 }
1442
1443 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
1444 db.union_data(self.id)
1445 .variant_data
1446 .fields()
1447 .iter()
1448 .map(|(id, _)| Field { parent: self.into(), id })
1449 .collect()
1450 }
1451
1452 fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
1453 db.union_data(self.id).variant_data.clone()
1454 }
1455
1456 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1457 db.attrs(self.id.into()).is_unstable()
1458 }
1459}
1460
1461impl HasVisibility for Union {
1462 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1463 db.union_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1464 }
1465}
1466
1467#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1468pub struct Enum {
1469 pub(crate) id: EnumId,
1470}
1471
1472impl Enum {
1473 pub fn module(self, db: &dyn HirDatabase) -> Module {
1474 Module { id: self.id.lookup(db.upcast()).container }
1475 }
1476
1477 pub fn name(self, db: &dyn HirDatabase) -> Name {
1478 db.enum_data(self.id).name.clone()
1479 }
1480
1481 pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> {
1482 db.enum_data(self.id).variants.iter().map(|&(id, _)| Variant { id }).collect()
1483 }
1484
1485 pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
1486 db.enum_data(self.id).repr
1487 }
1488
1489 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1490 Type::from_def(db, self.id)
1491 }
1492
1493 pub fn variant_body_ty(self, db: &dyn HirDatabase) -> Type {
1495 Type::new_for_crate(
1496 self.id.lookup(db.upcast()).container.krate(),
1497 TyBuilder::builtin(match db.enum_data(self.id).variant_body_type() {
1498 layout::IntegerType::Pointer(sign) => match sign {
1499 true => hir_def::builtin_type::BuiltinType::Int(
1500 hir_def::builtin_type::BuiltinInt::Isize,
1501 ),
1502 false => hir_def::builtin_type::BuiltinType::Uint(
1503 hir_def::builtin_type::BuiltinUint::Usize,
1504 ),
1505 },
1506 layout::IntegerType::Fixed(i, sign) => match sign {
1507 true => hir_def::builtin_type::BuiltinType::Int(match i {
1508 layout::Integer::I8 => hir_def::builtin_type::BuiltinInt::I8,
1509 layout::Integer::I16 => hir_def::builtin_type::BuiltinInt::I16,
1510 layout::Integer::I32 => hir_def::builtin_type::BuiltinInt::I32,
1511 layout::Integer::I64 => hir_def::builtin_type::BuiltinInt::I64,
1512 layout::Integer::I128 => hir_def::builtin_type::BuiltinInt::I128,
1513 }),
1514 false => hir_def::builtin_type::BuiltinType::Uint(match i {
1515 layout::Integer::I8 => hir_def::builtin_type::BuiltinUint::U8,
1516 layout::Integer::I16 => hir_def::builtin_type::BuiltinUint::U16,
1517 layout::Integer::I32 => hir_def::builtin_type::BuiltinUint::U32,
1518 layout::Integer::I64 => hir_def::builtin_type::BuiltinUint::U64,
1519 layout::Integer::I128 => hir_def::builtin_type::BuiltinUint::U128,
1520 }),
1521 },
1522 }),
1523 )
1524 }
1525
1526 pub fn is_data_carrying(self, db: &dyn HirDatabase) -> bool {
1528 self.variants(db).iter().any(|v| !matches!(v.kind(db), StructKind::Unit))
1529 }
1530
1531 pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
1532 Adt::from(self).layout(db)
1533 }
1534
1535 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1536 db.attrs(self.id.into()).is_unstable()
1537 }
1538}
1539
1540impl HasVisibility for Enum {
1541 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1542 db.enum_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1543 }
1544}
1545
1546impl From<&Variant> for DefWithBodyId {
1547 fn from(&v: &Variant) -> Self {
1548 DefWithBodyId::VariantId(v.into())
1549 }
1550}
1551
1552#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1553pub struct Variant {
1554 pub(crate) id: EnumVariantId,
1555}
1556
1557impl Variant {
1558 pub fn module(self, db: &dyn HirDatabase) -> Module {
1559 Module { id: self.id.module(db.upcast()) }
1560 }
1561
1562 pub fn parent_enum(self, db: &dyn HirDatabase) -> Enum {
1563 self.id.lookup(db.upcast()).parent.into()
1564 }
1565
1566 pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
1567 Type::from_value_def(db, self.id)
1568 }
1569
1570 pub fn name(self, db: &dyn HirDatabase) -> Name {
1571 db.enum_variant_data(self.id).name.clone()
1572 }
1573
1574 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
1575 self.variant_data(db)
1576 .fields()
1577 .iter()
1578 .map(|(id, _)| Field { parent: self.into(), id })
1579 .collect()
1580 }
1581
1582 pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
1583 self.variant_data(db).kind()
1584 }
1585
1586 pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
1587 db.enum_variant_data(self.id).variant_data.clone()
1588 }
1589
1590 pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
1591 self.source(db)?.value.expr()
1592 }
1593
1594 pub fn eval(self, db: &dyn HirDatabase) -> Result<i128, ConstEvalError> {
1595 db.const_eval_discriminant(self.into())
1596 }
1597
1598 pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
1599 let parent_enum = self.parent_enum(db);
1600 let parent_layout = parent_enum.layout(db)?;
1601 Ok(match &parent_layout.0.variants {
1602 layout::Variants::Multiple { variants, .. } => Layout(
1603 {
1604 let lookup = self.id.lookup(db.upcast());
1605 let rustc_enum_variant_idx = RustcEnumVariantIdx(lookup.index as usize);
1606 Arc::new(variants[rustc_enum_variant_idx].clone())
1607 },
1608 db.target_data_layout(parent_enum.krate(db).into()).unwrap(),
1609 ),
1610 _ => parent_layout,
1611 })
1612 }
1613
1614 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1615 db.attrs(self.id.into()).is_unstable()
1616 }
1617}
1618
1619impl HasVisibility for Variant {
1621 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1622 self.parent_enum(db).visibility(db)
1623 }
1624}
1625
1626#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1628pub enum Adt {
1629 Struct(Struct),
1630 Union(Union),
1631 Enum(Enum),
1632}
1633impl_from!(Struct, Union, Enum for Adt);
1634
1635impl Adt {
1636 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
1637 let subst = db.generic_defaults(self.into());
1638 subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
1639 GenericArgData::Ty(it) => it.is_unknown(),
1640 _ => false,
1641 })
1642 }
1643
1644 pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
1645 db.layout_of_adt(
1646 self.into(),
1647 TyBuilder::adt(db, self.into())
1648 .fill_with_defaults(db, || TyKind::Error.intern(Interner))
1649 .build_into_subst(),
1650 db.trait_environment(self.into()),
1651 )
1652 .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).id).unwrap()))
1653 }
1654
1655 pub fn ty(self, db: &dyn HirDatabase) -> Type {
1659 let id = AdtId::from(self);
1660 Type::from_def(db, id)
1661 }
1662
1663 pub fn ty_with_args(self, db: &dyn HirDatabase, args: impl Iterator<Item = Type>) -> Type {
1666 let id = AdtId::from(self);
1667 let mut it = args.map(|t| t.ty);
1668 let ty = TyBuilder::def_ty(db, id.into(), None)
1669 .fill(|x| {
1670 let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
1671 match x {
1672 ParamKind::Type => r.cast(Interner),
1673 ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
1674 ParamKind::Lifetime => error_lifetime().cast(Interner),
1675 }
1676 })
1677 .build();
1678 Type::new(db, id, ty)
1679 }
1680
1681 pub fn module(self, db: &dyn HirDatabase) -> Module {
1682 match self {
1683 Adt::Struct(s) => s.module(db),
1684 Adt::Union(s) => s.module(db),
1685 Adt::Enum(e) => e.module(db),
1686 }
1687 }
1688
1689 pub fn name(self, db: &dyn HirDatabase) -> Name {
1690 match self {
1691 Adt::Struct(s) => s.name(db),
1692 Adt::Union(u) => u.name(db),
1693 Adt::Enum(e) => e.name(db),
1694 }
1695 }
1696
1697 pub fn lifetime(&self, db: &dyn HirDatabase) -> Option<LifetimeParamData> {
1699 let resolver = match self {
1700 Adt::Struct(s) => s.id.resolver(db.upcast()),
1701 Adt::Union(u) => u.id.resolver(db.upcast()),
1702 Adt::Enum(e) => e.id.resolver(db.upcast()),
1703 };
1704 resolver
1705 .generic_params()
1706 .and_then(|gp| {
1707 gp.iter_lt()
1708 .nth(0)
1711 })
1712 .map(|arena| arena.1.clone())
1713 }
1714
1715 pub fn as_struct(&self) -> Option<Struct> {
1716 if let Self::Struct(v) = self {
1717 Some(*v)
1718 } else {
1719 None
1720 }
1721 }
1722
1723 pub fn as_enum(&self) -> Option<Enum> {
1724 if let Self::Enum(v) = self {
1725 Some(*v)
1726 } else {
1727 None
1728 }
1729 }
1730}
1731
1732impl HasVisibility for Adt {
1733 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1734 match self {
1735 Adt::Struct(it) => it.visibility(db),
1736 Adt::Union(it) => it.visibility(db),
1737 Adt::Enum(it) => it.visibility(db),
1738 }
1739 }
1740}
1741
1742#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1743pub enum VariantDef {
1744 Struct(Struct),
1745 Union(Union),
1746 Variant(Variant),
1747}
1748impl_from!(Struct, Union, Variant for VariantDef);
1749
1750impl VariantDef {
1751 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
1752 match self {
1753 VariantDef::Struct(it) => it.fields(db),
1754 VariantDef::Union(it) => it.fields(db),
1755 VariantDef::Variant(it) => it.fields(db),
1756 }
1757 }
1758
1759 pub fn module(self, db: &dyn HirDatabase) -> Module {
1760 match self {
1761 VariantDef::Struct(it) => it.module(db),
1762 VariantDef::Union(it) => it.module(db),
1763 VariantDef::Variant(it) => it.module(db),
1764 }
1765 }
1766
1767 pub fn name(&self, db: &dyn HirDatabase) -> Name {
1768 match self {
1769 VariantDef::Struct(s) => s.name(db),
1770 VariantDef::Union(u) => u.name(db),
1771 VariantDef::Variant(e) => e.name(db),
1772 }
1773 }
1774
1775 pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
1776 match self {
1777 VariantDef::Struct(it) => it.variant_data(db),
1778 VariantDef::Union(it) => it.variant_data(db),
1779 VariantDef::Variant(it) => it.variant_data(db),
1780 }
1781 }
1782}
1783
1784#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1786pub enum DefWithBody {
1787 Function(Function),
1788 Static(Static),
1789 Const(Const),
1790 Variant(Variant),
1791 InTypeConst(InTypeConst),
1792}
1793impl_from!(Function, Const, Static, Variant, InTypeConst for DefWithBody);
1794
1795impl DefWithBody {
1796 pub fn module(self, db: &dyn HirDatabase) -> Module {
1797 match self {
1798 DefWithBody::Const(c) => c.module(db),
1799 DefWithBody::Function(f) => f.module(db),
1800 DefWithBody::Static(s) => s.module(db),
1801 DefWithBody::Variant(v) => v.module(db),
1802 DefWithBody::InTypeConst(c) => c.module(db),
1803 }
1804 }
1805
1806 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
1807 match self {
1808 DefWithBody::Function(f) => Some(f.name(db)),
1809 DefWithBody::Static(s) => Some(s.name(db)),
1810 DefWithBody::Const(c) => c.name(db),
1811 DefWithBody::Variant(v) => Some(v.name(db)),
1812 DefWithBody::InTypeConst(_) => None,
1813 }
1814 }
1815
1816 pub fn body_type(self, db: &dyn HirDatabase) -> Type {
1818 match self {
1819 DefWithBody::Function(it) => it.ret_type(db),
1820 DefWithBody::Static(it) => it.ty(db),
1821 DefWithBody::Const(it) => it.ty(db),
1822 DefWithBody::Variant(it) => it.parent_enum(db).variant_body_ty(db),
1823 DefWithBody::InTypeConst(it) => Type::new_with_resolver_inner(
1824 db,
1825 &DefWithBodyId::from(it.id).resolver(db.upcast()),
1826 TyKind::Error.intern(Interner),
1827 ),
1828 }
1829 }
1830
1831 fn id(&self) -> DefWithBodyId {
1832 match self {
1833 DefWithBody::Function(it) => it.id.into(),
1834 DefWithBody::Static(it) => it.id.into(),
1835 DefWithBody::Const(it) => it.id.into(),
1836 DefWithBody::Variant(it) => it.into(),
1837 DefWithBody::InTypeConst(it) => it.id.into(),
1838 }
1839 }
1840
1841 pub fn debug_hir(self, db: &dyn HirDatabase) -> String {
1843 let body = db.body(self.id());
1844 body.pretty_print(db.upcast(), self.id(), Edition::CURRENT)
1845 }
1846
1847 pub fn debug_mir(self, db: &dyn HirDatabase) -> String {
1849 let body = db.mir_body(self.id());
1850 match body {
1851 Ok(body) => body.pretty_print(db),
1852 Err(e) => format!("error:\n{e:?}"),
1853 }
1854 }
1855
1856 pub fn diagnostics(
1857 self,
1858 db: &dyn HirDatabase,
1859 acc: &mut Vec<AnyDiagnostic>,
1860 style_lints: bool,
1861 ) {
1862 let krate = self.module(db).id.krate();
1863
1864 let (body, source_map) = db.body_with_source_map(self.into());
1865 let item_tree_source_maps;
1866 let outer_types_source_map = match self {
1867 DefWithBody::Function(function) => {
1868 let function = function.id.lookup(db.upcast()).id;
1869 item_tree_source_maps = function.item_tree_with_source_map(db.upcast()).1;
1870 item_tree_source_maps.function(function.value).item()
1871 }
1872 DefWithBody::Static(statik) => {
1873 let statik = statik.id.lookup(db.upcast()).id;
1874 item_tree_source_maps = statik.item_tree_with_source_map(db.upcast()).1;
1875 item_tree_source_maps.statik(statik.value)
1876 }
1877 DefWithBody::Const(konst) => {
1878 let konst = konst.id.lookup(db.upcast()).id;
1879 item_tree_source_maps = konst.item_tree_with_source_map(db.upcast()).1;
1880 item_tree_source_maps.konst(konst.value)
1881 }
1882 DefWithBody::Variant(_) | DefWithBody::InTypeConst(_) => &TypesSourceMap::EMPTY,
1883 };
1884
1885 for (_, def_map) in body.blocks(db.upcast()) {
1886 Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc, style_lints);
1887 }
1888
1889 source_map
1890 .macro_calls()
1891 .for_each(|(_ast_id, call_id)| macro_call_diagnostics(db, call_id.macro_call_id, acc));
1892
1893 for diag in source_map.diagnostics() {
1894 acc.push(match diag {
1895 ExpressionStoreDiagnostics::InactiveCode { node, cfg, opts } => {
1896 InactiveCode { node: *node, cfg: cfg.clone(), opts: opts.clone() }.into()
1897 }
1898 ExpressionStoreDiagnostics::MacroError { node, err } => {
1899 let RenderedExpandError { message, error, kind } =
1900 err.render_to_string(db.upcast());
1901
1902 let precise_location = if err.span().anchor.file_id == node.file_id {
1903 Some(
1904 err.span().range
1905 + db.ast_id_map(err.span().anchor.file_id.into())
1906 .get_erased(err.span().anchor.ast_id)
1907 .text_range()
1908 .start(),
1909 )
1910 } else {
1911 None
1912 };
1913 MacroError {
1914 node: (*node).map(|it| it.into()),
1915 precise_location,
1916 message,
1917 error,
1918 kind,
1919 }
1920 .into()
1921 }
1922 ExpressionStoreDiagnostics::UnresolvedMacroCall { node, path } => {
1923 UnresolvedMacroCall {
1924 macro_call: (*node).map(|ast_ptr| ast_ptr.into()),
1925 precise_location: None,
1926 path: path.clone(),
1927 is_bang: true,
1928 }
1929 .into()
1930 }
1931 ExpressionStoreDiagnostics::AwaitOutsideOfAsync { node, location } => {
1932 AwaitOutsideOfAsync { node: *node, location: location.clone() }.into()
1933 }
1934 ExpressionStoreDiagnostics::UnreachableLabel { node, name } => {
1935 UnreachableLabel { node: *node, name: name.clone() }.into()
1936 }
1937 ExpressionStoreDiagnostics::UndeclaredLabel { node, name } => {
1938 UndeclaredLabel { node: *node, name: name.clone() }.into()
1939 }
1940 });
1941 }
1942
1943 let infer = db.infer(self.into());
1944 for d in &infer.diagnostics {
1945 acc.extend(AnyDiagnostic::inference_diagnostic(
1946 db,
1947 self.into(),
1948 d,
1949 outer_types_source_map,
1950 &source_map,
1951 ));
1952 }
1953
1954 for (pat_or_expr, mismatch) in infer.type_mismatches() {
1955 let expr_or_pat = match pat_or_expr {
1956 ExprOrPatId::ExprId(expr) => source_map.expr_syntax(expr).map(Either::Left),
1957 ExprOrPatId::PatId(pat) => source_map.pat_syntax(pat).map(Either::Right),
1958 };
1959 let expr_or_pat = match expr_or_pat {
1960 Ok(Either::Left(expr)) => expr,
1961 Ok(Either::Right(InFile { file_id, value: pat })) => {
1962 let Some(ptr) = AstPtr::try_from_raw(pat.syntax_node_ptr()) else {
1964 continue;
1965 };
1966 InFile { file_id, value: ptr }
1967 }
1968 Err(SyntheticSyntax) => continue,
1969 };
1970
1971 acc.push(
1972 TypeMismatch {
1973 expr_or_pat,
1974 expected: Type::new(db, DefWithBodyId::from(self), mismatch.expected.clone()),
1975 actual: Type::new(db, DefWithBodyId::from(self), mismatch.actual.clone()),
1976 }
1977 .into(),
1978 );
1979 }
1980
1981 let missing_unsafe = hir_ty::diagnostics::missing_unsafe(db, self.into());
1982 for (node, reason) in missing_unsafe.unsafe_exprs {
1983 match source_map.expr_or_pat_syntax(node) {
1984 Ok(node) => acc.push(
1985 MissingUnsafe {
1986 node,
1987 lint: if missing_unsafe.fn_is_unsafe {
1988 UnsafeLint::UnsafeOpInUnsafeFn
1989 } else {
1990 UnsafeLint::HardError
1991 },
1992 reason,
1993 }
1994 .into(),
1995 ),
1996 Err(SyntheticSyntax) => {
1997 }
2000 }
2001 }
2002 for node in missing_unsafe.deprecated_safe_calls {
2003 match source_map.expr_syntax(node) {
2004 Ok(node) => acc.push(
2005 MissingUnsafe {
2006 node,
2007 lint: UnsafeLint::DeprecatedSafe2024,
2008 reason: UnsafetyReason::UnsafeFnCall,
2009 }
2010 .into(),
2011 ),
2012 Err(SyntheticSyntax) => never!("synthetic DeprecatedSafe2024"),
2013 }
2014 }
2015
2016 if let Ok(borrowck_results) = db.borrowck(self.into()) {
2017 for borrowck_result in borrowck_results.iter() {
2018 let mir_body = &borrowck_result.mir_body;
2019 for moof in &borrowck_result.moved_out_of_ref {
2020 let span: InFile<SyntaxNodePtr> = match moof.span {
2021 mir::MirSpan::ExprId(e) => match source_map.expr_syntax(e) {
2022 Ok(s) => s.map(|it| it.into()),
2023 Err(_) => continue,
2024 },
2025 mir::MirSpan::PatId(p) => match source_map.pat_syntax(p) {
2026 Ok(s) => s.map(|it| it.into()),
2027 Err(_) => continue,
2028 },
2029 mir::MirSpan::SelfParam => match source_map.self_param_syntax() {
2030 Some(s) => s.map(|it| it.into()),
2031 None => continue,
2032 },
2033 mir::MirSpan::BindingId(b) => {
2034 match source_map
2035 .patterns_for_binding(b)
2036 .iter()
2037 .find_map(|p| source_map.pat_syntax(*p).ok())
2038 {
2039 Some(s) => s.map(|it| it.into()),
2040 None => continue,
2041 }
2042 }
2043 mir::MirSpan::Unknown => continue,
2044 };
2045 acc.push(
2046 MovedOutOfRef { ty: Type::new_for_crate(krate, moof.ty.clone()), span }
2047 .into(),
2048 )
2049 }
2050 let mol = &borrowck_result.mutability_of_locals;
2051 for (binding_id, binding_data) in body.bindings.iter() {
2052 if binding_data.problems.is_some() {
2053 continue;
2055 }
2056 let Some(&local) = mir_body.binding_locals.get(binding_id) else {
2057 continue;
2058 };
2059 if source_map
2060 .patterns_for_binding(binding_id)
2061 .iter()
2062 .any(|&pat| source_map.pat_syntax(pat).is_err())
2063 {
2064 continue;
2066 }
2067 let mut need_mut = &mol[local];
2068 if body[binding_id].name == sym::self_.clone()
2069 && need_mut == &mir::MutabilityReason::Unused
2070 {
2071 need_mut = &mir::MutabilityReason::Not;
2072 }
2073 let local = Local { parent: self.into(), binding_id };
2074 let is_mut = body[binding_id].mode == BindingAnnotation::Mutable;
2075
2076 match (need_mut, is_mut) {
2077 (mir::MutabilityReason::Unused, _) => {
2078 let should_ignore = body[binding_id].name.as_str().starts_with('_');
2079 if !should_ignore {
2080 acc.push(UnusedVariable { local }.into())
2081 }
2082 }
2083 (mir::MutabilityReason::Mut { .. }, true)
2084 | (mir::MutabilityReason::Not, false) => (),
2085 (mir::MutabilityReason::Mut { spans }, false) => {
2086 for span in spans {
2087 let span: InFile<SyntaxNodePtr> = match span {
2088 mir::MirSpan::ExprId(e) => match source_map.expr_syntax(*e) {
2089 Ok(s) => s.map(|it| it.into()),
2090 Err(_) => continue,
2091 },
2092 mir::MirSpan::PatId(p) => match source_map.pat_syntax(*p) {
2093 Ok(s) => s.map(|it| it.into()),
2094 Err(_) => continue,
2095 },
2096 mir::MirSpan::BindingId(b) => {
2097 match source_map
2098 .patterns_for_binding(*b)
2099 .iter()
2100 .find_map(|p| source_map.pat_syntax(*p).ok())
2101 {
2102 Some(s) => s.map(|it| it.into()),
2103 None => continue,
2104 }
2105 }
2106 mir::MirSpan::SelfParam => match source_map.self_param_syntax()
2107 {
2108 Some(s) => s.map(|it| it.into()),
2109 None => continue,
2110 },
2111 mir::MirSpan::Unknown => continue,
2112 };
2113 acc.push(NeedMut { local, span }.into());
2114 }
2115 }
2116 (mir::MutabilityReason::Not, true) => {
2117 if !infer.mutated_bindings_in_closure.contains(&binding_id) {
2118 let should_ignore = body[binding_id].name.as_str().starts_with('_');
2119 if !should_ignore {
2120 acc.push(UnusedMut { local }.into())
2121 }
2122 }
2123 }
2124 }
2125 }
2126 }
2127 }
2128
2129 for diagnostic in BodyValidationDiagnostic::collect(db, self.into(), style_lints) {
2130 acc.extend(AnyDiagnostic::body_validation_diagnostic(db, diagnostic, &source_map));
2131 }
2132
2133 let def: ModuleDef = match self {
2134 DefWithBody::Function(it) => it.into(),
2135 DefWithBody::Static(it) => it.into(),
2136 DefWithBody::Const(it) => it.into(),
2137 DefWithBody::Variant(it) => it.into(),
2138 DefWithBody::InTypeConst(_) => return,
2140 };
2141 for diag in hir_ty::diagnostics::incorrect_case(db, def.into()) {
2142 acc.push(diag.into())
2143 }
2144 }
2145}
2146#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2147pub struct Function {
2148 pub(crate) id: FunctionId,
2149}
2150
2151impl Function {
2152 pub fn module(self, db: &dyn HirDatabase) -> Module {
2153 self.id.module(db.upcast()).into()
2154 }
2155
2156 pub fn name(self, db: &dyn HirDatabase) -> Name {
2157 db.function_data(self.id).name.clone()
2158 }
2159
2160 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2161 Type::from_value_def(db, self.id)
2162 }
2163
2164 pub fn fn_ptr_type(self, db: &dyn HirDatabase) -> Type {
2165 let resolver = self.id.resolver(db.upcast());
2166 let substs = TyBuilder::placeholder_subst(db, self.id);
2167 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
2168 let ty = TyKind::Function(callable_sig.to_fn_ptr()).intern(Interner);
2169 Type::new_with_resolver_inner(db, &resolver, ty)
2170 }
2171
2172 pub fn ret_type(self, db: &dyn HirDatabase) -> Type {
2174 let resolver = self.id.resolver(db.upcast());
2175 let substs = TyBuilder::placeholder_subst(db, self.id);
2176 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
2177 let ty = callable_sig.ret().clone();
2178 Type::new_with_resolver_inner(db, &resolver, ty)
2179 }
2180
2181 pub fn ret_type_with_args(
2183 self,
2184 db: &dyn HirDatabase,
2185 generics: impl Iterator<Item = Type>,
2186 ) -> Type {
2187 let resolver = self.id.resolver(db.upcast());
2188 let parent_id: Option<GenericDefId> = match self.id.lookup(db.upcast()).container {
2189 ItemContainerId::ImplId(it) => Some(it.into()),
2190 ItemContainerId::TraitId(it) => Some(it.into()),
2191 ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
2192 };
2193 let mut generics = generics.map(|it| it.ty);
2194 let mut filler = |x: &_| match x {
2195 ParamKind::Type => {
2196 generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
2197 }
2198 ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
2199 ParamKind::Lifetime => error_lifetime().cast(Interner),
2200 };
2201
2202 let parent_substs =
2203 parent_id.map(|id| TyBuilder::subst_for_def(db, id, None).fill(&mut filler).build());
2204 let substs = TyBuilder::subst_for_def(db, self.id, parent_substs).fill(&mut filler).build();
2205
2206 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
2207 let ty = callable_sig.ret().clone();
2208 Type::new_with_resolver_inner(db, &resolver, ty)
2209 }
2210
2211 pub fn async_ret_type(self, db: &dyn HirDatabase) -> Option<Type> {
2212 if !self.is_async(db) {
2213 return None;
2214 }
2215 let resolver = self.id.resolver(db.upcast());
2216 let substs = TyBuilder::placeholder_subst(db, self.id);
2217 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
2218 let ret_ty = callable_sig.ret().clone();
2219 for pred in ret_ty.impl_trait_bounds(db).into_iter().flatten() {
2220 if let WhereClause::AliasEq(output_eq) = pred.into_value_and_skipped_binders().0 {
2221 return Type::new_with_resolver_inner(db, &resolver, output_eq.ty).into();
2222 }
2223 }
2224 None
2225 }
2226
2227 pub fn has_self_param(self, db: &dyn HirDatabase) -> bool {
2228 db.function_data(self.id).has_self_param()
2229 }
2230
2231 pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
2232 self.has_self_param(db).then_some(SelfParam { func: self.id })
2233 }
2234
2235 pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param> {
2236 let environment = db.trait_environment(self.id.into());
2237 let substs = TyBuilder::placeholder_subst(db, self.id);
2238 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
2239 callable_sig
2240 .params()
2241 .iter()
2242 .enumerate()
2243 .map(|(idx, ty)| {
2244 let ty = Type { env: environment.clone(), ty: ty.clone() };
2245 Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
2246 })
2247 .collect()
2248 }
2249
2250 pub fn num_params(self, db: &dyn HirDatabase) -> usize {
2251 db.function_data(self.id).params.len()
2252 }
2253
2254 pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> {
2255 self.self_param(db)?;
2256 Some(self.params_without_self(db))
2257 }
2258
2259 pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec<Param> {
2260 let environment = db.trait_environment(self.id.into());
2261 let substs = TyBuilder::placeholder_subst(db, self.id);
2262 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
2263 let skip = if db.function_data(self.id).has_self_param() { 1 } else { 0 };
2264 callable_sig
2265 .params()
2266 .iter()
2267 .enumerate()
2268 .skip(skip)
2269 .map(|(idx, ty)| {
2270 let ty = Type { env: environment.clone(), ty: ty.clone() };
2271 Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
2272 })
2273 .collect()
2274 }
2275
2276 pub fn params_without_self_with_args(
2278 self,
2279 db: &dyn HirDatabase,
2280 generics: impl Iterator<Item = Type>,
2281 ) -> Vec<Param> {
2282 let environment = db.trait_environment(self.id.into());
2283 let parent_id: Option<GenericDefId> = match self.id.lookup(db.upcast()).container {
2284 ItemContainerId::ImplId(it) => Some(it.into()),
2285 ItemContainerId::TraitId(it) => Some(it.into()),
2286 ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
2287 };
2288 let mut generics = generics.map(|it| it.ty);
2289 let parent_substs = parent_id.map(|id| {
2290 TyBuilder::subst_for_def(db, id, None)
2291 .fill(|x| match x {
2292 ParamKind::Type => generics
2293 .next()
2294 .unwrap_or_else(|| TyKind::Error.intern(Interner))
2295 .cast(Interner),
2296 ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
2297 ParamKind::Lifetime => error_lifetime().cast(Interner),
2298 })
2299 .build()
2300 });
2301
2302 let substs = TyBuilder::subst_for_def(db, self.id, parent_substs)
2303 .fill(|_| {
2304 let ty = generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
2305 GenericArg::new(Interner, GenericArgData::Ty(ty))
2306 })
2307 .build();
2308 let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
2309 let skip = if db.function_data(self.id).has_self_param() { 1 } else { 0 };
2310 callable_sig
2311 .params()
2312 .iter()
2313 .enumerate()
2314 .skip(skip)
2315 .map(|(idx, ty)| {
2316 let ty = Type { env: environment.clone(), ty: ty.clone() };
2317 Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
2318 })
2319 .collect()
2320 }
2321
2322 pub fn is_const(self, db: &dyn HirDatabase) -> bool {
2323 db.function_data(self.id).is_const()
2324 }
2325
2326 pub fn is_async(self, db: &dyn HirDatabase) -> bool {
2327 db.function_data(self.id).is_async()
2328 }
2329
2330 pub fn extern_block(self, db: &dyn HirDatabase) -> Option<ExternBlock> {
2331 match self.id.lookup(db.upcast()).container {
2332 ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }),
2333 _ => None,
2334 }
2335 }
2336
2337 pub fn returns_impl_future(self, db: &dyn HirDatabase) -> bool {
2338 if self.is_async(db) {
2339 return true;
2340 }
2341
2342 let Some(impl_traits) = self.ret_type(db).as_impl_traits(db) else { return false };
2343 let Some(future_trait_id) =
2344 db.lang_item(self.ty(db).env.krate, LangItem::Future).and_then(|t| t.as_trait())
2345 else {
2346 return false;
2347 };
2348 let Some(sized_trait_id) =
2349 db.lang_item(self.ty(db).env.krate, LangItem::Sized).and_then(|t| t.as_trait())
2350 else {
2351 return false;
2352 };
2353
2354 let mut has_impl_future = false;
2355 impl_traits
2356 .filter(|t| {
2357 let fut = t.id == future_trait_id;
2358 has_impl_future |= fut;
2359 !fut && t.id != sized_trait_id
2360 })
2361 .all(|t| t.is_auto(db))
2363 && has_impl_future
2364 }
2365
2366 pub fn is_test(self, db: &dyn HirDatabase) -> bool {
2368 db.attrs(self.id.into()).is_test()
2369 }
2370
2371 pub fn is_main(self, db: &dyn HirDatabase) -> bool {
2373 db.attrs(self.id.into()).export_name() == Some(&sym::main)
2374 || self.module(db).is_crate_root() && db.function_data(self.id).name == sym::main
2375 }
2376
2377 pub fn exported_main(self, db: &dyn HirDatabase) -> bool {
2379 db.attrs(self.id.into()).export_name() == Some(&sym::main)
2380 }
2381
2382 pub fn is_ignore(self, db: &dyn HirDatabase) -> bool {
2384 db.attrs(self.id.into()).is_ignore()
2385 }
2386
2387 pub fn is_bench(self, db: &dyn HirDatabase) -> bool {
2389 db.attrs(self.id.into()).is_bench()
2390 }
2391
2392 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
2394 db.attrs(self.id.into()).is_unstable()
2395 }
2396
2397 pub fn is_unsafe_to_call(
2398 self,
2399 db: &dyn HirDatabase,
2400 caller: Option<Function>,
2401 call_edition: Edition,
2402 ) -> bool {
2403 let target_features = caller
2404 .map(|caller| hir_ty::TargetFeatures::from_attrs(&db.attrs(caller.id.into())))
2405 .unwrap_or_default();
2406 matches!(
2407 hir_ty::is_fn_unsafe_to_call(db, self.id, &target_features, call_edition),
2408 hir_ty::Unsafety::Unsafe
2409 )
2410 }
2411
2412 pub fn has_body(self, db: &dyn HirDatabase) -> bool {
2416 db.function_data(self.id).has_body()
2417 }
2418
2419 pub fn as_proc_macro(self, db: &dyn HirDatabase) -> Option<Macro> {
2420 let attrs = db.attrs(self.id.into());
2421 if !(attrs.is_proc_macro()
2423 || attrs.is_proc_macro_attribute()
2424 || attrs.is_proc_macro_derive())
2425 {
2426 return None;
2427 }
2428 let def_map = db.crate_def_map(HasModule::krate(&self.id, db.upcast()));
2429 def_map.fn_as_proc_macro(self.id).map(|id| Macro { id: id.into() })
2430 }
2431
2432 pub fn eval(
2433 self,
2434 db: &dyn HirDatabase,
2435 span_formatter: impl Fn(FileId, TextRange) -> String,
2436 ) -> Result<String, ConstEvalError> {
2437 let krate = HasModule::krate(&self.id, db.upcast());
2438 let edition = db.crate_graph()[krate].edition;
2439 let body = db.monomorphized_mir_body(
2440 self.id.into(),
2441 Substitution::empty(Interner),
2442 db.trait_environment(self.id.into()),
2443 )?;
2444 let (result, output) = interpret_mir(db, body, false, None)?;
2445 let mut text = match result {
2446 Ok(_) => "pass".to_owned(),
2447 Err(e) => {
2448 let mut r = String::new();
2449 _ = e.pretty_print(&mut r, db, &span_formatter, edition);
2450 r
2451 }
2452 };
2453 let stdout = output.stdout().into_owned();
2454 if !stdout.is_empty() {
2455 text += "\n--------- stdout ---------\n";
2456 text += &stdout;
2457 }
2458 let stderr = output.stdout().into_owned();
2459 if !stderr.is_empty() {
2460 text += "\n--------- stderr ---------\n";
2461 text += &stderr;
2462 }
2463 Ok(text)
2464 }
2465}
2466
2467#[derive(Clone, Copy, PartialEq, Eq)]
2469pub enum Access {
2470 Shared,
2471 Exclusive,
2472 Owned,
2473}
2474
2475impl From<hir_ty::Mutability> for Access {
2476 fn from(mutability: hir_ty::Mutability) -> Access {
2477 match mutability {
2478 hir_ty::Mutability::Not => Access::Shared,
2479 hir_ty::Mutability::Mut => Access::Exclusive,
2480 }
2481 }
2482}
2483
2484#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2485pub struct Param {
2486 func: Callee,
2487 idx: usize,
2489 ty: Type,
2490}
2491
2492impl Param {
2493 pub fn parent_fn(&self) -> Option<Function> {
2494 match self.func {
2495 Callee::Def(CallableDefId::FunctionId(f)) => Some(f.into()),
2496 _ => None,
2497 }
2498 }
2499
2500 pub fn index(&self) -> usize {
2505 self.idx
2506 }
2507
2508 pub fn ty(&self) -> &Type {
2509 &self.ty
2510 }
2511
2512 pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
2513 Some(self.as_local(db)?.name(db))
2514 }
2515
2516 pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
2517 match self.func {
2518 Callee::Def(CallableDefId::FunctionId(it)) => {
2519 let parent = DefWithBodyId::FunctionId(it);
2520 let body = db.body(parent);
2521 if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
2522 Some(Local { parent, binding_id: self_param })
2523 } else if let Pat::Bind { id, .. } =
2524 &body[body.params[self.idx - body.self_param.is_some() as usize]]
2525 {
2526 Some(Local { parent, binding_id: *id })
2527 } else {
2528 None
2529 }
2530 }
2531 Callee::Closure(closure, _) => {
2532 let c = db.lookup_intern_closure(closure.into());
2533 let body = db.body(c.0);
2534 if let Expr::Closure { args, .. } = &body[c.1] {
2535 if let Pat::Bind { id, .. } = &body[args[self.idx]] {
2536 return Some(Local { parent: c.0, binding_id: *id });
2537 }
2538 }
2539 None
2540 }
2541 _ => None,
2542 }
2543 }
2544
2545 pub fn pattern_source(self, db: &dyn HirDatabase) -> Option<ast::Pat> {
2546 self.source(db).and_then(|p| p.value.right()?.pat())
2547 }
2548}
2549
2550#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2551pub struct SelfParam {
2552 func: FunctionId,
2553}
2554
2555impl SelfParam {
2556 pub fn access(self, db: &dyn HirDatabase) -> Access {
2557 let func_data = db.function_data(self.func);
2558 func_data
2559 .params
2560 .first()
2561 .map(|¶m| match &func_data.types_map[param] {
2562 TypeRef::Reference(ref_) => match ref_.mutability {
2563 hir_def::type_ref::Mutability::Shared => Access::Shared,
2564 hir_def::type_ref::Mutability::Mut => Access::Exclusive,
2565 },
2566 _ => Access::Owned,
2567 })
2568 .unwrap_or(Access::Owned)
2569 }
2570
2571 pub fn parent_fn(&self) -> Function {
2572 Function::from(self.func)
2573 }
2574
2575 pub fn ty(&self, db: &dyn HirDatabase) -> Type {
2576 let substs = TyBuilder::placeholder_subst(db, self.func);
2577 let callable_sig =
2578 db.callable_item_signature(self.func.into()).substitute(Interner, &substs);
2579 let environment = db.trait_environment(self.func.into());
2580 let ty = callable_sig.params()[0].clone();
2581 Type { env: environment, ty }
2582 }
2583
2584 pub fn ty_with_args(&self, db: &dyn HirDatabase, generics: impl Iterator<Item = Type>) -> Type {
2586 let parent_id: GenericDefId = match self.func.lookup(db.upcast()).container {
2587 ItemContainerId::ImplId(it) => it.into(),
2588 ItemContainerId::TraitId(it) => it.into(),
2589 ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
2590 panic!("Never get here")
2591 }
2592 };
2593
2594 let mut generics = generics.map(|it| it.ty);
2595 let mut filler = |x: &_| match x {
2596 ParamKind::Type => {
2597 generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
2598 }
2599 ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
2600 ParamKind::Lifetime => error_lifetime().cast(Interner),
2601 };
2602
2603 let parent_substs = TyBuilder::subst_for_def(db, parent_id, None).fill(&mut filler).build();
2604 let substs =
2605 TyBuilder::subst_for_def(db, self.func, Some(parent_substs)).fill(&mut filler).build();
2606 let callable_sig =
2607 db.callable_item_signature(self.func.into()).substitute(Interner, &substs);
2608 let environment = db.trait_environment(self.func.into());
2609 let ty = callable_sig.params()[0].clone();
2610 Type { env: environment, ty }
2611 }
2612}
2613
2614impl HasVisibility for Function {
2615 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2616 db.function_visibility(self.id)
2617 }
2618}
2619
2620#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2621pub struct ExternCrateDecl {
2622 pub(crate) id: ExternCrateId,
2623}
2624
2625impl ExternCrateDecl {
2626 pub fn module(self, db: &dyn HirDatabase) -> Module {
2627 self.id.module(db.upcast()).into()
2628 }
2629
2630 pub fn resolved_crate(self, db: &dyn HirDatabase) -> Option<Crate> {
2631 db.extern_crate_decl_data(self.id).crate_id.map(Into::into)
2632 }
2633
2634 pub fn name(self, db: &dyn HirDatabase) -> Name {
2635 db.extern_crate_decl_data(self.id).name.clone()
2636 }
2637
2638 pub fn alias(self, db: &dyn HirDatabase) -> Option<ImportAlias> {
2639 db.extern_crate_decl_data(self.id).alias.clone()
2640 }
2641
2642 pub fn alias_or_name(self, db: &dyn HirDatabase) -> Option<Name> {
2644 let extern_crate_decl_data = db.extern_crate_decl_data(self.id);
2645 match &extern_crate_decl_data.alias {
2646 Some(ImportAlias::Underscore) => None,
2647 Some(ImportAlias::Alias(alias)) => Some(alias.clone()),
2648 None => Some(extern_crate_decl_data.name.clone()),
2649 }
2650 }
2651}
2652
2653impl HasVisibility for ExternCrateDecl {
2654 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2655 db.extern_crate_decl_data(self.id)
2656 .visibility
2657 .resolve(db.upcast(), &self.id.resolver(db.upcast()))
2658 }
2659}
2660
2661#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2662pub struct InTypeConst {
2663 pub(crate) id: InTypeConstId,
2664}
2665
2666impl InTypeConst {
2667 pub fn module(self, db: &dyn HirDatabase) -> Module {
2668 Module { id: self.id.lookup(db.upcast()).owner.module(db.upcast()) }
2669 }
2670}
2671
2672#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2673pub struct Const {
2674 pub(crate) id: ConstId,
2675}
2676
2677impl Const {
2678 pub fn module(self, db: &dyn HirDatabase) -> Module {
2679 Module { id: self.id.module(db.upcast()) }
2680 }
2681
2682 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
2683 db.const_data(self.id).name.clone()
2684 }
2685
2686 pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
2687 self.source(db)?.value.body()
2688 }
2689
2690 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2691 Type::from_value_def(db, self.id)
2692 }
2693
2694 pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst, ConstEvalError> {
2696 db.const_eval(self.id.into(), Substitution::empty(Interner), None)
2697 .map(|it| EvaluatedConst { const_: it, def: self.id.into() })
2698 }
2699}
2700
2701impl HasVisibility for Const {
2702 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2703 db.const_visibility(self.id)
2704 }
2705}
2706
2707pub struct EvaluatedConst {
2708 def: DefWithBodyId,
2709 const_: hir_ty::Const,
2710}
2711
2712impl EvaluatedConst {
2713 pub fn render(&self, db: &dyn HirDatabase, edition: Edition) -> String {
2714 format!("{}", self.const_.display(db, edition))
2715 }
2716
2717 pub fn render_debug(&self, db: &dyn HirDatabase) -> Result<String, MirEvalError> {
2718 let data = self.const_.data(Interner);
2719 if let TyKind::Scalar(s) = data.ty.kind(Interner) {
2720 if matches!(s, Scalar::Int(_) | Scalar::Uint(_)) {
2721 if let hir_ty::ConstValue::Concrete(c) = &data.value {
2722 if let hir_ty::ConstScalar::Bytes(b, _) = &c.interned {
2723 let value = u128::from_le_bytes(mir::pad16(b, false));
2724 let value_signed =
2725 i128::from_le_bytes(mir::pad16(b, matches!(s, Scalar::Int(_))));
2726 let mut result = if let Scalar::Int(_) = s {
2727 value_signed.to_string()
2728 } else {
2729 value.to_string()
2730 };
2731 if value >= 10 {
2732 format_to!(result, " ({value:#X})");
2733 return Ok(result);
2734 } else {
2735 return Ok(result);
2736 }
2737 }
2738 }
2739 }
2740 }
2741 mir::render_const_using_debug_impl(db, self.def, &self.const_)
2742 }
2743}
2744
2745#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2746pub struct Static {
2747 pub(crate) id: StaticId,
2748}
2749
2750impl Static {
2751 pub fn module(self, db: &dyn HirDatabase) -> Module {
2752 Module { id: self.id.module(db.upcast()) }
2753 }
2754
2755 pub fn name(self, db: &dyn HirDatabase) -> Name {
2756 db.static_data(self.id).name.clone()
2757 }
2758
2759 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
2760 db.static_data(self.id).mutable
2761 }
2762
2763 pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
2764 self.source(db)?.value.body()
2765 }
2766
2767 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2768 Type::from_value_def(db, self.id)
2769 }
2770
2771 pub fn extern_block(self, db: &dyn HirDatabase) -> Option<ExternBlock> {
2772 match self.id.lookup(db.upcast()).container {
2773 ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }),
2774 _ => None,
2775 }
2776 }
2777
2778 pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst, ConstEvalError> {
2780 db.const_eval(self.id.into(), Substitution::empty(Interner), None)
2781 .map(|it| EvaluatedConst { const_: it, def: self.id.into() })
2782 }
2783}
2784
2785impl HasVisibility for Static {
2786 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2787 db.static_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
2788 }
2789}
2790
2791#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2792pub struct Trait {
2793 pub(crate) id: TraitId,
2794}
2795
2796impl Trait {
2797 pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option<Trait> {
2798 db.lang_item(krate.into(), LangItem::from_name(name)?)
2799 .and_then(LangItemTarget::as_trait)
2800 .map(Into::into)
2801 }
2802
2803 pub fn module(self, db: &dyn HirDatabase) -> Module {
2804 Module { id: self.id.lookup(db.upcast()).container }
2805 }
2806
2807 pub fn name(self, db: &dyn HirDatabase) -> Name {
2808 db.trait_data(self.id).name.clone()
2809 }
2810
2811 pub fn direct_supertraits(self, db: &dyn HirDatabase) -> Vec<Trait> {
2812 let traits = direct_super_traits(db.upcast(), self.into());
2813 traits.iter().map(|tr| Trait::from(*tr)).collect()
2814 }
2815
2816 pub fn all_supertraits(self, db: &dyn HirDatabase) -> Vec<Trait> {
2817 let traits = all_super_traits(db.upcast(), self.into());
2818 traits.iter().map(|tr| Trait::from(*tr)).collect()
2819 }
2820
2821 pub fn function(self, db: &dyn HirDatabase, name: impl PartialEq<Name>) -> Option<Function> {
2822 db.trait_data(self.id).items.iter().find(|(n, _)| name == *n).and_then(
2823 |&(_, it)| match it {
2824 AssocItemId::FunctionId(id) => Some(Function { id }),
2825 _ => None,
2826 },
2827 )
2828 }
2829
2830 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
2831 db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
2832 }
2833
2834 pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
2835 self.all_supertraits(db).into_iter().flat_map(|tr| tr.items(db)).collect()
2836 }
2837
2838 pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
2839 db.trait_data(self.id).flags.contains(TraitFlags::IS_AUTO)
2840 }
2841
2842 pub fn is_unsafe(&self, db: &dyn HirDatabase) -> bool {
2843 db.trait_data(self.id).flags.contains(TraitFlags::IS_UNSAFE)
2844 }
2845
2846 pub fn type_or_const_param_count(
2847 &self,
2848 db: &dyn HirDatabase,
2849 count_required_only: bool,
2850 ) -> usize {
2851 db.generic_params(self.id.into())
2852 .iter_type_or_consts()
2853 .filter(|(_, ty)| !matches!(ty, TypeOrConstParamData::TypeParamData(ty) if ty.provenance != TypeParamProvenance::TypeParamList))
2854 .filter(|(_, ty)| !count_required_only || !ty.has_default())
2855 .count()
2856 }
2857
2858 pub fn dyn_compatibility(&self, db: &dyn HirDatabase) -> Option<DynCompatibilityViolation> {
2859 hir_ty::dyn_compatibility::dyn_compatibility(db, self.id)
2860 }
2861
2862 pub fn dyn_compatibility_all_violations(
2863 &self,
2864 db: &dyn HirDatabase,
2865 ) -> Option<Vec<DynCompatibilityViolation>> {
2866 let mut violations = vec![];
2867 hir_ty::dyn_compatibility::dyn_compatibility_with_callback(db, self.id, &mut |violation| {
2868 violations.push(violation);
2869 ControlFlow::Continue(())
2870 });
2871 violations.is_empty().not().then_some(violations)
2872 }
2873
2874 fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
2875 db.trait_data(self.id)
2876 .macro_calls
2877 .as_ref()
2878 .map(|it| it.as_ref().clone().into_boxed_slice())
2879 .unwrap_or_default()
2880 }
2881}
2882
2883impl HasVisibility for Trait {
2884 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2885 db.trait_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
2886 }
2887}
2888
2889#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2890pub struct TraitAlias {
2891 pub(crate) id: TraitAliasId,
2892}
2893
2894impl TraitAlias {
2895 pub fn module(self, db: &dyn HirDatabase) -> Module {
2896 Module { id: self.id.lookup(db.upcast()).container }
2897 }
2898
2899 pub fn name(self, db: &dyn HirDatabase) -> Name {
2900 db.trait_alias_data(self.id).name.clone()
2901 }
2902}
2903
2904impl HasVisibility for TraitAlias {
2905 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2906 db.trait_alias_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
2907 }
2908}
2909
2910#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2911pub struct TypeAlias {
2912 pub(crate) id: TypeAliasId,
2913}
2914
2915impl TypeAlias {
2916 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
2917 let subst = db.generic_defaults(self.id.into());
2918 subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
2919 GenericArgData::Ty(it) => it.is_unknown(),
2920 _ => false,
2921 })
2922 }
2923
2924 pub fn module(self, db: &dyn HirDatabase) -> Module {
2925 Module { id: self.id.module(db.upcast()) }
2926 }
2927
2928 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2929 Type::from_def(db, self.id)
2930 }
2931
2932 pub fn name(self, db: &dyn HirDatabase) -> Name {
2933 db.type_alias_data(self.id).name.clone()
2934 }
2935}
2936
2937impl HasVisibility for TypeAlias {
2938 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2939 let function_data = db.type_alias_data(self.id);
2940 let visibility = &function_data.visibility;
2941 visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
2942 }
2943}
2944
2945#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2946pub struct ExternBlock {
2947 pub(crate) id: ExternBlockId,
2948}
2949
2950impl ExternBlock {
2951 pub fn module(self, db: &dyn HirDatabase) -> Module {
2952 Module { id: self.id.module(db.upcast()) }
2953 }
2954}
2955
2956#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2957pub struct StaticLifetime;
2958
2959impl StaticLifetime {
2960 pub fn name(self) -> Name {
2961 Name::new_symbol_root(sym::tick_static.clone())
2962 }
2963}
2964
2965#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2966pub struct BuiltinType {
2967 pub(crate) inner: hir_def::builtin_type::BuiltinType,
2968}
2969
2970impl BuiltinType {
2971 pub fn str() -> BuiltinType {
2972 BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
2973 }
2974
2975 pub fn ty(self, db: &dyn HirDatabase) -> Type {
2976 Type::new_for_crate(db.crate_graph().iter().next().unwrap(), TyBuilder::builtin(self.inner))
2977 }
2978
2979 pub fn name(self) -> Name {
2980 self.inner.as_name()
2981 }
2982
2983 pub fn is_int(&self) -> bool {
2984 matches!(self.inner, hir_def::builtin_type::BuiltinType::Int(_))
2985 }
2986
2987 pub fn is_uint(&self) -> bool {
2988 matches!(self.inner, hir_def::builtin_type::BuiltinType::Uint(_))
2989 }
2990
2991 pub fn is_float(&self) -> bool {
2992 matches!(self.inner, hir_def::builtin_type::BuiltinType::Float(_))
2993 }
2994
2995 pub fn is_f16(&self) -> bool {
2996 matches!(
2997 self.inner,
2998 hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F16)
2999 )
3000 }
3001
3002 pub fn is_f32(&self) -> bool {
3003 matches!(
3004 self.inner,
3005 hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F32)
3006 )
3007 }
3008
3009 pub fn is_f64(&self) -> bool {
3010 matches!(
3011 self.inner,
3012 hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F64)
3013 )
3014 }
3015
3016 pub fn is_f128(&self) -> bool {
3017 matches!(
3018 self.inner,
3019 hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F128)
3020 )
3021 }
3022
3023 pub fn is_char(&self) -> bool {
3024 matches!(self.inner, hir_def::builtin_type::BuiltinType::Char)
3025 }
3026
3027 pub fn is_bool(&self) -> bool {
3028 matches!(self.inner, hir_def::builtin_type::BuiltinType::Bool)
3029 }
3030
3031 pub fn is_str(&self) -> bool {
3032 matches!(self.inner, hir_def::builtin_type::BuiltinType::Str)
3033 }
3034}
3035
3036#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3037pub enum MacroKind {
3038 Declarative,
3040 Derive,
3042 BuiltIn,
3044 Attr,
3046 ProcMacro,
3048}
3049
3050#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3051pub struct Macro {
3052 pub(crate) id: MacroId,
3053}
3054
3055impl Macro {
3056 pub fn module(self, db: &dyn HirDatabase) -> Module {
3057 Module { id: self.id.module(db.upcast()) }
3058 }
3059
3060 pub fn name(self, db: &dyn HirDatabase) -> Name {
3061 match self.id {
3062 MacroId::Macro2Id(id) => db.macro2_data(id).name.clone(),
3063 MacroId::MacroRulesId(id) => db.macro_rules_data(id).name.clone(),
3064 MacroId::ProcMacroId(id) => db.proc_macro_data(id).name.clone(),
3065 }
3066 }
3067
3068 pub fn is_macro_export(self, db: &dyn HirDatabase) -> bool {
3069 matches!(self.id, MacroId::MacroRulesId(id) if db.macro_rules_data(id).macro_export)
3070 }
3071
3072 pub fn is_proc_macro(self) -> bool {
3073 matches!(self.id, MacroId::ProcMacroId(_))
3074 }
3075
3076 pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind {
3077 match self.id {
3078 MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander {
3079 MacroExpander::Declarative => MacroKind::Declarative,
3080 MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
3081 MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
3082 MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
3083 },
3084 MacroId::MacroRulesId(it) => match it.lookup(db.upcast()).expander {
3085 MacroExpander::Declarative => MacroKind::Declarative,
3086 MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
3087 MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
3088 MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
3089 },
3090 MacroId::ProcMacroId(it) => match it.lookup(db.upcast()).kind {
3091 ProcMacroKind::CustomDerive => MacroKind::Derive,
3092 ProcMacroKind::Bang => MacroKind::ProcMacro,
3093 ProcMacroKind::Attr => MacroKind::Attr,
3094 },
3095 }
3096 }
3097
3098 pub fn is_fn_like(&self, db: &dyn HirDatabase) -> bool {
3099 match self.kind(db) {
3100 MacroKind::Declarative | MacroKind::BuiltIn | MacroKind::ProcMacro => true,
3101 MacroKind::Attr | MacroKind::Derive => false,
3102 }
3103 }
3104
3105 pub fn is_builtin_derive(&self, db: &dyn HirDatabase) -> bool {
3106 match self.id {
3107 MacroId::Macro2Id(it) => {
3108 matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInDerive(_))
3109 }
3110 MacroId::MacroRulesId(it) => {
3111 matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInDerive(_))
3112 }
3113 MacroId::ProcMacroId(_) => false,
3114 }
3115 }
3116
3117 pub fn is_env_or_option_env(&self, db: &dyn HirDatabase) -> bool {
3118 match self.id {
3119 MacroId::Macro2Id(it) => {
3120 matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
3121 }
3122 MacroId::MacroRulesId(it) => {
3123 matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
3124 }
3125 MacroId::ProcMacroId(_) => false,
3126 }
3127 }
3128
3129 pub fn is_asm_or_global_asm(&self, db: &dyn HirDatabase) -> bool {
3130 match self.id {
3131 MacroId::Macro2Id(it) => {
3132 matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltIn(m) if m.is_asm())
3133 }
3134 MacroId::MacroRulesId(it) => {
3135 matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltIn(m) if m.is_asm())
3136 }
3137 MacroId::ProcMacroId(_) => false,
3138 }
3139 }
3140
3141 pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
3142 matches!(self.kind(db), MacroKind::Attr)
3143 }
3144
3145 pub fn is_derive(&self, db: &dyn HirDatabase) -> bool {
3146 matches!(self.kind(db), MacroKind::Derive)
3147 }
3148}
3149
3150impl HasVisibility for Macro {
3151 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
3152 match self.id {
3153 MacroId::Macro2Id(id) => {
3154 let data = db.macro2_data(id);
3155 let visibility = &data.visibility;
3156 visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
3157 }
3158 MacroId::MacroRulesId(_) => Visibility::Public,
3159 MacroId::ProcMacroId(_) => Visibility::Public,
3160 }
3161 }
3162}
3163
3164#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
3165pub enum ItemInNs {
3166 Types(ModuleDef),
3167 Values(ModuleDef),
3168 Macros(Macro),
3169}
3170
3171impl From<Macro> for ItemInNs {
3172 fn from(it: Macro) -> Self {
3173 Self::Macros(it)
3174 }
3175}
3176
3177impl From<ModuleDef> for ItemInNs {
3178 fn from(module_def: ModuleDef) -> Self {
3179 match module_def {
3180 ModuleDef::Static(_) | ModuleDef::Const(_) | ModuleDef::Function(_) => {
3181 ItemInNs::Values(module_def)
3182 }
3183 ModuleDef::Macro(it) => ItemInNs::Macros(it),
3184 _ => ItemInNs::Types(module_def),
3185 }
3186 }
3187}
3188
3189impl ItemInNs {
3190 pub fn into_module_def(self) -> ModuleDef {
3191 match self {
3192 ItemInNs::Types(id) | ItemInNs::Values(id) => id,
3193 ItemInNs::Macros(id) => ModuleDef::Macro(id),
3194 }
3195 }
3196
3197 pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
3199 match self {
3200 ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate()),
3201 ItemInNs::Macros(id) => Some(id.module(db).krate()),
3202 }
3203 }
3204
3205 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
3206 match self {
3207 ItemInNs::Types(it) | ItemInNs::Values(it) => it.attrs(db),
3208 ItemInNs::Macros(it) => Some(it.attrs(db)),
3209 }
3210 }
3211}
3212
3213#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
3216pub enum ExternAssocItem {
3217 Function(Function),
3218 Static(Static),
3219 TypeAlias(TypeAlias),
3220}
3221
3222pub trait AsExternAssocItem {
3223 fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem>;
3224}
3225
3226impl AsExternAssocItem for Function {
3227 fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
3228 as_extern_assoc_item(db, ExternAssocItem::Function, self.id)
3229 }
3230}
3231
3232impl AsExternAssocItem for Static {
3233 fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
3234 as_extern_assoc_item(db, ExternAssocItem::Static, self.id)
3235 }
3236}
3237
3238impl AsExternAssocItem for TypeAlias {
3239 fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
3240 as_extern_assoc_item(db, ExternAssocItem::TypeAlias, self.id)
3241 }
3242}
3243
3244#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
3247pub enum AssocItem {
3248 Function(Function),
3249 Const(Const),
3250 TypeAlias(TypeAlias),
3251}
3252
3253#[derive(Debug, Clone)]
3254pub enum AssocItemContainer {
3255 Trait(Trait),
3256 Impl(Impl),
3257}
3258
3259pub trait AsAssocItem {
3260 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>;
3261}
3262
3263impl AsAssocItem for Function {
3264 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
3265 as_assoc_item(db, AssocItem::Function, self.id)
3266 }
3267}
3268
3269impl AsAssocItem for Const {
3270 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
3271 as_assoc_item(db, AssocItem::Const, self.id)
3272 }
3273}
3274
3275impl AsAssocItem for TypeAlias {
3276 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
3277 as_assoc_item(db, AssocItem::TypeAlias, self.id)
3278 }
3279}
3280
3281impl AsAssocItem for ModuleDef {
3282 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
3283 match self {
3284 ModuleDef::Function(it) => it.as_assoc_item(db),
3285 ModuleDef::Const(it) => it.as_assoc_item(db),
3286 ModuleDef::TypeAlias(it) => it.as_assoc_item(db),
3287 _ => None,
3288 }
3289 }
3290}
3291
3292impl AsAssocItem for DefWithBody {
3293 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
3294 match self {
3295 DefWithBody::Function(it) => it.as_assoc_item(db),
3296 DefWithBody::Const(it) => it.as_assoc_item(db),
3297 DefWithBody::Static(_) | DefWithBody::Variant(_) | DefWithBody::InTypeConst(_) => None,
3298 }
3299 }
3300}
3301
3302fn as_assoc_item<'db, ID, DEF, LOC>(
3303 db: &(dyn HirDatabase + 'db),
3304 ctor: impl FnOnce(DEF) -> AssocItem,
3305 id: ID,
3306) -> Option<AssocItem>
3307where
3308 ID: Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<LOC>>,
3309 DEF: From<ID>,
3310 LOC: ItemTreeNode,
3311{
3312 match id.lookup(db.upcast()).container {
3313 ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
3314 ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
3315 }
3316}
3317
3318fn as_extern_assoc_item<'db, ID, DEF, LOC>(
3319 db: &(dyn HirDatabase + 'db),
3320 ctor: impl FnOnce(DEF) -> ExternAssocItem,
3321 id: ID,
3322) -> Option<ExternAssocItem>
3323where
3324 ID: Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<LOC>>,
3325 DEF: From<ID>,
3326 LOC: ItemTreeNode,
3327{
3328 match id.lookup(db.upcast()).container {
3329 ItemContainerId::ExternBlockId(_) => Some(ctor(DEF::from(id))),
3330 ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) | ItemContainerId::ModuleId(_) => {
3331 None
3332 }
3333 }
3334}
3335
3336impl ExternAssocItem {
3337 pub fn name(self, db: &dyn HirDatabase) -> Name {
3338 match self {
3339 Self::Function(it) => it.name(db),
3340 Self::Static(it) => it.name(db),
3341 Self::TypeAlias(it) => it.name(db),
3342 }
3343 }
3344
3345 pub fn module(self, db: &dyn HirDatabase) -> Module {
3346 match self {
3347 Self::Function(f) => f.module(db),
3348 Self::Static(c) => c.module(db),
3349 Self::TypeAlias(t) => t.module(db),
3350 }
3351 }
3352
3353 pub fn as_function(self) -> Option<Function> {
3354 match self {
3355 Self::Function(v) => Some(v),
3356 _ => None,
3357 }
3358 }
3359
3360 pub fn as_static(self) -> Option<Static> {
3361 match self {
3362 Self::Static(v) => Some(v),
3363 _ => None,
3364 }
3365 }
3366
3367 pub fn as_type_alias(self) -> Option<TypeAlias> {
3368 match self {
3369 Self::TypeAlias(v) => Some(v),
3370 _ => None,
3371 }
3372 }
3373}
3374
3375impl AssocItem {
3376 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
3377 match self {
3378 AssocItem::Function(it) => Some(it.name(db)),
3379 AssocItem::Const(it) => it.name(db),
3380 AssocItem::TypeAlias(it) => Some(it.name(db)),
3381 }
3382 }
3383
3384 pub fn module(self, db: &dyn HirDatabase) -> Module {
3385 match self {
3386 AssocItem::Function(f) => f.module(db),
3387 AssocItem::Const(c) => c.module(db),
3388 AssocItem::TypeAlias(t) => t.module(db),
3389 }
3390 }
3391
3392 pub fn container(self, db: &dyn HirDatabase) -> AssocItemContainer {
3393 let container = match self {
3394 AssocItem::Function(it) => it.id.lookup(db.upcast()).container,
3395 AssocItem::Const(it) => it.id.lookup(db.upcast()).container,
3396 AssocItem::TypeAlias(it) => it.id.lookup(db.upcast()).container,
3397 };
3398 match container {
3399 ItemContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()),
3400 ItemContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()),
3401 ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
3402 panic!("invalid AssocItem")
3403 }
3404 }
3405 }
3406
3407 pub fn container_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
3408 match self.container(db) {
3409 AssocItemContainer::Trait(t) => Some(t),
3410 _ => None,
3411 }
3412 }
3413
3414 pub fn implemented_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
3415 match self.container(db) {
3416 AssocItemContainer::Impl(i) => i.trait_(db),
3417 _ => None,
3418 }
3419 }
3420
3421 pub fn container_or_implemented_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
3422 match self.container(db) {
3423 AssocItemContainer::Trait(t) => Some(t),
3424 AssocItemContainer::Impl(i) => i.trait_(db),
3425 }
3426 }
3427
3428 pub fn implementing_ty(self, db: &dyn HirDatabase) -> Option<Type> {
3429 match self.container(db) {
3430 AssocItemContainer::Impl(i) => Some(i.self_ty(db)),
3431 _ => None,
3432 }
3433 }
3434
3435 pub fn as_function(self) -> Option<Function> {
3436 match self {
3437 Self::Function(v) => Some(v),
3438 _ => None,
3439 }
3440 }
3441
3442 pub fn as_const(self) -> Option<Const> {
3443 match self {
3444 Self::Const(v) => Some(v),
3445 _ => None,
3446 }
3447 }
3448
3449 pub fn as_type_alias(self) -> Option<TypeAlias> {
3450 match self {
3451 Self::TypeAlias(v) => Some(v),
3452 _ => None,
3453 }
3454 }
3455
3456 pub fn diagnostics(
3457 self,
3458 db: &dyn HirDatabase,
3459 acc: &mut Vec<AnyDiagnostic>,
3460 style_lints: bool,
3461 ) {
3462 match self {
3463 AssocItem::Function(func) => {
3464 GenericDef::Function(func).diagnostics(db, acc);
3465 DefWithBody::from(func).diagnostics(db, acc, style_lints);
3466 }
3467 AssocItem::Const(const_) => {
3468 DefWithBody::from(const_).diagnostics(db, acc, style_lints);
3469 }
3470 AssocItem::TypeAlias(type_alias) => {
3471 GenericDef::TypeAlias(type_alias).diagnostics(db, acc);
3472 let tree_id = type_alias.id.lookup(db.upcast()).id;
3473 let tree_source_maps = tree_id.item_tree_with_source_map(db.upcast()).1;
3474 push_ty_diagnostics(
3475 db,
3476 acc,
3477 db.type_for_type_alias_with_diagnostics(type_alias.id).1,
3478 tree_source_maps.type_alias(tree_id.value).item(),
3479 );
3480 for diag in hir_ty::diagnostics::incorrect_case(db, type_alias.id.into()) {
3481 acc.push(diag.into());
3482 }
3483 }
3484 }
3485 }
3486}
3487
3488impl HasVisibility for AssocItem {
3489 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
3490 match self {
3491 AssocItem::Function(f) => f.visibility(db),
3492 AssocItem::Const(c) => c.visibility(db),
3493 AssocItem::TypeAlias(t) => t.visibility(db),
3494 }
3495 }
3496}
3497
3498impl From<AssocItem> for ModuleDef {
3499 fn from(assoc: AssocItem) -> Self {
3500 match assoc {
3501 AssocItem::Function(it) => ModuleDef::Function(it),
3502 AssocItem::Const(it) => ModuleDef::Const(it),
3503 AssocItem::TypeAlias(it) => ModuleDef::TypeAlias(it),
3504 }
3505 }
3506}
3507
3508#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
3509pub enum GenericDef {
3510 Function(Function),
3511 Adt(Adt),
3512 Trait(Trait),
3513 TraitAlias(TraitAlias),
3514 TypeAlias(TypeAlias),
3515 Impl(Impl),
3516 Const(Const),
3518 Static(Static),
3519}
3520impl_from!(
3521 Function,
3522 Adt(Struct, Enum, Union),
3523 Trait,
3524 TraitAlias,
3525 TypeAlias,
3526 Impl,
3527 Const,
3528 Static
3529 for GenericDef
3530);
3531
3532impl GenericDef {
3533 pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
3534 let generics = db.generic_params(self.into());
3535 let ty_params = generics.iter_type_or_consts().map(|(local_id, _)| {
3536 let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } };
3537 match toc.split(db) {
3538 Either::Left(it) => GenericParam::ConstParam(it),
3539 Either::Right(it) => GenericParam::TypeParam(it),
3540 }
3541 });
3542 self.lifetime_params(db)
3543 .into_iter()
3544 .map(GenericParam::LifetimeParam)
3545 .chain(ty_params)
3546 .collect()
3547 }
3548
3549 pub fn lifetime_params(self, db: &dyn HirDatabase) -> Vec<LifetimeParam> {
3550 let generics = db.generic_params(self.into());
3551 generics
3552 .iter_lt()
3553 .map(|(local_id, _)| LifetimeParam {
3554 id: LifetimeParamId { parent: self.into(), local_id },
3555 })
3556 .collect()
3557 }
3558
3559 pub fn type_or_const_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
3560 let generics = db.generic_params(self.into());
3561 generics
3562 .iter_type_or_consts()
3563 .map(|(local_id, _)| TypeOrConstParam {
3564 id: TypeOrConstParamId { parent: self.into(), local_id },
3565 })
3566 .collect()
3567 }
3568
3569 fn id(self) -> GenericDefId {
3570 match self {
3571 GenericDef::Function(it) => it.id.into(),
3572 GenericDef::Adt(it) => it.into(),
3573 GenericDef::Trait(it) => it.id.into(),
3574 GenericDef::TraitAlias(it) => it.id.into(),
3575 GenericDef::TypeAlias(it) => it.id.into(),
3576 GenericDef::Impl(it) => it.id.into(),
3577 GenericDef::Const(it) => it.id.into(),
3578 GenericDef::Static(it) => it.id.into(),
3579 }
3580 }
3581
3582 pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
3583 let def = self.id();
3584
3585 let item_tree_source_maps;
3586 let (generics, generics_source_map) = db.generic_params_with_source_map(def);
3587
3588 if generics.is_empty() && generics.no_predicates() {
3589 return;
3590 }
3591
3592 let source_map = match &generics_source_map {
3593 Some(it) => it,
3594 None => match def {
3595 GenericDefId::FunctionId(it) => {
3596 let id = it.lookup(db.upcast()).id;
3597 item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
3598 item_tree_source_maps.function(id.value).generics()
3599 }
3600 GenericDefId::AdtId(AdtId::EnumId(it)) => {
3601 let id = it.lookup(db.upcast()).id;
3602 item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
3603 item_tree_source_maps.enum_generic(id.value)
3604 }
3605 GenericDefId::AdtId(AdtId::StructId(it)) => {
3606 let id = it.lookup(db.upcast()).id;
3607 item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
3608 item_tree_source_maps.strukt(id.value).generics()
3609 }
3610 GenericDefId::AdtId(AdtId::UnionId(it)) => {
3611 let id = it.lookup(db.upcast()).id;
3612 item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
3613 item_tree_source_maps.union(id.value).generics()
3614 }
3615 GenericDefId::TraitId(it) => {
3616 let id = it.lookup(db.upcast()).id;
3617 item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
3618 item_tree_source_maps.trait_generic(id.value)
3619 }
3620 GenericDefId::TraitAliasId(it) => {
3621 let id = it.lookup(db.upcast()).id;
3622 item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
3623 item_tree_source_maps.trait_alias_generic(id.value)
3624 }
3625 GenericDefId::TypeAliasId(it) => {
3626 let id = it.lookup(db.upcast()).id;
3627 item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
3628 item_tree_source_maps.type_alias(id.value).generics()
3629 }
3630 GenericDefId::ImplId(it) => {
3631 let id = it.lookup(db.upcast()).id;
3632 item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1;
3633 item_tree_source_maps.impl_(id.value).generics()
3634 }
3635 GenericDefId::ConstId(_) => return,
3636 GenericDefId::StaticId(_) => return,
3637 },
3638 };
3639
3640 push_ty_diagnostics(db, acc, db.generic_defaults_with_diagnostics(def).1, source_map);
3641 push_ty_diagnostics(
3642 db,
3643 acc,
3644 db.generic_predicates_without_parent_with_diagnostics(def).1,
3645 source_map,
3646 );
3647 for (param_id, param) in generics.iter_type_or_consts() {
3648 if let TypeOrConstParamData::ConstParamData(_) = param {
3649 push_ty_diagnostics(
3650 db,
3651 acc,
3652 db.const_param_ty_with_diagnostics(ConstParamId::from_unchecked(
3653 TypeOrConstParamId { parent: def, local_id: param_id },
3654 ))
3655 .1,
3656 source_map,
3657 );
3658 }
3659 }
3660 }
3661}
3662
3663#[derive(Debug)]
3665pub struct GenericSubstitution {
3666 def: GenericDefId,
3667 subst: Substitution,
3668 env: Arc<TraitEnvironment>,
3669}
3670
3671impl GenericSubstitution {
3672 fn new(def: GenericDefId, subst: Substitution, env: Arc<TraitEnvironment>) -> Self {
3673 Self { def, subst, env }
3674 }
3675
3676 pub fn types(&self, db: &dyn HirDatabase) -> Vec<(Symbol, Type)> {
3677 let container = match self.def {
3678 GenericDefId::ConstId(id) => Some(id.lookup(db.upcast()).container),
3679 GenericDefId::FunctionId(id) => Some(id.lookup(db.upcast()).container),
3680 GenericDefId::TypeAliasId(id) => Some(id.lookup(db.upcast()).container),
3681 _ => None,
3682 };
3683 let container_type_params = container
3684 .and_then(|container| match container {
3685 ItemContainerId::ImplId(container) => Some(container.into()),
3686 ItemContainerId::TraitId(container) => Some(container.into()),
3687 _ => None,
3688 })
3689 .map(|container| {
3690 db.generic_params(container)
3691 .iter_type_or_consts()
3692 .filter_map(|param| match param.1 {
3693 TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
3694 TypeOrConstParamData::ConstParamData(_) => None,
3695 })
3696 .collect::<Vec<_>>()
3697 });
3698 let generics = db.generic_params(self.def);
3699 let type_params = generics.iter_type_or_consts().filter_map(|param| match param.1 {
3700 TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
3701 TypeOrConstParamData::ConstParamData(_) => None,
3702 });
3703 let self_params = self.subst.type_parameters(Interner).zip(type_params);
3705 let container_params = self.subst.as_slice(Interner)[generics.len()..]
3706 .iter()
3707 .filter_map(|param| param.ty(Interner).cloned())
3708 .zip(container_type_params.into_iter().flatten());
3709 container_params
3710 .chain(self_params)
3711 .filter_map(|(ty, name)| {
3712 Some((name?.symbol().clone(), Type { ty, env: self.env.clone() }))
3713 })
3714 .collect()
3715 }
3716}
3717
3718#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3720pub struct Local {
3721 pub(crate) parent: DefWithBodyId,
3722 pub(crate) binding_id: BindingId,
3723}
3724
3725pub struct LocalSource {
3726 pub local: Local,
3727 pub source: InFile<Either<ast::IdentPat, ast::SelfParam>>,
3728}
3729
3730impl LocalSource {
3731 pub fn as_ident_pat(&self) -> Option<&ast::IdentPat> {
3732 match &self.source.value {
3733 Either::Left(it) => Some(it),
3734 Either::Right(_) => None,
3735 }
3736 }
3737
3738 pub fn into_ident_pat(self) -> Option<ast::IdentPat> {
3739 match self.source.value {
3740 Either::Left(it) => Some(it),
3741 Either::Right(_) => None,
3742 }
3743 }
3744
3745 pub fn original_file(&self, db: &dyn HirDatabase) -> EditionedFileId {
3746 self.source.file_id.original_file(db.upcast())
3747 }
3748
3749 pub fn file(&self) -> HirFileId {
3750 self.source.file_id
3751 }
3752
3753 pub fn name(&self) -> Option<InFile<ast::Name>> {
3754 self.source.as_ref().map(|it| it.name()).transpose()
3755 }
3756
3757 pub fn syntax(&self) -> &SyntaxNode {
3758 self.source.value.syntax()
3759 }
3760
3761 pub fn syntax_ptr(self) -> InFile<SyntaxNodePtr> {
3762 self.source.map(|it| SyntaxNodePtr::new(it.syntax()))
3763 }
3764}
3765
3766impl Local {
3767 pub fn is_param(self, db: &dyn HirDatabase) -> bool {
3768 let src = self.primary_source(db);
3770 match src.source.value {
3771 Either::Left(pat) => pat
3772 .syntax()
3773 .ancestors()
3774 .map(|it| it.kind())
3775 .take_while(|&kind| ast::Pat::can_cast(kind) || ast::Param::can_cast(kind))
3776 .any(ast::Param::can_cast),
3777 Either::Right(_) => true,
3778 }
3779 }
3780
3781 pub fn as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
3782 match self.parent {
3783 DefWithBodyId::FunctionId(func) if self.is_self(db) => Some(SelfParam { func }),
3784 _ => None,
3785 }
3786 }
3787
3788 pub fn name(self, db: &dyn HirDatabase) -> Name {
3789 let body = db.body(self.parent);
3790 body[self.binding_id].name.clone()
3791 }
3792
3793 pub fn is_self(self, db: &dyn HirDatabase) -> bool {
3794 self.name(db) == sym::self_.clone()
3795 }
3796
3797 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
3798 let body = db.body(self.parent);
3799 body[self.binding_id].mode == BindingAnnotation::Mutable
3800 }
3801
3802 pub fn is_ref(self, db: &dyn HirDatabase) -> bool {
3803 let body = db.body(self.parent);
3804 matches!(body[self.binding_id].mode, BindingAnnotation::Ref | BindingAnnotation::RefMut)
3805 }
3806
3807 pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
3808 self.parent.into()
3809 }
3810
3811 pub fn module(self, db: &dyn HirDatabase) -> Module {
3812 self.parent(db).module(db)
3813 }
3814
3815 pub fn ty(self, db: &dyn HirDatabase) -> Type {
3816 let def = self.parent;
3817 let infer = db.infer(def);
3818 let ty = infer[self.binding_id].clone();
3819 Type::new(db, def, ty)
3820 }
3821
3822 pub fn sources(self, db: &dyn HirDatabase) -> Vec<LocalSource> {
3824 let (body, source_map) = db.body_with_source_map(self.parent);
3825 match body.self_param.zip(source_map.self_param_syntax()) {
3826 Some((param, source)) if param == self.binding_id => {
3827 let root = source.file_syntax(db.upcast());
3828 vec![LocalSource {
3829 local: self,
3830 source: source.map(|ast| Either::Right(ast.to_node(&root))),
3831 }]
3832 }
3833 _ => source_map
3834 .patterns_for_binding(self.binding_id)
3835 .iter()
3836 .map(|&definition| {
3837 let src = source_map.pat_syntax(definition).unwrap(); let root = src.file_syntax(db.upcast());
3839 LocalSource {
3840 local: self,
3841 source: src.map(|ast| match ast.to_node(&root) {
3842 Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
3843 _ => unreachable!("local with non ident-pattern"),
3844 }),
3845 }
3846 })
3847 .collect(),
3848 }
3849 }
3850
3851 pub fn primary_source(self, db: &dyn HirDatabase) -> LocalSource {
3853 let (body, source_map) = db.body_with_source_map(self.parent);
3854 match body.self_param.zip(source_map.self_param_syntax()) {
3855 Some((param, source)) if param == self.binding_id => {
3856 let root = source.file_syntax(db.upcast());
3857 LocalSource {
3858 local: self,
3859 source: source.map(|ast| Either::Right(ast.to_node(&root))),
3860 }
3861 }
3862 _ => source_map
3863 .patterns_for_binding(self.binding_id)
3864 .first()
3865 .map(|&definition| {
3866 let src = source_map.pat_syntax(definition).unwrap(); let root = src.file_syntax(db.upcast());
3868 LocalSource {
3869 local: self,
3870 source: src.map(|ast| match ast.to_node(&root) {
3871 Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
3872 _ => unreachable!("local with non ident-pattern"),
3873 }),
3874 }
3875 })
3876 .unwrap(),
3877 }
3878 }
3879}
3880
3881impl PartialOrd for Local {
3882 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
3883 Some(self.cmp(other))
3884 }
3885}
3886
3887impl Ord for Local {
3888 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
3889 self.binding_id.cmp(&other.binding_id)
3890 }
3891}
3892
3893#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3894pub struct DeriveHelper {
3895 pub(crate) derive: MacroId,
3896 pub(crate) idx: u32,
3897}
3898
3899impl DeriveHelper {
3900 pub fn derive(&self) -> Macro {
3901 Macro { id: self.derive }
3902 }
3903
3904 pub fn name(&self, db: &dyn HirDatabase) -> Name {
3905 match self.derive {
3906 MacroId::Macro2Id(it) => db
3907 .macro2_data(it)
3908 .helpers
3909 .as_deref()
3910 .and_then(|it| it.get(self.idx as usize))
3911 .cloned(),
3912 MacroId::MacroRulesId(_) => None,
3913 MacroId::ProcMacroId(proc_macro) => db
3914 .proc_macro_data(proc_macro)
3915 .helpers
3916 .as_deref()
3917 .and_then(|it| it.get(self.idx as usize))
3918 .cloned(),
3919 }
3920 .unwrap_or_else(Name::missing)
3921 }
3922}
3923
3924#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3926pub struct BuiltinAttr {
3927 krate: Option<CrateId>,
3928 idx: u32,
3929}
3930
3931impl BuiltinAttr {
3932 pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
3934 if let builtin @ Some(_) = Self::builtin(name) {
3935 return builtin;
3936 }
3937 let idx = db
3938 .crate_def_map(krate.id)
3939 .registered_attrs()
3940 .iter()
3941 .position(|it| it.as_str() == name)? as u32;
3942 Some(BuiltinAttr { krate: Some(krate.id), idx })
3943 }
3944
3945 fn builtin(name: &str) -> Option<Self> {
3946 hir_expand::inert_attr_macro::find_builtin_attr_idx(&Symbol::intern(name))
3947 .map(|idx| BuiltinAttr { krate: None, idx: idx as u32 })
3948 }
3949
3950 pub fn name(&self, db: &dyn HirDatabase) -> Name {
3951 match self.krate {
3952 Some(krate) => Name::new_symbol_root(
3953 db.crate_def_map(krate).registered_attrs()[self.idx as usize].clone(),
3954 ),
3955 None => Name::new_symbol_root(Symbol::intern(
3956 hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].name,
3957 )),
3958 }
3959 }
3960
3961 pub fn template(&self, _: &dyn HirDatabase) -> Option<AttributeTemplate> {
3962 match self.krate {
3963 Some(_) => None,
3964 None => {
3965 Some(hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].template)
3966 }
3967 }
3968 }
3969}
3970
3971#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3972pub struct ToolModule {
3973 krate: CrateId,
3974 idx: u32,
3975}
3976
3977impl ToolModule {
3978 pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
3979 let krate = krate.id;
3980 let idx =
3981 db.crate_def_map(krate).registered_tools().iter().position(|it| it.as_str() == name)?
3982 as u32;
3983 Some(ToolModule { krate, idx })
3984 }
3985
3986 pub fn name(&self, db: &dyn HirDatabase) -> Name {
3987 Name::new_symbol_root(
3988 db.crate_def_map(self.krate).registered_tools()[self.idx as usize].clone(),
3989 )
3990 }
3991
3992 pub fn krate(&self) -> Crate {
3993 Crate { id: self.krate }
3994 }
3995}
3996
3997#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3998pub struct Label {
3999 pub(crate) parent: DefWithBodyId,
4000 pub(crate) label_id: LabelId,
4001}
4002
4003impl Label {
4004 pub fn module(self, db: &dyn HirDatabase) -> Module {
4005 self.parent(db).module(db)
4006 }
4007
4008 pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
4009 self.parent.into()
4010 }
4011
4012 pub fn name(self, db: &dyn HirDatabase) -> Name {
4013 let body = db.body(self.parent);
4014 body[self.label_id].name.clone()
4015 }
4016}
4017
4018#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4019pub enum GenericParam {
4020 TypeParam(TypeParam),
4021 ConstParam(ConstParam),
4022 LifetimeParam(LifetimeParam),
4023}
4024impl_from!(TypeParam, ConstParam, LifetimeParam for GenericParam);
4025
4026impl GenericParam {
4027 pub fn module(self, db: &dyn HirDatabase) -> Module {
4028 match self {
4029 GenericParam::TypeParam(it) => it.module(db),
4030 GenericParam::ConstParam(it) => it.module(db),
4031 GenericParam::LifetimeParam(it) => it.module(db),
4032 }
4033 }
4034
4035 pub fn name(self, db: &dyn HirDatabase) -> Name {
4036 match self {
4037 GenericParam::TypeParam(it) => it.name(db),
4038 GenericParam::ConstParam(it) => it.name(db),
4039 GenericParam::LifetimeParam(it) => it.name(db),
4040 }
4041 }
4042
4043 pub fn parent(self) -> GenericDef {
4044 match self {
4045 GenericParam::TypeParam(it) => it.id.parent().into(),
4046 GenericParam::ConstParam(it) => it.id.parent().into(),
4047 GenericParam::LifetimeParam(it) => it.id.parent.into(),
4048 }
4049 }
4050
4051 pub fn variance(self, db: &dyn HirDatabase) -> Option<Variance> {
4052 let parent = match self {
4053 GenericParam::TypeParam(it) => it.id.parent(),
4054 GenericParam::ConstParam(_) => return None,
4056 GenericParam::LifetimeParam(it) => it.id.parent,
4057 };
4058 let generics = hir_ty::generics::generics(db.upcast(), parent);
4059 let index = match self {
4060 GenericParam::TypeParam(it) => generics.type_or_const_param_idx(it.id.into())?,
4061 GenericParam::ConstParam(_) => return None,
4062 GenericParam::LifetimeParam(it) => generics.lifetime_idx(it.id)?,
4063 };
4064 db.variances_of(parent)?.get(index).copied()
4065 }
4066}
4067
4068#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4069pub struct TypeParam {
4070 pub(crate) id: TypeParamId,
4071}
4072
4073impl TypeParam {
4074 pub fn merge(self) -> TypeOrConstParam {
4075 TypeOrConstParam { id: self.id.into() }
4076 }
4077
4078 pub fn name(self, db: &dyn HirDatabase) -> Name {
4079 self.merge().name(db)
4080 }
4081
4082 pub fn module(self, db: &dyn HirDatabase) -> Module {
4083 self.id.parent().module(db.upcast()).into()
4084 }
4085
4086 pub fn is_implicit(self, db: &dyn HirDatabase) -> bool {
4089 let params = db.generic_params(self.id.parent());
4090 let data = ¶ms[self.id.local_id()];
4091 match data.type_param().unwrap().provenance {
4092 hir_def::generics::TypeParamProvenance::TypeParamList => false,
4093 hir_def::generics::TypeParamProvenance::TraitSelf
4094 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => true,
4095 }
4096 }
4097
4098 pub fn ty(self, db: &dyn HirDatabase) -> Type {
4099 let resolver = self.id.parent().resolver(db.upcast());
4100 let ty =
4101 TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id.into())).intern(Interner);
4102 Type::new_with_resolver_inner(db, &resolver, ty)
4103 }
4104
4105 pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
4109 db.generic_predicates_for_param(self.id.parent(), self.id.into(), None)
4110 .iter()
4111 .filter_map(|pred| match &pred.skip_binders().skip_binders() {
4112 hir_ty::WhereClause::Implemented(trait_ref) => {
4113 Some(Trait::from(trait_ref.hir_trait_id()))
4114 }
4115 _ => None,
4116 })
4117 .collect()
4118 }
4119
4120 pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
4121 let ty = generic_arg_from_param(db, self.id.into())?;
4122 let resolver = self.id.parent().resolver(db.upcast());
4123 match ty.data(Interner) {
4124 GenericArgData::Ty(it) if *it.kind(Interner) != TyKind::Error => {
4125 Some(Type::new_with_resolver_inner(db, &resolver, it.clone()))
4126 }
4127 _ => None,
4128 }
4129 }
4130
4131 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
4132 db.attrs(GenericParamId::from(self.id).into()).is_unstable()
4133 }
4134}
4135
4136#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4137pub struct LifetimeParam {
4138 pub(crate) id: LifetimeParamId,
4139}
4140
4141impl LifetimeParam {
4142 pub fn name(self, db: &dyn HirDatabase) -> Name {
4143 let params = db.generic_params(self.id.parent);
4144 params[self.id.local_id].name.clone()
4145 }
4146
4147 pub fn module(self, db: &dyn HirDatabase) -> Module {
4148 self.id.parent.module(db.upcast()).into()
4149 }
4150
4151 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
4152 self.id.parent.into()
4153 }
4154}
4155
4156#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4157pub struct ConstParam {
4158 pub(crate) id: ConstParamId,
4159}
4160
4161impl ConstParam {
4162 pub fn merge(self) -> TypeOrConstParam {
4163 TypeOrConstParam { id: self.id.into() }
4164 }
4165
4166 pub fn name(self, db: &dyn HirDatabase) -> Name {
4167 let params = db.generic_params(self.id.parent());
4168 match params[self.id.local_id()].name() {
4169 Some(it) => it.clone(),
4170 None => {
4171 never!();
4172 Name::missing()
4173 }
4174 }
4175 }
4176
4177 pub fn module(self, db: &dyn HirDatabase) -> Module {
4178 self.id.parent().module(db.upcast()).into()
4179 }
4180
4181 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
4182 self.id.parent().into()
4183 }
4184
4185 pub fn ty(self, db: &dyn HirDatabase) -> Type {
4186 Type::new(db, self.id.parent(), db.const_param_ty(self.id))
4187 }
4188
4189 pub fn default(self, db: &dyn HirDatabase, edition: Edition) -> Option<ast::ConstArg> {
4190 let arg = generic_arg_from_param(db, self.id.into())?;
4191 known_const_to_ast(arg.constant(Interner)?, db, edition)
4192 }
4193}
4194
4195fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<GenericArg> {
4196 let local_idx = hir_ty::param_idx(db, id)?;
4197 let defaults = db.generic_defaults(id.parent);
4198 let ty = defaults.get(local_idx)?.clone();
4199 let subst = TyBuilder::placeholder_subst(db, id.parent);
4200 Some(ty.substitute(Interner, &subst))
4201}
4202
4203#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4204pub struct TypeOrConstParam {
4205 pub(crate) id: TypeOrConstParamId,
4206}
4207
4208impl TypeOrConstParam {
4209 pub fn name(self, db: &dyn HirDatabase) -> Name {
4210 let params = db.generic_params(self.id.parent);
4211 match params[self.id.local_id].name() {
4212 Some(n) => n.clone(),
4213 _ => Name::missing(),
4214 }
4215 }
4216
4217 pub fn module(self, db: &dyn HirDatabase) -> Module {
4218 self.id.parent.module(db.upcast()).into()
4219 }
4220
4221 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
4222 self.id.parent.into()
4223 }
4224
4225 pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
4226 let params = db.generic_params(self.id.parent);
4227 match ¶ms[self.id.local_id] {
4228 hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
4229 Either::Right(TypeParam { id: TypeParamId::from_unchecked(self.id) })
4230 }
4231 hir_def::generics::TypeOrConstParamData::ConstParamData(_) => {
4232 Either::Left(ConstParam { id: ConstParamId::from_unchecked(self.id) })
4233 }
4234 }
4235 }
4236
4237 pub fn ty(self, db: &dyn HirDatabase) -> Type {
4238 match self.split(db) {
4239 Either::Left(it) => it.ty(db),
4240 Either::Right(it) => it.ty(db),
4241 }
4242 }
4243
4244 pub fn as_type_param(self, db: &dyn HirDatabase) -> Option<TypeParam> {
4245 let params = db.generic_params(self.id.parent);
4246 match ¶ms[self.id.local_id] {
4247 hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
4248 Some(TypeParam { id: TypeParamId::from_unchecked(self.id) })
4249 }
4250 hir_def::generics::TypeOrConstParamData::ConstParamData(_) => None,
4251 }
4252 }
4253
4254 pub fn as_const_param(self, db: &dyn HirDatabase) -> Option<ConstParam> {
4255 let params = db.generic_params(self.id.parent);
4256 match ¶ms[self.id.local_id] {
4257 hir_def::generics::TypeOrConstParamData::TypeParamData(_) => None,
4258 hir_def::generics::TypeOrConstParamData::ConstParamData(_) => {
4259 Some(ConstParam { id: ConstParamId::from_unchecked(self.id) })
4260 }
4261 }
4262 }
4263}
4264
4265#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4266pub struct Impl {
4267 pub(crate) id: ImplId,
4268}
4269
4270impl Impl {
4271 pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<Impl> {
4272 let inherent = db.inherent_impls_in_crate(krate.id);
4273 let trait_ = db.trait_impls_in_crate(krate.id);
4274
4275 inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect()
4276 }
4277
4278 pub fn all_in_module(db: &dyn HirDatabase, module: Module) -> Vec<Impl> {
4279 module.id.def_map(db.upcast())[module.id.local_id].scope.impls().map(Into::into).collect()
4280 }
4281
4282 pub fn all_for_type(db: &dyn HirDatabase, Type { ty, env }: Type) -> Vec<Impl> {
4283 let def_crates = match method_resolution::def_crates(db, &ty, env.krate) {
4284 Some(def_crates) => def_crates,
4285 None => return Vec::new(),
4286 };
4287
4288 let filter = |impl_def: &Impl| {
4289 let self_ty = impl_def.self_ty(db);
4290 let rref = self_ty.remove_ref();
4291 ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
4292 };
4293
4294 let fp = TyFingerprint::for_inherent_impl(&ty);
4295 let fp = match fp {
4296 Some(fp) => fp,
4297 None => return Vec::new(),
4298 };
4299
4300 let mut all = Vec::new();
4301 def_crates.iter().for_each(|&id| {
4302 all.extend(
4303 db.inherent_impls_in_crate(id)
4304 .for_self_ty(&ty)
4305 .iter()
4306 .cloned()
4307 .map(Self::from)
4308 .filter(filter),
4309 )
4310 });
4311
4312 for id in def_crates
4313 .iter()
4314 .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
4315 .map(|Crate { id }| id)
4316 {
4317 all.extend(
4318 db.trait_impls_in_crate(id)
4319 .for_self_ty_without_blanket_impls(fp)
4320 .map(Self::from)
4321 .filter(filter),
4322 );
4323 }
4324
4325 if let Some(block) =
4326 ty.adt_id(Interner).and_then(|def| def.0.module(db.upcast()).containing_block())
4327 {
4328 if let Some(inherent_impls) = db.inherent_impls_in_block(block) {
4329 all.extend(
4330 inherent_impls.for_self_ty(&ty).iter().cloned().map(Self::from).filter(filter),
4331 );
4332 }
4333 if let Some(trait_impls) = db.trait_impls_in_block(block) {
4334 all.extend(
4335 trait_impls
4336 .for_self_ty_without_blanket_impls(fp)
4337 .map(Self::from)
4338 .filter(filter),
4339 );
4340 }
4341 }
4342
4343 all
4344 }
4345
4346 pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
4347 let module = trait_.module(db);
4348 let krate = module.krate();
4349 let mut all = Vec::new();
4350 for Crate { id } in krate.transitive_reverse_dependencies(db) {
4351 let impls = db.trait_impls_in_crate(id);
4352 all.extend(impls.for_trait(trait_.id).map(Self::from))
4353 }
4354 if let Some(block) = module.id.containing_block() {
4355 if let Some(trait_impls) = db.trait_impls_in_block(block) {
4356 all.extend(trait_impls.for_trait(trait_.id).map(Self::from));
4357 }
4358 }
4359 all
4360 }
4361
4362 pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> {
4363 let trait_ref = db.impl_trait(self.id)?;
4364 let id = trait_ref.skip_binders().hir_trait_id();
4365 Some(Trait { id })
4366 }
4367
4368 pub fn trait_ref(self, db: &dyn HirDatabase) -> Option<TraitRef> {
4369 let substs = TyBuilder::placeholder_subst(db, self.id);
4370 let trait_ref = db.impl_trait(self.id)?.substitute(Interner, &substs);
4371 let resolver = self.id.resolver(db.upcast());
4372 Some(TraitRef::new_with_resolver(db, &resolver, trait_ref))
4373 }
4374
4375 pub fn self_ty(self, db: &dyn HirDatabase) -> Type {
4376 let resolver = self.id.resolver(db.upcast());
4377 let substs = TyBuilder::placeholder_subst(db, self.id);
4378 let ty = db.impl_self_ty(self.id).substitute(Interner, &substs);
4379 Type::new_with_resolver_inner(db, &resolver, ty)
4380 }
4381
4382 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
4383 db.impl_data(self.id).items.iter().map(|&(_, it)| it.into()).collect()
4384 }
4385
4386 pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
4387 db.impl_data(self.id).is_negative
4388 }
4389
4390 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
4391 db.impl_data(self.id).is_unsafe
4392 }
4393
4394 pub fn module(self, db: &dyn HirDatabase) -> Module {
4395 self.id.lookup(db.upcast()).container.into()
4396 }
4397
4398 pub fn as_builtin_derive_path(self, db: &dyn HirDatabase) -> Option<InMacroFile<ast::Path>> {
4399 let src = self.source(db)?;
4400
4401 let macro_file = src.file_id.macro_file()?;
4402 let loc = macro_file.macro_call_id.lookup(db.upcast());
4403 let (derive_attr, derive_index) = match loc.kind {
4404 MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
4405 let module_id = self.id.lookup(db.upcast()).container;
4406 (
4407 db.crate_def_map(module_id.krate())[module_id.local_id]
4408 .scope
4409 .derive_macro_invoc(ast_id, derive_attr_index)?,
4410 derive_index,
4411 )
4412 }
4413 _ => return None,
4414 };
4415 let file_id = MacroFileId { macro_call_id: derive_attr };
4416 let path = db
4417 .parse_macro_expansion(file_id)
4418 .value
4419 .0
4420 .syntax_node()
4421 .children()
4422 .nth(derive_index as usize)
4423 .and_then(<ast::Attr as AstNode>::cast)
4424 .and_then(|it| it.path())?;
4425 Some(InMacroFile { file_id, value: path })
4426 }
4427
4428 pub fn check_orphan_rules(self, db: &dyn HirDatabase) -> bool {
4429 check_orphan_rules(db, self.id)
4430 }
4431
4432 fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
4433 db.impl_data(self.id)
4434 .macro_calls
4435 .as_ref()
4436 .map(|it| it.as_ref().clone().into_boxed_slice())
4437 .unwrap_or_default()
4438 }
4439}
4440
4441#[derive(Clone, PartialEq, Eq, Debug, Hash)]
4442pub struct TraitRef {
4443 env: Arc<TraitEnvironment>,
4444 trait_ref: hir_ty::TraitRef,
4445}
4446
4447impl TraitRef {
4448 pub(crate) fn new_with_resolver(
4449 db: &dyn HirDatabase,
4450 resolver: &Resolver,
4451 trait_ref: hir_ty::TraitRef,
4452 ) -> TraitRef {
4453 let env = resolver
4454 .generic_def()
4455 .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
4456 TraitRef { env, trait_ref }
4457 }
4458
4459 pub fn trait_(&self) -> Trait {
4460 let id = self.trait_ref.hir_trait_id();
4461 Trait { id }
4462 }
4463
4464 pub fn self_ty(&self) -> Type {
4465 let ty = self.trait_ref.self_type_parameter(Interner);
4466 Type { env: self.env.clone(), ty }
4467 }
4468
4469 pub fn get_type_argument(&self, idx: usize) -> Option<Type> {
4472 self.trait_ref
4473 .substitution
4474 .as_slice(Interner)
4475 .get(idx)
4476 .and_then(|arg| arg.ty(Interner))
4477 .cloned()
4478 .map(|ty| Type { env: self.env.clone(), ty })
4479 }
4480}
4481
4482#[derive(Clone, Debug, PartialEq, Eq, Hash)]
4483pub struct Closure {
4484 id: ClosureId,
4485 subst: Substitution,
4486}
4487
4488impl From<Closure> for ClosureId {
4489 fn from(value: Closure) -> Self {
4490 value.id
4491 }
4492}
4493
4494impl Closure {
4495 fn as_ty(self) -> Ty {
4496 TyKind::Closure(self.id, self.subst).intern(Interner)
4497 }
4498
4499 pub fn display_with_id(&self, db: &dyn HirDatabase, edition: Edition) -> String {
4500 self.clone()
4501 .as_ty()
4502 .display(db, edition)
4503 .with_closure_style(ClosureStyle::ClosureWithId)
4504 .to_string()
4505 }
4506
4507 pub fn display_with_impl(&self, db: &dyn HirDatabase, edition: Edition) -> String {
4508 self.clone()
4509 .as_ty()
4510 .display(db, edition)
4511 .with_closure_style(ClosureStyle::ImplFn)
4512 .to_string()
4513 }
4514
4515 pub fn captured_items(&self, db: &dyn HirDatabase) -> Vec<ClosureCapture> {
4516 let owner = db.lookup_intern_closure((self.id).into()).0;
4517 let infer = &db.infer(owner);
4518 let info = infer.closure_info(&self.id);
4519 info.0
4520 .iter()
4521 .cloned()
4522 .map(|capture| ClosureCapture { owner, closure: self.id, capture })
4523 .collect()
4524 }
4525
4526 pub fn capture_types(&self, db: &dyn HirDatabase) -> Vec<Type> {
4527 let owner = db.lookup_intern_closure((self.id).into()).0;
4528 let infer = &db.infer(owner);
4529 let (captures, _) = infer.closure_info(&self.id);
4530 captures
4531 .iter()
4532 .map(|capture| Type {
4533 env: db.trait_environment_for_body(owner),
4534 ty: capture.ty(&self.subst),
4535 })
4536 .collect()
4537 }
4538
4539 pub fn fn_trait(&self, db: &dyn HirDatabase) -> FnTrait {
4540 let owner = db.lookup_intern_closure((self.id).into()).0;
4541 let infer = &db.infer(owner);
4542 let info = infer.closure_info(&self.id);
4543 info.1
4544 }
4545}
4546
4547#[derive(Clone, Debug, PartialEq, Eq)]
4548pub struct ClosureCapture {
4549 owner: DefWithBodyId,
4550 closure: ClosureId,
4551 capture: hir_ty::CapturedItem,
4552}
4553
4554impl ClosureCapture {
4555 pub fn local(&self) -> Local {
4556 Local { parent: self.owner, binding_id: self.capture.local() }
4557 }
4558
4559 pub fn has_field_projections(&self) -> bool {
4561 self.capture.has_field_projections()
4562 }
4563
4564 pub fn usages(&self) -> CaptureUsages {
4565 CaptureUsages { parent: self.owner, spans: self.capture.spans() }
4566 }
4567
4568 pub fn kind(&self) -> CaptureKind {
4569 match self.capture.kind() {
4570 hir_ty::CaptureKind::ByRef(
4571 hir_ty::mir::BorrowKind::Shallow | hir_ty::mir::BorrowKind::Shared,
4572 ) => CaptureKind::SharedRef,
4573 hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Mut {
4574 kind: MutBorrowKind::ClosureCapture,
4575 }) => CaptureKind::UniqueSharedRef,
4576 hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Mut {
4577 kind: MutBorrowKind::Default | MutBorrowKind::TwoPhasedBorrow,
4578 }) => CaptureKind::MutableRef,
4579 hir_ty::CaptureKind::ByValue => CaptureKind::Move,
4580 }
4581 }
4582
4583 pub fn place_to_name(&self, db: &dyn HirDatabase) -> String {
4585 self.capture.place_to_name(self.owner, db)
4586 }
4587
4588 pub fn display_place_source_code(&self, db: &dyn HirDatabase) -> String {
4589 self.capture.display_place_source_code(self.owner, db)
4590 }
4591
4592 pub fn display_place(&self, db: &dyn HirDatabase) -> String {
4593 self.capture.display_place(self.owner, db)
4594 }
4595}
4596
4597#[derive(Clone, Copy, PartialEq, Eq)]
4598pub enum CaptureKind {
4599 SharedRef,
4600 UniqueSharedRef,
4601 MutableRef,
4602 Move,
4603}
4604
4605#[derive(Debug, Clone)]
4606pub struct CaptureUsages {
4607 parent: DefWithBodyId,
4608 spans: SmallVec<[mir::MirSpan; 3]>,
4609}
4610
4611impl CaptureUsages {
4612 pub fn sources(&self, db: &dyn HirDatabase) -> Vec<CaptureUsageSource> {
4613 let (body, source_map) = db.body_with_source_map(self.parent);
4614 let mut result = Vec::with_capacity(self.spans.len());
4615 for &span in self.spans.iter() {
4616 let is_ref = span.is_ref_span(&body);
4617 match span {
4618 mir::MirSpan::ExprId(expr) => {
4619 if let Ok(expr) = source_map.expr_syntax(expr) {
4620 result.push(CaptureUsageSource { is_ref, source: expr })
4621 }
4622 }
4623 mir::MirSpan::PatId(pat) => {
4624 if let Ok(pat) = source_map.pat_syntax(pat) {
4625 result.push(CaptureUsageSource { is_ref, source: pat });
4626 }
4627 }
4628 mir::MirSpan::BindingId(binding) => result.extend(
4629 source_map
4630 .patterns_for_binding(binding)
4631 .iter()
4632 .filter_map(|&pat| source_map.pat_syntax(pat).ok())
4633 .map(|pat| CaptureUsageSource { is_ref, source: pat }),
4634 ),
4635 mir::MirSpan::SelfParam | mir::MirSpan::Unknown => {
4636 unreachable!("invalid capture usage span")
4637 }
4638 }
4639 }
4640 result
4641 }
4642}
4643
4644#[derive(Debug)]
4645pub struct CaptureUsageSource {
4646 is_ref: bool,
4647 source: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
4648}
4649
4650impl CaptureUsageSource {
4651 pub fn source(&self) -> AstPtr<Either<ast::Expr, ast::Pat>> {
4652 self.source.value
4653 }
4654
4655 pub fn file_id(&self) -> HirFileId {
4656 self.source.file_id
4657 }
4658
4659 pub fn is_ref(&self) -> bool {
4660 self.is_ref
4661 }
4662}
4663
4664#[derive(Clone, PartialEq, Eq, Debug, Hash)]
4665pub struct Type {
4666 env: Arc<TraitEnvironment>,
4667 ty: Ty,
4668}
4669
4670impl Type {
4671 pub(crate) fn new_with_resolver(db: &dyn HirDatabase, resolver: &Resolver, ty: Ty) -> Type {
4672 Type::new_with_resolver_inner(db, resolver, ty)
4673 }
4674
4675 pub(crate) fn new_with_resolver_inner(
4676 db: &dyn HirDatabase,
4677 resolver: &Resolver,
4678 ty: Ty,
4679 ) -> Type {
4680 let environment = resolver
4681 .generic_def()
4682 .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
4683 Type { env: environment, ty }
4684 }
4685
4686 pub(crate) fn new_for_crate(krate: CrateId, ty: Ty) -> Type {
4687 Type { env: TraitEnvironment::empty(krate), ty }
4688 }
4689
4690 fn new(db: &dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty) -> Type {
4691 let resolver = lexical_env.resolver(db.upcast());
4692 let environment = resolver
4693 .generic_def()
4694 .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
4695 Type { env: environment, ty }
4696 }
4697
4698 fn from_def(db: &dyn HirDatabase, def: impl Into<TyDefId> + HasResolver) -> Type {
4699 let ty = db.ty(def.into());
4700 let substs = TyBuilder::unknown_subst(
4701 db,
4702 match def.into() {
4703 TyDefId::AdtId(it) => GenericDefId::AdtId(it),
4704 TyDefId::TypeAliasId(it) => GenericDefId::TypeAliasId(it),
4705 TyDefId::BuiltinType(_) => return Type::new(db, def, ty.skip_binders().clone()),
4706 },
4707 );
4708 Type::new(db, def, ty.substitute(Interner, &substs))
4709 }
4710
4711 fn from_value_def(db: &dyn HirDatabase, def: impl Into<ValueTyDefId> + HasResolver) -> Type {
4712 let Some(ty) = db.value_ty(def.into()) else {
4713 return Type::new(db, def, TyKind::Error.intern(Interner));
4714 };
4715 let substs = TyBuilder::unknown_subst(
4716 db,
4717 match def.into() {
4718 ValueTyDefId::ConstId(it) => GenericDefId::ConstId(it),
4719 ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it),
4720 ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)),
4721 ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)),
4722 ValueTyDefId::EnumVariantId(it) => {
4723 GenericDefId::AdtId(AdtId::EnumId(it.lookup(db.upcast()).parent))
4724 }
4725 ValueTyDefId::StaticId(_) => return Type::new(db, def, ty.skip_binders().clone()),
4726 },
4727 );
4728 Type::new(db, def, ty.substitute(Interner, &substs))
4729 }
4730
4731 pub fn new_slice(ty: Type) -> Type {
4732 Type { env: ty.env, ty: TyBuilder::slice(ty.ty) }
4733 }
4734
4735 pub fn new_tuple(krate: CrateId, tys: &[Type]) -> Type {
4736 let tys = tys.iter().map(|it| it.ty.clone());
4737 Type { env: TraitEnvironment::empty(krate), ty: TyBuilder::tuple_with(tys) }
4738 }
4739
4740 pub fn is_unit(&self) -> bool {
4741 matches!(self.ty.kind(Interner), TyKind::Tuple(0, ..))
4742 }
4743
4744 pub fn is_bool(&self) -> bool {
4745 matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Bool))
4746 }
4747
4748 pub fn is_str(&self) -> bool {
4749 matches!(self.ty.kind(Interner), TyKind::Str)
4750 }
4751
4752 pub fn is_never(&self) -> bool {
4753 matches!(self.ty.kind(Interner), TyKind::Never)
4754 }
4755
4756 pub fn is_mutable_reference(&self) -> bool {
4757 matches!(self.ty.kind(Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
4758 }
4759
4760 pub fn is_reference(&self) -> bool {
4761 matches!(self.ty.kind(Interner), TyKind::Ref(..))
4762 }
4763
4764 pub fn contains_reference(&self, db: &dyn HirDatabase) -> bool {
4765 return go(db, self.env.krate, &self.ty);
4766
4767 fn go(db: &dyn HirDatabase, krate: CrateId, ty: &Ty) -> bool {
4768 match ty.kind(Interner) {
4769 TyKind::Ref(_, _, _) => true,
4771
4772 TyKind::Adt(adt_id, substitution)
4774 if !db.adt_datum(krate, *adt_id).flags.phantom_data =>
4775 {
4776 let adt_datum = &db.adt_datum(krate, *adt_id);
4777 let adt_datum_bound =
4778 adt_datum.binders.clone().substitute(Interner, substitution);
4779 adt_datum_bound
4780 .variants
4781 .into_iter()
4782 .flat_map(|variant| variant.fields.into_iter())
4783 .any(|ty| go(db, krate, &ty))
4784 || substitution
4785 .iter(Interner)
4786 .filter_map(|x| x.ty(Interner))
4787 .any(|ty| go(db, krate, ty))
4788 }
4789 TyKind::Adt(_, substitution)
4791 | TyKind::Tuple(_, substitution)
4792 | TyKind::OpaqueType(_, substitution)
4793 | TyKind::AssociatedType(_, substitution)
4794 | TyKind::FnDef(_, substitution) => substitution
4795 .iter(Interner)
4796 .filter_map(|x| x.ty(Interner))
4797 .any(|ty| go(db, krate, ty)),
4798
4799 TyKind::Array(ty, _) | TyKind::Slice(ty) | TyKind::Raw(_, ty) => go(db, krate, ty),
4801
4802 _ => false,
4804 }
4805 }
4806 }
4807
4808 pub fn as_reference(&self) -> Option<(Type, Mutability)> {
4809 let (ty, _lt, m) = self.ty.as_reference()?;
4810 let m = Mutability::from_mutable(matches!(m, hir_ty::Mutability::Mut));
4811 Some((self.derived(ty.clone()), m))
4812 }
4813
4814 pub fn add_reference(&self, mutability: Mutability) -> Type {
4815 let ty_mutability = match mutability {
4816 Mutability::Shared => hir_ty::Mutability::Not,
4817 Mutability::Mut => hir_ty::Mutability::Mut,
4818 };
4819 self.derived(TyKind::Ref(ty_mutability, error_lifetime(), self.ty.clone()).intern(Interner))
4820 }
4821
4822 pub fn is_slice(&self) -> bool {
4823 matches!(self.ty.kind(Interner), TyKind::Slice(..))
4824 }
4825
4826 pub fn is_usize(&self) -> bool {
4827 matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
4828 }
4829
4830 pub fn is_float(&self) -> bool {
4831 matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Float(_)))
4832 }
4833
4834 pub fn is_char(&self) -> bool {
4835 matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Char))
4836 }
4837
4838 pub fn is_int_or_uint(&self) -> bool {
4839 matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)))
4840 }
4841
4842 pub fn is_scalar(&self) -> bool {
4843 matches!(self.ty.kind(Interner), TyKind::Scalar(_))
4844 }
4845
4846 pub fn is_tuple(&self) -> bool {
4847 matches!(self.ty.kind(Interner), TyKind::Tuple(..))
4848 }
4849
4850 pub fn remove_ref(&self) -> Option<Type> {
4851 match &self.ty.kind(Interner) {
4852 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
4853 _ => None,
4854 }
4855 }
4856
4857 pub fn as_slice(&self) -> Option<Type> {
4858 match &self.ty.kind(Interner) {
4859 TyKind::Slice(ty) => Some(self.derived(ty.clone())),
4860 _ => None,
4861 }
4862 }
4863
4864 pub fn strip_references(&self) -> Type {
4865 self.derived(self.ty.strip_references().clone())
4866 }
4867
4868 pub fn strip_reference(&self) -> Type {
4869 self.derived(self.ty.strip_reference().clone())
4870 }
4871
4872 pub fn is_unknown(&self) -> bool {
4873 self.ty.is_unknown()
4874 }
4875
4876 pub fn into_future_output(&self, db: &dyn HirDatabase) -> Option<Type> {
4880 let trait_ = db
4881 .lang_item(self.env.krate, LangItem::IntoFutureIntoFuture)
4882 .and_then(|it| {
4883 let into_future_fn = it.as_function()?;
4884 let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?;
4885 let into_future_trait = assoc_item.container_or_implemented_trait(db)?;
4886 Some(into_future_trait.id)
4887 })
4888 .or_else(|| {
4889 let future_trait = db.lang_item(self.env.krate, LangItem::Future)?;
4890 future_trait.as_trait()
4891 })?;
4892
4893 let canonical_ty =
4894 Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
4895 if !method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, trait_) {
4896 return None;
4897 }
4898
4899 let output_assoc_type = db
4900 .trait_data(trait_)
4901 .associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))?;
4902 self.normalize_trait_assoc_type(db, &[], output_assoc_type.into())
4903 }
4904
4905 pub fn future_output(self, db: &dyn HirDatabase) -> Option<Type> {
4907 let future_output =
4908 db.lang_item(self.env.krate, LangItem::FutureOutput)?.as_type_alias()?;
4909 self.normalize_trait_assoc_type(db, &[], future_output.into())
4910 }
4911
4912 pub fn iterator_item(self, db: &dyn HirDatabase) -> Option<Type> {
4914 let iterator_trait = db.lang_item(self.env.krate, LangItem::Iterator)?.as_trait()?;
4915 let iterator_item = db
4916 .trait_data(iterator_trait)
4917 .associated_type_by_name(&Name::new_symbol_root(sym::Item.clone()))?;
4918 self.normalize_trait_assoc_type(db, &[], iterator_item.into())
4919 }
4920
4921 pub fn impls_iterator(self, db: &dyn HirDatabase) -> bool {
4922 let Some(iterator_trait) =
4923 db.lang_item(self.env.krate, LangItem::Iterator).and_then(|it| it.as_trait())
4924 else {
4925 return false;
4926 };
4927 let canonical_ty =
4928 Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
4929 method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, iterator_trait)
4930 }
4931
4932 pub fn into_iterator_iter(self, db: &dyn HirDatabase) -> Option<Type> {
4934 let trait_ = db.lang_item(self.env.krate, LangItem::IntoIterIntoIter).and_then(|it| {
4935 let into_iter_fn = it.as_function()?;
4936 let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?;
4937 let into_iter_trait = assoc_item.container_or_implemented_trait(db)?;
4938 Some(into_iter_trait.id)
4939 })?;
4940
4941 let canonical_ty =
4942 Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
4943 if !method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, trait_) {
4944 return None;
4945 }
4946
4947 let into_iter_assoc_type = db
4948 .trait_data(trait_)
4949 .associated_type_by_name(&Name::new_symbol_root(sym::IntoIter.clone()))?;
4950 self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into())
4951 }
4952
4953 pub fn impls_fnonce(&self, db: &dyn HirDatabase) -> bool {
4958 let fnonce_trait = match FnTrait::FnOnce.get_id(db, self.env.krate) {
4959 Some(it) => it,
4960 None => return false,
4961 };
4962
4963 let canonical_ty =
4964 Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
4965 method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, fnonce_trait)
4966 }
4967
4968 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
4970 let mut it = args.iter().map(|t| t.ty.clone());
4971 let trait_ref = TyBuilder::trait_ref(db, trait_.id)
4972 .push(self.ty.clone())
4973 .fill(|x| {
4974 match x {
4975 ParamKind::Type => {
4976 it.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
4977 }
4978 ParamKind::Const(ty) => {
4979 unknown_const_as_generic(ty.clone())
4981 }
4982 ParamKind::Lifetime => error_lifetime().cast(Interner),
4983 }
4984 })
4985 .build();
4986
4987 let goal = Canonical {
4988 value: hir_ty::InEnvironment::new(&self.env.env, trait_ref.cast(Interner)),
4989 binders: CanonicalVarKinds::empty(Interner),
4990 };
4991
4992 db.trait_solve(self.env.krate, self.env.block, goal).is_some()
4993 }
4994
4995 pub fn normalize_trait_assoc_type(
4996 &self,
4997 db: &dyn HirDatabase,
4998 args: &[Type],
4999 alias: TypeAlias,
5000 ) -> Option<Type> {
5001 let mut args = args.iter();
5002 let trait_id = match alias.id.lookup(db.upcast()).container {
5003 ItemContainerId::TraitId(id) => id,
5004 _ => unreachable!("non assoc type alias reached in normalize_trait_assoc_type()"),
5005 };
5006 let parent_subst = TyBuilder::subst_for_def(db, trait_id, None)
5007 .push(self.ty.clone())
5008 .fill(|it| {
5009 match it {
5011 ParamKind::Type => args.next().unwrap().ty.clone().cast(Interner),
5012 ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
5013 ParamKind::Lifetime => error_lifetime().cast(Interner),
5014 }
5015 })
5016 .build();
5017 let projection = TyBuilder::assoc_type_projection(db, alias.id, Some(parent_subst)).build();
5019
5020 let ty = db.normalize_projection(projection, self.env.clone());
5021 if ty.is_unknown() {
5022 None
5023 } else {
5024 Some(self.derived(ty))
5025 }
5026 }
5027
5028 pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
5029 let lang_item = db.lang_item(self.env.krate, LangItem::Copy);
5030 let copy_trait = match lang_item {
5031 Some(LangItemTarget::Trait(it)) => it,
5032 _ => return false,
5033 };
5034 self.impls_trait(db, copy_trait.into(), &[])
5035 }
5036
5037 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
5038 let callee = match self.ty.kind(Interner) {
5039 TyKind::Closure(id, subst) => Callee::Closure(*id, subst.clone()),
5040 TyKind::Function(_) => Callee::FnPtr,
5041 TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(db)?),
5042 kind => {
5043 let (ty, kind) = if let TyKind::Ref(_, _, ty) = kind {
5045 (ty, ty.kind(Interner))
5046 } else {
5047 (&self.ty, kind)
5048 };
5049 if let TyKind::Closure(closure, subst) = kind {
5050 let sig = ty.callable_sig(db)?;
5051 return Some(Callable {
5052 ty: self.clone(),
5053 sig,
5054 callee: Callee::Closure(*closure, subst.clone()),
5055 is_bound_method: false,
5056 });
5057 }
5058 let (fn_trait, sig) = hir_ty::callable_sig_from_fn_trait(ty, self.env.clone(), db)?;
5059 return Some(Callable {
5060 ty: self.clone(),
5061 sig,
5062 callee: Callee::FnImpl(fn_trait),
5063 is_bound_method: false,
5064 });
5065 }
5066 };
5067
5068 let sig = self.ty.callable_sig(db)?;
5069 Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
5070 }
5071
5072 pub fn is_closure(&self) -> bool {
5073 matches!(self.ty.kind(Interner), TyKind::Closure { .. })
5074 }
5075
5076 pub fn as_closure(&self) -> Option<Closure> {
5077 match self.ty.kind(Interner) {
5078 TyKind::Closure(id, subst) => Some(Closure { id: *id, subst: subst.clone() }),
5079 _ => None,
5080 }
5081 }
5082
5083 pub fn is_fn(&self) -> bool {
5084 matches!(self.ty.kind(Interner), TyKind::FnDef(..) | TyKind::Function { .. })
5085 }
5086
5087 pub fn is_array(&self) -> bool {
5088 matches!(self.ty.kind(Interner), TyKind::Array(..))
5089 }
5090
5091 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
5092 let adt_id = match *self.ty.kind(Interner) {
5093 TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
5094 _ => return false,
5095 };
5096
5097 let adt = adt_id.into();
5098 match adt {
5099 Adt::Struct(s) => s.repr(db).unwrap_or_default().pack.is_some(),
5100 _ => false,
5101 }
5102 }
5103
5104 pub fn is_raw_ptr(&self) -> bool {
5105 matches!(self.ty.kind(Interner), TyKind::Raw(..))
5106 }
5107
5108 pub fn remove_raw_ptr(&self) -> Option<Type> {
5109 if let TyKind::Raw(_, ty) = self.ty.kind(Interner) {
5110 Some(self.derived(ty.clone()))
5111 } else {
5112 None
5113 }
5114 }
5115
5116 pub fn contains_unknown(&self) -> bool {
5117 return go(&self.ty);
5120
5121 fn go(ty: &Ty) -> bool {
5122 match ty.kind(Interner) {
5123 TyKind::Error => true,
5124
5125 TyKind::Adt(_, substs)
5126 | TyKind::AssociatedType(_, substs)
5127 | TyKind::Tuple(_, substs)
5128 | TyKind::OpaqueType(_, substs)
5129 | TyKind::FnDef(_, substs)
5130 | TyKind::Closure(_, substs) => {
5131 substs.iter(Interner).filter_map(|a| a.ty(Interner)).any(go)
5132 }
5133
5134 TyKind::Array(_ty, len) if len.is_unknown() => true,
5135 TyKind::Array(ty, _)
5136 | TyKind::Slice(ty)
5137 | TyKind::Raw(_, ty)
5138 | TyKind::Ref(_, _, ty) => go(ty),
5139
5140 TyKind::Scalar(_)
5141 | TyKind::Str
5142 | TyKind::Never
5143 | TyKind::Placeholder(_)
5144 | TyKind::BoundVar(_)
5145 | TyKind::InferenceVar(_, _)
5146 | TyKind::Dyn(_)
5147 | TyKind::Function(_)
5148 | TyKind::Alias(_)
5149 | TyKind::Foreign(_)
5150 | TyKind::Coroutine(..)
5151 | TyKind::CoroutineWitness(..) => false,
5152 }
5153 }
5154 }
5155
5156 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
5157 let (variant_id, substs) = match self.ty.kind(Interner) {
5158 TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), substs) => ((*s).into(), substs),
5159 TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), substs) => ((*u).into(), substs),
5160 _ => return Vec::new(),
5161 };
5162
5163 db.field_types(variant_id)
5164 .iter()
5165 .map(|(local_id, ty)| {
5166 let def = Field { parent: variant_id.into(), id: local_id };
5167 let ty = ty.clone().substitute(Interner, substs);
5168 (def, self.derived(ty))
5169 })
5170 .collect()
5171 }
5172
5173 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
5174 if let TyKind::Tuple(_, substs) = &self.ty.kind(Interner) {
5175 substs
5176 .iter(Interner)
5177 .map(|ty| self.derived(ty.assert_ty_ref(Interner).clone()))
5178 .collect()
5179 } else {
5180 Vec::new()
5181 }
5182 }
5183
5184 pub fn as_array(&self, db: &dyn HirDatabase) -> Option<(Type, usize)> {
5185 if let TyKind::Array(ty, len) = &self.ty.kind(Interner) {
5186 try_const_usize(db, len).map(|it| (self.derived(ty.clone()), it as usize))
5187 } else {
5188 None
5189 }
5190 }
5191
5192 pub fn fingerprint_for_trait_impl(&self) -> Option<TyFingerprint> {
5193 TyFingerprint::for_trait_impl(&self.ty)
5194 }
5195
5196 pub(crate) fn canonical(&self) -> Canonical<Ty> {
5197 hir_ty::replace_errors_with_variables(&self.ty)
5198 }
5199
5200 pub fn autoderef(&self, db: &dyn HirDatabase) -> impl Iterator<Item = Type> + '_ {
5203 self.autoderef_(db).map(move |ty| self.derived(ty))
5204 }
5205
5206 fn autoderef_(&self, db: &dyn HirDatabase) -> impl Iterator<Item = Ty> {
5207 let canonical = hir_ty::replace_errors_with_variables(&self.ty);
5209 autoderef(db, self.env.clone(), canonical)
5210 }
5211
5212 pub fn iterate_assoc_items<T>(
5215 &self,
5216 db: &dyn HirDatabase,
5217 krate: Crate,
5218 mut callback: impl FnMut(AssocItem) -> Option<T>,
5219 ) -> Option<T> {
5220 let mut slot = None;
5221 self.iterate_assoc_items_dyn(db, krate, &mut |assoc_item_id| {
5222 slot = callback(assoc_item_id.into());
5223 slot.is_some()
5224 });
5225 slot
5226 }
5227
5228 fn iterate_assoc_items_dyn(
5229 &self,
5230 db: &dyn HirDatabase,
5231 krate: Crate,
5232 callback: &mut dyn FnMut(AssocItemId) -> bool,
5233 ) {
5234 let def_crates = match method_resolution::def_crates(db, &self.ty, krate.id) {
5235 Some(it) => it,
5236 None => return,
5237 };
5238 for krate in def_crates {
5239 let impls = db.inherent_impls_in_crate(krate);
5240
5241 for impl_def in impls.for_self_ty(&self.ty) {
5242 for &(_, item) in db.impl_data(*impl_def).items.iter() {
5243 if callback(item) {
5244 return;
5245 }
5246 }
5247 }
5248 }
5249 }
5250
5251 pub fn type_arguments(&self) -> impl Iterator<Item = Type> + '_ {
5270 self.ty
5271 .strip_references()
5272 .as_adt()
5273 .map(|(_, substs)| substs)
5274 .or_else(|| self.ty.strip_references().as_tuple())
5275 .into_iter()
5276 .flat_map(|substs| substs.iter(Interner))
5277 .filter_map(|arg| arg.ty(Interner).cloned())
5278 .map(move |ty| self.derived(ty))
5279 }
5280
5281 pub fn type_and_const_arguments<'a>(
5300 &'a self,
5301 db: &'a dyn HirDatabase,
5302 edition: Edition,
5303 ) -> impl Iterator<Item = SmolStr> + 'a {
5304 self.ty
5305 .strip_references()
5306 .as_adt()
5307 .into_iter()
5308 .flat_map(|(_, substs)| substs.iter(Interner))
5309 .filter_map(move |arg| {
5310 if let Some(ty) = arg.ty(Interner) {
5312 Some(format_smolstr!("{}", ty.display(db, edition)))
5313 } else {
5314 arg.constant(Interner)
5315 .map(|const_| format_smolstr!("{}", const_.display(db, edition)))
5316 }
5317 })
5318 }
5319
5320 pub fn generic_parameters<'a>(
5322 &'a self,
5323 db: &'a dyn HirDatabase,
5324 edition: Edition,
5325 ) -> impl Iterator<Item = SmolStr> + 'a {
5326 self.as_adt()
5328 .and_then(|a| {
5329 a.lifetime(db).map(|lt| lt.name.display_no_db(Edition::Edition2015).to_smolstr())
5331 })
5332 .into_iter()
5333 .chain(self.type_and_const_arguments(db, edition))
5335 }
5336
5337 pub fn iterate_method_candidates_with_traits<T>(
5338 &self,
5339 db: &dyn HirDatabase,
5340 scope: &SemanticsScope<'_>,
5341 traits_in_scope: &FxHashSet<TraitId>,
5342 with_local_impls: Option<Module>,
5343 name: Option<&Name>,
5344 mut callback: impl FnMut(Function) -> Option<T>,
5345 ) -> Option<T> {
5346 let _p = tracing::info_span!("iterate_method_candidates_with_traits").entered();
5347 let mut slot = None;
5348 self.iterate_method_candidates_split_inherent(
5349 db,
5350 scope,
5351 traits_in_scope,
5352 with_local_impls,
5353 name,
5354 |f| match callback(f) {
5355 it @ Some(_) => {
5356 slot = it;
5357 ControlFlow::Break(())
5358 }
5359 None => ControlFlow::Continue(()),
5360 },
5361 );
5362 slot
5363 }
5364
5365 pub fn iterate_method_candidates<T>(
5366 &self,
5367 db: &dyn HirDatabase,
5368 scope: &SemanticsScope<'_>,
5369 with_local_impls: Option<Module>,
5370 name: Option<&Name>,
5371 callback: impl FnMut(Function) -> Option<T>,
5372 ) -> Option<T> {
5373 self.iterate_method_candidates_with_traits(
5374 db,
5375 scope,
5376 &scope.visible_traits().0,
5377 with_local_impls,
5378 name,
5379 callback,
5380 )
5381 }
5382
5383 pub fn iterate_method_candidates_split_inherent(
5388 &self,
5389 db: &dyn HirDatabase,
5390 scope: &SemanticsScope<'_>,
5391 traits_in_scope: &FxHashSet<TraitId>,
5392 with_local_impls: Option<Module>,
5393 name: Option<&Name>,
5394 callback: impl MethodCandidateCallback,
5395 ) {
5396 struct Callback<T>(T);
5397
5398 impl<T: MethodCandidateCallback> method_resolution::MethodCandidateCallback for Callback<T> {
5399 fn on_inherent_method(
5400 &mut self,
5401 _adjustments: method_resolution::ReceiverAdjustments,
5402 item: AssocItemId,
5403 _is_visible: bool,
5404 ) -> ControlFlow<()> {
5405 if let AssocItemId::FunctionId(func) = item {
5406 self.0.on_inherent_method(func.into())
5407 } else {
5408 ControlFlow::Continue(())
5409 }
5410 }
5411
5412 fn on_trait_method(
5413 &mut self,
5414 _adjustments: method_resolution::ReceiverAdjustments,
5415 item: AssocItemId,
5416 _is_visible: bool,
5417 ) -> ControlFlow<()> {
5418 if let AssocItemId::FunctionId(func) = item {
5419 self.0.on_trait_method(func.into())
5420 } else {
5421 ControlFlow::Continue(())
5422 }
5423 }
5424 }
5425
5426 let _p = tracing::info_span!(
5427 "iterate_method_candidates_dyn",
5428 with_local_impls = traits_in_scope.len(),
5429 traits_in_scope = traits_in_scope.len(),
5430 ?name,
5431 )
5432 .entered();
5433 let canonical = hir_ty::replace_errors_with_variables(&self.ty);
5435
5436 let krate = scope.krate();
5437 let environment = scope
5438 .resolver()
5439 .generic_def()
5440 .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d));
5441
5442 method_resolution::iterate_method_candidates_dyn(
5443 &canonical,
5444 db,
5445 environment,
5446 traits_in_scope,
5447 with_local_impls.and_then(|b| b.id.containing_block()).into(),
5448 name,
5449 method_resolution::LookupMode::MethodCall,
5450 &mut Callback(callback),
5451 );
5452 }
5453
5454 #[tracing::instrument(skip_all, fields(name = ?name))]
5455 pub fn iterate_path_candidates<T>(
5456 &self,
5457 db: &dyn HirDatabase,
5458 scope: &SemanticsScope<'_>,
5459 traits_in_scope: &FxHashSet<TraitId>,
5460 with_local_impls: Option<Module>,
5461 name: Option<&Name>,
5462 mut callback: impl FnMut(AssocItem) -> Option<T>,
5463 ) -> Option<T> {
5464 let _p = tracing::info_span!("iterate_path_candidates").entered();
5465 let mut slot = None;
5466
5467 self.iterate_path_candidates_split_inherent(
5468 db,
5469 scope,
5470 traits_in_scope,
5471 with_local_impls,
5472 name,
5473 |item| match callback(item) {
5474 it @ Some(_) => {
5475 slot = it;
5476 ControlFlow::Break(())
5477 }
5478 None => ControlFlow::Continue(()),
5479 },
5480 );
5481 slot
5482 }
5483
5484 #[tracing::instrument(skip_all, fields(name = ?name))]
5490 pub fn iterate_path_candidates_split_inherent(
5491 &self,
5492 db: &dyn HirDatabase,
5493 scope: &SemanticsScope<'_>,
5494 traits_in_scope: &FxHashSet<TraitId>,
5495 with_local_impls: Option<Module>,
5496 name: Option<&Name>,
5497 callback: impl PathCandidateCallback,
5498 ) {
5499 struct Callback<T>(T);
5500
5501 impl<T: PathCandidateCallback> method_resolution::MethodCandidateCallback for Callback<T> {
5502 fn on_inherent_method(
5503 &mut self,
5504 _adjustments: method_resolution::ReceiverAdjustments,
5505 item: AssocItemId,
5506 _is_visible: bool,
5507 ) -> ControlFlow<()> {
5508 self.0.on_inherent_item(item.into())
5509 }
5510
5511 fn on_trait_method(
5512 &mut self,
5513 _adjustments: method_resolution::ReceiverAdjustments,
5514 item: AssocItemId,
5515 _is_visible: bool,
5516 ) -> ControlFlow<()> {
5517 self.0.on_trait_item(item.into())
5518 }
5519 }
5520
5521 let canonical = hir_ty::replace_errors_with_variables(&self.ty);
5522
5523 let krate = scope.krate();
5524 let environment = scope
5525 .resolver()
5526 .generic_def()
5527 .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d));
5528
5529 method_resolution::iterate_path_candidates(
5530 &canonical,
5531 db,
5532 environment,
5533 traits_in_scope,
5534 with_local_impls.and_then(|b| b.id.containing_block()).into(),
5535 name,
5536 &mut Callback(callback),
5537 );
5538 }
5539
5540 pub fn as_adt(&self) -> Option<Adt> {
5541 let (adt, _subst) = self.ty.as_adt()?;
5542 Some(adt.into())
5543 }
5544
5545 pub fn as_builtin(&self) -> Option<BuiltinType> {
5546 self.ty.as_builtin().map(|inner| BuiltinType { inner })
5547 }
5548
5549 pub fn as_dyn_trait(&self) -> Option<Trait> {
5550 self.ty.dyn_trait().map(Into::into)
5551 }
5552
5553 pub fn applicable_inherent_traits<'a>(
5556 &'a self,
5557 db: &'a dyn HirDatabase,
5558 ) -> impl Iterator<Item = Trait> + 'a {
5559 let _p = tracing::info_span!("applicable_inherent_traits").entered();
5560 self.autoderef_(db)
5561 .filter_map(|ty| ty.dyn_trait())
5562 .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
5563 .map(Trait::from)
5564 }
5565
5566 pub fn env_traits<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Trait> + 'a {
5567 let _p = tracing::info_span!("env_traits").entered();
5568 self.autoderef_(db)
5569 .filter(|ty| matches!(ty.kind(Interner), TyKind::Placeholder(_)))
5570 .flat_map(|ty| {
5571 self.env
5572 .traits_in_scope_from_clauses(ty)
5573 .flat_map(|t| hir_ty::all_super_traits(db.upcast(), t))
5574 })
5575 .map(Trait::from)
5576 }
5577
5578 pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<impl Iterator<Item = Trait>> {
5579 self.ty.impl_trait_bounds(db).map(|it| {
5580 it.into_iter().filter_map(|pred| match pred.skip_binders() {
5581 hir_ty::WhereClause::Implemented(trait_ref) => {
5582 Some(Trait::from(trait_ref.hir_trait_id()))
5583 }
5584 _ => None,
5585 })
5586 })
5587 }
5588
5589 pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> {
5590 self.ty.associated_type_parent_trait(db).map(Into::into)
5591 }
5592
5593 fn derived(&self, ty: Ty) -> Type {
5594 Type { env: self.env.clone(), ty }
5595 }
5596
5597 pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
5600 fn walk_substs(
5601 db: &dyn HirDatabase,
5602 type_: &Type,
5603 substs: &Substitution,
5604 cb: &mut impl FnMut(Type),
5605 ) {
5606 for ty in substs.iter(Interner).filter_map(|a| a.ty(Interner)) {
5607 walk_type(db, &type_.derived(ty.clone()), cb);
5608 }
5609 }
5610
5611 fn walk_bounds(
5612 db: &dyn HirDatabase,
5613 type_: &Type,
5614 bounds: &[QuantifiedWhereClause],
5615 cb: &mut impl FnMut(Type),
5616 ) {
5617 for pred in bounds {
5618 if let WhereClause::Implemented(trait_ref) = pred.skip_binders() {
5619 cb(type_.clone());
5620 if let [self_ty, params @ ..] = trait_ref.substitution.as_slice(Interner) {
5622 for ty in
5623 params.iter().filter(|&ty| ty != self_ty).filter_map(|a| a.ty(Interner))
5624 {
5625 walk_type(db, &type_.derived(ty.clone()), cb);
5626 }
5627 }
5628 }
5629 }
5630 }
5631
5632 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
5633 let ty = type_.ty.strip_references();
5634 match ty.kind(Interner) {
5635 TyKind::Adt(_, substs) => {
5636 cb(type_.derived(ty.clone()));
5637 walk_substs(db, type_, substs, cb);
5638 }
5639 TyKind::AssociatedType(_, substs) => {
5640 if ty.associated_type_parent_trait(db).is_some() {
5641 cb(type_.derived(ty.clone()));
5642 }
5643 walk_substs(db, type_, substs, cb);
5644 }
5645 TyKind::OpaqueType(_, subst) => {
5646 if let Some(bounds) = ty.impl_trait_bounds(db) {
5647 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
5648 }
5649
5650 walk_substs(db, type_, subst, cb);
5651 }
5652 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
5653 if let Some(bounds) = ty.impl_trait_bounds(db) {
5654 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
5655 }
5656
5657 walk_substs(db, type_, &opaque_ty.substitution, cb);
5658 }
5659 TyKind::Placeholder(_) => {
5660 cb(type_.derived(ty.clone()));
5661 if let Some(bounds) = ty.impl_trait_bounds(db) {
5662 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
5663 }
5664 }
5665 TyKind::Dyn(bounds) => {
5666 walk_bounds(
5667 db,
5668 &type_.derived(ty.clone()),
5669 bounds.bounds.skip_binders().interned(),
5670 cb,
5671 );
5672 }
5673
5674 TyKind::Ref(_, _, ty)
5675 | TyKind::Raw(_, ty)
5676 | TyKind::Array(ty, _)
5677 | TyKind::Slice(ty) => {
5678 walk_type(db, &type_.derived(ty.clone()), cb);
5679 }
5680
5681 TyKind::FnDef(_, substs)
5682 | TyKind::Tuple(_, substs)
5683 | TyKind::Closure(.., substs) => {
5684 walk_substs(db, type_, substs, cb);
5685 }
5686 TyKind::Function(hir_ty::FnPointer { substitution, .. }) => {
5687 walk_substs(db, type_, &substitution.0, cb);
5688 }
5689
5690 _ => {}
5691 }
5692 }
5693
5694 walk_type(db, self, &mut cb);
5695 }
5696 pub fn could_unify_with(&self, db: &dyn HirDatabase, other: &Type) -> bool {
5701 let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone()));
5702 hir_ty::could_unify(db, self.env.clone(), &tys)
5703 }
5704
5705 pub fn could_unify_with_deeply(&self, db: &dyn HirDatabase, other: &Type) -> bool {
5710 let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone()));
5711 hir_ty::could_unify_deeply(db, self.env.clone(), &tys)
5712 }
5713
5714 pub fn could_coerce_to(&self, db: &dyn HirDatabase, to: &Type) -> bool {
5715 let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), to.ty.clone()));
5716 hir_ty::could_coerce(db, self.env.clone(), &tys)
5717 }
5718
5719 pub fn as_type_param(&self, db: &dyn HirDatabase) -> Option<TypeParam> {
5720 match self.ty.kind(Interner) {
5721 TyKind::Placeholder(p) => Some(TypeParam {
5722 id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p)),
5723 }),
5724 _ => None,
5725 }
5726 }
5727
5728 pub fn generic_params(&self, db: &dyn HirDatabase) -> FxHashSet<GenericParam> {
5730 hir_ty::collect_placeholders(&self.ty, db)
5731 .into_iter()
5732 .map(|id| TypeOrConstParam { id }.split(db).either_into())
5733 .collect()
5734 }
5735
5736 pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
5737 db.layout_of_ty(self.ty.clone(), self.env.clone())
5738 .map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap()))
5739 }
5740}
5741
5742#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
5743pub struct InlineAsmOperand {
5744 owner: DefWithBodyId,
5745 expr: ExprId,
5746 index: usize,
5747}
5748
5749impl InlineAsmOperand {
5750 pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
5751 self.owner.into()
5752 }
5753
5754 pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
5755 match &db.body(self.owner)[self.expr] {
5756 hir_def::hir::Expr::InlineAsm(e) => e.operands.get(self.index)?.0.clone(),
5757 _ => None,
5758 }
5759 }
5760}
5761
5762#[derive(Debug)]
5764pub struct Callable {
5765 ty: Type,
5766 sig: CallableSig,
5767 callee: Callee,
5768 is_bound_method: bool,
5770}
5771
5772#[derive(Clone, PartialEq, Eq, Hash, Debug)]
5773enum Callee {
5774 Def(CallableDefId),
5775 Closure(ClosureId, Substitution),
5776 FnPtr,
5777 FnImpl(FnTrait),
5778}
5779
5780pub enum CallableKind {
5781 Function(Function),
5782 TupleStruct(Struct),
5783 TupleEnumVariant(Variant),
5784 Closure(Closure),
5785 FnPtr,
5786 FnImpl(FnTrait),
5787}
5788
5789impl Callable {
5790 pub fn kind(&self) -> CallableKind {
5791 match self.callee {
5792 Callee::Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
5793 Callee::Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
5794 Callee::Def(CallableDefId::EnumVariantId(it)) => {
5795 CallableKind::TupleEnumVariant(it.into())
5796 }
5797 Callee::Closure(id, ref subst) => {
5798 CallableKind::Closure(Closure { id, subst: subst.clone() })
5799 }
5800 Callee::FnPtr => CallableKind::FnPtr,
5801 Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_),
5802 }
5803 }
5804 pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(SelfParam, Type)> {
5805 let func = match self.callee {
5806 Callee::Def(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
5807 _ => return None,
5808 };
5809 let func = Function { id: func };
5810 Some((func.self_param(db)?, self.ty.derived(self.sig.params()[0].clone())))
5811 }
5812 pub fn n_params(&self) -> usize {
5813 self.sig.params().len() - if self.is_bound_method { 1 } else { 0 }
5814 }
5815 pub fn params(&self) -> Vec<Param> {
5816 self.sig
5817 .params()
5818 .iter()
5819 .enumerate()
5820 .skip(if self.is_bound_method { 1 } else { 0 })
5821 .map(|(idx, ty)| (idx, self.ty.derived(ty.clone())))
5822 .map(|(idx, ty)| Param { func: self.callee.clone(), idx, ty })
5823 .collect()
5824 }
5825 pub fn return_type(&self) -> Type {
5826 self.ty.derived(self.sig.ret().clone())
5827 }
5828 pub fn sig(&self) -> &CallableSig {
5829 &self.sig
5830 }
5831
5832 pub fn ty(&self) -> &Type {
5833 &self.ty
5834 }
5835}
5836
5837#[derive(Clone, Debug, Eq, PartialEq)]
5838pub struct Layout(Arc<TyLayout>, Arc<TargetDataLayout>);
5839
5840impl Layout {
5841 pub fn size(&self) -> u64 {
5842 self.0.size.bytes()
5843 }
5844
5845 pub fn align(&self) -> u64 {
5846 self.0.align.abi.bytes()
5847 }
5848
5849 pub fn niches(&self) -> Option<u128> {
5850 Some(self.0.largest_niche?.available(&*self.1))
5851 }
5852
5853 pub fn field_offset(&self, field: Field) -> Option<u64> {
5854 match self.0.fields {
5855 layout::FieldsShape::Primitive => None,
5856 layout::FieldsShape::Union(_) => Some(0),
5857 layout::FieldsShape::Array { stride, count } => {
5858 let i = u64::try_from(field.index()).ok()?;
5859 (i < count).then_some((stride * i).bytes())
5860 }
5861 layout::FieldsShape::Arbitrary { ref offsets, .. } => {
5862 Some(offsets.get(RustcFieldIdx(field.id))?.bytes())
5863 }
5864 }
5865 }
5866
5867 pub fn tuple_field_offset(&self, field: usize) -> Option<u64> {
5868 match self.0.fields {
5869 layout::FieldsShape::Primitive => None,
5870 layout::FieldsShape::Union(_) => Some(0),
5871 layout::FieldsShape::Array { stride, count } => {
5872 let i = u64::try_from(field).ok()?;
5873 (i < count).then_some((stride * i).bytes())
5874 }
5875 layout::FieldsShape::Arbitrary { ref offsets, .. } => {
5876 Some(offsets.get(RustcFieldIdx::new(field))?.bytes())
5877 }
5878 }
5879 }
5880
5881 pub fn enum_tag_size(&self) -> Option<usize> {
5882 let tag_size =
5883 if let layout::Variants::Multiple { tag, tag_encoding, .. } = &self.0.variants {
5884 match tag_encoding {
5885 TagEncoding::Direct => tag.size(&*self.1).bytes_usize(),
5886 TagEncoding::Niche { .. } => 0,
5887 }
5888 } else {
5889 return None;
5890 };
5891 Some(tag_size)
5892 }
5893}
5894
5895#[derive(Copy, Clone, Debug, Eq, PartialEq)]
5896pub enum BindingMode {
5897 Move,
5898 Ref(Mutability),
5899}
5900
5901#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
5903pub enum ScopeDef {
5904 ModuleDef(ModuleDef),
5905 GenericParam(GenericParam),
5906 ImplSelfType(Impl),
5907 AdtSelfType(Adt),
5908 Local(Local),
5909 Label(Label),
5910 Unknown,
5911}
5912
5913impl ScopeDef {
5914 pub fn all_items(def: PerNs) -> ArrayVec<Self, 3> {
5915 let mut items = ArrayVec::new();
5916
5917 match (def.take_types(), def.take_values()) {
5918 (Some(m1), None) => items.push(ScopeDef::ModuleDef(m1.into())),
5919 (None, Some(m2)) => items.push(ScopeDef::ModuleDef(m2.into())),
5920 (Some(m1), Some(m2)) => {
5921 if m1 != m2 {
5925 items.push(ScopeDef::ModuleDef(m1.into()));
5926 items.push(ScopeDef::ModuleDef(m2.into()));
5927 } else {
5928 items.push(ScopeDef::ModuleDef(m1.into()));
5929 }
5930 }
5931 (None, None) => {}
5932 };
5933
5934 if let Some(macro_def_id) = def.take_macros() {
5935 items.push(ScopeDef::ModuleDef(ModuleDef::Macro(macro_def_id.into())));
5936 }
5937
5938 if items.is_empty() {
5939 items.push(ScopeDef::Unknown);
5940 }
5941
5942 items
5943 }
5944
5945 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
5946 match self {
5947 ScopeDef::ModuleDef(it) => it.attrs(db),
5948 ScopeDef::GenericParam(it) => Some(it.attrs(db)),
5949 ScopeDef::ImplSelfType(_)
5950 | ScopeDef::AdtSelfType(_)
5951 | ScopeDef::Local(_)
5952 | ScopeDef::Label(_)
5953 | ScopeDef::Unknown => None,
5954 }
5955 }
5956
5957 pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
5958 match self {
5959 ScopeDef::ModuleDef(it) => it.module(db).map(|m| m.krate()),
5960 ScopeDef::GenericParam(it) => Some(it.module(db).krate()),
5961 ScopeDef::ImplSelfType(_) => None,
5962 ScopeDef::AdtSelfType(it) => Some(it.module(db).krate()),
5963 ScopeDef::Local(it) => Some(it.module(db).krate()),
5964 ScopeDef::Label(it) => Some(it.module(db).krate()),
5965 ScopeDef::Unknown => None,
5966 }
5967 }
5968}
5969
5970impl From<ItemInNs> for ScopeDef {
5971 fn from(item: ItemInNs) -> Self {
5972 match item {
5973 ItemInNs::Types(id) => ScopeDef::ModuleDef(id),
5974 ItemInNs::Values(id) => ScopeDef::ModuleDef(id),
5975 ItemInNs::Macros(id) => ScopeDef::ModuleDef(ModuleDef::Macro(id)),
5976 }
5977 }
5978}
5979
5980#[derive(Clone, Debug, PartialEq, Eq)]
5981pub struct Adjustment {
5982 pub source: Type,
5983 pub target: Type,
5984 pub kind: Adjust,
5985}
5986
5987#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
5988pub enum Adjust {
5989 NeverToAny,
5991 Deref(Option<OverloadedDeref>),
5993 Borrow(AutoBorrow),
5995 Pointer(PointerCast),
5996}
5997
5998#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
5999pub enum AutoBorrow {
6000 Ref(Mutability),
6002 RawPtr(Mutability),
6004}
6005
6006#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6007pub struct OverloadedDeref(pub Mutability);
6008
6009pub trait HasVisibility {
6010 fn visibility(&self, db: &dyn HirDatabase) -> Visibility;
6011 fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool {
6012 let vis = self.visibility(db);
6013 vis.is_visible_from(db.upcast(), module.id)
6014 }
6015}
6016
6017pub trait HasCrate {
6019 fn krate(&self, db: &dyn HirDatabase) -> Crate;
6020}
6021
6022impl<T: hir_def::HasModule> HasCrate for T {
6023 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6024 self.module(db.upcast()).krate().into()
6025 }
6026}
6027
6028impl HasCrate for AssocItem {
6029 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6030 self.module(db).krate()
6031 }
6032}
6033
6034impl HasCrate for Struct {
6035 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6036 self.module(db).krate()
6037 }
6038}
6039
6040impl HasCrate for Union {
6041 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6042 self.module(db).krate()
6043 }
6044}
6045
6046impl HasCrate for Enum {
6047 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6048 self.module(db).krate()
6049 }
6050}
6051
6052impl HasCrate for Field {
6053 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6054 self.parent_def(db).module(db).krate()
6055 }
6056}
6057
6058impl HasCrate for Variant {
6059 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6060 self.module(db).krate()
6061 }
6062}
6063
6064impl HasCrate for Function {
6065 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6066 self.module(db).krate()
6067 }
6068}
6069
6070impl HasCrate for Const {
6071 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6072 self.module(db).krate()
6073 }
6074}
6075
6076impl HasCrate for TypeAlias {
6077 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6078 self.module(db).krate()
6079 }
6080}
6081
6082impl HasCrate for Type {
6083 fn krate(&self, _db: &dyn HirDatabase) -> Crate {
6084 self.env.krate.into()
6085 }
6086}
6087
6088impl HasCrate for Macro {
6089 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6090 self.module(db).krate()
6091 }
6092}
6093
6094impl HasCrate for Trait {
6095 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6096 self.module(db).krate()
6097 }
6098}
6099
6100impl HasCrate for TraitAlias {
6101 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6102 self.module(db).krate()
6103 }
6104}
6105
6106impl HasCrate for Static {
6107 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6108 self.module(db).krate()
6109 }
6110}
6111
6112impl HasCrate for Adt {
6113 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6114 self.module(db).krate()
6115 }
6116}
6117
6118impl HasCrate for Impl {
6119 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6120 self.module(db).krate()
6121 }
6122}
6123
6124impl HasCrate for Module {
6125 fn krate(&self, _: &dyn HirDatabase) -> Crate {
6126 Module::krate(*self)
6127 }
6128}
6129
6130pub trait HasContainer {
6131 fn container(&self, db: &dyn HirDatabase) -> ItemContainer;
6132}
6133
6134impl HasContainer for ExternCrateDecl {
6135 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6136 container_id_to_hir(self.id.lookup(db.upcast()).container.into())
6137 }
6138}
6139
6140impl HasContainer for Module {
6141 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6142 let def_map = self.id.def_map(db.upcast());
6144 match def_map[self.id.local_id].parent {
6145 Some(parent_id) => ItemContainer::Module(Module { id: def_map.module_id(parent_id) }),
6146 None => ItemContainer::Crate(def_map.krate()),
6147 }
6148 }
6149}
6150
6151impl HasContainer for Function {
6152 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6153 container_id_to_hir(self.id.lookup(db.upcast()).container)
6154 }
6155}
6156
6157impl HasContainer for Struct {
6158 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6159 ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
6160 }
6161}
6162
6163impl HasContainer for Union {
6164 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6165 ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
6166 }
6167}
6168
6169impl HasContainer for Enum {
6170 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6171 ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
6172 }
6173}
6174
6175impl HasContainer for TypeAlias {
6176 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6177 container_id_to_hir(self.id.lookup(db.upcast()).container)
6178 }
6179}
6180
6181impl HasContainer for Const {
6182 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6183 container_id_to_hir(self.id.lookup(db.upcast()).container)
6184 }
6185}
6186
6187impl HasContainer for Static {
6188 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6189 container_id_to_hir(self.id.lookup(db.upcast()).container)
6190 }
6191}
6192
6193impl HasContainer for Trait {
6194 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6195 ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
6196 }
6197}
6198
6199impl HasContainer for TraitAlias {
6200 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6201 ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
6202 }
6203}
6204
6205impl HasContainer for ExternBlock {
6206 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6207 ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
6208 }
6209}
6210
6211fn container_id_to_hir(c: ItemContainerId) -> ItemContainer {
6212 match c {
6213 ItemContainerId::ExternBlockId(id) => ItemContainer::ExternBlock(ExternBlock { id }),
6214 ItemContainerId::ModuleId(id) => ItemContainer::Module(Module { id }),
6215 ItemContainerId::ImplId(id) => ItemContainer::Impl(Impl { id }),
6216 ItemContainerId::TraitId(id) => ItemContainer::Trait(Trait { id }),
6217 }
6218}
6219
6220#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6221pub enum ItemContainer {
6222 Trait(Trait),
6223 Impl(Impl),
6224 Module(Module),
6225 ExternBlock(ExternBlock),
6226 Crate(CrateId),
6227}
6228
6229pub enum DocLinkDef {
6231 ModuleDef(ModuleDef),
6232 Field(Field),
6233 SelfType(Trait),
6234}
6235
6236fn push_ty_diagnostics(
6237 db: &dyn HirDatabase,
6238 acc: &mut Vec<AnyDiagnostic>,
6239 diagnostics: Option<ThinArc<(), TyLoweringDiagnostic>>,
6240 source_map: &TypesSourceMap,
6241) {
6242 if let Some(diagnostics) = diagnostics {
6243 acc.extend(
6244 diagnostics
6245 .slice
6246 .iter()
6247 .filter_map(|diagnostic| AnyDiagnostic::ty_diagnostic(diagnostic, source_map, db)),
6248 );
6249 }
6250}
6251
6252pub trait MethodCandidateCallback {
6253 fn on_inherent_method(&mut self, f: Function) -> ControlFlow<()>;
6254
6255 fn on_trait_method(&mut self, f: Function) -> ControlFlow<()>;
6256}
6257
6258impl<F> MethodCandidateCallback for F
6259where
6260 F: FnMut(Function) -> ControlFlow<()>,
6261{
6262 fn on_inherent_method(&mut self, f: Function) -> ControlFlow<()> {
6263 self(f)
6264 }
6265
6266 fn on_trait_method(&mut self, f: Function) -> ControlFlow<()> {
6267 self(f)
6268 }
6269}
6270
6271pub trait PathCandidateCallback {
6272 fn on_inherent_item(&mut self, item: AssocItem) -> ControlFlow<()>;
6273
6274 fn on_trait_item(&mut self, item: AssocItem) -> ControlFlow<()>;
6275}
6276
6277impl<F> PathCandidateCallback for F
6278where
6279 F: FnMut(AssocItem) -> ControlFlow<()>,
6280{
6281 fn on_inherent_item(&mut self, item: AssocItem) -> ControlFlow<()> {
6282 self(item)
6283 }
6284
6285 fn on_trait_item(&mut self, item: AssocItem) -> ControlFlow<()> {
6286 self(item)
6287 }
6288}