hir/
lib.rs

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