1#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
21#![recursion_limit = "512"]
22
23extern crate ra_ap_rustc_type_ir as rustc_type_ir;
24
25mod attrs;
26mod from_id;
27mod has_source;
28mod semantics;
29mod source_analyzer;
30
31pub mod db;
32pub mod diagnostics;
33pub mod symbols;
34pub mod term_search;
35
36mod display;
37
38#[doc(hidden)]
39pub use hir_def::ModuleId;
40
41use std::{
42 borrow::Borrow,
43 fmt, iter,
44 mem::discriminant,
45 ops::{ControlFlow, Not},
46};
47
48use arrayvec::ArrayVec;
49use base_db::{CrateDisplayName, CrateOrigin, LangCrateOrigin, all_crates};
50use either::Either;
51use hir_def::{
52 AdtId, AssocItemId, AssocItemLoc, BuiltinDeriveImplId, CallableDefId, ConstId, ConstParamId,
53 DefWithBodyId, EnumId, EnumVariantId, ExpressionStoreOwnerId, ExternBlockId, ExternCrateId,
54 FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalFieldId,
55 Lookup, MacroExpander, MacroId, StaticId, StructId, SyntheticSyntax, TupleId, TypeAliasId,
56 TypeOrConstParamId, TypeParamId, UnionId,
57 attrs::AttrFlags,
58 builtin_derive::BuiltinDeriveImplMethod,
59 expr_store::{ExpressionStore, ExpressionStoreDiagnostics, ExpressionStoreSourceMap},
60 hir::{
61 BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat,
62 generics::{GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
63 },
64 item_tree::ImportAlias,
65 lang_item::LangItemTarget,
66 layout::{self, ReprOptions, TargetDataLayout},
67 nameres::{
68 assoc::TraitItems,
69 diagnostics::{DefDiagnostic, DefDiagnosticKind},
70 },
71 per_ns::PerNs,
72 resolver::{HasResolver, Resolver},
73 signatures::{
74 ConstSignature, EnumSignature, FunctionSignature, ImplFlags, ImplSignature, StaticFlags,
75 StaticSignature, StructFlags, StructSignature, TraitFlags, TraitSignature,
76 TypeAliasSignature, UnionSignature, VariantFields,
77 },
78 src::HasSource as _,
79 unstable_features::UnstableFeatures,
80 visibility::visibility_from_ast,
81};
82use hir_expand::{
83 AstId, MacroCallKind, RenderedExpandError, ValueResult, builtin::BuiltinDeriveExpander,
84 proc_macro::ProcMacroKind,
85};
86use hir_ty::{
87 GenericPredicates, InferBodyId, InferenceResult, ParamEnvAndCrate, TyDefId,
88 TyLoweringDiagnostic, ValueTyDefId, all_super_traits, autoderef, check_orphan_rules,
89 consteval::try_const_usize,
90 db::{AnonConstId, InternedClosure, InternedClosureId, InternedCoroutineClosureId},
91 diagnostics::BodyValidationDiagnostic,
92 direct_super_traits, known_const_to_ast,
93 layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
94 method_resolution::{self, InherentImpls, MethodResolutionContext},
95 mir::interpret_mir,
96 next_solver::{
97 AliasTy, AnyImplId, ClauseKind, DbInterner, EarlyBinder, ErrorGuaranteed, GenericArg,
98 GenericArgs, ParamEnv, PolyFnSig, Region, SolverDefId, Ty, TyKind, TypingMode,
99 infer::{DbInternerInferExt, InferCtxt},
100 },
101 traits::{self, is_inherent_impl_coherent, structurally_normalize_ty},
102};
103use itertools::Itertools;
104use rustc_hash::{FxHashMap, FxHashSet};
105use rustc_type_ir::{
106 AliasTyKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, fast_reject,
107 inherent::{AdtDef as _, GenericArgs as _, IntoKind, SliceLike, Term as _, Ty as _},
108};
109use span::{AstIdNode, Edition, FileId};
110use stdx::{format_to, impl_from, never};
111use syntax::{
112 AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr,
113 ast::{self, HasName as _, HasVisibility as _},
114 format_smolstr,
115};
116use triomphe::Arc;
117
118use crate::db::{DefDatabase, HirDatabase};
119
120pub use crate::{
121 attrs::{AttrsWithOwner, HasAttrs, resolve_doc_path_on},
122 diagnostics::*,
123 has_source::HasSource,
124 semantics::{
125 LintAttr, PathResolution, PathResolutionPerNs, Semantics, SemanticsImpl, SemanticsScope,
126 TypeInfo, VisibleTraits,
127 },
128};
129
130pub use {
140 cfg::{CfgAtom, CfgExpr, CfgOptions},
141 hir_def::{
142 Complete,
143 FindPathConfig,
144 attrs::{Docs, IsInnerDoc},
145 expr_store::Body,
146 find_path::PrefixKind,
147 import_map,
148 lang_item::{LangItemEnum as LangItem, crate_lang_items},
149 nameres::{DefMap, ModuleSource, crate_def_map},
150 per_ns::Namespace,
151 type_ref::{Mutability, TypeRef},
152 visibility::Visibility,
153 {GenericParamId, ModuleDefId, TraitId},
156 },
157 hir_expand::{
158 EditionedFileId, ExpandResult, HirFileId, MacroCallId, MacroKind,
159 change::ChangeWithProcMacros,
160 files::{
161 FilePosition, FilePositionWrapper, FileRange, FileRangeWrapper, HirFilePosition,
162 HirFileRange, InFile, InFileWrapper, InMacroFile, InRealFile, MacroFilePosition,
163 MacroFileRange,
164 },
165 inert_attr_macro::AttributeTemplate,
166 mod_path::{ModPath, PathKind, tool_path},
167 name::Name,
168 prettify_macro_expansion,
169 proc_macro::{ProcMacros, ProcMacrosBuilder},
170 tt,
171 },
172 hir_ty::mir,
174 hir_ty::{
175 CastError, PointerCast, attach_db, attach_db_allow_change,
176 consteval::ConstEvalError,
177 diagnostics::UnsafetyReason,
178 display::{ClosureStyle, DisplayTarget, HirDisplay, HirDisplayError, HirWrite},
179 drop::DropGlue,
180 dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode},
181 layout::LayoutError,
182 mir::{MirEvalError, MirLowerError},
183 next_solver::abi::Safety,
184 next_solver::{clear_tls_solver_cache, collect_ty_garbage},
185 setup_tracing,
186 },
187 hir_ty::{method_resolution::TraitImpls, next_solver::SimplifiedType},
189 intern::{Symbol, sym},
190};
191
192#[allow(unused)]
195use {
196 hir_def::expr_store::path::Path,
197 hir_expand::{
198 name::AsName,
199 span_map::{ExpansionSpanMap, RealSpanMap, SpanMap},
200 },
201 hir_ty::next_solver,
202};
203
204#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
208pub struct Crate {
209 pub(crate) id: base_db::Crate,
210}
211
212#[derive(Debug)]
213pub struct CrateDependency {
214 pub krate: Crate,
215 pub name: Name,
216}
217
218impl Crate {
219 pub fn base(self) -> base_db::Crate {
220 self.id
221 }
222
223 pub fn origin(self, db: &dyn HirDatabase) -> CrateOrigin {
224 self.id.data(db).origin.clone()
225 }
226
227 pub fn is_builtin(self, db: &dyn HirDatabase) -> bool {
228 matches!(self.origin(db), CrateOrigin::Lang(_))
229 }
230
231 pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
232 self.id
233 .data(db)
234 .dependencies
235 .iter()
236 .map(|dep| {
237 let krate = Crate { id: dep.crate_id };
238 let name = dep.as_name();
239 CrateDependency { krate, name }
240 })
241 .collect()
242 }
243
244 pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
245 let all_crates = all_crates(db);
246 all_crates
247 .iter()
248 .copied()
249 .filter(|&krate| krate.data(db).dependencies.iter().any(|it| it.crate_id == self.id))
250 .map(|id| Crate { id })
251 .collect()
252 }
253
254 pub fn transitive_reverse_dependencies(
255 self,
256 db: &dyn HirDatabase,
257 ) -> impl Iterator<Item = Crate> {
258 self.id.transitive_rev_deps(db).into_iter().map(|id| Crate { id })
259 }
260
261 pub fn notable_traits_in_deps(self, db: &dyn HirDatabase) -> impl Iterator<Item = &TraitId> {
262 self.id
263 .transitive_deps(db)
264 .into_iter()
265 .filter_map(|krate| db.crate_notable_traits(krate))
266 .flatten()
267 }
268
269 pub fn root_module(self, db: &dyn HirDatabase) -> Module {
270 Module { id: crate_def_map(db, self.id).root_module_id() }
271 }
272
273 pub fn modules(self, db: &dyn HirDatabase) -> Vec<Module> {
274 let def_map = crate_def_map(db, self.id);
275 def_map.modules().map(|(id, _)| id.into()).collect()
276 }
277
278 pub fn root_file(self, db: &dyn HirDatabase) -> FileId {
279 self.id.data(db).root_file_id
280 }
281
282 pub fn edition(self, db: &dyn HirDatabase) -> Edition {
283 self.id.data(db).edition
284 }
285
286 pub fn version(self, db: &dyn HirDatabase) -> Option<String> {
287 self.id.extra_data(db).version.clone()
288 }
289
290 pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateDisplayName> {
291 self.id.extra_data(db).display_name.clone()
292 }
293
294 pub fn query_external_importables(
295 self,
296 db: &dyn DefDatabase,
297 query: import_map::Query,
298 ) -> impl Iterator<Item = (Either<ModuleDef, Macro>, Complete)> {
299 let _p = tracing::info_span!("query_external_importables").entered();
300 import_map::search_dependencies(db, self.into(), &query).into_iter().map(
301 |(item, do_not_complete)| {
302 let item = match ItemInNs::from(item) {
303 ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id),
304 ItemInNs::Macros(mac_id) => Either::Right(mac_id),
305 };
306 (item, do_not_complete)
307 },
308 )
309 }
310
311 pub fn all(db: &dyn HirDatabase) -> Vec<Crate> {
312 all_crates(db).iter().map(|&id| Crate { id }).collect()
313 }
314
315 pub fn get_html_root_url(self, db: &dyn HirDatabase) -> Option<String> {
317 let doc_url = AttrFlags::doc_html_root_url(db, self.id);
319 doc_url.as_ref().map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
320 }
321
322 pub fn cfg<'db>(&self, db: &'db dyn HirDatabase) -> &'db CfgOptions {
323 self.id.cfg_options(db)
324 }
325
326 pub fn potential_cfg<'db>(&self, db: &'db dyn HirDatabase) -> &'db CfgOptions {
327 let data = self.id.extra_data(db);
328 data.potential_cfg_options.as_ref().unwrap_or_else(|| self.id.cfg_options(db))
329 }
330
331 pub fn to_display_target(self, db: &dyn HirDatabase) -> DisplayTarget {
332 DisplayTarget::from_crate(db, self.id)
333 }
334
335 fn core(db: &dyn HirDatabase) -> Option<Crate> {
336 all_crates(db)
337 .iter()
338 .copied()
339 .find(|&krate| {
340 matches!(krate.data(db).origin, CrateOrigin::Lang(LangCrateOrigin::Core))
341 })
342 .map(Crate::from)
343 }
344
345 pub fn is_unstable_feature_enabled(self, db: &dyn HirDatabase, feature: &Symbol) -> bool {
346 UnstableFeatures::query(db, self.id).is_enabled(feature)
347 }
348}
349
350#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
351pub struct Module {
352 pub(crate) id: ModuleId,
353}
354
355#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
357pub enum ModuleDef {
358 Module(Module),
359 Function(Function),
360 Adt(Adt),
361 EnumVariant(EnumVariant),
363 Const(Const),
364 Static(Static),
365 Trait(Trait),
366 TypeAlias(TypeAlias),
367 BuiltinType(BuiltinType),
368 Macro(Macro),
369}
370impl_from!(
371 Module,
372 Function,
373 Adt(Struct, Enum, Union),
374 EnumVariant,
375 Const,
376 Static,
377 Trait,
378 TypeAlias,
379 BuiltinType,
380 Macro
381 for ModuleDef
382);
383
384impl From<Variant> for ModuleDef {
385 fn from(var: Variant) -> Self {
386 match var {
387 Variant::Struct(t) => Adt::from(t).into(),
388 Variant::Union(t) => Adt::from(t).into(),
389 Variant::EnumVariant(t) => t.into(),
390 }
391 }
392}
393
394impl ModuleDef {
395 pub fn module(self, db: &dyn HirDatabase) -> Option<Module> {
396 match self {
397 ModuleDef::Module(it) => it.parent(db),
398 ModuleDef::Function(it) => Some(it.module(db)),
399 ModuleDef::Adt(it) => Some(it.module(db)),
400 ModuleDef::EnumVariant(it) => Some(it.module(db)),
401 ModuleDef::Const(it) => Some(it.module(db)),
402 ModuleDef::Static(it) => Some(it.module(db)),
403 ModuleDef::Trait(it) => Some(it.module(db)),
404 ModuleDef::TypeAlias(it) => Some(it.module(db)),
405 ModuleDef::Macro(it) => Some(it.module(db)),
406 ModuleDef::BuiltinType(_) => None,
407 }
408 }
409
410 pub fn canonical_path(&self, db: &dyn HirDatabase, edition: Edition) -> Option<String> {
411 let mut segments = vec![self.name(db)?];
412 for m in self.module(db)?.path_to_root(db) {
413 segments.extend(m.name(db))
414 }
415 segments.reverse();
416 Some(segments.iter().map(|it| it.display(db, edition)).join("::"))
417 }
418
419 pub fn canonical_module_path(
420 &self,
421 db: &dyn HirDatabase,
422 ) -> Option<impl Iterator<Item = Module>> {
423 self.module(db).map(|it| it.path_to_root(db).into_iter().rev())
424 }
425
426 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
427 let name = match self {
428 ModuleDef::Module(it) => it.name(db)?,
429 ModuleDef::Const(it) => it.name(db)?,
430 ModuleDef::Adt(it) => it.name(db),
431 ModuleDef::Trait(it) => it.name(db),
432 ModuleDef::Function(it) => it.name(db),
433 ModuleDef::EnumVariant(it) => it.name(db),
434 ModuleDef::TypeAlias(it) => it.name(db),
435 ModuleDef::Static(it) => it.name(db),
436 ModuleDef::Macro(it) => it.name(db),
437 ModuleDef::BuiltinType(it) => it.name(),
438 };
439 Some(name)
440 }
441
442 pub fn diagnostics<'db>(
443 self,
444 db: &'db dyn HirDatabase,
445 style_lints: bool,
446 ) -> Vec<AnyDiagnostic<'db>> {
447 let id = match self {
448 ModuleDef::Adt(it) => match it {
449 Adt::Struct(it) => it.id.into(),
450 Adt::Enum(it) => it.id.into(),
451 Adt::Union(it) => it.id.into(),
452 },
453 ModuleDef::Trait(it) => it.id.into(),
454 ModuleDef::Function(it) => match it.id {
455 AnyFunctionId::FunctionId(it) => it.into(),
456 AnyFunctionId::BuiltinDeriveImplMethod { .. } => return Vec::new(),
457 },
458 ModuleDef::TypeAlias(it) => it.id.into(),
459 ModuleDef::Module(it) => it.id.into(),
460 ModuleDef::Const(it) => it.id.into(),
461 ModuleDef::Static(it) => it.id.into(),
462 ModuleDef::EnumVariant(it) => it.id.into(),
463 ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(),
464 };
465
466 let mut acc = Vec::new();
467
468 match self.as_def_with_body() {
469 Some(def) => {
470 def.diagnostics(db, &mut acc, style_lints);
471 }
472 None => {
473 for diag in hir_ty::diagnostics::incorrect_case(db, id) {
474 acc.push(diag.into())
475 }
476 }
477 }
478
479 if let Some(def) = self.as_self_generic_def() {
480 def.diagnostics(db, &mut acc);
481 }
482
483 acc
484 }
485
486 pub fn as_def_with_body(self) -> Option<DefWithBody> {
487 match self {
488 ModuleDef::Function(it) => Some(it.into()),
489 ModuleDef::Const(it) => Some(it.into()),
490 ModuleDef::Static(it) => Some(it.into()),
491 ModuleDef::EnumVariant(it) => Some(it.into()),
492
493 ModuleDef::Module(_)
494 | ModuleDef::Adt(_)
495 | ModuleDef::Trait(_)
496 | ModuleDef::TypeAlias(_)
497 | ModuleDef::Macro(_)
498 | ModuleDef::BuiltinType(_) => None,
499 }
500 }
501
502 pub fn as_self_generic_def(self) -> Option<GenericDef> {
504 match self {
505 ModuleDef::Function(it) => Some(it.into()),
506 ModuleDef::Adt(it) => Some(it.into()),
507 ModuleDef::Trait(it) => Some(it.into()),
508 ModuleDef::TypeAlias(it) => Some(it.into()),
509 ModuleDef::Module(_)
510 | ModuleDef::EnumVariant(_)
511 | ModuleDef::Static(_)
512 | ModuleDef::Const(_)
513 | ModuleDef::BuiltinType(_)
514 | ModuleDef::Macro(_) => None,
515 }
516 }
517
518 pub fn as_generic_def(self) -> Option<GenericDef> {
519 match self {
520 ModuleDef::Function(it) => Some(it.into()),
521 ModuleDef::Adt(it) => Some(it.into()),
522 ModuleDef::Trait(it) => Some(it.into()),
523 ModuleDef::TypeAlias(it) => Some(it.into()),
524 ModuleDef::Static(it) => Some(it.into()),
525 ModuleDef::Const(it) => Some(it.into()),
526 ModuleDef::EnumVariant(_)
527 | ModuleDef::Module(_)
528 | ModuleDef::BuiltinType(_)
529 | ModuleDef::Macro(_) => None,
530 }
531 }
532
533 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
534 Some(match self {
535 ModuleDef::Module(it) => it.attrs(db),
536 ModuleDef::Function(it) => HasAttrs::attrs(*it, db),
537 ModuleDef::Adt(it) => it.attrs(db),
538 ModuleDef::EnumVariant(it) => it.attrs(db),
539 ModuleDef::Const(it) => it.attrs(db),
540 ModuleDef::Static(it) => it.attrs(db),
541 ModuleDef::Trait(it) => it.attrs(db),
542 ModuleDef::TypeAlias(it) => it.attrs(db),
543 ModuleDef::Macro(it) => it.attrs(db),
544 ModuleDef::BuiltinType(_) => return None,
545 })
546 }
547}
548
549impl HasCrate for ModuleDef {
550 fn krate(&self, db: &dyn HirDatabase) -> Crate {
551 match self.module(db) {
552 Some(module) => module.krate(db),
553 None => Crate::core(db).unwrap_or_else(|| all_crates(db)[0].into()),
554 }
555 }
556}
557
558impl HasAttrs for ModuleDef {
559 fn attr_id(self, db: &dyn HirDatabase) -> attrs::AttrsOwner {
560 match self {
561 ModuleDef::Module(it) => it.attr_id(db),
562 ModuleDef::Function(it) => it.attr_id(db),
563 ModuleDef::Adt(it) => it.attr_id(db),
564 ModuleDef::EnumVariant(it) => it.attr_id(db),
565 ModuleDef::Const(it) => it.attr_id(db),
566 ModuleDef::Static(it) => it.attr_id(db),
567 ModuleDef::Trait(it) => it.attr_id(db),
568 ModuleDef::TypeAlias(it) => it.attr_id(db),
569 ModuleDef::Macro(it) => it.attr_id(db),
570 ModuleDef::BuiltinType(_) => attrs::AttrsOwner::Dummy,
571 }
572 }
573}
574
575impl HasVisibility for ModuleDef {
576 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
577 match *self {
578 ModuleDef::Module(it) => it.visibility(db),
579 ModuleDef::Function(it) => it.visibility(db),
580 ModuleDef::Adt(it) => it.visibility(db),
581 ModuleDef::Const(it) => it.visibility(db),
582 ModuleDef::Static(it) => it.visibility(db),
583 ModuleDef::Trait(it) => it.visibility(db),
584 ModuleDef::TypeAlias(it) => it.visibility(db),
585 ModuleDef::EnumVariant(it) => it.visibility(db),
586 ModuleDef::Macro(it) => it.visibility(db),
587 ModuleDef::BuiltinType(_) => Visibility::Public,
588 }
589 }
590}
591
592impl Module {
593 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
595 self.id.name(db)
596 }
597
598 pub fn krate(self, db: &dyn HirDatabase) -> Crate {
600 Crate { id: self.id.krate(db) }
601 }
602
603 pub fn crate_root(self, db: &dyn HirDatabase) -> Module {
607 let def_map = crate_def_map(db, self.id.krate(db));
608 Module { id: def_map.crate_root(db) }
609 }
610
611 pub fn is_crate_root(self, db: &dyn HirDatabase) -> bool {
612 self.crate_root(db) == self
613 }
614
615 pub fn children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module> {
617 let def_map = self.id.def_map(db);
618 let children = def_map[self.id]
619 .children
620 .values()
621 .map(|module_id| Module { id: *module_id })
622 .collect::<Vec<_>>();
623 children.into_iter()
624 }
625
626 pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> {
628 let def_map = self.id.def_map(db);
629 let parent_id = def_map.containing_module(self.id)?;
630 Some(Module { id: parent_id })
631 }
632
633 pub fn nearest_non_block_module(self, db: &dyn HirDatabase) -> Module {
635 let mut id = self.id;
636 while id.is_block_module(db) {
637 id = id.containing_module(db).expect("block without parent module");
638 }
639 Module { id }
640 }
641
642 pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> {
643 let mut res = vec![self];
644 let mut curr = self;
645 while let Some(next) = curr.parent(db) {
646 res.push(next);
647 curr = next
648 }
649 res
650 }
651
652 pub fn modules_in_scope(&self, db: &dyn HirDatabase, pub_only: bool) -> Vec<(Name, Module)> {
653 let def_map = self.id.def_map(db);
654 let scope = &def_map[self.id].scope;
655
656 let mut res = Vec::new();
657
658 for (name, item) in scope.types() {
659 if let ModuleDefId::ModuleId(m) = item.def
660 && (!pub_only || item.vis == Visibility::Public)
661 {
662 res.push((name.clone(), Module { id: m }));
663 }
664 }
665
666 res
667 }
668
669 pub fn scope(
671 self,
672 db: &dyn HirDatabase,
673 visible_from: Option<Module>,
674 ) -> Vec<(Name, ScopeDef)> {
675 self.id.def_map(db)[self.id]
676 .scope
677 .entries()
678 .filter_map(|(name, def)| {
679 if let Some(m) = visible_from {
680 let filtered = def.filter_visibility(|vis| vis.is_visible_from(db, m.id));
681 if filtered.is_none() && !def.is_none() { None } else { Some((name, filtered)) }
682 } else {
683 Some((name, def))
684 }
685 })
686 .flat_map(|(name, def)| {
687 ScopeDef::all_items(def).into_iter().map(move |item| (name.clone(), item))
688 })
689 .collect()
690 }
691
692 pub fn resolve_mod_path(
693 &self,
694 db: &dyn HirDatabase,
695 segments: impl IntoIterator<Item = Name>,
696 ) -> Option<impl Iterator<Item = ItemInNs>> {
697 let items = self
698 .id
699 .resolver(db)
700 .resolve_module_path_in_items(db, &ModPath::from_segments(PathKind::Plain, segments));
701 Some(items.iter_items().map(|(item, _)| item.into()))
702 }
703
704 pub fn diagnostics<'db>(
706 self,
707 db: &'db dyn HirDatabase,
708 acc: &mut Vec<AnyDiagnostic<'db>>,
709 style_lints: bool,
710 ) {
711 let _p = tracing::info_span!("diagnostics", name = ?self.name(db)).entered();
712 let edition = self.id.krate(db).data(db).edition;
713 let def_map = self.id.def_map(db);
714 for diag in def_map.diagnostics() {
715 if diag.in_module != self.id {
716 continue;
718 }
719 emit_def_diagnostic(db, acc, diag, edition, def_map.krate());
720 }
721
722 if !self.id.is_block_module(db) {
723 let scope = &def_map[self.id].scope;
725 scope.all_macro_calls().for_each(|it| macro_call_diagnostics(db, it, acc));
726 }
727
728 for def in self.declarations(db) {
729 match def {
730 ModuleDef::Module(m) => {
731 if def_map[m.id].origin.is_inline() {
733 m.diagnostics(db, acc, style_lints)
734 }
735 acc.extend(def.diagnostics(db, style_lints))
736 }
737 ModuleDef::Trait(t) => {
738 let krate = t.krate(db);
739 for diag in TraitItems::query_with_diagnostics(db, t.id).1.iter() {
740 emit_def_diagnostic(db, acc, diag, edition, krate.id);
741 }
742
743 for item in t.items(db) {
744 item.diagnostics(db, acc, style_lints);
745 }
746
747 t.all_macro_calls(db)
748 .iter()
749 .for_each(|&(_ast, call_id)| macro_call_diagnostics(db, call_id, acc));
750
751 acc.extend(def.diagnostics(db, style_lints))
752 }
753 ModuleDef::Adt(adt) => {
754 match adt {
755 Adt::Struct(s) => {
756 let source_map = &StructSignature::with_source_map(db, s.id).1;
757 expr_store_diagnostics(db, acc, source_map);
758 let source_map = &s.id.fields_with_source_map(db).1;
759 expr_store_diagnostics(db, acc, source_map);
760 push_ty_diagnostics(
761 db,
762 acc,
763 db.field_types_with_diagnostics(s.id.into()).diagnostics(),
764 source_map,
765 );
766 }
767 Adt::Union(u) => {
768 let source_map = &UnionSignature::with_source_map(db, u.id).1;
769 expr_store_diagnostics(db, acc, source_map);
770 let source_map = &u.id.fields_with_source_map(db).1;
771 expr_store_diagnostics(db, acc, source_map);
772 push_ty_diagnostics(
773 db,
774 acc,
775 db.field_types_with_diagnostics(u.id.into()).diagnostics(),
776 source_map,
777 );
778 }
779 Adt::Enum(e) => {
780 let source_map = &EnumSignature::with_source_map(db, e.id).1;
781 expr_store_diagnostics(db, acc, source_map);
782 let (variants, diagnostics) = e.id.enum_variants_with_diagnostics(db);
783 let file = e.id.lookup(db).id.file_id;
784 let ast_id_map = db.ast_id_map(file);
785 for diag in diagnostics {
786 acc.push(
787 InactiveCode {
788 node: InFile::new(
789 file,
790 ast_id_map.get(diag.ast_id).syntax_node_ptr(),
791 ),
792 cfg: diag.cfg.clone(),
793 opts: diag.opts.clone(),
794 }
795 .into(),
796 );
797 }
798 for &(v, _) in variants.variants.values() {
799 let source_map = &v.fields_with_source_map(db).1;
800 push_ty_diagnostics(
801 db,
802 acc,
803 db.field_types_with_diagnostics(v.into()).diagnostics(),
804 source_map,
805 );
806 expr_store_diagnostics(db, acc, source_map);
807 }
808 }
809 }
810 acc.extend(def.diagnostics(db, style_lints))
811 }
812 ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m),
813 ModuleDef::TypeAlias(type_alias) => {
814 let source_map = &TypeAliasSignature::with_source_map(db, type_alias.id).1;
815 expr_store_diagnostics(db, acc, source_map);
816 push_ty_diagnostics(
817 db,
818 acc,
819 db.type_for_type_alias_with_diagnostics(type_alias.id).diagnostics(),
820 source_map,
821 );
822 acc.extend(def.diagnostics(db, style_lints));
823 }
824 _ => acc.extend(def.diagnostics(db, style_lints)),
825 }
826 }
827 self.legacy_macros(db).into_iter().for_each(|m| emit_macro_def_diagnostics(db, acc, m));
828
829 let interner = DbInterner::new_with(db, self.id.krate(db));
830 let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
831
832 let mut impl_assoc_items_scratch = vec![];
833 for impl_def in self.impl_defs(db) {
834 GenericDef::Impl(impl_def).diagnostics(db, acc);
835
836 let AnyImplId::ImplId(impl_id) = impl_def.id else {
837 continue;
838 };
839 let loc = impl_id.lookup(db);
840 let (impl_signature, source_map) = ImplSignature::with_source_map(db, impl_id);
841 expr_store_diagnostics(db, acc, source_map);
842
843 let file_id = loc.id.file_id;
844 if file_id.macro_file().is_some_and(|it| it.kind(db) == MacroKind::DeriveBuiltIn) {
845 continue;
848 }
849 impl_def
850 .all_macro_calls(db)
851 .iter()
852 .for_each(|&(_ast, call_id)| macro_call_diagnostics(db, call_id, acc));
853
854 let ast_id_map = db.ast_id_map(file_id);
855
856 for diag in impl_id.impl_items_with_diagnostics(db).1.iter() {
857 emit_def_diagnostic(db, acc, diag, edition, loc.container.krate(db));
858 }
859
860 let trait_impl = impl_signature.target_trait.is_some();
861 if !trait_impl && !is_inherent_impl_coherent(db, def_map, impl_id) {
862 acc.push(IncoherentImpl { impl_: ast_id_map.get(loc.id.value), file_id }.into())
863 }
864
865 if trait_impl && !impl_def.check_orphan_rules(db) {
866 acc.push(TraitImplOrphan { impl_: ast_id_map.get(loc.id.value), file_id }.into())
867 }
868
869 let trait_ = trait_impl.then(|| impl_def.trait_(db)).flatten();
870 let mut trait_is_unsafe = trait_.is_some_and(|t| t.is_unsafe(db));
871 let impl_is_negative = impl_def.is_negative(db);
872 let impl_is_unsafe = impl_def.is_unsafe(db);
873
874 let trait_is_unresolved = trait_.is_none() && trait_impl;
875 if trait_is_unresolved {
876 trait_is_unsafe = impl_is_unsafe;
879 }
880
881 let drop_maybe_dangle = (|| {
882 let trait_ = trait_?;
883 let drop_trait = interner.lang_items().Drop?;
884 if drop_trait != trait_.into() {
885 return None;
886 }
887 let parent = impl_id.into();
888 let (lifetimes_attrs, type_and_consts_attrs) =
889 AttrFlags::query_generic_params(db, parent);
890 let res = lifetimes_attrs.values().any(|it| it.contains(AttrFlags::MAY_DANGLE))
891 || type_and_consts_attrs.values().any(|it| it.contains(AttrFlags::MAY_DANGLE));
892 Some(res)
893 })()
894 .unwrap_or(false);
895
896 match (impl_is_unsafe, trait_is_unsafe, impl_is_negative, drop_maybe_dangle) {
897 (true, _, true, _) |
899 (true, false, _, false) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(loc.id.value), file_id, should_be_safe: true }.into()),
901 (false, true, false, _) |
903 (false, false, _, true) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(loc.id.value), file_id, should_be_safe: false }.into()),
905 _ => (),
906 };
907
908 if let (false, Some(trait_)) = (impl_is_negative, trait_) {
910 let items = &trait_.id.trait_items(db).items;
911 let required_items = items.iter().filter(|&(_, assoc)| match *assoc {
912 AssocItemId::FunctionId(it) => !FunctionSignature::of(db, it).has_body(),
913 AssocItemId::ConstId(id) => !ConstSignature::of(db, id).has_body(),
914 AssocItemId::TypeAliasId(it) => TypeAliasSignature::of(db, it).ty.is_none(),
915 });
916 impl_assoc_items_scratch.extend(impl_id.impl_items(db).items.iter().cloned());
917
918 let redundant = impl_assoc_items_scratch
919 .iter()
920 .filter(|(name, id)| {
921 !items.iter().any(|(impl_name, impl_item)| {
922 discriminant(impl_item) == discriminant(id) && impl_name == name
923 })
924 })
925 .map(|(name, item)| (name.clone(), AssocItem::from(*item)));
926 for (name, assoc_item) in redundant {
927 acc.push(
928 TraitImplRedundantAssocItems {
929 trait_,
930 file_id,
931 impl_: ast_id_map.get(loc.id.value),
932 assoc_item: (name, assoc_item),
933 }
934 .into(),
935 )
936 }
937
938 let mut missing: Vec<_> = required_items
939 .filter(|(name, id)| {
940 !impl_assoc_items_scratch.iter().any(|(impl_name, impl_item)| {
941 discriminant(impl_item) == discriminant(id) && impl_name == name
942 })
943 })
944 .map(|(name, item)| (name.clone(), AssocItem::from(*item)))
945 .collect();
946
947 if !missing.is_empty() {
948 let env = ParamEnvAndCrate {
949 param_env: db.trait_environment(GenericDefId::from(impl_id)),
950 krate: self.id.krate(db),
951 };
952 let self_ty = db.impl_self_ty(impl_id).instantiate_identity().skip_norm_wip();
953 let self_ty = structurally_normalize_ty(&infcx, self_ty, env.param_env);
954 let tail_ty = struct_tail_raw(db, interner, self_ty, |ty| {
955 structurally_normalize_ty(&infcx, ty, env.param_env)
956 });
957 let self_ty_is_guaranteed_unsized = matches!(
958 tail_ty.kind(),
959 TyKind::Dynamic(..) | TyKind::Slice(..) | TyKind::Str
960 );
961 if self_ty_is_guaranteed_unsized {
962 missing.retain(|(_, assoc_item)| {
963 let assoc_item = match *assoc_item {
964 AssocItem::Function(it) => match it.id {
965 AnyFunctionId::FunctionId(id) => id.into(),
966 AnyFunctionId::BuiltinDeriveImplMethod { .. } => {
967 never!("should not have an `AnyFunctionId::BuiltinDeriveImplMethod` here");
968 return false;
969 },
970 },
971 AssocItem::Const(it) => it.id.into(),
972 AssocItem::TypeAlias(it) => it.id.into(),
973 };
974 !hir_ty::dyn_compatibility::generics_require_sized_self(db, assoc_item)
975 });
976 }
977 }
978
979 if !missing.is_empty() {
986 let krate = self.krate(db).id;
987 let features = UnstableFeatures::query(db, krate);
988 if features.specialization || features.min_specialization {
989 missing.retain(|(assoc_name, assoc_item)| {
990 let AssocItem::Function(_) = assoc_item else {
991 return true;
992 };
993
994 for &impl_ in TraitImpls::for_crate(db, krate).blanket_impls(trait_.id)
995 {
996 if impl_ == impl_id {
997 continue;
998 }
999
1000 for (name, item) in &impl_.impl_items(db).items {
1001 let AssocItemId::FunctionId(fn_) = item else {
1002 continue;
1003 };
1004 if name != assoc_name {
1005 continue;
1006 }
1007
1008 if FunctionSignature::of(db, *fn_).is_default() {
1009 return false;
1010 }
1011 }
1012 }
1013
1014 true
1015 });
1016 }
1017 }
1018
1019 if !missing.is_empty() {
1020 acc.push(
1021 TraitImplMissingAssocItems {
1022 impl_: ast_id_map.get(loc.id.value),
1023 file_id,
1024 missing,
1025 }
1026 .into(),
1027 )
1028 }
1029 impl_assoc_items_scratch.clear();
1030 }
1031
1032 push_ty_diagnostics(
1033 db,
1034 acc,
1035 db.impl_self_ty_with_diagnostics(impl_id).diagnostics(),
1036 source_map,
1037 );
1038 push_ty_diagnostics(
1039 db,
1040 acc,
1041 db.impl_trait_with_diagnostics(impl_id)
1042 .as_ref()
1043 .map(|it| it.diagnostics())
1044 .unwrap_or_default(),
1045 source_map,
1046 );
1047
1048 for &(_, item) in impl_id.impl_items(db).items.iter() {
1049 AssocItem::from(item).diagnostics(db, acc, style_lints);
1050 }
1051 }
1052 }
1053
1054 pub fn declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef> {
1055 let def_map = self.id.def_map(db);
1056 let scope = &def_map[self.id].scope;
1057 scope
1058 .declarations()
1059 .map(ModuleDef::from)
1060 .chain(scope.unnamed_consts().map(|id| ModuleDef::Const(Const::from(id))))
1061 .collect()
1062 }
1063
1064 pub fn legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro> {
1065 let def_map = self.id.def_map(db);
1066 let scope = &def_map[self.id].scope;
1067 scope.legacy_macros().flat_map(|(_, it)| it).map(|&it| it.into()).collect()
1068 }
1069
1070 pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {
1071 let def_map = self.id.def_map(db);
1072 let scope = &def_map[self.id].scope;
1073 scope.impls().map(Impl::from).chain(scope.builtin_derive_impls().map(Impl::from)).collect()
1074 }
1075
1076 pub fn find_path(
1079 self,
1080 db: &dyn DefDatabase,
1081 item: impl Into<ItemInNs>,
1082 cfg: FindPathConfig,
1083 ) -> Option<ModPath> {
1084 hir_def::find_path::find_path(
1085 db,
1086 item.into().try_into().ok()?,
1087 self.into(),
1088 PrefixKind::Plain,
1089 false,
1090 cfg,
1091 )
1092 }
1093
1094 pub fn find_use_path(
1097 self,
1098 db: &dyn DefDatabase,
1099 item: impl Into<ItemInNs>,
1100 prefix_kind: PrefixKind,
1101 cfg: FindPathConfig,
1102 ) -> Option<ModPath> {
1103 hir_def::find_path::find_path(
1104 db,
1105 item.into().try_into().ok()?,
1106 self.into(),
1107 prefix_kind,
1108 true,
1109 cfg,
1110 )
1111 }
1112
1113 #[inline]
1114 pub fn doc_keyword(self, db: &dyn HirDatabase) -> Option<Symbol> {
1115 AttrFlags::doc_keyword(db, self.id)
1116 }
1117
1118 #[inline]
1120 pub fn has_path(&self, db: &dyn HirDatabase) -> bool {
1121 self.attrs(db).attrs.contains(AttrFlags::HAS_PATH)
1122 }
1123}
1124
1125fn macro_call_diagnostics<'db>(
1126 db: &'db dyn HirDatabase,
1127 macro_call_id: MacroCallId,
1128 acc: &mut Vec<AnyDiagnostic<'db>>,
1129) {
1130 let Some(e) = db.parse_macro_expansion_error(macro_call_id) else {
1131 return;
1132 };
1133 let ValueResult { value: parse_errors, err } = e;
1134 if let Some(err) = err {
1135 let loc = macro_call_id.loc(db);
1136 let file_id = loc.kind.file_id();
1137 let mut range = precise_macro_call_location(&loc.kind, db, loc.krate);
1138 let RenderedExpandError { message, error, kind } = err.render_to_string(db);
1139 if Some(err.span().anchor.file_id) == file_id.file_id().map(|it| it.span_file_id(db)) {
1140 range.value = err.span().range
1141 + db.ast_id_map(file_id).get_erased(err.span().anchor.ast_id).text_range().start();
1142 }
1143 acc.push(MacroError { range, message, error, kind }.into());
1144 }
1145
1146 if !parse_errors.is_empty() {
1147 let loc = macro_call_id.loc(db);
1148 let range = precise_macro_call_location(&loc.kind, db, loc.krate);
1149 acc.push(MacroExpansionParseError { range, errors: parse_errors.clone() }.into())
1150 }
1151}
1152
1153fn emit_macro_def_diagnostics<'db>(
1154 db: &'db dyn HirDatabase,
1155 acc: &mut Vec<AnyDiagnostic<'db>>,
1156 m: Macro,
1157) {
1158 let id = db.macro_def(m.id);
1159 if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_expander(id)
1160 && let Some(e) = expander.mac.err()
1161 {
1162 let Some(ast) = id.ast_id().left() else {
1163 never!("declarative expander for non decl-macro: {:?}", e);
1164 return;
1165 };
1166 let krate = HasModule::krate(&m.id, db);
1167 let edition = krate.data(db).edition;
1168 emit_def_diagnostic_(
1169 db,
1170 acc,
1171 &DefDiagnosticKind::MacroDefError { ast, message: e.to_string() },
1172 edition,
1173 m.krate(db).id,
1174 );
1175 }
1176}
1177
1178fn emit_def_diagnostic<'db>(
1179 db: &'db dyn HirDatabase,
1180 acc: &mut Vec<AnyDiagnostic<'db>>,
1181 diag: &DefDiagnostic,
1182 edition: Edition,
1183 krate: base_db::Crate,
1184) {
1185 emit_def_diagnostic_(db, acc, &diag.kind, edition, krate)
1186}
1187
1188fn emit_def_diagnostic_<'db>(
1189 db: &'db dyn HirDatabase,
1190 acc: &mut Vec<AnyDiagnostic<'db>>,
1191 diag: &DefDiagnosticKind,
1192 edition: Edition,
1193 krate: base_db::Crate,
1194) {
1195 match diag {
1196 DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates } => {
1197 let decl = declaration.to_ptr(db);
1198 acc.push(
1199 UnresolvedModule {
1200 decl: InFile::new(declaration.file_id, decl),
1201 candidates: candidates.clone(),
1202 }
1203 .into(),
1204 )
1205 }
1206 DefDiagnosticKind::UnresolvedExternCrate { ast } => {
1207 let item = ast.to_ptr(db);
1208 acc.push(UnresolvedExternCrate { decl: InFile::new(ast.file_id, item) }.into());
1209 }
1210
1211 DefDiagnosticKind::MacroError { ast, path, err } => {
1212 let item = ast.to_ptr(db);
1213 let RenderedExpandError { message, error, kind } = err.render_to_string(db);
1214 acc.push(
1215 MacroError {
1216 range: InFile::new(ast.file_id, item.text_range()),
1217 message: format!("{}: {message}", path.display(db, edition)),
1218 error,
1219 kind,
1220 }
1221 .into(),
1222 )
1223 }
1224 DefDiagnosticKind::UnresolvedImport { id, index } => {
1225 let file_id = id.file_id;
1226
1227 let use_tree = hir_def::src::use_tree_to_ast(db, *id, *index);
1228 acc.push(
1229 UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) }.into(),
1230 );
1231 }
1232
1233 DefDiagnosticKind::UnconfiguredCode { ast_id, cfg, opts } => {
1234 let ast_id_map = db.ast_id_map(ast_id.file_id);
1235 let ptr = ast_id_map.get_erased(ast_id.value);
1236 acc.push(
1237 InactiveCode {
1238 node: InFile::new(ast_id.file_id, ptr),
1239 cfg: cfg.clone(),
1240 opts: opts.clone(),
1241 }
1242 .into(),
1243 );
1244 }
1245 DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
1246 let location = precise_macro_call_location(ast, db, krate);
1247 acc.push(
1248 UnresolvedMacroCall {
1249 range: location,
1250 path: path.clone(),
1251 is_bang: matches!(ast, MacroCallKind::FnLike { .. }),
1252 }
1253 .into(),
1254 );
1255 }
1256 DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
1257 let node = ast.to_node(db);
1258 let name = node.name().expect("unimplemented builtin macro with no name");
1260 acc.push(
1261 UnimplementedBuiltinMacro {
1262 node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&name))),
1263 }
1264 .into(),
1265 );
1266 }
1267 DefDiagnosticKind::InvalidDeriveTarget { ast, id } => {
1268 let (_, attr) = id.find_attr_range(db, krate, *ast);
1269 let derive = attr
1270 .path()
1271 .map(|path| path.syntax().text_range())
1272 .unwrap_or_else(|| attr.syntax().text_range());
1273 acc.push(InvalidDeriveTarget { range: ast.with_value(derive) }.into());
1274 }
1275 DefDiagnosticKind::MalformedDerive { ast, id } => {
1276 let derive = id.find_attr_range(db, krate, *ast).1.syntax().text_range();
1277 acc.push(MalformedDerive { range: ast.with_value(derive) }.into());
1278 }
1279 DefDiagnosticKind::MacroDefError { ast, message } => {
1280 let node = ast.to_node(db);
1281 acc.push(
1282 MacroDefError {
1283 node: InFile::new(ast.file_id, AstPtr::new(&node)),
1284 name: node.name().map(|it| it.syntax().text_range()),
1285 message: message.clone(),
1286 }
1287 .into(),
1288 );
1289 }
1290 }
1291}
1292
1293fn precise_macro_call_location(
1294 ast: &MacroCallKind,
1295 db: &dyn HirDatabase,
1296 krate: base_db::Crate,
1297) -> InFile<TextRange> {
1298 match ast {
1301 MacroCallKind::FnLike { ast_id, .. } => {
1302 let node = ast_id.to_node(db);
1303 let range = node
1304 .path()
1305 .and_then(|it| it.segment())
1306 .and_then(|it| it.name_ref())
1307 .map(|it| it.syntax().text_range());
1308 let range = range.unwrap_or_else(|| node.syntax().text_range());
1309 ast_id.with_value(range)
1310 }
1311 MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
1312 let range = derive_attr_index.find_derive_range(db, krate, *ast_id, *derive_index);
1313 ast_id.with_value(range)
1314 }
1315 MacroCallKind::Attr { ast_id, censored_attr_ids: attr_ids, .. } => {
1316 let attr_range =
1317 attr_ids.invoc_attr().find_attr_range(db, krate, *ast_id).1.syntax().text_range();
1318 ast_id.with_value(attr_range)
1319 }
1320 }
1321}
1322
1323impl HasVisibility for Module {
1324 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1325 let def_map = self.id.def_map(db);
1326 let module_data = &def_map[self.id];
1327 module_data.visibility
1328 }
1329}
1330
1331#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1332pub struct Field {
1333 pub(crate) parent: Variant,
1334 pub(crate) id: LocalFieldId,
1335}
1336
1337#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
1338pub struct TupleField {
1339 pub owner: InferBodyId,
1340 pub tuple: TupleId,
1341 pub index: u32,
1342}
1343
1344impl TupleField {
1345 pub fn name(&self) -> Name {
1346 Name::new_tuple_field(self.index as usize)
1347 }
1348
1349 pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> {
1350 let interner = DbInterner::new_no_crate(db);
1351 let ty = InferenceResult::of(db, self.owner)
1352 .tuple_field_access_type(self.tuple)
1353 .as_slice()
1354 .get(self.index as usize)
1355 .copied()
1356 .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed));
1357 Type::new_body(db, self.owner.expression_store_owner(db), ty)
1358 }
1359}
1360
1361#[derive(Debug, PartialEq, Eq)]
1362pub enum FieldSource {
1363 Named(ast::RecordField),
1364 Pos(ast::TupleField),
1365}
1366
1367impl AstNode for FieldSource {
1368 fn can_cast(kind: syntax::SyntaxKind) -> bool
1369 where
1370 Self: Sized,
1371 {
1372 ast::RecordField::can_cast(kind) || ast::TupleField::can_cast(kind)
1373 }
1374
1375 fn cast(syntax: SyntaxNode) -> Option<Self>
1376 where
1377 Self: Sized,
1378 {
1379 if ast::RecordField::can_cast(syntax.kind()) {
1380 <ast::RecordField as AstNode>::cast(syntax).map(FieldSource::Named)
1381 } else if ast::TupleField::can_cast(syntax.kind()) {
1382 <ast::TupleField as AstNode>::cast(syntax).map(FieldSource::Pos)
1383 } else {
1384 None
1385 }
1386 }
1387
1388 fn syntax(&self) -> &SyntaxNode {
1389 match self {
1390 FieldSource::Named(it) => it.syntax(),
1391 FieldSource::Pos(it) => it.syntax(),
1392 }
1393 }
1394}
1395
1396impl Field {
1397 pub fn name(&self, db: &dyn HirDatabase) -> Name {
1398 VariantId::from(self.parent).fields(db).fields()[self.id].name.clone()
1399 }
1400
1401 pub fn index(&self) -> usize {
1402 u32::from(self.id.into_raw()) as usize
1403 }
1404
1405 pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> {
1408 let var_id = self.parent.into();
1409 let ty = db.field_types(var_id)[self.id].get().instantiate_identity().skip_norm_wip();
1410 Type::new(var_id.adt_id(db).into(), ty)
1411 }
1412
1413 pub fn layout<'db>(&self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> {
1414 self.ty(db).layout(db)
1415 }
1416
1417 pub fn parent_def(&self, _db: &dyn HirDatabase) -> Variant {
1418 self.parent
1419 }
1420}
1421
1422impl HasVisibility for Field {
1423 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1424 let variant_data = VariantId::from(self.parent).fields(db);
1425 let visibility = &variant_data.fields()[self.id].visibility;
1426 let parent_id: hir_def::VariantId = self.parent.into();
1427 Visibility::resolve(db, &parent_id.resolver(db), visibility)
1429 }
1430}
1431
1432#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1433pub struct Struct {
1434 pub(crate) id: StructId,
1435}
1436
1437impl Struct {
1438 pub fn module(self, db: &dyn HirDatabase) -> Module {
1439 Module { id: self.id.lookup(db).container }
1440 }
1441
1442 pub fn name(self, db: &dyn HirDatabase) -> Name {
1443 StructSignature::of(db, self.id).name.clone()
1444 }
1445
1446 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
1447 self.id
1448 .fields(db)
1449 .fields()
1450 .iter()
1451 .map(|(id, _)| Field { parent: self.into(), id })
1452 .collect()
1453 }
1454
1455 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
1456 Type::from_def(db, self.id)
1457 }
1458
1459 pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> {
1460 Type::from_value_def(db, self.id)
1461 }
1462
1463 pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
1464 AttrFlags::repr(db, self.id.into())
1465 }
1466
1467 pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
1468 match self.variant_fields(db).shape {
1469 hir_def::item_tree::FieldsShape::Record => StructKind::Record,
1470 hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
1471 hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
1472 }
1473 }
1474
1475 fn variant_fields(self, db: &dyn HirDatabase) -> &VariantFields {
1476 self.id.fields(db)
1477 }
1478
1479 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1480 AttrFlags::query(db, self.id.into()).contains(AttrFlags::IS_UNSTABLE)
1481 }
1482}
1483
1484impl HasVisibility for Struct {
1485 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1486 let loc = self.id.lookup(db);
1487 let source = loc.source(db);
1488 visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
1489 }
1490}
1491
1492#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1493pub struct Union {
1494 pub(crate) id: UnionId,
1495}
1496
1497impl Union {
1498 pub fn name(self, db: &dyn HirDatabase) -> Name {
1499 UnionSignature::of(db, self.id).name.clone()
1500 }
1501
1502 pub fn module(self, db: &dyn HirDatabase) -> Module {
1503 Module { id: self.id.lookup(db).container }
1504 }
1505
1506 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
1507 Type::from_def(db, self.id)
1508 }
1509
1510 pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> {
1511 Type::from_value_def(db, self.id)
1512 }
1513
1514 pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
1515 match self.id.fields(db).shape {
1516 hir_def::item_tree::FieldsShape::Record => StructKind::Record,
1517 hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
1518 hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
1519 }
1520 }
1521
1522 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
1523 self.id
1524 .fields(db)
1525 .fields()
1526 .iter()
1527 .map(|(id, _)| Field { parent: self.into(), id })
1528 .collect()
1529 }
1530 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1531 AttrFlags::query(db, self.id.into()).contains(AttrFlags::IS_UNSTABLE)
1532 }
1533}
1534
1535impl HasVisibility for Union {
1536 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1537 let loc = self.id.lookup(db);
1538 let source = loc.source(db);
1539 visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
1540 }
1541}
1542
1543#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1544pub struct Enum {
1545 pub(crate) id: EnumId,
1546}
1547
1548impl Enum {
1549 pub fn module(self, db: &dyn HirDatabase) -> Module {
1550 Module { id: self.id.lookup(db).container }
1551 }
1552
1553 pub fn name(self, db: &dyn HirDatabase) -> Name {
1554 EnumSignature::of(db, self.id).name.clone()
1555 }
1556
1557 pub fn variants(self, db: &dyn HirDatabase) -> Vec<EnumVariant> {
1558 self.id.enum_variants(db).variants.values().map(|&(id, _)| EnumVariant { id }).collect()
1559 }
1560
1561 pub fn num_variants(self, db: &dyn HirDatabase) -> usize {
1562 self.id.enum_variants(db).variants.len()
1563 }
1564
1565 pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
1566 AttrFlags::repr(db, self.id.into())
1567 }
1568
1569 pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
1570 Type::from_def(db, self.id)
1571 }
1572
1573 pub fn variant_body_ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
1575 let interner = DbInterner::new_no_crate(db);
1576 Type::no_params(
1577 Type::builtin_type_crate(db),
1578 match EnumSignature::variant_body_type(db, self.id) {
1579 layout::IntegerType::Pointer(sign) => match sign {
1580 true => Ty::new_int(interner, rustc_type_ir::IntTy::Isize),
1581 false => Ty::new_uint(interner, rustc_type_ir::UintTy::Usize),
1582 },
1583 layout::IntegerType::Fixed(i, sign) => match sign {
1584 true => Ty::new_int(
1585 interner,
1586 match i {
1587 layout::Integer::I8 => rustc_type_ir::IntTy::I8,
1588 layout::Integer::I16 => rustc_type_ir::IntTy::I16,
1589 layout::Integer::I32 => rustc_type_ir::IntTy::I32,
1590 layout::Integer::I64 => rustc_type_ir::IntTy::I64,
1591 layout::Integer::I128 => rustc_type_ir::IntTy::I128,
1592 },
1593 ),
1594 false => Ty::new_uint(
1595 interner,
1596 match i {
1597 layout::Integer::I8 => rustc_type_ir::UintTy::U8,
1598 layout::Integer::I16 => rustc_type_ir::UintTy::U16,
1599 layout::Integer::I32 => rustc_type_ir::UintTy::U32,
1600 layout::Integer::I64 => rustc_type_ir::UintTy::U64,
1601 layout::Integer::I128 => rustc_type_ir::UintTy::U128,
1602 },
1603 ),
1604 },
1605 },
1606 )
1607 }
1608
1609 pub fn is_data_carrying(self, db: &dyn HirDatabase) -> bool {
1611 self.variants(db).iter().any(|v| !matches!(v.kind(db), StructKind::Unit))
1612 }
1613
1614 pub fn layout<'db>(self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> {
1615 Adt::from(self).layout(db)
1616 }
1617
1618 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1619 AttrFlags::query(db, self.id.into()).contains(AttrFlags::IS_UNSTABLE)
1620 }
1621}
1622
1623impl HasVisibility for Enum {
1624 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1625 let loc = self.id.lookup(db);
1626 let source = loc.source(db);
1627 visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
1628 }
1629}
1630
1631#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1632pub struct EnumVariant {
1633 pub(crate) id: EnumVariantId,
1634}
1635
1636impl EnumVariant {
1637 pub fn module(self, db: &dyn HirDatabase) -> Module {
1638 Module { id: self.id.module(db) }
1639 }
1640
1641 pub fn parent_enum(self, db: &dyn HirDatabase) -> Enum {
1642 self.id.lookup(db).parent.into()
1643 }
1644
1645 pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> {
1646 Type::from_value_def(db, self.id)
1647 }
1648
1649 pub fn name(self, db: &dyn HirDatabase) -> Name {
1650 self.id.lookup(db).name.clone()
1651 }
1652
1653 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
1654 self.id
1655 .fields(db)
1656 .fields()
1657 .iter()
1658 .map(|(id, _)| Field { parent: self.into(), id })
1659 .collect()
1660 }
1661
1662 pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
1663 match self.id.fields(db).shape {
1664 hir_def::item_tree::FieldsShape::Record => StructKind::Record,
1665 hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
1666 hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
1667 }
1668 }
1669
1670 pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
1671 self.source(db)?.value.const_arg()?.expr()
1672 }
1673
1674 pub fn eval(self, db: &dyn HirDatabase) -> Result<i128, ConstEvalError> {
1675 db.const_eval_discriminant(self.into())
1676 }
1677
1678 pub fn layout<'db>(&self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> {
1679 let parent_enum = self.parent_enum(db);
1680 let parent_layout = parent_enum.layout(db)?;
1681 Ok(match &parent_layout.0.variants {
1682 layout::Variants::Multiple { variants, .. } => Layout(
1683 {
1684 let lookup = self.id.lookup(db);
1685 let rustc_enum_variant_idx = RustcEnumVariantIdx(lookup.index(db));
1686 Arc::new(variants[rustc_enum_variant_idx].clone())
1687 },
1688 db.target_data_layout(parent_enum.krate(db).into()).unwrap(),
1689 ),
1690 _ => parent_layout,
1691 })
1692 }
1693
1694 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1695 AttrFlags::query(db, self.id.into()).contains(AttrFlags::IS_UNSTABLE)
1696 }
1697}
1698
1699#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1700pub enum StructKind {
1701 Record,
1702 Tuple,
1703 Unit,
1704}
1705
1706impl HasVisibility for EnumVariant {
1708 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1709 self.parent_enum(db).visibility(db)
1710 }
1711}
1712
1713#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1715pub enum Adt {
1716 Struct(Struct),
1717 Union(Union),
1718 Enum(Enum),
1719}
1720impl_from!(Struct, Union, Enum for Adt);
1721
1722impl Adt {
1723 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
1724 has_non_default_type_params(db, self.into())
1725 }
1726
1727 pub fn layout<'db>(self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> {
1728 let interner = DbInterner::new_no_crate(db);
1729 let adt_id = AdtId::from(self);
1730 let args = GenericArgs::for_item_with_defaults(interner, adt_id.into(), |_, id, _| {
1731 GenericArg::error_from_id(interner, id)
1732 });
1733 db.layout_of_adt(adt_id, args.store(), param_env_from_has_crate(db, adt_id).store())
1734 .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).id).unwrap()))
1735 }
1736
1737 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
1741 let id = AdtId::from(self);
1742 Type::from_def(db, id)
1743 }
1744
1745 pub fn module(self, db: &dyn HirDatabase) -> Module {
1746 match self {
1747 Adt::Struct(s) => s.module(db),
1748 Adt::Union(s) => s.module(db),
1749 Adt::Enum(e) => e.module(db),
1750 }
1751 }
1752
1753 pub fn name(self, db: &dyn HirDatabase) -> Name {
1754 match self {
1755 Adt::Struct(s) => s.name(db),
1756 Adt::Union(u) => u.name(db),
1757 Adt::Enum(e) => e.name(db),
1758 }
1759 }
1760
1761 pub fn lifetime(&self, db: &dyn HirDatabase) -> Option<LifetimeParamData> {
1763 let resolver = match self {
1764 Adt::Struct(s) => s.id.resolver(db),
1765 Adt::Union(u) => u.id.resolver(db),
1766 Adt::Enum(e) => e.id.resolver(db),
1767 };
1768 resolver
1769 .generic_params()
1770 .and_then(|gp| {
1771 gp.iter_lt()
1772 .nth(0)
1775 })
1776 .map(|arena| arena.1.clone())
1777 }
1778
1779 pub fn as_struct(&self) -> Option<Struct> {
1780 if let Self::Struct(v) = self { Some(*v) } else { None }
1781 }
1782
1783 pub fn as_enum(&self) -> Option<Enum> {
1784 if let Self::Enum(v) = self { Some(*v) } else { None }
1785 }
1786}
1787
1788impl HasVisibility for Adt {
1789 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1790 match self {
1791 Adt::Struct(it) => it.visibility(db),
1792 Adt::Union(it) => it.visibility(db),
1793 Adt::Enum(it) => it.visibility(db),
1794 }
1795 }
1796}
1797
1798#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1799pub enum Variant {
1800 Struct(Struct),
1801 Union(Union),
1802 EnumVariant(EnumVariant),
1803}
1804impl_from!(Struct, Union, EnumVariant for Variant);
1805
1806impl Variant {
1807 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
1808 match self {
1809 Variant::Struct(it) => it.fields(db),
1810 Variant::Union(it) => it.fields(db),
1811 Variant::EnumVariant(it) => it.fields(db),
1812 }
1813 }
1814
1815 pub fn module(self, db: &dyn HirDatabase) -> Module {
1816 match self {
1817 Variant::Struct(it) => it.module(db),
1818 Variant::Union(it) => it.module(db),
1819 Variant::EnumVariant(it) => it.module(db),
1820 }
1821 }
1822
1823 pub fn name(&self, db: &dyn HirDatabase) -> Name {
1824 match self {
1825 Variant::Struct(s) => (*s).name(db),
1826 Variant::Union(u) => (*u).name(db),
1827 Variant::EnumVariant(e) => (*e).name(db),
1828 }
1829 }
1830
1831 pub fn adt(&self, db: &dyn HirDatabase) -> Adt {
1832 match *self {
1833 Variant::Struct(it) => it.into(),
1834 Variant::Union(it) => it.into(),
1835 Variant::EnumVariant(it) => it.parent_enum(db).into(),
1836 }
1837 }
1838}
1839
1840#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1841pub struct AnonConst {
1842 id: AnonConstId,
1843}
1844
1845impl AnonConst {
1846 pub fn owner(self, db: &dyn HirDatabase) -> ExpressionStoreOwner {
1847 self.id.loc(db).owner.into()
1848 }
1849
1850 pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
1851 let loc = self.id.loc(db);
1852 Type { owner: self.id.into(), ty: loc.ty.get() }
1853 }
1854
1855 pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError> {
1856 let interner = DbInterner::new_no_crate(db);
1857 let ty = self.id.loc(db).ty.get().instantiate_identity().skip_norm_wip();
1858 db.anon_const_eval(self.id, GenericArgs::empty(interner), None).map(|it| EvaluatedConst {
1859 allocation: it,
1860 def: self.id.into(),
1861 ty,
1862 })
1863 }
1864}
1865
1866#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1867pub enum InferBody {
1868 Body(DefWithBody),
1869 AnonConst(AnonConst),
1870}
1871
1872#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1873pub enum ExpressionStoreOwner {
1874 Body(DefWithBody),
1875 Signature(GenericDef),
1876 VariantFields(Variant),
1877}
1878
1879impl From<GenericDef> for ExpressionStoreOwner {
1880 fn from(v: GenericDef) -> Self {
1881 Self::Signature(v)
1882 }
1883}
1884
1885impl From<DefWithBody> for ExpressionStoreOwner {
1886 fn from(v: DefWithBody) -> Self {
1887 Self::Body(v)
1888 }
1889}
1890
1891impl From<ExpressionStoreOwnerId> for ExpressionStoreOwner {
1892 fn from(v: ExpressionStoreOwnerId) -> Self {
1893 match v {
1894 ExpressionStoreOwnerId::Signature(generic_def_id) => {
1895 Self::Signature(generic_def_id.into())
1896 }
1897 ExpressionStoreOwnerId::Body(def_with_body_id) => Self::Body(def_with_body_id.into()),
1898 ExpressionStoreOwnerId::VariantFields(variant_id) => {
1899 Self::VariantFields(variant_id.into())
1900 }
1901 }
1902 }
1903}
1904
1905impl ExpressionStoreOwner {
1906 pub fn module(self, db: &dyn HirDatabase) -> Module {
1907 match self {
1908 Self::Body(body) => body.module(db),
1909 Self::Signature(generic_def) => generic_def.module(db),
1910 Self::VariantFields(variant) => variant.module(db),
1911 }
1912 }
1913}
1914
1915#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1917pub enum DefWithBody {
1918 Function(Function),
1919 Static(Static),
1920 Const(Const),
1921 EnumVariant(EnumVariant),
1922}
1923impl_from!(Function, Const, Static, EnumVariant for DefWithBody);
1924
1925impl DefWithBody {
1926 pub fn module(self, db: &dyn HirDatabase) -> Module {
1927 match self {
1928 DefWithBody::Const(c) => c.module(db),
1929 DefWithBody::Function(f) => f.module(db),
1930 DefWithBody::Static(s) => s.module(db),
1931 DefWithBody::EnumVariant(v) => v.module(db),
1932 }
1933 }
1934
1935 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
1936 match self {
1937 DefWithBody::Function(f) => Some(f.name(db)),
1938 DefWithBody::Static(s) => Some(s.name(db)),
1939 DefWithBody::Const(c) => c.name(db),
1940 DefWithBody::EnumVariant(v) => Some(v.name(db)),
1941 }
1942 }
1943
1944 pub fn body_type(self, db: &dyn HirDatabase) -> Type<'_> {
1946 match self {
1947 DefWithBody::Function(it) => it.ret_type(db),
1948 DefWithBody::Static(it) => it.ty(db),
1949 DefWithBody::Const(it) => it.ty(db),
1950 DefWithBody::EnumVariant(it) => it.parent_enum(db).variant_body_ty(db),
1951 }
1952 }
1953
1954 fn id(&self) -> Option<DefWithBodyId> {
1955 Some(match self {
1956 DefWithBody::Function(it) => match it.id {
1957 AnyFunctionId::FunctionId(id) => id.into(),
1958 AnyFunctionId::BuiltinDeriveImplMethod { .. } => return None,
1959 },
1960 DefWithBody::Static(it) => it.id.into(),
1961 DefWithBody::Const(it) => it.id.into(),
1962 DefWithBody::EnumVariant(it) => it.id.into(),
1963 })
1964 }
1965
1966 #[deprecated = "you should really not use this, this is exported for analysis-stats only"]
1967 pub fn run_mir_body(self, db: &dyn HirDatabase) -> Result<(), MirLowerError> {
1968 let Some(id) = self.id() else { return Ok(()) };
1969 db.mir_body(id.into()).map(drop)
1970 }
1971
1972 pub fn debug_hir(self, db: &dyn HirDatabase) -> String {
1974 let Some(id) = self.id() else {
1975 return String::new();
1976 };
1977 let body = Body::of(db, id);
1978 body.pretty_print(db, id, Edition::CURRENT)
1979 }
1980
1981 pub fn debug_mir(self, db: &dyn HirDatabase) -> String {
1983 let Some(id) = self.id() else {
1984 return String::new();
1985 };
1986 let body = db.mir_body(id.into());
1987 match body {
1988 Ok(body) => body.pretty_print(db, self.module(db).krate(db).to_display_target(db)),
1989 Err(e) => format!("error:\n{e:?}"),
1990 }
1991 }
1992
1993 pub fn diagnostics<'db>(
1994 self,
1995 db: &'db dyn HirDatabase,
1996 acc: &mut Vec<AnyDiagnostic<'db>>,
1997 style_lints: bool,
1998 ) {
1999 let Ok(id) = self.try_into() else {
2000 return;
2001 };
2002
2003 let (body, source_map) = Body::with_source_map(db, id);
2004 let sig_source_map = match self {
2005 DefWithBody::Function(id) => match id.id {
2006 AnyFunctionId::FunctionId(id) => &FunctionSignature::with_source_map(db, id).1,
2007 AnyFunctionId::BuiltinDeriveImplMethod { .. } => return,
2008 },
2009 DefWithBody::Static(id) => &StaticSignature::with_source_map(db, id.into()).1,
2010 DefWithBody::Const(id) => &ConstSignature::with_source_map(db, id.into()).1,
2011 DefWithBody::EnumVariant(variant) => {
2012 let enum_id = variant.parent_enum(db).id;
2013 &EnumSignature::with_source_map(db, enum_id).1
2014 }
2015 };
2016
2017 for (_, def_map) in body.blocks(db) {
2018 Module { id: def_map.root_module_id() }.diagnostics(db, acc, style_lints);
2019 }
2020
2021 expr_store_diagnostics(db, acc, source_map);
2022
2023 let infer = InferenceResult::of(db, id);
2024 let type_owner = id.generic_def(db).into();
2025 for d in infer.diagnostics() {
2026 acc.extend(AnyDiagnostic::inference_diagnostic(
2027 db,
2028 id,
2029 d,
2030 source_map,
2031 sig_source_map,
2032 type_owner,
2033 ));
2034 }
2035
2036 let missing_unsafe = hir_ty::diagnostics::missing_unsafe(db, id);
2037 for (node, reason) in missing_unsafe.unsafe_exprs {
2038 match source_map.expr_or_pat_syntax(node) {
2039 Ok(node) => acc.push(
2040 MissingUnsafe {
2041 node,
2042 lint: if missing_unsafe.fn_is_unsafe {
2043 UnsafeLint::UnsafeOpInUnsafeFn
2044 } else {
2045 UnsafeLint::HardError
2046 },
2047 reason,
2048 }
2049 .into(),
2050 ),
2051 Err(SyntheticSyntax) => {
2052 }
2055 }
2056 }
2057 for node in missing_unsafe.deprecated_safe_calls {
2058 match source_map.expr_syntax(node) {
2059 Ok(node) => acc.push(
2060 MissingUnsafe {
2061 node,
2062 lint: UnsafeLint::DeprecatedSafe2024,
2063 reason: UnsafetyReason::UnsafeFnCall,
2064 }
2065 .into(),
2066 ),
2067 Err(SyntheticSyntax) => never!("synthetic DeprecatedSafe2024"),
2068 }
2069 }
2070
2071 if let Ok(borrowck_results) = db.borrowck(id.into()) {
2072 for borrowck_result in borrowck_results.iter() {
2073 let mir_body = borrowck_result.mir_body(db);
2074 for moof in &borrowck_result.moved_out_of_ref {
2075 let span: InFile<SyntaxNodePtr> = match moof.span {
2076 mir::MirSpan::ExprId(e) => match source_map.expr_syntax(e) {
2077 Ok(s) => s.map(|it| it.into()),
2078 Err(_) => continue,
2079 },
2080 mir::MirSpan::PatId(p) => match source_map.pat_syntax(p) {
2081 Ok(s) => s.map(|it| it.into()),
2082 Err(_) => continue,
2083 },
2084 mir::MirSpan::SelfParam => match source_map.self_param_syntax() {
2085 Some(s) => s.map(|it| it.into()),
2086 None => continue,
2087 },
2088 mir::MirSpan::BindingId(b) => {
2089 match source_map
2090 .patterns_for_binding(b)
2091 .iter()
2092 .find_map(|p| source_map.pat_syntax(*p).ok())
2093 {
2094 Some(s) => s.map(|it| it.into()),
2095 None => continue,
2096 }
2097 }
2098 mir::MirSpan::Unknown => continue,
2099 };
2100 acc.push(
2101 MovedOutOfRef {
2102 ty: Type { owner: type_owner, ty: EarlyBinder::bind(moof.ty.as_ref()) },
2103 span,
2104 }
2105 .into(),
2106 )
2107 }
2108 let mol = &borrowck_result.mutability_of_locals;
2109 for (binding_id, binding_data) in body.bindings() {
2110 if binding_data.problems.is_some() {
2111 continue;
2113 }
2114 let Some(&local) = mir_body.binding_locals.get(binding_id) else {
2115 continue;
2116 };
2117 if source_map
2118 .patterns_for_binding(binding_id)
2119 .iter()
2120 .any(|&pat| source_map.pat_syntax(pat).is_err())
2121 {
2122 continue;
2124 }
2125 let mut need_mut = &mol[local];
2126 if body[binding_id].name == sym::self_
2127 && need_mut == &mir::MutabilityReason::Unused
2128 {
2129 need_mut = &mir::MutabilityReason::Not;
2130 }
2131 let local =
2132 Local { parent: id.into(), parent_infer: mir_body.owner, binding_id };
2133 let is_mut = body[binding_id].mode == BindingAnnotation::Mutable;
2134
2135 match (need_mut, is_mut) {
2136 (mir::MutabilityReason::Unused, _) => {
2137 let should_ignore = body[binding_id].name.as_str().starts_with('_');
2138 if !should_ignore {
2139 acc.push(UnusedVariable { local }.into())
2140 }
2141 }
2142 (mir::MutabilityReason::Mut { .. }, true)
2143 | (mir::MutabilityReason::Not, false) => (),
2144 (mir::MutabilityReason::Mut { spans }, false) => {
2145 for span in spans {
2146 let span: InFile<SyntaxNodePtr> = match span {
2147 mir::MirSpan::ExprId(e) => match source_map.expr_syntax(*e) {
2148 Ok(s) => s.map(|it| it.into()),
2149 Err(_) => continue,
2150 },
2151 mir::MirSpan::PatId(p) => match source_map.pat_syntax(*p) {
2152 Ok(s) => s.map(|it| it.into()),
2153 Err(_) => continue,
2154 },
2155 mir::MirSpan::BindingId(b) => {
2156 match source_map
2157 .patterns_for_binding(*b)
2158 .iter()
2159 .find_map(|p| source_map.pat_syntax(*p).ok())
2160 {
2161 Some(s) => s.map(|it| it.into()),
2162 None => continue,
2163 }
2164 }
2165 mir::MirSpan::SelfParam => match source_map.self_param_syntax()
2166 {
2167 Some(s) => s.map(|it| it.into()),
2168 None => continue,
2169 },
2170 mir::MirSpan::Unknown => continue,
2171 };
2172 acc.push(NeedMut { local, span }.into());
2173 }
2174 }
2175 (mir::MutabilityReason::Not, true) => {
2176 let should_ignore = body[binding_id].name.as_str().starts_with('_');
2177 if !should_ignore {
2178 acc.push(UnusedMut { local }.into())
2179 }
2180 }
2181 }
2182 }
2183 }
2184 }
2185
2186 for diagnostic in BodyValidationDiagnostic::collect(db, id, style_lints) {
2187 acc.extend(AnyDiagnostic::body_validation_diagnostic(db, diagnostic, source_map));
2188 }
2189
2190 for diag in hir_ty::diagnostics::incorrect_case(db, id.into()) {
2191 acc.push(diag.into())
2192 }
2193 }
2194
2195 pub fn expression_types<'db>(
2197 self,
2198 db: &'db dyn HirDatabase,
2199 ) -> impl Iterator<Item = Type<'db>> {
2200 self.id().into_iter().flat_map(move |def_id| {
2201 let infer = InferenceResult::of(db, def_id);
2202 let def_id = def_id.generic_def(db);
2203
2204 infer.expression_types().map(move |(_, ty)| Type::new(def_id, ty))
2205 })
2206 }
2207
2208 pub fn pattern_types<'db>(self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Type<'db>> {
2210 self.id().into_iter().flat_map(move |def_id| {
2211 let infer = InferenceResult::of(db, def_id);
2212 let def_id = def_id.generic_def(db);
2213
2214 infer.pattern_types().map(move |(_, ty)| Type::new(def_id, ty))
2215 })
2216 }
2217
2218 pub fn binding_types<'db>(self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Type<'db>> {
2220 self.id().into_iter().flat_map(move |def_id| {
2221 let infer = InferenceResult::of(db, def_id);
2222 let def_id = def_id.generic_def(db);
2223
2224 infer.binding_types().map(move |(_, ty)| Type::new(def_id, ty))
2225 })
2226 }
2227}
2228
2229fn expr_store_diagnostics<'db>(
2230 db: &'db dyn HirDatabase,
2231 acc: &mut Vec<AnyDiagnostic<'db>>,
2232 source_map: &ExpressionStoreSourceMap,
2233) {
2234 for diag in source_map.diagnostics() {
2235 acc.push(match diag {
2236 ExpressionStoreDiagnostics::InactiveCode { node, cfg, opts } => {
2237 InactiveCode { node: *node, cfg: cfg.clone(), opts: opts.clone() }.into()
2238 }
2239 ExpressionStoreDiagnostics::UnresolvedMacroCall { node, path } => UnresolvedMacroCall {
2240 range: node.map(|ptr| ptr.text_range()),
2241 path: path.clone(),
2242 is_bang: true,
2243 }
2244 .into(),
2245 ExpressionStoreDiagnostics::AwaitOutsideOfAsync { node, location } => {
2246 AwaitOutsideOfAsync { node: *node, location: location.clone() }.into()
2247 }
2248 ExpressionStoreDiagnostics::UnreachableLabel { node, name } => {
2249 UnreachableLabel { node: *node, name: name.clone() }.into()
2250 }
2251 ExpressionStoreDiagnostics::UndeclaredLabel { node, name } => {
2252 UndeclaredLabel { node: *node, name: name.clone() }.into()
2253 }
2254 ExpressionStoreDiagnostics::PatternArgInExternFn { node } => {
2255 PatternArgInExternFn { node: *node }.into()
2256 }
2257 ExpressionStoreDiagnostics::FruInDestructuringAssignment { node } => {
2258 FruInDestructuringAssignment { node: *node }.into()
2259 }
2260 });
2261 }
2262
2263 source_map
2264 .macro_calls()
2265 .for_each(|(_ast_id, call_id)| macro_call_diagnostics(db, call_id, acc));
2266}
2267
2268#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2269enum AnyFunctionId {
2270 FunctionId(FunctionId),
2271 BuiltinDeriveImplMethod { method: BuiltinDeriveImplMethod, impl_: BuiltinDeriveImplId },
2272}
2273
2274#[derive(Clone, Copy, PartialEq, Eq, Hash)]
2275pub struct Function {
2276 pub(crate) id: AnyFunctionId,
2277}
2278
2279impl fmt::Debug for Function {
2280 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2281 fmt::Debug::fmt(&self.id, f)
2282 }
2283}
2284
2285impl Function {
2286 pub fn module(self, db: &dyn HirDatabase) -> Module {
2287 match self.id {
2288 AnyFunctionId::FunctionId(id) => id.module(db).into(),
2289 AnyFunctionId::BuiltinDeriveImplMethod { impl_, .. } => impl_.module(db).into(),
2290 }
2291 }
2292
2293 pub fn name(self, db: &dyn HirDatabase) -> Name {
2294 match self.id {
2295 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).name.clone(),
2296 AnyFunctionId::BuiltinDeriveImplMethod { method, .. } => {
2297 Name::new_symbol_root(method.name())
2298 }
2299 }
2300 }
2301
2302 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
2303 match self.id {
2304 AnyFunctionId::FunctionId(id) => Type::from_value_def(db, id),
2305 AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } => {
2306 let Some(trait_method) = method.trait_method(db, impl_) else {
2310 return Type::unknown();
2311 };
2312 Function::from(trait_method).ty(db)
2313 }
2314 }
2315 }
2316
2317 pub fn fn_ptr_type(self, db: &dyn HirDatabase) -> Type<'_> {
2318 match self.id {
2319 AnyFunctionId::FunctionId(id) => {
2320 let interner = DbInterner::new_no_crate(db);
2321 let callable_sig =
2322 db.callable_item_signature(id.into()).instantiate_identity().skip_norm_wip();
2323 let ty = Ty::new_fn_ptr(interner, callable_sig);
2324 Type::new(id.into(), ty)
2325 }
2326 AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } => {
2327 let Some(trait_method) = method.trait_method(db, impl_) else {
2331 return Type::unknown();
2332 };
2333 Function::from(trait_method).fn_ptr_type(db)
2334 }
2335 }
2336 }
2337
2338 fn fn_sig<'db>(self, db: &'db dyn HirDatabase) -> (TypeOwnerId, PolyFnSig<'db>) {
2339 let fn_ptr = self.fn_ptr_type(db);
2340 let TyKind::FnPtr(sig_tys, hdr) = fn_ptr.ty.skip_binder().kind() else {
2341 unreachable!();
2342 };
2343 (fn_ptr.owner, sig_tys.with(hdr))
2344 }
2345
2346 pub fn ret_type(self, db: &dyn HirDatabase) -> Type<'_> {
2348 let (owner, sig) = self.fn_sig(db);
2349 Type { owner, ty: EarlyBinder::bind(sig.skip_binder().output()) }
2350 }
2351
2352 pub fn async_ret_type<'db>(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
2353 let AnyFunctionId::FunctionId(id) = self.id else {
2354 return None;
2355 };
2356 if !self.is_async(db) {
2357 return None;
2358 }
2359 let ret_ty =
2360 db.callable_item_signature(id.into()).instantiate_identity().skip_binder().output();
2361 for pred in ret_ty.impl_trait_bounds(db).into_iter().flatten() {
2362 if let ClauseKind::Projection(projection) = pred.kind().skip_binder()
2363 && let Some(output_ty) = projection.term.as_type()
2364 {
2365 return Some(Type::new(id.into(), output_ty));
2366 }
2367 }
2368 None
2369 }
2370
2371 pub fn has_self_param(self, db: &dyn HirDatabase) -> bool {
2372 match self.id {
2373 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).has_self_param(),
2374 AnyFunctionId::BuiltinDeriveImplMethod { method, .. } => match method {
2375 BuiltinDeriveImplMethod::clone
2376 | BuiltinDeriveImplMethod::fmt
2377 | BuiltinDeriveImplMethod::hash
2378 | BuiltinDeriveImplMethod::cmp
2379 | BuiltinDeriveImplMethod::partial_cmp
2380 | BuiltinDeriveImplMethod::eq => true,
2381 BuiltinDeriveImplMethod::default => false,
2382 },
2383 }
2384 }
2385
2386 pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
2387 self.has_self_param(db).then_some(SelfParam { func: self })
2388 }
2389
2390 pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param<'_>> {
2391 let (owner, sig) = self.fn_sig(db);
2392 let func = match self.id {
2393 AnyFunctionId::FunctionId(id) => Callee::Def(CallableDefId::FunctionId(id)),
2394 AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } => {
2395 Callee::BuiltinDeriveImplMethod { method, impl_ }
2396 }
2397 };
2398 sig.skip_binder()
2399 .inputs()
2400 .iter()
2401 .enumerate()
2402 .map(|(idx, &ty)| Param {
2403 func: func.clone(),
2404 ty: Type { owner, ty: EarlyBinder::bind(ty) },
2405 idx,
2406 })
2407 .collect()
2408 }
2409
2410 pub fn num_params(self, db: &dyn HirDatabase) -> usize {
2411 match self.id {
2412 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).params.len(),
2413 AnyFunctionId::BuiltinDeriveImplMethod { .. } => {
2414 self.fn_sig(db).1.skip_binder().inputs().len()
2415 }
2416 }
2417 }
2418
2419 pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param<'_>>> {
2420 self.self_param(db)?;
2421 Some(self.params_without_self(db))
2422 }
2423
2424 pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec<Param<'_>> {
2425 let mut params = self.assoc_fn_params(db);
2426 if self.has_self_param(db) {
2427 params.remove(0);
2428 }
2429 params
2430 }
2431
2432 pub fn is_const(self, db: &dyn HirDatabase) -> bool {
2433 match self.id {
2434 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).is_const(),
2435 AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
2436 }
2437 }
2438
2439 pub fn is_async(self, db: &dyn HirDatabase) -> bool {
2440 match self.id {
2441 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).is_async(),
2442 AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
2443 }
2444 }
2445
2446 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
2447 match self.id {
2448 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).is_unsafe(),
2449 AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
2450 }
2451 }
2452
2453 pub fn is_varargs(self, db: &dyn HirDatabase) -> bool {
2454 match self.id {
2455 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).is_varargs(),
2456 AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
2457 }
2458 }
2459
2460 pub fn extern_block(self, db: &dyn HirDatabase) -> Option<ExternBlock> {
2461 match self.id {
2462 AnyFunctionId::FunctionId(id) => match id.lookup(db).container {
2463 ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }),
2464 _ => None,
2465 },
2466 AnyFunctionId::BuiltinDeriveImplMethod { .. } => None,
2467 }
2468 }
2469
2470 pub fn returns_impl_future(self, db: &dyn HirDatabase) -> bool {
2471 if self.is_async(db) {
2472 return true;
2473 }
2474
2475 let ret_type = self.ret_type(db);
2476 let Some(impl_traits) = ret_type.as_impl_traits(db) else { return false };
2477 let lang_items = hir_def::lang_item::lang_items(db, self.krate(db).id);
2478 let Some(future_trait_id) = lang_items.Future else {
2479 return false;
2480 };
2481 let Some(sized_trait_id) = lang_items.Sized else {
2482 return false;
2483 };
2484
2485 let mut has_impl_future = false;
2486 impl_traits
2487 .filter(|t| {
2488 let fut = t.id == future_trait_id;
2489 has_impl_future |= fut;
2490 !fut && t.id != sized_trait_id
2491 })
2492 .all(|t| t.is_auto(db))
2494 && has_impl_future
2495 }
2496
2497 pub fn is_test(self, db: &dyn HirDatabase) -> bool {
2499 self.attrs(db).contains(AttrFlags::IS_TEST)
2500 }
2501
2502 pub fn is_main(self, db: &dyn HirDatabase) -> bool {
2504 match self.id {
2505 AnyFunctionId::FunctionId(id) => {
2506 self.exported_main(db)
2507 || self.module(db).is_crate_root(db)
2508 && FunctionSignature::of(db, id).name == sym::main
2509 }
2510 AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
2511 }
2512 }
2513
2514 fn attrs(self, db: &dyn HirDatabase) -> AttrFlags {
2515 match self.id {
2516 AnyFunctionId::FunctionId(id) => AttrFlags::query(db, id.into()),
2517 AnyFunctionId::BuiltinDeriveImplMethod { .. } => AttrFlags::empty(),
2518 }
2519 }
2520
2521 pub fn exported_main(self, db: &dyn HirDatabase) -> bool {
2523 self.attrs(db).contains(AttrFlags::IS_EXPORT_NAME_MAIN)
2524 }
2525
2526 pub fn is_ignore(self, db: &dyn HirDatabase) -> bool {
2528 self.attrs(db).contains(AttrFlags::IS_IGNORE)
2529 }
2530
2531 pub fn is_bench(self, db: &dyn HirDatabase) -> bool {
2533 self.attrs(db).contains(AttrFlags::IS_BENCH)
2534 }
2535
2536 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
2538 self.attrs(db).contains(AttrFlags::IS_UNSTABLE)
2539 }
2540
2541 pub fn is_unsafe_to_call(
2542 self,
2543 db: &dyn HirDatabase,
2544 caller: Option<Function>,
2545 call_edition: Edition,
2546 ) -> bool {
2547 let AnyFunctionId::FunctionId(id) = self.id else {
2548 return false;
2549 };
2550 let (target_features, target_feature_is_safe_in_target) = caller
2551 .map(|caller| {
2552 let target_features = match caller.id {
2553 AnyFunctionId::FunctionId(id) => hir_ty::TargetFeatures::from_fn(db, id),
2554 AnyFunctionId::BuiltinDeriveImplMethod { .. } => {
2555 hir_ty::TargetFeatures::default()
2556 }
2557 };
2558 let target_feature_is_safe_in_target =
2559 match &caller.krate(db).id.workspace_data(db).target {
2560 Ok(target) => hir_ty::target_feature_is_safe_in_target(target),
2561 Err(_) => hir_ty::TargetFeatureIsSafeInTarget::No,
2562 };
2563 (target_features, target_feature_is_safe_in_target)
2564 })
2565 .unwrap_or_else(|| {
2566 (hir_ty::TargetFeatures::default(), hir_ty::TargetFeatureIsSafeInTarget::No)
2567 });
2568 matches!(
2569 hir_ty::is_fn_unsafe_to_call(
2570 db,
2571 id,
2572 &target_features,
2573 call_edition,
2574 target_feature_is_safe_in_target
2575 ),
2576 hir_ty::Unsafety::Unsafe
2577 )
2578 }
2579
2580 pub fn has_body(self, db: &dyn HirDatabase) -> bool {
2584 match self.id {
2585 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).has_body(),
2586 AnyFunctionId::BuiltinDeriveImplMethod { .. } => true,
2587 }
2588 }
2589
2590 pub fn as_proc_macro(self, db: &dyn HirDatabase) -> Option<Macro> {
2591 let AnyFunctionId::FunctionId(id) = self.id else {
2592 return None;
2593 };
2594 let def_map = crate_def_map(db, HasModule::krate(&id, db));
2595 def_map.fn_as_proc_macro(id).map(|id| Macro { id: id.into() })
2596 }
2597
2598 pub fn eval(
2599 self,
2600 db: &dyn HirDatabase,
2601 span_formatter: impl Fn(FileId, TextRange) -> String,
2602 ) -> Result<String, ConstEvalError> {
2603 let AnyFunctionId::FunctionId(id) = self.id else {
2604 return Err(ConstEvalError::MirEvalError(MirEvalError::NotSupported(
2605 "evaluation of builtin derive impl methods is not supported".to_owned(),
2606 )));
2607 };
2608 let interner = DbInterner::new_no_crate(db);
2609 let body = db.monomorphized_mir_body(
2610 id.into(),
2611 GenericArgs::empty(interner).store(),
2612 ParamEnvAndCrate {
2613 param_env: db.trait_environment(id.into()),
2614 krate: id.module(db).krate(db),
2615 }
2616 .store(),
2617 )?;
2618 let (result, output) = interpret_mir(db, body, false, None)?;
2619 let mut text = match result {
2620 Ok(_) => "pass".to_owned(),
2621 Err(e) => {
2622 let mut r = String::new();
2623 _ = e.pretty_print(
2624 &mut r,
2625 db,
2626 &span_formatter,
2627 self.krate(db).to_display_target(db),
2628 );
2629 r
2630 }
2631 };
2632 let stdout = output.stdout().into_owned();
2633 if !stdout.is_empty() {
2634 text += "\n--------- stdout ---------\n";
2635 text += &stdout;
2636 }
2637 let stderr = output.stdout().into_owned();
2638 if !stderr.is_empty() {
2639 text += "\n--------- stderr ---------\n";
2640 text += &stderr;
2641 }
2642 Ok(text)
2643 }
2644}
2645
2646#[derive(Clone, Copy, PartialEq, Eq)]
2648pub enum Access {
2649 Shared,
2650 Exclusive,
2651 Owned,
2652}
2653
2654impl From<hir_ty::next_solver::Mutability> for Access {
2655 fn from(mutability: hir_ty::next_solver::Mutability) -> Access {
2656 match mutability {
2657 hir_ty::next_solver::Mutability::Not => Access::Shared,
2658 hir_ty::next_solver::Mutability::Mut => Access::Exclusive,
2659 }
2660 }
2661}
2662
2663#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2664pub struct Param<'db> {
2665 func: Callee<'db>,
2666 idx: usize,
2668 ty: Type<'db>,
2669}
2670
2671impl<'db> Param<'db> {
2672 pub fn parent_fn(&self) -> Option<Function> {
2673 match self.func {
2674 Callee::Def(CallableDefId::FunctionId(f)) => Some(f.into()),
2675 _ => None,
2676 }
2677 }
2678
2679 pub fn index(&self) -> usize {
2684 self.idx
2685 }
2686
2687 pub fn ty(&self) -> &Type<'db> {
2688 &self.ty
2689 }
2690
2691 pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
2692 Some(self.as_local(db)?.name(db))
2693 }
2694
2695 pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
2696 match self.func {
2697 Callee::Def(CallableDefId::FunctionId(it)) => {
2698 let parent = DefWithBodyId::FunctionId(it);
2699 let body = Body::of(db, parent);
2700 if let Some(self_param) = body.self_param().filter(|_| self.idx == 0) {
2701 Some(Local {
2702 parent: parent.into(),
2703 parent_infer: parent.into(),
2704 binding_id: self_param,
2705 })
2706 } else if let Pat::Bind { id, .. } =
2707 &body[body.params[self.idx - body.self_param().is_some() as usize]]
2708 {
2709 Some(Local {
2710 parent: parent.into(),
2711 parent_infer: parent.into(),
2712 binding_id: *id,
2713 })
2714 } else {
2715 None
2716 }
2717 }
2718 Callee::Closure(closure, _) => {
2719 let c = closure.loc(db);
2720 let body_infer_owner = c.owner;
2721 let body_owner = c.owner.expression_store_owner(db);
2722 let store = ExpressionStore::of(db, body_owner);
2723
2724 if let Expr::Closure { args, .. } = &store[c.expr]
2725 && let Pat::Bind { id, .. } = &store[args[self.idx]]
2726 {
2727 return Some(Local {
2728 parent: body_owner,
2729 parent_infer: body_infer_owner,
2730 binding_id: *id,
2731 });
2732 }
2733 None
2734 }
2735 _ => None,
2736 }
2737 }
2738
2739 pub fn pattern_source(self, db: &dyn HirDatabase) -> Option<ast::Pat> {
2740 self.source(db).and_then(|p| p.value.right()?.pat())
2741 }
2742}
2743
2744#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2745pub struct SelfParam {
2746 func: Function,
2747}
2748
2749impl SelfParam {
2750 pub fn access(self, db: &dyn HirDatabase) -> Access {
2751 match self.func.id {
2752 AnyFunctionId::FunctionId(id) => {
2753 let func_data = FunctionSignature::of(db, id);
2754 func_data
2755 .params
2756 .first()
2757 .map(|¶m| match &func_data.store[param] {
2758 TypeRef::Reference(ref_) => match ref_.mutability {
2759 hir_def::type_ref::Mutability::Shared => Access::Shared,
2760 hir_def::type_ref::Mutability::Mut => Access::Exclusive,
2761 },
2762 _ => Access::Owned,
2763 })
2764 .unwrap_or(Access::Owned)
2765 }
2766 AnyFunctionId::BuiltinDeriveImplMethod { method, .. } => match method {
2767 BuiltinDeriveImplMethod::clone
2768 | BuiltinDeriveImplMethod::fmt
2769 | BuiltinDeriveImplMethod::hash
2770 | BuiltinDeriveImplMethod::cmp
2771 | BuiltinDeriveImplMethod::partial_cmp
2772 | BuiltinDeriveImplMethod::eq => Access::Shared,
2773 BuiltinDeriveImplMethod::default => {
2774 unreachable!("this function does not have a self param")
2775 }
2776 },
2777 }
2778 }
2779
2780 pub fn parent_fn(&self) -> Function {
2781 self.func
2782 }
2783
2784 pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> {
2785 let (owner, sig) = self.func.fn_sig(db);
2786 Type { owner, ty: EarlyBinder::bind(sig.skip_binder().inputs()[0]) }
2787 }
2788}
2789
2790impl HasVisibility for Function {
2791 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2792 match self.id {
2793 AnyFunctionId::FunctionId(id) => db.assoc_visibility(id.into()),
2794 AnyFunctionId::BuiltinDeriveImplMethod { .. } => Visibility::Public,
2795 }
2796 }
2797}
2798
2799#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2800pub struct ExternCrateDecl {
2801 pub(crate) id: ExternCrateId,
2802}
2803
2804impl ExternCrateDecl {
2805 pub fn module(self, db: &dyn HirDatabase) -> Module {
2806 self.id.module(db).into()
2807 }
2808
2809 pub fn resolved_crate(self, db: &dyn HirDatabase) -> Option<Crate> {
2810 let loc = self.id.lookup(db);
2811 let krate = loc.container.krate(db);
2812 let name = self.name(db);
2813 if name == sym::self_ {
2814 Some(krate.into())
2815 } else {
2816 krate.data(db).dependencies.iter().find_map(|dep| {
2817 if dep.name.symbol() == name.symbol() { Some(dep.crate_id.into()) } else { None }
2818 })
2819 }
2820 }
2821
2822 pub fn name(self, db: &dyn HirDatabase) -> Name {
2823 let loc = self.id.lookup(db);
2824 let source = loc.source(db);
2825 as_name_opt(source.value.name_ref())
2826 }
2827
2828 pub fn alias(self, db: &dyn HirDatabase) -> Option<ImportAlias> {
2829 let loc = self.id.lookup(db);
2830 let source = loc.source(db);
2831 let rename = source.value.rename()?;
2832 if let Some(name) = rename.name() {
2833 Some(ImportAlias::Alias(name.as_name()))
2834 } else if rename.underscore_token().is_some() {
2835 Some(ImportAlias::Underscore)
2836 } else {
2837 None
2838 }
2839 }
2840
2841 pub fn alias_or_name(self, db: &dyn HirDatabase) -> Option<Name> {
2843 match self.alias(db) {
2844 Some(ImportAlias::Underscore) => None,
2845 Some(ImportAlias::Alias(alias)) => Some(alias),
2846 None => Some(self.name(db)),
2847 }
2848 }
2849}
2850
2851impl HasVisibility for ExternCrateDecl {
2852 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2853 let loc = self.id.lookup(db);
2854 let source = loc.source(db);
2855 visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
2856 }
2857}
2858
2859#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2860pub struct Const {
2861 pub(crate) id: ConstId,
2862}
2863
2864impl Const {
2865 pub fn module(self, db: &dyn HirDatabase) -> Module {
2866 Module { id: self.id.module(db) }
2867 }
2868
2869 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
2870 ConstSignature::of(db, self.id).name.clone()
2871 }
2872
2873 pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
2874 self.source(db)?.value.body()
2875 }
2876
2877 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
2878 Type::from_value_def(db, self.id)
2879 }
2880
2881 pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError> {
2883 let interner = DbInterner::new_no_crate(db);
2884 let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity().skip_norm_wip();
2885 db.const_eval(self.id, GenericArgs::empty(interner), None).map(|it| EvaluatedConst {
2886 allocation: it,
2887 def: self.id.into(),
2888 ty,
2889 })
2890 }
2891}
2892
2893impl HasVisibility for Const {
2894 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2895 db.assoc_visibility(self.id.into())
2896 }
2897}
2898
2899pub struct EvaluatedConst<'db> {
2900 def: InferBodyId,
2901 allocation: hir_ty::next_solver::Allocation<'db>,
2902 ty: Ty<'db>,
2903}
2904
2905impl<'db> EvaluatedConst<'db> {
2906 pub fn render(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
2907 format!("{}", self.allocation.display(db, display_target))
2908 }
2909
2910 pub fn render_debug(&self, db: &'db dyn HirDatabase) -> Result<String, MirEvalError> {
2911 let ty = self.allocation.ty.kind();
2912 if let TyKind::Int(_) | TyKind::Uint(_) = ty {
2913 let b = &self.allocation.memory;
2914 let value = u128::from_le_bytes(mir::pad16(b, false));
2915 let value_signed = i128::from_le_bytes(mir::pad16(b, matches!(ty, TyKind::Int(_))));
2916 let mut result =
2917 if let TyKind::Int(_) = ty { value_signed.to_string() } else { value.to_string() };
2918 if value >= 10 {
2919 format_to!(result, " ({value:#X})");
2920 return Ok(result);
2921 } else {
2922 return Ok(result);
2923 }
2924 }
2925 mir::render_const_using_debug_impl(db, self.def, self.allocation, self.ty)
2926 }
2927}
2928
2929#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2930pub struct Static {
2931 pub(crate) id: StaticId,
2932}
2933
2934impl Static {
2935 pub fn module(self, db: &dyn HirDatabase) -> Module {
2936 Module { id: self.id.module(db) }
2937 }
2938
2939 pub fn name(self, db: &dyn HirDatabase) -> Name {
2940 StaticSignature::of(db, self.id).name.clone()
2941 }
2942
2943 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
2944 StaticSignature::of(db, self.id).flags.contains(StaticFlags::MUTABLE)
2945 }
2946
2947 pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
2948 self.source(db)?.value.body()
2949 }
2950
2951 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
2952 Type::from_value_def(db, self.id)
2953 }
2954
2955 pub fn extern_block(self, db: &dyn HirDatabase) -> Option<ExternBlock> {
2956 match self.id.lookup(db).container {
2957 ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }),
2958 _ => None,
2959 }
2960 }
2961
2962 pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError> {
2964 let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity().skip_norm_wip();
2965 db.const_eval_static(self.id).map(|it| EvaluatedConst {
2966 allocation: it,
2967 def: self.id.into(),
2968 ty,
2969 })
2970 }
2971}
2972
2973impl HasVisibility for Static {
2974 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2975 let loc = self.id.lookup(db);
2976 let source = loc.source(db);
2977 visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
2978 }
2979}
2980
2981#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2982pub struct Trait {
2983 pub(crate) id: TraitId,
2984}
2985
2986impl Trait {
2987 pub fn lang(db: &dyn HirDatabase, krate: Crate, lang_item: LangItem) -> Option<Trait> {
2988 let lang_items = hir_def::lang_item::lang_items(db, krate.id);
2989 match lang_item.from_lang_items(lang_items)? {
2990 LangItemTarget::TraitId(it) => Some(it.into()),
2991 _ => None,
2992 }
2993 }
2994
2995 pub fn module(self, db: &dyn HirDatabase) -> Module {
2996 Module { id: self.id.lookup(db).container }
2997 }
2998
2999 pub fn name(self, db: &dyn HirDatabase) -> Name {
3000 TraitSignature::of(db, self.id).name.clone()
3001 }
3002
3003 pub fn direct_supertraits(self, db: &dyn HirDatabase) -> Vec<Trait> {
3004 let traits = direct_super_traits(db, self.into());
3005 traits.iter().map(|tr| Trait::from(*tr)).collect()
3006 }
3007
3008 pub fn all_supertraits(self, db: &dyn HirDatabase) -> Vec<Trait> {
3009 let traits = all_super_traits(db, self.into());
3010 traits.iter().map(|tr| Trait::from(*tr)).collect()
3011 }
3012
3013 pub fn function(self, db: &dyn HirDatabase, name: impl PartialEq<Name>) -> Option<Function> {
3014 self.id.trait_items(db).items.iter().find(|(n, _)| name == *n).and_then(|&(_, it)| match it
3015 {
3016 AssocItemId::FunctionId(id) => Some(id.into()),
3017 _ => None,
3018 })
3019 }
3020
3021 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
3022 self.id.trait_items(db).items.iter().map(|(_name, it)| (*it).into()).collect()
3023 }
3024
3025 pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
3026 self.all_supertraits(db).into_iter().flat_map(|tr| tr.items(db)).collect()
3027 }
3028
3029 pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
3030 TraitSignature::of(db, self.id).flags.contains(TraitFlags::AUTO)
3031 }
3032
3033 pub fn is_unsafe(&self, db: &dyn HirDatabase) -> bool {
3034 TraitSignature::of(db, self.id).flags.contains(TraitFlags::UNSAFE)
3035 }
3036
3037 pub fn type_or_const_param_count(
3038 &self,
3039 db: &dyn HirDatabase,
3040 count_required_only: bool,
3041 ) -> usize {
3042 GenericParams::of(db,self.id.into())
3043 .iter_type_or_consts()
3044 .filter(|(_, ty)| !matches!(ty, TypeOrConstParamData::TypeParamData(ty) if ty.provenance != TypeParamProvenance::TypeParamList))
3045 .filter(|(_, ty)| !count_required_only || !ty.has_default())
3046 .count()
3047 }
3048
3049 pub fn dyn_compatibility(&self, db: &dyn HirDatabase) -> Option<DynCompatibilityViolation> {
3050 hir_ty::dyn_compatibility::dyn_compatibility(db, self.id)
3051 }
3052
3053 pub fn dyn_compatibility_all_violations(
3054 &self,
3055 db: &dyn HirDatabase,
3056 ) -> Option<Vec<DynCompatibilityViolation>> {
3057 let mut violations = vec![];
3058 _ = hir_ty::dyn_compatibility::dyn_compatibility_with_callback(
3059 db,
3060 self.id,
3061 &mut |violation| {
3062 violations.push(violation);
3063 ControlFlow::Continue(())
3064 },
3065 );
3066 violations.is_empty().not().then_some(violations)
3067 }
3068
3069 fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
3070 self.id.trait_items(db).macro_calls.to_vec().into_boxed_slice()
3071 }
3072
3073 pub fn complete(self, db: &dyn HirDatabase) -> Complete {
3075 Complete::extract(true, self.attrs(db).attrs)
3076 }
3077
3078 pub fn prefer_underscore_import(self, db: &dyn HirDatabase) -> bool {
3088 AttrFlags::query(db, self.id.into()).contains(AttrFlags::PREFER_UNDERSCORE_IMPORT)
3089 }
3090}
3091
3092impl HasVisibility for Trait {
3093 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
3094 let loc = self.id.lookup(db);
3095 let source = loc.source(db);
3096 visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
3097 }
3098}
3099
3100#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3101pub struct TypeAlias {
3102 pub(crate) id: TypeAliasId,
3103}
3104
3105impl TypeAlias {
3106 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
3107 has_non_default_type_params(db, self.id.into())
3108 }
3109
3110 pub fn module(self, db: &dyn HirDatabase) -> Module {
3111 Module { id: self.id.module(db) }
3112 }
3113
3114 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
3115 Type::from_def(db, self.id)
3116 }
3117
3118 pub fn name(self, db: &dyn HirDatabase) -> Name {
3119 TypeAliasSignature::of(db, self.id).name.clone()
3120 }
3121}
3122
3123impl HasVisibility for TypeAlias {
3124 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
3125 db.assoc_visibility(self.id.into())
3126 }
3127}
3128
3129#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3130pub struct ExternBlock {
3131 pub(crate) id: ExternBlockId,
3132}
3133
3134impl ExternBlock {
3135 pub fn module(self, db: &dyn HirDatabase) -> Module {
3136 Module { id: self.id.module(db) }
3137 }
3138}
3139
3140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3141pub struct StaticLifetime;
3142
3143impl StaticLifetime {
3144 pub fn name(self) -> Name {
3145 Name::new_symbol_root(sym::tick_static)
3146 }
3147}
3148
3149#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3150pub struct BuiltinType {
3151 pub(crate) inner: hir_def::builtin_type::BuiltinType,
3152}
3153
3154impl BuiltinType {
3155 pub fn str() -> BuiltinType {
3157 BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
3158 }
3159
3160 pub fn i32() -> BuiltinType {
3161 BuiltinType {
3162 inner: hir_def::builtin_type::BuiltinType::Int(hir_ty::primitive::BuiltinInt::I32),
3163 }
3164 }
3165
3166 pub fn bool() -> BuiltinType {
3167 BuiltinType { inner: hir_def::builtin_type::BuiltinType::Bool }
3168 }
3169
3170 pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
3171 let interner = DbInterner::new_no_crate(db);
3172 Type::no_params(Type::builtin_type_crate(db), Ty::from_builtin_type(interner, self.inner))
3173 }
3174
3175 pub fn name(self) -> Name {
3176 self.inner.as_name()
3177 }
3178
3179 pub fn is_int(&self) -> bool {
3180 matches!(self.inner, hir_def::builtin_type::BuiltinType::Int(_))
3181 }
3182
3183 pub fn is_uint(&self) -> bool {
3184 matches!(self.inner, hir_def::builtin_type::BuiltinType::Uint(_))
3185 }
3186
3187 pub fn is_float(&self) -> bool {
3188 matches!(self.inner, hir_def::builtin_type::BuiltinType::Float(_))
3189 }
3190
3191 pub fn is_f16(&self) -> bool {
3192 matches!(
3193 self.inner,
3194 hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F16)
3195 )
3196 }
3197
3198 pub fn is_f32(&self) -> bool {
3199 matches!(
3200 self.inner,
3201 hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F32)
3202 )
3203 }
3204
3205 pub fn is_f64(&self) -> bool {
3206 matches!(
3207 self.inner,
3208 hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F64)
3209 )
3210 }
3211
3212 pub fn is_f128(&self) -> bool {
3213 matches!(
3214 self.inner,
3215 hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F128)
3216 )
3217 }
3218
3219 pub fn is_char(&self) -> bool {
3220 matches!(self.inner, hir_def::builtin_type::BuiltinType::Char)
3221 }
3222
3223 pub fn is_bool(&self) -> bool {
3224 matches!(self.inner, hir_def::builtin_type::BuiltinType::Bool)
3225 }
3226
3227 pub fn is_str(&self) -> bool {
3228 matches!(self.inner, hir_def::builtin_type::BuiltinType::Str)
3229 }
3230}
3231
3232#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3233pub struct Macro {
3234 pub(crate) id: MacroId,
3235}
3236
3237impl Macro {
3238 pub fn module(self, db: &dyn HirDatabase) -> Module {
3239 Module { id: self.id.module(db) }
3240 }
3241
3242 pub fn name(self, db: &dyn HirDatabase) -> Name {
3243 match self.id {
3244 MacroId::Macro2Id(id) => {
3245 let loc = id.lookup(db);
3246 let source = loc.source(db);
3247 as_name_opt(source.value.name())
3248 }
3249 MacroId::MacroRulesId(id) => {
3250 let loc = id.lookup(db);
3251 let source = loc.source(db);
3252 as_name_opt(source.value.name())
3253 }
3254 MacroId::ProcMacroId(id) => {
3255 let loc = id.lookup(db);
3256 let source = loc.source(db);
3257 match loc.kind {
3258 ProcMacroKind::CustomDerive => AttrFlags::derive_info(db, self.id).map_or_else(
3259 || as_name_opt(source.value.name()),
3260 |info| Name::new_symbol_root(info.trait_name.clone()),
3261 ),
3262 ProcMacroKind::Bang | ProcMacroKind::Attr => as_name_opt(source.value.name()),
3263 }
3264 }
3265 }
3266 }
3267
3268 pub fn is_macro_export(self, db: &dyn HirDatabase) -> bool {
3269 matches!(self.id, MacroId::MacroRulesId(_) if AttrFlags::query(db, self.id.into()).contains(AttrFlags::IS_MACRO_EXPORT))
3270 }
3271
3272 pub fn is_proc_macro(self) -> bool {
3273 matches!(self.id, MacroId::ProcMacroId(_))
3274 }
3275
3276 pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind {
3277 match self.id {
3278 MacroId::Macro2Id(it) => match it.lookup(db).expander {
3279 MacroExpander::Declarative { .. } => MacroKind::Declarative,
3280 MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => {
3281 MacroKind::DeclarativeBuiltIn
3282 }
3283 MacroExpander::BuiltInAttr(_) => MacroKind::AttrBuiltIn,
3284 MacroExpander::BuiltInDerive(_) => MacroKind::DeriveBuiltIn,
3285 MacroExpander::UnimplementedBuiltIn => MacroKind::Declarative,
3286 },
3287 MacroId::MacroRulesId(it) => match it.lookup(db).expander {
3288 MacroExpander::Declarative { .. } => MacroKind::Declarative,
3289 MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => {
3290 MacroKind::DeclarativeBuiltIn
3291 }
3292 MacroExpander::BuiltInAttr(_) => MacroKind::AttrBuiltIn,
3293 MacroExpander::BuiltInDerive(_) => MacroKind::DeriveBuiltIn,
3294 MacroExpander::UnimplementedBuiltIn => MacroKind::Declarative,
3295 },
3296 MacroId::ProcMacroId(it) => match it.lookup(db).kind {
3297 ProcMacroKind::CustomDerive => MacroKind::Derive,
3298 ProcMacroKind::Bang => MacroKind::ProcMacro,
3299 ProcMacroKind::Attr => MacroKind::Attr,
3300 },
3301 }
3302 }
3303
3304 pub fn is_fn_like(&self, db: &dyn HirDatabase) -> bool {
3305 matches!(
3306 self.kind(db),
3307 MacroKind::Declarative | MacroKind::DeclarativeBuiltIn | MacroKind::ProcMacro
3308 )
3309 }
3310
3311 pub fn builtin_derive_kind(&self, db: &dyn HirDatabase) -> Option<BuiltinDeriveMacroKind> {
3312 let expander = match self.id {
3313 MacroId::Macro2Id(it) => it.lookup(db).expander,
3314 MacroId::MacroRulesId(it) => it.lookup(db).expander,
3315 MacroId::ProcMacroId(_) => return None,
3316 };
3317 match expander {
3318 MacroExpander::BuiltInDerive(kind) => Some(BuiltinDeriveMacroKind(kind)),
3319 _ => None,
3320 }
3321 }
3322
3323 pub fn is_env_or_option_env(&self, db: &dyn HirDatabase) -> bool {
3324 match self.id {
3325 MacroId::Macro2Id(it) => {
3326 matches!(it.lookup(db).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
3327 }
3328 MacroId::MacroRulesId(it) => {
3329 matches!(it.lookup(db).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
3330 }
3331 MacroId::ProcMacroId(_) => false,
3332 }
3333 }
3334
3335 pub fn is_asm_like(&self, db: &dyn HirDatabase) -> bool {
3337 match self.id {
3338 MacroId::Macro2Id(it) => {
3339 matches!(it.lookup(db).expander, MacroExpander::BuiltIn(m) if m.is_asm())
3340 }
3341 MacroId::MacroRulesId(it) => {
3342 matches!(it.lookup(db).expander, MacroExpander::BuiltIn(m) if m.is_asm())
3343 }
3344 MacroId::ProcMacroId(_) => false,
3345 }
3346 }
3347
3348 pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
3349 matches!(self.kind(db), MacroKind::Attr | MacroKind::AttrBuiltIn)
3350 }
3351
3352 pub fn is_derive(&self, db: &dyn HirDatabase) -> bool {
3353 matches!(self.kind(db), MacroKind::Derive | MacroKind::DeriveBuiltIn)
3354 }
3355
3356 pub fn preferred_brace_style(&self, db: &dyn HirDatabase) -> Option<MacroBraces> {
3357 let attrs = self.attrs(db);
3358 MacroBraces::extract(attrs.attrs)
3359 }
3360}
3361
3362#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3381pub enum MacroBraces {
3382 Braces,
3383 Brackets,
3384 Parentheses,
3385}
3386
3387impl MacroBraces {
3388 fn extract(attrs: AttrFlags) -> Option<Self> {
3389 if attrs.contains(AttrFlags::MACRO_STYLE_BRACES) {
3390 Some(Self::Braces)
3391 } else if attrs.contains(AttrFlags::MACRO_STYLE_BRACKETS) {
3392 Some(Self::Brackets)
3393 } else if attrs.contains(AttrFlags::MACRO_STYLE_PARENTHESES) {
3394 Some(Self::Parentheses)
3395 } else {
3396 None
3397 }
3398 }
3399}
3400
3401#[derive(Clone, Copy, PartialEq, Eq, Hash)]
3402pub struct BuiltinDeriveMacroKind(BuiltinDeriveExpander);
3403
3404impl HasVisibility for Macro {
3405 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
3406 match self.id {
3407 MacroId::Macro2Id(id) => {
3408 let loc = id.lookup(db);
3409 let source = loc.source(db);
3410 visibility_from_ast(db, id, source.map(|src| src.visibility()))
3411 }
3412 MacroId::MacroRulesId(_) => Visibility::Public,
3413 MacroId::ProcMacroId(_) => Visibility::Public,
3414 }
3415 }
3416}
3417
3418#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
3419pub enum ItemInNs {
3420 Types(ModuleDef),
3421 Values(ModuleDef),
3422 Macros(Macro),
3423}
3424
3425impl From<Macro> for ItemInNs {
3426 fn from(it: Macro) -> Self {
3427 Self::Macros(it)
3428 }
3429}
3430
3431impl From<ModuleDef> for ItemInNs {
3432 fn from(module_def: ModuleDef) -> Self {
3433 match module_def {
3434 ModuleDef::Static(_) | ModuleDef::Const(_) | ModuleDef::Function(_) => {
3435 ItemInNs::Values(module_def)
3436 }
3437 ModuleDef::Macro(it) => ItemInNs::Macros(it),
3438 _ => ItemInNs::Types(module_def),
3439 }
3440 }
3441}
3442
3443impl ItemInNs {
3444 pub fn into_module_def(self) -> ModuleDef {
3445 match self {
3446 ItemInNs::Types(id) | ItemInNs::Values(id) => id,
3447 ItemInNs::Macros(id) => ModuleDef::Macro(id),
3448 }
3449 }
3450
3451 pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
3453 match self {
3454 ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate(db)),
3455 ItemInNs::Macros(id) => Some(id.module(db).krate(db)),
3456 }
3457 }
3458
3459 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
3460 match self {
3461 ItemInNs::Types(it) | ItemInNs::Values(it) => it.attrs(db),
3462 ItemInNs::Macros(it) => Some(it.attrs(db)),
3463 }
3464 }
3465}
3466
3467#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
3470pub enum ExternAssocItem {
3471 Function(Function),
3472 Static(Static),
3473 TypeAlias(TypeAlias),
3474}
3475
3476pub trait AsExternAssocItem {
3477 fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem>;
3478}
3479
3480impl AsExternAssocItem for Function {
3481 fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
3482 let AnyFunctionId::FunctionId(id) = self.id else {
3483 return None;
3484 };
3485 as_extern_assoc_item(db, ExternAssocItem::Function, id)
3486 }
3487}
3488
3489impl AsExternAssocItem for Static {
3490 fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
3491 as_extern_assoc_item(db, ExternAssocItem::Static, self.id)
3492 }
3493}
3494
3495impl AsExternAssocItem for TypeAlias {
3496 fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
3497 as_extern_assoc_item(db, ExternAssocItem::TypeAlias, self.id)
3498 }
3499}
3500
3501#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
3504pub enum AssocItem {
3505 Function(Function),
3506 Const(Const),
3507 TypeAlias(TypeAlias),
3508}
3509
3510impl From<method_resolution::CandidateId> for AssocItem {
3511 fn from(value: method_resolution::CandidateId) -> Self {
3512 match value {
3513 method_resolution::CandidateId::FunctionId(id) => AssocItem::Function(id.into()),
3514 method_resolution::CandidateId::ConstId(id) => AssocItem::Const(Const { id }),
3515 }
3516 }
3517}
3518
3519#[derive(Debug, Clone)]
3520pub enum AssocItemContainer {
3521 Trait(Trait),
3522 Impl(Impl),
3523}
3524
3525pub trait AsAssocItem {
3526 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>;
3527}
3528
3529impl AsAssocItem for Function {
3530 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
3531 match self.id {
3532 AnyFunctionId::FunctionId(id) => as_assoc_item(db, AssocItem::Function, id),
3533 AnyFunctionId::BuiltinDeriveImplMethod { .. } => Some(AssocItem::Function(self)),
3534 }
3535 }
3536}
3537
3538impl AsAssocItem for Const {
3539 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
3540 as_assoc_item(db, AssocItem::Const, self.id)
3541 }
3542}
3543
3544impl AsAssocItem for TypeAlias {
3545 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
3546 as_assoc_item(db, AssocItem::TypeAlias, self.id)
3547 }
3548}
3549
3550impl AsAssocItem for ModuleDef {
3551 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
3552 match self {
3553 ModuleDef::Function(it) => it.as_assoc_item(db),
3554 ModuleDef::Const(it) => it.as_assoc_item(db),
3555 ModuleDef::TypeAlias(it) => it.as_assoc_item(db),
3556 _ => None,
3557 }
3558 }
3559}
3560
3561impl AsAssocItem for DefWithBody {
3562 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
3563 match self {
3564 DefWithBody::Function(it) => it.as_assoc_item(db),
3565 DefWithBody::Const(it) => it.as_assoc_item(db),
3566 DefWithBody::Static(_) | DefWithBody::EnumVariant(_) => None,
3567 }
3568 }
3569}
3570
3571impl AsAssocItem for GenericDef {
3572 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
3573 match self {
3574 GenericDef::Function(it) => it.as_assoc_item(db),
3575 GenericDef::Const(it) => it.as_assoc_item(db),
3576 GenericDef::TypeAlias(it) => it.as_assoc_item(db),
3577 _ => None,
3578 }
3579 }
3580}
3581
3582fn as_assoc_item<'db, ID, DEF, LOC>(
3583 db: &(dyn HirDatabase + 'db),
3584 ctor: impl FnOnce(DEF) -> AssocItem,
3585 id: ID,
3586) -> Option<AssocItem>
3587where
3588 ID: Lookup<Database = dyn DefDatabase, Data = AssocItemLoc<LOC>>,
3589 DEF: From<ID>,
3590 LOC: AstIdNode,
3591{
3592 match id.lookup(db).container {
3593 ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
3594 ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
3595 }
3596}
3597
3598fn as_extern_assoc_item<'db, ID, DEF, LOC>(
3599 db: &(dyn HirDatabase + 'db),
3600 ctor: impl FnOnce(DEF) -> ExternAssocItem,
3601 id: ID,
3602) -> Option<ExternAssocItem>
3603where
3604 ID: Lookup<Database = dyn DefDatabase, Data = AssocItemLoc<LOC>>,
3605 DEF: From<ID>,
3606 LOC: AstIdNode,
3607{
3608 match id.lookup(db).container {
3609 ItemContainerId::ExternBlockId(_) => Some(ctor(DEF::from(id))),
3610 ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) | ItemContainerId::ModuleId(_) => {
3611 None
3612 }
3613 }
3614}
3615
3616impl ExternAssocItem {
3617 pub fn name(self, db: &dyn HirDatabase) -> Name {
3618 match self {
3619 Self::Function(it) => it.name(db),
3620 Self::Static(it) => it.name(db),
3621 Self::TypeAlias(it) => it.name(db),
3622 }
3623 }
3624
3625 pub fn module(self, db: &dyn HirDatabase) -> Module {
3626 match self {
3627 Self::Function(f) => f.module(db),
3628 Self::Static(c) => c.module(db),
3629 Self::TypeAlias(t) => t.module(db),
3630 }
3631 }
3632
3633 pub fn as_function(self) -> Option<Function> {
3634 match self {
3635 Self::Function(v) => Some(v),
3636 _ => None,
3637 }
3638 }
3639
3640 pub fn as_static(self) -> Option<Static> {
3641 match self {
3642 Self::Static(v) => Some(v),
3643 _ => None,
3644 }
3645 }
3646
3647 pub fn as_type_alias(self) -> Option<TypeAlias> {
3648 match self {
3649 Self::TypeAlias(v) => Some(v),
3650 _ => None,
3651 }
3652 }
3653}
3654
3655impl AssocItem {
3656 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
3657 match self {
3658 AssocItem::Function(it) => Some(it.name(db)),
3659 AssocItem::Const(it) => it.name(db),
3660 AssocItem::TypeAlias(it) => Some(it.name(db)),
3661 }
3662 }
3663
3664 pub fn module(self, db: &dyn HirDatabase) -> Module {
3665 match self {
3666 AssocItem::Function(f) => f.module(db),
3667 AssocItem::Const(c) => c.module(db),
3668 AssocItem::TypeAlias(t) => t.module(db),
3669 }
3670 }
3671
3672 pub fn container(self, db: &dyn HirDatabase) -> AssocItemContainer {
3673 let container = match self {
3674 AssocItem::Function(it) => match it.id {
3675 AnyFunctionId::FunctionId(id) => id.lookup(db).container,
3676 AnyFunctionId::BuiltinDeriveImplMethod { impl_, .. } => {
3677 return AssocItemContainer::Impl(Impl {
3678 id: AnyImplId::BuiltinDeriveImplId(impl_),
3679 });
3680 }
3681 },
3682 AssocItem::Const(it) => it.id.lookup(db).container,
3683 AssocItem::TypeAlias(it) => it.id.lookup(db).container,
3684 };
3685 match container {
3686 ItemContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()),
3687 ItemContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()),
3688 ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
3689 panic!("invalid AssocItem")
3690 }
3691 }
3692 }
3693
3694 pub fn container_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
3695 match self.container(db) {
3696 AssocItemContainer::Trait(t) => Some(t),
3697 _ => None,
3698 }
3699 }
3700
3701 pub fn implemented_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
3702 match self.container(db) {
3703 AssocItemContainer::Impl(i) => i.trait_(db),
3704 _ => None,
3705 }
3706 }
3707
3708 pub fn container_or_implemented_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
3709 match self.container(db) {
3710 AssocItemContainer::Trait(t) => Some(t),
3711 AssocItemContainer::Impl(i) => i.trait_(db),
3712 }
3713 }
3714
3715 pub fn implementing_ty(self, db: &dyn HirDatabase) -> Option<Type<'_>> {
3716 match self.container(db) {
3717 AssocItemContainer::Impl(i) => Some(i.self_ty(db)),
3718 _ => None,
3719 }
3720 }
3721
3722 pub fn as_function(self) -> Option<Function> {
3723 match self {
3724 Self::Function(v) => Some(v),
3725 _ => None,
3726 }
3727 }
3728
3729 pub fn as_const(self) -> Option<Const> {
3730 match self {
3731 Self::Const(v) => Some(v),
3732 _ => None,
3733 }
3734 }
3735
3736 pub fn as_type_alias(self) -> Option<TypeAlias> {
3737 match self {
3738 Self::TypeAlias(v) => Some(v),
3739 _ => None,
3740 }
3741 }
3742
3743 pub fn diagnostics<'db>(
3744 self,
3745 db: &'db dyn HirDatabase,
3746 acc: &mut Vec<AnyDiagnostic<'db>>,
3747 style_lints: bool,
3748 ) {
3749 match self {
3750 AssocItem::Function(func) => {
3751 GenericDef::Function(func).diagnostics(db, acc);
3752 DefWithBody::from(func).diagnostics(db, acc, style_lints);
3753 }
3754 AssocItem::Const(const_) => {
3755 GenericDef::Const(const_).diagnostics(db, acc);
3756 DefWithBody::from(const_).diagnostics(db, acc, style_lints);
3757 }
3758 AssocItem::TypeAlias(type_alias) => {
3759 GenericDef::TypeAlias(type_alias).diagnostics(db, acc);
3760 push_ty_diagnostics(
3761 db,
3762 acc,
3763 db.type_for_type_alias_with_diagnostics(type_alias.id).diagnostics(),
3764 &TypeAliasSignature::with_source_map(db, type_alias.id).1,
3765 );
3766 for diag in hir_ty::diagnostics::incorrect_case(db, type_alias.id.into()) {
3767 acc.push(diag.into());
3768 }
3769 }
3770 }
3771 }
3772}
3773
3774impl HasVisibility for AssocItem {
3775 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
3776 match self {
3777 AssocItem::Function(f) => f.visibility(db),
3778 AssocItem::Const(c) => c.visibility(db),
3779 AssocItem::TypeAlias(t) => t.visibility(db),
3780 }
3781 }
3782}
3783
3784impl From<AssocItem> for ModuleDef {
3785 fn from(assoc: AssocItem) -> Self {
3786 match assoc {
3787 AssocItem::Function(it) => ModuleDef::Function(it),
3788 AssocItem::Const(it) => ModuleDef::Const(it),
3789 AssocItem::TypeAlias(it) => ModuleDef::TypeAlias(it),
3790 }
3791 }
3792}
3793
3794#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
3795pub enum GenericDef {
3796 Function(Function),
3797 Adt(Adt),
3798 Trait(Trait),
3799 TypeAlias(TypeAlias),
3800 Impl(Impl),
3801 Const(Const),
3803 Static(Static),
3804}
3805impl_from!(
3806 Function,
3807 Adt(Struct, Enum, Union),
3808 Trait,
3809 TypeAlias,
3810 Impl,
3811 Const,
3812 Static
3813 for GenericDef
3814);
3815
3816impl GenericDef {
3817 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
3818 match self {
3819 GenericDef::Function(it) => Some(it.name(db)),
3820 GenericDef::Adt(it) => Some(it.name(db)),
3821 GenericDef::Trait(it) => Some(it.name(db)),
3822 GenericDef::TypeAlias(it) => Some(it.name(db)),
3823 GenericDef::Impl(_) => None,
3824 GenericDef::Const(it) => it.name(db),
3825 GenericDef::Static(it) => Some(it.name(db)),
3826 }
3827 }
3828
3829 pub fn module(self, db: &dyn HirDatabase) -> Module {
3830 match self {
3831 GenericDef::Function(it) => it.module(db),
3832 GenericDef::Adt(it) => it.module(db),
3833 GenericDef::Trait(it) => it.module(db),
3834 GenericDef::TypeAlias(it) => it.module(db),
3835 GenericDef::Impl(it) => it.module(db),
3836 GenericDef::Const(it) => it.module(db),
3837 GenericDef::Static(it) => it.module(db),
3838 }
3839 }
3840
3841 pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
3842 let Ok(id) = self.try_into() else {
3843 return Vec::new();
3845 };
3846 let generics = GenericParams::of(db, id);
3847 let ty_params = generics.iter_type_or_consts().map(|(local_id, _)| {
3848 let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: id, local_id } };
3849 match toc.split(db) {
3850 Either::Left(it) => GenericParam::ConstParam(it),
3851 Either::Right(it) => GenericParam::TypeParam(it),
3852 }
3853 });
3854 self.lifetime_params(db)
3855 .into_iter()
3856 .map(GenericParam::LifetimeParam)
3857 .chain(ty_params)
3858 .collect()
3859 }
3860
3861 pub fn lifetime_params(self, db: &dyn HirDatabase) -> Vec<LifetimeParam> {
3862 let Ok(id) = self.try_into() else {
3863 return Vec::new();
3865 };
3866 let generics = GenericParams::of(db, id);
3867 generics
3868 .iter_lt()
3869 .map(|(local_id, _)| LifetimeParam { id: LifetimeParamId { parent: id, local_id } })
3870 .collect()
3871 }
3872
3873 pub fn type_or_const_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
3874 let Ok(id) = self.try_into() else {
3875 return Vec::new();
3877 };
3878 let generics = GenericParams::of(db, id);
3879 generics
3880 .iter_type_or_consts()
3881 .map(|(local_id, _)| TypeOrConstParam {
3882 id: TypeOrConstParamId { parent: id, local_id },
3883 })
3884 .collect()
3885 }
3886
3887 fn id(self) -> Option<GenericDefId> {
3888 Some(match self {
3889 GenericDef::Function(it) => match it.id {
3890 AnyFunctionId::FunctionId(it) => it.into(),
3891 AnyFunctionId::BuiltinDeriveImplMethod { .. } => return None,
3892 },
3893 GenericDef::Adt(it) => it.into(),
3894 GenericDef::Trait(it) => it.id.into(),
3895 GenericDef::TypeAlias(it) => it.id.into(),
3896 GenericDef::Impl(it) => match it.id {
3897 AnyImplId::ImplId(it) => it.into(),
3898 AnyImplId::BuiltinDeriveImplId(_) => return None,
3899 },
3900 GenericDef::Const(it) => it.id.into(),
3901 GenericDef::Static(it) => it.id.into(),
3902 })
3903 }
3904
3905 pub fn diagnostics<'db>(self, db: &'db dyn HirDatabase, acc: &mut Vec<AnyDiagnostic<'db>>) {
3906 let Some(def) = self.id() else { return };
3907
3908 let generics = GenericParams::of(db, def);
3909
3910 if generics.is_empty() && generics.has_no_predicates() {
3911 return;
3912 }
3913
3914 let source_map = match def {
3915 GenericDefId::AdtId(AdtId::EnumId(it)) => &EnumSignature::with_source_map(db, it).1,
3916 GenericDefId::AdtId(AdtId::StructId(it)) => &StructSignature::with_source_map(db, it).1,
3917 GenericDefId::AdtId(AdtId::UnionId(it)) => &UnionSignature::with_source_map(db, it).1,
3918 GenericDefId::ConstId(_) => return,
3919 GenericDefId::FunctionId(it) => &FunctionSignature::with_source_map(db, it).1,
3920 GenericDefId::ImplId(it) => &ImplSignature::with_source_map(db, it).1,
3921 GenericDefId::StaticId(_) => return,
3922 GenericDefId::TraitId(it) => &TraitSignature::with_source_map(db, it).1,
3923 GenericDefId::TypeAliasId(it) => &TypeAliasSignature::with_source_map(db, it).1,
3924 };
3925
3926 expr_store_diagnostics(db, acc, source_map);
3927 push_ty_diagnostics(
3928 db,
3929 acc,
3930 db.generic_defaults_with_diagnostics(def).diagnostics(),
3931 source_map,
3932 );
3933 push_ty_diagnostics(
3934 db,
3935 acc,
3936 GenericPredicates::query_with_diagnostics(db, def).diagnostics(),
3937 source_map,
3938 );
3939 push_ty_diagnostics(
3940 db,
3941 acc,
3942 db.const_param_types_with_diagnostics(def).diagnostics(),
3943 source_map,
3944 );
3945 }
3946
3947 #[inline]
3949 pub fn description(self) -> &'static str {
3950 match self {
3951 GenericDef::Function(_) => "function",
3952 GenericDef::Adt(Adt::Struct(_)) => "struct",
3953 GenericDef::Adt(Adt::Enum(_)) => "enum",
3954 GenericDef::Adt(Adt::Union(_)) => "union",
3955 GenericDef::Trait(_) => "trait",
3956 GenericDef::TypeAlias(_) => "type alias",
3957 GenericDef::Impl(_) => "impl",
3958 GenericDef::Const(_) => "constant",
3959 GenericDef::Static(_) => "static",
3960 }
3961 }
3962}
3963
3964#[derive(Debug)]
3966pub struct GenericSubstitution<'db> {
3967 owner: TypeOwnerId,
3968 def: GenericDefId,
3969 subst: GenericArgs<'db>,
3970}
3971
3972impl<'db> GenericSubstitution<'db> {
3973 fn new(def: GenericDefId, subst: GenericArgs<'db>, owner: TypeOwnerId) -> Self {
3974 Self { owner, def, subst }
3975 }
3976
3977 fn new_from_fn(def: Function, subst: GenericArgs<'db>, owner: TypeOwnerId) -> Option<Self> {
3978 match def.id {
3979 AnyFunctionId::FunctionId(def) => Some(Self::new(def.into(), subst, owner)),
3980 AnyFunctionId::BuiltinDeriveImplMethod { .. } => None,
3981 }
3982 }
3983
3984 pub fn types(&self, db: &'db dyn HirDatabase) -> Vec<(Symbol, Type<'db>)> {
3985 let container = match self.def {
3986 GenericDefId::ConstId(id) => Some(id.lookup(db).container),
3987 GenericDefId::FunctionId(id) => Some(id.lookup(db).container),
3988 GenericDefId::TypeAliasId(id) => Some(id.lookup(db).container),
3989 _ => None,
3990 };
3991 let container_type_params = container
3992 .and_then(|container| match container {
3993 ItemContainerId::ImplId(container) => Some(container.into()),
3994 ItemContainerId::TraitId(container) => Some(container.into()),
3995 _ => None,
3996 })
3997 .map(|container| {
3998 GenericParams::of(db, container)
3999 .iter_type_or_consts()
4000 .filter_map(|param| match param.1 {
4001 TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
4002 TypeOrConstParamData::ConstParamData(_) => None,
4003 })
4004 .collect::<Vec<_>>()
4005 });
4006 let generics = GenericParams::of(db, self.def);
4007 let type_params = generics.iter_type_or_consts().filter_map(|param| match param.1 {
4008 TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
4009 TypeOrConstParamData::ConstParamData(_) => None,
4010 });
4011 let parent_len = self.subst.len()
4012 - generics
4013 .iter_type_or_consts()
4014 .filter(|g| matches!(g.1, TypeOrConstParamData::TypeParamData(..)))
4015 .count();
4016 let container_params = self.subst.as_slice()[..parent_len]
4017 .iter()
4018 .filter_map(|param| param.ty())
4019 .zip(container_type_params.into_iter().flatten());
4020 let self_params = self.subst.as_slice()[parent_len..]
4021 .iter()
4022 .filter_map(|param| param.ty())
4023 .zip(type_params);
4024 container_params
4025 .chain(self_params)
4026 .filter_map(|(ty, name)| {
4027 Some((
4028 name?.symbol().clone(),
4029 Type { ty: EarlyBinder::bind(ty), owner: self.owner },
4030 ))
4031 })
4032 .collect()
4033 }
4034}
4035
4036#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4038pub struct Local {
4039 pub(crate) parent: ExpressionStoreOwnerId,
4040 pub(crate) parent_infer: InferBodyId,
4041 pub(crate) binding_id: BindingId,
4042}
4043
4044pub struct LocalSource {
4045 pub local: Local,
4046 pub source: InFile<Either<ast::IdentPat, ast::SelfParam>>,
4047}
4048
4049impl LocalSource {
4050 pub fn as_ident_pat(&self) -> Option<&ast::IdentPat> {
4051 match &self.source.value {
4052 Either::Left(it) => Some(it),
4053 Either::Right(_) => None,
4054 }
4055 }
4056
4057 pub fn into_ident_pat(self) -> Option<ast::IdentPat> {
4058 match self.source.value {
4059 Either::Left(it) => Some(it),
4060 Either::Right(_) => None,
4061 }
4062 }
4063
4064 pub fn original_file(&self, db: &dyn HirDatabase) -> EditionedFileId {
4065 self.source.file_id.original_file(db)
4066 }
4067
4068 pub fn file(&self) -> HirFileId {
4069 self.source.file_id
4070 }
4071
4072 pub fn name(&self) -> Option<InFile<ast::Name>> {
4073 self.source.as_ref().map(|it| it.name()).transpose()
4074 }
4075
4076 pub fn syntax(&self) -> &SyntaxNode {
4077 self.source.value.syntax()
4078 }
4079
4080 pub fn syntax_ptr(self) -> InFile<SyntaxNodePtr> {
4081 self.source.map(|it| SyntaxNodePtr::new(it.syntax()))
4082 }
4083}
4084
4085impl Local {
4086 pub fn is_param(self, db: &dyn HirDatabase) -> bool {
4087 let src = self.primary_source(db);
4089 match src.source.value {
4090 Either::Left(pat) => pat
4091 .syntax()
4092 .ancestors()
4093 .map(|it| it.kind())
4094 .take_while(|&kind| ast::Pat::can_cast(kind) || ast::Param::can_cast(kind))
4095 .any(ast::Param::can_cast),
4096 Either::Right(_) => true,
4097 }
4098 }
4099
4100 pub fn as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
4101 match self.parent {
4102 ExpressionStoreOwnerId::Body(DefWithBodyId::FunctionId(func)) if self.is_self(db) => {
4103 Some(SelfParam { func: func.into() })
4104 }
4105 _ => None,
4106 }
4107 }
4108
4109 pub fn name(self, db: &dyn HirDatabase) -> Name {
4110 ExpressionStore::of(db, self.parent)[self.binding_id].name.clone()
4111 }
4112
4113 pub fn is_self(self, db: &dyn HirDatabase) -> bool {
4114 self.name(db) == sym::self_
4115 }
4116
4117 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
4118 ExpressionStore::of(db, self.parent)[self.binding_id].mode == BindingAnnotation::Mutable
4119 }
4120
4121 pub fn is_ref(self, db: &dyn HirDatabase) -> bool {
4122 matches!(
4123 ExpressionStore::of(db, self.parent)[self.binding_id].mode,
4124 BindingAnnotation::Ref | BindingAnnotation::RefMut
4125 )
4126 }
4127
4128 pub fn parent(self, _db: &dyn HirDatabase) -> ExpressionStoreOwner {
4129 self.parent.into()
4130 }
4131
4132 pub fn module(self, db: &dyn HirDatabase) -> Module {
4133 self.parent(db).module(db)
4134 }
4135
4136 pub fn as_id(self) -> u32 {
4137 self.binding_id.into_raw().into_u32()
4138 }
4139
4140 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
4141 let def = self.parent;
4142 let infer = InferenceResult::of(db, self.parent_infer);
4143 let ty = infer.binding_ty(self.binding_id);
4144 Type::new_body(db, def, ty)
4145 }
4146
4147 pub fn sources(self, db: &dyn HirDatabase) -> Vec<LocalSource> {
4149 let b;
4150 let (_, source_map) = match self.parent {
4151 ExpressionStoreOwnerId::Signature(generic_def_id) => {
4152 ExpressionStore::with_source_map(db, generic_def_id.into())
4153 }
4154 ExpressionStoreOwnerId::Body(def_with_body_id) => {
4155 b = Body::with_source_map(db, def_with_body_id);
4156 if b.0.self_params.contains(&self.binding_id)
4157 && let Some(source) = b.1.self_param_syntax()
4158 {
4159 let root = source.file_syntax(db);
4160 return vec![LocalSource {
4161 local: self,
4162 source: source.map(|ast| Either::Right(ast.to_node(&root))),
4163 }];
4164 }
4165 (&b.0.store, &b.1.store)
4166 }
4167 ExpressionStoreOwnerId::VariantFields(def) => {
4168 ExpressionStore::with_source_map(db, def.into())
4169 }
4170 };
4171 source_map
4172 .patterns_for_binding(self.binding_id)
4173 .iter()
4174 .map(|&definition| {
4175 let src = source_map.pat_syntax(definition).unwrap(); let root = src.file_syntax(db);
4177 LocalSource {
4178 local: self,
4179 source: src.map(|ast| match ast.to_node(&root) {
4180 Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
4181 _ => unreachable!("local with non ident-pattern"),
4182 }),
4183 }
4184 })
4185 .collect()
4186 }
4187
4188 pub fn primary_source(self, db: &dyn HirDatabase) -> LocalSource {
4190 let b;
4191 let (_, source_map) = match self.parent {
4192 ExpressionStoreOwnerId::Signature(generic_def_id) => {
4193 ExpressionStore::with_source_map(db, generic_def_id.into())
4194 }
4195 ExpressionStoreOwnerId::Body(def_with_body_id) => {
4196 b = Body::with_source_map(db, def_with_body_id);
4197 if b.0.self_params.contains(&self.binding_id)
4198 && let Some(source) = b.1.self_param_syntax()
4199 {
4200 let root = source.file_syntax(db);
4201 return LocalSource {
4202 local: self,
4203 source: source.map(|ast| Either::Right(ast.to_node(&root))),
4204 };
4205 }
4206 (&b.0.store, &b.1.store)
4207 }
4208 ExpressionStoreOwnerId::VariantFields(def) => {
4209 ExpressionStore::with_source_map(db, def.into())
4210 }
4211 };
4212 source_map
4213 .patterns_for_binding(self.binding_id)
4214 .first()
4215 .map(|&definition| {
4216 let src = source_map.pat_syntax(definition).unwrap(); let root = src.file_syntax(db);
4218 LocalSource {
4219 local: self,
4220 source: src.map(|ast| match ast.to_node(&root) {
4221 Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
4222 _ => unreachable!("local with non ident-pattern"),
4223 }),
4224 }
4225 })
4226 .unwrap()
4227 }
4228}
4229
4230impl PartialOrd for Local {
4231 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
4232 Some(self.cmp(other))
4233 }
4234}
4235
4236impl Ord for Local {
4237 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
4238 self.binding_id.cmp(&other.binding_id)
4239 }
4240}
4241
4242#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4243pub struct DeriveHelper {
4244 pub(crate) derive: MacroId,
4245 pub(crate) idx: u32,
4246}
4247
4248impl DeriveHelper {
4249 pub fn derive(&self) -> Macro {
4250 Macro { id: self.derive }
4251 }
4252
4253 pub fn name(&self, db: &dyn HirDatabase) -> Name {
4254 AttrFlags::derive_info(db, self.derive)
4255 .and_then(|it| it.helpers.get(self.idx as usize))
4256 .map(|helper| Name::new_symbol_root(helper.clone()))
4257 .unwrap_or_else(Name::missing)
4258 }
4259}
4260
4261#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4262pub struct BuiltinAttr {
4263 idx: u32,
4264}
4265
4266impl BuiltinAttr {
4267 fn builtin(name: &str) -> Option<Self> {
4268 hir_expand::inert_attr_macro::find_builtin_attr_idx(&Symbol::intern(name))
4269 .map(|idx| BuiltinAttr { idx: idx as u32 })
4270 }
4271
4272 pub fn name(&self) -> Name {
4273 Name::new_symbol_root(Symbol::intern(
4274 hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].name,
4275 ))
4276 }
4277
4278 pub fn template(&self) -> Option<AttributeTemplate> {
4279 Some(hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].template)
4280 }
4281}
4282
4283#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4284pub struct ToolModule {
4285 krate: base_db::Crate,
4286 idx: u32,
4287}
4288
4289impl ToolModule {
4290 pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
4291 let krate = krate.id;
4292 let idx =
4293 crate_def_map(db, krate).registered_tools().iter().position(|it| it.as_str() == name)?
4294 as u32;
4295 Some(ToolModule { krate, idx })
4296 }
4297
4298 pub fn name(&self, db: &dyn HirDatabase) -> Name {
4299 Name::new_symbol_root(
4300 crate_def_map(db, self.krate).registered_tools()[self.idx as usize].clone(),
4301 )
4302 }
4303
4304 pub fn krate(&self) -> Crate {
4305 Crate { id: self.krate }
4306 }
4307}
4308
4309#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4310pub struct Label {
4311 pub(crate) parent: ExpressionStoreOwnerId,
4312 pub(crate) label_id: LabelId,
4313}
4314
4315impl Label {
4316 pub fn module(self, db: &dyn HirDatabase) -> Module {
4317 self.parent(db).module(db)
4318 }
4319
4320 pub fn parent(self, _db: &dyn HirDatabase) -> ExpressionStoreOwner {
4321 self.parent.into()
4322 }
4323
4324 pub fn name(self, db: &dyn HirDatabase) -> Name {
4325 ExpressionStore::of(db, self.parent)[self.label_id].name.clone()
4326 }
4327}
4328
4329#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4330pub enum GenericParam {
4331 TypeParam(TypeParam),
4332 ConstParam(ConstParam),
4333 LifetimeParam(LifetimeParam),
4334}
4335impl_from!(TypeParam, ConstParam, LifetimeParam for GenericParam);
4336
4337impl GenericParam {
4338 pub fn module(self, db: &dyn HirDatabase) -> Module {
4339 match self {
4340 GenericParam::TypeParam(it) => it.module(db),
4341 GenericParam::ConstParam(it) => it.module(db),
4342 GenericParam::LifetimeParam(it) => it.module(db),
4343 }
4344 }
4345
4346 pub fn name(self, db: &dyn HirDatabase) -> Name {
4347 match self {
4348 GenericParam::TypeParam(it) => it.name(db),
4349 GenericParam::ConstParam(it) => it.name(db),
4350 GenericParam::LifetimeParam(it) => it.name(db),
4351 }
4352 }
4353
4354 pub fn parent(self) -> GenericDef {
4355 match self {
4356 GenericParam::TypeParam(it) => it.id.parent().into(),
4357 GenericParam::ConstParam(it) => it.id.parent().into(),
4358 GenericParam::LifetimeParam(it) => it.id.parent.into(),
4359 }
4360 }
4361
4362 pub fn variance(self, db: &dyn HirDatabase) -> Option<Variance> {
4363 let parent = match self {
4364 GenericParam::TypeParam(it) => it.id.parent(),
4365 GenericParam::ConstParam(_) => return None,
4367 GenericParam::LifetimeParam(it) => it.id.parent,
4368 };
4369 let index = match self {
4370 GenericParam::TypeParam(it) => hir_ty::type_or_const_param_idx(db, it.id.into()),
4371 GenericParam::ConstParam(_) => return None,
4372 GenericParam::LifetimeParam(it) => hir_ty::lifetime_param_idx(db, it.id),
4373 };
4374 db.variances_of(parent).get(index as usize).map(Into::into)
4375 }
4376}
4377
4378#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4379pub enum Variance {
4380 Bivariant,
4381 Covariant,
4382 Contravariant,
4383 Invariant,
4384}
4385
4386impl From<rustc_type_ir::Variance> for Variance {
4387 #[inline]
4388 fn from(value: rustc_type_ir::Variance) -> Self {
4389 match value {
4390 rustc_type_ir::Variance::Covariant => Variance::Covariant,
4391 rustc_type_ir::Variance::Invariant => Variance::Invariant,
4392 rustc_type_ir::Variance::Contravariant => Variance::Contravariant,
4393 rustc_type_ir::Variance::Bivariant => Variance::Bivariant,
4394 }
4395 }
4396}
4397
4398impl fmt::Display for Variance {
4399 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4400 let description = match self {
4401 Variance::Bivariant => "bivariant",
4402 Variance::Covariant => "covariant",
4403 Variance::Contravariant => "contravariant",
4404 Variance::Invariant => "invariant",
4405 };
4406 f.pad(description)
4407 }
4408}
4409
4410#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4411pub struct TypeParam {
4412 pub(crate) id: TypeParamId,
4413}
4414
4415impl TypeParam {
4416 pub fn merge(self) -> TypeOrConstParam {
4417 TypeOrConstParam { id: self.id.into() }
4418 }
4419
4420 pub fn name(self, db: &dyn HirDatabase) -> Name {
4421 self.merge().name(db)
4422 }
4423
4424 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
4425 self.id.parent().into()
4426 }
4427
4428 pub fn module(self, db: &dyn HirDatabase) -> Module {
4429 self.id.parent().module(db).into()
4430 }
4431
4432 pub fn is_implicit(self, db: &dyn HirDatabase) -> bool {
4435 let params = GenericParams::of(db, self.id.parent());
4436 let data = ¶ms[self.id.local_id()];
4437 match data.type_param().unwrap().provenance {
4438 TypeParamProvenance::TypeParamList => false,
4439 TypeParamProvenance::TraitSelf | TypeParamProvenance::ArgumentImplTrait => true,
4440 }
4441 }
4442
4443 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
4444 let interner = DbInterner::new_no_crate(db);
4445 let index = hir_ty::type_or_const_param_idx(db, self.id.into());
4446 let ty = Ty::new_param(interner, self.id, index);
4447 Type::new(self.id.parent(), ty)
4448 }
4449
4450 pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
4454 let self_ty = self.ty(db).ty.instantiate_identity().skip_norm_wip();
4455 GenericPredicates::query_explicit(db, self.id.parent())
4456 .iter_identity()
4457 .filter_map(|pred| match &pred.kind().skip_binder() {
4458 ClauseKind::Trait(trait_ref) if trait_ref.self_ty() == self_ty => {
4459 Some(Trait::from(trait_ref.def_id().0))
4460 }
4461 _ => None,
4462 })
4463 .collect()
4464 }
4465
4466 pub fn default(self, db: &dyn HirDatabase) -> Option<Type<'_>> {
4467 let ty = generic_arg_from_param(db, self.id.into())?;
4468 match ty.kind() {
4469 rustc_type_ir::GenericArgKind::Type(it) if !it.is_ty_error() => {
4470 Some(Type::new(self.id.parent(), it))
4471 }
4472 _ => None,
4473 }
4474 }
4475
4476 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
4477 self.attrs(db).is_unstable()
4478 }
4479}
4480
4481#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4482pub struct LifetimeParam {
4483 pub(crate) id: LifetimeParamId,
4484}
4485
4486impl LifetimeParam {
4487 pub fn name(self, db: &dyn HirDatabase) -> Name {
4488 let params = GenericParams::of(db, self.id.parent);
4489 params[self.id.local_id].name.clone()
4490 }
4491
4492 pub fn module(self, db: &dyn HirDatabase) -> Module {
4493 self.id.parent.module(db).into()
4494 }
4495
4496 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
4497 self.id.parent.into()
4498 }
4499}
4500
4501#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4502pub struct ConstParam {
4503 pub(crate) id: ConstParamId,
4504}
4505
4506impl ConstParam {
4507 pub fn merge(self) -> TypeOrConstParam {
4508 TypeOrConstParam { id: self.id.into() }
4509 }
4510
4511 pub fn name(self, db: &dyn HirDatabase) -> Name {
4512 let params = GenericParams::of(db, self.id.parent());
4513 match params[self.id.local_id()].name() {
4514 Some(it) => it.clone(),
4515 None => {
4516 never!();
4517 Name::missing()
4518 }
4519 }
4520 }
4521
4522 pub fn module(self, db: &dyn HirDatabase) -> Module {
4523 self.id.parent().module(db).into()
4524 }
4525
4526 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
4527 self.id.parent().into()
4528 }
4529
4530 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
4531 Type::new(self.id.parent(), db.const_param_ty(self.id))
4532 }
4533
4534 pub fn default(self, db: &dyn HirDatabase, display_target: DisplayTarget) -> Option<String> {
4535 let arg = generic_arg_from_param(db, self.id.into())?;
4536 Some(arg.display(db, display_target).to_string())
4537 }
4538
4539 pub fn default_source_code(
4540 self,
4541 db: &dyn HirDatabase,
4542 target_module: Module,
4543 ) -> Option<ast::ConstArg> {
4544 let arg = generic_arg_from_param(db, self.id.into())?;
4545 known_const_to_ast(arg.konst()?, db, target_module.id)
4546 }
4547}
4548
4549fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<GenericArg<'_>> {
4550 let local_idx = hir_ty::type_or_const_param_idx(db, id);
4551 let defaults = db.generic_defaults(id.parent);
4552 let ty = defaults.get(local_idx as usize)?;
4553 Some(ty.instantiate_identity().skip_norm_wip())
4555}
4556
4557#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4558pub struct TypeOrConstParam {
4559 pub(crate) id: TypeOrConstParamId,
4560}
4561
4562impl TypeOrConstParam {
4563 pub fn name(self, db: &dyn HirDatabase) -> Name {
4564 let params = GenericParams::of(db, self.id.parent);
4565 match params[self.id.local_id].name() {
4566 Some(n) => n.clone(),
4567 _ => Name::missing(),
4568 }
4569 }
4570
4571 pub fn module(self, db: &dyn HirDatabase) -> Module {
4572 self.id.parent.module(db).into()
4573 }
4574
4575 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
4576 self.id.parent.into()
4577 }
4578
4579 pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
4580 let params = GenericParams::of(db, self.id.parent);
4581 match ¶ms[self.id.local_id] {
4582 TypeOrConstParamData::TypeParamData(_) => {
4583 Either::Right(TypeParam { id: TypeParamId::from_unchecked(self.id) })
4584 }
4585 TypeOrConstParamData::ConstParamData(_) => {
4586 Either::Left(ConstParam { id: ConstParamId::from_unchecked(self.id) })
4587 }
4588 }
4589 }
4590
4591 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
4592 match self.split(db) {
4593 Either::Left(it) => it.ty(db),
4594 Either::Right(it) => it.ty(db),
4595 }
4596 }
4597
4598 pub fn as_type_param(self, db: &dyn HirDatabase) -> Option<TypeParam> {
4599 let params = GenericParams::of(db, self.id.parent);
4600 match ¶ms[self.id.local_id] {
4601 TypeOrConstParamData::TypeParamData(_) => {
4602 Some(TypeParam { id: TypeParamId::from_unchecked(self.id) })
4603 }
4604 TypeOrConstParamData::ConstParamData(_) => None,
4605 }
4606 }
4607
4608 pub fn as_const_param(self, db: &dyn HirDatabase) -> Option<ConstParam> {
4609 let params = GenericParams::of(db, self.id.parent);
4610 match ¶ms[self.id.local_id] {
4611 TypeOrConstParamData::TypeParamData(_) => None,
4612 TypeOrConstParamData::ConstParamData(_) => {
4613 Some(ConstParam { id: ConstParamId::from_unchecked(self.id) })
4614 }
4615 }
4616 }
4617}
4618
4619#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4620pub struct Impl {
4621 pub(crate) id: AnyImplId,
4622}
4623
4624impl Impl {
4625 pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<Impl> {
4626 let mut result = Vec::new();
4627 extend_with_def_map(db, crate_def_map(db, krate.id), &mut result);
4628 return result;
4629
4630 fn extend_with_def_map(db: &dyn HirDatabase, def_map: &DefMap, result: &mut Vec<Impl>) {
4631 for (_, module) in def_map.modules() {
4632 result.extend(module.scope.impls().map(Impl::from));
4633 result.extend(module.scope.builtin_derive_impls().map(Impl::from));
4634
4635 for unnamed_const in module.scope.unnamed_consts() {
4636 for (_, block_def_map) in Body::of(db, unnamed_const.into()).blocks(db) {
4637 extend_with_def_map(db, block_def_map, result);
4638 }
4639 }
4640 }
4641 }
4642 }
4643
4644 pub fn all_in_module(db: &dyn HirDatabase, module: Module) -> Vec<Impl> {
4645 module.impl_defs(db)
4646 }
4647
4648 pub fn all_for_type<'db>(db: &'db dyn HirDatabase, ty: Type<'db>) -> Vec<Impl> {
4654 let mut result = Vec::new();
4655 let interner = DbInterner::new_no_crate(db);
4656 let Some(simplified_ty) = fast_reject::simplify_type(
4657 interner,
4658 ty.ty.skip_binder(),
4659 fast_reject::TreatParams::AsRigid,
4660 ) else {
4661 return Vec::new();
4662 };
4663 let mut extend_with_impls = |impls: Either<&[ImplId], &[BuiltinDeriveImplId]>| match impls {
4664 Either::Left(impls) => result.extend(impls.iter().copied().map(Impl::from)),
4665 Either::Right(impls) => result.extend(impls.iter().copied().map(Impl::from)),
4666 };
4667 method_resolution::with_incoherent_inherent_impls(
4668 db,
4669 ty.krate(db),
4670 &simplified_ty,
4671 |impls| extend_with_impls(Either::Left(impls)),
4672 );
4673 if let Some(module) = method_resolution::simplified_type_module(db, &simplified_ty) {
4674 InherentImpls::for_each_crate_and_block(
4675 db,
4676 module.krate(db),
4677 module.block(db),
4678 &mut |impls| extend_with_impls(Either::Left(impls.for_self_ty(&simplified_ty))),
4679 );
4680 iter::successors(module.block(db), |block| block.loc(db).module.block(db))
4681 .filter_map(|block| TraitImpls::for_block(db, block).as_deref())
4682 .for_each(|impls| impls.for_self_ty(&simplified_ty, &mut extend_with_impls));
4683 for &krate in &*all_crates(db) {
4684 TraitImpls::for_crate(db, krate)
4685 .for_self_ty(&simplified_ty, &mut extend_with_impls);
4686 }
4687 } else {
4688 for &krate in &*all_crates(db) {
4689 TraitImpls::for_crate(db, krate)
4690 .for_self_ty(&simplified_ty, &mut extend_with_impls);
4691 }
4692 }
4693 result
4694 }
4695
4696 pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
4697 let module = trait_.module(db).id;
4698 let mut all = Vec::new();
4699 let mut handle_impls = |impls: &TraitImpls| {
4700 impls.for_trait(trait_.id, |impls| match impls {
4701 Either::Left(impls) => all.extend(impls.iter().copied().map(Impl::from)),
4702 Either::Right(impls) => all.extend(impls.iter().copied().map(Impl::from)),
4703 });
4704 };
4705 for krate in module.krate(db).transitive_rev_deps(db) {
4706 handle_impls(TraitImpls::for_crate(db, krate));
4707 }
4708 if let Some(block) = module.block(db)
4709 && let Some(impls) = TraitImpls::for_block(db, block)
4710 {
4711 handle_impls(impls);
4712 }
4713 all
4714 }
4715
4716 pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> {
4717 match self.id {
4718 AnyImplId::ImplId(id) => {
4719 let trait_ref = db.impl_trait(id)?;
4720 let id = trait_ref.skip_binder().def_id;
4721 Some(Trait { id: id.0 })
4722 }
4723 AnyImplId::BuiltinDeriveImplId(id) => {
4724 let loc = id.loc(db);
4725 let lang_items = hir_def::lang_item::lang_items(db, loc.adt.module(db).krate(db));
4726 loc.trait_.get_id(lang_items).map(Trait::from)
4727 }
4728 }
4729 }
4730
4731 pub fn trait_ref(self, db: &dyn HirDatabase) -> Option<TraitRef<'_>> {
4732 match self.id {
4733 AnyImplId::ImplId(id) => {
4734 let trait_ref = db.impl_trait(id)?.instantiate_identity().skip_norm_wip();
4735 Some(TraitRef::new(id.into(), trait_ref))
4736 }
4737 AnyImplId::BuiltinDeriveImplId(id) => {
4738 let loc = id.loc(db);
4739 let krate = loc.module(db).krate(db);
4740 let interner = DbInterner::new_with(db, krate);
4741 let trait_ref = hir_ty::builtin_derive::impl_trait(interner, id)
4742 .instantiate_identity()
4743 .skip_norm_wip();
4744 Some(TraitRef { owner: TypeOwnerId::BuiltinDeriveImplId(id), trait_ref })
4745 }
4746 }
4747 }
4748
4749 pub fn self_ty(self, db: &dyn HirDatabase) -> Type<'_> {
4750 match self.id {
4751 AnyImplId::ImplId(id) => {
4752 let ty = db.impl_self_ty(id).instantiate_identity().skip_norm_wip();
4753 Type::new(id.into(), ty)
4754 }
4755 AnyImplId::BuiltinDeriveImplId(id) => {
4756 let loc = id.loc(db);
4757 let krate = loc.module(db).krate(db);
4758 let interner = DbInterner::new_with(db, krate);
4759 let ty =
4760 hir_ty::builtin_derive::impl_trait(interner, id).map_bound(|it| it.self_ty());
4761 Type { owner: TypeOwnerId::BuiltinDeriveImplId(id), ty }
4762 }
4763 }
4764 }
4765
4766 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
4767 match self.id {
4768 AnyImplId::ImplId(id) => {
4769 id.impl_items(db).items.iter().map(|&(_, it)| it.into()).collect()
4770 }
4771 AnyImplId::BuiltinDeriveImplId(impl_) => impl_
4772 .loc(db)
4773 .trait_
4774 .all_methods()
4775 .iter()
4776 .map(|&method| {
4777 AssocItem::Function(Function {
4778 id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ },
4779 })
4780 })
4781 .collect(),
4782 }
4783 }
4784
4785 pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
4786 match self.id {
4787 AnyImplId::ImplId(id) => ImplSignature::of(db, id).flags.contains(ImplFlags::NEGATIVE),
4788 AnyImplId::BuiltinDeriveImplId(_) => false,
4789 }
4790 }
4791
4792 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
4793 match self.id {
4794 AnyImplId::ImplId(id) => ImplSignature::of(db, id).flags.contains(ImplFlags::UNSAFE),
4795 AnyImplId::BuiltinDeriveImplId(_) => false,
4796 }
4797 }
4798
4799 pub fn module(self, db: &dyn HirDatabase) -> Module {
4800 match self.id {
4801 AnyImplId::ImplId(id) => id.module(db).into(),
4802 AnyImplId::BuiltinDeriveImplId(id) => id.module(db).into(),
4803 }
4804 }
4805
4806 pub fn check_orphan_rules(self, db: &dyn HirDatabase) -> bool {
4807 match self.id {
4808 AnyImplId::ImplId(id) => check_orphan_rules(db, id),
4809 AnyImplId::BuiltinDeriveImplId(_) => true,
4810 }
4811 }
4812
4813 fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
4814 match self.id {
4815 AnyImplId::ImplId(id) => id.impl_items(db).macro_calls.to_vec().into_boxed_slice(),
4816 AnyImplId::BuiltinDeriveImplId(_) => Box::default(),
4817 }
4818 }
4819}
4820
4821#[derive(Clone, PartialEq, Eq, Debug, Hash)]
4822pub struct TraitRef<'db> {
4823 owner: TypeOwnerId,
4824 trait_ref: hir_ty::next_solver::TraitRef<'db>,
4825}
4826
4827impl<'db> TraitRef<'db> {
4828 fn new(owner: GenericDefId, trait_ref: hir_ty::next_solver::TraitRef<'db>) -> Self {
4829 Self { owner: TypeOwnerId::GenericDefId(owner), trait_ref }
4830 }
4831
4832 pub fn trait_(&self) -> Trait {
4833 Trait { id: self.trait_ref.def_id.0 }
4834 }
4835
4836 pub fn self_ty(&self) -> Type<'_> {
4837 let ty = self.trait_ref.self_ty();
4838 Type { owner: self.owner, ty: EarlyBinder::bind(ty) }
4839 }
4840
4841 pub fn get_type_argument(&self, idx: usize) -> Option<Type<'db>> {
4844 self.trait_ref
4845 .args
4846 .as_slice()
4847 .get(idx)
4848 .and_then(|arg| arg.ty())
4849 .map(|ty| Type { owner: self.owner, ty: EarlyBinder::bind(ty) })
4850 }
4851}
4852
4853#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4854enum AnyClosureId {
4855 ClosureId(InternedClosureId),
4856 CoroutineClosureId(InternedCoroutineClosureId),
4857}
4858
4859#[derive(Clone, Debug, PartialEq, Eq, Hash)]
4860pub struct Closure<'db> {
4861 owner: TypeOwnerId,
4862 id: AnyClosureId,
4863 subst: GenericArgs<'db>,
4864}
4865
4866impl<'db> Closure<'db> {
4867 fn as_ty(&self, db: &'db dyn HirDatabase) -> Ty<'db> {
4868 let interner = DbInterner::new_no_crate(db);
4869 match self.id {
4870 AnyClosureId::ClosureId(id) => Ty::new_closure(interner, id.into(), self.subst),
4871 AnyClosureId::CoroutineClosureId(id) => {
4872 Ty::new_coroutine_closure(interner, id.into(), self.subst)
4873 }
4874 }
4875 }
4876
4877 pub fn display_with_id(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
4878 self.as_ty(db)
4879 .display(db, display_target)
4880 .with_closure_style(ClosureStyle::ClosureWithId)
4881 .to_string()
4882 }
4883
4884 pub fn display_with_impl(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
4885 self.as_ty(db)
4886 .display(db, display_target)
4887 .with_closure_style(ClosureStyle::ImplFn)
4888 .to_string()
4889 }
4890
4891 pub fn captured_items(&self, db: &'db dyn HirDatabase) -> Vec<ClosureCapture<'db>> {
4892 let closure = match self.id {
4893 AnyClosureId::ClosureId(it) => it.loc(db),
4894 AnyClosureId::CoroutineClosureId(it) => it.loc(db),
4895 };
4896 let InternedClosure { owner: infer_owner, expr: closure, .. } = closure;
4897 let infer = InferenceResult::of(db, infer_owner);
4898 let owner = infer_owner.expression_store_owner(db);
4899 infer.closures_data[&closure]
4900 .min_captures
4901 .values()
4902 .flatten()
4903 .map(|capture| ClosureCapture { owner, infer_owner, closure, capture })
4904 .collect()
4905 }
4906
4907 pub fn fn_trait(&self, _db: &dyn HirDatabase) -> FnTrait {
4908 match self.id {
4909 AnyClosureId::ClosureId(_) => match self.subst.as_closure().kind() {
4910 rustc_type_ir::ClosureKind::Fn => FnTrait::Fn,
4911 rustc_type_ir::ClosureKind::FnMut => FnTrait::FnMut,
4912 rustc_type_ir::ClosureKind::FnOnce => FnTrait::FnOnce,
4913 },
4914 AnyClosureId::CoroutineClosureId(_) => match self.subst.as_coroutine_closure().kind() {
4915 rustc_type_ir::ClosureKind::Fn => FnTrait::AsyncFn,
4916 rustc_type_ir::ClosureKind::FnMut => FnTrait::AsyncFnMut,
4917 rustc_type_ir::ClosureKind::FnOnce => FnTrait::AsyncFnOnce,
4918 },
4919 }
4920 }
4921}
4922
4923#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4924pub enum FnTrait {
4925 FnOnce,
4926 FnMut,
4927 Fn,
4928
4929 AsyncFnOnce,
4930 AsyncFnMut,
4931 AsyncFn,
4932}
4933
4934impl From<traits::FnTrait> for FnTrait {
4935 fn from(value: traits::FnTrait) -> Self {
4936 match value {
4937 traits::FnTrait::FnOnce => FnTrait::FnOnce,
4938 traits::FnTrait::FnMut => FnTrait::FnMut,
4939 traits::FnTrait::Fn => FnTrait::Fn,
4940 traits::FnTrait::AsyncFnOnce => FnTrait::AsyncFnOnce,
4941 traits::FnTrait::AsyncFnMut => FnTrait::AsyncFnMut,
4942 traits::FnTrait::AsyncFn => FnTrait::AsyncFn,
4943 }
4944 }
4945}
4946
4947impl fmt::Display for FnTrait {
4948 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4949 match self {
4950 FnTrait::FnOnce => write!(f, "FnOnce"),
4951 FnTrait::FnMut => write!(f, "FnMut"),
4952 FnTrait::Fn => write!(f, "Fn"),
4953 FnTrait::AsyncFnOnce => write!(f, "AsyncFnOnce"),
4954 FnTrait::AsyncFnMut => write!(f, "AsyncFnMut"),
4955 FnTrait::AsyncFn => write!(f, "AsyncFn"),
4956 }
4957 }
4958}
4959
4960impl FnTrait {
4961 pub const fn function_name(&self) -> &'static str {
4962 match self {
4963 FnTrait::FnOnce => "call_once",
4964 FnTrait::FnMut => "call_mut",
4965 FnTrait::Fn => "call",
4966 FnTrait::AsyncFnOnce => "async_call_once",
4967 FnTrait::AsyncFnMut => "async_call_mut",
4968 FnTrait::AsyncFn => "async_call",
4969 }
4970 }
4971
4972 pub fn lang_item(self) -> LangItem {
4973 match self {
4974 FnTrait::FnOnce => LangItem::FnOnce,
4975 FnTrait::FnMut => LangItem::FnMut,
4976 FnTrait::Fn => LangItem::Fn,
4977 FnTrait::AsyncFnOnce => LangItem::AsyncFnOnce,
4978 FnTrait::AsyncFnMut => LangItem::AsyncFnMut,
4979 FnTrait::AsyncFn => LangItem::AsyncFn,
4980 }
4981 }
4982
4983 pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option<Trait> {
4984 Trait::lang(db, krate, self.lang_item())
4985 }
4986}
4987
4988#[derive(Clone, Debug, PartialEq, Eq)]
4989pub struct ClosureCapture<'db> {
4990 owner: ExpressionStoreOwnerId,
4991 infer_owner: InferBodyId,
4992 closure: ExprId,
4993 capture: &'db hir_ty::closure_analysis::CapturedPlace,
4994}
4995
4996impl<'db> ClosureCapture<'db> {
4997 pub fn local(&self) -> Local {
4998 Local {
4999 parent: self.owner,
5000 parent_infer: self.infer_owner,
5001 binding_id: self.capture.captured_local(),
5002 }
5003 }
5004
5005 pub fn has_field_projections(&self) -> bool {
5007 self.capture
5008 .place
5009 .projections
5010 .iter()
5011 .any(|proj| matches!(proj.kind, hir_ty::closure_analysis::ProjectionKind::Field { .. }))
5012 }
5013
5014 pub fn usages(&self) -> CaptureUsages<'db> {
5015 CaptureUsages { parent: self.owner, sources: &self.capture.info.sources }
5016 }
5017
5018 pub fn kind(&self) -> CaptureKind {
5019 match self.capture.info.capture_kind {
5020 hir_ty::closure_analysis::UpvarCapture::ByValue => CaptureKind::Move,
5021 hir_ty::closure_analysis::UpvarCapture::ByUse => CaptureKind::SharedRef, hir_ty::closure_analysis::UpvarCapture::ByRef(
5023 hir_ty::closure_analysis::BorrowKind::Immutable,
5024 ) => CaptureKind::SharedRef,
5025 hir_ty::closure_analysis::UpvarCapture::ByRef(
5026 hir_ty::closure_analysis::BorrowKind::UniqueImmutable,
5027 ) => CaptureKind::UniqueSharedRef,
5028 hir_ty::closure_analysis::UpvarCapture::ByRef(
5029 hir_ty::closure_analysis::BorrowKind::Mutable,
5030 ) => CaptureKind::MutableRef,
5031 }
5032 }
5033
5034 pub fn place_to_name(&self, db: &dyn HirDatabase, edition: Edition) -> String {
5036 let mut result = self.local().name(db).display(db, edition).to_string();
5037 for (i, proj) in self.capture.place.projections.iter().enumerate() {
5038 match proj.kind {
5039 hir_ty::closure_analysis::ProjectionKind::Deref => {}
5040 hir_ty::closure_analysis::ProjectionKind::Field { field_idx, variant_idx } => {
5041 let ty = self.capture.place.ty_before_projection(i);
5042 match ty.kind() {
5043 TyKind::Tuple(_) => format_to!(result, "_{field_idx}"),
5044 TyKind::Adt(adt_def, _) => {
5045 let variant = match adt_def.def_id() {
5046 AdtId::StructId(id) => VariantId::from(id),
5047 AdtId::UnionId(id) => id.into(),
5048 AdtId::EnumId(id) => {
5049 id.enum_variants(db).variants[variant_idx as usize].0.into()
5050 }
5051 };
5052 let field = &variant.fields(db).fields()
5053 [LocalFieldId::from_raw(la_arena::RawIdx::from_u32(field_idx))];
5054 format_to!(result, "_{}", field.name.display(db, edition));
5055 }
5056 _ => never!("mismatching projection type"),
5057 }
5058 }
5059 _ => never!("unexpected projection kind"),
5060 }
5061 }
5062 result
5063 }
5064
5065 pub fn display_place_source_code(&self, db: &dyn HirDatabase, edition: Edition) -> String {
5066 let mut result = self.local().name(db).display(db, edition).to_string();
5067 let mut last_derefs = 0;
5069 for (i, proj) in self.capture.place.projections.iter().enumerate() {
5070 match proj.kind {
5071 hir_ty::closure_analysis::ProjectionKind::Deref => last_derefs += 1,
5072 hir_ty::closure_analysis::ProjectionKind::Field { field_idx, variant_idx } => {
5073 last_derefs = 0;
5074
5075 let ty = self.capture.place.ty_before_projection(i);
5076 match ty.kind() {
5077 TyKind::Tuple(_) => format_to!(result, ".{field_idx}"),
5078 TyKind::Adt(adt_def, _) => {
5079 let variant = match adt_def.def_id() {
5080 AdtId::StructId(id) => VariantId::from(id),
5081 AdtId::UnionId(id) => id.into(),
5082 AdtId::EnumId(id) => {
5083 id.enum_variants(db).variants[variant_idx as usize].0.into()
5085 }
5086 };
5087 let field = &variant.fields(db).fields()
5088 [LocalFieldId::from_raw(la_arena::RawIdx::from_u32(field_idx))];
5089 format_to!(result, ".{}", field.name.display(db, edition));
5090 }
5091 _ => never!("mismatching projection type"),
5092 }
5093 }
5094 _ => never!("unexpected projection kind"),
5095 }
5096 }
5097 result.insert_str(0, &"*".repeat(last_derefs));
5098 result
5099 }
5100
5101 pub fn ty(&self, db: &'db dyn HirDatabase) -> Type<'db> {
5102 Type::new_body(db, self.owner, self.capture.place.ty())
5103 }
5104
5105 pub fn captured_ty(&self, db: &'db dyn HirDatabase) -> Type<'db> {
5108 Type::new_body(db, self.owner, self.capture.captured_ty(db))
5109 }
5110}
5111
5112#[derive(Clone, Copy, PartialEq, Eq)]
5113pub enum CaptureKind {
5114 SharedRef,
5115 UniqueSharedRef,
5116 MutableRef,
5117 Move,
5118}
5119
5120#[derive(Debug, Clone)]
5121pub struct CaptureUsages<'db> {
5122 parent: ExpressionStoreOwnerId,
5123 sources: &'db [hir_ty::closure_analysis::CaptureSourceStack],
5124}
5125
5126impl CaptureUsages<'_> {
5127 fn is_ref(store: &ExpressionStore, id: ExprOrPatId) -> bool {
5128 match id {
5129 ExprOrPatId::ExprId(expr) => matches!(store[expr], Expr::Ref { .. }),
5130 ExprOrPatId::PatId(pat) => match store[pat] {
5132 Pat::Bind { id: binding, .. } => matches!(
5133 store[binding].mode,
5134 BindingAnnotation::Ref | BindingAnnotation::RefMut
5135 ),
5136 _ => false,
5137 },
5138 }
5139 }
5140
5141 pub fn sources(&self, db: &dyn HirDatabase) -> Vec<CaptureUsageSource> {
5142 let (store, source_map) = ExpressionStore::with_source_map(db, self.parent);
5143 let mut result = Vec::with_capacity(self.sources.len());
5144 for source in self.sources {
5145 let source = source.final_source();
5146 let is_ref = Self::is_ref(store, source);
5147 match source {
5148 ExprOrPatId::ExprId(expr) => {
5149 if let Ok(expr) = source_map.expr_syntax(expr) {
5150 result.push(CaptureUsageSource { is_ref, source: expr })
5151 }
5152 }
5153 ExprOrPatId::PatId(pat) => {
5154 if let Ok(pat) = source_map.pat_syntax(pat) {
5155 result.push(CaptureUsageSource { is_ref, source: pat });
5156 }
5157 }
5158 }
5159 }
5160 result
5161 }
5162}
5163
5164#[derive(Debug)]
5165pub struct CaptureUsageSource {
5166 is_ref: bool,
5167 source: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
5168}
5169
5170impl CaptureUsageSource {
5171 pub fn source(&self) -> AstPtr<Either<ast::Expr, ast::Pat>> {
5172 self.source.value
5173 }
5174
5175 pub fn file_id(&self) -> HirFileId {
5176 self.source.file_id
5177 }
5178
5179 pub fn is_ref(&self) -> bool {
5180 self.is_ref
5181 }
5182}
5183
5184#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
5185enum TypeOwnerId {
5186 GenericDefId(GenericDefId),
5187 BuiltinDeriveImplId(BuiltinDeriveImplId),
5188 AnonConstId(AnonConstId),
5189 NoParams(base_db::Crate),
5191}
5192impl_from!(GenericDefId, BuiltinDeriveImplId, AnonConstId for TypeOwnerId);
5193
5194impl TypeOwnerId {
5195 fn unify(self, other: Self) -> Option<Self> {
5196 match (self, other) {
5197 (TypeOwnerId::NoParams(_), owner) => Some(owner),
5198 (owner, TypeOwnerId::NoParams(_)) => Some(owner),
5199 (_, _) => {
5200 if self == other {
5201 Some(self)
5202 } else {
5203 None
5204 }
5205 }
5206 }
5207 }
5208
5209 #[track_caller]
5210 fn must_unify(self, other: Self) -> Self {
5211 self.unify(other).expect("failed to unify type owners")
5212 }
5213
5214 fn can_rebase_into(
5215 self,
5216 db: &dyn HirDatabase,
5217 rebase_into: Self,
5218 self_ty: EarlyBinder<'_, Ty<'_>>,
5219 ) -> bool {
5220 if self == rebase_into || !self_ty.skip_binder().has_param() {
5221 return true;
5222 }
5223 let self_def = match self {
5224 TypeOwnerId::GenericDefId(def) => def,
5225 TypeOwnerId::BuiltinDeriveImplId(_) | TypeOwnerId::AnonConstId(_) => return false,
5226 TypeOwnerId::NoParams(_) => return true,
5227 };
5228 let self_def = match self_def {
5229 GenericDefId::ImplId(def) => ItemContainerId::ImplId(def),
5230 GenericDefId::TraitId(def) => ItemContainerId::TraitId(def),
5231 GenericDefId::AdtId(_)
5232 | GenericDefId::ConstId(_)
5233 | GenericDefId::FunctionId(_)
5234 | GenericDefId::StaticId(_)
5235 | GenericDefId::TypeAliasId(_) => return false,
5236 };
5237 let rebase_into_def = match rebase_into {
5238 TypeOwnerId::GenericDefId(def) => def,
5239 TypeOwnerId::BuiltinDeriveImplId(_)
5240 | TypeOwnerId::AnonConstId(_)
5241 | TypeOwnerId::NoParams(_) => return false,
5242 };
5243 let rebase_into_parent = match rebase_into_def {
5244 GenericDefId::ConstId(def) => def.loc(db).container,
5245 GenericDefId::FunctionId(def) => def.loc(db).container,
5246 GenericDefId::TypeAliasId(def) => def.loc(db).container,
5247 GenericDefId::AdtId(_)
5248 | GenericDefId::ImplId(_)
5249 | GenericDefId::StaticId(_)
5250 | GenericDefId::TraitId(_) => return false,
5251 };
5252 self_def == rebase_into_parent
5253 }
5254}
5255
5256#[derive(Clone, Debug)]
5259pub struct Type<'db> {
5260 owner: TypeOwnerId,
5261 ty: EarlyBinder<'db, Ty<'db>>,
5262}
5263
5264impl<'db> std::hash::Hash for Type<'db> {
5265 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
5266 self.ty.hash(state);
5269 }
5270}
5271
5272impl<'db> PartialEq for Type<'db> {
5273 fn eq(&self, other: &Self) -> bool {
5274 if self.ty != other.ty {
5275 return false;
5276 }
5277 hir_ty::with_attached_db(|db| {
5278 self.owner.can_rebase_into(db, other.owner, self.ty)
5279 || other.owner.can_rebase_into(db, self.owner, other.ty)
5280 })
5281 }
5282}
5283
5284impl<'db> Eq for Type<'db> {}
5285
5286impl<'db> Type<'db> {
5287 fn new(owner: GenericDefId, ty: Ty<'db>) -> Self {
5288 Type { owner: TypeOwnerId::GenericDefId(owner), ty: EarlyBinder::bind(ty) }
5289 }
5290
5291 fn new_body(db: &dyn HirDatabase, owner: ExpressionStoreOwnerId, ty: Ty<'db>) -> Self {
5292 Self::new(owner.generic_def(db), ty)
5293 }
5294
5295 fn no_params(krate: base_db::Crate, ty: Ty<'db>) -> Self {
5296 Type { owner: TypeOwnerId::NoParams(krate), ty: EarlyBinder::bind(ty) }
5297 }
5298
5299 fn builtin_type_crate(db: &'db dyn HirDatabase) -> base_db::Crate {
5300 all_crates(db)[0]
5302 }
5303
5304 fn from_def(db: &'db dyn HirDatabase, def: impl Into<TyDefId>) -> Self {
5305 let def = def.into();
5306 let ty = db.ty(def);
5307 let owner = match def {
5308 TyDefId::AdtId(it) => TypeOwnerId::GenericDefId(GenericDefId::AdtId(it)),
5309 TyDefId::TypeAliasId(it) => TypeOwnerId::GenericDefId(GenericDefId::TypeAliasId(it)),
5310 TyDefId::BuiltinType(_) => TypeOwnerId::NoParams(Self::builtin_type_crate(db)),
5311 };
5312 Type { owner, ty }
5313 }
5314
5315 fn from_value_def(db: &'db dyn HirDatabase, def: impl Into<ValueTyDefId>) -> Self {
5316 let def = def.into();
5317 let Some(ty) = db.value_ty(def) else {
5318 return Type::unknown();
5319 };
5320 let def = match def {
5321 ValueTyDefId::ConstId(it) => GenericDefId::ConstId(it),
5322 ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it),
5323 ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)),
5324 ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)),
5325 ValueTyDefId::EnumVariantId(it) => {
5326 GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent))
5327 }
5328 ValueTyDefId::StaticId(it) => {
5329 return Type::no_params(hir_def::HasModule::krate(&it, db), ty.skip_binder());
5330 }
5331 };
5332 Type::new(def, ty.instantiate_identity().skip_norm_wip())
5333 }
5334
5335 pub fn instantiate_with_errors(&self) -> Self {
5337 let interner = DbInterner::conjure();
5338 let krate = self.krate(interner.db());
5339 let args = match self.owner {
5340 TypeOwnerId::GenericDefId(def) => GenericArgs::error_for_item(interner, def.into()),
5341 TypeOwnerId::BuiltinDeriveImplId(def) => {
5342 GenericArgs::error_for_item(interner, def.into())
5343 }
5344 TypeOwnerId::AnonConstId(def) => GenericArgs::error_for_item(interner, def.into()),
5345 TypeOwnerId::NoParams(_) => GenericArgs::empty(interner),
5346 };
5347 Type::no_params(krate, self.ty.instantiate(interner, args).skip_norm_wip())
5348 }
5349
5350 pub fn instantiate(&self, args: impl IntoIterator<Item: Borrow<Type<'db>>>) -> Type<'db> {
5352 let interner = DbInterner::conjure();
5353 let (args, owner) = match self.owner {
5354 TypeOwnerId::GenericDefId(def) => generic_args_from_tys(interner, def.into(), args),
5355 TypeOwnerId::BuiltinDeriveImplId(def) => {
5356 generic_args_from_tys(interner, def.into(), args)
5357 }
5358 TypeOwnerId::AnonConstId(def) => generic_args_from_tys(interner, def.into(), args),
5359 TypeOwnerId::NoParams(krate) => {
5360 (GenericArgs::empty(interner), TypeOwnerId::NoParams(krate))
5361 }
5362 };
5363 Type { owner, ty: EarlyBinder::bind(self.ty.instantiate(interner, args).skip_norm_wip()) }
5364 }
5365
5366 fn instantiate_many_with_infer(
5368 tys: impl IntoIterator<Item: Borrow<Type<'db>>>,
5369 infcx: &InferCtxt<'db>,
5370 ) -> impl Iterator<Item = Ty<'db>> {
5371 let mut var_for_param = FxHashMap::default();
5372 tys.into_iter().map(move |ty| {
5373 let ty = ty.borrow();
5374 let owner = match ty.owner {
5375 TypeOwnerId::GenericDefId(def) => def.into(),
5376 TypeOwnerId::BuiltinDeriveImplId(def) => def.into(),
5377 TypeOwnerId::AnonConstId(def) => def.into(),
5378 TypeOwnerId::NoParams(_) => return ty.ty.skip_binder(),
5379 };
5380 let args = GenericArgs::for_item(infcx.interner, owner, |_, param, _| {
5381 *var_for_param
5382 .entry(param)
5383 .or_insert_with(|| infcx.var_for_def(param, hir_ty::Span::Dummy))
5384 });
5385
5386 ty.ty.instantiate(infcx.interner, args).skip_norm_wip()
5387 })
5388 }
5389
5390 pub fn try_rebase_into(
5395 &self,
5396 db: &'db dyn HirDatabase,
5397 rebase_into: &Type<'db>,
5398 ) -> Option<Self> {
5399 if self.owner.can_rebase_into(db, rebase_into.owner, self.ty) {
5400 Some(Type { owner: rebase_into.owner, ty: self.ty })
5401 } else {
5402 None
5403 }
5404 }
5405
5406 pub fn rebase_into_or_error(
5409 &self,
5410 db: &'db dyn HirDatabase,
5411 rebase_into: &Type<'db>,
5412 ) -> Type<'db> {
5413 self.try_rebase_into(db, rebase_into).unwrap_or_else(|| self.instantiate_with_errors())
5414 }
5415
5416 pub fn try_rebase_into_owner(
5417 &self,
5418 db: &'db dyn HirDatabase,
5419 new_owner: GenericDef,
5420 ) -> Option<Self> {
5421 let new_owner = new_owner.id()?.into();
5422 if self.owner.can_rebase_into(db, new_owner, self.ty) {
5423 Some(Type { owner: new_owner, ty: self.ty })
5424 } else {
5425 None
5426 }
5427 }
5428
5429 pub fn rebase_into_owner_or_error(
5430 &self,
5431 db: &'db dyn HirDatabase,
5432 new_owner: GenericDef,
5433 ) -> Self {
5434 self.try_rebase_into_owner(db, new_owner).unwrap_or_else(|| self.instantiate_with_errors())
5435 }
5436
5437 pub fn unknown() -> Self {
5438 let interner = DbInterner::conjure();
5439 Type::no_params(
5440 Self::builtin_type_crate(interner.db()),
5441 Ty::new_error(interner, ErrorGuaranteed),
5442 )
5443 }
5444
5445 pub fn new_slice(db: &'db dyn HirDatabase, ty: Self) -> Self {
5446 let interner = DbInterner::new_no_crate(db);
5447 Type { owner: ty.owner, ty: ty.ty.map_bound(|ty| Ty::new_slice(interner, ty)) }
5448 }
5449
5450 pub fn new_tuple(
5451 db: &'db dyn HirDatabase,
5452 tys: impl IntoIterator<Item: Borrow<Type<'db>>>,
5453 ) -> Self {
5454 let interner = DbInterner::new_no_crate(db);
5455 let mut owner = None::<TypeOwnerId>;
5456 let ty = EarlyBinder::bind(Ty::new_tup_from_iter(
5457 interner,
5458 tys.into_iter().map(|ty| {
5459 let ty = ty.borrow();
5460
5461 match &mut owner {
5462 Some(owner) => *owner = owner.must_unify(ty.owner),
5463 None => owner = Some(ty.owner),
5464 }
5465
5466 ty.ty.skip_binder()
5467 }),
5468 ));
5469 let owner =
5470 owner.unwrap_or_else(|| TypeOwnerId::NoParams(Self::builtin_type_crate(interner.db())));
5471 Type { owner, ty }
5472 }
5473
5474 pub fn new_unit() -> Self {
5475 let interner = DbInterner::conjure();
5476 Type::no_params(Self::builtin_type_crate(interner.db()), Ty::new_unit(interner))
5477 }
5478
5479 pub fn is_unit(&self) -> bool {
5480 self.ty.skip_binder().is_unit()
5481 }
5482
5483 pub fn is_bool(&self) -> bool {
5484 matches!(self.ty.skip_binder().kind(), TyKind::Bool)
5485 }
5486
5487 pub fn is_str(&self) -> bool {
5488 matches!(self.ty.skip_binder().kind(), TyKind::Str)
5489 }
5490
5491 pub fn is_never(&self) -> bool {
5492 matches!(self.ty.skip_binder().kind(), TyKind::Never)
5493 }
5494
5495 pub fn is_mutable_reference(&self) -> bool {
5496 matches!(
5497 self.ty.skip_binder().kind(),
5498 TyKind::Ref(.., hir_ty::next_solver::Mutability::Mut)
5499 )
5500 }
5501
5502 pub fn is_reference(&self) -> bool {
5503 matches!(self.ty.skip_binder().kind(), TyKind::Ref(..))
5504 }
5505
5506 pub fn contains_reference(&self, db: &'db dyn HirDatabase) -> bool {
5507 let interner = DbInterner::new_no_crate(db);
5508 return self
5509 .ty
5510 .instantiate_identity()
5511 .skip_norm_wip()
5512 .visit_with(&mut Visitor { interner })
5513 .is_break();
5514
5515 fn is_phantom_data(db: &dyn HirDatabase, adt_id: AdtId) -> bool {
5516 match adt_id {
5517 AdtId::StructId(s) => {
5518 let flags = StructSignature::of(db, s).flags;
5519 flags.contains(StructFlags::IS_PHANTOM_DATA)
5520 }
5521 AdtId::UnionId(_) | AdtId::EnumId(_) => false,
5522 }
5523 }
5524
5525 struct Visitor<'db> {
5526 interner: DbInterner<'db>,
5527 }
5528
5529 impl<'db> TypeVisitor<DbInterner<'db>> for Visitor<'db> {
5530 type Result = ControlFlow<()>;
5531
5532 fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
5533 match ty.kind() {
5534 TyKind::Ref(..) => ControlFlow::Break(()),
5536
5537 TyKind::Adt(adt_def, args)
5539 if !is_phantom_data(self.interner.db(), adt_def.def_id()) =>
5540 {
5541 let _variant_id_to_fields = |id: VariantId| {
5542 let variant_data = &id.fields(self.interner.db());
5543 if variant_data.fields().is_empty() {
5544 vec![]
5545 } else {
5546 let field_types = self.interner.db().field_types(id);
5547 variant_data
5548 .fields()
5549 .iter()
5550 .map(|(idx, _)| {
5551 field_types[idx]
5552 .get()
5553 .instantiate(self.interner, args)
5554 .skip_norm_wip()
5555 })
5556 .filter(|it| !it.references_non_lt_error())
5557 .collect()
5558 }
5559 };
5560 let variant_id_to_fields = |_: VariantId| vec![];
5561
5562 let variants: Vec<Vec<Ty<'db>>> = match adt_def.def_id() {
5563 AdtId::StructId(id) => {
5564 vec![variant_id_to_fields(id.into())]
5565 }
5566 AdtId::EnumId(id) => id
5567 .enum_variants(self.interner.db())
5568 .variants
5569 .values()
5570 .map(|&(variant_id, _)| variant_id_to_fields(variant_id.into()))
5571 .collect(),
5572 AdtId::UnionId(id) => {
5573 vec![variant_id_to_fields(id.into())]
5574 }
5575 };
5576
5577 variants
5578 .into_iter()
5579 .flat_map(|variant| variant.into_iter())
5580 .try_for_each(|ty| ty.visit_with(self))?;
5581 args.visit_with(self)
5582 }
5583 _ => ty.super_visit_with(self),
5585 }
5586 }
5587 }
5588 }
5589
5590 pub fn as_reference(&self) -> Option<(Type<'db>, Mutability)> {
5591 let TyKind::Ref(_lt, ty, m) = self.ty.skip_binder().kind() else { return None };
5592 let m = Mutability::from_mutable(matches!(m, hir_ty::next_solver::Mutability::Mut));
5593 Some((self.derived(ty), m))
5594 }
5595
5596 pub fn as_reference_inner(&self) -> Option<Type<'db>> {
5597 self.as_reference().map(|(inner, _)| inner)
5598 }
5599
5600 pub fn add_reference(&self, db: &'db dyn HirDatabase, mutability: Mutability) -> Self {
5601 let interner = DbInterner::new_no_crate(db);
5602 let ty_mutability = match mutability {
5603 Mutability::Shared => hir_ty::next_solver::Mutability::Not,
5604 Mutability::Mut => hir_ty::next_solver::Mutability::Mut,
5605 };
5606 self.derived(Ty::new_ref(
5607 interner,
5608 Region::error(interner),
5609 self.ty.skip_binder(),
5610 ty_mutability,
5611 ))
5612 }
5613
5614 pub fn is_slice(&self) -> bool {
5615 matches!(self.ty.skip_binder().kind(), TyKind::Slice(..))
5616 }
5617
5618 pub fn is_usize(&self) -> bool {
5619 matches!(self.ty.skip_binder().kind(), TyKind::Uint(rustc_type_ir::UintTy::Usize))
5620 }
5621
5622 pub fn is_float(&self) -> bool {
5623 matches!(self.ty.skip_binder().kind(), TyKind::Float(_))
5624 }
5625
5626 pub fn is_char(&self) -> bool {
5627 matches!(self.ty.skip_binder().kind(), TyKind::Char)
5628 }
5629
5630 pub fn is_int_or_uint(&self) -> bool {
5631 matches!(self.ty.skip_binder().kind(), TyKind::Int(_) | TyKind::Uint(_))
5632 }
5633
5634 pub fn is_scalar(&self) -> bool {
5635 matches!(
5636 self.ty.skip_binder().kind(),
5637 TyKind::Bool | TyKind::Char | TyKind::Int(_) | TyKind::Uint(_) | TyKind::Float(_)
5638 )
5639 }
5640
5641 pub fn is_tuple(&self) -> bool {
5642 matches!(self.ty.skip_binder().kind(), TyKind::Tuple(..))
5643 }
5644
5645 pub fn as_slice(&self) -> Option<Type<'db>> {
5646 match self.ty.skip_binder().kind() {
5647 TyKind::Slice(ty) => Some(self.derived(ty)),
5648 _ => None,
5649 }
5650 }
5651
5652 pub fn strip_references(&self) -> Self {
5653 self.derived(self.ty.skip_binder().strip_references())
5654 }
5655
5656 pub fn strip_reference(&self) -> Self {
5658 self.derived(self.ty.skip_binder().strip_reference())
5659 }
5660
5661 pub fn is_unknown(&self) -> bool {
5662 self.ty.skip_binder().is_ty_error()
5663 }
5664
5665 fn krate(&self, db: &'db dyn HirDatabase) -> base_db::Crate {
5666 match self.owner {
5667 TypeOwnerId::GenericDefId(def) => hir_def::HasModule::krate(&def, db),
5668 TypeOwnerId::BuiltinDeriveImplId(def) => {
5669 hir_def::HasModule::krate(&def.loc(db).adt, db)
5670 }
5671 TypeOwnerId::AnonConstId(def) => hir_def::HasModule::krate(&def, db),
5672 TypeOwnerId::NoParams(krate) => krate,
5673 }
5674 }
5675
5676 fn param_env(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> {
5677 let interner = DbInterner::new_no_crate(db);
5678 let krate = self.krate(db);
5679 match self.owner {
5680 TypeOwnerId::GenericDefId(def) => {
5681 ParamEnvAndCrate { param_env: db.trait_environment(def), krate }
5682 }
5683 TypeOwnerId::BuiltinDeriveImplId(def) => ParamEnvAndCrate {
5684 param_env: hir_ty::builtin_derive::param_env(interner, def),
5685 krate,
5686 },
5687 TypeOwnerId::AnonConstId(def) => ParamEnvAndCrate {
5688 param_env: db.trait_environment(def.loc(db).owner.generic_def(db)),
5689 krate,
5690 },
5691 TypeOwnerId::NoParams(_) => {
5692 ParamEnvAndCrate { param_env: ParamEnv::empty(interner), krate }
5693 }
5694 }
5695 }
5696
5697 pub fn into_future_output(&self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
5701 let env = self.param_env(db);
5702 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
5703 let (trait_, output_assoc_type) = lang_items
5704 .IntoFuture
5705 .zip(lang_items.IntoFutureOutput)
5706 .or(lang_items.Future.zip(lang_items.FutureOutput))?;
5707
5708 if !traits::implements_trait_unique(
5709 self.ty.instantiate_identity().skip_norm_wip(),
5710 db,
5711 env,
5712 trait_,
5713 ) {
5714 return None;
5715 }
5716
5717 self.normalize_trait_assoc_type(db, &[], output_assoc_type.into())
5718 }
5719
5720 pub fn future_output(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
5722 let krate = self.krate(db);
5723 let lang_items = hir_def::lang_item::lang_items(db, krate);
5724 let future_output = lang_items.FutureOutput?;
5725 self.normalize_trait_assoc_type(db, &[], future_output.into())
5726 }
5727
5728 pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
5730 let krate = self.krate(db);
5731 let lang_items = hir_def::lang_item::lang_items(db, krate);
5732 let iterator_item = lang_items.IteratorItem?;
5733 self.normalize_trait_assoc_type(db, &[], iterator_item.into())
5734 }
5735
5736 pub fn impls_iterator(self, db: &'db dyn HirDatabase) -> bool {
5737 let env = self.param_env(db);
5738 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
5739 let Some(iterator_trait) = lang_items.Iterator else {
5740 return false;
5741 };
5742 traits::implements_trait_unique(
5743 self.ty.instantiate_identity().skip_norm_wip(),
5744 db,
5745 env,
5746 iterator_trait,
5747 )
5748 }
5749
5750 pub fn into_iterator_iter(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
5752 let env = self.param_env(db);
5753 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
5754 let trait_ = lang_items.IntoIterator?;
5755
5756 if !traits::implements_trait_unique(
5757 self.ty.instantiate_identity().skip_norm_wip(),
5758 db,
5759 env,
5760 trait_,
5761 ) {
5762 return None;
5763 }
5764
5765 let into_iter_assoc_type = lang_items.IntoIterIntoIterType?;
5766 self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into())
5767 }
5768
5769 pub fn impls_fnonce(&self, db: &'db dyn HirDatabase) -> bool {
5774 let env = self.param_env(db);
5775 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
5776 let fnonce_trait = match lang_items.FnOnce {
5777 Some(it) => it,
5778 None => return false,
5779 };
5780
5781 traits::implements_trait_unique(
5782 self.ty.instantiate_identity().skip_norm_wip(),
5783 db,
5784 env,
5785 fnonce_trait,
5786 )
5787 }
5788
5789 pub fn impls_trait(&self, db: &'db dyn HirDatabase, trait_: Trait, args: &[Type<'db>]) -> bool {
5791 let env = self.param_env(db);
5792 let interner = DbInterner::new_no_crate(db);
5793 let (args, _owner) =
5794 generic_args_from_tys(interner, trait_.id.into(), iter::once(self).chain(args));
5795 traits::implements_trait_unique_with_args(db, env, trait_.id, args)
5796 }
5797
5798 pub fn has_any_impl(
5812 &self,
5813 db: &'db dyn HirDatabase,
5814 trait_: Trait,
5815 args: &[Type<'db>],
5816 ) -> bool {
5817 let interner = DbInterner::new_no_crate(db);
5818 let env = ParamEnvAndCrate { param_env: ParamEnv::empty(interner), krate: self.krate(db) };
5819 traits::implements_trait_unique_with_infcx(db, env, trait_.id, &mut |infcx| {
5820 let mut args = Self::instantiate_many_with_infer(iter::once(self).chain(args), infcx);
5821 GenericArgs::for_item(infcx.interner, trait_.id.into(), |_, param, _| {
5822 if let GenericParamId::TypeParamId(_) = param
5823 && let Some(arg) = args.next()
5824 {
5825 arg.into()
5826 } else {
5827 infcx.var_for_def(param, hir_ty::Span::Dummy)
5828 }
5829 })
5830 })
5831 }
5832
5833 pub fn normalize_trait_assoc_type(
5834 &self,
5835 db: &'db dyn HirDatabase,
5836 args: &[Type<'db>],
5837 alias: TypeAlias,
5838 ) -> Option<Type<'db>> {
5839 let env = self.param_env(db);
5840 let interner = DbInterner::new_with(db, env.krate);
5841 let (args, owner) =
5842 generic_args_from_tys(interner, alias.id.into(), iter::once(self).chain(args));
5843 let projection = Ty::new_alias(
5845 interner,
5846 AliasTy::new_from_args(
5847 interner,
5848 AliasTyKind::Projection { def_id: alias.id.into() },
5849 args,
5850 ),
5851 );
5852
5853 let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
5854 let ty = structurally_normalize_ty(&infcx, projection, env.param_env);
5855 if ty.is_ty_error() { None } else { Some(Type { owner, ty: EarlyBinder::bind(ty) }) }
5856 }
5857
5858 pub fn is_copy(&self, db: &'db dyn HirDatabase) -> bool {
5859 let env = self.param_env(db);
5860 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
5861 let Some(copy_trait) = lang_items.Copy else {
5862 return false;
5863 };
5864 self.impls_trait(db, copy_trait.into(), &[])
5865 }
5866
5867 pub fn as_callable(&self, db: &'db dyn HirDatabase) -> Option<Callable<'db>> {
5868 let interner = DbInterner::new_no_crate(db);
5869 let callee = match self.ty.skip_binder().kind() {
5870 TyKind::Closure(id, subst) => Callee::Closure(id.0, subst),
5871 TyKind::CoroutineClosure(id, subst) => Callee::CoroutineClosure(id.0, subst),
5872 TyKind::FnPtr(..) => Callee::FnPtr,
5873 TyKind::FnDef(id, _) => Callee::Def(id.0),
5874 TyKind::Ref(_, inner_ty, _) => return self.derived(inner_ty).as_callable(db),
5876 _ => {
5877 let env = self.param_env(db);
5878 let (fn_trait, sig) =
5879 hir_ty::callable_sig_from_fn_trait(self.ty.skip_binder(), env, db)?;
5880 return Some(Callable {
5881 ty: self.clone(),
5882 sig,
5883 callee: Callee::FnImpl(fn_trait),
5884 is_bound_method: false,
5885 });
5886 }
5887 };
5888
5889 let sig = self.ty.skip_binder().callable_sig(interner)?;
5890 Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
5891 }
5892
5893 pub fn is_closure(&self) -> bool {
5894 matches!(self.ty.skip_binder().kind(), TyKind::Closure { .. })
5895 }
5896
5897 pub fn as_closure(&self) -> Option<Closure<'db>> {
5898 match self.ty.skip_binder().kind() {
5899 TyKind::Closure(id, subst) => {
5900 Some(Closure { id: AnyClosureId::ClosureId(id.0), subst, owner: self.owner })
5901 }
5902 TyKind::CoroutineClosure(id, subst) => Some(Closure {
5903 id: AnyClosureId::CoroutineClosureId(id.0),
5904 subst,
5905 owner: self.owner,
5906 }),
5907 _ => None,
5908 }
5909 }
5910
5911 pub fn is_fn(&self) -> bool {
5912 matches!(self.ty.skip_binder().kind(), TyKind::FnDef(..) | TyKind::FnPtr { .. })
5913 }
5914
5915 pub fn is_array(&self) -> bool {
5916 matches!(self.ty.skip_binder().kind(), TyKind::Array(..))
5917 }
5918
5919 pub fn is_packed(&self, _db: &'db dyn HirDatabase) -> bool {
5920 match self.ty.skip_binder().kind() {
5921 TyKind::Adt(adt_def, ..) => adt_def.is_packed(),
5922 _ => false,
5923 }
5924 }
5925
5926 pub fn is_raw_ptr(&self) -> bool {
5927 matches!(self.ty.skip_binder().kind(), TyKind::RawPtr(..))
5928 }
5929
5930 pub fn is_mutable_raw_ptr(&self) -> bool {
5931 matches!(
5933 self.ty.skip_binder().kind(),
5934 TyKind::RawPtr(.., hir_ty::next_solver::Mutability::Mut)
5935 )
5936 }
5937
5938 pub fn as_raw_ptr(&self) -> Option<(Type<'db>, Mutability)> {
5939 let TyKind::RawPtr(ty, m) = self.ty.skip_binder().kind() else { return None };
5941 let m = Mutability::from_mutable(matches!(m, hir_ty::next_solver::Mutability::Mut));
5942 Some((self.derived(ty), m))
5943 }
5944
5945 pub fn remove_raw_ptr(&self) -> Option<Type<'db>> {
5946 if let TyKind::RawPtr(ty, _) = self.ty.skip_binder().kind() {
5947 Some(self.derived(ty))
5948 } else {
5949 None
5950 }
5951 }
5952
5953 pub fn contains_unknown(&self) -> bool {
5954 self.ty.skip_binder().references_non_lt_error()
5955 }
5956
5957 pub fn fields(&self, db: &'db dyn HirDatabase) -> Vec<(Field, Self)> {
5958 let interner = DbInterner::new_no_crate(db);
5959 let (variant_id, substs) = match self.ty.skip_binder().kind() {
5960 TyKind::Adt(adt_def, substs) => {
5961 let id = match adt_def.def_id() {
5962 AdtId::StructId(id) => id.into(),
5963 AdtId::UnionId(id) => id.into(),
5964 AdtId::EnumId(_) => return Vec::new(),
5965 };
5966 (id, substs)
5967 }
5968 _ => return Vec::new(),
5969 };
5970
5971 db.field_types(variant_id)
5972 .iter()
5973 .map(|(local_id, ty)| {
5974 let def = Field { parent: variant_id.into(), id: local_id };
5975 let ty = ty.get().instantiate(interner, substs).skip_norm_wip();
5976 (def, self.derived(ty))
5977 })
5978 .collect()
5979 }
5980
5981 pub fn tuple_fields(&self, _db: &'db dyn HirDatabase) -> Vec<Self> {
5982 if let TyKind::Tuple(substs) = self.ty.skip_binder().kind() {
5983 substs.iter().map(|ty| self.derived(ty)).collect()
5984 } else {
5985 Vec::new()
5986 }
5987 }
5988
5989 pub fn as_array(&self, db: &'db dyn HirDatabase) -> Option<(Self, usize)> {
5990 if let TyKind::Array(ty, len) = self.ty.skip_binder().kind() {
5991 try_const_usize(db, len).map(|it| (self.derived(ty), it as usize))
5992 } else {
5993 None
5994 }
5995 }
5996
5997 pub fn fingerprint_for_trait_impl(&self, db: &'db dyn HirDatabase) -> Option<SimplifiedType> {
5999 fast_reject::simplify_type(
6000 DbInterner::new_no_crate(db),
6001 self.ty.skip_binder(),
6002 fast_reject::TreatParams::AsRigid,
6003 )
6004 }
6005
6006 pub fn autoderef(
6009 &self,
6010 db: &'db dyn HirDatabase,
6011 ) -> impl Iterator<Item = Type<'db>> + use<'_, 'db> {
6012 self.autoderef_(db).map(move |ty| self.derived(ty))
6013 }
6014
6015 fn autoderef_(&self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Ty<'db>> {
6016 let interner = DbInterner::new_no_crate(db);
6017 let env = self.param_env(db);
6018 let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty.skip_binder());
6020 autoderef(db, env, canonical)
6021 }
6022
6023 pub fn iterate_assoc_items<T>(
6026 &self,
6027 db: &'db dyn HirDatabase,
6028 mut callback: impl FnMut(AssocItem) -> Option<T>,
6029 ) -> Option<T> {
6030 let mut slot = None;
6031 self.iterate_assoc_items_dyn(db, &mut |assoc_item_id| {
6032 slot = callback(assoc_item_id.into());
6033 slot.is_some()
6034 });
6035 slot
6036 }
6037
6038 fn iterate_assoc_items_dyn(
6039 &self,
6040 db: &'db dyn HirDatabase,
6041 callback: &mut dyn FnMut(AssocItemId) -> bool,
6042 ) {
6043 let mut handle_impls = |impls: &[ImplId]| {
6044 for &impl_def in impls {
6045 for &(_, item) in impl_def.impl_items(db).items.iter() {
6046 if callback(item) {
6047 return;
6048 }
6049 }
6050 }
6051 };
6052 let krate = self.krate(db);
6053
6054 let interner = DbInterner::new_no_crate(db);
6055 let Some(simplified_type) = fast_reject::simplify_type(
6056 interner,
6057 self.ty.skip_binder(),
6058 fast_reject::TreatParams::AsRigid,
6059 ) else {
6060 return;
6061 };
6062
6063 method_resolution::with_incoherent_inherent_impls(
6064 db,
6065 krate,
6066 &simplified_type,
6067 &mut handle_impls,
6068 );
6069
6070 if let Some(module) = method_resolution::simplified_type_module(db, &simplified_type) {
6071 InherentImpls::for_each_crate_and_block(
6072 db,
6073 module.krate(db),
6074 module.block(db),
6075 &mut |impls| {
6076 handle_impls(impls.for_self_ty(&simplified_type));
6077 },
6078 );
6079 }
6080 }
6081
6082 pub fn type_arguments(&self) -> impl Iterator<Item = Type<'db>> + '_ {
6101 match self.ty.skip_binder().strip_references().kind() {
6102 TyKind::Adt(_, substs) => Either::Left(substs.types().map(move |ty| self.derived(ty))),
6103 TyKind::Tuple(substs) => {
6104 Either::Right(Either::Left(substs.iter().map(move |ty| self.derived(ty))))
6105 }
6106 _ => Either::Right(Either::Right(iter::empty())),
6107 }
6108 }
6109
6110 pub fn type_and_const_arguments<'a>(
6129 &'a self,
6130 db: &'a dyn HirDatabase,
6131 display_target: DisplayTarget,
6132 ) -> impl Iterator<Item = SmolStr> + 'a {
6133 self.ty
6134 .skip_binder()
6135 .strip_references()
6136 .as_adt()
6137 .into_iter()
6138 .flat_map(|(_, substs)| substs.iter())
6139 .filter_map(move |arg| match arg.kind() {
6140 rustc_type_ir::GenericArgKind::Type(ty) => {
6141 Some(format_smolstr!("{}", ty.display(db, display_target)))
6142 }
6143 rustc_type_ir::GenericArgKind::Const(const_) => {
6144 Some(format_smolstr!("{}", const_.display(db, display_target)))
6145 }
6146 rustc_type_ir::GenericArgKind::Lifetime(_) => None,
6147 })
6148 }
6149
6150 pub fn generic_parameters<'a>(
6152 &'a self,
6153 db: &'a dyn HirDatabase,
6154 display_target: DisplayTarget,
6155 ) -> impl Iterator<Item = SmolStr> + 'a {
6156 self.as_adt()
6158 .and_then(|a| {
6159 a.lifetime(db).map(|lt| lt.name.display_no_db(Edition::Edition2015).to_smolstr())
6161 })
6162 .into_iter()
6163 .chain(self.type_and_const_arguments(db, display_target))
6165 }
6166
6167 pub fn iterate_method_candidates_with_traits<T>(
6168 &self,
6169 db: &'db dyn HirDatabase,
6170 scope: &SemanticsScope<'_>,
6171 traits_in_scope: &FxHashSet<TraitId>,
6172 name: Option<&Name>,
6173 mut callback: impl FnMut(Function) -> Option<T>,
6174 ) -> Option<T> {
6175 let _p = tracing::info_span!("iterate_method_candidates_with_traits").entered();
6176 let mut slot = None;
6177 self.iterate_method_candidates_split_inherent(db, scope, traits_in_scope, name, |f| {
6178 match callback(f) {
6179 it @ Some(_) => {
6180 slot = it;
6181 ControlFlow::Break(())
6182 }
6183 None => ControlFlow::Continue(()),
6184 }
6185 });
6186 slot
6187 }
6188
6189 pub fn iterate_method_candidates<T>(
6190 &self,
6191 db: &'db dyn HirDatabase,
6192 scope: &SemanticsScope<'_>,
6193 name: Option<&Name>,
6194 callback: impl FnMut(Function) -> Option<T>,
6195 ) -> Option<T> {
6196 self.iterate_method_candidates_with_traits(
6197 db,
6198 scope,
6199 &scope.visible_traits().0,
6200 name,
6201 callback,
6202 )
6203 }
6204
6205 fn with_method_resolution<R>(
6206 &self,
6207 db: &'db dyn HirDatabase,
6208 resolver: &Resolver<'db>,
6209 traits_in_scope: &FxHashSet<TraitId>,
6210 f: impl FnOnce(&MethodResolutionContext<'_, 'db>) -> R,
6211 ) -> R {
6212 let module = resolver.module();
6213 let interner = DbInterner::new_with(db, module.krate(db));
6214 let typing_mode = if let Some(store_owner) = resolver.expression_store_owner() {
6219 TypingMode::analysis_in_body(interner, store_owner.into())
6220 } else {
6221 TypingMode::non_body_analysis()
6222 };
6223 let infcx = interner.infer_ctxt().build(typing_mode);
6224 let features = resolver.top_level_def_map().features();
6225 let environment = self.param_env(db);
6226 let ctx = MethodResolutionContext {
6227 infcx: &infcx,
6228 resolver,
6229 param_env: environment.param_env,
6230 traits_in_scope,
6231 edition: resolver.krate().data(db).edition,
6232 features,
6233 call_span: hir_ty::Span::Dummy,
6234 receiver_span: hir_ty::Span::Dummy,
6235 };
6236 f(&ctx)
6237 }
6238
6239 pub fn iterate_method_candidates_split_inherent(
6244 &self,
6245 db: &'db dyn HirDatabase,
6246 scope: &SemanticsScope<'_>,
6247 traits_in_scope: &FxHashSet<TraitId>,
6248 name: Option<&Name>,
6249 mut callback: impl MethodCandidateCallback,
6250 ) {
6251 let _p = tracing::info_span!(
6252 "iterate_method_candidates_split_inherent",
6253 traits_in_scope = traits_in_scope.len(),
6254 ?name,
6255 )
6256 .entered();
6257
6258 self.with_method_resolution(db, scope.resolver(), traits_in_scope, |ctx| {
6259 let canonical =
6261 hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty.skip_binder());
6262 let (self_ty, _) = ctx.infcx.instantiate_canonical(hir_ty::Span::Dummy, &canonical);
6263
6264 match name {
6265 Some(name) => {
6266 match ctx.probe_for_name(
6267 method_resolution::Mode::MethodCall,
6268 name.clone(),
6269 self_ty,
6270 ) {
6271 Ok(candidate)
6272 | Err(method_resolution::MethodError::PrivateMatch(candidate)) => {
6273 let method_resolution::CandidateId::FunctionId(id) = candidate.item
6274 else {
6275 unreachable!("`Mode::MethodCall` can only return functions");
6276 };
6277 let id = Function { id: AnyFunctionId::FunctionId(id) };
6278 match candidate.kind {
6279 method_resolution::PickKind::InherentImplPick(_)
6280 | method_resolution::PickKind::ObjectPick(..)
6281 | method_resolution::PickKind::WhereClausePick(..) => {
6282 _ = callback.on_inherent_method(id);
6284 }
6285 method_resolution::PickKind::TraitPick(..) => {
6286 _ = callback.on_trait_method(id);
6287 }
6288 }
6289 }
6290 Err(_) => {}
6291 };
6292 }
6293 None => {
6294 _ = ctx.probe_all(method_resolution::Mode::MethodCall, self_ty).try_for_each(
6295 |candidate| {
6296 let method_resolution::CandidateId::FunctionId(id) =
6297 candidate.candidate.item
6298 else {
6299 unreachable!("`Mode::MethodCall` can only return functions");
6300 };
6301 let id = Function { id: AnyFunctionId::FunctionId(id) };
6302 match candidate.candidate.kind {
6303 method_resolution::CandidateKind::InherentImplCandidate {
6304 ..
6305 }
6306 | method_resolution::CandidateKind::ObjectCandidate(..)
6307 | method_resolution::CandidateKind::WhereClauseCandidate(..) => {
6308 callback.on_inherent_method(id)
6310 }
6311 method_resolution::CandidateKind::TraitCandidate(..) => {
6312 callback.on_trait_method(id)
6313 }
6314 }
6315 },
6316 );
6317 }
6318 }
6319 })
6320 }
6321
6322 #[tracing::instrument(skip_all, fields(name = ?name))]
6323 pub fn iterate_path_candidates<T>(
6324 &self,
6325 db: &'db dyn HirDatabase,
6326 scope: &SemanticsScope<'_>,
6327 traits_in_scope: &FxHashSet<TraitId>,
6328 name: Option<&Name>,
6329 mut callback: impl FnMut(AssocItem) -> Option<T>,
6330 ) -> Option<T> {
6331 let _p = tracing::info_span!("iterate_path_candidates").entered();
6332 let mut slot = None;
6333
6334 self.iterate_path_candidates_split_inherent(db, scope, traits_in_scope, name, |item| {
6335 match callback(item) {
6336 it @ Some(_) => {
6337 slot = it;
6338 ControlFlow::Break(())
6339 }
6340 None => ControlFlow::Continue(()),
6341 }
6342 });
6343 slot
6344 }
6345
6346 #[tracing::instrument(skip_all, fields(name = ?name))]
6352 pub fn iterate_path_candidates_split_inherent(
6353 &self,
6354 db: &'db dyn HirDatabase,
6355 scope: &SemanticsScope<'_>,
6356 traits_in_scope: &FxHashSet<TraitId>,
6357 name: Option<&Name>,
6358 mut callback: impl PathCandidateCallback,
6359 ) {
6360 let _p = tracing::info_span!(
6361 "iterate_path_candidates_split_inherent",
6362 traits_in_scope = traits_in_scope.len(),
6363 ?name,
6364 )
6365 .entered();
6366
6367 self.with_method_resolution(db, scope.resolver(), traits_in_scope, |ctx| {
6368 let canonical =
6370 hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty.skip_binder());
6371 let (self_ty, _) = ctx.infcx.instantiate_canonical(hir_ty::Span::Dummy, &canonical);
6372
6373 match name {
6374 Some(name) => {
6375 match ctx.probe_for_name(method_resolution::Mode::Path, name.clone(), self_ty) {
6376 Ok(candidate)
6377 | Err(method_resolution::MethodError::PrivateMatch(candidate)) => {
6378 let id = candidate.item.into();
6379 match candidate.kind {
6380 method_resolution::PickKind::InherentImplPick(_)
6381 | method_resolution::PickKind::ObjectPick(..)
6382 | method_resolution::PickKind::WhereClausePick(..) => {
6383 _ = callback.on_inherent_item(id);
6385 }
6386 method_resolution::PickKind::TraitPick(..) => {
6387 _ = callback.on_trait_item(id);
6388 }
6389 }
6390 }
6391 Err(_) => {}
6392 };
6393 }
6394 None => {
6395 _ = ctx.probe_all(method_resolution::Mode::Path, self_ty).try_for_each(
6396 |candidate| {
6397 let id = candidate.candidate.item.into();
6398 match candidate.candidate.kind {
6399 method_resolution::CandidateKind::InherentImplCandidate {
6400 ..
6401 }
6402 | method_resolution::CandidateKind::ObjectCandidate(..)
6403 | method_resolution::CandidateKind::WhereClauseCandidate(..) => {
6404 callback.on_inherent_item(id)
6406 }
6407 method_resolution::CandidateKind::TraitCandidate(..) => {
6408 callback.on_trait_item(id)
6409 }
6410 }
6411 },
6412 );
6413 }
6414 }
6415 })
6416 }
6417
6418 pub fn as_adt(&self) -> Option<Adt> {
6419 let (adt, _subst) = self.ty.skip_binder().as_adt()?;
6420 Some(adt.into())
6421 }
6422
6423 pub fn as_adt_with_args(&self) -> Option<(Adt, Vec<Option<Type<'db>>>)> {
6425 let (adt, args) = self.ty.skip_binder().as_adt()?;
6426 let args = args.iter().map(|arg| Some(self.derived(arg.ty()?))).collect();
6427 Some((adt.into(), args))
6428 }
6429
6430 pub fn as_builtin(&self) -> Option<BuiltinType> {
6431 self.ty.skip_binder().as_builtin().map(|inner| BuiltinType { inner })
6432 }
6433
6434 pub fn as_dyn_trait(&self) -> Option<Trait> {
6435 self.ty.skip_binder().dyn_trait().map(Into::into)
6436 }
6437
6438 pub fn applicable_inherent_traits(
6441 &self,
6442 db: &'db dyn HirDatabase,
6443 ) -> impl Iterator<Item = Trait> {
6444 let _p = tracing::info_span!("applicable_inherent_traits").entered();
6445 self.autoderef_(db)
6446 .filter_map(|ty| ty.dyn_trait())
6447 .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db, dyn_trait_id))
6448 .copied()
6449 .map(Trait::from)
6450 }
6451
6452 pub fn env_traits(&self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Trait> {
6453 let _p = tracing::info_span!("env_traits").entered();
6454 let env = self.param_env(db);
6455 self.autoderef_(db)
6456 .filter(|ty| matches!(ty.kind(), TyKind::Param(_)))
6457 .flat_map(move |ty| {
6458 env.param_env
6459 .clauses()
6460 .iter()
6461 .filter_map(move |pred| match pred.kind().skip_binder() {
6462 ClauseKind::Trait(tr) if tr.self_ty() == ty => Some(tr.def_id().0),
6463 _ => None,
6464 })
6465 .flat_map(|t| hir_ty::all_super_traits(db, t))
6466 .copied()
6467 })
6468 .map(Trait::from)
6469 }
6470
6471 pub fn as_impl_traits(&self, db: &'db dyn HirDatabase) -> Option<impl Iterator<Item = Trait>> {
6472 self.ty.skip_binder().impl_trait_bounds(db).map(|it| {
6473 it.into_iter().filter_map(|pred| match pred.kind().skip_binder() {
6474 ClauseKind::Trait(trait_ref) => Some(Trait::from(trait_ref.def_id().0)),
6475 _ => None,
6476 })
6477 })
6478 }
6479
6480 pub fn as_associated_type_parent_trait(&self, db: &'db dyn HirDatabase) -> Option<Trait> {
6481 let TyKind::Alias(AliasTy { kind: AliasTyKind::Projection { def_id }, .. }) =
6482 self.ty.skip_binder().kind()
6483 else {
6484 return None;
6485 };
6486 match def_id.0.loc(db).container {
6487 ItemContainerId::TraitId(id) => Some(Trait { id }),
6488 _ => None,
6489 }
6490 }
6491
6492 fn derived(&self, ty: Ty<'db>) -> Self {
6493 Type { owner: self.owner, ty: EarlyBinder::bind(ty) }
6494 }
6495
6496 pub fn walk(&self, db: &'db dyn HirDatabase, callback: impl FnMut(Type<'db>)) {
6499 struct Visitor<'db, F> {
6500 db: &'db dyn HirDatabase,
6501 owner: TypeOwnerId,
6502 callback: F,
6503 visited: FxHashSet<Ty<'db>>,
6504 }
6505 impl<'db, F> TypeVisitor<DbInterner<'db>> for Visitor<'db, F>
6506 where
6507 F: FnMut(Type<'db>),
6508 {
6509 type Result = ();
6510
6511 fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
6512 if !self.visited.insert(ty) {
6513 return;
6514 }
6515
6516 (self.callback)(Type { owner: self.owner, ty: EarlyBinder::bind(ty) });
6517
6518 if let Some(bounds) = ty.impl_trait_bounds(self.db) {
6519 bounds.visit_with(self);
6520 }
6521
6522 ty.super_visit_with(self);
6523 }
6524 }
6525
6526 let mut visitor =
6527 Visitor { db, owner: self.owner, callback, visited: FxHashSet::default() };
6528 self.ty.skip_binder().visit_with(&mut visitor);
6529 }
6530 pub fn could_unify_with(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool {
6535 self.owner.must_unify(other.owner);
6536 let env = self.param_env(db);
6537 let interner = DbInterner::new_no_crate(db);
6538 let tys = hir_ty::replace_errors_with_variables(
6539 interner,
6540 &(self.ty.skip_binder(), other.ty.skip_binder()),
6541 );
6542 hir_ty::could_unify(db, env, &tys)
6543 }
6544
6545 pub fn could_unify_with_deeply(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool {
6550 self.owner.must_unify(other.owner);
6551 let env = self.param_env(db);
6552 let interner = DbInterner::new_no_crate(db);
6553 let tys = hir_ty::replace_errors_with_variables(
6554 interner,
6555 &(self.ty.skip_binder(), other.ty.skip_binder()),
6556 );
6557 hir_ty::could_unify_deeply(db, env, &tys)
6558 }
6559
6560 pub fn could_coerce_to(&self, db: &'db dyn HirDatabase, to: &Type<'db>) -> bool {
6561 self.owner.must_unify(to.owner);
6562 let env = self.param_env(db);
6563 let interner = DbInterner::new_no_crate(db);
6564 let tys = hir_ty::replace_errors_with_variables(
6565 interner,
6566 &(self.ty.skip_binder(), to.ty.skip_binder()),
6567 );
6568 hir_ty::could_coerce(db, env, &tys)
6569 }
6570
6571 pub fn as_type_param(&self, _db: &'db dyn HirDatabase) -> Option<TypeParam> {
6572 match self.ty.skip_binder().kind() {
6573 TyKind::Param(param) => Some(TypeParam { id: param.id }),
6574 _ => None,
6575 }
6576 }
6577
6578 pub fn generic_params(&self, db: &'db dyn HirDatabase) -> FxHashSet<GenericParam> {
6580 hir_ty::collect_params(&self.ty.skip_binder())
6581 .into_iter()
6582 .map(|id| TypeOrConstParam { id }.split(db).either_into())
6583 .collect()
6584 }
6585
6586 pub fn layout(&self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> {
6587 let env = self.param_env(db);
6588 db.layout_of_ty(self.ty.skip_binder().store(), env.store())
6589 .map(|layout| Layout(layout, db.target_data_layout(env.krate).unwrap()))
6590 }
6591
6592 pub fn drop_glue(&self, db: &'db dyn HirDatabase) -> DropGlue {
6593 let env = self.param_env(db);
6594 let interner = DbInterner::new_with(db, env.krate);
6595 let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
6596 hir_ty::drop::has_drop_glue(&infcx, self.ty.skip_binder(), env.param_env)
6597 }
6598}
6599
6600#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
6601pub struct InlineAsmOperand {
6602 owner: ExpressionStoreOwnerId,
6603 expr: ExprId,
6604 index: usize,
6605}
6606
6607impl InlineAsmOperand {
6608 pub fn parent(self, _db: &dyn HirDatabase) -> ExpressionStoreOwner {
6609 self.owner.into()
6610 }
6611
6612 pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
6613 let body = ExpressionStore::of(db, self.owner);
6614 match &body[self.expr] {
6615 hir_def::hir::Expr::InlineAsm(e) => e.operands.get(self.index)?.0.clone(),
6616 _ => None,
6617 }
6618 }
6619}
6620
6621#[derive(Debug)]
6623pub struct Callable<'db> {
6624 ty: Type<'db>,
6625 sig: PolyFnSig<'db>,
6626 callee: Callee<'db>,
6627 is_bound_method: bool,
6629}
6630
6631#[derive(Clone, PartialEq, Eq, Hash, Debug)]
6632enum Callee<'db> {
6633 Def(CallableDefId),
6634 Closure(InternedClosureId, GenericArgs<'db>),
6635 CoroutineClosure(InternedCoroutineClosureId, GenericArgs<'db>),
6636 FnPtr,
6637 FnImpl(traits::FnTrait),
6638 BuiltinDeriveImplMethod { method: BuiltinDeriveImplMethod, impl_: BuiltinDeriveImplId },
6639}
6640
6641pub enum CallableKind<'db> {
6642 Function(Function),
6643 TupleStruct(Struct),
6644 TupleEnumVariant(EnumVariant),
6645 Closure(Closure<'db>),
6646 FnPtr,
6647 FnImpl(FnTrait),
6648}
6649
6650impl<'db> Callable<'db> {
6651 pub fn kind(&self) -> CallableKind<'db> {
6652 match self.callee {
6653 Callee::Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
6654 Callee::BuiltinDeriveImplMethod { method, impl_ } => CallableKind::Function(Function {
6655 id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ },
6656 }),
6657 Callee::Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
6658 Callee::Def(CallableDefId::EnumVariantId(it)) => {
6659 CallableKind::TupleEnumVariant(it.into())
6660 }
6661 Callee::Closure(id, subst) => CallableKind::Closure(Closure {
6662 id: AnyClosureId::ClosureId(id),
6663 subst,
6664 owner: self.ty.owner,
6665 }),
6666 Callee::CoroutineClosure(id, subst) => CallableKind::Closure(Closure {
6667 id: AnyClosureId::CoroutineClosureId(id),
6668 subst,
6669 owner: self.ty.owner,
6670 }),
6671 Callee::FnPtr => CallableKind::FnPtr,
6672 Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_.into()),
6673 }
6674 }
6675
6676 fn as_function(&self) -> Option<Function> {
6677 match self.callee {
6678 Callee::Def(CallableDefId::FunctionId(it)) => Some(it.into()),
6679 Callee::BuiltinDeriveImplMethod { method, impl_ } => {
6680 Some(Function { id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } })
6681 }
6682 _ => None,
6683 }
6684 }
6685
6686 pub fn receiver_param(&self, db: &'db dyn HirDatabase) -> Option<(SelfParam, Type<'db>)> {
6687 if !self.is_bound_method {
6688 return None;
6689 }
6690 let func = self.as_function()?;
6691 Some((
6692 func.self_param(db)?,
6693 self.ty.derived(self.sig.skip_binder().inputs_and_output.inputs()[0]),
6694 ))
6695 }
6696 pub fn n_params(&self) -> usize {
6697 self.sig.skip_binder().inputs_and_output.inputs().len()
6698 - if self.is_bound_method { 1 } else { 0 }
6699 }
6700 pub fn params(&self) -> Vec<Param<'db>> {
6701 self.sig
6702 .skip_binder()
6703 .inputs_and_output
6704 .inputs()
6705 .iter()
6706 .enumerate()
6707 .skip(if self.is_bound_method { 1 } else { 0 })
6708 .map(|(idx, ty)| (idx, self.ty.derived(*ty)))
6709 .map(|(idx, ty)| Param { func: self.callee.clone(), idx, ty })
6710 .collect()
6711 }
6712 pub fn return_type(&self) -> Type<'db> {
6713 self.ty.derived(self.sig.skip_binder().output())
6714 }
6715 pub fn sig(&self) -> impl Eq {
6716 &self.sig
6717 }
6718
6719 pub fn ty(&self) -> &Type<'db> {
6720 &self.ty
6721 }
6722}
6723
6724#[derive(Clone, Debug, Eq, PartialEq)]
6725pub struct Layout<'db>(Arc<TyLayout>, &'db TargetDataLayout);
6726
6727impl<'db> Layout<'db> {
6728 pub fn size(&self) -> u64 {
6729 self.0.size.bytes()
6730 }
6731
6732 pub fn align(&self) -> u64 {
6733 self.0.align.bytes()
6734 }
6735
6736 pub fn niches(&self) -> Option<u128> {
6737 Some(self.0.largest_niche?.available(self.1))
6738 }
6739
6740 pub fn field_offset(&self, field: Field) -> Option<u64> {
6741 match self.0.fields {
6742 layout::FieldsShape::Primitive => None,
6743 layout::FieldsShape::Union(_) => Some(0),
6744 layout::FieldsShape::Array { stride, count } => {
6745 let i = u64::try_from(field.index()).ok()?;
6746 (i < count).then_some((stride * i).bytes())
6747 }
6748 layout::FieldsShape::Arbitrary { ref offsets, .. } => {
6749 Some(offsets.get(RustcFieldIdx(field.id))?.bytes())
6750 }
6751 }
6752 }
6753
6754 pub fn tuple_field_offset(&self, field: usize) -> Option<u64> {
6755 match self.0.fields {
6756 layout::FieldsShape::Primitive => None,
6757 layout::FieldsShape::Union(_) => Some(0),
6758 layout::FieldsShape::Array { stride, count } => {
6759 let i = u64::try_from(field).ok()?;
6760 (i < count).then_some((stride * i).bytes())
6761 }
6762 layout::FieldsShape::Arbitrary { ref offsets, .. } => {
6763 Some(offsets.get(RustcFieldIdx::new(field))?.bytes())
6764 }
6765 }
6766 }
6767
6768 pub fn tail_padding(&self, field_size: &mut impl FnMut(usize) -> Option<u64>) -> Option<u64> {
6769 match self.0.fields {
6770 layout::FieldsShape::Primitive => None,
6771 layout::FieldsShape::Union(_) => None,
6772 layout::FieldsShape::Array { stride, count } => count.checked_sub(1).and_then(|tail| {
6773 let tail_field_size = field_size(tail as usize)?;
6774 let offset = stride.bytes() * tail;
6775 self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size)
6776 }),
6777 layout::FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => {
6778 let tail = in_memory_order[in_memory_order.len().checked_sub(1)? as u32];
6779 let tail_field_size = field_size(tail.0.into_raw().into_u32() as usize)?;
6780 let offset = offsets.get(tail)?.bytes();
6781 self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size)
6782 }
6783 }
6784 }
6785
6786 pub fn largest_padding(
6787 &self,
6788 field_size: &mut impl FnMut(usize) -> Option<u64>,
6789 ) -> Option<u64> {
6790 match self.0.fields {
6791 layout::FieldsShape::Primitive => None,
6792 layout::FieldsShape::Union(_) => None,
6793 layout::FieldsShape::Array { stride: _, count: 0 } => None,
6794 layout::FieldsShape::Array { stride, .. } => {
6795 let size = field_size(0)?;
6796 stride.bytes().checked_sub(size)
6797 }
6798 layout::FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => {
6799 let mut reverse_index = vec![None; in_memory_order.len()];
6800 for (mem, src) in in_memory_order.iter().enumerate() {
6801 reverse_index[mem] =
6802 Some((src.0.into_raw().into_u32() as usize, offsets[*src].bytes()));
6803 }
6804 if reverse_index.iter().any(|it| it.is_none()) {
6805 stdx::never!();
6806 return None;
6807 }
6808 reverse_index
6809 .into_iter()
6810 .flatten()
6811 .chain(iter::once((0, self.0.size.bytes())))
6812 .tuple_windows()
6813 .filter_map(|((i, start), (_, end))| {
6814 let size = field_size(i)?;
6815 end.checked_sub(start)?.checked_sub(size)
6816 })
6817 .max()
6818 }
6819 }
6820 }
6821
6822 pub fn enum_tag_size(&self) -> Option<usize> {
6823 let tag_size =
6824 if let layout::Variants::Multiple { tag, tag_encoding, .. } = &self.0.variants {
6825 match tag_encoding {
6826 TagEncoding::Direct => tag.size(self.1).bytes_usize(),
6827 TagEncoding::Niche { .. } => 0,
6828 }
6829 } else {
6830 return None;
6831 };
6832 Some(tag_size)
6833 }
6834}
6835
6836#[derive(Copy, Clone, Debug, Eq, PartialEq)]
6837pub enum BindingMode {
6838 Move,
6839 Ref(Mutability),
6840}
6841
6842#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
6844pub enum ScopeDef {
6845 ModuleDef(ModuleDef),
6846 GenericParam(GenericParam),
6847 ImplSelfType(Impl),
6848 AdtSelfType(Adt),
6849 Local(Local),
6850 Label(Label),
6851 Unknown,
6852}
6853
6854impl ScopeDef {
6855 pub fn all_items(def: PerNs) -> ArrayVec<Self, 3> {
6856 let mut items = ArrayVec::new();
6857
6858 match (def.take_types(), def.take_values()) {
6859 (Some(m1), None) => items.push(ScopeDef::ModuleDef(m1.into())),
6860 (None, Some(m2)) => items.push(ScopeDef::ModuleDef(m2.into())),
6861 (Some(m1), Some(m2)) => {
6862 if m1 != m2 {
6866 items.push(ScopeDef::ModuleDef(m1.into()));
6867 items.push(ScopeDef::ModuleDef(m2.into()));
6868 } else {
6869 items.push(ScopeDef::ModuleDef(m1.into()));
6870 }
6871 }
6872 (None, None) => {}
6873 };
6874
6875 if let Some(macro_def_id) = def.take_macros() {
6876 items.push(ScopeDef::ModuleDef(ModuleDef::Macro(macro_def_id.into())));
6877 }
6878
6879 if items.is_empty() {
6880 items.push(ScopeDef::Unknown);
6881 }
6882
6883 items
6884 }
6885
6886 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
6887 match self {
6888 ScopeDef::ModuleDef(it) => it.attrs(db),
6889 ScopeDef::GenericParam(it) => Some(it.attrs(db)),
6890 ScopeDef::ImplSelfType(_)
6891 | ScopeDef::AdtSelfType(_)
6892 | ScopeDef::Local(_)
6893 | ScopeDef::Label(_)
6894 | ScopeDef::Unknown => None,
6895 }
6896 }
6897
6898 pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
6899 match self {
6900 ScopeDef::ModuleDef(it) => it.module(db).map(|m| m.krate(db)),
6901 ScopeDef::GenericParam(it) => Some(it.module(db).krate(db)),
6902 ScopeDef::ImplSelfType(_) => None,
6903 ScopeDef::AdtSelfType(it) => Some(it.module(db).krate(db)),
6904 ScopeDef::Local(it) => Some(it.module(db).krate(db)),
6905 ScopeDef::Label(it) => Some(it.module(db).krate(db)),
6906 ScopeDef::Unknown => None,
6907 }
6908 }
6909}
6910
6911impl From<ItemInNs> for ScopeDef {
6912 fn from(item: ItemInNs) -> Self {
6913 match item {
6914 ItemInNs::Types(id) => ScopeDef::ModuleDef(id),
6915 ItemInNs::Values(id) => ScopeDef::ModuleDef(id),
6916 ItemInNs::Macros(id) => ScopeDef::ModuleDef(ModuleDef::Macro(id)),
6917 }
6918 }
6919}
6920
6921#[derive(Clone, Debug, PartialEq, Eq)]
6922pub struct Adjustment<'db> {
6923 pub source: Type<'db>,
6924 pub target: Type<'db>,
6925 pub kind: Adjust,
6926}
6927
6928#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6929pub enum Adjust {
6930 NeverToAny,
6932 Deref(Option<OverloadedDeref>),
6934 Borrow(AutoBorrow),
6936 Pointer(PointerCast),
6937}
6938
6939#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6940pub enum AutoBorrow {
6941 Ref(Mutability),
6943 RawPtr(Mutability),
6945}
6946
6947#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6948pub struct OverloadedDeref(pub Mutability);
6949
6950pub trait HasVisibility {
6951 fn visibility(&self, db: &dyn HirDatabase) -> Visibility;
6952 fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool {
6953 let vis = self.visibility(db);
6954 vis.is_visible_from(db, module.id)
6955 }
6956}
6957
6958#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6959pub enum PredicatePolarity {
6960 Positive,
6962 Negative,
6964}
6965
6966#[derive(Debug, Clone, PartialEq, Eq)]
6967pub struct TraitPredicate<'db> {
6968 inner: hir_ty::next_solver::TraitPredicate<'db>,
6969 owner: TypeOwnerId,
6970}
6971
6972impl<'db> TraitPredicate<'db> {
6973 pub fn polarity(&self) -> PredicatePolarity {
6974 match self.inner.polarity {
6975 rustc_type_ir::PredicatePolarity::Positive => PredicatePolarity::Positive,
6976 rustc_type_ir::PredicatePolarity::Negative => PredicatePolarity::Negative,
6977 }
6978 }
6979
6980 pub fn trait_ref(&self) -> TraitRef<'db> {
6981 TraitRef { owner: self.owner, trait_ref: self.inner.trait_ref }
6982 }
6983}
6984
6985pub trait HasCrate {
6987 fn krate(&self, db: &dyn HirDatabase) -> Crate;
6988}
6989
6990impl<T: hir_def::HasModule> HasCrate for T {
6991 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6992 self.module(db).krate(db).into()
6993 }
6994}
6995
6996impl HasCrate for AssocItem {
6997 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6998 self.module(db).krate(db)
6999 }
7000}
7001
7002impl HasCrate for Struct {
7003 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7004 self.module(db).krate(db)
7005 }
7006}
7007
7008impl HasCrate for Union {
7009 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7010 self.module(db).krate(db)
7011 }
7012}
7013
7014impl HasCrate for Enum {
7015 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7016 self.module(db).krate(db)
7017 }
7018}
7019
7020impl HasCrate for Field {
7021 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7022 self.parent_def(db).module(db).krate(db)
7023 }
7024}
7025
7026impl HasCrate for EnumVariant {
7027 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7028 self.module(db).krate(db)
7029 }
7030}
7031
7032impl HasCrate for Function {
7033 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7034 self.module(db).krate(db)
7035 }
7036}
7037
7038impl HasCrate for Const {
7039 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7040 self.module(db).krate(db)
7041 }
7042}
7043
7044impl HasCrate for TypeAlias {
7045 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7046 self.module(db).krate(db)
7047 }
7048}
7049
7050impl HasCrate for Type<'_> {
7051 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7052 self.krate(db).into()
7053 }
7054}
7055
7056impl HasCrate for Macro {
7057 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7058 self.module(db).krate(db)
7059 }
7060}
7061
7062impl HasCrate for Trait {
7063 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7064 self.module(db).krate(db)
7065 }
7066}
7067
7068impl HasCrate for Static {
7069 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7070 self.module(db).krate(db)
7071 }
7072}
7073
7074impl HasCrate for Adt {
7075 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7076 self.module(db).krate(db)
7077 }
7078}
7079
7080impl HasCrate for Impl {
7081 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7082 self.module(db).krate(db)
7083 }
7084}
7085
7086impl HasCrate for Module {
7087 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7088 Module::krate(*self, db)
7089 }
7090}
7091
7092impl HasCrate for AnonConst {
7093 fn krate(&self, db: &dyn HirDatabase) -> Crate {
7094 hir_def::HasModule::krate(&self.id.loc(db).owner, db).into()
7095 }
7096}
7097
7098pub trait HasContainer {
7099 fn container(&self, db: &dyn HirDatabase) -> ItemContainer;
7100}
7101
7102impl HasContainer for ExternCrateDecl {
7103 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
7104 container_id_to_hir(self.id.lookup(db).container.into())
7105 }
7106}
7107
7108impl HasContainer for Module {
7109 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
7110 let def_map = self.id.def_map(db);
7112 match def_map[self.id].parent {
7113 Some(parent_id) => ItemContainer::Module(Module { id: parent_id }),
7114 None => ItemContainer::Crate(def_map.krate().into()),
7115 }
7116 }
7117}
7118
7119impl HasContainer for Function {
7120 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
7121 match self.id {
7122 AnyFunctionId::FunctionId(id) => container_id_to_hir(id.lookup(db).container),
7123 AnyFunctionId::BuiltinDeriveImplMethod { impl_, .. } => {
7124 ItemContainer::Impl(Impl { id: AnyImplId::BuiltinDeriveImplId(impl_) })
7125 }
7126 }
7127 }
7128}
7129
7130impl HasContainer for Struct {
7131 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
7132 ItemContainer::Module(Module { id: self.id.lookup(db).container })
7133 }
7134}
7135
7136impl HasContainer for Union {
7137 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
7138 ItemContainer::Module(Module { id: self.id.lookup(db).container })
7139 }
7140}
7141
7142impl HasContainer for Enum {
7143 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
7144 ItemContainer::Module(Module { id: self.id.lookup(db).container })
7145 }
7146}
7147
7148impl HasContainer for TypeAlias {
7149 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
7150 container_id_to_hir(self.id.lookup(db).container)
7151 }
7152}
7153
7154impl HasContainer for Const {
7155 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
7156 container_id_to_hir(self.id.lookup(db).container)
7157 }
7158}
7159
7160impl HasContainer for Static {
7161 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
7162 container_id_to_hir(self.id.lookup(db).container)
7163 }
7164}
7165
7166impl HasContainer for Trait {
7167 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
7168 ItemContainer::Module(Module { id: self.id.lookup(db).container })
7169 }
7170}
7171
7172impl HasContainer for ExternBlock {
7173 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
7174 ItemContainer::Module(Module { id: self.id.lookup(db).container })
7175 }
7176}
7177
7178pub trait HasName {
7179 fn name(&self, db: &dyn HirDatabase) -> Option<Name>;
7180}
7181
7182macro_rules! impl_has_name {
7183 ( $( $ty:ident ),* $(,)? ) => {
7184 $(
7185 impl HasName for $ty {
7186 fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
7187 (*self).name(db).into()
7188 }
7189 }
7190 )*
7191 };
7192}
7193
7194impl_has_name!(
7195 ModuleDef,
7196 Module,
7197 Field,
7198 Struct,
7199 Union,
7200 Enum,
7201 EnumVariant,
7202 Adt,
7203 Variant,
7204 DefWithBody,
7205 Function,
7206 ExternCrateDecl,
7207 Const,
7208 Static,
7209 Trait,
7210 TypeAlias,
7211 Macro,
7212 ExternAssocItem,
7213 AssocItem,
7214 Local,
7215 DeriveHelper,
7216 ToolModule,
7217 Label,
7218 GenericParam,
7219 TypeParam,
7220 LifetimeParam,
7221 ConstParam,
7222 TypeOrConstParam,
7223 InlineAsmOperand,
7224);
7225
7226macro_rules! impl_has_name_no_db {
7227 ( $( $ty:ident ),* $(,)? ) => {
7228 $(
7229 impl HasName for $ty {
7230 fn name(&self, _db: &dyn HirDatabase) -> Option<Name> {
7231 (*self).name().into()
7232 }
7233 }
7234 )*
7235 };
7236}
7237
7238impl_has_name_no_db!(TupleField, StaticLifetime, BuiltinType, BuiltinAttr);
7239
7240impl HasName for Param<'_> {
7241 fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
7242 self.name(db)
7243 }
7244}
7245
7246fn container_id_to_hir(c: ItemContainerId) -> ItemContainer {
7247 match c {
7248 ItemContainerId::ExternBlockId(id) => ItemContainer::ExternBlock(ExternBlock { id }),
7249 ItemContainerId::ModuleId(id) => ItemContainer::Module(Module { id }),
7250 ItemContainerId::ImplId(id) => ItemContainer::Impl(id.into()),
7251 ItemContainerId::TraitId(id) => ItemContainer::Trait(Trait { id }),
7252 }
7253}
7254
7255#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7256pub enum ItemContainer {
7257 Trait(Trait),
7258 Impl(Impl),
7259 Module(Module),
7260 ExternBlock(ExternBlock),
7261 Crate(Crate),
7262}
7263
7264pub enum DocLinkDef {
7266 ModuleDef(ModuleDef),
7267 Field(Field),
7268 SelfType(Trait),
7269}
7270
7271fn push_ty_diagnostics<'db>(
7272 db: &'db dyn HirDatabase,
7273 acc: &mut Vec<AnyDiagnostic<'db>>,
7274 diagnostics: &[TyLoweringDiagnostic],
7275 source_map: &ExpressionStoreSourceMap,
7276) {
7277 acc.extend(
7278 diagnostics
7279 .iter()
7280 .filter_map(|diagnostic| AnyDiagnostic::ty_diagnostic(diagnostic, source_map, db)),
7281 );
7282}
7283
7284pub trait MethodCandidateCallback {
7285 fn on_inherent_method(&mut self, f: Function) -> ControlFlow<()>;
7286
7287 fn on_trait_method(&mut self, f: Function) -> ControlFlow<()>;
7288}
7289
7290impl<F> MethodCandidateCallback for F
7291where
7292 F: FnMut(Function) -> ControlFlow<()>,
7293{
7294 fn on_inherent_method(&mut self, f: Function) -> ControlFlow<()> {
7295 self(f)
7296 }
7297
7298 fn on_trait_method(&mut self, f: Function) -> ControlFlow<()> {
7299 self(f)
7300 }
7301}
7302
7303pub trait PathCandidateCallback {
7304 fn on_inherent_item(&mut self, item: AssocItem) -> ControlFlow<()>;
7305
7306 fn on_trait_item(&mut self, item: AssocItem) -> ControlFlow<()>;
7307}
7308
7309impl<F> PathCandidateCallback for F
7310where
7311 F: FnMut(AssocItem) -> ControlFlow<()>,
7312{
7313 fn on_inherent_item(&mut self, item: AssocItem) -> ControlFlow<()> {
7314 self(item)
7315 }
7316
7317 fn on_trait_item(&mut self, item: AssocItem) -> ControlFlow<()> {
7318 self(item)
7319 }
7320}
7321
7322pub fn resolve_absolute_path<'a, I: Iterator<Item = Symbol> + Clone + 'a>(
7323 db: &'a dyn HirDatabase,
7324 mut segments: I,
7325) -> impl Iterator<Item = ItemInNs> + use<'a, I> {
7326 segments
7327 .next()
7328 .into_iter()
7329 .flat_map(move |crate_name| {
7330 all_crates(db)
7331 .iter()
7332 .filter(|&krate| {
7333 krate
7334 .extra_data(db)
7335 .display_name
7336 .as_ref()
7337 .is_some_and(|name| *name.crate_name().symbol() == crate_name)
7338 })
7339 .filter_map(|&krate| {
7340 let segments = segments.clone();
7341 let mut def_map = crate_def_map(db, krate);
7342 let mut module = &def_map[def_map.root_module_id()];
7343 let mut segments = segments.with_position().peekable();
7344 while let Some((_, segment)) = segments.next_if(|&(position, _)| {
7345 !matches!(position, itertools::Position::Last | itertools::Position::Only)
7346 }) {
7347 let res = module
7348 .scope
7349 .get(&Name::new_symbol_root(segment))
7350 .take_types()
7351 .and_then(|res| match res {
7352 ModuleDefId::ModuleId(it) => Some(it),
7353 _ => None,
7354 })?;
7355 def_map = res.def_map(db);
7356 module = &def_map[res];
7357 }
7358 let (_, item_name) = segments.next()?;
7359 let res = module.scope.get(&Name::new_symbol_root(item_name));
7360 Some(res.iter_items().map(|(item, _)| item.into()))
7361 })
7362 .collect::<Vec<_>>()
7363 })
7364 .flatten()
7365}
7366
7367fn as_name_opt(name: Option<impl AsName>) -> Name {
7368 name.map_or_else(Name::missing, |name| name.as_name())
7369}
7370
7371#[track_caller]
7372fn generic_args_from_tys<'db>(
7373 interner: DbInterner<'db>,
7374 def_id: SolverDefId,
7375 args: impl IntoIterator<Item: Borrow<Type<'db>>>,
7376) -> (GenericArgs<'db>, TypeOwnerId) {
7377 let mut owner = None::<TypeOwnerId>;
7378 let mut args = args.into_iter();
7379 let args = GenericArgs::for_item(interner, def_id, |_, id, _| {
7380 if matches!(id, GenericParamId::TypeParamId(_))
7381 && let Some(arg) = args.next()
7382 {
7383 let arg = arg.borrow();
7384
7385 match &mut owner {
7386 Some(owner) => *owner = owner.must_unify(arg.owner),
7387 None => owner = Some(arg.owner),
7388 }
7389
7390 arg.ty.skip_binder().into()
7391 } else {
7392 next_solver::GenericArg::error_from_id(interner, id)
7393 }
7394 });
7395 let owner =
7396 owner.unwrap_or_else(|| TypeOwnerId::NoParams(Type::builtin_type_crate(interner.db())));
7397 (args, owner)
7398}
7399
7400fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId) -> bool {
7401 let params = GenericParams::of(db, generic_def);
7402 let defaults = db.generic_defaults(generic_def);
7403 params
7404 .iter_type_or_consts()
7405 .filter(|(_, param)| matches!(param, TypeOrConstParamData::TypeParamData(_)))
7406 .map(|(local_id, _)| TypeOrConstParamId { parent: generic_def, local_id })
7407 .any(|param| {
7408 let param = hir_ty::type_or_const_param_idx(db, param);
7409 defaults.get(param as usize).is_none()
7410 })
7411}
7412
7413fn param_env_from_has_crate<'db>(
7414 db: &'db dyn HirDatabase,
7415 id: impl hir_def::HasModule + Into<GenericDefId> + Copy,
7416) -> ParamEnvAndCrate<'db> {
7417 ParamEnvAndCrate { param_env: db.trait_environment(id.into()), krate: id.krate(db) }
7418}
7419
7420pub trait MacroCallIdExt {
7422 fn loc(self, db: &dyn HirDatabase) -> &hir_expand::MacroCallLoc;
7423}
7424impl MacroCallIdExt for span::MacroCallId {
7425 #[inline]
7426 fn loc(self, db: &dyn HirDatabase) -> &hir_expand::MacroCallLoc {
7427 hir_expand::MacroCallId::from(self).loc(db)
7428 }
7429}
7430
7431pub fn struct_tail_raw<'db>(
7433 db: &'db dyn HirDatabase,
7434 interner: DbInterner<'db>,
7435 mut ty: Ty<'db>,
7436 mut normalize: impl FnMut(Ty<'db>) -> Ty<'db>,
7437) -> Ty<'db> {
7438 let recursion_limit = 16;
7439 for iteration in 0.. {
7440 if iteration >= recursion_limit {
7441 return Ty::new_error(interner, ErrorGuaranteed);
7442 }
7443 match ty.kind() {
7444 TyKind::Adt(def, args) => {
7445 let AdtId::StructId(def_id) = def.def_id() else { break };
7446 let last_field = db.field_types(def_id.into()).iter().next_back();
7447 match last_field {
7448 Some((_, field)) => {
7449 ty = normalize(field.get().instantiate(interner, args).skip_norm_wip())
7450 }
7451 None => break,
7452 }
7453 }
7454 TyKind::Tuple(tys) if let Some((&last_ty, _)) = tys.split_last() => {
7455 ty = last_ty;
7456 }
7457 TyKind::Tuple(_) => break,
7458 TyKind::Pat(inner, _) => {
7459 ty = inner;
7460 }
7461 _ => {
7462 break;
7463 }
7464 }
7465 }
7466 ty
7467}