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