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 fn types_impl(
3142 &self,
3143 db: &'db dyn HirDatabase,
3144 ) -> impl Iterator<Item = (Ty<'db>, Option<Name>)> {
3145 let container = match self.def {
3146 GenericDefId::ConstId(id) => Some(id.lookup(db).container),
3147 GenericDefId::FunctionId(id) => Some(id.lookup(db).container),
3148 GenericDefId::TypeAliasId(id) => Some(id.lookup(db).container),
3149 _ => None,
3150 };
3151 let container_type_params = container
3152 .and_then(|container| match container {
3153 ItemContainerId::ImplId(container) => Some(container.into()),
3154 ItemContainerId::TraitId(container) => Some(container.into()),
3155 _ => None,
3156 })
3157 .map(|container| {
3158 GenericParams::of(db, container)
3159 .iter_type_or_consts()
3160 .filter_map(|param| match param.1 {
3161 TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
3162 TypeOrConstParamData::ConstParamData(_) => None,
3163 })
3164 .collect::<Vec<_>>()
3165 });
3166 let generics = GenericParams::of(db, self.def);
3167 let type_params = generics.iter_type_or_consts().filter_map(|param| match param.1 {
3168 TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
3169 TypeOrConstParamData::ConstParamData(_) => None,
3170 });
3171 self.subst.types().zip(container_type_params.into_iter().flatten().chain(type_params))
3172 }
3173
3174 pub fn types(&self, db: &'db dyn HirDatabase) -> Vec<(Symbol, Type<'db>)> {
3176 self.types_impl(db)
3177 .filter_map(|(ty, name)| {
3178 Some((
3179 name?.symbol().clone(),
3180 Type { ty: EarlyBinder::bind(ty), owner: self.owner },
3181 ))
3182 })
3183 .collect()
3184 }
3185
3186 pub fn all_types(&self, db: &'db dyn HirDatabase) -> Vec<Type<'db>> {
3193 self.types_impl(db)
3194 .map(|(ty, _)| Type { ty: EarlyBinder::bind(ty), owner: self.owner })
3195 .collect()
3196 }
3197}
3198
3199#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3201pub struct Local<'db> {
3202 pub(crate) parent: ExpressionStoreOwnerId,
3203 pub(crate) parent_infer: InferBodyId<'db>,
3204 pub(crate) binding_id: BindingId,
3205}
3206
3207pub struct LocalSource<'db> {
3208 pub local: Local<'db>,
3209 pub source: InFile<Either<ast::IdentPat, ast::SelfParam>>,
3210}
3211
3212impl<'db> LocalSource<'db> {
3213 pub fn as_ident_pat(&self) -> Option<&ast::IdentPat> {
3214 match &self.source.value {
3215 Either::Left(it) => Some(it),
3216 Either::Right(_) => None,
3217 }
3218 }
3219
3220 pub fn into_ident_pat(self) -> Option<ast::IdentPat> {
3221 match self.source.value {
3222 Either::Left(it) => Some(it),
3223 Either::Right(_) => None,
3224 }
3225 }
3226
3227 pub fn original_file(&self, db: &dyn HirDatabase) -> EditionedFileId {
3228 self.source.file_id.original_file(db)
3229 }
3230
3231 pub fn file(&self) -> HirFileId {
3232 self.source.file_id
3233 }
3234
3235 pub fn name(&self) -> Option<InFile<ast::Name>> {
3236 self.source.as_ref().map(|it| it.name()).transpose()
3237 }
3238
3239 pub fn syntax(&self) -> &SyntaxNode {
3240 self.source.value.syntax()
3241 }
3242
3243 pub fn syntax_ptr(self) -> InFile<SyntaxNodePtr> {
3244 self.source.map(|it| SyntaxNodePtr::new(it.syntax()))
3245 }
3246}
3247
3248impl<'db> Local<'db> {
3249 pub fn is_param(self, db: &dyn HirDatabase) -> bool {
3250 let src = self.primary_source(db);
3252 match src.source.value {
3253 Either::Left(pat) => pat
3254 .syntax()
3255 .ancestors()
3256 .map(|it| it.kind())
3257 .take_while(|&kind| ast::Pat::can_cast(kind) || ast::Param::can_cast(kind))
3258 .any(ast::Param::can_cast),
3259 Either::Right(_) => true,
3260 }
3261 }
3262
3263 pub fn as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
3264 match self.parent {
3265 ExpressionStoreOwnerId::Body(DefWithBodyId::FunctionId(func)) if self.is_self(db) => {
3266 Some(SelfParam { func: func.into() })
3267 }
3268 _ => None,
3269 }
3270 }
3271
3272 pub fn name(self, db: &dyn HirDatabase) -> Name {
3273 ExpressionStore::of(db, self.parent)[self.binding_id].name.clone()
3274 }
3275
3276 pub fn is_self(self, db: &dyn HirDatabase) -> bool {
3277 self.name(db) == sym::self_
3278 }
3279
3280 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
3281 ExpressionStore::of(db, self.parent)[self.binding_id].mode == BindingAnnotation::Mutable
3282 }
3283
3284 pub fn is_ref(self, db: &dyn HirDatabase) -> bool {
3285 matches!(
3286 ExpressionStore::of(db, self.parent)[self.binding_id].mode,
3287 BindingAnnotation::Ref | BindingAnnotation::RefMut
3288 )
3289 }
3290
3291 pub fn parent(self, _db: &dyn HirDatabase) -> ExpressionStoreOwner {
3292 self.parent.into()
3293 }
3294
3295 pub fn module(self, db: &dyn HirDatabase) -> Module {
3296 self.parent(db).module(db)
3297 }
3298
3299 pub fn as_id(self) -> u32 {
3300 self.binding_id.into_raw().into_u32()
3301 }
3302
3303 pub fn ty(self, db: &'db dyn HirDatabase) -> Type<'db> {
3304 let def = self.parent;
3305 let infer = InferenceResult::of(db, self.parent_infer);
3306 let ty = infer.binding_ty(self.binding_id);
3307 Type::new_body(db, def, ty)
3308 }
3309
3310 pub fn sources(self, db: &dyn HirDatabase) -> Vec<LocalSource<'db>> {
3312 let b;
3313 let (_, source_map) = match self.parent {
3314 ExpressionStoreOwnerId::Signature(generic_def_id) => {
3315 ExpressionStore::with_source_map(db, generic_def_id.into())
3316 }
3317 ExpressionStoreOwnerId::Body(def_with_body_id) => {
3318 b = Body::with_source_map(db, def_with_body_id);
3319 if b.0.is_any_self_param(self.binding_id)
3320 && let Some(source) = b.1.self_param_syntax()
3321 {
3322 let root = source.file_syntax(db);
3323 return vec![LocalSource {
3324 local: self,
3325 source: source.map(|ast| Either::Right(ast.to_node(&root))),
3326 }];
3327 }
3328 (&b.0.store, &b.1.store)
3329 }
3330 ExpressionStoreOwnerId::VariantFields(def) => {
3331 ExpressionStore::with_source_map(db, def.into())
3332 }
3333 };
3334 source_map
3335 .patterns_for_binding(self.binding_id)
3336 .iter()
3337 .map(|&definition| {
3338 let src = source_map.pat_syntax(definition).unwrap(); let root = src.file_syntax(db);
3340 LocalSource {
3341 local: self,
3342 source: src.map(|ast| match ast.to_node(&root) {
3343 Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
3344 _ => unreachable!("local with non ident-pattern"),
3345 }),
3346 }
3347 })
3348 .collect()
3349 }
3350
3351 pub fn primary_source(self, db: &dyn HirDatabase) -> LocalSource<'db> {
3353 let b;
3354 let (_, source_map) = match self.parent {
3355 ExpressionStoreOwnerId::Signature(generic_def_id) => {
3356 ExpressionStore::with_source_map(db, generic_def_id.into())
3357 }
3358 ExpressionStoreOwnerId::Body(def_with_body_id) => {
3359 b = Body::with_source_map(db, def_with_body_id);
3360 if b.0.is_any_self_param(self.binding_id)
3361 && let Some(source) = b.1.self_param_syntax()
3362 {
3363 let root = source.file_syntax(db);
3364 return LocalSource {
3365 local: self,
3366 source: source.map(|ast| Either::Right(ast.to_node(&root))),
3367 };
3368 }
3369 (&b.0.store, &b.1.store)
3370 }
3371 ExpressionStoreOwnerId::VariantFields(def) => {
3372 ExpressionStore::with_source_map(db, def.into())
3373 }
3374 };
3375 source_map
3376 .patterns_for_binding(self.binding_id)
3377 .first()
3378 .map(|&definition| {
3379 let src = source_map.pat_syntax(definition).unwrap(); let root = src.file_syntax(db);
3381 LocalSource {
3382 local: self,
3383 source: src.map(|ast| match ast.to_node(&root) {
3384 Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
3385 _ => unreachable!("local with non ident-pattern"),
3386 }),
3387 }
3388 })
3389 .unwrap()
3390 }
3391}
3392
3393impl PartialOrd for Local<'_> {
3394 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
3395 Some(self.cmp(other))
3396 }
3397}
3398
3399impl Ord for Local<'_> {
3400 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
3401 self.binding_id.cmp(&other.binding_id)
3402 }
3403}
3404
3405#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3406pub struct DeriveHelper {
3407 pub(crate) derive: MacroId,
3408 pub(crate) idx: u32,
3409}
3410
3411impl DeriveHelper {
3412 pub fn derive(&self) -> Macro {
3413 Macro { id: self.derive }
3414 }
3415
3416 pub fn name(&self, db: &dyn HirDatabase) -> Name {
3417 AttrFlags::derive_info(db, self.derive)
3418 .and_then(|it| it.helpers.get(self.idx as usize))
3419 .map(|helper| Name::new_symbol_root(helper.clone()))
3420 .unwrap_or_else(Name::missing)
3421 }
3422}
3423
3424#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3425pub struct BuiltinAttr {
3426 idx: u32,
3427}
3428
3429impl BuiltinAttr {
3430 fn builtin(name: &str) -> Option<Self> {
3431 hir_expand::inert_attr_macro::find_builtin_attr_idx(&Symbol::intern(name))
3432 .map(|idx| BuiltinAttr { idx: idx as u32 })
3433 }
3434
3435 pub fn name(&self) -> Name {
3436 Name::new_symbol_root(Symbol::intern(
3437 hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].name,
3438 ))
3439 }
3440
3441 pub fn template(&self) -> Option<AttributeTemplate> {
3442 Some(hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].template)
3443 }
3444}
3445
3446#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3447pub struct ToolModule {
3448 krate: base_db::Crate,
3449 idx: u32,
3450}
3451
3452impl ToolModule {
3453 pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
3454 let krate = krate.id;
3455 let idx =
3456 crate_def_map(db, krate).registered_tools().iter().position(|it| it.as_str() == name)?
3457 as u32;
3458 Some(ToolModule { krate, idx })
3459 }
3460
3461 pub fn name(&self, db: &dyn HirDatabase) -> Name {
3462 Name::new_symbol_root(
3463 crate_def_map(db, self.krate).registered_tools()[self.idx as usize].clone(),
3464 )
3465 }
3466
3467 pub fn krate(&self) -> Crate {
3468 Crate { id: self.krate }
3469 }
3470}
3471
3472#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3473pub struct Label {
3474 pub(crate) parent: ExpressionStoreOwnerId,
3475 pub(crate) label_id: LabelId,
3476}
3477
3478impl Label {
3479 pub fn module(self, db: &dyn HirDatabase) -> Module {
3480 self.parent(db).module(db)
3481 }
3482
3483 pub fn parent(self, _db: &dyn HirDatabase) -> ExpressionStoreOwner {
3484 self.parent.into()
3485 }
3486
3487 pub fn name(self, db: &dyn HirDatabase) -> Name {
3488 ExpressionStore::of(db, self.parent)[self.label_id].name.clone()
3489 }
3490}
3491
3492#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3493pub enum GenericParam {
3494 TypeParam(TypeParam),
3495 ConstParam(ConstParam),
3496 LifetimeParam(LifetimeParam),
3497}
3498impl_from!(TypeParam, ConstParam, LifetimeParam for GenericParam);
3499
3500impl GenericParam {
3501 pub fn module(self, db: &dyn HirDatabase) -> Module {
3502 match self {
3503 GenericParam::TypeParam(it) => it.module(db),
3504 GenericParam::ConstParam(it) => it.module(db),
3505 GenericParam::LifetimeParam(it) => it.module(db),
3506 }
3507 }
3508
3509 pub fn name(self, db: &dyn HirDatabase) -> Name {
3510 match self {
3511 GenericParam::TypeParam(it) => it.name(db),
3512 GenericParam::ConstParam(it) => it.name(db),
3513 GenericParam::LifetimeParam(it) => it.name(db),
3514 }
3515 }
3516
3517 pub fn parent(self) -> GenericDef {
3518 match self {
3519 GenericParam::TypeParam(it) => it.id.parent().into(),
3520 GenericParam::ConstParam(it) => it.id.parent().into(),
3521 GenericParam::LifetimeParam(it) => it.id.parent.into(),
3522 }
3523 }
3524
3525 pub fn variance(self, db: &dyn HirDatabase) -> Option<Variance> {
3526 let parent = match self {
3527 GenericParam::TypeParam(it) => it.id.parent(),
3528 GenericParam::ConstParam(_) => return None,
3530 GenericParam::LifetimeParam(it) => it.id.parent,
3531 };
3532 let index = match self {
3533 GenericParam::TypeParam(it) => hir_ty::type_or_const_param_idx(db, it.id.into()),
3534 GenericParam::ConstParam(_) => return None,
3535 GenericParam::LifetimeParam(it) => hir_ty::lifetime_param_idx(db, it.id),
3536 };
3537 db.variances_of(parent).get(index as usize).map(Into::into)
3538 }
3539}
3540
3541#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3542pub enum Variance {
3543 Bivariant,
3544 Covariant,
3545 Contravariant,
3546 Invariant,
3547}
3548
3549impl From<rustc_type_ir::Variance> for Variance {
3550 #[inline]
3551 fn from(value: rustc_type_ir::Variance) -> Self {
3552 match value {
3553 rustc_type_ir::Variance::Covariant => Variance::Covariant,
3554 rustc_type_ir::Variance::Invariant => Variance::Invariant,
3555 rustc_type_ir::Variance::Contravariant => Variance::Contravariant,
3556 rustc_type_ir::Variance::Bivariant => Variance::Bivariant,
3557 }
3558 }
3559}
3560
3561impl fmt::Display for Variance {
3562 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3563 let description = match self {
3564 Variance::Bivariant => "bivariant",
3565 Variance::Covariant => "covariant",
3566 Variance::Contravariant => "contravariant",
3567 Variance::Invariant => "invariant",
3568 };
3569 f.pad(description)
3570 }
3571}
3572
3573#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3574pub struct TypeParam {
3575 pub(crate) id: TypeParamId,
3576}
3577
3578impl TypeParam {
3579 pub fn merge(self) -> TypeOrConstParam {
3580 TypeOrConstParam { id: self.id.into() }
3581 }
3582
3583 pub fn name(self, db: &dyn HirDatabase) -> Name {
3584 self.merge().name(db)
3585 }
3586
3587 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
3588 self.id.parent().into()
3589 }
3590
3591 pub fn module(self, db: &dyn HirDatabase) -> Module {
3592 self.id.parent().module(db).into()
3593 }
3594
3595 pub fn is_implicit(self, db: &dyn HirDatabase) -> bool {
3598 let params = GenericParams::of(db, self.id.parent());
3599 let data = ¶ms[self.id.local_id()];
3600 match data.type_param().unwrap().provenance {
3601 TypeParamProvenance::TypeParamList => false,
3602 TypeParamProvenance::TraitSelf | TypeParamProvenance::ArgumentImplTrait => true,
3603 }
3604 }
3605
3606 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
3607 let interner = DbInterner::new_no_crate(db);
3608 let index = hir_ty::type_or_const_param_idx(db, self.id.into());
3609 let ty = Ty::new_param(interner, self.id, index);
3610 Type::new(self.id.parent(), ty)
3611 }
3612
3613 pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
3617 let self_ty = self.ty(db).ty.instantiate_identity().skip_norm_wip();
3618 GenericPredicates::query_explicit(db, self.id.parent())
3619 .iter_identity()
3620 .filter_map(|pred| match &pred.kind().skip_binder() {
3621 ClauseKind::Trait(trait_ref) if trait_ref.self_ty() == self_ty => {
3622 Some(Trait::from(trait_ref.def_id().0))
3623 }
3624 _ => None,
3625 })
3626 .collect()
3627 }
3628
3629 pub fn default(self, db: &dyn HirDatabase) -> Option<Type<'_>> {
3630 let ty = generic_arg_from_param(db, self.id.into())?;
3631 match ty.kind() {
3632 rustc_type_ir::GenericArgKind::Type(it) if !it.is_ty_error() => {
3633 Some(Type::new(self.id.parent(), it))
3634 }
3635 _ => None,
3636 }
3637 }
3638
3639 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
3640 self.attrs(db).is_unstable()
3641 }
3642}
3643
3644#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3645pub struct LifetimeParam {
3646 pub(crate) id: LifetimeParamId,
3647}
3648
3649impl LifetimeParam {
3650 pub fn name(self, db: &dyn HirDatabase) -> Name {
3651 let params = GenericParams::of(db, self.id.parent);
3652 params[self.id.local_id].name.clone()
3653 }
3654
3655 pub fn module(self, db: &dyn HirDatabase) -> Module {
3656 self.id.parent.module(db).into()
3657 }
3658
3659 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
3660 self.id.parent.into()
3661 }
3662}
3663
3664#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3665pub struct ConstParam {
3666 pub(crate) id: ConstParamId,
3667}
3668
3669impl ConstParam {
3670 pub fn merge(self) -> TypeOrConstParam {
3671 TypeOrConstParam { id: self.id.into() }
3672 }
3673
3674 pub fn name(self, db: &dyn HirDatabase) -> Name {
3675 let params = GenericParams::of(db, self.id.parent());
3676 match params[self.id.local_id()].name() {
3677 Some(it) => it.clone(),
3678 None => {
3679 never!();
3680 Name::missing()
3681 }
3682 }
3683 }
3684
3685 pub fn module(self, db: &dyn HirDatabase) -> Module {
3686 self.id.parent().module(db).into()
3687 }
3688
3689 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
3690 self.id.parent().into()
3691 }
3692
3693 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
3694 Type::new(self.id.parent(), db.const_param_ty(self.id))
3695 }
3696
3697 pub fn default(self, db: &dyn HirDatabase, display_target: DisplayTarget) -> Option<String> {
3698 let arg = generic_arg_from_param(db, self.id.into())?;
3699 Some(arg.display(db, display_target).to_string())
3700 }
3701
3702 pub fn default_source_code(
3703 self,
3704 db: &dyn HirDatabase,
3705 target_module: Module,
3706 ) -> Option<ast::ConstArg> {
3707 let arg = generic_arg_from_param(db, self.id.into())?;
3708 known_const_to_ast(arg.konst()?, db, target_module.id)
3709 }
3710}
3711
3712fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<GenericArg<'_>> {
3713 let local_idx = hir_ty::type_or_const_param_idx(db, id);
3714 let defaults = db.generic_defaults(id.parent);
3715 let ty = defaults.get(local_idx as usize)?;
3716 Some(ty.instantiate_identity().skip_norm_wip())
3718}
3719
3720#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3721pub struct TypeOrConstParam {
3722 pub(crate) id: TypeOrConstParamId,
3723}
3724
3725impl TypeOrConstParam {
3726 pub fn name(self, db: &dyn HirDatabase) -> Name {
3727 let params = GenericParams::of(db, self.id.parent);
3728 match params[self.id.local_id].name() {
3729 Some(n) => n.clone(),
3730 _ => Name::missing(),
3731 }
3732 }
3733
3734 pub fn module(self, db: &dyn HirDatabase) -> Module {
3735 self.id.parent.module(db).into()
3736 }
3737
3738 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
3739 self.id.parent.into()
3740 }
3741
3742 pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
3743 let params = GenericParams::of(db, self.id.parent);
3744 match ¶ms[self.id.local_id] {
3745 TypeOrConstParamData::TypeParamData(_) => {
3746 Either::Right(TypeParam { id: TypeParamId::from_unchecked(self.id) })
3747 }
3748 TypeOrConstParamData::ConstParamData(_) => {
3749 Either::Left(ConstParam { id: ConstParamId::from_unchecked(self.id) })
3750 }
3751 }
3752 }
3753
3754 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
3755 match self.split(db) {
3756 Either::Left(it) => it.ty(db),
3757 Either::Right(it) => it.ty(db),
3758 }
3759 }
3760
3761 pub fn as_type_param(self, db: &dyn HirDatabase) -> Option<TypeParam> {
3762 let params = GenericParams::of(db, self.id.parent);
3763 match ¶ms[self.id.local_id] {
3764 TypeOrConstParamData::TypeParamData(_) => {
3765 Some(TypeParam { id: TypeParamId::from_unchecked(self.id) })
3766 }
3767 TypeOrConstParamData::ConstParamData(_) => None,
3768 }
3769 }
3770
3771 pub fn as_const_param(self, db: &dyn HirDatabase) -> Option<ConstParam> {
3772 let params = GenericParams::of(db, self.id.parent);
3773 match ¶ms[self.id.local_id] {
3774 TypeOrConstParamData::TypeParamData(_) => None,
3775 TypeOrConstParamData::ConstParamData(_) => {
3776 Some(ConstParam { id: ConstParamId::from_unchecked(self.id) })
3777 }
3778 }
3779 }
3780}
3781
3782#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3783pub struct Impl {
3784 pub(crate) id: AnyImplId,
3785}
3786
3787impl Impl {
3788 pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<Impl> {
3789 let mut result = Vec::new();
3790 extend_with_def_map(db, crate_def_map(db, krate.id), &mut result);
3791 return result;
3792
3793 fn extend_with_def_map(db: &dyn HirDatabase, def_map: &DefMap, result: &mut Vec<Impl>) {
3794 for (_, module) in def_map.modules() {
3795 result.extend(module.scope.impls().map(Impl::from));
3796 result.extend(module.scope.builtin_derive_impls().map(Impl::from));
3797
3798 for unnamed_const in module.scope.unnamed_consts() {
3799 for (_, block_def_map) in Body::of(db, unnamed_const.into()).blocks(db) {
3800 extend_with_def_map(db, block_def_map, result);
3801 }
3802 }
3803 }
3804 }
3805 }
3806
3807 pub fn all_in_module(db: &dyn HirDatabase, module: Module) -> Vec<Impl> {
3808 module.impl_defs(db)
3809 }
3810
3811 pub fn all_for_type<'db>(db: &'db dyn HirDatabase, ty: Type<'db>) -> Vec<Impl> {
3817 let mut result = Vec::new();
3818 let interner = DbInterner::new_no_crate(db);
3819 let Some(simplified_ty) = fast_reject::simplify_type(
3820 interner,
3821 ty.ty.skip_binder(),
3822 fast_reject::TreatParams::AsRigid,
3823 ) else {
3824 return Vec::new();
3825 };
3826 let mut extend_with_impls = |impls: Either<&[ImplId], &[BuiltinDeriveImplId]>| match impls {
3827 Either::Left(impls) => result.extend(impls.iter().copied().map(Impl::from)),
3828 Either::Right(impls) => result.extend(impls.iter().copied().map(Impl::from)),
3829 };
3830 method_resolution::with_incoherent_inherent_impls(
3831 db,
3832 ty.krate(db),
3833 &simplified_ty,
3834 |impls| extend_with_impls(Either::Left(impls)),
3835 );
3836 if let Some(module) = method_resolution::simplified_type_module(db, &simplified_ty) {
3837 InherentImpls::for_each_crate_and_block(
3838 db,
3839 module.krate(db),
3840 module.block(db),
3841 &mut |impls| extend_with_impls(Either::Left(impls.for_self_ty(&simplified_ty))),
3842 );
3843 std::iter::successors(module.block(db), |block| block.module(db).block(db))
3844 .filter_map(|block| TraitImpls::for_block(db, block))
3845 .for_each(|impls| impls.for_self_ty(&simplified_ty, &mut extend_with_impls));
3846 for &krate in &*all_crates(db) {
3847 TraitImpls::for_crate(db, krate)
3848 .for_self_ty(&simplified_ty, &mut extend_with_impls);
3849 }
3850 } else {
3851 for &krate in &*all_crates(db) {
3852 TraitImpls::for_crate(db, krate)
3853 .for_self_ty(&simplified_ty, &mut extend_with_impls);
3854 }
3855 }
3856 result
3857 }
3858
3859 pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
3860 let module = trait_.module(db).id;
3861 let mut all = Vec::new();
3862 let mut handle_impls = |impls: &TraitImpls<'_>| {
3863 impls.for_trait(trait_.id, |impls| match impls {
3864 Either::Left(impls) => all.extend(impls.iter().copied().map(Impl::from)),
3865 Either::Right(impls) => all.extend(impls.iter().copied().map(Impl::from)),
3866 });
3867 };
3868 for krate in module.krate(db).transitive_rev_deps(db) {
3869 handle_impls(TraitImpls::for_crate(db, krate));
3870 }
3871 if let Some(block) = module.block(db)
3872 && let Some(impls) = TraitImpls::for_block(db, block)
3873 {
3874 handle_impls(impls);
3875 }
3876 all
3877 }
3878
3879 pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> {
3880 match self.id {
3881 AnyImplId::ImplId(id) => {
3882 let trait_ref = db.impl_trait(id)?;
3883 let id = trait_ref.skip_binder().def_id;
3884 Some(Trait { id: id.0 })
3885 }
3886 AnyImplId::BuiltinDeriveImplId(id) => {
3887 let loc = id.loc(db);
3888 let lang_items = hir_def::lang_item::lang_items(db, loc.adt.module(db).krate(db));
3889 loc.trait_.get_id(lang_items).map(Trait::from)
3890 }
3891 }
3892 }
3893
3894 pub fn trait_ref(self, db: &dyn HirDatabase) -> Option<TraitRef<'_>> {
3895 match self.id {
3896 AnyImplId::ImplId(id) => {
3897 let trait_ref = db.impl_trait(id)?.instantiate_identity().skip_norm_wip();
3898 Some(TraitRef::new(id.into(), trait_ref))
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 trait_ref = hir_ty::builtin_derive::impl_trait(interner, id)
3905 .instantiate_identity()
3906 .skip_norm_wip();
3907 Some(TraitRef { owner: TypeOwnerId::BuiltinDeriveImplId(id), trait_ref })
3908 }
3909 }
3910 }
3911
3912 pub fn self_ty(self, db: &dyn HirDatabase) -> Type<'_> {
3913 match self.id {
3914 AnyImplId::ImplId(id) => {
3915 let ty = db.impl_self_ty(id).instantiate_identity().skip_norm_wip();
3916 Type::new(id.into(), ty)
3917 }
3918 AnyImplId::BuiltinDeriveImplId(id) => {
3919 let loc = id.loc(db);
3920 let krate = loc.module(db).krate(db);
3921 let interner = DbInterner::new_with(db, krate);
3922 let ty =
3923 hir_ty::builtin_derive::impl_trait(interner, id).map_bound(|it| it.self_ty());
3924 Type { owner: TypeOwnerId::BuiltinDeriveImplId(id), ty }
3925 }
3926 }
3927 }
3928
3929 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
3930 match self.id {
3931 AnyImplId::ImplId(id) => {
3932 id.impl_items(db).items.iter().map(|&(_, it)| it.into()).collect()
3933 }
3934 AnyImplId::BuiltinDeriveImplId(impl_) => impl_
3935 .loc(db)
3936 .trait_
3937 .all_methods()
3938 .iter()
3939 .map(|&method| {
3940 AssocItem::Function(Function {
3941 id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ },
3942 })
3943 })
3944 .collect(),
3945 }
3946 }
3947
3948 pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
3949 match self.id {
3950 AnyImplId::ImplId(id) => ImplSignature::of(db, id).flags.contains(ImplFlags::NEGATIVE),
3951 AnyImplId::BuiltinDeriveImplId(_) => false,
3952 }
3953 }
3954
3955 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
3956 match self.id {
3957 AnyImplId::ImplId(id) => ImplSignature::of(db, id).flags.contains(ImplFlags::UNSAFE),
3958 AnyImplId::BuiltinDeriveImplId(_) => false,
3959 }
3960 }
3961
3962 pub fn module(self, db: &dyn HirDatabase) -> Module {
3963 match self.id {
3964 AnyImplId::ImplId(id) => id.module(db).into(),
3965 AnyImplId::BuiltinDeriveImplId(id) => id.module(db).into(),
3966 }
3967 }
3968
3969 pub fn check_orphan_rules(self, db: &dyn HirDatabase) -> bool {
3970 match self.id {
3971 AnyImplId::ImplId(id) => check_orphan_rules(db, id),
3972 AnyImplId::BuiltinDeriveImplId(_) => true,
3973 }
3974 }
3975}
3976
3977#[derive(Clone, PartialEq, Eq, Debug, Hash)]
3978pub struct TraitRef<'db> {
3979 owner: TypeOwnerId,
3980 trait_ref: hir_ty::next_solver::TraitRef<'db>,
3981}
3982
3983impl<'db> TraitRef<'db> {
3984 fn new(owner: GenericDefId, trait_ref: hir_ty::next_solver::TraitRef<'db>) -> Self {
3985 Self { owner: TypeOwnerId::GenericDefId(owner), trait_ref }
3986 }
3987
3988 pub fn trait_(&self) -> Trait {
3989 Trait { id: self.trait_ref.def_id.0 }
3990 }
3991
3992 pub fn self_ty(&self) -> Type<'_> {
3993 let ty = self.trait_ref.self_ty();
3994 Type { owner: self.owner, ty: EarlyBinder::bind(ty) }
3995 }
3996
3997 pub fn get_type_argument(&self, idx: usize) -> Option<Type<'db>> {
4000 self.trait_ref
4001 .args
4002 .as_slice()
4003 .get(idx)
4004 .and_then(|arg| arg.ty())
4005 .map(|ty| Type { owner: self.owner, ty: EarlyBinder::bind(ty) })
4006 }
4007}
4008
4009#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4010enum AnyClosureId<'db> {
4011 ClosureId(InternedClosureId<'db>),
4012 CoroutineClosureId(InternedCoroutineClosureId<'db>),
4013}
4014
4015#[derive(Clone, Debug, PartialEq, Eq, Hash)]
4016pub struct Closure<'db> {
4017 owner: TypeOwnerId,
4018 id: AnyClosureId<'db>,
4019 subst: GenericArgs<'db>,
4020}
4021
4022impl<'db> Closure<'db> {
4023 fn as_ty(&self, db: &'db dyn HirDatabase) -> Ty<'db> {
4024 let interner = DbInterner::new_no_crate(db);
4025 match self.id {
4026 AnyClosureId::ClosureId(id) => Ty::new_closure(interner, id.into(), self.subst),
4027 AnyClosureId::CoroutineClosureId(id) => {
4028 Ty::new_coroutine_closure(interner, id.into(), self.subst)
4029 }
4030 }
4031 }
4032
4033 pub fn display_with_id(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
4034 self.as_ty(db)
4035 .display(db, display_target)
4036 .with_closure_style(ClosureStyle::ClosureWithId)
4037 .to_string()
4038 }
4039
4040 pub fn display_with_impl(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
4041 self.as_ty(db)
4042 .display(db, display_target)
4043 .with_closure_style(ClosureStyle::ImplFn)
4044 .to_string()
4045 }
4046
4047 pub fn captured_items(&self, db: &'db dyn HirDatabase) -> Vec<ClosureCapture<'db>> {
4048 let closure = match self.id {
4049 AnyClosureId::ClosureId(it) => it.loc(db),
4050 AnyClosureId::CoroutineClosureId(it) => it.loc(db),
4051 };
4052 captured_items(db, closure)
4053 }
4054
4055 pub fn fn_trait(&self, _db: &dyn HirDatabase) -> FnTrait {
4056 match self.id {
4057 AnyClosureId::ClosureId(_) => match self.subst.as_closure().kind() {
4058 rustc_type_ir::ClosureKind::Fn => FnTrait::Fn,
4059 rustc_type_ir::ClosureKind::FnMut => FnTrait::FnMut,
4060 rustc_type_ir::ClosureKind::FnOnce => FnTrait::FnOnce,
4061 },
4062 AnyClosureId::CoroutineClosureId(_) => match self.subst.as_coroutine_closure().kind() {
4063 rustc_type_ir::ClosureKind::Fn => FnTrait::AsyncFn,
4064 rustc_type_ir::ClosureKind::FnMut => FnTrait::AsyncFnMut,
4065 rustc_type_ir::ClosureKind::FnOnce => FnTrait::AsyncFnOnce,
4066 },
4067 }
4068 }
4069}
4070
4071#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4073pub struct Coroutine<'db> {
4074 id: InternedCoroutineId<'db>,
4075}
4076
4077impl<'db> Coroutine<'db> {
4078 pub fn captured_items(&self, db: &'db dyn HirDatabase) -> Vec<ClosureCapture<'db>> {
4080 captured_items(db, self.id.loc(db))
4081 }
4082}
4083
4084fn captured_items<'db>(
4085 db: &'db dyn HirDatabase,
4086 closure: InternedClosure<'db>,
4087) -> Vec<ClosureCapture<'db>> {
4088 let InternedClosure { owner: infer_owner, expr: closure, .. } = closure;
4089 let infer = InferenceResult::of(db, infer_owner);
4090 let owner = infer_owner.expression_store_owner(db);
4091 infer.closures_data[&closure]
4092 .min_captures
4093 .values()
4094 .flatten()
4095 .map(|capture| ClosureCapture { owner, infer_owner, closure, capture })
4096 .collect()
4097}
4098
4099#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4100pub enum FnTrait {
4101 FnOnce,
4102 FnMut,
4103 Fn,
4104
4105 AsyncFnOnce,
4106 AsyncFnMut,
4107 AsyncFn,
4108}
4109
4110impl From<traits::FnTrait> for FnTrait {
4111 fn from(value: traits::FnTrait) -> Self {
4112 match value {
4113 traits::FnTrait::FnOnce => FnTrait::FnOnce,
4114 traits::FnTrait::FnMut => FnTrait::FnMut,
4115 traits::FnTrait::Fn => FnTrait::Fn,
4116 traits::FnTrait::AsyncFnOnce => FnTrait::AsyncFnOnce,
4117 traits::FnTrait::AsyncFnMut => FnTrait::AsyncFnMut,
4118 traits::FnTrait::AsyncFn => FnTrait::AsyncFn,
4119 }
4120 }
4121}
4122
4123impl fmt::Display for FnTrait {
4124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4125 match self {
4126 FnTrait::FnOnce => write!(f, "FnOnce"),
4127 FnTrait::FnMut => write!(f, "FnMut"),
4128 FnTrait::Fn => write!(f, "Fn"),
4129 FnTrait::AsyncFnOnce => write!(f, "AsyncFnOnce"),
4130 FnTrait::AsyncFnMut => write!(f, "AsyncFnMut"),
4131 FnTrait::AsyncFn => write!(f, "AsyncFn"),
4132 }
4133 }
4134}
4135
4136impl FnTrait {
4137 pub const fn function_name(&self) -> &'static str {
4138 match self {
4139 FnTrait::FnOnce => "call_once",
4140 FnTrait::FnMut => "call_mut",
4141 FnTrait::Fn => "call",
4142 FnTrait::AsyncFnOnce => "async_call_once",
4143 FnTrait::AsyncFnMut => "async_call_mut",
4144 FnTrait::AsyncFn => "async_call",
4145 }
4146 }
4147
4148 pub fn lang_item(self) -> LangItem {
4149 match self {
4150 FnTrait::FnOnce => LangItem::FnOnce,
4151 FnTrait::FnMut => LangItem::FnMut,
4152 FnTrait::Fn => LangItem::Fn,
4153 FnTrait::AsyncFnOnce => LangItem::AsyncFnOnce,
4154 FnTrait::AsyncFnMut => LangItem::AsyncFnMut,
4155 FnTrait::AsyncFn => LangItem::AsyncFn,
4156 }
4157 }
4158
4159 pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option<Trait> {
4160 Trait::lang(db, krate, self.lang_item())
4161 }
4162}
4163
4164#[derive(Clone, Debug, PartialEq, Eq)]
4165pub struct ClosureCapture<'db> {
4166 owner: ExpressionStoreOwnerId,
4167 infer_owner: InferBodyId<'db>,
4168 closure: ExprId,
4169 capture: &'db hir_ty::closure_analysis::CapturedPlace,
4170}
4171
4172impl<'db> ClosureCapture<'db> {
4173 pub fn local(&self) -> Local<'db> {
4174 Local {
4175 parent: self.owner,
4176 parent_infer: self.infer_owner,
4177 binding_id: self.capture.captured_local(),
4178 }
4179 }
4180
4181 pub fn has_field_projections(&self) -> bool {
4183 self.capture
4184 .place
4185 .projections
4186 .iter()
4187 .any(|proj| matches!(proj.kind, hir_ty::closure_analysis::ProjectionKind::Field { .. }))
4188 }
4189
4190 pub fn usages(&self) -> CaptureUsages<'db> {
4191 CaptureUsages { parent: self.owner, sources: &self.capture.info.sources }
4192 }
4193
4194 pub fn kind(&self) -> CaptureKind {
4195 match self.capture.info.capture_kind {
4196 hir_ty::closure_analysis::UpvarCapture::ByValue => CaptureKind::Move,
4197 hir_ty::closure_analysis::UpvarCapture::ByUse => CaptureKind::SharedRef, hir_ty::closure_analysis::UpvarCapture::ByRef(
4199 hir_ty::closure_analysis::BorrowKind::Immutable,
4200 ) => CaptureKind::SharedRef,
4201 hir_ty::closure_analysis::UpvarCapture::ByRef(
4202 hir_ty::closure_analysis::BorrowKind::UniqueImmutable,
4203 ) => CaptureKind::UniqueSharedRef,
4204 hir_ty::closure_analysis::UpvarCapture::ByRef(
4205 hir_ty::closure_analysis::BorrowKind::Mutable,
4206 ) => CaptureKind::MutableRef,
4207 }
4208 }
4209
4210 pub fn place_to_name(&self, db: &dyn HirDatabase, edition: Edition) -> String {
4212 let mut result = self.local().name(db).display(db, edition).to_string();
4213 for (i, proj) in self.capture.place.projections.iter().enumerate() {
4214 match proj.kind {
4215 hir_ty::closure_analysis::ProjectionKind::Deref => {}
4216 hir_ty::closure_analysis::ProjectionKind::Field { field_idx, variant_idx } => {
4217 let ty = self.capture.place.ty_before_projection(i);
4218 match ty.kind() {
4219 TyKind::Tuple(_) => format_to!(result, "_{field_idx}"),
4220 TyKind::Adt(adt_def, _) => {
4221 let variant = match adt_def.def_id() {
4222 AdtId::StructId(id) => VariantId::from(id),
4223 AdtId::UnionId(id) => id.into(),
4224 AdtId::EnumId(id) => {
4225 id.enum_variants(db).variants[variant_idx as usize].0.into()
4226 }
4227 };
4228 let field = &variant.fields(db).fields()
4229 [LocalFieldId::from_raw(la_arena::RawIdx::from_u32(field_idx))];
4230 format_to!(result, "_{}", field.name.display(db, edition));
4231 }
4232 _ => never!("mismatching projection type"),
4233 }
4234 }
4235 _ => never!("unexpected projection kind"),
4236 }
4237 }
4238 result
4239 }
4240
4241 pub fn display_place_source_code(&self, db: &dyn HirDatabase, edition: Edition) -> String {
4242 let mut result = self.local().name(db).display(db, edition).to_string();
4243 let mut last_derefs = 0;
4245 for (i, proj) in self.capture.place.projections.iter().enumerate() {
4246 match proj.kind {
4247 hir_ty::closure_analysis::ProjectionKind::Deref => last_derefs += 1,
4248 hir_ty::closure_analysis::ProjectionKind::Field { field_idx, variant_idx } => {
4249 last_derefs = 0;
4250
4251 let ty = self.capture.place.ty_before_projection(i);
4252 match ty.kind() {
4253 TyKind::Tuple(_) => format_to!(result, ".{field_idx}"),
4254 TyKind::Adt(adt_def, _) => {
4255 let variant = match adt_def.def_id() {
4256 AdtId::StructId(id) => VariantId::from(id),
4257 AdtId::UnionId(id) => id.into(),
4258 AdtId::EnumId(id) => {
4259 id.enum_variants(db).variants[variant_idx as usize].0.into()
4261 }
4262 };
4263 let field = &variant.fields(db).fields()
4264 [LocalFieldId::from_raw(la_arena::RawIdx::from_u32(field_idx))];
4265 format_to!(result, ".{}", field.name.display(db, edition));
4266 }
4267 _ => never!("mismatching projection type"),
4268 }
4269 }
4270 _ => never!("unexpected projection kind"),
4271 }
4272 }
4273 result.insert_str(0, &"*".repeat(last_derefs));
4274 result
4275 }
4276
4277 pub fn ty(&self, db: &'db dyn HirDatabase) -> Type<'db> {
4278 Type::new_body(db, self.owner, self.capture.place.ty())
4279 }
4280
4281 pub fn captured_ty(&self, db: &'db dyn HirDatabase) -> Type<'db> {
4284 Type::new_body(db, self.owner, self.capture.captured_ty(db))
4285 }
4286}
4287
4288#[derive(Clone, Copy, PartialEq, Eq)]
4289pub enum CaptureKind {
4290 SharedRef,
4291 UniqueSharedRef,
4292 MutableRef,
4293 Move,
4294}
4295
4296#[derive(Debug, Clone)]
4297pub struct CaptureUsages<'db> {
4298 parent: ExpressionStoreOwnerId,
4299 sources: &'db [hir_ty::closure_analysis::CaptureSourceStack],
4300}
4301
4302impl CaptureUsages<'_> {
4303 fn is_ref(store: &ExpressionStore, id: ExprOrPatId) -> bool {
4304 match id {
4305 ExprOrPatId::ExprId(expr) => matches!(store[expr], Expr::Ref { .. }),
4306 ExprOrPatId::PatId(pat) => match store[pat] {
4308 Pat::Bind { id: binding, .. } => matches!(
4309 store[binding].mode,
4310 BindingAnnotation::Ref | BindingAnnotation::RefMut
4311 ),
4312 _ => false,
4313 },
4314 }
4315 }
4316
4317 pub fn sources(&self, db: &dyn HirDatabase) -> Vec<CaptureUsageSource> {
4318 let (store, source_map) = ExpressionStore::with_source_map(db, self.parent);
4319 let mut result = Vec::with_capacity(self.sources.len());
4320 for source in self.sources {
4321 let source = source.final_source();
4322 let is_ref = Self::is_ref(store, source.unpack());
4323 match source.unpack() {
4324 ExprOrPatId::ExprId(expr) => {
4325 if let Ok(expr) = source_map.expr_syntax(expr) {
4326 result.push(CaptureUsageSource { is_ref, source: expr })
4327 }
4328 }
4329 ExprOrPatId::PatId(pat) => {
4330 if let Ok(pat) = source_map.pat_syntax(pat) {
4331 result.push(CaptureUsageSource { is_ref, source: pat });
4332 }
4333 }
4334 }
4335 }
4336 result
4337 }
4338}
4339
4340#[derive(Debug)]
4341pub struct CaptureUsageSource {
4342 is_ref: bool,
4343 source: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
4344}
4345
4346impl CaptureUsageSource {
4347 pub fn source(&self) -> AstPtr<Either<ast::Expr, ast::Pat>> {
4348 self.source.value
4349 }
4350
4351 pub fn file_id(&self) -> HirFileId {
4352 self.source.file_id
4353 }
4354
4355 pub fn is_ref(&self) -> bool {
4356 self.is_ref
4357 }
4358}
4359
4360#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
4361enum TypeOwnerId {
4362 GenericDefId(GenericDefId),
4363 BuiltinDeriveImplId(BuiltinDeriveImplId),
4364 NoParams(base_db::Crate),
4366}
4367
4368impl_from!(
4369 GenericDefId,
4370 BuiltinDeriveImplId
4371 for TypeOwnerId
4372);
4373
4374impl TypeOwnerId {
4375 fn from_anon_const<'db>(id: AnonConstId<'db>, db: &'db dyn HirDatabase) -> TypeOwnerId {
4378 TypeOwnerId::GenericDefId(id.loc(db).owner.generic_def(db))
4379 }
4380
4381 fn unify(self, other: Self) -> Option<Self> {
4382 match (self, other) {
4383 (TypeOwnerId::NoParams(_), owner) => Some(owner),
4384 (owner, TypeOwnerId::NoParams(_)) => Some(owner),
4385 (_, _) => {
4386 if self == other {
4387 Some(self)
4388 } else {
4389 None
4390 }
4391 }
4392 }
4393 }
4394
4395 #[track_caller]
4396 fn must_unify(self, other: Self) -> Self {
4397 self.unify(other).expect("failed to unify type owners")
4398 }
4399
4400 fn can_rebase_into(
4401 self,
4402 db: &dyn HirDatabase,
4403 rebase_into: Self,
4404 self_ty: EarlyBinder<'_, Ty<'_>>,
4405 ) -> bool {
4406 if self == rebase_into || !self_ty.skip_binder().has_param() {
4407 return true;
4408 }
4409 let self_def = match self {
4410 TypeOwnerId::GenericDefId(def) => def,
4411 TypeOwnerId::BuiltinDeriveImplId(_) => return false,
4412 TypeOwnerId::NoParams(_) => return true,
4413 };
4414 let self_def = match self_def {
4415 GenericDefId::ImplId(def) => ItemContainerId::ImplId(def),
4416 GenericDefId::TraitId(def) => ItemContainerId::TraitId(def),
4417 GenericDefId::AdtId(_)
4418 | GenericDefId::ConstId(_)
4419 | GenericDefId::FunctionId(_)
4420 | GenericDefId::StaticId(_)
4421 | GenericDefId::TypeAliasId(_) => return false,
4422 };
4423 let rebase_into_def = match rebase_into {
4424 TypeOwnerId::GenericDefId(def) => def,
4425 TypeOwnerId::BuiltinDeriveImplId(_) | TypeOwnerId::NoParams(_) => return false,
4426 };
4427 let rebase_into_parent = match rebase_into_def {
4428 GenericDefId::ConstId(def) => def.loc(db).container,
4429 GenericDefId::FunctionId(def) => def.loc(db).container,
4430 GenericDefId::TypeAliasId(def) => def.loc(db).container,
4431 GenericDefId::AdtId(_)
4432 | GenericDefId::ImplId(_)
4433 | GenericDefId::StaticId(_)
4434 | GenericDefId::TraitId(_) => return false,
4435 };
4436 self_def == rebase_into_parent
4437 }
4438}
4439
4440#[derive(Clone, Debug)]
4443pub struct Type<'db> {
4444 owner: TypeOwnerId,
4445 ty: EarlyBinder<'db, Ty<'db>>,
4446}
4447
4448impl<'db> std::hash::Hash for Type<'db> {
4449 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
4450 self.ty.hash(state);
4453 }
4454}
4455
4456impl<'db> PartialEq for Type<'db> {
4457 fn eq(&self, other: &Self) -> bool {
4458 if self.ty != other.ty {
4459 return false;
4460 }
4461 hir_ty::with_attached_db(|db| {
4462 self.owner.can_rebase_into(db, other.owner, self.ty)
4463 || other.owner.can_rebase_into(db, self.owner, other.ty)
4464 })
4465 }
4466}
4467
4468impl<'db> Eq for Type<'db> {}
4469
4470impl<'db> Type<'db> {
4471 fn new(owner: GenericDefId, ty: Ty<'db>) -> Self {
4472 Type { owner: TypeOwnerId::GenericDefId(owner), ty: EarlyBinder::bind(ty) }
4473 }
4474
4475 fn new_body(db: &dyn HirDatabase, owner: ExpressionStoreOwnerId, ty: Ty<'db>) -> Self {
4476 Self::new(owner.generic_def(db), ty)
4477 }
4478
4479 fn no_params(krate: base_db::Crate, ty: Ty<'db>) -> Self {
4480 Type { owner: TypeOwnerId::NoParams(krate), ty: EarlyBinder::bind(ty) }
4481 }
4482
4483 fn builtin_type_crate(db: &'db dyn HirDatabase) -> base_db::Crate {
4484 all_crates(db)[0]
4486 }
4487
4488 fn from_def(db: &'db dyn HirDatabase, def: impl Into<TyDefId>) -> Self {
4489 let def = def.into();
4490 let ty = db.ty(def);
4491 let owner = match def {
4492 TyDefId::AdtId(it) => TypeOwnerId::GenericDefId(GenericDefId::AdtId(it)),
4493 TyDefId::TypeAliasId(it) => TypeOwnerId::GenericDefId(GenericDefId::TypeAliasId(it)),
4494 TyDefId::BuiltinType(_) => TypeOwnerId::NoParams(Self::builtin_type_crate(db)),
4495 };
4496 Type { owner, ty }
4497 }
4498
4499 fn from_value_def(db: &'db dyn HirDatabase, def: impl Into<ValueTyDefId>) -> Self {
4500 let def = def.into();
4501 let Some(ty) = db.value_ty(def) else {
4502 return Type::unknown();
4503 };
4504 let def = match def {
4505 ValueTyDefId::ConstId(it) => GenericDefId::ConstId(it),
4506 ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it),
4507 ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)),
4508 ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)),
4509 ValueTyDefId::EnumVariantId(it) => {
4510 GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent))
4511 }
4512 ValueTyDefId::StaticId(it) => {
4513 return Type::no_params(hir_def::HasModule::krate(&it, db), ty.skip_binder());
4514 }
4515 };
4516 Type::new(def, ty.instantiate_identity().skip_norm_wip())
4517 }
4518
4519 pub fn instantiate_with_errors(&self) -> Self {
4521 let interner = DbInterner::conjure();
4522 let krate = self.krate(interner.db());
4523 let args = match self.owner {
4524 TypeOwnerId::GenericDefId(def) => GenericArgs::error_for_item(interner, def.into()),
4525 TypeOwnerId::BuiltinDeriveImplId(def) => {
4526 GenericArgs::error_for_item(interner, def.into())
4527 }
4528 TypeOwnerId::NoParams(_) => GenericArgs::empty(),
4529 };
4530 Type::no_params(krate, self.ty.instantiate(interner, args).skip_norm_wip())
4531 }
4532
4533 pub fn instantiate(&self, args: impl IntoIterator<Item: Borrow<Type<'db>>>) -> Type<'db> {
4535 let interner = DbInterner::conjure();
4536 let (args, owner) = match self.owner {
4537 TypeOwnerId::GenericDefId(def) => generic_args_from_tys(interner, def.into(), args),
4538 TypeOwnerId::BuiltinDeriveImplId(def) => {
4539 generic_args_from_tys(interner, def.into(), args)
4540 }
4541 TypeOwnerId::NoParams(krate) => (GenericArgs::empty(), TypeOwnerId::NoParams(krate)),
4542 };
4543 Type { owner, ty: EarlyBinder::bind(self.ty.instantiate(interner, args).skip_norm_wip()) }
4544 }
4545
4546 fn instantiate_many_with_infer(
4548 tys: impl IntoIterator<Item: Borrow<Type<'db>>>,
4549 infcx: &InferCtxt<'db>,
4550 ) -> impl Iterator<Item = Ty<'db>> {
4551 let mut var_for_param = FxHashMap::default();
4552 tys.into_iter().map(move |ty| {
4553 let ty = ty.borrow();
4554 let owner = match ty.owner {
4555 TypeOwnerId::GenericDefId(def) => def.into(),
4556 TypeOwnerId::BuiltinDeriveImplId(def) => def.into(),
4557 TypeOwnerId::NoParams(_) => return ty.ty.skip_binder(),
4558 };
4559 let args = GenericArgs::for_item(infcx.interner, owner, |_, param, _, _| {
4560 *var_for_param
4561 .entry(param)
4562 .or_insert_with(|| infcx.var_for_def(param, hir_ty::Span::Dummy))
4563 });
4564
4565 ty.ty.instantiate(infcx.interner, args).skip_norm_wip()
4566 })
4567 }
4568
4569 pub fn try_rebase_into(
4574 &self,
4575 db: &'db dyn HirDatabase,
4576 rebase_into: &Type<'db>,
4577 ) -> Option<Self> {
4578 if self.owner.can_rebase_into(db, rebase_into.owner, self.ty) {
4579 Some(Type { owner: rebase_into.owner, ty: self.ty })
4580 } else {
4581 None
4582 }
4583 }
4584
4585 pub fn rebase_into_or_error(
4588 &self,
4589 db: &'db dyn HirDatabase,
4590 rebase_into: &Type<'db>,
4591 ) -> Type<'db> {
4592 self.try_rebase_into(db, rebase_into).unwrap_or_else(|| self.instantiate_with_errors())
4593 }
4594
4595 pub fn try_rebase_into_owner(
4596 &self,
4597 db: &'db dyn HirDatabase,
4598 new_owner: GenericDef,
4599 ) -> Option<Self> {
4600 let new_owner = new_owner.id()?.into();
4601 if self.owner.can_rebase_into(db, new_owner, self.ty) {
4602 Some(Type { owner: new_owner, ty: self.ty })
4603 } else {
4604 None
4605 }
4606 }
4607
4608 pub fn rebase_into_owner_or_error(
4609 &self,
4610 db: &'db dyn HirDatabase,
4611 new_owner: GenericDef,
4612 ) -> Self {
4613 self.try_rebase_into_owner(db, new_owner).unwrap_or_else(|| self.instantiate_with_errors())
4614 }
4615
4616 pub fn unknown() -> Self {
4617 let interner = DbInterner::conjure();
4618 Type::no_params(
4619 Self::builtin_type_crate(interner.db()),
4620 Ty::new_error(interner, ErrorGuaranteed),
4621 )
4622 }
4623
4624 pub fn new_slice(db: &'db dyn HirDatabase, ty: Self) -> Self {
4625 let interner = DbInterner::new_no_crate(db);
4626 Type { owner: ty.owner, ty: ty.ty.map_bound(|ty| Ty::new_slice(interner, ty)) }
4627 }
4628
4629 pub fn new_tuple(
4630 db: &'db dyn HirDatabase,
4631 tys: impl IntoIterator<Item: Borrow<Type<'db>>>,
4632 ) -> Self {
4633 let interner = DbInterner::new_no_crate(db);
4634 let mut owner = None::<TypeOwnerId>;
4635 let ty = EarlyBinder::bind(Ty::new_tup_from_iter(
4636 interner,
4637 tys.into_iter().map(|ty| {
4638 let ty = ty.borrow();
4639
4640 match &mut owner {
4641 Some(owner) => *owner = owner.must_unify(ty.owner),
4642 None => owner = Some(ty.owner),
4643 }
4644
4645 ty.ty.skip_binder()
4646 }),
4647 ));
4648 let owner =
4649 owner.unwrap_or_else(|| TypeOwnerId::NoParams(Self::builtin_type_crate(interner.db())));
4650 Type { owner, ty }
4651 }
4652
4653 pub fn new_unit() -> Self {
4654 let interner = DbInterner::conjure();
4655 Type::no_params(Self::builtin_type_crate(interner.db()), Ty::new_unit(interner))
4656 }
4657
4658 pub fn is_unit(&self) -> bool {
4659 self.ty.skip_binder().is_unit()
4660 }
4661
4662 pub fn is_bool(&self) -> bool {
4663 matches!(self.ty.skip_binder().kind(), TyKind::Bool)
4664 }
4665
4666 pub fn is_str(&self) -> bool {
4667 matches!(self.ty.skip_binder().kind(), TyKind::Str)
4668 }
4669
4670 pub fn is_never(&self) -> bool {
4671 matches!(self.ty.skip_binder().kind(), TyKind::Never)
4672 }
4673
4674 pub fn is_mutable_reference(&self) -> bool {
4675 matches!(
4676 self.ty.skip_binder().kind(),
4677 TyKind::Ref(.., hir_ty::next_solver::Mutability::Mut)
4678 )
4679 }
4680
4681 pub fn is_reference(&self) -> bool {
4682 matches!(self.ty.skip_binder().kind(), TyKind::Ref(..))
4683 }
4684
4685 pub fn contains_reference(&self, db: &'db dyn HirDatabase) -> bool {
4686 let interner = DbInterner::new_no_crate(db);
4687 return self
4688 .ty
4689 .instantiate_identity()
4690 .skip_norm_wip()
4691 .visit_with(&mut Visitor { interner })
4692 .is_break();
4693
4694 fn is_phantom_data(db: &dyn HirDatabase, adt_id: AdtId) -> bool {
4695 match adt_id {
4696 AdtId::StructId(s) => {
4697 let flags = StructSignature::of(db, s).flags;
4698 flags.contains(StructFlags::IS_PHANTOM_DATA)
4699 }
4700 AdtId::UnionId(_) | AdtId::EnumId(_) => false,
4701 }
4702 }
4703
4704 struct Visitor<'db> {
4705 interner: DbInterner<'db>,
4706 }
4707
4708 impl<'db> TypeVisitor<DbInterner<'db>> for Visitor<'db> {
4709 type Result = ControlFlow<()>;
4710
4711 fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
4712 match ty.kind() {
4713 TyKind::Ref(..) => ControlFlow::Break(()),
4715
4716 TyKind::Adt(adt_def, args)
4718 if !is_phantom_data(self.interner.db(), adt_def.def_id()) =>
4719 {
4720 let _variant_id_to_fields = |id: VariantId| {
4721 let variant_data = &id.fields(self.interner.db());
4722 if variant_data.fields().is_empty() {
4723 vec![]
4724 } else {
4725 let field_types = self.interner.db().field_types(id);
4726 variant_data
4727 .fields()
4728 .iter()
4729 .map(|(idx, _)| {
4730 field_types[idx]
4731 .ty()
4732 .instantiate(self.interner, args)
4733 .skip_norm_wip()
4734 })
4735 .filter(|it| !it.references_non_lt_error())
4736 .collect()
4737 }
4738 };
4739 let variant_id_to_fields = |_: VariantId| vec![];
4740
4741 let variants: Vec<Vec<Ty<'db>>> = match adt_def.def_id() {
4742 AdtId::StructId(id) => {
4743 vec![variant_id_to_fields(id.into())]
4744 }
4745 AdtId::EnumId(id) => id
4746 .enum_variants(self.interner.db())
4747 .variants
4748 .values()
4749 .map(|&(variant_id, _)| variant_id_to_fields(variant_id.into()))
4750 .collect(),
4751 AdtId::UnionId(id) => {
4752 vec![variant_id_to_fields(id.into())]
4753 }
4754 };
4755
4756 variants
4757 .into_iter()
4758 .flat_map(|variant| variant.into_iter())
4759 .try_for_each(|ty| ty.visit_with(self))?;
4760 args.visit_with(self)
4761 }
4762 _ => ty.super_visit_with(self),
4764 }
4765 }
4766 }
4767 }
4768
4769 pub fn as_reference(&self) -> Option<(Type<'db>, Mutability)> {
4770 let TyKind::Ref(_lt, ty, m) = self.ty.skip_binder().kind() else { return None };
4771 let m = Mutability::from_mutable(matches!(m, hir_ty::next_solver::Mutability::Mut));
4772 Some((self.derived(ty), m))
4773 }
4774
4775 pub fn as_reference_inner(&self) -> Option<Type<'db>> {
4776 self.as_reference().map(|(inner, _)| inner)
4777 }
4778
4779 pub fn add_reference(&self, db: &'db dyn HirDatabase, mutability: Mutability) -> Self {
4780 let interner = DbInterner::new_no_crate(db);
4781 let ty_mutability = match mutability {
4782 Mutability::Shared => hir_ty::next_solver::Mutability::Not,
4783 Mutability::Mut => hir_ty::next_solver::Mutability::Mut,
4784 };
4785 self.derived(Ty::new_ref(
4786 interner,
4787 Region::error(interner),
4788 self.ty.skip_binder(),
4789 ty_mutability,
4790 ))
4791 }
4792
4793 pub fn is_slice(&self) -> bool {
4794 matches!(self.ty.skip_binder().kind(), TyKind::Slice(..))
4795 }
4796
4797 pub fn is_usize(&self) -> bool {
4798 matches!(self.ty.skip_binder().kind(), TyKind::Uint(rustc_type_ir::UintTy::Usize))
4799 }
4800
4801 pub fn is_float(&self) -> bool {
4802 matches!(self.ty.skip_binder().kind(), TyKind::Float(_))
4803 }
4804
4805 pub fn is_char(&self) -> bool {
4806 matches!(self.ty.skip_binder().kind(), TyKind::Char)
4807 }
4808
4809 pub fn is_int_or_uint(&self) -> bool {
4810 matches!(self.ty.skip_binder().kind(), TyKind::Int(_) | TyKind::Uint(_))
4811 }
4812
4813 pub fn is_scalar(&self) -> bool {
4814 matches!(
4815 self.ty.skip_binder().kind(),
4816 TyKind::Bool | TyKind::Char | TyKind::Int(_) | TyKind::Uint(_) | TyKind::Float(_)
4817 )
4818 }
4819
4820 pub fn is_tuple(&self) -> bool {
4821 matches!(self.ty.skip_binder().kind(), TyKind::Tuple(..))
4822 }
4823
4824 pub fn as_slice(&self) -> Option<Type<'db>> {
4825 match self.ty.skip_binder().kind() {
4826 TyKind::Slice(ty) => Some(self.derived(ty)),
4827 _ => None,
4828 }
4829 }
4830
4831 pub fn strip_references(&self) -> Self {
4832 self.derived(self.ty.skip_binder().strip_references())
4833 }
4834
4835 pub fn strip_reference(&self) -> Self {
4837 self.derived(self.ty.skip_binder().strip_reference())
4838 }
4839
4840 pub fn is_unknown(&self) -> bool {
4841 self.ty.skip_binder().is_ty_error()
4842 }
4843
4844 fn krate(&self, db: &'db dyn HirDatabase) -> base_db::Crate {
4845 match self.owner {
4846 TypeOwnerId::GenericDefId(def) => hir_def::HasModule::krate(&def, db),
4847 TypeOwnerId::BuiltinDeriveImplId(def) => {
4848 hir_def::HasModule::krate(&def.loc(db).adt, db)
4849 }
4850 TypeOwnerId::NoParams(krate) => krate,
4851 }
4852 }
4853
4854 fn param_env(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> {
4855 let krate = self.krate(db);
4856 match self.owner {
4857 TypeOwnerId::GenericDefId(def) => {
4858 ParamEnvAndCrate { param_env: db.trait_environment(def), krate }
4859 }
4860 TypeOwnerId::BuiltinDeriveImplId(def) => ParamEnvAndCrate {
4861 param_env: hir_ty::builtin_derive::param_env(DbInterner::new_with(db, krate), def),
4862 krate,
4863 },
4864 TypeOwnerId::NoParams(_) => ParamEnvAndCrate { param_env: ParamEnv::empty(), krate },
4865 }
4866 }
4867
4868 pub fn into_future_output(&self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
4872 let env = self.param_env(db);
4873 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
4874 let (trait_, output_assoc_type) = lang_items
4875 .IntoFuture
4876 .zip(lang_items.IntoFutureOutput)
4877 .or(lang_items.Future.zip(lang_items.FutureOutput))?;
4878
4879 if !traits::implements_trait_unique(
4880 self.ty.instantiate_identity().skip_norm_wip(),
4881 db,
4882 env,
4883 trait_,
4884 ) {
4885 return None;
4886 }
4887
4888 self.normalize_trait_assoc_type(db, &[], output_assoc_type.into())
4889 }
4890
4891 pub fn future_output(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
4893 let krate = self.krate(db);
4894 let lang_items = hir_def::lang_item::lang_items(db, krate);
4895 let future_output = lang_items.FutureOutput?;
4896 self.normalize_trait_assoc_type(db, &[], future_output.into())
4897 }
4898
4899 pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
4901 let krate = self.krate(db);
4902 let lang_items = hir_def::lang_item::lang_items(db, krate);
4903 let iterator_item = lang_items.IteratorItem?;
4904 self.normalize_trait_assoc_type(db, &[], iterator_item.into())
4905 }
4906
4907 pub fn impls_iterator(self, db: &'db dyn HirDatabase) -> bool {
4908 let env = self.param_env(db);
4909 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
4910 let Some(iterator_trait) = lang_items.Iterator else {
4911 return false;
4912 };
4913 traits::implements_trait_unique(
4914 self.ty.instantiate_identity().skip_norm_wip(),
4915 db,
4916 env,
4917 iterator_trait,
4918 )
4919 }
4920
4921 pub fn into_iterator_iter(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
4923 let env = self.param_env(db);
4924 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
4925 let trait_ = lang_items.IntoIterator?;
4926
4927 if !traits::implements_trait_unique(
4928 self.ty.instantiate_identity().skip_norm_wip(),
4929 db,
4930 env,
4931 trait_,
4932 ) {
4933 return None;
4934 }
4935
4936 let into_iter_assoc_type = lang_items.IntoIterIntoIterType?;
4937 self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into())
4938 }
4939
4940 pub fn impls_fnonce(&self, db: &'db dyn HirDatabase) -> bool {
4945 let env = self.param_env(db);
4946 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
4947 let fnonce_trait = match lang_items.FnOnce {
4948 Some(it) => it,
4949 None => return false,
4950 };
4951
4952 traits::implements_trait_unique(
4953 self.ty.instantiate_identity().skip_norm_wip(),
4954 db,
4955 env,
4956 fnonce_trait,
4957 )
4958 }
4959
4960 pub fn impls_trait(&self, db: &'db dyn HirDatabase, trait_: Trait, args: &[Type<'db>]) -> bool {
4962 let env = self.param_env(db);
4963 let interner = DbInterner::new_no_crate(db);
4964 let (args, _owner) =
4965 generic_args_from_tys(interner, trait_.id.into(), iter::once(self).chain(args));
4966 traits::implements_trait_unique_with_args(db, env, trait_.id, args)
4967 }
4968
4969 pub fn has_any_impl(
4983 &self,
4984 db: &'db dyn HirDatabase,
4985 trait_: Trait,
4986 args: &[Type<'db>],
4987 ) -> bool {
4988 let env = ParamEnvAndCrate { param_env: ParamEnv::empty(), krate: self.krate(db) };
4989 traits::implements_trait_unique_with_infcx(db, env, trait_.id, &mut |infcx| {
4990 let mut args = Self::instantiate_many_with_infer(iter::once(self).chain(args), infcx);
4991 GenericArgs::for_item(infcx.interner, trait_.id.into(), |_, param, _, _| {
4992 if let GenericParamId::TypeParamId(_) = param
4993 && let Some(arg) = args.next()
4994 {
4995 arg.into()
4996 } else {
4997 infcx.var_for_def(param, hir_ty::Span::Dummy)
4998 }
4999 })
5000 })
5001 }
5002
5003 pub fn normalize_trait_assoc_type(
5004 &self,
5005 db: &'db dyn HirDatabase,
5006 args: &[Type<'db>],
5007 alias: TypeAlias,
5008 ) -> Option<Type<'db>> {
5009 let env = self.param_env(db);
5010 let interner = DbInterner::new_with(db, env.krate);
5011 let (args, owner) =
5012 generic_args_from_tys(interner, alias.id.into(), iter::once(self).chain(args));
5013 let projection = Ty::new_alias(
5015 interner,
5016 AliasTy::new_from_args(
5017 interner,
5018 AliasTyKind::Projection { def_id: alias.id.into() },
5019 args,
5020 ),
5021 );
5022
5023 let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
5024 let ty = structurally_normalize_ty(&infcx, projection, env.param_env);
5025 if ty.is_ty_error() { None } else { Some(Type { owner, ty: EarlyBinder::bind(ty) }) }
5026 }
5027
5028 pub fn is_copy(&self, db: &'db dyn HirDatabase) -> bool {
5029 let env = self.param_env(db);
5030 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
5031 let Some(copy_trait) = lang_items.Copy else {
5032 return false;
5033 };
5034 self.impls_trait(db, copy_trait.into(), &[])
5035 }
5036
5037 pub fn as_callable(&self, db: &'db dyn HirDatabase) -> Option<Callable<'db>> {
5038 let interner = DbInterner::new_no_crate(db);
5039 let callee = match self.ty.skip_binder().kind() {
5040 TyKind::Closure(id, subst) => Callee::Closure(id.0, subst),
5041 TyKind::CoroutineClosure(id, subst) => Callee::CoroutineClosure(id.0, subst),
5042 TyKind::FnPtr(..) => Callee::FnPtr,
5043 TyKind::FnDef(id, _) => Callee::Def(id.0),
5044 TyKind::Ref(_, inner_ty, _) => return self.derived(inner_ty).as_callable(db),
5046 _ => {
5047 let env = self.param_env(db);
5048 let (fn_trait, sig) =
5049 hir_ty::callable_sig_from_fn_trait(self.ty.skip_binder(), env, db)?;
5050 return Some(Callable {
5051 ty: self.clone(),
5052 sig,
5053 callee: Callee::FnImpl(fn_trait),
5054 is_bound_method: false,
5055 });
5056 }
5057 };
5058
5059 let sig = self.ty.skip_binder().callable_sig(interner)?;
5060 Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
5061 }
5062
5063 pub fn is_closure(&self) -> bool {
5064 matches!(self.ty.skip_binder().kind(), TyKind::Closure { .. })
5065 }
5066
5067 pub fn as_closure(&self) -> Option<Closure<'db>> {
5068 match self.ty.skip_binder().kind() {
5069 TyKind::Closure(id, subst) => {
5070 Some(Closure { id: AnyClosureId::ClosureId(id.0), subst, owner: self.owner })
5071 }
5072 TyKind::CoroutineClosure(id, subst) => Some(Closure {
5073 id: AnyClosureId::CoroutineClosureId(id.0),
5074 subst,
5075 owner: self.owner,
5076 }),
5077 _ => None,
5078 }
5079 }
5080
5081 pub fn as_coroutine(&self) -> Option<Coroutine<'db>> {
5083 match self.ty.skip_binder().kind() {
5084 TyKind::Coroutine(id, _) => Some(Coroutine { id: id.0 }),
5085 _ => None,
5086 }
5087 }
5088
5089 pub fn is_fn(&self) -> bool {
5090 matches!(self.ty.skip_binder().kind(), TyKind::FnDef(..) | TyKind::FnPtr { .. })
5091 }
5092
5093 pub fn is_array(&self) -> bool {
5094 matches!(self.ty.skip_binder().kind(), TyKind::Array(..))
5095 }
5096
5097 pub fn is_packed(&self, _db: &'db dyn HirDatabase) -> bool {
5098 match self.ty.skip_binder().kind() {
5099 TyKind::Adt(adt_def, ..) => adt_def.is_packed(),
5100 _ => false,
5101 }
5102 }
5103
5104 pub fn is_raw_ptr(&self) -> bool {
5105 matches!(self.ty.skip_binder().kind(), TyKind::RawPtr(..))
5106 }
5107
5108 pub fn is_mutable_raw_ptr(&self) -> bool {
5109 matches!(
5111 self.ty.skip_binder().kind(),
5112 TyKind::RawPtr(.., hir_ty::next_solver::Mutability::Mut)
5113 )
5114 }
5115
5116 pub fn as_raw_ptr(&self) -> Option<(Type<'db>, Mutability)> {
5117 let TyKind::RawPtr(ty, m) = self.ty.skip_binder().kind() else { return None };
5119 let m = Mutability::from_mutable(matches!(m, hir_ty::next_solver::Mutability::Mut));
5120 Some((self.derived(ty), m))
5121 }
5122
5123 pub fn remove_raw_ptr(&self) -> Option<Type<'db>> {
5124 if let TyKind::RawPtr(ty, _) = self.ty.skip_binder().kind() {
5125 Some(self.derived(ty))
5126 } else {
5127 None
5128 }
5129 }
5130
5131 pub fn contains_unknown(&self) -> bool {
5132 self.ty.skip_binder().references_non_lt_error()
5133 }
5134
5135 pub fn fields(&self, db: &'db dyn HirDatabase) -> Vec<(Field, Self)> {
5136 let interner = DbInterner::new_no_crate(db);
5137 let (variant_id, substs) = match self.ty.skip_binder().kind() {
5138 TyKind::Adt(adt_def, substs) => {
5139 let id = match adt_def.def_id() {
5140 AdtId::StructId(id) => id.into(),
5141 AdtId::UnionId(id) => id.into(),
5142 AdtId::EnumId(_) => return Vec::new(),
5143 };
5144 (id, substs)
5145 }
5146 _ => return Vec::new(),
5147 };
5148
5149 db.field_types(variant_id)
5150 .iter()
5151 .map(|(local_id, field)| {
5152 let def = Field { parent: variant_id.into(), id: local_id };
5153 let ty = field.ty().instantiate(interner, substs).skip_norm_wip();
5154 (def, self.derived(ty))
5155 })
5156 .collect()
5157 }
5158
5159 pub fn tuple_fields(&self, _db: &'db dyn HirDatabase) -> Vec<Self> {
5160 if let TyKind::Tuple(substs) = self.ty.skip_binder().kind() {
5161 substs.iter().map(|ty| self.derived(ty)).collect()
5162 } else {
5163 Vec::new()
5164 }
5165 }
5166
5167 pub fn as_array(&self, db: &'db dyn HirDatabase) -> Option<(Self, usize)> {
5168 if let TyKind::Array(ty, len) = self.ty.skip_binder().kind() {
5169 try_const_usize(db, len).map(|it| (self.derived(ty), it as usize))
5170 } else {
5171 None
5172 }
5173 }
5174
5175 pub fn fingerprint_for_trait_impl(
5177 &self,
5178 db: &'db dyn HirDatabase,
5179 ) -> Option<SimplifiedType<'db>> {
5180 fast_reject::simplify_type(
5181 DbInterner::new_no_crate(db),
5182 self.ty.skip_binder(),
5183 fast_reject::TreatParams::AsRigid,
5184 )
5185 }
5186
5187 pub fn autoderef(
5190 &self,
5191 db: &'db dyn HirDatabase,
5192 ) -> impl Iterator<Item = Type<'db>> + use<'_, 'db> {
5193 self.autoderef_(db).map(move |ty| self.derived(ty))
5194 }
5195
5196 fn autoderef_(&self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Ty<'db>> {
5197 let interner = DbInterner::new_no_crate(db);
5198 let env = self.param_env(db);
5199 let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty.skip_binder());
5201 autoderef(db, env, canonical)
5202 }
5203
5204 pub fn iterate_assoc_items<T>(
5207 &self,
5208 db: &'db dyn HirDatabase,
5209 mut callback: impl FnMut(AssocItem) -> Option<T>,
5210 ) -> Option<T> {
5211 let mut slot = None;
5212 self.iterate_assoc_items_dyn(db, &mut |assoc_item_id| {
5213 slot = callback(assoc_item_id.into());
5214 slot.is_some()
5215 });
5216 slot
5217 }
5218
5219 fn iterate_assoc_items_dyn(
5220 &self,
5221 db: &'db dyn HirDatabase,
5222 callback: &mut dyn FnMut(AssocItemId) -> bool,
5223 ) {
5224 let mut handle_impls = |impls: &[ImplId]| {
5225 for &impl_def in impls {
5226 for &(_, item) in impl_def.impl_items(db).items.iter() {
5227 if callback(item) {
5228 return;
5229 }
5230 }
5231 }
5232 };
5233 let krate = self.krate(db);
5234
5235 let interner = DbInterner::new_no_crate(db);
5236 let Some(simplified_type) = fast_reject::simplify_type(
5237 interner,
5238 self.ty.skip_binder(),
5239 fast_reject::TreatParams::AsRigid,
5240 ) else {
5241 return;
5242 };
5243
5244 method_resolution::with_incoherent_inherent_impls(
5245 db,
5246 krate,
5247 &simplified_type,
5248 &mut handle_impls,
5249 );
5250
5251 if let Some(module) = method_resolution::simplified_type_module(db, &simplified_type) {
5252 InherentImpls::for_each_crate_and_block(
5253 db,
5254 module.krate(db),
5255 module.block(db),
5256 &mut |impls| {
5257 handle_impls(impls.for_self_ty(&simplified_type));
5258 },
5259 );
5260 }
5261 }
5262
5263 pub fn type_arguments(&self) -> impl Iterator<Item = Type<'db>> + '_ {
5282 match self.ty.skip_binder().strip_references().kind() {
5283 TyKind::Adt(_, substs) => Either::Left(substs.types().map(move |ty| self.derived(ty))),
5284 TyKind::Tuple(substs) => {
5285 Either::Right(Either::Left(substs.iter().map(move |ty| self.derived(ty))))
5286 }
5287 _ => Either::Right(Either::Right(iter::empty())),
5288 }
5289 }
5290
5291 pub fn type_and_const_arguments<'a>(
5310 &'a self,
5311 db: &'a dyn HirDatabase,
5312 display_target: DisplayTarget,
5313 ) -> impl Iterator<Item = SmolStr> + 'a {
5314 self.ty
5315 .skip_binder()
5316 .strip_references()
5317 .as_adt()
5318 .into_iter()
5319 .flat_map(|(_, substs)| substs.iter())
5320 .filter_map(move |arg| match arg.kind() {
5321 rustc_type_ir::GenericArgKind::Type(ty) => {
5322 Some(format_smolstr!("{}", ty.display(db, display_target)))
5323 }
5324 rustc_type_ir::GenericArgKind::Const(const_) => {
5325 Some(format_smolstr!("{}", const_.display(db, display_target)))
5326 }
5327 rustc_type_ir::GenericArgKind::Lifetime(_) => None,
5328 })
5329 }
5330
5331 pub fn generic_parameters<'a>(
5333 &'a self,
5334 db: &'a dyn HirDatabase,
5335 display_target: DisplayTarget,
5336 ) -> impl Iterator<Item = SmolStr> + 'a {
5337 self.as_adt()
5339 .and_then(|a| {
5340 a.lifetime(db).map(|lt| lt.name.display_no_db(Edition::Edition2015).to_smolstr())
5342 })
5343 .into_iter()
5344 .chain(self.type_and_const_arguments(db, display_target))
5346 }
5347
5348 pub fn iterate_method_candidates_with_traits<T>(
5349 &self,
5350 db: &'db dyn HirDatabase,
5351 scope: &SemanticsScope<'_>,
5352 traits_in_scope: &FxHashSet<TraitId>,
5353 name: Option<&Name>,
5354 mut callback: impl FnMut(Function) -> Option<T>,
5355 ) -> Option<T> {
5356 let _p = tracing::info_span!("iterate_method_candidates_with_traits").entered();
5357 let mut slot = None;
5358 self.iterate_method_candidates_split_inherent(db, scope, traits_in_scope, name, |f| {
5359 match callback(f) {
5360 it @ Some(_) => {
5361 slot = it;
5362 ControlFlow::Break(())
5363 }
5364 None => ControlFlow::Continue(()),
5365 }
5366 });
5367 slot
5368 }
5369
5370 pub fn iterate_method_candidates<T>(
5371 &self,
5372 db: &'db dyn HirDatabase,
5373 scope: &SemanticsScope<'_>,
5374 name: Option<&Name>,
5375 callback: impl FnMut(Function) -> Option<T>,
5376 ) -> Option<T> {
5377 self.iterate_method_candidates_with_traits(
5378 db,
5379 scope,
5380 &scope.visible_traits().0,
5381 name,
5382 callback,
5383 )
5384 }
5385
5386 fn with_method_resolution<R>(
5387 &self,
5388 db: &'db dyn HirDatabase,
5389 resolver: &Resolver<'db>,
5390 traits_in_scope: &FxHashSet<TraitId>,
5391 f: impl FnOnce(&MethodResolutionContext<'_, 'db>) -> R,
5392 ) -> R {
5393 let module = resolver.module();
5394 let interner = DbInterner::new_with(db, module.krate(db));
5395 let typing_mode = if let Some(store_owner) = resolver.expression_store_owner() {
5400 TypingMode::analysis_in_body(interner, store_owner.into())
5401 } else {
5402 TypingMode::non_body_analysis()
5403 };
5404 let infcx = interner.infer_ctxt().build(typing_mode);
5405 let features = resolver.top_level_def_map().features();
5406 let environment = self.param_env(db);
5407 let ctx = MethodResolutionContext {
5408 infcx: &infcx,
5409 resolver,
5410 param_env: environment.param_env,
5411 traits_in_scope,
5412 edition: resolver.krate().data(db).edition,
5413 features,
5414 call_span: hir_ty::Span::Dummy,
5415 receiver_span: hir_ty::Span::Dummy,
5416 };
5417 f(&ctx)
5418 }
5419
5420 pub fn iterate_method_candidates_split_inherent(
5425 &self,
5426 db: &'db dyn HirDatabase,
5427 scope: &SemanticsScope<'_>,
5428 traits_in_scope: &FxHashSet<TraitId>,
5429 name: Option<&Name>,
5430 mut callback: impl MethodCandidateCallback,
5431 ) {
5432 let _p = tracing::info_span!(
5433 "iterate_method_candidates_split_inherent",
5434 traits_in_scope = traits_in_scope.len(),
5435 ?name,
5436 )
5437 .entered();
5438
5439 self.with_method_resolution(db, scope.resolver(), traits_in_scope, |ctx| {
5440 let canonical =
5442 hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty.skip_binder());
5443 let (self_ty, _) = ctx.infcx.instantiate_canonical(hir_ty::Span::Dummy, &canonical);
5444
5445 match name {
5446 Some(name) => {
5447 match ctx.probe_for_name(
5448 method_resolution::Mode::MethodCall,
5449 name.clone(),
5450 self_ty,
5451 ) {
5452 Ok(candidate)
5453 | Err(method_resolution::MethodError::PrivateMatch(candidate)) => {
5454 let method_resolution::CandidateId::FunctionId(id) = candidate.item
5455 else {
5456 unreachable!("`Mode::MethodCall` can only return functions");
5457 };
5458 let id = Function { id: AnyFunctionId::FunctionId(id) };
5459 match candidate.kind {
5460 method_resolution::PickKind::InherentImplPick(_)
5461 | method_resolution::PickKind::ObjectPick(..)
5462 | method_resolution::PickKind::WhereClausePick(..) => {
5463 _ = callback.on_inherent_method(id);
5465 }
5466 method_resolution::PickKind::TraitPick(..) => {
5467 _ = callback.on_trait_method(id);
5468 }
5469 }
5470 }
5471 Err(_) => {}
5472 };
5473 }
5474 None => {
5475 _ = ctx.probe_all(method_resolution::Mode::MethodCall, self_ty).try_for_each(
5476 |candidate| {
5477 let method_resolution::CandidateId::FunctionId(id) =
5478 candidate.candidate.item
5479 else {
5480 unreachable!("`Mode::MethodCall` can only return functions");
5481 };
5482 let id = Function { id: AnyFunctionId::FunctionId(id) };
5483 match candidate.candidate.kind {
5484 method_resolution::CandidateKind::InherentImplCandidate {
5485 ..
5486 }
5487 | method_resolution::CandidateKind::ObjectCandidate(..)
5488 | method_resolution::CandidateKind::WhereClauseCandidate(..) => {
5489 callback.on_inherent_method(id)
5491 }
5492 method_resolution::CandidateKind::TraitCandidate(..) => {
5493 callback.on_trait_method(id)
5494 }
5495 }
5496 },
5497 );
5498 }
5499 }
5500 })
5501 }
5502
5503 #[tracing::instrument(skip_all, fields(name = ?name))]
5504 pub fn iterate_path_candidates<T>(
5505 &self,
5506 db: &'db dyn HirDatabase,
5507 scope: &SemanticsScope<'_>,
5508 traits_in_scope: &FxHashSet<TraitId>,
5509 name: Option<&Name>,
5510 mut callback: impl FnMut(AssocItem) -> Option<T>,
5511 ) -> Option<T> {
5512 let _p = tracing::info_span!("iterate_path_candidates").entered();
5513 let mut slot = None;
5514
5515 self.iterate_path_candidates_split_inherent(db, scope, traits_in_scope, name, |item| {
5516 match callback(item) {
5517 it @ Some(_) => {
5518 slot = it;
5519 ControlFlow::Break(())
5520 }
5521 None => ControlFlow::Continue(()),
5522 }
5523 });
5524 slot
5525 }
5526
5527 #[tracing::instrument(skip_all, fields(name = ?name))]
5533 pub fn iterate_path_candidates_split_inherent(
5534 &self,
5535 db: &'db dyn HirDatabase,
5536 scope: &SemanticsScope<'_>,
5537 traits_in_scope: &FxHashSet<TraitId>,
5538 name: Option<&Name>,
5539 mut callback: impl PathCandidateCallback,
5540 ) {
5541 let _p = tracing::info_span!(
5542 "iterate_path_candidates_split_inherent",
5543 traits_in_scope = traits_in_scope.len(),
5544 ?name,
5545 )
5546 .entered();
5547
5548 self.with_method_resolution(db, scope.resolver(), traits_in_scope, |ctx| {
5549 let canonical =
5551 hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty.skip_binder());
5552 let (self_ty, _) = ctx.infcx.instantiate_canonical(hir_ty::Span::Dummy, &canonical);
5553
5554 match name {
5555 Some(name) => {
5556 match ctx.probe_for_name(method_resolution::Mode::Path, name.clone(), self_ty) {
5557 Ok(candidate)
5558 | Err(method_resolution::MethodError::PrivateMatch(candidate)) => {
5559 let id = candidate.item.into();
5560 match candidate.kind {
5561 method_resolution::PickKind::InherentImplPick(_)
5562 | method_resolution::PickKind::ObjectPick(..)
5563 | method_resolution::PickKind::WhereClausePick(..) => {
5564 _ = callback.on_inherent_item(id);
5566 }
5567 method_resolution::PickKind::TraitPick(..) => {
5568 _ = callback.on_trait_item(id);
5569 }
5570 }
5571 }
5572 Err(_) => {}
5573 };
5574 }
5575 None => {
5576 _ = ctx.probe_all(method_resolution::Mode::Path, self_ty).try_for_each(
5577 |candidate| {
5578 let id = candidate.candidate.item.into();
5579 match candidate.candidate.kind {
5580 method_resolution::CandidateKind::InherentImplCandidate {
5581 ..
5582 }
5583 | method_resolution::CandidateKind::ObjectCandidate(..)
5584 | method_resolution::CandidateKind::WhereClauseCandidate(..) => {
5585 callback.on_inherent_item(id)
5587 }
5588 method_resolution::CandidateKind::TraitCandidate(..) => {
5589 callback.on_trait_item(id)
5590 }
5591 }
5592 },
5593 );
5594 }
5595 }
5596 })
5597 }
5598
5599 pub fn as_adt(&self) -> Option<Adt> {
5600 let (adt, _subst) = self.ty.skip_binder().as_adt()?;
5601 Some(adt.into())
5602 }
5603
5604 pub fn as_adt_with_args(&self) -> Option<(Adt, Vec<Option<Type<'db>>>)> {
5606 let (adt, args) = self.ty.skip_binder().as_adt()?;
5607 let args = args.iter().map(|arg| Some(self.derived(arg.ty()?))).collect();
5608 Some((adt.into(), args))
5609 }
5610
5611 pub fn as_builtin(&self) -> Option<BuiltinType> {
5612 self.ty.skip_binder().as_builtin().map(|inner| BuiltinType { inner })
5613 }
5614
5615 pub fn as_dyn_trait(&self) -> Option<Trait> {
5616 self.ty.skip_binder().dyn_trait().map(Into::into)
5617 }
5618
5619 pub fn applicable_inherent_traits(
5622 &self,
5623 db: &'db dyn HirDatabase,
5624 ) -> impl Iterator<Item = Trait> {
5625 let _p = tracing::info_span!("applicable_inherent_traits").entered();
5626 self.autoderef_(db)
5627 .filter_map(|ty| ty.dyn_trait())
5628 .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db, dyn_trait_id))
5629 .copied()
5630 .map(Trait::from)
5631 }
5632
5633 pub fn env_traits(&self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Trait> {
5634 let _p = tracing::info_span!("env_traits").entered();
5635 let env = self.param_env(db);
5636 self.autoderef_(db)
5637 .filter(|ty| matches!(ty.kind(), TyKind::Param(_)))
5638 .flat_map(move |ty| {
5639 env.param_env
5640 .clauses()
5641 .iter()
5642 .filter_map(move |pred| match pred.kind().skip_binder() {
5643 ClauseKind::Trait(tr) if tr.self_ty() == ty => Some(tr.def_id().0),
5644 _ => None,
5645 })
5646 .flat_map(|t| hir_ty::all_super_traits(db, t))
5647 .copied()
5648 })
5649 .map(Trait::from)
5650 }
5651
5652 pub fn as_impl_traits(&self, db: &'db dyn HirDatabase) -> Option<impl Iterator<Item = Trait>> {
5653 self.ty.skip_binder().impl_trait_bounds(db).map(|it| {
5654 it.into_iter().filter_map(|pred| match pred.kind().skip_binder() {
5655 ClauseKind::Trait(trait_ref) => Some(Trait::from(trait_ref.def_id().0)),
5656 _ => None,
5657 })
5658 })
5659 }
5660
5661 pub fn as_associated_type_parent_trait(&self, db: &'db dyn HirDatabase) -> Option<Trait> {
5662 let TyKind::Alias(AliasTy { kind: AliasTyKind::Projection { def_id }, .. }) =
5663 self.ty.skip_binder().kind()
5664 else {
5665 return None;
5666 };
5667 match def_id.0.loc(db).container {
5668 ItemContainerId::TraitId(id) => Some(Trait { id }),
5669 _ => None,
5670 }
5671 }
5672
5673 fn derived(&self, ty: Ty<'db>) -> Self {
5674 Type { owner: self.owner, ty: EarlyBinder::bind(ty) }
5675 }
5676
5677 pub fn walk(&self, db: &'db dyn HirDatabase, callback: impl FnMut(Type<'db>)) {
5680 struct Visitor<'db, F> {
5681 db: &'db dyn HirDatabase,
5682 owner: TypeOwnerId,
5683 callback: F,
5684 visited: FxHashSet<Ty<'db>>,
5685 }
5686 impl<'db, F> TypeVisitor<DbInterner<'db>> for Visitor<'db, F>
5687 where
5688 F: FnMut(Type<'db>),
5689 {
5690 type Result = ();
5691
5692 fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
5693 if !self.visited.insert(ty) {
5694 return;
5695 }
5696
5697 (self.callback)(Type { owner: self.owner, ty: EarlyBinder::bind(ty) });
5698
5699 if let Some(bounds) = ty.impl_trait_bounds(self.db) {
5700 bounds.visit_with(self);
5701 }
5702
5703 ty.super_visit_with(self);
5704 }
5705 }
5706
5707 let mut visitor =
5708 Visitor { db, owner: self.owner, callback, visited: FxHashSet::default() };
5709 self.ty.skip_binder().visit_with(&mut visitor);
5710 }
5711 pub fn could_unify_with(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool {
5716 self.owner.must_unify(other.owner);
5717 let env = self.param_env(db);
5718 let interner = DbInterner::new_no_crate(db);
5719 let tys = hir_ty::replace_errors_with_variables(
5720 interner,
5721 &(self.ty.skip_binder(), other.ty.skip_binder()),
5722 );
5723 hir_ty::could_unify(db, env, &tys)
5724 }
5725
5726 pub fn could_unify_with_deeply(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool {
5731 self.owner.must_unify(other.owner);
5732 let env = self.param_env(db);
5733 let interner = DbInterner::new_no_crate(db);
5734 let tys = hir_ty::replace_errors_with_variables(
5735 interner,
5736 &(self.ty.skip_binder(), other.ty.skip_binder()),
5737 );
5738 hir_ty::could_unify_deeply(db, env, &tys)
5739 }
5740
5741 pub fn could_coerce_to(&self, db: &'db dyn HirDatabase, to: &Type<'db>) -> bool {
5742 self.owner.must_unify(to.owner);
5743 let env = self.param_env(db);
5744 let interner = DbInterner::new_no_crate(db);
5745 let tys = hir_ty::replace_errors_with_variables(
5746 interner,
5747 &(self.ty.skip_binder(), to.ty.skip_binder()),
5748 );
5749 hir_ty::could_coerce(db, env, &tys)
5750 }
5751
5752 pub fn as_type_param(&self, _db: &'db dyn HirDatabase) -> Option<TypeParam> {
5753 match self.ty.skip_binder().kind() {
5754 TyKind::Param(param) => Some(TypeParam { id: param.id }),
5755 _ => None,
5756 }
5757 }
5758
5759 pub fn generic_params(&self, db: &'db dyn HirDatabase) -> FxHashSet<GenericParam> {
5761 hir_ty::collect_params(&self.ty.skip_binder())
5762 .into_iter()
5763 .map(|id| TypeOrConstParam { id }.split(db).either_into())
5764 .collect()
5765 }
5766
5767 pub fn layout(&self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> {
5768 let env = self.param_env(db);
5769 db.layout_of_ty(self.ty.skip_binder().store(), env.store())
5770 .map(|layout| Layout(layout, db.target_data_layout(env.krate).unwrap()))
5771 }
5772
5773 pub fn drop_glue(&self, db: &'db dyn HirDatabase) -> DropGlue {
5774 let env = self.param_env(db);
5775 let interner = DbInterner::new_with(db, env.krate);
5776 let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
5777 hir_ty::drop::has_drop_glue(&infcx, self.ty.skip_binder(), env.param_env)
5778 }
5779}
5780
5781#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
5782pub struct InlineAsmOperand {
5783 owner: ExpressionStoreOwnerId,
5784 expr: ExprId,
5785 index: usize,
5786}
5787
5788impl InlineAsmOperand {
5789 pub fn parent(self, _db: &dyn HirDatabase) -> ExpressionStoreOwner {
5790 self.owner.into()
5791 }
5792
5793 pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
5794 let body = ExpressionStore::of(db, self.owner);
5795 match &body[self.expr] {
5796 hir_def::hir::Expr::InlineAsm(e) => e.operands.get(self.index)?.0.clone(),
5797 _ => None,
5798 }
5799 }
5800}
5801
5802#[derive(Debug)]
5804pub struct Callable<'db> {
5805 ty: Type<'db>,
5806 sig: PolyFnSig<'db>,
5807 callee: Callee<'db>,
5808 is_bound_method: bool,
5810}
5811
5812#[derive(Clone, PartialEq, Eq, Hash, Debug)]
5813enum Callee<'db> {
5814 Def(CallableDefId),
5815 Closure(InternedClosureId<'db>, GenericArgs<'db>),
5816 CoroutineClosure(InternedCoroutineClosureId<'db>, GenericArgs<'db>),
5817 FnPtr,
5818 FnImpl(traits::FnTrait),
5819 BuiltinDeriveImplMethod { method: BuiltinDeriveImplMethod, impl_: BuiltinDeriveImplId },
5820}
5821
5822pub enum CallableKind<'db> {
5823 Function(Function),
5824 TupleStruct(Struct),
5825 TupleEnumVariant(EnumVariant),
5826 Closure(Closure<'db>),
5827 FnPtr,
5828 FnImpl(FnTrait),
5829}
5830
5831impl<'db> Callable<'db> {
5832 fn erased_sig(&self) -> FnSig<'db> {
5833 DbInterner::conjure().instantiate_bound_regions_with_erased(self.sig)
5834 }
5835
5836 pub fn kind(&self) -> CallableKind<'db> {
5837 match self.callee {
5838 Callee::Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
5839 Callee::BuiltinDeriveImplMethod { method, impl_ } => CallableKind::Function(Function {
5840 id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ },
5841 }),
5842 Callee::Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
5843 Callee::Def(CallableDefId::EnumVariantId(it)) => {
5844 CallableKind::TupleEnumVariant(it.into())
5845 }
5846 Callee::Closure(id, subst) => CallableKind::Closure(Closure {
5847 id: AnyClosureId::ClosureId(id),
5848 subst,
5849 owner: self.ty.owner,
5850 }),
5851 Callee::CoroutineClosure(id, subst) => CallableKind::Closure(Closure {
5852 id: AnyClosureId::CoroutineClosureId(id),
5853 subst,
5854 owner: self.ty.owner,
5855 }),
5856 Callee::FnPtr => CallableKind::FnPtr,
5857 Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_.into()),
5858 }
5859 }
5860
5861 fn as_function(&self) -> Option<Function> {
5862 match self.callee {
5863 Callee::Def(CallableDefId::FunctionId(it)) => Some(it.into()),
5864 Callee::BuiltinDeriveImplMethod { method, impl_ } => {
5865 Some(Function { id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } })
5866 }
5867 _ => None,
5868 }
5869 }
5870
5871 pub fn receiver_param(&self, db: &'db dyn HirDatabase) -> Option<(SelfParam, Type<'db>)> {
5872 if !self.is_bound_method {
5873 return None;
5874 }
5875 let func = self.as_function()?;
5876 Some((func.self_param(db)?, self.ty.derived(self.erased_sig().inputs()[0])))
5877 }
5878 pub fn n_params(&self) -> usize {
5879 self.sig.skip_binder().inputs_and_output.inputs().len()
5880 - if self.is_bound_method { 1 } else { 0 }
5881 }
5882 pub fn params(&self) -> Vec<Param<'db>> {
5883 self.erased_sig()
5884 .inputs()
5885 .iter()
5886 .enumerate()
5887 .skip(if self.is_bound_method { 1 } else { 0 })
5888 .map(|(idx, ty)| (idx, self.ty.derived(*ty)))
5889 .map(|(idx, ty)| Param { func: self.callee.clone(), idx, ty })
5890 .collect()
5891 }
5892 pub fn return_type(&self) -> Type<'db> {
5893 self.ty.derived(self.erased_sig().output())
5894 }
5895 pub fn sig(&self) -> impl Eq {
5896 &self.sig
5897 }
5898
5899 pub fn ty(&self) -> &Type<'db> {
5900 &self.ty
5901 }
5902}
5903
5904#[derive(Clone, Debug, Eq, PartialEq)]
5905pub struct Layout<'db>(Arc<TyLayout>, &'db TargetDataLayout);
5906
5907impl<'db> Layout<'db> {
5908 pub fn size(&self) -> u64 {
5909 self.0.size.bytes()
5910 }
5911
5912 pub fn align(&self) -> u64 {
5913 self.0.align.bytes()
5914 }
5915
5916 pub fn niches(&self) -> Option<u128> {
5917 Some(self.0.largest_niche?.available(self.1))
5918 }
5919
5920 pub fn field_offset(&self, field: Field) -> Option<u64> {
5921 match self.0.fields {
5922 layout::FieldsShape::Primitive => None,
5923 layout::FieldsShape::Union(_) => Some(0),
5924 layout::FieldsShape::Array { stride, count } => {
5925 let i = u64::try_from(field.index()).ok()?;
5926 (i < count).then_some((stride * i).bytes())
5927 }
5928 layout::FieldsShape::Arbitrary { ref offsets, .. } => {
5929 Some(offsets.get(RustcFieldIdx(field.id))?.bytes())
5930 }
5931 }
5932 }
5933
5934 pub fn tuple_field_offset(&self, field: usize) -> Option<u64> {
5935 match self.0.fields {
5936 layout::FieldsShape::Primitive => None,
5937 layout::FieldsShape::Union(_) => Some(0),
5938 layout::FieldsShape::Array { stride, count } => {
5939 let i = u64::try_from(field).ok()?;
5940 (i < count).then_some((stride * i).bytes())
5941 }
5942 layout::FieldsShape::Arbitrary { ref offsets, .. } => {
5943 Some(offsets.get(RustcFieldIdx::new(field))?.bytes())
5944 }
5945 }
5946 }
5947
5948 pub fn tail_padding(&self, field_size: &mut impl FnMut(usize) -> Option<u64>) -> Option<u64> {
5949 match self.0.fields {
5950 layout::FieldsShape::Primitive => None,
5951 layout::FieldsShape::Union(_) => None,
5952 layout::FieldsShape::Array { stride, count } => count.checked_sub(1).and_then(|tail| {
5953 let tail_field_size = field_size(tail as usize)?;
5954 let offset = stride.bytes() * tail;
5955 self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size)
5956 }),
5957 layout::FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => {
5958 let tail = in_memory_order[in_memory_order.len().checked_sub(1)? as u32];
5959 let tail_field_size = field_size(tail.0.into_raw().into_u32() as usize)?;
5960 let offset = offsets.get(tail)?.bytes();
5961 self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size)
5962 }
5963 }
5964 }
5965
5966 pub fn largest_padding(
5967 &self,
5968 field_size: &mut impl FnMut(usize) -> Option<u64>,
5969 ) -> Option<u64> {
5970 match self.0.fields {
5971 layout::FieldsShape::Primitive => None,
5972 layout::FieldsShape::Union(_) => None,
5973 layout::FieldsShape::Array { stride: _, count: 0 } => None,
5974 layout::FieldsShape::Array { stride, .. } => {
5975 let size = field_size(0)?;
5976 stride.bytes().checked_sub(size)
5977 }
5978 layout::FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => {
5979 let mut reverse_index = vec![None; in_memory_order.len()];
5980 for (mem, src) in in_memory_order.iter().enumerate() {
5981 reverse_index[mem] =
5982 Some((src.0.into_raw().into_u32() as usize, offsets[*src].bytes()));
5983 }
5984 if reverse_index.iter().any(|it| it.is_none()) {
5985 stdx::never!();
5986 return None;
5987 }
5988 reverse_index
5989 .into_iter()
5990 .flatten()
5991 .chain(iter::once((0, self.0.size.bytes())))
5992 .array_windows()
5993 .filter_map(|[(i, start), (_, end)]| {
5994 let size = field_size(i)?;
5995 end.checked_sub(start)?.checked_sub(size)
5996 })
5997 .max()
5998 }
5999 }
6000 }
6001
6002 pub fn enum_tag_size(&self) -> Option<usize> {
6003 let tag_size =
6004 if let layout::Variants::Multiple { tag, tag_encoding, .. } = &self.0.variants {
6005 match tag_encoding {
6006 TagEncoding::Direct => tag.size(self.1).bytes_usize(),
6007 TagEncoding::Niche { .. } => 0,
6008 }
6009 } else {
6010 return None;
6011 };
6012 Some(tag_size)
6013 }
6014}
6015
6016#[derive(Copy, Clone, Debug, Eq, PartialEq)]
6017pub enum BindingMode {
6018 Move,
6019 Ref(Mutability),
6020}
6021
6022#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
6024pub enum ScopeDef<'db> {
6025 ModuleDef(ModuleDef),
6026 GenericParam(GenericParam),
6027 ImplSelfType(Impl),
6028 AdtSelfType(Adt),
6029 Local(Local<'db>),
6030 Label(Label),
6031 Unknown,
6032}
6033
6034impl ScopeDef<'_> {
6035 pub fn all_items(def: PerNs) -> ArrayVec<Self, 3> {
6036 let mut items = ArrayVec::new();
6037
6038 match (def.take_types(), def.take_values()) {
6039 (Some(m1), None) => items.push(ScopeDef::ModuleDef(m1.into())),
6040 (None, Some(m2)) => items.push(ScopeDef::ModuleDef(m2.into())),
6041 (Some(m1), Some(m2)) => {
6042 if m1 != m2 {
6046 items.push(ScopeDef::ModuleDef(m1.into()));
6047 items.push(ScopeDef::ModuleDef(m2.into()));
6048 } else {
6049 items.push(ScopeDef::ModuleDef(m1.into()));
6050 }
6051 }
6052 (None, None) => {}
6053 };
6054
6055 if let Some(macro_def_id) = def.take_macros() {
6056 items.push(ScopeDef::ModuleDef(ModuleDef::Macro(macro_def_id.into())));
6057 }
6058
6059 if items.is_empty() {
6060 items.push(ScopeDef::Unknown);
6061 }
6062
6063 items
6064 }
6065
6066 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
6067 match self {
6068 ScopeDef::ModuleDef(it) => it.attrs(db),
6069 ScopeDef::GenericParam(it) => Some(it.attrs(db)),
6070 ScopeDef::ImplSelfType(_)
6071 | ScopeDef::AdtSelfType(_)
6072 | ScopeDef::Local(_)
6073 | ScopeDef::Label(_)
6074 | ScopeDef::Unknown => None,
6075 }
6076 }
6077
6078 pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
6079 match self {
6080 ScopeDef::ModuleDef(it) => it.module(db).map(|m| m.krate(db)),
6081 ScopeDef::GenericParam(it) => Some(it.module(db).krate(db)),
6082 ScopeDef::ImplSelfType(_) => None,
6083 ScopeDef::AdtSelfType(it) => Some(it.module(db).krate(db)),
6084 ScopeDef::Local(it) => Some(it.module(db).krate(db)),
6085 ScopeDef::Label(it) => Some(it.module(db).krate(db)),
6086 ScopeDef::Unknown => None,
6087 }
6088 }
6089}
6090
6091impl_from!(
6092 impl<'db>
6093 ItemInNs { Types => ModuleDef, Values => ModuleDef, Macros => ModuleDef }
6094 for ScopeDef<'db>
6095);
6096
6097#[derive(Clone, Debug, PartialEq, Eq)]
6098pub struct Adjustment<'db> {
6099 pub source: Type<'db>,
6100 pub target: Type<'db>,
6101 pub kind: Adjust,
6102}
6103
6104#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6105pub enum Adjust {
6106 NeverToAny,
6108 Deref(Option<OverloadedDeref>),
6110 Borrow(AutoBorrow),
6112 Pointer(PointerCast),
6113}
6114
6115#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6116pub enum AutoBorrow {
6117 Ref(Mutability),
6119 RawPtr(Mutability),
6121}
6122
6123#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6124pub struct OverloadedDeref(pub Mutability);
6125
6126pub trait HasVisibility {
6127 fn visibility(&self, db: &dyn HirDatabase) -> Visibility;
6128 fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool {
6129 let vis = self.visibility(db);
6130 vis.is_visible_from(db, module.id)
6131 }
6132}
6133
6134#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6135pub enum PredicatePolarity {
6136 Positive,
6138 Negative,
6140}
6141
6142#[derive(Debug, Clone, PartialEq, Eq)]
6143pub struct TraitPredicate<'db> {
6144 inner: hir_ty::next_solver::TraitPredicate<'db>,
6145 owner: TypeOwnerId,
6146}
6147
6148impl<'db> TraitPredicate<'db> {
6149 pub fn polarity(&self) -> PredicatePolarity {
6150 match self.inner.polarity {
6151 rustc_type_ir::PredicatePolarity::Positive => PredicatePolarity::Positive,
6152 rustc_type_ir::PredicatePolarity::Negative => PredicatePolarity::Negative,
6153 }
6154 }
6155
6156 pub fn trait_ref(&self) -> TraitRef<'db> {
6157 TraitRef { owner: self.owner, trait_ref: self.inner.trait_ref }
6158 }
6159}
6160
6161pub trait HasCrate {
6163 fn krate(&self, db: &dyn HirDatabase) -> Crate;
6164}
6165
6166impl<T: hir_def::HasModule> HasCrate for T {
6167 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6168 self.module(db).krate(db).into()
6169 }
6170}
6171
6172impl HasCrate for AssocItem {
6173 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6174 self.module(db).krate(db)
6175 }
6176}
6177
6178impl HasCrate for Struct {
6179 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6180 self.module(db).krate(db)
6181 }
6182}
6183
6184impl HasCrate for Union {
6185 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6186 self.module(db).krate(db)
6187 }
6188}
6189
6190impl HasCrate for Enum {
6191 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6192 self.module(db).krate(db)
6193 }
6194}
6195
6196impl HasCrate for Field {
6197 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6198 self.parent_def(db).module(db).krate(db)
6199 }
6200}
6201
6202impl HasCrate for EnumVariant {
6203 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6204 self.module(db).krate(db)
6205 }
6206}
6207
6208impl HasCrate for Function {
6209 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6210 self.module(db).krate(db)
6211 }
6212}
6213
6214impl HasCrate for Const {
6215 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6216 self.module(db).krate(db)
6217 }
6218}
6219
6220impl HasCrate for TypeAlias {
6221 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6222 self.module(db).krate(db)
6223 }
6224}
6225
6226impl HasCrate for Type<'_> {
6227 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6228 self.krate(db).into()
6229 }
6230}
6231
6232impl HasCrate for Macro {
6233 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6234 self.module(db).krate(db)
6235 }
6236}
6237
6238impl HasCrate for Trait {
6239 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6240 self.module(db).krate(db)
6241 }
6242}
6243
6244impl HasCrate for Static {
6245 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6246 self.module(db).krate(db)
6247 }
6248}
6249
6250impl HasCrate for Adt {
6251 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6252 self.module(db).krate(db)
6253 }
6254}
6255
6256impl HasCrate for Impl {
6257 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6258 self.module(db).krate(db)
6259 }
6260}
6261
6262impl HasCrate for Module {
6263 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6264 Module::krate(*self, db)
6265 }
6266}
6267
6268impl<'db> HasCrate for AnonConst<'db> {
6269 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6270 hir_def::HasModule::krate(&self.id.loc(db).owner, db).into()
6271 }
6272}
6273
6274pub trait HasContainer {
6275 fn container(&self, db: &dyn HirDatabase) -> ItemContainer;
6276}
6277
6278impl HasContainer for ExternCrateDecl {
6279 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6280 container_id_to_hir(self.id.lookup(db).container.into())
6281 }
6282}
6283
6284impl HasContainer for Module {
6285 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6286 let def_map = self.id.def_map(db);
6288 match def_map[self.id].parent {
6289 Some(parent_id) => ItemContainer::Module(Module { id: parent_id }),
6290 None => ItemContainer::Crate(def_map.krate().into()),
6291 }
6292 }
6293}
6294
6295impl HasContainer for Function {
6296 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6297 match self.id {
6298 AnyFunctionId::FunctionId(id) => container_id_to_hir(id.lookup(db).container),
6299 AnyFunctionId::BuiltinDeriveImplMethod { impl_, .. } => {
6300 ItemContainer::Impl(Impl { id: AnyImplId::BuiltinDeriveImplId(impl_) })
6301 }
6302 }
6303 }
6304}
6305
6306impl HasContainer for Struct {
6307 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6308 ItemContainer::Module(Module { id: self.id.lookup(db).container })
6309 }
6310}
6311
6312impl HasContainer for Union {
6313 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6314 ItemContainer::Module(Module { id: self.id.lookup(db).container })
6315 }
6316}
6317
6318impl HasContainer for Enum {
6319 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6320 ItemContainer::Module(Module { id: self.id.lookup(db).container })
6321 }
6322}
6323
6324impl HasContainer for TypeAlias {
6325 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6326 container_id_to_hir(self.id.lookup(db).container)
6327 }
6328}
6329
6330impl HasContainer for Const {
6331 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6332 container_id_to_hir(self.id.lookup(db).container)
6333 }
6334}
6335
6336impl HasContainer for Static {
6337 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6338 container_id_to_hir(self.id.lookup(db).container)
6339 }
6340}
6341
6342impl HasContainer for Trait {
6343 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6344 ItemContainer::Module(Module { id: self.id.lookup(db).container })
6345 }
6346}
6347
6348impl HasContainer for ExternBlock {
6349 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6350 ItemContainer::Module(Module { id: self.id.lookup(db).container })
6351 }
6352}
6353
6354pub trait HasName {
6355 fn name(&self, db: &dyn HirDatabase) -> Option<Name>;
6356}
6357
6358macro_rules! impl_has_name {
6359 ( $( $ty:ident ),* $(,)? ) => {
6360 $(
6361 impl HasName for $ty {
6362 fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
6363 (*self).name(db).into()
6364 }
6365 }
6366 )*
6367 };
6368}
6369
6370impl_has_name!(
6371 ModuleDef,
6372 Module,
6373 Field,
6374 Struct,
6375 Union,
6376 Enum,
6377 EnumVariant,
6378 Adt,
6379 Variant,
6380 DefWithBody,
6381 Function,
6382 ExternCrateDecl,
6383 Const,
6384 Static,
6385 Trait,
6386 TypeAlias,
6387 Macro,
6388 ExternAssocItem,
6389 AssocItem,
6390 DeriveHelper,
6391 ToolModule,
6392 Label,
6393 GenericParam,
6394 TypeParam,
6395 LifetimeParam,
6396 ConstParam,
6397 TypeOrConstParam,
6398 InlineAsmOperand,
6399);
6400
6401macro_rules! impl_has_name_no_db {
6402 ( $( $ty:ident ),* $(,)? ) => {
6403 $(
6404 impl HasName for $ty {
6405 fn name(&self, _db: &dyn HirDatabase) -> Option<Name> {
6406 (*self).name().into()
6407 }
6408 }
6409 )*
6410 };
6411}
6412
6413impl_has_name_no_db!(StaticLifetime, BuiltinType, BuiltinAttr);
6414
6415impl HasName for Local<'_> {
6416 fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
6417 (*self).name(db).into()
6418 }
6419}
6420
6421impl HasName for TupleField<'_> {
6422 fn name(&self, _db: &dyn HirDatabase) -> Option<Name> {
6423 (*self).name().into()
6424 }
6425}
6426
6427impl HasName for Param<'_> {
6428 fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
6429 self.name(db)
6430 }
6431}
6432
6433fn container_id_to_hir(c: ItemContainerId) -> ItemContainer {
6434 match c {
6435 ItemContainerId::ExternBlockId(id) => ItemContainer::ExternBlock(ExternBlock { id }),
6436 ItemContainerId::ModuleId(id) => ItemContainer::Module(Module { id }),
6437 ItemContainerId::ImplId(id) => ItemContainer::Impl(id.into()),
6438 ItemContainerId::TraitId(id) => ItemContainer::Trait(Trait { id }),
6439 }
6440}
6441
6442#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6443pub enum ItemContainer {
6444 Trait(Trait),
6445 Impl(Impl),
6446 Module(Module),
6447 ExternBlock(ExternBlock),
6448 Crate(Crate),
6449}
6450
6451pub enum DocLinkDef {
6453 ModuleDef(ModuleDef),
6454 Field(Field),
6455 SelfType(Trait),
6456}
6457
6458pub trait MethodCandidateCallback {
6459 fn on_inherent_method(&mut self, f: Function) -> ControlFlow<()>;
6460
6461 fn on_trait_method(&mut self, f: Function) -> ControlFlow<()>;
6462}
6463
6464impl<F> MethodCandidateCallback for F
6465where
6466 F: FnMut(Function) -> ControlFlow<()>,
6467{
6468 fn on_inherent_method(&mut self, f: Function) -> ControlFlow<()> {
6469 self(f)
6470 }
6471
6472 fn on_trait_method(&mut self, f: Function) -> ControlFlow<()> {
6473 self(f)
6474 }
6475}
6476
6477pub trait PathCandidateCallback {
6478 fn on_inherent_item(&mut self, item: AssocItem) -> ControlFlow<()>;
6479
6480 fn on_trait_item(&mut self, item: AssocItem) -> ControlFlow<()>;
6481}
6482
6483impl<F> PathCandidateCallback for F
6484where
6485 F: FnMut(AssocItem) -> ControlFlow<()>,
6486{
6487 fn on_inherent_item(&mut self, item: AssocItem) -> ControlFlow<()> {
6488 self(item)
6489 }
6490
6491 fn on_trait_item(&mut self, item: AssocItem) -> ControlFlow<()> {
6492 self(item)
6493 }
6494}
6495
6496pub fn resolve_absolute_path<'a, I: Iterator<Item = Symbol> + Clone + 'a>(
6497 db: &'a dyn HirDatabase,
6498 mut segments: I,
6499) -> impl Iterator<Item = ItemInNs> + use<'a, I> {
6500 segments
6501 .next()
6502 .into_iter()
6503 .flat_map(move |crate_name| {
6504 all_crates(db)
6505 .iter()
6506 .filter(|&krate| {
6507 krate
6508 .extra_data(db)
6509 .display_name
6510 .as_ref()
6511 .is_some_and(|name| *name.crate_name().symbol() == crate_name)
6512 })
6513 .filter_map(|&krate| {
6514 let segments = segments.clone();
6515 let mut def_map = crate_def_map(db, krate);
6516 let mut module = &def_map[def_map.root_module_id()];
6517 let mut segments = segments.with_position().peekable();
6518 while let Some((_, segment)) =
6519 segments.next_if(|&(position, _)| !position.is_last)
6520 {
6521 let res = module
6522 .scope
6523 .get(&Name::new_symbol_root(segment))
6524 .take_types()
6525 .and_then(|res| match res {
6526 ModuleDefId::ModuleId(it) => Some(it),
6527 _ => None,
6528 })?;
6529 def_map = res.def_map(db);
6530 module = &def_map[res];
6531 }
6532 let (_, item_name) = segments.next()?;
6533 let res = module.scope.get(&Name::new_symbol_root(item_name));
6534 Some(res.iter_items().map(|(item, _)| item.into()))
6535 })
6536 .collect::<Vec<_>>()
6537 })
6538 .flatten()
6539}
6540
6541fn as_name_opt(name: Option<impl AsName>) -> Name {
6542 name.map_or_else(Name::missing, |name| name.as_name())
6543}
6544
6545#[track_caller]
6546fn generic_args_from_tys<'db>(
6547 interner: DbInterner<'db>,
6548 def_id: SolverDefId<'db>,
6549 args: impl IntoIterator<Item: Borrow<Type<'db>>>,
6550) -> (GenericArgs<'db>, TypeOwnerId) {
6551 let mut owner = None::<TypeOwnerId>;
6552 let mut args = args.into_iter();
6553 let args = GenericArgs::for_item(interner, def_id, |_, id, _, _| {
6554 if matches!(id, GenericParamId::TypeParamId(_))
6555 && let Some(arg) = args.next()
6556 {
6557 let arg = arg.borrow();
6558
6559 match &mut owner {
6560 Some(owner) => *owner = owner.must_unify(arg.owner),
6561 None => owner = Some(arg.owner),
6562 }
6563
6564 arg.ty.skip_binder().into()
6565 } else {
6566 next_solver::GenericArg::error_from_id(interner, id)
6567 }
6568 });
6569 let owner =
6570 owner.unwrap_or_else(|| TypeOwnerId::NoParams(Type::builtin_type_crate(interner.db())));
6571 (args, owner)
6572}
6573
6574fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId) -> bool {
6575 let params = GenericParams::of(db, generic_def);
6576 let defaults = db.generic_defaults(generic_def);
6577 params
6578 .iter_type_or_consts()
6579 .filter(|(_, param)| matches!(param, TypeOrConstParamData::TypeParamData(_)))
6580 .map(|(local_id, _)| TypeOrConstParamId { parent: generic_def, local_id })
6581 .any(|param| {
6582 let param = hir_ty::type_or_const_param_idx(db, param);
6583 defaults.get(param as usize).is_none()
6584 })
6585}
6586
6587fn param_env_from_has_crate<'db>(
6588 db: &'db dyn HirDatabase,
6589 id: impl hir_def::HasModule + Into<GenericDefId> + Copy,
6590) -> ParamEnvAndCrate<'db> {
6591 ParamEnvAndCrate { param_env: db.trait_environment(id.into()), krate: id.krate(db) }
6592}
6593
6594pub trait MacroCallIdExt {
6596 fn loc(self, db: &dyn HirDatabase) -> &hir_expand::MacroCallLoc;
6597}
6598impl MacroCallIdExt for span::MacroCallId {
6599 #[inline]
6600 fn loc(self, db: &dyn HirDatabase) -> &hir_expand::MacroCallLoc {
6601 hir_expand::MacroCallId::from(self).loc(db)
6602 }
6603}
6604
6605fn struct_tail_raw<'db>(
6607 db: &'db dyn HirDatabase,
6608 interner: DbInterner<'db>,
6609 mut ty: Ty<'db>,
6610 mut normalize: impl FnMut(Ty<'db>) -> Ty<'db>,
6611) -> Ty<'db> {
6612 let recursion_limit = 16;
6613 for iteration in 0.. {
6614 if iteration >= recursion_limit {
6615 return Ty::new_error(interner, ErrorGuaranteed);
6616 }
6617 match ty.kind() {
6618 TyKind::Adt(def, args) => {
6619 let AdtId::StructId(def_id) = def.def_id() else { break };
6620 let last_field = db.field_types(def_id.into()).iter().next_back();
6621 match last_field {
6622 Some((_, field)) => {
6623 ty = normalize(field.ty().instantiate(interner, args).skip_norm_wip())
6624 }
6625 None => break,
6626 }
6627 }
6628 TyKind::Tuple(tys) if let Some((&last_ty, _)) = tys.split_last() => {
6629 ty = last_ty;
6630 }
6631 TyKind::Tuple(_) => break,
6632 TyKind::Pat(inner, _) => {
6633 ty = inner;
6634 }
6635 _ => {
6636 break;
6637 }
6638 }
6639 }
6640 ty
6641}