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