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