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: self.id.into(), 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 interner = DbInterner::new_no_crate(db);
1310 let ty = self.id.loc(db).ty.get().instantiate_identity().skip_norm_wip();
1311 db.anon_const_eval(self.id, GenericArgs::empty(interner), None).map(|it| EvaluatedConst {
1312 allocation: it,
1313 def: self.id.into(),
1314 ty,
1315 })
1316 }
1317}
1318
1319#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1320pub enum InferBody<'db> {
1321 Body(DefWithBody),
1322 AnonConst(AnonConst<'db>),
1323}
1324
1325#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1326pub enum ExpressionStoreOwner {
1327 Body(DefWithBody),
1328 Signature(GenericDef),
1329 VariantFields(Variant),
1330}
1331
1332impl From<GenericDef> for ExpressionStoreOwner {
1333 fn from(v: GenericDef) -> Self {
1334 Self::Signature(v)
1335 }
1336}
1337
1338impl From<DefWithBody> for ExpressionStoreOwner {
1339 fn from(v: DefWithBody) -> Self {
1340 Self::Body(v)
1341 }
1342}
1343
1344impl_from!(
1345 ExpressionStoreOwnerId {
1346 Signature => Signature,
1347 Body => Body,
1348 VariantFields => VariantFields,
1349 }
1350 for ExpressionStoreOwner
1351);
1352
1353impl ExpressionStoreOwner {
1354 pub fn module(self, db: &dyn HirDatabase) -> Module {
1355 match self {
1356 Self::Body(body) => body.module(db),
1357 Self::Signature(generic_def) => generic_def.module(db),
1358 Self::VariantFields(variant) => variant.module(db),
1359 }
1360 }
1361}
1362
1363#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1365pub enum DefWithBody {
1366 Function(Function),
1367 Static(Static),
1368 Const(Const),
1369 EnumVariant(EnumVariant),
1370}
1371impl_from!(Function, Const, Static, EnumVariant for DefWithBody);
1372
1373impl DefWithBody {
1374 pub fn module(self, db: &dyn HirDatabase) -> Module {
1375 match self {
1376 DefWithBody::Const(c) => c.module(db),
1377 DefWithBody::Function(f) => f.module(db),
1378 DefWithBody::Static(s) => s.module(db),
1379 DefWithBody::EnumVariant(v) => v.module(db),
1380 }
1381 }
1382
1383 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
1384 match self {
1385 DefWithBody::Function(f) => Some(f.name(db)),
1386 DefWithBody::Static(s) => Some(s.name(db)),
1387 DefWithBody::Const(c) => c.name(db),
1388 DefWithBody::EnumVariant(v) => Some(v.name(db)),
1389 }
1390 }
1391
1392 pub fn body_type(self, db: &dyn HirDatabase) -> Type<'_> {
1394 match self {
1395 DefWithBody::Function(it) => it.ret_type(db),
1396 DefWithBody::Static(it) => it.ty(db),
1397 DefWithBody::Const(it) => it.ty(db),
1398 DefWithBody::EnumVariant(it) => it.parent_enum(db).variant_body_ty(db),
1399 }
1400 }
1401
1402 fn id(&self) -> Option<DefWithBodyId> {
1403 Some(match self {
1404 DefWithBody::Function(it) => match it.id {
1405 AnyFunctionId::FunctionId(id) => id.into(),
1406 AnyFunctionId::BuiltinDeriveImplMethod { .. } => return None,
1407 },
1408 DefWithBody::Static(it) => it.id.into(),
1409 DefWithBody::Const(it) => it.id.into(),
1410 DefWithBody::EnumVariant(it) => it.id.into(),
1411 })
1412 }
1413
1414 #[deprecated = "you should really not use this, this is exported for analysis-stats only"]
1415 pub fn run_mir_body(self, db: &dyn HirDatabase) -> Result<(), MirLowerError<'_>> {
1416 let Some(id) = self.id() else { return Ok(()) };
1417 db.mir_body(id.into()).map(drop)
1418 }
1419
1420 pub fn debug_hir(self, db: &dyn HirDatabase) -> String {
1422 let Some(id) = self.id() else {
1423 return String::new();
1424 };
1425 let body = Body::of(db, id);
1426 body.pretty_print(db, id, Edition::CURRENT)
1427 }
1428
1429 pub fn debug_mir(self, db: &dyn HirDatabase) -> String {
1431 let Some(id) = self.id() else {
1432 return String::new();
1433 };
1434 let body = db.mir_body(id.into());
1435 match body {
1436 Ok(body) => body.pretty_print(db, self.module(db).krate(db).to_display_target(db)),
1437 Err(e) => format!("error:\n{e:?}"),
1438 }
1439 }
1440
1441 pub fn expression_types<'db>(
1443 self,
1444 db: &'db dyn HirDatabase,
1445 ) -> impl Iterator<Item = Type<'db>> {
1446 self.id().into_iter().flat_map(move |def_id| {
1447 let infer = InferenceResult::of(db, def_id);
1448 let def_id = def_id.generic_def(db);
1449
1450 infer.expression_types().map(move |(_, ty)| Type::new(def_id, ty))
1451 })
1452 }
1453
1454 pub fn pattern_types<'db>(self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Type<'db>> {
1456 self.id().into_iter().flat_map(move |def_id| {
1457 let infer = InferenceResult::of(db, def_id);
1458 let def_id = def_id.generic_def(db);
1459
1460 infer.pattern_types().map(move |(_, ty)| Type::new(def_id, ty))
1461 })
1462 }
1463
1464 pub fn binding_types<'db>(self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Type<'db>> {
1466 self.id().into_iter().flat_map(move |def_id| {
1467 let infer = InferenceResult::of(db, def_id);
1468 let def_id = def_id.generic_def(db);
1469
1470 infer.binding_types().map(move |(_, ty)| Type::new(def_id, ty))
1471 })
1472 }
1473}
1474
1475#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1476enum AnyFunctionId {
1477 FunctionId(FunctionId),
1478 BuiltinDeriveImplMethod { method: BuiltinDeriveImplMethod, impl_: BuiltinDeriveImplId },
1479}
1480
1481#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1482pub struct Function {
1483 pub(crate) id: AnyFunctionId,
1484}
1485
1486impl fmt::Debug for Function {
1487 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1488 fmt::Debug::fmt(&self.id, f)
1489 }
1490}
1491
1492impl Function {
1493 pub fn lang(db: &dyn HirDatabase, krate: Crate, lang_item: LangItem) -> Option<Function> {
1494 let lang_items = hir_def::lang_item::lang_items(db, krate.id);
1495 match lang_item.from_lang_items(lang_items)? {
1496 LangItemTarget::FunctionId(it) => Some(it.into()),
1497 _ => None,
1498 }
1499 }
1500
1501 pub fn module(self, db: &dyn HirDatabase) -> Module {
1502 match self.id {
1503 AnyFunctionId::FunctionId(id) => id.module(db).into(),
1504 AnyFunctionId::BuiltinDeriveImplMethod { impl_, .. } => impl_.module(db).into(),
1505 }
1506 }
1507
1508 pub fn name(self, db: &dyn HirDatabase) -> Name {
1509 match self.id {
1510 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).name.clone(),
1511 AnyFunctionId::BuiltinDeriveImplMethod { method, .. } => {
1512 Name::new_symbol_root(method.name())
1513 }
1514 }
1515 }
1516
1517 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
1518 match self.id {
1519 AnyFunctionId::FunctionId(id) => Type::from_value_def(db, id),
1520 AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } => {
1521 let Some(trait_method) = method.trait_method(db, impl_) else {
1525 return Type::unknown();
1526 };
1527 Function::from(trait_method).ty(db)
1528 }
1529 }
1530 }
1531
1532 pub fn fn_ptr_type(self, db: &dyn HirDatabase) -> Type<'_> {
1533 match self.id {
1534 AnyFunctionId::FunctionId(id) => {
1535 let interner = DbInterner::new_no_crate(db);
1536 let callable_sig =
1537 db.callable_item_signature(id.into()).instantiate_identity().skip_norm_wip();
1538 let ty = Ty::new_fn_ptr(interner, callable_sig);
1539 Type::new(id.into(), ty)
1540 }
1541 AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } => {
1542 let Some(trait_method) = method.trait_method(db, impl_) else {
1546 return Type::unknown();
1547 };
1548 Function::from(trait_method).fn_ptr_type(db)
1549 }
1550 }
1551 }
1552
1553 fn fn_sig<'db>(self, db: &'db dyn HirDatabase) -> (TypeOwnerId<'db>, PolyFnSig<'db>) {
1554 let fn_ptr = self.fn_ptr_type(db);
1555 let TyKind::FnPtr(sig_tys, hdr) = fn_ptr.ty.skip_binder().kind() else {
1556 unreachable!();
1557 };
1558 (fn_ptr.owner, sig_tys.with(hdr))
1559 }
1560
1561 fn erased_fn_sig<'db>(self, db: &'db dyn HirDatabase) -> (TypeOwnerId<'db>, FnSig<'db>) {
1562 let (owner, sig) = self.fn_sig(db);
1563 let sig = DbInterner::new_no_crate(db).instantiate_bound_regions_with_erased(sig);
1564 (owner, sig)
1565 }
1566
1567 pub fn ret_type(self, db: &dyn HirDatabase) -> Type<'_> {
1569 let (owner, sig) = self.erased_fn_sig(db);
1570 Type { owner, ty: EarlyBinder::bind(sig.output()) }
1571 }
1572
1573 pub fn async_ret_type<'db>(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
1574 let AnyFunctionId::FunctionId(id) = self.id else {
1575 return None;
1576 };
1577 if !self.is_async(db) {
1578 return None;
1579 }
1580 let interner = DbInterner::new_no_crate(db);
1581 let sig = db.callable_item_signature(id.into()).instantiate_identity().skip_norm_wip();
1582 let ret_ty = interner.instantiate_bound_regions_with_erased(sig).output();
1583 for pred in ret_ty.impl_trait_bounds(db).into_iter().flatten() {
1584 let clause = interner.instantiate_bound_regions_with_erased(pred.kind());
1585 if let ClauseKind::Projection(projection) = clause
1586 && let Some(output_ty) = projection.term.as_type()
1587 {
1588 return Some(Type::new(id.into(), output_ty));
1589 }
1590 }
1591 None
1592 }
1593
1594 pub fn has_self_param(self, db: &dyn HirDatabase) -> bool {
1595 match self.id {
1596 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).has_self_param(),
1597 AnyFunctionId::BuiltinDeriveImplMethod { method, .. } => match method {
1598 BuiltinDeriveImplMethod::clone
1599 | BuiltinDeriveImplMethod::fmt
1600 | BuiltinDeriveImplMethod::hash
1601 | BuiltinDeriveImplMethod::cmp
1602 | BuiltinDeriveImplMethod::partial_cmp
1603 | BuiltinDeriveImplMethod::eq => true,
1604 BuiltinDeriveImplMethod::default => false,
1605 },
1606 }
1607 }
1608
1609 pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
1610 self.has_self_param(db).then_some(SelfParam { func: self })
1611 }
1612
1613 pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param<'_>> {
1614 let (owner, sig) = self.erased_fn_sig(db);
1615 let func = match self.id {
1616 AnyFunctionId::FunctionId(id) => Callee::Def(CallableDefId::FunctionId(id)),
1617 AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } => {
1618 Callee::BuiltinDeriveImplMethod { method, impl_ }
1619 }
1620 };
1621 sig.inputs()
1622 .iter()
1623 .enumerate()
1624 .map(|(idx, &ty)| Param {
1625 func: func.clone(),
1626 ty: Type { owner, ty: EarlyBinder::bind(ty) },
1627 idx,
1628 })
1629 .collect()
1630 }
1631
1632 pub fn num_params(self, db: &dyn HirDatabase) -> usize {
1633 match self.id {
1634 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).params.len(),
1635 AnyFunctionId::BuiltinDeriveImplMethod { .. } => {
1636 self.fn_sig(db).1.skip_binder().inputs().len()
1637 }
1638 }
1639 }
1640
1641 pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param<'_>>> {
1642 self.self_param(db)?;
1643 Some(self.params_without_self(db))
1644 }
1645
1646 pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec<Param<'_>> {
1647 let mut params = self.assoc_fn_params(db);
1648 if self.has_self_param(db) {
1649 params.remove(0);
1650 }
1651 params
1652 }
1653
1654 pub fn is_const(self, db: &dyn HirDatabase) -> bool {
1655 match self.id {
1656 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).is_const(),
1657 AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
1658 }
1659 }
1660
1661 pub fn is_async(self, db: &dyn HirDatabase) -> bool {
1662 match self.id {
1663 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).is_async(),
1664 AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
1665 }
1666 }
1667
1668 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
1669 match self.id {
1670 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).is_unsafe(),
1671 AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
1672 }
1673 }
1674
1675 pub fn is_varargs(self, db: &dyn HirDatabase) -> bool {
1676 match self.id {
1677 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).is_varargs(),
1678 AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
1679 }
1680 }
1681
1682 pub fn extern_block(self, db: &dyn HirDatabase) -> Option<ExternBlock> {
1683 match self.id {
1684 AnyFunctionId::FunctionId(id) => match id.lookup(db).container {
1685 ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }),
1686 _ => None,
1687 },
1688 AnyFunctionId::BuiltinDeriveImplMethod { .. } => None,
1689 }
1690 }
1691
1692 pub fn returns_impl_future(self, db: &dyn HirDatabase) -> bool {
1693 if self.is_async(db) {
1694 return true;
1695 }
1696
1697 let ret_type = self.ret_type(db);
1698 let Some(impl_traits) = ret_type.as_impl_traits(db) else { return false };
1699 let lang_items = hir_def::lang_item::lang_items(db, self.krate(db).id);
1700 let Some(future_trait_id) = lang_items.Future else {
1701 return false;
1702 };
1703 let Some(sized_trait_id) = lang_items.Sized else {
1704 return false;
1705 };
1706
1707 let mut has_impl_future = false;
1708 impl_traits
1709 .filter(|t| {
1710 let fut = t.id == future_trait_id;
1711 has_impl_future |= fut;
1712 !fut && t.id != sized_trait_id
1713 })
1714 .all(|t| t.is_auto(db))
1716 && has_impl_future
1717 }
1718
1719 pub fn is_test(self, db: &dyn HirDatabase) -> bool {
1721 self.attrs(db).contains(AttrFlags::IS_TEST)
1722 }
1723
1724 pub fn is_main(self, db: &dyn HirDatabase) -> bool {
1726 match self.id {
1727 AnyFunctionId::FunctionId(id) => {
1728 self.exported_main(db)
1729 || self.module(db).is_crate_root(db)
1730 && FunctionSignature::of(db, id).name == sym::main
1731 }
1732 AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
1733 }
1734 }
1735
1736 fn attrs(self, db: &dyn HirDatabase) -> AttrFlags {
1737 match self.id {
1738 AnyFunctionId::FunctionId(id) => AttrFlags::query(db, id.into()),
1739 AnyFunctionId::BuiltinDeriveImplMethod { .. } => AttrFlags::empty(),
1740 }
1741 }
1742
1743 pub fn exported_main(self, db: &dyn HirDatabase) -> bool {
1745 self.attrs(db).contains(AttrFlags::IS_EXPORT_NAME_MAIN)
1746 }
1747
1748 pub fn is_ignore(self, db: &dyn HirDatabase) -> bool {
1750 self.attrs(db).contains(AttrFlags::IS_IGNORE)
1751 }
1752
1753 pub fn is_bench(self, db: &dyn HirDatabase) -> bool {
1755 self.attrs(db).contains(AttrFlags::IS_BENCH)
1756 }
1757
1758 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1760 self.attrs(db).contains(AttrFlags::IS_UNSTABLE)
1761 }
1762
1763 pub fn is_unsafe_to_call(
1764 self,
1765 db: &dyn HirDatabase,
1766 caller: Option<Function>,
1767 call_edition: Edition,
1768 ) -> bool {
1769 let AnyFunctionId::FunctionId(id) = self.id else {
1770 return false;
1771 };
1772 let (target_features, target_feature_is_safe_in_target) = caller
1773 .map(|caller| {
1774 let target_features = match caller.id {
1775 AnyFunctionId::FunctionId(id) => hir_ty::TargetFeatures::from_fn(db, id),
1776 AnyFunctionId::BuiltinDeriveImplMethod { .. } => {
1777 hir_ty::TargetFeatures::default()
1778 }
1779 };
1780 let target_feature_is_safe_in_target =
1781 match &caller.krate(db).id.workspace_data(db).target {
1782 Ok(target) => hir_ty::target_feature_is_safe_in_target(target),
1783 Err(_) => hir_ty::TargetFeatureIsSafeInTarget::No,
1784 };
1785 (target_features, target_feature_is_safe_in_target)
1786 })
1787 .unwrap_or_else(|| {
1788 (hir_ty::TargetFeatures::default(), hir_ty::TargetFeatureIsSafeInTarget::No)
1789 });
1790 matches!(
1791 hir_ty::is_fn_unsafe_to_call(
1792 db,
1793 id,
1794 &target_features,
1795 call_edition,
1796 target_feature_is_safe_in_target
1797 ),
1798 hir_ty::Unsafety::Unsafe
1799 )
1800 }
1801
1802 pub fn has_body(self, db: &dyn HirDatabase) -> bool {
1806 match self.id {
1807 AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).has_body(),
1808 AnyFunctionId::BuiltinDeriveImplMethod { .. } => true,
1809 }
1810 }
1811
1812 pub fn as_proc_macro(self, db: &dyn HirDatabase) -> Option<Macro> {
1813 let AnyFunctionId::FunctionId(id) = self.id else {
1814 return None;
1815 };
1816 let def_map = crate_def_map(db, HasModule::krate(&id, db));
1817 def_map.fn_as_proc_macro(id).map(|id| Macro { id: id.into() })
1818 }
1819
1820 pub fn eval(
1821 self,
1822 db: &dyn HirDatabase,
1823 span_formatter: impl Fn(FileId, TextRange) -> String,
1824 ) -> Result<String, ConstEvalError<'_>> {
1825 let AnyFunctionId::FunctionId(id) = self.id else {
1826 return Err(ConstEvalError::MirEvalError(MirEvalError::NotSupported(
1827 "evaluation of builtin derive impl methods is not supported".to_owned(),
1828 )));
1829 };
1830 let interner = DbInterner::new_no_crate(db);
1831 let body = db.monomorphized_mir_body(
1832 id.into(),
1833 GenericArgs::empty(interner).store(),
1834 ParamEnvAndCrate {
1835 param_env: db.trait_environment(id.into()),
1836 krate: id.module(db).krate(db),
1837 }
1838 .store(),
1839 )?;
1840 let (result, output) = interpret_mir(db, body, false, None)?;
1841 let mut text = match result {
1842 Ok(_) => "pass".to_owned(),
1843 Err(e) => {
1844 let mut r = String::new();
1845 _ = e.pretty_print(
1846 &mut r,
1847 db,
1848 &span_formatter,
1849 self.krate(db).to_display_target(db),
1850 );
1851 r
1852 }
1853 };
1854 let stdout = output.stdout().into_owned();
1855 if !stdout.is_empty() {
1856 text += "\n--------- stdout ---------\n";
1857 text += &stdout;
1858 }
1859 let stderr = output.stdout().into_owned();
1860 if !stderr.is_empty() {
1861 text += "\n--------- stderr ---------\n";
1862 text += &stderr;
1863 }
1864 Ok(text)
1865 }
1866}
1867
1868#[derive(Clone, Copy, PartialEq, Eq)]
1870pub enum Access {
1871 Shared,
1872 Exclusive,
1873 Owned,
1874}
1875
1876impl From<hir_ty::next_solver::Mutability> for Access {
1877 fn from(mutability: hir_ty::next_solver::Mutability) -> Access {
1878 match mutability {
1879 hir_ty::next_solver::Mutability::Not => Access::Shared,
1880 hir_ty::next_solver::Mutability::Mut => Access::Exclusive,
1881 }
1882 }
1883}
1884
1885#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1886pub struct Param<'db> {
1887 func: Callee<'db>,
1888 idx: usize,
1890 ty: Type<'db>,
1891}
1892
1893impl<'db> Param<'db> {
1894 pub fn parent_fn(&self) -> Option<Function> {
1895 match self.func {
1896 Callee::Def(CallableDefId::FunctionId(f)) => Some(f.into()),
1897 Callee::BuiltinDeriveImplMethod { method, impl_ } => {
1898 Some(Function { id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } })
1899 }
1900 _ => None,
1901 }
1902 }
1903
1904 pub fn index(&self) -> usize {
1909 self.idx
1910 }
1911
1912 pub fn ty(&self) -> &Type<'db> {
1913 &self.ty
1914 }
1915
1916 pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
1917 Some(self.as_local(db)?.name(db))
1918 }
1919
1920 pub fn as_local(&self, db: &'db dyn HirDatabase) -> Option<Local<'db>> {
1921 match self.func {
1922 Callee::Def(CallableDefId::FunctionId(it)) => {
1923 let parent = DefWithBodyId::FunctionId(it);
1924 let body = Body::of(db, parent);
1925 if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
1926 Some(Local {
1927 parent: parent.into(),
1928 parent_infer: parent.into(),
1929 binding_id: self_param.user_written,
1930 })
1931 } else if let Pat::Bind { id, .. } =
1932 &body[body.params[self.idx - body.self_param.is_some() as usize].user_written]
1933 {
1934 Some(Local {
1935 parent: parent.into(),
1936 parent_infer: parent.into(),
1937 binding_id: *id,
1938 })
1939 } else {
1940 None
1941 }
1942 }
1943 Callee::Closure(closure, _) => {
1944 let c = closure.loc(db);
1945 let body_infer_owner = c.owner;
1946 let body_owner = c.owner.expression_store_owner(db);
1947 let store = ExpressionStore::of(db, body_owner);
1948
1949 if let Expr::Closure { args, .. } = &store[c.expr]
1950 && let Pat::Bind { id, .. } = &store[args[self.idx]]
1951 {
1952 return Some(Local {
1953 parent: body_owner,
1954 parent_infer: body_infer_owner,
1955 binding_id: *id,
1956 });
1957 }
1958 None
1959 }
1960 _ => None,
1961 }
1962 }
1963
1964 pub fn pattern_source(self, db: &dyn HirDatabase) -> Option<ast::Pat> {
1965 self.source(db).and_then(|p| p.value.right()?.pat())
1966 }
1967}
1968
1969#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1970pub struct SelfParam {
1971 func: Function,
1972}
1973
1974impl SelfParam {
1975 pub fn access(self, db: &dyn HirDatabase) -> Access {
1976 match self.func.id {
1977 AnyFunctionId::FunctionId(id) => {
1978 let func_data = FunctionSignature::of(db, id);
1979 func_data
1980 .params
1981 .first()
1982 .map(|¶m| match &func_data.store[param] {
1983 TypeRef::Reference(ref_) => match ref_.mutability {
1984 hir_def::type_ref::Mutability::Shared => Access::Shared,
1985 hir_def::type_ref::Mutability::Mut => Access::Exclusive,
1986 },
1987 _ => Access::Owned,
1988 })
1989 .unwrap_or(Access::Owned)
1990 }
1991 AnyFunctionId::BuiltinDeriveImplMethod { method, .. } => match method {
1992 BuiltinDeriveImplMethod::clone
1993 | BuiltinDeriveImplMethod::fmt
1994 | BuiltinDeriveImplMethod::hash
1995 | BuiltinDeriveImplMethod::cmp
1996 | BuiltinDeriveImplMethod::partial_cmp
1997 | BuiltinDeriveImplMethod::eq => Access::Shared,
1998 BuiltinDeriveImplMethod::default => {
1999 unreachable!("this function does not have a self param")
2000 }
2001 },
2002 }
2003 }
2004
2005 pub fn parent_fn(&self) -> Function {
2006 self.func
2007 }
2008
2009 pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> {
2010 let (owner, sig) = self.func.erased_fn_sig(db);
2011 Type { owner, ty: EarlyBinder::bind(sig.inputs()[0]) }
2012 }
2013}
2014
2015impl HasVisibility for Function {
2016 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2017 match self.id {
2018 AnyFunctionId::FunctionId(id) => AssocItemId::from(id).assoc_visibility(db),
2019 AnyFunctionId::BuiltinDeriveImplMethod { .. } => Visibility::Public,
2020 }
2021 }
2022}
2023
2024#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2025pub struct ExternCrateDecl {
2026 pub(crate) id: ExternCrateId,
2027}
2028
2029impl ExternCrateDecl {
2030 pub fn module(self, db: &dyn HirDatabase) -> Module {
2031 self.id.module(db).into()
2032 }
2033
2034 pub fn resolved_crate(self, db: &dyn HirDatabase) -> Option<Crate> {
2035 let loc = self.id.lookup(db);
2036 let krate = loc.container.krate(db);
2037 let name = self.name(db);
2038 if name == sym::self_ {
2039 Some(krate.into())
2040 } else {
2041 krate.data(db).dependencies.iter().find_map(|dep| {
2042 if dep.name.symbol() == name.symbol() { Some(dep.crate_id.into()) } else { None }
2043 })
2044 }
2045 }
2046
2047 pub fn name(self, db: &dyn HirDatabase) -> Name {
2048 let loc = self.id.lookup(db);
2049 let source = loc.source(db);
2050 as_name_opt(source.value.name_ref())
2051 }
2052
2053 pub fn alias(self, db: &dyn HirDatabase) -> Option<ImportAlias> {
2054 let loc = self.id.lookup(db);
2055 let source = loc.source(db);
2056 let rename = source.value.rename()?;
2057 if let Some(name) = rename.name() {
2058 Some(ImportAlias::Alias(name.as_name()))
2059 } else if rename.underscore_token().is_some() {
2060 Some(ImportAlias::Underscore)
2061 } else {
2062 None
2063 }
2064 }
2065
2066 pub fn alias_or_name(self, db: &dyn HirDatabase) -> Option<Name> {
2068 match self.alias(db) {
2069 Some(ImportAlias::Underscore) => None,
2070 Some(ImportAlias::Alias(alias)) => Some(alias),
2071 None => Some(self.name(db)),
2072 }
2073 }
2074}
2075
2076impl HasVisibility for ExternCrateDecl {
2077 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2078 let loc = self.id.lookup(db);
2079 let source = loc.source(db);
2080 visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
2081 }
2082}
2083
2084#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2085pub struct Const {
2086 pub(crate) id: ConstId,
2087}
2088
2089impl Const {
2090 pub fn module(self, db: &dyn HirDatabase) -> Module {
2091 Module { id: self.id.module(db) }
2092 }
2093
2094 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
2095 ConstSignature::of(db, self.id).name.clone()
2096 }
2097
2098 pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
2099 self.source(db)?.value.body()
2100 }
2101
2102 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
2103 Type::from_value_def(db, self.id)
2104 }
2105
2106 pub fn has_body(self, db: &dyn HirDatabase) -> bool {
2107 ConstSignature::of(db, self.id).has_body()
2108 }
2109
2110 pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError<'_>> {
2112 let interner = DbInterner::new_no_crate(db);
2113 let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity().skip_norm_wip();
2114 db.const_eval(self.id, GenericArgs::empty(interner), None).map(|it| EvaluatedConst {
2115 allocation: it,
2116 def: self.id.into(),
2117 ty,
2118 })
2119 }
2120}
2121
2122impl HasVisibility for Const {
2123 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2124 AssocItemId::from(self.id).assoc_visibility(db)
2125 }
2126}
2127
2128pub struct EvaluatedConst<'db> {
2129 def: InferBodyId<'db>,
2130 allocation: hir_ty::next_solver::Allocation<'db>,
2131 ty: Ty<'db>,
2132}
2133
2134impl<'db> EvaluatedConst<'db> {
2135 pub fn render(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
2136 format!("{}", self.allocation.display(db, display_target))
2137 }
2138
2139 pub fn render_debug(&self, db: &'db dyn HirDatabase) -> Result<String, MirEvalError<'db>> {
2140 let ty = self.allocation.ty.kind();
2141 if let TyKind::Int(_) | TyKind::Uint(_) = ty {
2142 let b = &self.allocation.memory;
2143 let value = u128::from_le_bytes(mir::pad16(b, mir::IsSigned::No));
2144 let is_signed = matches!(ty, TyKind::Int(_)).into();
2145 let value_signed = i128::from_le_bytes(mir::pad16(b, is_signed));
2146 let mut result =
2147 if let TyKind::Int(_) = ty { value_signed.to_string() } else { value.to_string() };
2148 if value >= 10 {
2149 format_to!(result, " ({value:#X})");
2150 return Ok(result);
2151 } else {
2152 return Ok(result);
2153 }
2154 }
2155 mir::render_const_using_debug_impl(db, self.def, self.allocation, self.ty)
2156 }
2157}
2158
2159#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2160pub struct Static {
2161 pub(crate) id: StaticId,
2162}
2163
2164impl Static {
2165 pub fn module(self, db: &dyn HirDatabase) -> Module {
2166 Module { id: self.id.module(db) }
2167 }
2168
2169 pub fn name(self, db: &dyn HirDatabase) -> Name {
2170 StaticSignature::of(db, self.id).name.clone()
2171 }
2172
2173 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
2174 StaticSignature::of(db, self.id).flags.contains(StaticFlags::MUTABLE)
2175 }
2176
2177 pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
2178 self.source(db)?.value.body()
2179 }
2180
2181 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
2182 Type::from_value_def(db, self.id)
2183 }
2184
2185 pub fn extern_block(self, db: &dyn HirDatabase) -> Option<ExternBlock> {
2186 match self.id.lookup(db).container {
2187 ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }),
2188 _ => None,
2189 }
2190 }
2191
2192 pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError<'_>> {
2194 let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity().skip_norm_wip();
2195 db.const_eval_static(self.id).map(|it| EvaluatedConst {
2196 allocation: it,
2197 def: self.id.into(),
2198 ty,
2199 })
2200 }
2201}
2202
2203impl HasVisibility for Static {
2204 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2205 let loc = self.id.lookup(db);
2206 let source = loc.source(db);
2207 visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
2208 }
2209}
2210
2211#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2212pub struct Trait {
2213 pub(crate) id: TraitId,
2214}
2215
2216impl Trait {
2217 pub fn lang(db: &dyn HirDatabase, krate: Crate, lang_item: LangItem) -> Option<Trait> {
2218 let lang_items = hir_def::lang_item::lang_items(db, krate.id);
2219 match lang_item.from_lang_items(lang_items)? {
2220 LangItemTarget::TraitId(it) => Some(it.into()),
2221 _ => None,
2222 }
2223 }
2224
2225 pub fn module(self, db: &dyn HirDatabase) -> Module {
2226 Module { id: self.id.lookup(db).container }
2227 }
2228
2229 pub fn name(self, db: &dyn HirDatabase) -> Name {
2230 TraitSignature::of(db, self.id).name.clone()
2231 }
2232
2233 pub fn direct_supertraits(self, db: &dyn HirDatabase) -> Vec<Trait> {
2234 let traits = direct_super_traits(db, self.into());
2235 traits.iter().map(|tr| Trait::from(*tr)).collect()
2236 }
2237
2238 pub fn all_supertraits(self, db: &dyn HirDatabase) -> Vec<Trait> {
2239 let traits = all_super_traits(db, self.into());
2240 traits.iter().map(|tr| Trait::from(*tr)).collect()
2241 }
2242
2243 pub fn function(self, db: &dyn HirDatabase, name: impl PartialEq<Name>) -> Option<Function> {
2244 self.id.trait_items(db).items.iter().find(|(n, _)| name == *n).and_then(|&(_, it)| match it
2245 {
2246 AssocItemId::FunctionId(id) => Some(id.into()),
2247 _ => None,
2248 })
2249 }
2250
2251 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
2252 self.id.trait_items(db).items.iter().map(|(_name, it)| (*it).into()).collect()
2253 }
2254
2255 pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
2256 self.all_supertraits(db).into_iter().flat_map(|tr| tr.items(db)).collect()
2257 }
2258
2259 pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
2260 TraitSignature::of(db, self.id).flags.contains(TraitFlags::AUTO)
2261 }
2262
2263 pub fn is_unsafe(&self, db: &dyn HirDatabase) -> bool {
2264 TraitSignature::of(db, self.id).flags.contains(TraitFlags::UNSAFE)
2265 }
2266
2267 pub fn type_or_const_param_count(
2268 &self,
2269 db: &dyn HirDatabase,
2270 count_required_only: bool,
2271 ) -> usize {
2272 GenericParams::of(db,self.id.into())
2273 .iter_type_or_consts()
2274 .filter(|(_, ty)| !matches!(ty, TypeOrConstParamData::TypeParamData(ty) if ty.provenance != TypeParamProvenance::TypeParamList))
2275 .filter(|(_, ty)| !count_required_only || !ty.has_default())
2276 .count()
2277 }
2278
2279 pub fn dyn_compatibility(&self, db: &dyn HirDatabase) -> Option<DynCompatibilityViolation> {
2280 hir_ty::dyn_compatibility::dyn_compatibility(db, self.id)
2281 }
2282
2283 pub fn dyn_compatibility_all_violations(
2284 &self,
2285 db: &dyn HirDatabase,
2286 ) -> Option<Vec<DynCompatibilityViolation>> {
2287 let mut violations = vec![];
2288 _ = hir_ty::dyn_compatibility::dyn_compatibility_with_callback(
2289 db,
2290 self.id,
2291 &mut |violation| {
2292 violations.push(violation);
2293 ControlFlow::Continue(())
2294 },
2295 );
2296 violations.is_empty().not().then_some(violations)
2297 }
2298
2299 pub fn complete(self, db: &dyn HirDatabase) -> Complete {
2301 Complete::extract(true, self.attrs(db).attrs)
2302 }
2303
2304 pub fn prefer_underscore_import(self, db: &dyn HirDatabase) -> bool {
2314 AttrFlags::query(db, self.id.into()).contains(AttrFlags::PREFER_UNDERSCORE_IMPORT)
2315 }
2316
2317 pub fn must_implement_one_of(self, db: &dyn HirDatabase) -> Option<&[Name]> {
2318 AttrFlags::must_implement_one_of(db, self.id)
2319 }
2320}
2321
2322impl HasVisibility for Trait {
2323 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2324 let loc = self.id.lookup(db);
2325 let source = loc.source(db);
2326 visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
2327 }
2328}
2329
2330#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2331pub struct TypeAlias {
2332 pub(crate) id: TypeAliasId,
2333}
2334
2335impl TypeAlias {
2336 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
2337 has_non_default_type_params(db, self.id.into())
2338 }
2339
2340 pub fn module(self, db: &dyn HirDatabase) -> Module {
2341 Module { id: self.id.module(db) }
2342 }
2343
2344 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
2345 Type::from_def(db, self.id)
2346 }
2347
2348 pub fn name(self, db: &dyn HirDatabase) -> Name {
2349 TypeAliasSignature::of(db, self.id).name.clone()
2350 }
2351
2352 pub fn has_type(self, db: &dyn HirDatabase) -> bool {
2353 TypeAliasSignature::of(db, self.id).ty.is_some()
2354 }
2355}
2356
2357impl HasVisibility for TypeAlias {
2358 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2359 AssocItemId::from(self.id).assoc_visibility(db)
2360 }
2361}
2362
2363#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2364pub struct ExternBlock {
2365 pub(crate) id: ExternBlockId,
2366}
2367
2368impl ExternBlock {
2369 pub fn module(self, db: &dyn HirDatabase) -> Module {
2370 Module { id: self.id.module(db) }
2371 }
2372}
2373
2374#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2375pub struct StaticLifetime;
2376
2377impl StaticLifetime {
2378 pub fn name(self) -> Name {
2379 Name::new_symbol_root(sym::tick_static)
2380 }
2381}
2382
2383#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2384pub struct BuiltinType {
2385 pub(crate) inner: hir_def::builtin_type::BuiltinType,
2386}
2387
2388impl BuiltinType {
2389 pub fn str() -> BuiltinType {
2391 BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
2392 }
2393
2394 pub fn i32() -> BuiltinType {
2395 BuiltinType {
2396 inner: hir_def::builtin_type::BuiltinType::Int(hir_ty::primitive::BuiltinInt::I32),
2397 }
2398 }
2399
2400 pub fn bool() -> BuiltinType {
2401 BuiltinType { inner: hir_def::builtin_type::BuiltinType::Bool }
2402 }
2403
2404 pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
2405 let interner = DbInterner::new_no_crate(db);
2406 Type::no_params(Type::builtin_type_crate(db), Ty::from_builtin_type(interner, self.inner))
2407 }
2408
2409 pub fn name(self) -> Name {
2410 self.inner.as_name()
2411 }
2412
2413 pub fn is_int(&self) -> bool {
2414 matches!(self.inner, hir_def::builtin_type::BuiltinType::Int(_))
2415 }
2416
2417 pub fn is_uint(&self) -> bool {
2418 matches!(self.inner, hir_def::builtin_type::BuiltinType::Uint(_))
2419 }
2420
2421 pub fn is_float(&self) -> bool {
2422 matches!(self.inner, hir_def::builtin_type::BuiltinType::Float(_))
2423 }
2424
2425 pub fn is_f16(&self) -> bool {
2426 matches!(
2427 self.inner,
2428 hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F16)
2429 )
2430 }
2431
2432 pub fn is_f32(&self) -> bool {
2433 matches!(
2434 self.inner,
2435 hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F32)
2436 )
2437 }
2438
2439 pub fn is_f64(&self) -> bool {
2440 matches!(
2441 self.inner,
2442 hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F64)
2443 )
2444 }
2445
2446 pub fn is_f128(&self) -> bool {
2447 matches!(
2448 self.inner,
2449 hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F128)
2450 )
2451 }
2452
2453 pub fn is_char(&self) -> bool {
2454 matches!(self.inner, hir_def::builtin_type::BuiltinType::Char)
2455 }
2456
2457 pub fn is_bool(&self) -> bool {
2458 matches!(self.inner, hir_def::builtin_type::BuiltinType::Bool)
2459 }
2460
2461 pub fn is_str(&self) -> bool {
2462 matches!(self.inner, hir_def::builtin_type::BuiltinType::Str)
2463 }
2464}
2465
2466#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2467pub struct Macro {
2468 pub(crate) id: MacroId,
2469}
2470
2471impl Macro {
2472 pub fn module(self, db: &dyn HirDatabase) -> Module {
2473 Module { id: self.id.module(db) }
2474 }
2475
2476 pub fn name(self, db: &dyn HirDatabase) -> Name {
2477 match self.id {
2478 MacroId::Macro2Id(id) => {
2479 let loc = id.lookup(db);
2480 let source = loc.source(db);
2481 as_name_opt(source.value.name())
2482 }
2483 MacroId::MacroRulesId(id) => {
2484 let loc = id.lookup(db);
2485 let source = loc.source(db);
2486 as_name_opt(source.value.name())
2487 }
2488 MacroId::ProcMacroId(id) => {
2489 let loc = id.lookup(db);
2490 let source = loc.source(db);
2491 match loc.kind {
2492 ProcMacroKind::CustomDerive => AttrFlags::derive_info(db, self.id).map_or_else(
2493 || as_name_opt(source.value.name()),
2494 |info| Name::new_symbol_root(info.trait_name.clone()),
2495 ),
2496 ProcMacroKind::Bang | ProcMacroKind::Attr => as_name_opt(source.value.name()),
2497 }
2498 }
2499 }
2500 }
2501
2502 pub fn is_proc_macro(self) -> bool {
2503 matches!(self.id, MacroId::ProcMacroId(_))
2504 }
2505
2506 pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind {
2507 match self.id {
2508 MacroId::Macro2Id(it) => match it.lookup(db).expander {
2509 MacroExpander::Declarative { .. } => MacroKind::Declarative,
2510 MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => {
2511 MacroKind::DeclarativeBuiltIn
2512 }
2513 MacroExpander::BuiltInAttr(_) => MacroKind::AttrBuiltIn,
2514 MacroExpander::BuiltInDerive(_) => MacroKind::DeriveBuiltIn,
2515 MacroExpander::UnimplementedBuiltIn => MacroKind::Declarative,
2516 },
2517 MacroId::MacroRulesId(it) => match it.lookup(db).expander {
2518 MacroExpander::Declarative { .. } => MacroKind::Declarative,
2519 MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => {
2520 MacroKind::DeclarativeBuiltIn
2521 }
2522 MacroExpander::BuiltInAttr(_) => MacroKind::AttrBuiltIn,
2523 MacroExpander::BuiltInDerive(_) => MacroKind::DeriveBuiltIn,
2524 MacroExpander::UnimplementedBuiltIn => MacroKind::Declarative,
2525 },
2526 MacroId::ProcMacroId(it) => match it.lookup(db).kind {
2527 ProcMacroKind::CustomDerive => MacroKind::Derive,
2528 ProcMacroKind::Bang => MacroKind::ProcMacro,
2529 ProcMacroKind::Attr => MacroKind::Attr,
2530 },
2531 }
2532 }
2533
2534 pub fn is_fn_like(&self, db: &dyn HirDatabase) -> bool {
2535 matches!(
2536 self.kind(db),
2537 MacroKind::Declarative | MacroKind::DeclarativeBuiltIn | MacroKind::ProcMacro
2538 )
2539 }
2540
2541 pub fn builtin_derive_kind(&self, db: &dyn HirDatabase) -> Option<BuiltinDeriveMacroKind> {
2542 let expander = match self.id {
2543 MacroId::Macro2Id(it) => it.lookup(db).expander,
2544 MacroId::MacroRulesId(it) => it.lookup(db).expander,
2545 MacroId::ProcMacroId(_) => return None,
2546 };
2547 match expander {
2548 MacroExpander::BuiltInDerive(kind) => Some(BuiltinDeriveMacroKind(kind)),
2549 _ => None,
2550 }
2551 }
2552
2553 pub fn is_env_or_option_env(&self, db: &dyn HirDatabase) -> bool {
2554 match self.id {
2555 MacroId::Macro2Id(it) => {
2556 matches!(it.lookup(db).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
2557 }
2558 MacroId::MacroRulesId(it) => {
2559 matches!(it.lookup(db).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
2560 }
2561 MacroId::ProcMacroId(_) => false,
2562 }
2563 }
2564
2565 pub fn is_asm_like(&self, db: &dyn HirDatabase) -> bool {
2567 match self.id {
2568 MacroId::Macro2Id(it) => {
2569 matches!(it.lookup(db).expander, MacroExpander::BuiltIn(m) if m.is_asm())
2570 }
2571 MacroId::MacroRulesId(it) => {
2572 matches!(it.lookup(db).expander, MacroExpander::BuiltIn(m) if m.is_asm())
2573 }
2574 MacroId::ProcMacroId(_) => false,
2575 }
2576 }
2577
2578 pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
2579 matches!(self.kind(db), MacroKind::Attr | MacroKind::AttrBuiltIn)
2580 }
2581
2582 pub fn is_derive(&self, db: &dyn HirDatabase) -> bool {
2583 matches!(self.kind(db), MacroKind::Derive | MacroKind::DeriveBuiltIn)
2584 }
2585
2586 pub fn preferred_brace_style(&self, db: &dyn HirDatabase) -> Option<MacroBraces> {
2587 let attrs = self.attrs(db);
2588 MacroBraces::extract(attrs.attrs)
2589 }
2590}
2591
2592#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2611pub enum MacroBraces {
2612 Braces,
2613 Brackets,
2614 Parentheses,
2615}
2616
2617impl MacroBraces {
2618 fn extract(attrs: AttrFlags) -> Option<Self> {
2619 if attrs.contains(AttrFlags::MACRO_STYLE_BRACES) {
2620 Some(Self::Braces)
2621 } else if attrs.contains(AttrFlags::MACRO_STYLE_BRACKETS) {
2622 Some(Self::Brackets)
2623 } else if attrs.contains(AttrFlags::MACRO_STYLE_PARENTHESES) {
2624 Some(Self::Parentheses)
2625 } else {
2626 None
2627 }
2628 }
2629}
2630
2631#[derive(Clone, Copy, PartialEq, Eq, Hash)]
2632pub struct BuiltinDeriveMacroKind(BuiltinDeriveExpander);
2633
2634impl HasVisibility for Macro {
2635 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2636 match self.id {
2637 MacroId::Macro2Id(id) => {
2638 let loc = id.lookup(db);
2639 let source = loc.source(db);
2640 visibility_from_ast(db, id, source.map(|src| src.visibility()))
2641 }
2642 MacroId::MacroRulesId(id) => {
2643 if AttrFlags::query(db, id.into()).contains(AttrFlags::IS_MACRO_EXPORT) {
2644 Visibility::Public
2645 } else {
2646 Visibility::PubCrate(self.krate(db).id)
2647 }
2648 }
2649 MacroId::ProcMacroId(_) => Visibility::Public,
2650 }
2651 }
2652}
2653
2654#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
2655pub enum ItemInNs {
2656 Types(ModuleDef),
2657 Values(ModuleDef),
2658 Macros(Macro),
2659}
2660
2661impl From<Macro> for ItemInNs {
2662 fn from(it: Macro) -> Self {
2663 Self::Macros(it)
2664 }
2665}
2666
2667impl_from!(
2668 ModuleDef {
2669 Module => Types,
2670 Function => Values,
2671 Adt => Types,
2672 EnumVariant => Types,
2673 Const => Values,
2674 Static => Values,
2675 Trait => Types,
2676 TypeAlias => Types,
2677 BuiltinType => Types,
2678 Macro => Macros,
2679 }
2680 for ItemInNs
2681);
2682
2683impl ItemInNs {
2684 pub fn into_module_def(self) -> ModuleDef {
2685 match self {
2686 ItemInNs::Types(id) | ItemInNs::Values(id) => id,
2687 ItemInNs::Macros(id) => ModuleDef::Macro(id),
2688 }
2689 }
2690
2691 pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
2693 match self {
2694 ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate(db)),
2695 ItemInNs::Macros(id) => Some(id.module(db).krate(db)),
2696 }
2697 }
2698
2699 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
2700 match self {
2701 ItemInNs::Types(it) | ItemInNs::Values(it) => it.attrs(db),
2702 ItemInNs::Macros(it) => Some(it.attrs(db)),
2703 }
2704 }
2705}
2706
2707#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2710pub enum ExternAssocItem {
2711 Function(Function),
2712 Static(Static),
2713 TypeAlias(TypeAlias),
2714}
2715
2716pub trait AsExternAssocItem {
2717 fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem>;
2718}
2719
2720impl AsExternAssocItem for Function {
2721 fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
2722 let AnyFunctionId::FunctionId(id) = self.id else {
2723 return None;
2724 };
2725 as_extern_assoc_item(db, ExternAssocItem::Function, id)
2726 }
2727}
2728
2729impl AsExternAssocItem for Static {
2730 fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
2731 as_extern_assoc_item(db, ExternAssocItem::Static, self.id)
2732 }
2733}
2734
2735impl AsExternAssocItem for TypeAlias {
2736 fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
2737 as_extern_assoc_item(db, ExternAssocItem::TypeAlias, self.id)
2738 }
2739}
2740
2741#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2744pub enum AssocItem {
2745 Function(Function),
2746 Const(Const),
2747 TypeAlias(TypeAlias),
2748}
2749
2750impl From<method_resolution::CandidateId> for AssocItem {
2751 fn from(value: method_resolution::CandidateId) -> Self {
2752 match value {
2753 method_resolution::CandidateId::FunctionId(id) => AssocItem::Function(id.into()),
2754 method_resolution::CandidateId::ConstId(id) => AssocItem::Const(Const { id }),
2755 }
2756 }
2757}
2758
2759#[derive(Debug, Clone)]
2760pub enum AssocItemContainer {
2761 Trait(Trait),
2762 Impl(Impl),
2763}
2764
2765pub trait AsAssocItem {
2766 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>;
2767}
2768
2769impl AsAssocItem for Function {
2770 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2771 match self.id {
2772 AnyFunctionId::FunctionId(id) => as_assoc_item(db, AssocItem::Function, id),
2773 AnyFunctionId::BuiltinDeriveImplMethod { .. } => Some(AssocItem::Function(self)),
2774 }
2775 }
2776}
2777
2778impl AsAssocItem for Const {
2779 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2780 as_assoc_item(db, AssocItem::Const, self.id)
2781 }
2782}
2783
2784impl AsAssocItem for TypeAlias {
2785 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2786 as_assoc_item(db, AssocItem::TypeAlias, self.id)
2787 }
2788}
2789
2790impl AsAssocItem for ModuleDef {
2791 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2792 match self {
2793 ModuleDef::Function(it) => it.as_assoc_item(db),
2794 ModuleDef::Const(it) => it.as_assoc_item(db),
2795 ModuleDef::TypeAlias(it) => it.as_assoc_item(db),
2796 _ => None,
2797 }
2798 }
2799}
2800
2801impl AsAssocItem for DefWithBody {
2802 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2803 match self {
2804 DefWithBody::Function(it) => it.as_assoc_item(db),
2805 DefWithBody::Const(it) => it.as_assoc_item(db),
2806 DefWithBody::Static(_) | DefWithBody::EnumVariant(_) => None,
2807 }
2808 }
2809}
2810
2811impl AsAssocItem for GenericDef {
2812 fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
2813 match self {
2814 GenericDef::Function(it) => it.as_assoc_item(db),
2815 GenericDef::Const(it) => it.as_assoc_item(db),
2816 GenericDef::TypeAlias(it) => it.as_assoc_item(db),
2817 _ => None,
2818 }
2819 }
2820}
2821
2822fn as_assoc_item<'db, ID, DEF, LOC>(
2823 db: &(dyn HirDatabase + 'db),
2824 ctor: impl FnOnce(DEF) -> AssocItem,
2825 id: ID,
2826) -> Option<AssocItem>
2827where
2828 ID: Lookup<Data = AssocItemLoc<LOC>>,
2829 DEF: From<ID>,
2830 LOC: AstIdNode,
2831{
2832 match id.lookup(db).container {
2833 ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
2834 ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
2835 }
2836}
2837
2838fn as_extern_assoc_item<'db, ID, DEF, LOC>(
2839 db: &(dyn HirDatabase + 'db),
2840 ctor: impl FnOnce(DEF) -> ExternAssocItem,
2841 id: ID,
2842) -> Option<ExternAssocItem>
2843where
2844 ID: Lookup<Data = AssocItemLoc<LOC>>,
2845 DEF: From<ID>,
2846 LOC: AstIdNode,
2847{
2848 match id.lookup(db).container {
2849 ItemContainerId::ExternBlockId(_) => Some(ctor(DEF::from(id))),
2850 ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) | ItemContainerId::ModuleId(_) => {
2851 None
2852 }
2853 }
2854}
2855
2856impl ExternAssocItem {
2857 pub fn name(self, db: &dyn HirDatabase) -> Name {
2858 match self {
2859 Self::Function(it) => it.name(db),
2860 Self::Static(it) => it.name(db),
2861 Self::TypeAlias(it) => it.name(db),
2862 }
2863 }
2864
2865 pub fn module(self, db: &dyn HirDatabase) -> Module {
2866 match self {
2867 Self::Function(f) => f.module(db),
2868 Self::Static(c) => c.module(db),
2869 Self::TypeAlias(t) => t.module(db),
2870 }
2871 }
2872
2873 pub fn as_function(self) -> Option<Function> {
2874 match self {
2875 Self::Function(v) => Some(v),
2876 _ => None,
2877 }
2878 }
2879
2880 pub fn as_static(self) -> Option<Static> {
2881 match self {
2882 Self::Static(v) => Some(v),
2883 _ => None,
2884 }
2885 }
2886
2887 pub fn as_type_alias(self) -> Option<TypeAlias> {
2888 match self {
2889 Self::TypeAlias(v) => Some(v),
2890 _ => None,
2891 }
2892 }
2893}
2894
2895impl AssocItem {
2896 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
2897 match self {
2898 AssocItem::Function(it) => Some(it.name(db)),
2899 AssocItem::Const(it) => it.name(db),
2900 AssocItem::TypeAlias(it) => Some(it.name(db)),
2901 }
2902 }
2903
2904 pub fn module(self, db: &dyn HirDatabase) -> Module {
2905 match self {
2906 AssocItem::Function(f) => f.module(db),
2907 AssocItem::Const(c) => c.module(db),
2908 AssocItem::TypeAlias(t) => t.module(db),
2909 }
2910 }
2911
2912 pub fn container(self, db: &dyn HirDatabase) -> AssocItemContainer {
2913 let container = match self {
2914 AssocItem::Function(it) => match it.id {
2915 AnyFunctionId::FunctionId(id) => id.lookup(db).container,
2916 AnyFunctionId::BuiltinDeriveImplMethod { impl_, .. } => {
2917 return AssocItemContainer::Impl(Impl {
2918 id: AnyImplId::BuiltinDeriveImplId(impl_),
2919 });
2920 }
2921 },
2922 AssocItem::Const(it) => it.id.lookup(db).container,
2923 AssocItem::TypeAlias(it) => it.id.lookup(db).container,
2924 };
2925 match container {
2926 ItemContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()),
2927 ItemContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()),
2928 ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
2929 panic!("invalid AssocItem")
2930 }
2931 }
2932 }
2933
2934 pub fn container_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
2935 match self.container(db) {
2936 AssocItemContainer::Trait(t) => Some(t),
2937 _ => None,
2938 }
2939 }
2940
2941 pub fn implemented_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
2942 match self.container(db) {
2943 AssocItemContainer::Impl(i) => i.trait_(db),
2944 _ => None,
2945 }
2946 }
2947
2948 pub fn container_or_implemented_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
2949 match self.container(db) {
2950 AssocItemContainer::Trait(t) => Some(t),
2951 AssocItemContainer::Impl(i) => i.trait_(db),
2952 }
2953 }
2954
2955 pub fn implementing_ty(self, db: &dyn HirDatabase) -> Option<Type<'_>> {
2956 match self.container(db) {
2957 AssocItemContainer::Impl(i) => Some(i.self_ty(db)),
2958 _ => None,
2959 }
2960 }
2961
2962 pub fn as_function(self) -> Option<Function> {
2963 match self {
2964 Self::Function(v) => Some(v),
2965 _ => None,
2966 }
2967 }
2968
2969 pub fn as_const(self) -> Option<Const> {
2970 match self {
2971 Self::Const(v) => Some(v),
2972 _ => None,
2973 }
2974 }
2975
2976 pub fn as_type_alias(self) -> Option<TypeAlias> {
2977 match self {
2978 Self::TypeAlias(v) => Some(v),
2979 _ => None,
2980 }
2981 }
2982}
2983
2984impl HasVisibility for AssocItem {
2985 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
2986 match self {
2987 AssocItem::Function(f) => f.visibility(db),
2988 AssocItem::Const(c) => c.visibility(db),
2989 AssocItem::TypeAlias(t) => t.visibility(db),
2990 }
2991 }
2992}
2993
2994impl_from!(AssocItem { Function, Const, TypeAlias } for ModuleDef);
2995
2996#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
2997pub enum GenericDef {
2998 Function(Function),
2999 Adt(Adt),
3000 Trait(Trait),
3001 TypeAlias(TypeAlias),
3002 Impl(Impl),
3003 Const(Const),
3005 Static(Static),
3006}
3007impl_from!(
3008 Function,
3009 Adt(Struct, Enum, Union),
3010 Trait,
3011 TypeAlias,
3012 Impl,
3013 Const,
3014 Static
3015 for GenericDef
3016);
3017
3018impl GenericDef {
3019 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
3020 match self {
3021 GenericDef::Function(it) => Some(it.name(db)),
3022 GenericDef::Adt(it) => Some(it.name(db)),
3023 GenericDef::Trait(it) => Some(it.name(db)),
3024 GenericDef::TypeAlias(it) => Some(it.name(db)),
3025 GenericDef::Impl(_) => None,
3026 GenericDef::Const(it) => it.name(db),
3027 GenericDef::Static(it) => Some(it.name(db)),
3028 }
3029 }
3030
3031 pub fn module(self, db: &dyn HirDatabase) -> Module {
3032 match self {
3033 GenericDef::Function(it) => it.module(db),
3034 GenericDef::Adt(it) => it.module(db),
3035 GenericDef::Trait(it) => it.module(db),
3036 GenericDef::TypeAlias(it) => it.module(db),
3037 GenericDef::Impl(it) => it.module(db),
3038 GenericDef::Const(it) => it.module(db),
3039 GenericDef::Static(it) => it.module(db),
3040 }
3041 }
3042
3043 pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
3044 let Ok(id) = self.try_into() else {
3045 return Vec::new();
3047 };
3048 let generics = GenericParams::of(db, id);
3049 let ty_params = generics.iter_type_or_consts().map(|(local_id, _)| {
3050 let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: id, local_id } };
3051 match toc.split(db) {
3052 Either::Left(it) => GenericParam::ConstParam(it),
3053 Either::Right(it) => GenericParam::TypeParam(it),
3054 }
3055 });
3056 self.lifetime_params(db)
3057 .into_iter()
3058 .map(GenericParam::LifetimeParam)
3059 .chain(ty_params)
3060 .collect()
3061 }
3062
3063 pub fn lifetime_params(self, db: &dyn HirDatabase) -> Vec<LifetimeParam> {
3064 let Ok(id) = self.try_into() else {
3065 return Vec::new();
3067 };
3068 let generics = GenericParams::of(db, id);
3069 generics
3070 .iter_lt()
3071 .map(|(local_id, _)| LifetimeParam { id: LifetimeParamId { parent: id, local_id } })
3072 .collect()
3073 }
3074
3075 pub fn type_or_const_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
3076 let Ok(id) = self.try_into() else {
3077 return Vec::new();
3079 };
3080 let generics = GenericParams::of(db, id);
3081 generics
3082 .iter_type_or_consts()
3083 .map(|(local_id, _)| TypeOrConstParam {
3084 id: TypeOrConstParamId { parent: id, local_id },
3085 })
3086 .collect()
3087 }
3088
3089 fn id(self) -> Option<GenericDefId> {
3090 Some(match self {
3091 GenericDef::Function(it) => match it.id {
3092 AnyFunctionId::FunctionId(it) => it.into(),
3093 AnyFunctionId::BuiltinDeriveImplMethod { .. } => return None,
3094 },
3095 GenericDef::Adt(it) => it.into(),
3096 GenericDef::Trait(it) => it.id.into(),
3097 GenericDef::TypeAlias(it) => it.id.into(),
3098 GenericDef::Impl(it) => match it.id {
3099 AnyImplId::ImplId(it) => it.into(),
3100 AnyImplId::BuiltinDeriveImplId(_) => return None,
3101 },
3102 GenericDef::Const(it) => it.id.into(),
3103 GenericDef::Static(it) => it.id.into(),
3104 })
3105 }
3106
3107 #[inline]
3109 pub fn description(self) -> &'static str {
3110 match self {
3111 GenericDef::Function(_) => "function",
3112 GenericDef::Adt(Adt::Struct(_)) => "struct",
3113 GenericDef::Adt(Adt::Enum(_)) => "enum",
3114 GenericDef::Adt(Adt::Union(_)) => "union",
3115 GenericDef::Trait(_) => "trait",
3116 GenericDef::TypeAlias(_) => "type alias",
3117 GenericDef::Impl(_) => "impl",
3118 GenericDef::Const(_) => "constant",
3119 GenericDef::Static(_) => "static",
3120 }
3121 }
3122}
3123
3124#[derive(Debug)]
3126pub struct GenericSubstitution<'db> {
3127 owner: TypeOwnerId<'db>,
3128 def: GenericDefId,
3129 subst: GenericArgs<'db>,
3130}
3131
3132impl<'db> GenericSubstitution<'db> {
3133 fn new(def: GenericDefId, subst: GenericArgs<'db>, owner: TypeOwnerId<'db>) -> Self {
3134 Self { owner, def, subst }
3135 }
3136
3137 fn new_from_fn(
3138 def: Function,
3139 subst: GenericArgs<'db>,
3140 owner: TypeOwnerId<'db>,
3141 ) -> Option<Self> {
3142 match def.id {
3143 AnyFunctionId::FunctionId(def) => Some(Self::new(def.into(), subst, owner)),
3144 AnyFunctionId::BuiltinDeriveImplMethod { .. } => None,
3145 }
3146 }
3147
3148 pub fn types(&self, db: &'db dyn HirDatabase) -> Vec<(Symbol, Type<'db>)> {
3149 let container = match self.def {
3150 GenericDefId::ConstId(id) => Some(id.lookup(db).container),
3151 GenericDefId::FunctionId(id) => Some(id.lookup(db).container),
3152 GenericDefId::TypeAliasId(id) => Some(id.lookup(db).container),
3153 _ => None,
3154 };
3155 let container_type_params = container
3156 .and_then(|container| match container {
3157 ItemContainerId::ImplId(container) => Some(container.into()),
3158 ItemContainerId::TraitId(container) => Some(container.into()),
3159 _ => None,
3160 })
3161 .map(|container| {
3162 GenericParams::of(db, container)
3163 .iter_type_or_consts()
3164 .filter_map(|param| match param.1 {
3165 TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
3166 TypeOrConstParamData::ConstParamData(_) => None,
3167 })
3168 .collect::<Vec<_>>()
3169 });
3170 let generics = GenericParams::of(db, self.def);
3171 let type_params = generics.iter_type_or_consts().filter_map(|param| match param.1 {
3172 TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
3173 TypeOrConstParamData::ConstParamData(_) => None,
3174 });
3175 self.subst
3176 .types()
3177 .zip(container_type_params.into_iter().flatten().chain(type_params))
3178 .filter_map(|(ty, name)| {
3179 Some((
3180 name?.symbol().clone(),
3181 Type { ty: EarlyBinder::bind(ty), owner: self.owner },
3182 ))
3183 })
3184 .collect()
3185 }
3186}
3187
3188#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3190pub struct Local<'db> {
3191 pub(crate) parent: ExpressionStoreOwnerId,
3192 pub(crate) parent_infer: InferBodyId<'db>,
3193 pub(crate) binding_id: BindingId,
3194}
3195
3196pub struct LocalSource<'db> {
3197 pub local: Local<'db>,
3198 pub source: InFile<Either<ast::IdentPat, ast::SelfParam>>,
3199}
3200
3201impl<'db> LocalSource<'db> {
3202 pub fn as_ident_pat(&self) -> Option<&ast::IdentPat> {
3203 match &self.source.value {
3204 Either::Left(it) => Some(it),
3205 Either::Right(_) => None,
3206 }
3207 }
3208
3209 pub fn into_ident_pat(self) -> Option<ast::IdentPat> {
3210 match self.source.value {
3211 Either::Left(it) => Some(it),
3212 Either::Right(_) => None,
3213 }
3214 }
3215
3216 pub fn original_file(&self, db: &dyn HirDatabase) -> EditionedFileId {
3217 self.source.file_id.original_file(db)
3218 }
3219
3220 pub fn file(&self) -> HirFileId {
3221 self.source.file_id
3222 }
3223
3224 pub fn name(&self) -> Option<InFile<ast::Name>> {
3225 self.source.as_ref().map(|it| it.name()).transpose()
3226 }
3227
3228 pub fn syntax(&self) -> &SyntaxNode {
3229 self.source.value.syntax()
3230 }
3231
3232 pub fn syntax_ptr(self) -> InFile<SyntaxNodePtr> {
3233 self.source.map(|it| SyntaxNodePtr::new(it.syntax()))
3234 }
3235}
3236
3237impl<'db> Local<'db> {
3238 pub fn is_param(self, db: &dyn HirDatabase) -> bool {
3239 let src = self.primary_source(db);
3241 match src.source.value {
3242 Either::Left(pat) => pat
3243 .syntax()
3244 .ancestors()
3245 .map(|it| it.kind())
3246 .take_while(|&kind| ast::Pat::can_cast(kind) || ast::Param::can_cast(kind))
3247 .any(ast::Param::can_cast),
3248 Either::Right(_) => true,
3249 }
3250 }
3251
3252 pub fn as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
3253 match self.parent {
3254 ExpressionStoreOwnerId::Body(DefWithBodyId::FunctionId(func)) if self.is_self(db) => {
3255 Some(SelfParam { func: func.into() })
3256 }
3257 _ => None,
3258 }
3259 }
3260
3261 pub fn name(self, db: &dyn HirDatabase) -> Name {
3262 ExpressionStore::of(db, self.parent)[self.binding_id].name.clone()
3263 }
3264
3265 pub fn is_self(self, db: &dyn HirDatabase) -> bool {
3266 self.name(db) == sym::self_
3267 }
3268
3269 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
3270 ExpressionStore::of(db, self.parent)[self.binding_id].mode == BindingAnnotation::Mutable
3271 }
3272
3273 pub fn is_ref(self, db: &dyn HirDatabase) -> bool {
3274 matches!(
3275 ExpressionStore::of(db, self.parent)[self.binding_id].mode,
3276 BindingAnnotation::Ref | BindingAnnotation::RefMut
3277 )
3278 }
3279
3280 pub fn parent(self, _db: &dyn HirDatabase) -> ExpressionStoreOwner {
3281 self.parent.into()
3282 }
3283
3284 pub fn module(self, db: &dyn HirDatabase) -> Module {
3285 self.parent(db).module(db)
3286 }
3287
3288 pub fn as_id(self) -> u32 {
3289 self.binding_id.into_raw().into_u32()
3290 }
3291
3292 pub fn ty(self, db: &'db dyn HirDatabase) -> Type<'db> {
3293 let def = self.parent;
3294 let infer = InferenceResult::of(db, self.parent_infer);
3295 let ty = infer.binding_ty(self.binding_id);
3296 Type::new_body(db, def, ty)
3297 }
3298
3299 pub fn sources(self, db: &dyn HirDatabase) -> Vec<LocalSource<'db>> {
3301 let b;
3302 let (_, source_map) = match self.parent {
3303 ExpressionStoreOwnerId::Signature(generic_def_id) => {
3304 ExpressionStore::with_source_map(db, generic_def_id.into())
3305 }
3306 ExpressionStoreOwnerId::Body(def_with_body_id) => {
3307 b = Body::with_source_map(db, def_with_body_id);
3308 if b.0.is_any_self_param(self.binding_id)
3309 && let Some(source) = b.1.self_param_syntax()
3310 {
3311 let root = source.file_syntax(db);
3312 return vec![LocalSource {
3313 local: self,
3314 source: source.map(|ast| Either::Right(ast.to_node(&root))),
3315 }];
3316 }
3317 (&b.0.store, &b.1.store)
3318 }
3319 ExpressionStoreOwnerId::VariantFields(def) => {
3320 ExpressionStore::with_source_map(db, def.into())
3321 }
3322 };
3323 source_map
3324 .patterns_for_binding(self.binding_id)
3325 .iter()
3326 .map(|&definition| {
3327 let src = source_map.pat_syntax(definition).unwrap(); let root = src.file_syntax(db);
3329 LocalSource {
3330 local: self,
3331 source: src.map(|ast| match ast.to_node(&root) {
3332 Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
3333 _ => unreachable!("local with non ident-pattern"),
3334 }),
3335 }
3336 })
3337 .collect()
3338 }
3339
3340 pub fn primary_source(self, db: &dyn HirDatabase) -> LocalSource<'db> {
3342 let b;
3343 let (_, source_map) = match self.parent {
3344 ExpressionStoreOwnerId::Signature(generic_def_id) => {
3345 ExpressionStore::with_source_map(db, generic_def_id.into())
3346 }
3347 ExpressionStoreOwnerId::Body(def_with_body_id) => {
3348 b = Body::with_source_map(db, def_with_body_id);
3349 if b.0.is_any_self_param(self.binding_id)
3350 && let Some(source) = b.1.self_param_syntax()
3351 {
3352 let root = source.file_syntax(db);
3353 return LocalSource {
3354 local: self,
3355 source: source.map(|ast| Either::Right(ast.to_node(&root))),
3356 };
3357 }
3358 (&b.0.store, &b.1.store)
3359 }
3360 ExpressionStoreOwnerId::VariantFields(def) => {
3361 ExpressionStore::with_source_map(db, def.into())
3362 }
3363 };
3364 source_map
3365 .patterns_for_binding(self.binding_id)
3366 .first()
3367 .map(|&definition| {
3368 let src = source_map.pat_syntax(definition).unwrap(); let root = src.file_syntax(db);
3370 LocalSource {
3371 local: self,
3372 source: src.map(|ast| match ast.to_node(&root) {
3373 Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
3374 _ => unreachable!("local with non ident-pattern"),
3375 }),
3376 }
3377 })
3378 .unwrap()
3379 }
3380}
3381
3382impl PartialOrd for Local<'_> {
3383 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
3384 Some(self.cmp(other))
3385 }
3386}
3387
3388impl Ord for Local<'_> {
3389 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
3390 self.binding_id.cmp(&other.binding_id)
3391 }
3392}
3393
3394#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3395pub struct DeriveHelper {
3396 pub(crate) derive: MacroId,
3397 pub(crate) idx: u32,
3398}
3399
3400impl DeriveHelper {
3401 pub fn derive(&self) -> Macro {
3402 Macro { id: self.derive }
3403 }
3404
3405 pub fn name(&self, db: &dyn HirDatabase) -> Name {
3406 AttrFlags::derive_info(db, self.derive)
3407 .and_then(|it| it.helpers.get(self.idx as usize))
3408 .map(|helper| Name::new_symbol_root(helper.clone()))
3409 .unwrap_or_else(Name::missing)
3410 }
3411}
3412
3413#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3414pub struct BuiltinAttr {
3415 idx: u32,
3416}
3417
3418impl BuiltinAttr {
3419 fn builtin(name: &str) -> Option<Self> {
3420 hir_expand::inert_attr_macro::find_builtin_attr_idx(&Symbol::intern(name))
3421 .map(|idx| BuiltinAttr { idx: idx as u32 })
3422 }
3423
3424 pub fn name(&self) -> Name {
3425 Name::new_symbol_root(Symbol::intern(
3426 hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].name,
3427 ))
3428 }
3429
3430 pub fn template(&self) -> Option<AttributeTemplate> {
3431 Some(hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].template)
3432 }
3433}
3434
3435#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3436pub struct ToolModule {
3437 krate: base_db::Crate,
3438 idx: u32,
3439}
3440
3441impl ToolModule {
3442 pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
3443 let krate = krate.id;
3444 let idx =
3445 crate_def_map(db, krate).registered_tools().iter().position(|it| it.as_str() == name)?
3446 as u32;
3447 Some(ToolModule { krate, idx })
3448 }
3449
3450 pub fn name(&self, db: &dyn HirDatabase) -> Name {
3451 Name::new_symbol_root(
3452 crate_def_map(db, self.krate).registered_tools()[self.idx as usize].clone(),
3453 )
3454 }
3455
3456 pub fn krate(&self) -> Crate {
3457 Crate { id: self.krate }
3458 }
3459}
3460
3461#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3462pub struct Label {
3463 pub(crate) parent: ExpressionStoreOwnerId,
3464 pub(crate) label_id: LabelId,
3465}
3466
3467impl Label {
3468 pub fn module(self, db: &dyn HirDatabase) -> Module {
3469 self.parent(db).module(db)
3470 }
3471
3472 pub fn parent(self, _db: &dyn HirDatabase) -> ExpressionStoreOwner {
3473 self.parent.into()
3474 }
3475
3476 pub fn name(self, db: &dyn HirDatabase) -> Name {
3477 ExpressionStore::of(db, self.parent)[self.label_id].name.clone()
3478 }
3479}
3480
3481#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3482pub enum GenericParam {
3483 TypeParam(TypeParam),
3484 ConstParam(ConstParam),
3485 LifetimeParam(LifetimeParam),
3486}
3487impl_from!(TypeParam, ConstParam, LifetimeParam for GenericParam);
3488
3489impl GenericParam {
3490 pub fn module(self, db: &dyn HirDatabase) -> Module {
3491 match self {
3492 GenericParam::TypeParam(it) => it.module(db),
3493 GenericParam::ConstParam(it) => it.module(db),
3494 GenericParam::LifetimeParam(it) => it.module(db),
3495 }
3496 }
3497
3498 pub fn name(self, db: &dyn HirDatabase) -> Name {
3499 match self {
3500 GenericParam::TypeParam(it) => it.name(db),
3501 GenericParam::ConstParam(it) => it.name(db),
3502 GenericParam::LifetimeParam(it) => it.name(db),
3503 }
3504 }
3505
3506 pub fn parent(self) -> GenericDef {
3507 match self {
3508 GenericParam::TypeParam(it) => it.id.parent().into(),
3509 GenericParam::ConstParam(it) => it.id.parent().into(),
3510 GenericParam::LifetimeParam(it) => it.id.parent.into(),
3511 }
3512 }
3513
3514 pub fn variance(self, db: &dyn HirDatabase) -> Option<Variance> {
3515 let parent = match self {
3516 GenericParam::TypeParam(it) => it.id.parent(),
3517 GenericParam::ConstParam(_) => return None,
3519 GenericParam::LifetimeParam(it) => it.id.parent,
3520 };
3521 let index = match self {
3522 GenericParam::TypeParam(it) => hir_ty::type_or_const_param_idx(db, it.id.into()),
3523 GenericParam::ConstParam(_) => return None,
3524 GenericParam::LifetimeParam(it) => hir_ty::lifetime_param_idx(db, it.id),
3525 };
3526 db.variances_of(parent).get(index as usize).map(Into::into)
3527 }
3528}
3529
3530#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3531pub enum Variance {
3532 Bivariant,
3533 Covariant,
3534 Contravariant,
3535 Invariant,
3536}
3537
3538impl From<rustc_type_ir::Variance> for Variance {
3539 #[inline]
3540 fn from(value: rustc_type_ir::Variance) -> Self {
3541 match value {
3542 rustc_type_ir::Variance::Covariant => Variance::Covariant,
3543 rustc_type_ir::Variance::Invariant => Variance::Invariant,
3544 rustc_type_ir::Variance::Contravariant => Variance::Contravariant,
3545 rustc_type_ir::Variance::Bivariant => Variance::Bivariant,
3546 }
3547 }
3548}
3549
3550impl fmt::Display for Variance {
3551 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3552 let description = match self {
3553 Variance::Bivariant => "bivariant",
3554 Variance::Covariant => "covariant",
3555 Variance::Contravariant => "contravariant",
3556 Variance::Invariant => "invariant",
3557 };
3558 f.pad(description)
3559 }
3560}
3561
3562#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3563pub struct TypeParam {
3564 pub(crate) id: TypeParamId,
3565}
3566
3567impl TypeParam {
3568 pub fn merge(self) -> TypeOrConstParam {
3569 TypeOrConstParam { id: self.id.into() }
3570 }
3571
3572 pub fn name(self, db: &dyn HirDatabase) -> Name {
3573 self.merge().name(db)
3574 }
3575
3576 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
3577 self.id.parent().into()
3578 }
3579
3580 pub fn module(self, db: &dyn HirDatabase) -> Module {
3581 self.id.parent().module(db).into()
3582 }
3583
3584 pub fn is_implicit(self, db: &dyn HirDatabase) -> bool {
3587 let params = GenericParams::of(db, self.id.parent());
3588 let data = ¶ms[self.id.local_id()];
3589 match data.type_param().unwrap().provenance {
3590 TypeParamProvenance::TypeParamList => false,
3591 TypeParamProvenance::TraitSelf | TypeParamProvenance::ArgumentImplTrait => true,
3592 }
3593 }
3594
3595 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
3596 let interner = DbInterner::new_no_crate(db);
3597 let index = hir_ty::type_or_const_param_idx(db, self.id.into());
3598 let ty = Ty::new_param(interner, self.id, index);
3599 Type::new(self.id.parent(), ty)
3600 }
3601
3602 pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
3606 let self_ty = self.ty(db).ty.instantiate_identity().skip_norm_wip();
3607 GenericPredicates::query_explicit(db, self.id.parent())
3608 .iter_identity()
3609 .filter_map(|pred| match &pred.kind().skip_binder() {
3610 ClauseKind::Trait(trait_ref) if trait_ref.self_ty() == self_ty => {
3611 Some(Trait::from(trait_ref.def_id().0))
3612 }
3613 _ => None,
3614 })
3615 .collect()
3616 }
3617
3618 pub fn default(self, db: &dyn HirDatabase) -> Option<Type<'_>> {
3619 let ty = generic_arg_from_param(db, self.id.into())?;
3620 match ty.kind() {
3621 rustc_type_ir::GenericArgKind::Type(it) if !it.is_ty_error() => {
3622 Some(Type::new(self.id.parent(), it))
3623 }
3624 _ => None,
3625 }
3626 }
3627
3628 pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
3629 self.attrs(db).is_unstable()
3630 }
3631}
3632
3633#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3634pub struct LifetimeParam {
3635 pub(crate) id: LifetimeParamId,
3636}
3637
3638impl LifetimeParam {
3639 pub fn name(self, db: &dyn HirDatabase) -> Name {
3640 let params = GenericParams::of(db, self.id.parent);
3641 params[self.id.local_id].name.clone()
3642 }
3643
3644 pub fn module(self, db: &dyn HirDatabase) -> Module {
3645 self.id.parent.module(db).into()
3646 }
3647
3648 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
3649 self.id.parent.into()
3650 }
3651}
3652
3653#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3654pub struct ConstParam {
3655 pub(crate) id: ConstParamId,
3656}
3657
3658impl ConstParam {
3659 pub fn merge(self) -> TypeOrConstParam {
3660 TypeOrConstParam { id: self.id.into() }
3661 }
3662
3663 pub fn name(self, db: &dyn HirDatabase) -> Name {
3664 let params = GenericParams::of(db, self.id.parent());
3665 match params[self.id.local_id()].name() {
3666 Some(it) => it.clone(),
3667 None => {
3668 never!();
3669 Name::missing()
3670 }
3671 }
3672 }
3673
3674 pub fn module(self, db: &dyn HirDatabase) -> Module {
3675 self.id.parent().module(db).into()
3676 }
3677
3678 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
3679 self.id.parent().into()
3680 }
3681
3682 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
3683 Type::new(self.id.parent(), db.const_param_ty(self.id))
3684 }
3685
3686 pub fn default(self, db: &dyn HirDatabase, display_target: DisplayTarget) -> Option<String> {
3687 let arg = generic_arg_from_param(db, self.id.into())?;
3688 Some(arg.display(db, display_target).to_string())
3689 }
3690
3691 pub fn default_source_code(
3692 self,
3693 db: &dyn HirDatabase,
3694 target_module: Module,
3695 ) -> Option<ast::ConstArg> {
3696 let arg = generic_arg_from_param(db, self.id.into())?;
3697 known_const_to_ast(arg.konst()?, db, target_module.id)
3698 }
3699}
3700
3701fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<GenericArg<'_>> {
3702 let local_idx = hir_ty::type_or_const_param_idx(db, id);
3703 let defaults = db.generic_defaults(id.parent);
3704 let ty = defaults.get(local_idx as usize)?;
3705 Some(ty.instantiate_identity().skip_norm_wip())
3707}
3708
3709#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3710pub struct TypeOrConstParam {
3711 pub(crate) id: TypeOrConstParamId,
3712}
3713
3714impl TypeOrConstParam {
3715 pub fn name(self, db: &dyn HirDatabase) -> Name {
3716 let params = GenericParams::of(db, self.id.parent);
3717 match params[self.id.local_id].name() {
3718 Some(n) => n.clone(),
3719 _ => Name::missing(),
3720 }
3721 }
3722
3723 pub fn module(self, db: &dyn HirDatabase) -> Module {
3724 self.id.parent.module(db).into()
3725 }
3726
3727 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
3728 self.id.parent.into()
3729 }
3730
3731 pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
3732 let params = GenericParams::of(db, self.id.parent);
3733 match ¶ms[self.id.local_id] {
3734 TypeOrConstParamData::TypeParamData(_) => {
3735 Either::Right(TypeParam { id: TypeParamId::from_unchecked(self.id) })
3736 }
3737 TypeOrConstParamData::ConstParamData(_) => {
3738 Either::Left(ConstParam { id: ConstParamId::from_unchecked(self.id) })
3739 }
3740 }
3741 }
3742
3743 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
3744 match self.split(db) {
3745 Either::Left(it) => it.ty(db),
3746 Either::Right(it) => it.ty(db),
3747 }
3748 }
3749
3750 pub fn as_type_param(self, db: &dyn HirDatabase) -> Option<TypeParam> {
3751 let params = GenericParams::of(db, self.id.parent);
3752 match ¶ms[self.id.local_id] {
3753 TypeOrConstParamData::TypeParamData(_) => {
3754 Some(TypeParam { id: TypeParamId::from_unchecked(self.id) })
3755 }
3756 TypeOrConstParamData::ConstParamData(_) => None,
3757 }
3758 }
3759
3760 pub fn as_const_param(self, db: &dyn HirDatabase) -> Option<ConstParam> {
3761 let params = GenericParams::of(db, self.id.parent);
3762 match ¶ms[self.id.local_id] {
3763 TypeOrConstParamData::TypeParamData(_) => None,
3764 TypeOrConstParamData::ConstParamData(_) => {
3765 Some(ConstParam { id: ConstParamId::from_unchecked(self.id) })
3766 }
3767 }
3768 }
3769}
3770
3771#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3772pub struct Impl {
3773 pub(crate) id: AnyImplId,
3774}
3775
3776impl Impl {
3777 pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<Impl> {
3778 let mut result = Vec::new();
3779 extend_with_def_map(db, crate_def_map(db, krate.id), &mut result);
3780 return result;
3781
3782 fn extend_with_def_map(db: &dyn HirDatabase, def_map: &DefMap, result: &mut Vec<Impl>) {
3783 for (_, module) in def_map.modules() {
3784 result.extend(module.scope.impls().map(Impl::from));
3785 result.extend(module.scope.builtin_derive_impls().map(Impl::from));
3786
3787 for unnamed_const in module.scope.unnamed_consts() {
3788 for (_, block_def_map) in Body::of(db, unnamed_const.into()).blocks(db) {
3789 extend_with_def_map(db, block_def_map, result);
3790 }
3791 }
3792 }
3793 }
3794 }
3795
3796 pub fn all_in_module(db: &dyn HirDatabase, module: Module) -> Vec<Impl> {
3797 module.impl_defs(db)
3798 }
3799
3800 pub fn all_for_type<'db>(db: &'db dyn HirDatabase, ty: Type<'db>) -> Vec<Impl> {
3806 let mut result = Vec::new();
3807 let interner = DbInterner::new_no_crate(db);
3808 let Some(simplified_ty) = fast_reject::simplify_type(
3809 interner,
3810 ty.ty.skip_binder(),
3811 fast_reject::TreatParams::AsRigid,
3812 ) else {
3813 return Vec::new();
3814 };
3815 let mut extend_with_impls = |impls: Either<&[ImplId], &[BuiltinDeriveImplId]>| match impls {
3816 Either::Left(impls) => result.extend(impls.iter().copied().map(Impl::from)),
3817 Either::Right(impls) => result.extend(impls.iter().copied().map(Impl::from)),
3818 };
3819 method_resolution::with_incoherent_inherent_impls(
3820 db,
3821 ty.krate(db),
3822 &simplified_ty,
3823 |impls| extend_with_impls(Either::Left(impls)),
3824 );
3825 if let Some(module) = method_resolution::simplified_type_module(db, &simplified_ty) {
3826 InherentImpls::for_each_crate_and_block(
3827 db,
3828 module.krate(db),
3829 module.block(db),
3830 &mut |impls| extend_with_impls(Either::Left(impls.for_self_ty(&simplified_ty))),
3831 );
3832 std::iter::successors(module.block(db), |block| block.module(db).block(db))
3833 .filter_map(|block| TraitImpls::for_block(db, block))
3834 .for_each(|impls| impls.for_self_ty(&simplified_ty, &mut extend_with_impls));
3835 for &krate in &*all_crates(db) {
3836 TraitImpls::for_crate(db, krate)
3837 .for_self_ty(&simplified_ty, &mut extend_with_impls);
3838 }
3839 } else {
3840 for &krate in &*all_crates(db) {
3841 TraitImpls::for_crate(db, krate)
3842 .for_self_ty(&simplified_ty, &mut extend_with_impls);
3843 }
3844 }
3845 result
3846 }
3847
3848 pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
3849 let module = trait_.module(db).id;
3850 let mut all = Vec::new();
3851 let mut handle_impls = |impls: &TraitImpls<'_>| {
3852 impls.for_trait(trait_.id, |impls| match impls {
3853 Either::Left(impls) => all.extend(impls.iter().copied().map(Impl::from)),
3854 Either::Right(impls) => all.extend(impls.iter().copied().map(Impl::from)),
3855 });
3856 };
3857 for krate in module.krate(db).transitive_rev_deps(db) {
3858 handle_impls(TraitImpls::for_crate(db, krate));
3859 }
3860 if let Some(block) = module.block(db)
3861 && let Some(impls) = TraitImpls::for_block(db, block)
3862 {
3863 handle_impls(impls);
3864 }
3865 all
3866 }
3867
3868 pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> {
3869 match self.id {
3870 AnyImplId::ImplId(id) => {
3871 let trait_ref = db.impl_trait(id)?;
3872 let id = trait_ref.skip_binder().def_id;
3873 Some(Trait { id: id.0 })
3874 }
3875 AnyImplId::BuiltinDeriveImplId(id) => {
3876 let loc = id.loc(db);
3877 let lang_items = hir_def::lang_item::lang_items(db, loc.adt.module(db).krate(db));
3878 loc.trait_.get_id(lang_items).map(Trait::from)
3879 }
3880 }
3881 }
3882
3883 pub fn trait_ref(self, db: &dyn HirDatabase) -> Option<TraitRef<'_>> {
3884 match self.id {
3885 AnyImplId::ImplId(id) => {
3886 let trait_ref = db.impl_trait(id)?.instantiate_identity().skip_norm_wip();
3887 Some(TraitRef::new(id.into(), trait_ref))
3888 }
3889 AnyImplId::BuiltinDeriveImplId(id) => {
3890 let loc = id.loc(db);
3891 let krate = loc.module(db).krate(db);
3892 let interner = DbInterner::new_with(db, krate);
3893 let trait_ref = hir_ty::builtin_derive::impl_trait(interner, id)
3894 .instantiate_identity()
3895 .skip_norm_wip();
3896 Some(TraitRef { owner: TypeOwnerId::BuiltinDeriveImplId(id), trait_ref })
3897 }
3898 }
3899 }
3900
3901 pub fn self_ty(self, db: &dyn HirDatabase) -> Type<'_> {
3902 match self.id {
3903 AnyImplId::ImplId(id) => {
3904 let ty = db.impl_self_ty(id).instantiate_identity().skip_norm_wip();
3905 Type::new(id.into(), ty)
3906 }
3907 AnyImplId::BuiltinDeriveImplId(id) => {
3908 let loc = id.loc(db);
3909 let krate = loc.module(db).krate(db);
3910 let interner = DbInterner::new_with(db, krate);
3911 let ty =
3912 hir_ty::builtin_derive::impl_trait(interner, id).map_bound(|it| it.self_ty());
3913 Type { owner: TypeOwnerId::BuiltinDeriveImplId(id), ty }
3914 }
3915 }
3916 }
3917
3918 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
3919 match self.id {
3920 AnyImplId::ImplId(id) => {
3921 id.impl_items(db).items.iter().map(|&(_, it)| it.into()).collect()
3922 }
3923 AnyImplId::BuiltinDeriveImplId(impl_) => impl_
3924 .loc(db)
3925 .trait_
3926 .all_methods()
3927 .iter()
3928 .map(|&method| {
3929 AssocItem::Function(Function {
3930 id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ },
3931 })
3932 })
3933 .collect(),
3934 }
3935 }
3936
3937 pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
3938 match self.id {
3939 AnyImplId::ImplId(id) => ImplSignature::of(db, id).flags.contains(ImplFlags::NEGATIVE),
3940 AnyImplId::BuiltinDeriveImplId(_) => false,
3941 }
3942 }
3943
3944 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
3945 match self.id {
3946 AnyImplId::ImplId(id) => ImplSignature::of(db, id).flags.contains(ImplFlags::UNSAFE),
3947 AnyImplId::BuiltinDeriveImplId(_) => false,
3948 }
3949 }
3950
3951 pub fn module(self, db: &dyn HirDatabase) -> Module {
3952 match self.id {
3953 AnyImplId::ImplId(id) => id.module(db).into(),
3954 AnyImplId::BuiltinDeriveImplId(id) => id.module(db).into(),
3955 }
3956 }
3957
3958 pub fn check_orphan_rules(self, db: &dyn HirDatabase) -> bool {
3959 match self.id {
3960 AnyImplId::ImplId(id) => check_orphan_rules(db, id),
3961 AnyImplId::BuiltinDeriveImplId(_) => true,
3962 }
3963 }
3964}
3965
3966#[derive(Clone, PartialEq, Eq, Debug, Hash)]
3967pub struct TraitRef<'db> {
3968 owner: TypeOwnerId<'db>,
3969 trait_ref: hir_ty::next_solver::TraitRef<'db>,
3970}
3971
3972impl<'db> TraitRef<'db> {
3973 fn new(owner: GenericDefId, trait_ref: hir_ty::next_solver::TraitRef<'db>) -> Self {
3974 Self { owner: TypeOwnerId::GenericDefId(owner), trait_ref }
3975 }
3976
3977 pub fn trait_(&self) -> Trait {
3978 Trait { id: self.trait_ref.def_id.0 }
3979 }
3980
3981 pub fn self_ty(&self) -> Type<'_> {
3982 let ty = self.trait_ref.self_ty();
3983 Type { owner: self.owner, ty: EarlyBinder::bind(ty) }
3984 }
3985
3986 pub fn get_type_argument(&self, idx: usize) -> Option<Type<'db>> {
3989 self.trait_ref
3990 .args
3991 .as_slice()
3992 .get(idx)
3993 .and_then(|arg| arg.ty())
3994 .map(|ty| Type { owner: self.owner, ty: EarlyBinder::bind(ty) })
3995 }
3996}
3997
3998#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3999enum AnyClosureId<'db> {
4000 ClosureId(InternedClosureId<'db>),
4001 CoroutineClosureId(InternedCoroutineClosureId<'db>),
4002}
4003
4004#[derive(Clone, Debug, PartialEq, Eq, Hash)]
4005pub struct Closure<'db> {
4006 owner: TypeOwnerId<'db>,
4007 id: AnyClosureId<'db>,
4008 subst: GenericArgs<'db>,
4009}
4010
4011impl<'db> Closure<'db> {
4012 fn as_ty(&self, db: &'db dyn HirDatabase) -> Ty<'db> {
4013 let interner = DbInterner::new_no_crate(db);
4014 match self.id {
4015 AnyClosureId::ClosureId(id) => Ty::new_closure(interner, id.into(), self.subst),
4016 AnyClosureId::CoroutineClosureId(id) => {
4017 Ty::new_coroutine_closure(interner, id.into(), self.subst)
4018 }
4019 }
4020 }
4021
4022 pub fn display_with_id(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
4023 self.as_ty(db)
4024 .display(db, display_target)
4025 .with_closure_style(ClosureStyle::ClosureWithId)
4026 .to_string()
4027 }
4028
4029 pub fn display_with_impl(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
4030 self.as_ty(db)
4031 .display(db, display_target)
4032 .with_closure_style(ClosureStyle::ImplFn)
4033 .to_string()
4034 }
4035
4036 pub fn captured_items(&self, db: &'db dyn HirDatabase) -> Vec<ClosureCapture<'db>> {
4037 let closure = match self.id {
4038 AnyClosureId::ClosureId(it) => it.loc(db),
4039 AnyClosureId::CoroutineClosureId(it) => it.loc(db),
4040 };
4041 captured_items(db, closure)
4042 }
4043
4044 pub fn fn_trait(&self, _db: &dyn HirDatabase) -> FnTrait {
4045 match self.id {
4046 AnyClosureId::ClosureId(_) => match self.subst.as_closure().kind() {
4047 rustc_type_ir::ClosureKind::Fn => FnTrait::Fn,
4048 rustc_type_ir::ClosureKind::FnMut => FnTrait::FnMut,
4049 rustc_type_ir::ClosureKind::FnOnce => FnTrait::FnOnce,
4050 },
4051 AnyClosureId::CoroutineClosureId(_) => match self.subst.as_coroutine_closure().kind() {
4052 rustc_type_ir::ClosureKind::Fn => FnTrait::AsyncFn,
4053 rustc_type_ir::ClosureKind::FnMut => FnTrait::AsyncFnMut,
4054 rustc_type_ir::ClosureKind::FnOnce => FnTrait::AsyncFnOnce,
4055 },
4056 }
4057 }
4058}
4059
4060#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4062pub struct Coroutine<'db> {
4063 id: InternedCoroutineId<'db>,
4064}
4065
4066impl<'db> Coroutine<'db> {
4067 pub fn captured_items(&self, db: &'db dyn HirDatabase) -> Vec<ClosureCapture<'db>> {
4069 captured_items(db, self.id.loc(db))
4070 }
4071}
4072
4073fn captured_items<'db>(
4074 db: &'db dyn HirDatabase,
4075 closure: InternedClosure<'db>,
4076) -> Vec<ClosureCapture<'db>> {
4077 let InternedClosure { owner: infer_owner, expr: closure, .. } = closure;
4078 let infer = InferenceResult::of(db, infer_owner);
4079 let owner = infer_owner.expression_store_owner(db);
4080 infer.closures_data[&closure]
4081 .min_captures
4082 .values()
4083 .flatten()
4084 .map(|capture| ClosureCapture { owner, infer_owner, closure, capture })
4085 .collect()
4086}
4087
4088#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4089pub enum FnTrait {
4090 FnOnce,
4091 FnMut,
4092 Fn,
4093
4094 AsyncFnOnce,
4095 AsyncFnMut,
4096 AsyncFn,
4097}
4098
4099impl From<traits::FnTrait> for FnTrait {
4100 fn from(value: traits::FnTrait) -> Self {
4101 match value {
4102 traits::FnTrait::FnOnce => FnTrait::FnOnce,
4103 traits::FnTrait::FnMut => FnTrait::FnMut,
4104 traits::FnTrait::Fn => FnTrait::Fn,
4105 traits::FnTrait::AsyncFnOnce => FnTrait::AsyncFnOnce,
4106 traits::FnTrait::AsyncFnMut => FnTrait::AsyncFnMut,
4107 traits::FnTrait::AsyncFn => FnTrait::AsyncFn,
4108 }
4109 }
4110}
4111
4112impl fmt::Display for FnTrait {
4113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4114 match self {
4115 FnTrait::FnOnce => write!(f, "FnOnce"),
4116 FnTrait::FnMut => write!(f, "FnMut"),
4117 FnTrait::Fn => write!(f, "Fn"),
4118 FnTrait::AsyncFnOnce => write!(f, "AsyncFnOnce"),
4119 FnTrait::AsyncFnMut => write!(f, "AsyncFnMut"),
4120 FnTrait::AsyncFn => write!(f, "AsyncFn"),
4121 }
4122 }
4123}
4124
4125impl FnTrait {
4126 pub const fn function_name(&self) -> &'static str {
4127 match self {
4128 FnTrait::FnOnce => "call_once",
4129 FnTrait::FnMut => "call_mut",
4130 FnTrait::Fn => "call",
4131 FnTrait::AsyncFnOnce => "async_call_once",
4132 FnTrait::AsyncFnMut => "async_call_mut",
4133 FnTrait::AsyncFn => "async_call",
4134 }
4135 }
4136
4137 pub fn lang_item(self) -> LangItem {
4138 match self {
4139 FnTrait::FnOnce => LangItem::FnOnce,
4140 FnTrait::FnMut => LangItem::FnMut,
4141 FnTrait::Fn => LangItem::Fn,
4142 FnTrait::AsyncFnOnce => LangItem::AsyncFnOnce,
4143 FnTrait::AsyncFnMut => LangItem::AsyncFnMut,
4144 FnTrait::AsyncFn => LangItem::AsyncFn,
4145 }
4146 }
4147
4148 pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option<Trait> {
4149 Trait::lang(db, krate, self.lang_item())
4150 }
4151}
4152
4153#[derive(Clone, Debug, PartialEq, Eq)]
4154pub struct ClosureCapture<'db> {
4155 owner: ExpressionStoreOwnerId,
4156 infer_owner: InferBodyId<'db>,
4157 closure: ExprId,
4158 capture: &'db hir_ty::closure_analysis::CapturedPlace,
4159}
4160
4161impl<'db> ClosureCapture<'db> {
4162 pub fn local(&self) -> Local<'db> {
4163 Local {
4164 parent: self.owner,
4165 parent_infer: self.infer_owner,
4166 binding_id: self.capture.captured_local(),
4167 }
4168 }
4169
4170 pub fn has_field_projections(&self) -> bool {
4172 self.capture
4173 .place
4174 .projections
4175 .iter()
4176 .any(|proj| matches!(proj.kind, hir_ty::closure_analysis::ProjectionKind::Field { .. }))
4177 }
4178
4179 pub fn usages(&self) -> CaptureUsages<'db> {
4180 CaptureUsages { parent: self.owner, sources: &self.capture.info.sources }
4181 }
4182
4183 pub fn kind(&self) -> CaptureKind {
4184 match self.capture.info.capture_kind {
4185 hir_ty::closure_analysis::UpvarCapture::ByValue => CaptureKind::Move,
4186 hir_ty::closure_analysis::UpvarCapture::ByUse => CaptureKind::SharedRef, hir_ty::closure_analysis::UpvarCapture::ByRef(
4188 hir_ty::closure_analysis::BorrowKind::Immutable,
4189 ) => CaptureKind::SharedRef,
4190 hir_ty::closure_analysis::UpvarCapture::ByRef(
4191 hir_ty::closure_analysis::BorrowKind::UniqueImmutable,
4192 ) => CaptureKind::UniqueSharedRef,
4193 hir_ty::closure_analysis::UpvarCapture::ByRef(
4194 hir_ty::closure_analysis::BorrowKind::Mutable,
4195 ) => CaptureKind::MutableRef,
4196 }
4197 }
4198
4199 pub fn place_to_name(&self, db: &dyn HirDatabase, edition: Edition) -> String {
4201 let mut result = self.local().name(db).display(db, edition).to_string();
4202 for (i, proj) in self.capture.place.projections.iter().enumerate() {
4203 match proj.kind {
4204 hir_ty::closure_analysis::ProjectionKind::Deref => {}
4205 hir_ty::closure_analysis::ProjectionKind::Field { field_idx, variant_idx } => {
4206 let ty = self.capture.place.ty_before_projection(i);
4207 match ty.kind() {
4208 TyKind::Tuple(_) => format_to!(result, "_{field_idx}"),
4209 TyKind::Adt(adt_def, _) => {
4210 let variant = match adt_def.def_id() {
4211 AdtId::StructId(id) => VariantId::from(id),
4212 AdtId::UnionId(id) => id.into(),
4213 AdtId::EnumId(id) => {
4214 id.enum_variants(db).variants[variant_idx as usize].0.into()
4215 }
4216 };
4217 let field = &variant.fields(db).fields()
4218 [LocalFieldId::from_raw(la_arena::RawIdx::from_u32(field_idx))];
4219 format_to!(result, "_{}", field.name.display(db, edition));
4220 }
4221 _ => never!("mismatching projection type"),
4222 }
4223 }
4224 _ => never!("unexpected projection kind"),
4225 }
4226 }
4227 result
4228 }
4229
4230 pub fn display_place_source_code(&self, db: &dyn HirDatabase, edition: Edition) -> String {
4231 let mut result = self.local().name(db).display(db, edition).to_string();
4232 let mut last_derefs = 0;
4234 for (i, proj) in self.capture.place.projections.iter().enumerate() {
4235 match proj.kind {
4236 hir_ty::closure_analysis::ProjectionKind::Deref => last_derefs += 1,
4237 hir_ty::closure_analysis::ProjectionKind::Field { field_idx, variant_idx } => {
4238 last_derefs = 0;
4239
4240 let ty = self.capture.place.ty_before_projection(i);
4241 match ty.kind() {
4242 TyKind::Tuple(_) => format_to!(result, ".{field_idx}"),
4243 TyKind::Adt(adt_def, _) => {
4244 let variant = match adt_def.def_id() {
4245 AdtId::StructId(id) => VariantId::from(id),
4246 AdtId::UnionId(id) => id.into(),
4247 AdtId::EnumId(id) => {
4248 id.enum_variants(db).variants[variant_idx as usize].0.into()
4250 }
4251 };
4252 let field = &variant.fields(db).fields()
4253 [LocalFieldId::from_raw(la_arena::RawIdx::from_u32(field_idx))];
4254 format_to!(result, ".{}", field.name.display(db, edition));
4255 }
4256 _ => never!("mismatching projection type"),
4257 }
4258 }
4259 _ => never!("unexpected projection kind"),
4260 }
4261 }
4262 result.insert_str(0, &"*".repeat(last_derefs));
4263 result
4264 }
4265
4266 pub fn ty(&self, db: &'db dyn HirDatabase) -> Type<'db> {
4267 Type::new_body(db, self.owner, self.capture.place.ty())
4268 }
4269
4270 pub fn captured_ty(&self, db: &'db dyn HirDatabase) -> Type<'db> {
4273 Type::new_body(db, self.owner, self.capture.captured_ty(db))
4274 }
4275}
4276
4277#[derive(Clone, Copy, PartialEq, Eq)]
4278pub enum CaptureKind {
4279 SharedRef,
4280 UniqueSharedRef,
4281 MutableRef,
4282 Move,
4283}
4284
4285#[derive(Debug, Clone)]
4286pub struct CaptureUsages<'db> {
4287 parent: ExpressionStoreOwnerId,
4288 sources: &'db [hir_ty::closure_analysis::CaptureSourceStack],
4289}
4290
4291impl CaptureUsages<'_> {
4292 fn is_ref(store: &ExpressionStore, id: ExprOrPatId) -> bool {
4293 match id {
4294 ExprOrPatId::ExprId(expr) => matches!(store[expr], Expr::Ref { .. }),
4295 ExprOrPatId::PatId(pat) => match store[pat] {
4297 Pat::Bind { id: binding, .. } => matches!(
4298 store[binding].mode,
4299 BindingAnnotation::Ref | BindingAnnotation::RefMut
4300 ),
4301 _ => false,
4302 },
4303 }
4304 }
4305
4306 pub fn sources(&self, db: &dyn HirDatabase) -> Vec<CaptureUsageSource> {
4307 let (store, source_map) = ExpressionStore::with_source_map(db, self.parent);
4308 let mut result = Vec::with_capacity(self.sources.len());
4309 for source in self.sources {
4310 let source = source.final_source();
4311 let is_ref = Self::is_ref(store, source.unpack());
4312 match source.unpack() {
4313 ExprOrPatId::ExprId(expr) => {
4314 if let Ok(expr) = source_map.expr_syntax(expr) {
4315 result.push(CaptureUsageSource { is_ref, source: expr })
4316 }
4317 }
4318 ExprOrPatId::PatId(pat) => {
4319 if let Ok(pat) = source_map.pat_syntax(pat) {
4320 result.push(CaptureUsageSource { is_ref, source: pat });
4321 }
4322 }
4323 }
4324 }
4325 result
4326 }
4327}
4328
4329#[derive(Debug)]
4330pub struct CaptureUsageSource {
4331 is_ref: bool,
4332 source: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
4333}
4334
4335impl CaptureUsageSource {
4336 pub fn source(&self) -> AstPtr<Either<ast::Expr, ast::Pat>> {
4337 self.source.value
4338 }
4339
4340 pub fn file_id(&self) -> HirFileId {
4341 self.source.file_id
4342 }
4343
4344 pub fn is_ref(&self) -> bool {
4345 self.is_ref
4346 }
4347}
4348
4349#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
4350enum TypeOwnerId<'db> {
4351 GenericDefId(GenericDefId),
4352 BuiltinDeriveImplId(BuiltinDeriveImplId),
4353 AnonConstId(AnonConstId<'db>),
4354 NoParams(base_db::Crate),
4356}
4357
4358impl_from!(
4359 impl<'db>
4360 GenericDefId,
4361 BuiltinDeriveImplId,
4362 AnonConstId<'db>
4363 for TypeOwnerId<'db>
4364);
4365
4366impl TypeOwnerId<'_> {
4367 fn unify(self, other: Self) -> Option<Self> {
4368 match (self, other) {
4369 (TypeOwnerId::NoParams(_), owner) => Some(owner),
4370 (owner, TypeOwnerId::NoParams(_)) => Some(owner),
4371 (_, _) => {
4372 if self == other {
4373 Some(self)
4374 } else {
4375 None
4376 }
4377 }
4378 }
4379 }
4380
4381 #[track_caller]
4382 fn must_unify(self, other: Self) -> Self {
4383 self.unify(other).expect("failed to unify type owners")
4384 }
4385
4386 fn can_rebase_into(
4387 self,
4388 db: &dyn HirDatabase,
4389 rebase_into: Self,
4390 self_ty: EarlyBinder<'_, Ty<'_>>,
4391 ) -> bool {
4392 if self == rebase_into || !self_ty.skip_binder().has_param() {
4393 return true;
4394 }
4395 let self_def = match self {
4396 TypeOwnerId::GenericDefId(def) => def,
4397 TypeOwnerId::BuiltinDeriveImplId(_) | TypeOwnerId::AnonConstId(_) => return false,
4398 TypeOwnerId::NoParams(_) => return true,
4399 };
4400 let self_def = match self_def {
4401 GenericDefId::ImplId(def) => ItemContainerId::ImplId(def),
4402 GenericDefId::TraitId(def) => ItemContainerId::TraitId(def),
4403 GenericDefId::AdtId(_)
4404 | GenericDefId::ConstId(_)
4405 | GenericDefId::FunctionId(_)
4406 | GenericDefId::StaticId(_)
4407 | GenericDefId::TypeAliasId(_) => return false,
4408 };
4409 let rebase_into_def = match rebase_into {
4410 TypeOwnerId::GenericDefId(def) => def,
4411 TypeOwnerId::BuiltinDeriveImplId(_)
4412 | TypeOwnerId::AnonConstId(_)
4413 | TypeOwnerId::NoParams(_) => return false,
4414 };
4415 let rebase_into_parent = match rebase_into_def {
4416 GenericDefId::ConstId(def) => def.loc(db).container,
4417 GenericDefId::FunctionId(def) => def.loc(db).container,
4418 GenericDefId::TypeAliasId(def) => def.loc(db).container,
4419 GenericDefId::AdtId(_)
4420 | GenericDefId::ImplId(_)
4421 | GenericDefId::StaticId(_)
4422 | GenericDefId::TraitId(_) => return false,
4423 };
4424 self_def == rebase_into_parent
4425 }
4426}
4427
4428#[derive(Clone, Debug)]
4431pub struct Type<'db> {
4432 owner: TypeOwnerId<'db>,
4433 ty: EarlyBinder<'db, Ty<'db>>,
4434}
4435
4436impl<'db> std::hash::Hash for Type<'db> {
4437 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
4438 self.ty.hash(state);
4441 }
4442}
4443
4444impl<'db> PartialEq for Type<'db> {
4445 fn eq(&self, other: &Self) -> bool {
4446 if self.ty != other.ty {
4447 return false;
4448 }
4449 hir_ty::with_attached_db(|db| {
4450 self.owner.can_rebase_into(db, other.owner, self.ty)
4451 || other.owner.can_rebase_into(db, self.owner, other.ty)
4452 })
4453 }
4454}
4455
4456impl<'db> Eq for Type<'db> {}
4457
4458impl<'db> Type<'db> {
4459 fn new(owner: GenericDefId, ty: Ty<'db>) -> Self {
4460 Type { owner: TypeOwnerId::GenericDefId(owner), ty: EarlyBinder::bind(ty) }
4461 }
4462
4463 fn new_body(db: &dyn HirDatabase, owner: ExpressionStoreOwnerId, ty: Ty<'db>) -> Self {
4464 Self::new(owner.generic_def(db), ty)
4465 }
4466
4467 fn no_params(krate: base_db::Crate, ty: Ty<'db>) -> Self {
4468 Type { owner: TypeOwnerId::NoParams(krate), ty: EarlyBinder::bind(ty) }
4469 }
4470
4471 fn builtin_type_crate(db: &'db dyn HirDatabase) -> base_db::Crate {
4472 all_crates(db)[0]
4474 }
4475
4476 fn from_def(db: &'db dyn HirDatabase, def: impl Into<TyDefId>) -> Self {
4477 let def = def.into();
4478 let ty = db.ty(def);
4479 let owner = match def {
4480 TyDefId::AdtId(it) => TypeOwnerId::GenericDefId(GenericDefId::AdtId(it)),
4481 TyDefId::TypeAliasId(it) => TypeOwnerId::GenericDefId(GenericDefId::TypeAliasId(it)),
4482 TyDefId::BuiltinType(_) => TypeOwnerId::NoParams(Self::builtin_type_crate(db)),
4483 };
4484 Type { owner, ty }
4485 }
4486
4487 fn from_value_def(db: &'db dyn HirDatabase, def: impl Into<ValueTyDefId>) -> Self {
4488 let def = def.into();
4489 let Some(ty) = db.value_ty(def) else {
4490 return Type::unknown();
4491 };
4492 let def = match def {
4493 ValueTyDefId::ConstId(it) => GenericDefId::ConstId(it),
4494 ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it),
4495 ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)),
4496 ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)),
4497 ValueTyDefId::EnumVariantId(it) => {
4498 GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent))
4499 }
4500 ValueTyDefId::StaticId(it) => {
4501 return Type::no_params(hir_def::HasModule::krate(&it, db), ty.skip_binder());
4502 }
4503 };
4504 Type::new(def, ty.instantiate_identity().skip_norm_wip())
4505 }
4506
4507 pub fn instantiate_with_errors(&self) -> Self {
4509 let interner = DbInterner::conjure();
4510 let krate = self.krate(interner.db());
4511 let args = match self.owner {
4512 TypeOwnerId::GenericDefId(def) => GenericArgs::error_for_item(interner, def.into()),
4513 TypeOwnerId::BuiltinDeriveImplId(def) => {
4514 GenericArgs::error_for_item(interner, def.into())
4515 }
4516 TypeOwnerId::AnonConstId(def) => GenericArgs::error_for_item(interner, def.into()),
4517 TypeOwnerId::NoParams(_) => GenericArgs::empty(interner),
4518 };
4519 Type::no_params(krate, self.ty.instantiate(interner, args).skip_norm_wip())
4520 }
4521
4522 pub fn instantiate(&self, args: impl IntoIterator<Item: Borrow<Type<'db>>>) -> Type<'db> {
4524 let interner = DbInterner::conjure();
4525 let (args, owner) = match self.owner {
4526 TypeOwnerId::GenericDefId(def) => generic_args_from_tys(interner, def.into(), args),
4527 TypeOwnerId::BuiltinDeriveImplId(def) => {
4528 generic_args_from_tys(interner, def.into(), args)
4529 }
4530 TypeOwnerId::AnonConstId(def) => generic_args_from_tys(interner, def.into(), args),
4531 TypeOwnerId::NoParams(krate) => {
4532 (GenericArgs::empty(interner), TypeOwnerId::NoParams(krate))
4533 }
4534 };
4535 Type { owner, ty: EarlyBinder::bind(self.ty.instantiate(interner, args).skip_norm_wip()) }
4536 }
4537
4538 fn instantiate_many_with_infer(
4540 tys: impl IntoIterator<Item: Borrow<Type<'db>>>,
4541 infcx: &InferCtxt<'db>,
4542 ) -> impl Iterator<Item = Ty<'db>> {
4543 let mut var_for_param = FxHashMap::default();
4544 tys.into_iter().map(move |ty| {
4545 let ty = ty.borrow();
4546 let owner = match ty.owner {
4547 TypeOwnerId::GenericDefId(def) => def.into(),
4548 TypeOwnerId::BuiltinDeriveImplId(def) => def.into(),
4549 TypeOwnerId::AnonConstId(def) => def.into(),
4550 TypeOwnerId::NoParams(_) => return ty.ty.skip_binder(),
4551 };
4552 let args = GenericArgs::for_item(infcx.interner, owner, |_, param, _, _| {
4553 *var_for_param
4554 .entry(param)
4555 .or_insert_with(|| infcx.var_for_def(param, hir_ty::Span::Dummy))
4556 });
4557
4558 ty.ty.instantiate(infcx.interner, args).skip_norm_wip()
4559 })
4560 }
4561
4562 pub fn try_rebase_into(
4567 &self,
4568 db: &'db dyn HirDatabase,
4569 rebase_into: &Type<'db>,
4570 ) -> Option<Self> {
4571 if self.owner.can_rebase_into(db, rebase_into.owner, self.ty) {
4572 Some(Type { owner: rebase_into.owner, ty: self.ty })
4573 } else {
4574 None
4575 }
4576 }
4577
4578 pub fn rebase_into_or_error(
4581 &self,
4582 db: &'db dyn HirDatabase,
4583 rebase_into: &Type<'db>,
4584 ) -> Type<'db> {
4585 self.try_rebase_into(db, rebase_into).unwrap_or_else(|| self.instantiate_with_errors())
4586 }
4587
4588 pub fn try_rebase_into_owner(
4589 &self,
4590 db: &'db dyn HirDatabase,
4591 new_owner: GenericDef,
4592 ) -> Option<Self> {
4593 let new_owner = new_owner.id()?.into();
4594 if self.owner.can_rebase_into(db, new_owner, self.ty) {
4595 Some(Type { owner: new_owner, ty: self.ty })
4596 } else {
4597 None
4598 }
4599 }
4600
4601 pub fn rebase_into_owner_or_error(
4602 &self,
4603 db: &'db dyn HirDatabase,
4604 new_owner: GenericDef,
4605 ) -> Self {
4606 self.try_rebase_into_owner(db, new_owner).unwrap_or_else(|| self.instantiate_with_errors())
4607 }
4608
4609 pub fn unknown() -> Self {
4610 let interner = DbInterner::conjure();
4611 Type::no_params(
4612 Self::builtin_type_crate(interner.db()),
4613 Ty::new_error(interner, ErrorGuaranteed),
4614 )
4615 }
4616
4617 pub fn new_slice(db: &'db dyn HirDatabase, ty: Self) -> Self {
4618 let interner = DbInterner::new_no_crate(db);
4619 Type { owner: ty.owner, ty: ty.ty.map_bound(|ty| Ty::new_slice(interner, ty)) }
4620 }
4621
4622 pub fn new_tuple(
4623 db: &'db dyn HirDatabase,
4624 tys: impl IntoIterator<Item: Borrow<Type<'db>>>,
4625 ) -> Self {
4626 let interner = DbInterner::new_no_crate(db);
4627 let mut owner = None::<TypeOwnerId<'db>>;
4628 let ty = EarlyBinder::bind(Ty::new_tup_from_iter(
4629 interner,
4630 tys.into_iter().map(|ty| {
4631 let ty = ty.borrow();
4632
4633 match &mut owner {
4634 Some(owner) => *owner = owner.must_unify(ty.owner),
4635 None => owner = Some(ty.owner),
4636 }
4637
4638 ty.ty.skip_binder()
4639 }),
4640 ));
4641 let owner =
4642 owner.unwrap_or_else(|| TypeOwnerId::NoParams(Self::builtin_type_crate(interner.db())));
4643 Type { owner, ty }
4644 }
4645
4646 pub fn new_unit() -> Self {
4647 let interner = DbInterner::conjure();
4648 Type::no_params(Self::builtin_type_crate(interner.db()), Ty::new_unit(interner))
4649 }
4650
4651 pub fn is_unit(&self) -> bool {
4652 self.ty.skip_binder().is_unit()
4653 }
4654
4655 pub fn is_bool(&self) -> bool {
4656 matches!(self.ty.skip_binder().kind(), TyKind::Bool)
4657 }
4658
4659 pub fn is_str(&self) -> bool {
4660 matches!(self.ty.skip_binder().kind(), TyKind::Str)
4661 }
4662
4663 pub fn is_never(&self) -> bool {
4664 matches!(self.ty.skip_binder().kind(), TyKind::Never)
4665 }
4666
4667 pub fn is_mutable_reference(&self) -> bool {
4668 matches!(
4669 self.ty.skip_binder().kind(),
4670 TyKind::Ref(.., hir_ty::next_solver::Mutability::Mut)
4671 )
4672 }
4673
4674 pub fn is_reference(&self) -> bool {
4675 matches!(self.ty.skip_binder().kind(), TyKind::Ref(..))
4676 }
4677
4678 pub fn contains_reference(&self, db: &'db dyn HirDatabase) -> bool {
4679 let interner = DbInterner::new_no_crate(db);
4680 return self
4681 .ty
4682 .instantiate_identity()
4683 .skip_norm_wip()
4684 .visit_with(&mut Visitor { interner })
4685 .is_break();
4686
4687 fn is_phantom_data(db: &dyn HirDatabase, adt_id: AdtId) -> bool {
4688 match adt_id {
4689 AdtId::StructId(s) => {
4690 let flags = StructSignature::of(db, s).flags;
4691 flags.contains(StructFlags::IS_PHANTOM_DATA)
4692 }
4693 AdtId::UnionId(_) | AdtId::EnumId(_) => false,
4694 }
4695 }
4696
4697 struct Visitor<'db> {
4698 interner: DbInterner<'db>,
4699 }
4700
4701 impl<'db> TypeVisitor<DbInterner<'db>> for Visitor<'db> {
4702 type Result = ControlFlow<()>;
4703
4704 fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
4705 match ty.kind() {
4706 TyKind::Ref(..) => ControlFlow::Break(()),
4708
4709 TyKind::Adt(adt_def, args)
4711 if !is_phantom_data(self.interner.db(), adt_def.def_id()) =>
4712 {
4713 let _variant_id_to_fields = |id: VariantId| {
4714 let variant_data = &id.fields(self.interner.db());
4715 if variant_data.fields().is_empty() {
4716 vec![]
4717 } else {
4718 let field_types = self.interner.db().field_types(id);
4719 variant_data
4720 .fields()
4721 .iter()
4722 .map(|(idx, _)| {
4723 field_types[idx]
4724 .ty()
4725 .instantiate(self.interner, args)
4726 .skip_norm_wip()
4727 })
4728 .filter(|it| !it.references_non_lt_error())
4729 .collect()
4730 }
4731 };
4732 let variant_id_to_fields = |_: VariantId| vec![];
4733
4734 let variants: Vec<Vec<Ty<'db>>> = match adt_def.def_id() {
4735 AdtId::StructId(id) => {
4736 vec![variant_id_to_fields(id.into())]
4737 }
4738 AdtId::EnumId(id) => id
4739 .enum_variants(self.interner.db())
4740 .variants
4741 .values()
4742 .map(|&(variant_id, _)| variant_id_to_fields(variant_id.into()))
4743 .collect(),
4744 AdtId::UnionId(id) => {
4745 vec![variant_id_to_fields(id.into())]
4746 }
4747 };
4748
4749 variants
4750 .into_iter()
4751 .flat_map(|variant| variant.into_iter())
4752 .try_for_each(|ty| ty.visit_with(self))?;
4753 args.visit_with(self)
4754 }
4755 _ => ty.super_visit_with(self),
4757 }
4758 }
4759 }
4760 }
4761
4762 pub fn as_reference(&self) -> Option<(Type<'db>, Mutability)> {
4763 let TyKind::Ref(_lt, ty, m) = self.ty.skip_binder().kind() else { return None };
4764 let m = Mutability::from_mutable(matches!(m, hir_ty::next_solver::Mutability::Mut));
4765 Some((self.derived(ty), m))
4766 }
4767
4768 pub fn as_reference_inner(&self) -> Option<Type<'db>> {
4769 self.as_reference().map(|(inner, _)| inner)
4770 }
4771
4772 pub fn add_reference(&self, db: &'db dyn HirDatabase, mutability: Mutability) -> Self {
4773 let interner = DbInterner::new_no_crate(db);
4774 let ty_mutability = match mutability {
4775 Mutability::Shared => hir_ty::next_solver::Mutability::Not,
4776 Mutability::Mut => hir_ty::next_solver::Mutability::Mut,
4777 };
4778 self.derived(Ty::new_ref(
4779 interner,
4780 Region::error(interner),
4781 self.ty.skip_binder(),
4782 ty_mutability,
4783 ))
4784 }
4785
4786 pub fn is_slice(&self) -> bool {
4787 matches!(self.ty.skip_binder().kind(), TyKind::Slice(..))
4788 }
4789
4790 pub fn is_usize(&self) -> bool {
4791 matches!(self.ty.skip_binder().kind(), TyKind::Uint(rustc_type_ir::UintTy::Usize))
4792 }
4793
4794 pub fn is_float(&self) -> bool {
4795 matches!(self.ty.skip_binder().kind(), TyKind::Float(_))
4796 }
4797
4798 pub fn is_char(&self) -> bool {
4799 matches!(self.ty.skip_binder().kind(), TyKind::Char)
4800 }
4801
4802 pub fn is_int_or_uint(&self) -> bool {
4803 matches!(self.ty.skip_binder().kind(), TyKind::Int(_) | TyKind::Uint(_))
4804 }
4805
4806 pub fn is_scalar(&self) -> bool {
4807 matches!(
4808 self.ty.skip_binder().kind(),
4809 TyKind::Bool | TyKind::Char | TyKind::Int(_) | TyKind::Uint(_) | TyKind::Float(_)
4810 )
4811 }
4812
4813 pub fn is_tuple(&self) -> bool {
4814 matches!(self.ty.skip_binder().kind(), TyKind::Tuple(..))
4815 }
4816
4817 pub fn as_slice(&self) -> Option<Type<'db>> {
4818 match self.ty.skip_binder().kind() {
4819 TyKind::Slice(ty) => Some(self.derived(ty)),
4820 _ => None,
4821 }
4822 }
4823
4824 pub fn strip_references(&self) -> Self {
4825 self.derived(self.ty.skip_binder().strip_references())
4826 }
4827
4828 pub fn strip_reference(&self) -> Self {
4830 self.derived(self.ty.skip_binder().strip_reference())
4831 }
4832
4833 pub fn is_unknown(&self) -> bool {
4834 self.ty.skip_binder().is_ty_error()
4835 }
4836
4837 fn krate(&self, db: &'db dyn HirDatabase) -> base_db::Crate {
4838 match self.owner {
4839 TypeOwnerId::GenericDefId(def) => hir_def::HasModule::krate(&def, db),
4840 TypeOwnerId::BuiltinDeriveImplId(def) => {
4841 hir_def::HasModule::krate(&def.loc(db).adt, db)
4842 }
4843 TypeOwnerId::AnonConstId(def) => hir_def::HasModule::krate(&def, db),
4844 TypeOwnerId::NoParams(krate) => krate,
4845 }
4846 }
4847
4848 fn param_env(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> {
4849 let interner = DbInterner::new_no_crate(db);
4850 let krate = self.krate(db);
4851 match self.owner {
4852 TypeOwnerId::GenericDefId(def) => {
4853 ParamEnvAndCrate { param_env: db.trait_environment(def), krate }
4854 }
4855 TypeOwnerId::BuiltinDeriveImplId(def) => ParamEnvAndCrate {
4856 param_env: hir_ty::builtin_derive::param_env(interner, def),
4857 krate,
4858 },
4859 TypeOwnerId::AnonConstId(def) => ParamEnvAndCrate {
4860 param_env: db.trait_environment(def.loc(db).owner.generic_def(db)),
4861 krate,
4862 },
4863 TypeOwnerId::NoParams(_) => {
4864 ParamEnvAndCrate { param_env: ParamEnv::empty(interner), krate }
4865 }
4866 }
4867 }
4868
4869 pub fn into_future_output(&self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
4873 let env = self.param_env(db);
4874 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
4875 let (trait_, output_assoc_type) = lang_items
4876 .IntoFuture
4877 .zip(lang_items.IntoFutureOutput)
4878 .or(lang_items.Future.zip(lang_items.FutureOutput))?;
4879
4880 if !traits::implements_trait_unique(
4881 self.ty.instantiate_identity().skip_norm_wip(),
4882 db,
4883 env,
4884 trait_,
4885 ) {
4886 return None;
4887 }
4888
4889 self.normalize_trait_assoc_type(db, &[], output_assoc_type.into())
4890 }
4891
4892 pub fn future_output(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
4894 let krate = self.krate(db);
4895 let lang_items = hir_def::lang_item::lang_items(db, krate);
4896 let future_output = lang_items.FutureOutput?;
4897 self.normalize_trait_assoc_type(db, &[], future_output.into())
4898 }
4899
4900 pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
4902 let krate = self.krate(db);
4903 let lang_items = hir_def::lang_item::lang_items(db, krate);
4904 let iterator_item = lang_items.IteratorItem?;
4905 self.normalize_trait_assoc_type(db, &[], iterator_item.into())
4906 }
4907
4908 pub fn impls_iterator(self, db: &'db dyn HirDatabase) -> bool {
4909 let env = self.param_env(db);
4910 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
4911 let Some(iterator_trait) = lang_items.Iterator else {
4912 return false;
4913 };
4914 traits::implements_trait_unique(
4915 self.ty.instantiate_identity().skip_norm_wip(),
4916 db,
4917 env,
4918 iterator_trait,
4919 )
4920 }
4921
4922 pub fn into_iterator_iter(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
4924 let env = self.param_env(db);
4925 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
4926 let trait_ = lang_items.IntoIterator?;
4927
4928 if !traits::implements_trait_unique(
4929 self.ty.instantiate_identity().skip_norm_wip(),
4930 db,
4931 env,
4932 trait_,
4933 ) {
4934 return None;
4935 }
4936
4937 let into_iter_assoc_type = lang_items.IntoIterIntoIterType?;
4938 self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into())
4939 }
4940
4941 pub fn impls_fnonce(&self, db: &'db dyn HirDatabase) -> bool {
4946 let env = self.param_env(db);
4947 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
4948 let fnonce_trait = match lang_items.FnOnce {
4949 Some(it) => it,
4950 None => return false,
4951 };
4952
4953 traits::implements_trait_unique(
4954 self.ty.instantiate_identity().skip_norm_wip(),
4955 db,
4956 env,
4957 fnonce_trait,
4958 )
4959 }
4960
4961 pub fn impls_trait(&self, db: &'db dyn HirDatabase, trait_: Trait, args: &[Type<'db>]) -> bool {
4963 let env = self.param_env(db);
4964 let interner = DbInterner::new_no_crate(db);
4965 let (args, _owner) =
4966 generic_args_from_tys(interner, trait_.id.into(), iter::once(self).chain(args));
4967 traits::implements_trait_unique_with_args(db, env, trait_.id, args)
4968 }
4969
4970 pub fn has_any_impl(
4984 &self,
4985 db: &'db dyn HirDatabase,
4986 trait_: Trait,
4987 args: &[Type<'db>],
4988 ) -> bool {
4989 let interner = DbInterner::new_no_crate(db);
4990 let env = ParamEnvAndCrate { param_env: ParamEnv::empty(interner), krate: self.krate(db) };
4991 traits::implements_trait_unique_with_infcx(db, env, trait_.id, &mut |infcx| {
4992 let mut args = Self::instantiate_many_with_infer(iter::once(self).chain(args), infcx);
4993 GenericArgs::for_item(infcx.interner, trait_.id.into(), |_, param, _, _| {
4994 if let GenericParamId::TypeParamId(_) = param
4995 && let Some(arg) = args.next()
4996 {
4997 arg.into()
4998 } else {
4999 infcx.var_for_def(param, hir_ty::Span::Dummy)
5000 }
5001 })
5002 })
5003 }
5004
5005 pub fn normalize_trait_assoc_type(
5006 &self,
5007 db: &'db dyn HirDatabase,
5008 args: &[Type<'db>],
5009 alias: TypeAlias,
5010 ) -> Option<Type<'db>> {
5011 let env = self.param_env(db);
5012 let interner = DbInterner::new_with(db, env.krate);
5013 let (args, owner) =
5014 generic_args_from_tys(interner, alias.id.into(), iter::once(self).chain(args));
5015 let projection = Ty::new_alias(
5017 interner,
5018 AliasTy::new_from_args(
5019 interner,
5020 AliasTyKind::Projection { def_id: alias.id.into() },
5021 args,
5022 ),
5023 );
5024
5025 let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
5026 let ty = structurally_normalize_ty(&infcx, projection, env.param_env);
5027 if ty.is_ty_error() { None } else { Some(Type { owner, ty: EarlyBinder::bind(ty) }) }
5028 }
5029
5030 pub fn is_copy(&self, db: &'db dyn HirDatabase) -> bool {
5031 let env = self.param_env(db);
5032 let lang_items = hir_def::lang_item::lang_items(db, env.krate);
5033 let Some(copy_trait) = lang_items.Copy else {
5034 return false;
5035 };
5036 self.impls_trait(db, copy_trait.into(), &[])
5037 }
5038
5039 pub fn as_callable(&self, db: &'db dyn HirDatabase) -> Option<Callable<'db>> {
5040 let interner = DbInterner::new_no_crate(db);
5041 let callee = match self.ty.skip_binder().kind() {
5042 TyKind::Closure(id, subst) => Callee::Closure(id.0, subst),
5043 TyKind::CoroutineClosure(id, subst) => Callee::CoroutineClosure(id.0, subst),
5044 TyKind::FnPtr(..) => Callee::FnPtr,
5045 TyKind::FnDef(id, _) => Callee::Def(id.0),
5046 TyKind::Ref(_, inner_ty, _) => return self.derived(inner_ty).as_callable(db),
5048 _ => {
5049 let env = self.param_env(db);
5050 let (fn_trait, sig) =
5051 hir_ty::callable_sig_from_fn_trait(self.ty.skip_binder(), env, db)?;
5052 return Some(Callable {
5053 ty: self.clone(),
5054 sig,
5055 callee: Callee::FnImpl(fn_trait),
5056 is_bound_method: false,
5057 });
5058 }
5059 };
5060
5061 let sig = self.ty.skip_binder().callable_sig(interner)?;
5062 Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
5063 }
5064
5065 pub fn is_closure(&self) -> bool {
5066 matches!(self.ty.skip_binder().kind(), TyKind::Closure { .. })
5067 }
5068
5069 pub fn as_closure(&self) -> Option<Closure<'db>> {
5070 match self.ty.skip_binder().kind() {
5071 TyKind::Closure(id, subst) => {
5072 Some(Closure { id: AnyClosureId::ClosureId(id.0), subst, owner: self.owner })
5073 }
5074 TyKind::CoroutineClosure(id, subst) => Some(Closure {
5075 id: AnyClosureId::CoroutineClosureId(id.0),
5076 subst,
5077 owner: self.owner,
5078 }),
5079 _ => None,
5080 }
5081 }
5082
5083 pub fn as_coroutine(&self) -> Option<Coroutine<'db>> {
5085 match self.ty.skip_binder().kind() {
5086 TyKind::Coroutine(id, _) => Some(Coroutine { id: id.0 }),
5087 _ => None,
5088 }
5089 }
5090
5091 pub fn is_fn(&self) -> bool {
5092 matches!(self.ty.skip_binder().kind(), TyKind::FnDef(..) | TyKind::FnPtr { .. })
5093 }
5094
5095 pub fn is_array(&self) -> bool {
5096 matches!(self.ty.skip_binder().kind(), TyKind::Array(..))
5097 }
5098
5099 pub fn is_packed(&self, _db: &'db dyn HirDatabase) -> bool {
5100 match self.ty.skip_binder().kind() {
5101 TyKind::Adt(adt_def, ..) => adt_def.is_packed(),
5102 _ => false,
5103 }
5104 }
5105
5106 pub fn is_raw_ptr(&self) -> bool {
5107 matches!(self.ty.skip_binder().kind(), TyKind::RawPtr(..))
5108 }
5109
5110 pub fn is_mutable_raw_ptr(&self) -> bool {
5111 matches!(
5113 self.ty.skip_binder().kind(),
5114 TyKind::RawPtr(.., hir_ty::next_solver::Mutability::Mut)
5115 )
5116 }
5117
5118 pub fn as_raw_ptr(&self) -> Option<(Type<'db>, Mutability)> {
5119 let TyKind::RawPtr(ty, m) = self.ty.skip_binder().kind() else { return None };
5121 let m = Mutability::from_mutable(matches!(m, hir_ty::next_solver::Mutability::Mut));
5122 Some((self.derived(ty), m))
5123 }
5124
5125 pub fn remove_raw_ptr(&self) -> Option<Type<'db>> {
5126 if let TyKind::RawPtr(ty, _) = self.ty.skip_binder().kind() {
5127 Some(self.derived(ty))
5128 } else {
5129 None
5130 }
5131 }
5132
5133 pub fn contains_unknown(&self) -> bool {
5134 self.ty.skip_binder().references_non_lt_error()
5135 }
5136
5137 pub fn fields(&self, db: &'db dyn HirDatabase) -> Vec<(Field, Self)> {
5138 let interner = DbInterner::new_no_crate(db);
5139 let (variant_id, substs) = match self.ty.skip_binder().kind() {
5140 TyKind::Adt(adt_def, substs) => {
5141 let id = match adt_def.def_id() {
5142 AdtId::StructId(id) => id.into(),
5143 AdtId::UnionId(id) => id.into(),
5144 AdtId::EnumId(_) => return Vec::new(),
5145 };
5146 (id, substs)
5147 }
5148 _ => return Vec::new(),
5149 };
5150
5151 db.field_types(variant_id)
5152 .iter()
5153 .map(|(local_id, field)| {
5154 let def = Field { parent: variant_id.into(), id: local_id };
5155 let ty = field.ty().instantiate(interner, substs).skip_norm_wip();
5156 (def, self.derived(ty))
5157 })
5158 .collect()
5159 }
5160
5161 pub fn tuple_fields(&self, _db: &'db dyn HirDatabase) -> Vec<Self> {
5162 if let TyKind::Tuple(substs) = self.ty.skip_binder().kind() {
5163 substs.iter().map(|ty| self.derived(ty)).collect()
5164 } else {
5165 Vec::new()
5166 }
5167 }
5168
5169 pub fn as_array(&self, db: &'db dyn HirDatabase) -> Option<(Self, usize)> {
5170 if let TyKind::Array(ty, len) = self.ty.skip_binder().kind() {
5171 try_const_usize(db, len).map(|it| (self.derived(ty), it as usize))
5172 } else {
5173 None
5174 }
5175 }
5176
5177 pub fn fingerprint_for_trait_impl(
5179 &self,
5180 db: &'db dyn HirDatabase,
5181 ) -> Option<SimplifiedType<'db>> {
5182 fast_reject::simplify_type(
5183 DbInterner::new_no_crate(db),
5184 self.ty.skip_binder(),
5185 fast_reject::TreatParams::AsRigid,
5186 )
5187 }
5188
5189 pub fn autoderef(
5192 &self,
5193 db: &'db dyn HirDatabase,
5194 ) -> impl Iterator<Item = Type<'db>> + use<'_, 'db> {
5195 self.autoderef_(db).map(move |ty| self.derived(ty))
5196 }
5197
5198 fn autoderef_(&self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Ty<'db>> {
5199 let interner = DbInterner::new_no_crate(db);
5200 let env = self.param_env(db);
5201 let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty.skip_binder());
5203 autoderef(db, env, canonical)
5204 }
5205
5206 pub fn iterate_assoc_items<T>(
5209 &self,
5210 db: &'db dyn HirDatabase,
5211 mut callback: impl FnMut(AssocItem) -> Option<T>,
5212 ) -> Option<T> {
5213 let mut slot = None;
5214 self.iterate_assoc_items_dyn(db, &mut |assoc_item_id| {
5215 slot = callback(assoc_item_id.into());
5216 slot.is_some()
5217 });
5218 slot
5219 }
5220
5221 fn iterate_assoc_items_dyn(
5222 &self,
5223 db: &'db dyn HirDatabase,
5224 callback: &mut dyn FnMut(AssocItemId) -> bool,
5225 ) {
5226 let mut handle_impls = |impls: &[ImplId]| {
5227 for &impl_def in impls {
5228 for &(_, item) in impl_def.impl_items(db).items.iter() {
5229 if callback(item) {
5230 return;
5231 }
5232 }
5233 }
5234 };
5235 let krate = self.krate(db);
5236
5237 let interner = DbInterner::new_no_crate(db);
5238 let Some(simplified_type) = fast_reject::simplify_type(
5239 interner,
5240 self.ty.skip_binder(),
5241 fast_reject::TreatParams::AsRigid,
5242 ) else {
5243 return;
5244 };
5245
5246 method_resolution::with_incoherent_inherent_impls(
5247 db,
5248 krate,
5249 &simplified_type,
5250 &mut handle_impls,
5251 );
5252
5253 if let Some(module) = method_resolution::simplified_type_module(db, &simplified_type) {
5254 InherentImpls::for_each_crate_and_block(
5255 db,
5256 module.krate(db),
5257 module.block(db),
5258 &mut |impls| {
5259 handle_impls(impls.for_self_ty(&simplified_type));
5260 },
5261 );
5262 }
5263 }
5264
5265 pub fn type_arguments(&self) -> impl Iterator<Item = Type<'db>> + '_ {
5284 match self.ty.skip_binder().strip_references().kind() {
5285 TyKind::Adt(_, substs) => Either::Left(substs.types().map(move |ty| self.derived(ty))),
5286 TyKind::Tuple(substs) => {
5287 Either::Right(Either::Left(substs.iter().map(move |ty| self.derived(ty))))
5288 }
5289 _ => Either::Right(Either::Right(iter::empty())),
5290 }
5291 }
5292
5293 pub fn type_and_const_arguments<'a>(
5312 &'a self,
5313 db: &'a dyn HirDatabase,
5314 display_target: DisplayTarget,
5315 ) -> impl Iterator<Item = SmolStr> + 'a {
5316 self.ty
5317 .skip_binder()
5318 .strip_references()
5319 .as_adt()
5320 .into_iter()
5321 .flat_map(|(_, substs)| substs.iter())
5322 .filter_map(move |arg| match arg.kind() {
5323 rustc_type_ir::GenericArgKind::Type(ty) => {
5324 Some(format_smolstr!("{}", ty.display(db, display_target)))
5325 }
5326 rustc_type_ir::GenericArgKind::Const(const_) => {
5327 Some(format_smolstr!("{}", const_.display(db, display_target)))
5328 }
5329 rustc_type_ir::GenericArgKind::Lifetime(_) => None,
5330 })
5331 }
5332
5333 pub fn generic_parameters<'a>(
5335 &'a self,
5336 db: &'a dyn HirDatabase,
5337 display_target: DisplayTarget,
5338 ) -> impl Iterator<Item = SmolStr> + 'a {
5339 self.as_adt()
5341 .and_then(|a| {
5342 a.lifetime(db).map(|lt| lt.name.display_no_db(Edition::Edition2015).to_smolstr())
5344 })
5345 .into_iter()
5346 .chain(self.type_and_const_arguments(db, display_target))
5348 }
5349
5350 pub fn iterate_method_candidates_with_traits<T>(
5351 &self,
5352 db: &'db dyn HirDatabase,
5353 scope: &SemanticsScope<'_>,
5354 traits_in_scope: &FxHashSet<TraitId>,
5355 name: Option<&Name>,
5356 mut callback: impl FnMut(Function) -> Option<T>,
5357 ) -> Option<T> {
5358 let _p = tracing::info_span!("iterate_method_candidates_with_traits").entered();
5359 let mut slot = None;
5360 self.iterate_method_candidates_split_inherent(db, scope, traits_in_scope, name, |f| {
5361 match callback(f) {
5362 it @ Some(_) => {
5363 slot = it;
5364 ControlFlow::Break(())
5365 }
5366 None => ControlFlow::Continue(()),
5367 }
5368 });
5369 slot
5370 }
5371
5372 pub fn iterate_method_candidates<T>(
5373 &self,
5374 db: &'db dyn HirDatabase,
5375 scope: &SemanticsScope<'_>,
5376 name: Option<&Name>,
5377 callback: impl FnMut(Function) -> Option<T>,
5378 ) -> Option<T> {
5379 self.iterate_method_candidates_with_traits(
5380 db,
5381 scope,
5382 &scope.visible_traits().0,
5383 name,
5384 callback,
5385 )
5386 }
5387
5388 fn with_method_resolution<R>(
5389 &self,
5390 db: &'db dyn HirDatabase,
5391 resolver: &Resolver<'db>,
5392 traits_in_scope: &FxHashSet<TraitId>,
5393 f: impl FnOnce(&MethodResolutionContext<'_, 'db>) -> R,
5394 ) -> R {
5395 let module = resolver.module();
5396 let interner = DbInterner::new_with(db, module.krate(db));
5397 let typing_mode = if let Some(store_owner) = resolver.expression_store_owner() {
5402 TypingMode::analysis_in_body(interner, store_owner.into())
5403 } else {
5404 TypingMode::non_body_analysis()
5405 };
5406 let infcx = interner.infer_ctxt().build(typing_mode);
5407 let features = resolver.top_level_def_map().features();
5408 let environment = self.param_env(db);
5409 let ctx = MethodResolutionContext {
5410 infcx: &infcx,
5411 resolver,
5412 param_env: environment.param_env,
5413 traits_in_scope,
5414 edition: resolver.krate().data(db).edition,
5415 features,
5416 call_span: hir_ty::Span::Dummy,
5417 receiver_span: hir_ty::Span::Dummy,
5418 };
5419 f(&ctx)
5420 }
5421
5422 pub fn iterate_method_candidates_split_inherent(
5427 &self,
5428 db: &'db dyn HirDatabase,
5429 scope: &SemanticsScope<'_>,
5430 traits_in_scope: &FxHashSet<TraitId>,
5431 name: Option<&Name>,
5432 mut callback: impl MethodCandidateCallback,
5433 ) {
5434 let _p = tracing::info_span!(
5435 "iterate_method_candidates_split_inherent",
5436 traits_in_scope = traits_in_scope.len(),
5437 ?name,
5438 )
5439 .entered();
5440
5441 self.with_method_resolution(db, scope.resolver(), traits_in_scope, |ctx| {
5442 let canonical =
5444 hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty.skip_binder());
5445 let (self_ty, _) = ctx.infcx.instantiate_canonical(hir_ty::Span::Dummy, &canonical);
5446
5447 match name {
5448 Some(name) => {
5449 match ctx.probe_for_name(
5450 method_resolution::Mode::MethodCall,
5451 name.clone(),
5452 self_ty,
5453 ) {
5454 Ok(candidate)
5455 | Err(method_resolution::MethodError::PrivateMatch(candidate)) => {
5456 let method_resolution::CandidateId::FunctionId(id) = candidate.item
5457 else {
5458 unreachable!("`Mode::MethodCall` can only return functions");
5459 };
5460 let id = Function { id: AnyFunctionId::FunctionId(id) };
5461 match candidate.kind {
5462 method_resolution::PickKind::InherentImplPick(_)
5463 | method_resolution::PickKind::ObjectPick(..)
5464 | method_resolution::PickKind::WhereClausePick(..) => {
5465 _ = callback.on_inherent_method(id);
5467 }
5468 method_resolution::PickKind::TraitPick(..) => {
5469 _ = callback.on_trait_method(id);
5470 }
5471 }
5472 }
5473 Err(_) => {}
5474 };
5475 }
5476 None => {
5477 _ = ctx.probe_all(method_resolution::Mode::MethodCall, self_ty).try_for_each(
5478 |candidate| {
5479 let method_resolution::CandidateId::FunctionId(id) =
5480 candidate.candidate.item
5481 else {
5482 unreachable!("`Mode::MethodCall` can only return functions");
5483 };
5484 let id = Function { id: AnyFunctionId::FunctionId(id) };
5485 match candidate.candidate.kind {
5486 method_resolution::CandidateKind::InherentImplCandidate {
5487 ..
5488 }
5489 | method_resolution::CandidateKind::ObjectCandidate(..)
5490 | method_resolution::CandidateKind::WhereClauseCandidate(..) => {
5491 callback.on_inherent_method(id)
5493 }
5494 method_resolution::CandidateKind::TraitCandidate(..) => {
5495 callback.on_trait_method(id)
5496 }
5497 }
5498 },
5499 );
5500 }
5501 }
5502 })
5503 }
5504
5505 #[tracing::instrument(skip_all, fields(name = ?name))]
5506 pub fn iterate_path_candidates<T>(
5507 &self,
5508 db: &'db dyn HirDatabase,
5509 scope: &SemanticsScope<'_>,
5510 traits_in_scope: &FxHashSet<TraitId>,
5511 name: Option<&Name>,
5512 mut callback: impl FnMut(AssocItem) -> Option<T>,
5513 ) -> Option<T> {
5514 let _p = tracing::info_span!("iterate_path_candidates").entered();
5515 let mut slot = None;
5516
5517 self.iterate_path_candidates_split_inherent(db, scope, traits_in_scope, name, |item| {
5518 match callback(item) {
5519 it @ Some(_) => {
5520 slot = it;
5521 ControlFlow::Break(())
5522 }
5523 None => ControlFlow::Continue(()),
5524 }
5525 });
5526 slot
5527 }
5528
5529 #[tracing::instrument(skip_all, fields(name = ?name))]
5535 pub fn iterate_path_candidates_split_inherent(
5536 &self,
5537 db: &'db dyn HirDatabase,
5538 scope: &SemanticsScope<'_>,
5539 traits_in_scope: &FxHashSet<TraitId>,
5540 name: Option<&Name>,
5541 mut callback: impl PathCandidateCallback,
5542 ) {
5543 let _p = tracing::info_span!(
5544 "iterate_path_candidates_split_inherent",
5545 traits_in_scope = traits_in_scope.len(),
5546 ?name,
5547 )
5548 .entered();
5549
5550 self.with_method_resolution(db, scope.resolver(), traits_in_scope, |ctx| {
5551 let canonical =
5553 hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty.skip_binder());
5554 let (self_ty, _) = ctx.infcx.instantiate_canonical(hir_ty::Span::Dummy, &canonical);
5555
5556 match name {
5557 Some(name) => {
5558 match ctx.probe_for_name(method_resolution::Mode::Path, name.clone(), self_ty) {
5559 Ok(candidate)
5560 | Err(method_resolution::MethodError::PrivateMatch(candidate)) => {
5561 let id = candidate.item.into();
5562 match candidate.kind {
5563 method_resolution::PickKind::InherentImplPick(_)
5564 | method_resolution::PickKind::ObjectPick(..)
5565 | method_resolution::PickKind::WhereClausePick(..) => {
5566 _ = callback.on_inherent_item(id);
5568 }
5569 method_resolution::PickKind::TraitPick(..) => {
5570 _ = callback.on_trait_item(id);
5571 }
5572 }
5573 }
5574 Err(_) => {}
5575 };
5576 }
5577 None => {
5578 _ = ctx.probe_all(method_resolution::Mode::Path, self_ty).try_for_each(
5579 |candidate| {
5580 let id = candidate.candidate.item.into();
5581 match candidate.candidate.kind {
5582 method_resolution::CandidateKind::InherentImplCandidate {
5583 ..
5584 }
5585 | method_resolution::CandidateKind::ObjectCandidate(..)
5586 | method_resolution::CandidateKind::WhereClauseCandidate(..) => {
5587 callback.on_inherent_item(id)
5589 }
5590 method_resolution::CandidateKind::TraitCandidate(..) => {
5591 callback.on_trait_item(id)
5592 }
5593 }
5594 },
5595 );
5596 }
5597 }
5598 })
5599 }
5600
5601 pub fn as_adt(&self) -> Option<Adt> {
5602 let (adt, _subst) = self.ty.skip_binder().as_adt()?;
5603 Some(adt.into())
5604 }
5605
5606 pub fn as_adt_with_args(&self) -> Option<(Adt, Vec<Option<Type<'db>>>)> {
5608 let (adt, args) = self.ty.skip_binder().as_adt()?;
5609 let args = args.iter().map(|arg| Some(self.derived(arg.ty()?))).collect();
5610 Some((adt.into(), args))
5611 }
5612
5613 pub fn as_builtin(&self) -> Option<BuiltinType> {
5614 self.ty.skip_binder().as_builtin().map(|inner| BuiltinType { inner })
5615 }
5616
5617 pub fn as_dyn_trait(&self) -> Option<Trait> {
5618 self.ty.skip_binder().dyn_trait().map(Into::into)
5619 }
5620
5621 pub fn applicable_inherent_traits(
5624 &self,
5625 db: &'db dyn HirDatabase,
5626 ) -> impl Iterator<Item = Trait> {
5627 let _p = tracing::info_span!("applicable_inherent_traits").entered();
5628 self.autoderef_(db)
5629 .filter_map(|ty| ty.dyn_trait())
5630 .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db, dyn_trait_id))
5631 .copied()
5632 .map(Trait::from)
5633 }
5634
5635 pub fn env_traits(&self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Trait> {
5636 let _p = tracing::info_span!("env_traits").entered();
5637 let env = self.param_env(db);
5638 self.autoderef_(db)
5639 .filter(|ty| matches!(ty.kind(), TyKind::Param(_)))
5640 .flat_map(move |ty| {
5641 env.param_env
5642 .clauses()
5643 .iter()
5644 .filter_map(move |pred| match pred.kind().skip_binder() {
5645 ClauseKind::Trait(tr) if tr.self_ty() == ty => Some(tr.def_id().0),
5646 _ => None,
5647 })
5648 .flat_map(|t| hir_ty::all_super_traits(db, t))
5649 .copied()
5650 })
5651 .map(Trait::from)
5652 }
5653
5654 pub fn as_impl_traits(&self, db: &'db dyn HirDatabase) -> Option<impl Iterator<Item = Trait>> {
5655 self.ty.skip_binder().impl_trait_bounds(db).map(|it| {
5656 it.into_iter().filter_map(|pred| match pred.kind().skip_binder() {
5657 ClauseKind::Trait(trait_ref) => Some(Trait::from(trait_ref.def_id().0)),
5658 _ => None,
5659 })
5660 })
5661 }
5662
5663 pub fn as_associated_type_parent_trait(&self, db: &'db dyn HirDatabase) -> Option<Trait> {
5664 let TyKind::Alias(AliasTy { kind: AliasTyKind::Projection { def_id }, .. }) =
5665 self.ty.skip_binder().kind()
5666 else {
5667 return None;
5668 };
5669 match def_id.0.loc(db).container {
5670 ItemContainerId::TraitId(id) => Some(Trait { id }),
5671 _ => None,
5672 }
5673 }
5674
5675 fn derived(&self, ty: Ty<'db>) -> Self {
5676 Type { owner: self.owner, ty: EarlyBinder::bind(ty) }
5677 }
5678
5679 pub fn walk(&self, db: &'db dyn HirDatabase, callback: impl FnMut(Type<'db>)) {
5682 struct Visitor<'db, F> {
5683 db: &'db dyn HirDatabase,
5684 owner: TypeOwnerId<'db>,
5685 callback: F,
5686 visited: FxHashSet<Ty<'db>>,
5687 }
5688 impl<'db, F> TypeVisitor<DbInterner<'db>> for Visitor<'db, F>
5689 where
5690 F: FnMut(Type<'db>),
5691 {
5692 type Result = ();
5693
5694 fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
5695 if !self.visited.insert(ty) {
5696 return;
5697 }
5698
5699 (self.callback)(Type { owner: self.owner, ty: EarlyBinder::bind(ty) });
5700
5701 if let Some(bounds) = ty.impl_trait_bounds(self.db) {
5702 bounds.visit_with(self);
5703 }
5704
5705 ty.super_visit_with(self);
5706 }
5707 }
5708
5709 let mut visitor =
5710 Visitor { db, owner: self.owner, callback, visited: FxHashSet::default() };
5711 self.ty.skip_binder().visit_with(&mut visitor);
5712 }
5713 pub fn could_unify_with(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool {
5718 self.owner.must_unify(other.owner);
5719 let env = self.param_env(db);
5720 let interner = DbInterner::new_no_crate(db);
5721 let tys = hir_ty::replace_errors_with_variables(
5722 interner,
5723 &(self.ty.skip_binder(), other.ty.skip_binder()),
5724 );
5725 hir_ty::could_unify(db, env, &tys)
5726 }
5727
5728 pub fn could_unify_with_deeply(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool {
5733 self.owner.must_unify(other.owner);
5734 let env = self.param_env(db);
5735 let interner = DbInterner::new_no_crate(db);
5736 let tys = hir_ty::replace_errors_with_variables(
5737 interner,
5738 &(self.ty.skip_binder(), other.ty.skip_binder()),
5739 );
5740 hir_ty::could_unify_deeply(db, env, &tys)
5741 }
5742
5743 pub fn could_coerce_to(&self, db: &'db dyn HirDatabase, to: &Type<'db>) -> bool {
5744 self.owner.must_unify(to.owner);
5745 let env = self.param_env(db);
5746 let interner = DbInterner::new_no_crate(db);
5747 let tys = hir_ty::replace_errors_with_variables(
5748 interner,
5749 &(self.ty.skip_binder(), to.ty.skip_binder()),
5750 );
5751 hir_ty::could_coerce(db, env, &tys)
5752 }
5753
5754 pub fn as_type_param(&self, _db: &'db dyn HirDatabase) -> Option<TypeParam> {
5755 match self.ty.skip_binder().kind() {
5756 TyKind::Param(param) => Some(TypeParam { id: param.id }),
5757 _ => None,
5758 }
5759 }
5760
5761 pub fn generic_params(&self, db: &'db dyn HirDatabase) -> FxHashSet<GenericParam> {
5763 hir_ty::collect_params(&self.ty.skip_binder())
5764 .into_iter()
5765 .map(|id| TypeOrConstParam { id }.split(db).either_into())
5766 .collect()
5767 }
5768
5769 pub fn layout(&self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> {
5770 let env = self.param_env(db);
5771 db.layout_of_ty(self.ty.skip_binder().store(), env.store())
5772 .map(|layout| Layout(layout, db.target_data_layout(env.krate).unwrap()))
5773 }
5774
5775 pub fn drop_glue(&self, db: &'db dyn HirDatabase) -> DropGlue {
5776 let env = self.param_env(db);
5777 let interner = DbInterner::new_with(db, env.krate);
5778 let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
5779 hir_ty::drop::has_drop_glue(&infcx, self.ty.skip_binder(), env.param_env)
5780 }
5781}
5782
5783#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
5784pub struct InlineAsmOperand {
5785 owner: ExpressionStoreOwnerId,
5786 expr: ExprId,
5787 index: usize,
5788}
5789
5790impl InlineAsmOperand {
5791 pub fn parent(self, _db: &dyn HirDatabase) -> ExpressionStoreOwner {
5792 self.owner.into()
5793 }
5794
5795 pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
5796 let body = ExpressionStore::of(db, self.owner);
5797 match &body[self.expr] {
5798 hir_def::hir::Expr::InlineAsm(e) => e.operands.get(self.index)?.0.clone(),
5799 _ => None,
5800 }
5801 }
5802}
5803
5804#[derive(Debug)]
5806pub struct Callable<'db> {
5807 ty: Type<'db>,
5808 sig: PolyFnSig<'db>,
5809 callee: Callee<'db>,
5810 is_bound_method: bool,
5812}
5813
5814#[derive(Clone, PartialEq, Eq, Hash, Debug)]
5815enum Callee<'db> {
5816 Def(CallableDefId),
5817 Closure(InternedClosureId<'db>, GenericArgs<'db>),
5818 CoroutineClosure(InternedCoroutineClosureId<'db>, GenericArgs<'db>),
5819 FnPtr,
5820 FnImpl(traits::FnTrait),
5821 BuiltinDeriveImplMethod { method: BuiltinDeriveImplMethod, impl_: BuiltinDeriveImplId },
5822}
5823
5824pub enum CallableKind<'db> {
5825 Function(Function),
5826 TupleStruct(Struct),
5827 TupleEnumVariant(EnumVariant),
5828 Closure(Closure<'db>),
5829 FnPtr,
5830 FnImpl(FnTrait),
5831}
5832
5833impl<'db> Callable<'db> {
5834 fn erased_sig(&self) -> FnSig<'db> {
5835 DbInterner::conjure().instantiate_bound_regions_with_erased(self.sig)
5836 }
5837
5838 pub fn kind(&self) -> CallableKind<'db> {
5839 match self.callee {
5840 Callee::Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
5841 Callee::BuiltinDeriveImplMethod { method, impl_ } => CallableKind::Function(Function {
5842 id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ },
5843 }),
5844 Callee::Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
5845 Callee::Def(CallableDefId::EnumVariantId(it)) => {
5846 CallableKind::TupleEnumVariant(it.into())
5847 }
5848 Callee::Closure(id, subst) => CallableKind::Closure(Closure {
5849 id: AnyClosureId::ClosureId(id),
5850 subst,
5851 owner: self.ty.owner,
5852 }),
5853 Callee::CoroutineClosure(id, subst) => CallableKind::Closure(Closure {
5854 id: AnyClosureId::CoroutineClosureId(id),
5855 subst,
5856 owner: self.ty.owner,
5857 }),
5858 Callee::FnPtr => CallableKind::FnPtr,
5859 Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_.into()),
5860 }
5861 }
5862
5863 fn as_function(&self) -> Option<Function> {
5864 match self.callee {
5865 Callee::Def(CallableDefId::FunctionId(it)) => Some(it.into()),
5866 Callee::BuiltinDeriveImplMethod { method, impl_ } => {
5867 Some(Function { id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } })
5868 }
5869 _ => None,
5870 }
5871 }
5872
5873 pub fn receiver_param(&self, db: &'db dyn HirDatabase) -> Option<(SelfParam, Type<'db>)> {
5874 if !self.is_bound_method {
5875 return None;
5876 }
5877 let func = self.as_function()?;
5878 Some((func.self_param(db)?, self.ty.derived(self.erased_sig().inputs()[0])))
5879 }
5880 pub fn n_params(&self) -> usize {
5881 self.sig.skip_binder().inputs_and_output.inputs().len()
5882 - if self.is_bound_method { 1 } else { 0 }
5883 }
5884 pub fn params(&self) -> Vec<Param<'db>> {
5885 self.erased_sig()
5886 .inputs()
5887 .iter()
5888 .enumerate()
5889 .skip(if self.is_bound_method { 1 } else { 0 })
5890 .map(|(idx, ty)| (idx, self.ty.derived(*ty)))
5891 .map(|(idx, ty)| Param { func: self.callee.clone(), idx, ty })
5892 .collect()
5893 }
5894 pub fn return_type(&self) -> Type<'db> {
5895 self.ty.derived(self.erased_sig().output())
5896 }
5897 pub fn sig(&self) -> impl Eq {
5898 &self.sig
5899 }
5900
5901 pub fn ty(&self) -> &Type<'db> {
5902 &self.ty
5903 }
5904}
5905
5906#[derive(Clone, Debug, Eq, PartialEq)]
5907pub struct Layout<'db>(Arc<TyLayout>, &'db TargetDataLayout);
5908
5909impl<'db> Layout<'db> {
5910 pub fn size(&self) -> u64 {
5911 self.0.size.bytes()
5912 }
5913
5914 pub fn align(&self) -> u64 {
5915 self.0.align.bytes()
5916 }
5917
5918 pub fn niches(&self) -> Option<u128> {
5919 Some(self.0.largest_niche?.available(self.1))
5920 }
5921
5922 pub fn field_offset(&self, field: Field) -> Option<u64> {
5923 match self.0.fields {
5924 layout::FieldsShape::Primitive => None,
5925 layout::FieldsShape::Union(_) => Some(0),
5926 layout::FieldsShape::Array { stride, count } => {
5927 let i = u64::try_from(field.index()).ok()?;
5928 (i < count).then_some((stride * i).bytes())
5929 }
5930 layout::FieldsShape::Arbitrary { ref offsets, .. } => {
5931 Some(offsets.get(RustcFieldIdx(field.id))?.bytes())
5932 }
5933 }
5934 }
5935
5936 pub fn tuple_field_offset(&self, field: usize) -> Option<u64> {
5937 match self.0.fields {
5938 layout::FieldsShape::Primitive => None,
5939 layout::FieldsShape::Union(_) => Some(0),
5940 layout::FieldsShape::Array { stride, count } => {
5941 let i = u64::try_from(field).ok()?;
5942 (i < count).then_some((stride * i).bytes())
5943 }
5944 layout::FieldsShape::Arbitrary { ref offsets, .. } => {
5945 Some(offsets.get(RustcFieldIdx::new(field))?.bytes())
5946 }
5947 }
5948 }
5949
5950 pub fn tail_padding(&self, field_size: &mut impl FnMut(usize) -> Option<u64>) -> Option<u64> {
5951 match self.0.fields {
5952 layout::FieldsShape::Primitive => None,
5953 layout::FieldsShape::Union(_) => None,
5954 layout::FieldsShape::Array { stride, count } => count.checked_sub(1).and_then(|tail| {
5955 let tail_field_size = field_size(tail as usize)?;
5956 let offset = stride.bytes() * tail;
5957 self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size)
5958 }),
5959 layout::FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => {
5960 let tail = in_memory_order[in_memory_order.len().checked_sub(1)? as u32];
5961 let tail_field_size = field_size(tail.0.into_raw().into_u32() as usize)?;
5962 let offset = offsets.get(tail)?.bytes();
5963 self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size)
5964 }
5965 }
5966 }
5967
5968 pub fn largest_padding(
5969 &self,
5970 field_size: &mut impl FnMut(usize) -> Option<u64>,
5971 ) -> Option<u64> {
5972 match self.0.fields {
5973 layout::FieldsShape::Primitive => None,
5974 layout::FieldsShape::Union(_) => None,
5975 layout::FieldsShape::Array { stride: _, count: 0 } => None,
5976 layout::FieldsShape::Array { stride, .. } => {
5977 let size = field_size(0)?;
5978 stride.bytes().checked_sub(size)
5979 }
5980 layout::FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => {
5981 let mut reverse_index = vec![None; in_memory_order.len()];
5982 for (mem, src) in in_memory_order.iter().enumerate() {
5983 reverse_index[mem] =
5984 Some((src.0.into_raw().into_u32() as usize, offsets[*src].bytes()));
5985 }
5986 if reverse_index.iter().any(|it| it.is_none()) {
5987 stdx::never!();
5988 return None;
5989 }
5990 reverse_index
5991 .into_iter()
5992 .flatten()
5993 .chain(iter::once((0, self.0.size.bytes())))
5994 .array_windows()
5995 .filter_map(|[(i, start), (_, end)]| {
5996 let size = field_size(i)?;
5997 end.checked_sub(start)?.checked_sub(size)
5998 })
5999 .max()
6000 }
6001 }
6002 }
6003
6004 pub fn enum_tag_size(&self) -> Option<usize> {
6005 let tag_size =
6006 if let layout::Variants::Multiple { tag, tag_encoding, .. } = &self.0.variants {
6007 match tag_encoding {
6008 TagEncoding::Direct => tag.size(self.1).bytes_usize(),
6009 TagEncoding::Niche { .. } => 0,
6010 }
6011 } else {
6012 return None;
6013 };
6014 Some(tag_size)
6015 }
6016}
6017
6018#[derive(Copy, Clone, Debug, Eq, PartialEq)]
6019pub enum BindingMode {
6020 Move,
6021 Ref(Mutability),
6022}
6023
6024#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
6026pub enum ScopeDef<'db> {
6027 ModuleDef(ModuleDef),
6028 GenericParam(GenericParam),
6029 ImplSelfType(Impl),
6030 AdtSelfType(Adt),
6031 Local(Local<'db>),
6032 Label(Label),
6033 Unknown,
6034}
6035
6036impl ScopeDef<'_> {
6037 pub fn all_items(def: PerNs) -> ArrayVec<Self, 3> {
6038 let mut items = ArrayVec::new();
6039
6040 match (def.take_types(), def.take_values()) {
6041 (Some(m1), None) => items.push(ScopeDef::ModuleDef(m1.into())),
6042 (None, Some(m2)) => items.push(ScopeDef::ModuleDef(m2.into())),
6043 (Some(m1), Some(m2)) => {
6044 if m1 != m2 {
6048 items.push(ScopeDef::ModuleDef(m1.into()));
6049 items.push(ScopeDef::ModuleDef(m2.into()));
6050 } else {
6051 items.push(ScopeDef::ModuleDef(m1.into()));
6052 }
6053 }
6054 (None, None) => {}
6055 };
6056
6057 if let Some(macro_def_id) = def.take_macros() {
6058 items.push(ScopeDef::ModuleDef(ModuleDef::Macro(macro_def_id.into())));
6059 }
6060
6061 if items.is_empty() {
6062 items.push(ScopeDef::Unknown);
6063 }
6064
6065 items
6066 }
6067
6068 pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
6069 match self {
6070 ScopeDef::ModuleDef(it) => it.attrs(db),
6071 ScopeDef::GenericParam(it) => Some(it.attrs(db)),
6072 ScopeDef::ImplSelfType(_)
6073 | ScopeDef::AdtSelfType(_)
6074 | ScopeDef::Local(_)
6075 | ScopeDef::Label(_)
6076 | ScopeDef::Unknown => None,
6077 }
6078 }
6079
6080 pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
6081 match self {
6082 ScopeDef::ModuleDef(it) => it.module(db).map(|m| m.krate(db)),
6083 ScopeDef::GenericParam(it) => Some(it.module(db).krate(db)),
6084 ScopeDef::ImplSelfType(_) => None,
6085 ScopeDef::AdtSelfType(it) => Some(it.module(db).krate(db)),
6086 ScopeDef::Local(it) => Some(it.module(db).krate(db)),
6087 ScopeDef::Label(it) => Some(it.module(db).krate(db)),
6088 ScopeDef::Unknown => None,
6089 }
6090 }
6091}
6092
6093impl_from!(
6094 impl<'db>
6095 ItemInNs { Types => ModuleDef, Values => ModuleDef, Macros => ModuleDef }
6096 for ScopeDef<'db>
6097);
6098
6099#[derive(Clone, Debug, PartialEq, Eq)]
6100pub struct Adjustment<'db> {
6101 pub source: Type<'db>,
6102 pub target: Type<'db>,
6103 pub kind: Adjust,
6104}
6105
6106#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6107pub enum Adjust {
6108 NeverToAny,
6110 Deref(Option<OverloadedDeref>),
6112 Borrow(AutoBorrow),
6114 Pointer(PointerCast),
6115}
6116
6117#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6118pub enum AutoBorrow {
6119 Ref(Mutability),
6121 RawPtr(Mutability),
6123}
6124
6125#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6126pub struct OverloadedDeref(pub Mutability);
6127
6128pub trait HasVisibility {
6129 fn visibility(&self, db: &dyn HirDatabase) -> Visibility;
6130 fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool {
6131 let vis = self.visibility(db);
6132 vis.is_visible_from(db, module.id)
6133 }
6134}
6135
6136#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6137pub enum PredicatePolarity {
6138 Positive,
6140 Negative,
6142}
6143
6144#[derive(Debug, Clone, PartialEq, Eq)]
6145pub struct TraitPredicate<'db> {
6146 inner: hir_ty::next_solver::TraitPredicate<'db>,
6147 owner: TypeOwnerId<'db>,
6148}
6149
6150impl<'db> TraitPredicate<'db> {
6151 pub fn polarity(&self) -> PredicatePolarity {
6152 match self.inner.polarity {
6153 rustc_type_ir::PredicatePolarity::Positive => PredicatePolarity::Positive,
6154 rustc_type_ir::PredicatePolarity::Negative => PredicatePolarity::Negative,
6155 }
6156 }
6157
6158 pub fn trait_ref(&self) -> TraitRef<'db> {
6159 TraitRef { owner: self.owner, trait_ref: self.inner.trait_ref }
6160 }
6161}
6162
6163pub trait HasCrate {
6165 fn krate(&self, db: &dyn HirDatabase) -> Crate;
6166}
6167
6168impl<T: hir_def::HasModule> HasCrate for T {
6169 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6170 self.module(db).krate(db).into()
6171 }
6172}
6173
6174impl HasCrate for AssocItem {
6175 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6176 self.module(db).krate(db)
6177 }
6178}
6179
6180impl HasCrate for Struct {
6181 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6182 self.module(db).krate(db)
6183 }
6184}
6185
6186impl HasCrate for Union {
6187 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6188 self.module(db).krate(db)
6189 }
6190}
6191
6192impl HasCrate for Enum {
6193 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6194 self.module(db).krate(db)
6195 }
6196}
6197
6198impl HasCrate for Field {
6199 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6200 self.parent_def(db).module(db).krate(db)
6201 }
6202}
6203
6204impl HasCrate for EnumVariant {
6205 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6206 self.module(db).krate(db)
6207 }
6208}
6209
6210impl HasCrate for Function {
6211 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6212 self.module(db).krate(db)
6213 }
6214}
6215
6216impl HasCrate for Const {
6217 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6218 self.module(db).krate(db)
6219 }
6220}
6221
6222impl HasCrate for TypeAlias {
6223 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6224 self.module(db).krate(db)
6225 }
6226}
6227
6228impl HasCrate for Type<'_> {
6229 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6230 self.krate(db).into()
6231 }
6232}
6233
6234impl HasCrate for Macro {
6235 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6236 self.module(db).krate(db)
6237 }
6238}
6239
6240impl HasCrate for Trait {
6241 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6242 self.module(db).krate(db)
6243 }
6244}
6245
6246impl HasCrate for Static {
6247 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6248 self.module(db).krate(db)
6249 }
6250}
6251
6252impl HasCrate for Adt {
6253 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6254 self.module(db).krate(db)
6255 }
6256}
6257
6258impl HasCrate for Impl {
6259 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6260 self.module(db).krate(db)
6261 }
6262}
6263
6264impl HasCrate for Module {
6265 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6266 Module::krate(*self, db)
6267 }
6268}
6269
6270impl<'db> HasCrate for AnonConst<'db> {
6271 fn krate(&self, db: &dyn HirDatabase) -> Crate {
6272 hir_def::HasModule::krate(&self.id.loc(db).owner, db).into()
6273 }
6274}
6275
6276pub trait HasContainer {
6277 fn container(&self, db: &dyn HirDatabase) -> ItemContainer;
6278}
6279
6280impl HasContainer for ExternCrateDecl {
6281 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6282 container_id_to_hir(self.id.lookup(db).container.into())
6283 }
6284}
6285
6286impl HasContainer for Module {
6287 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6288 let def_map = self.id.def_map(db);
6290 match def_map[self.id].parent {
6291 Some(parent_id) => ItemContainer::Module(Module { id: parent_id }),
6292 None => ItemContainer::Crate(def_map.krate().into()),
6293 }
6294 }
6295}
6296
6297impl HasContainer for Function {
6298 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6299 match self.id {
6300 AnyFunctionId::FunctionId(id) => container_id_to_hir(id.lookup(db).container),
6301 AnyFunctionId::BuiltinDeriveImplMethod { impl_, .. } => {
6302 ItemContainer::Impl(Impl { id: AnyImplId::BuiltinDeriveImplId(impl_) })
6303 }
6304 }
6305 }
6306}
6307
6308impl HasContainer for Struct {
6309 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6310 ItemContainer::Module(Module { id: self.id.lookup(db).container })
6311 }
6312}
6313
6314impl HasContainer for Union {
6315 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6316 ItemContainer::Module(Module { id: self.id.lookup(db).container })
6317 }
6318}
6319
6320impl HasContainer for Enum {
6321 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6322 ItemContainer::Module(Module { id: self.id.lookup(db).container })
6323 }
6324}
6325
6326impl HasContainer for TypeAlias {
6327 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6328 container_id_to_hir(self.id.lookup(db).container)
6329 }
6330}
6331
6332impl HasContainer for Const {
6333 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6334 container_id_to_hir(self.id.lookup(db).container)
6335 }
6336}
6337
6338impl HasContainer for Static {
6339 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6340 container_id_to_hir(self.id.lookup(db).container)
6341 }
6342}
6343
6344impl HasContainer for Trait {
6345 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6346 ItemContainer::Module(Module { id: self.id.lookup(db).container })
6347 }
6348}
6349
6350impl HasContainer for ExternBlock {
6351 fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
6352 ItemContainer::Module(Module { id: self.id.lookup(db).container })
6353 }
6354}
6355
6356pub trait HasName {
6357 fn name(&self, db: &dyn HirDatabase) -> Option<Name>;
6358}
6359
6360macro_rules! impl_has_name {
6361 ( $( $ty:ident ),* $(,)? ) => {
6362 $(
6363 impl HasName for $ty {
6364 fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
6365 (*self).name(db).into()
6366 }
6367 }
6368 )*
6369 };
6370}
6371
6372impl_has_name!(
6373 ModuleDef,
6374 Module,
6375 Field,
6376 Struct,
6377 Union,
6378 Enum,
6379 EnumVariant,
6380 Adt,
6381 Variant,
6382 DefWithBody,
6383 Function,
6384 ExternCrateDecl,
6385 Const,
6386 Static,
6387 Trait,
6388 TypeAlias,
6389 Macro,
6390 ExternAssocItem,
6391 AssocItem,
6392 DeriveHelper,
6393 ToolModule,
6394 Label,
6395 GenericParam,
6396 TypeParam,
6397 LifetimeParam,
6398 ConstParam,
6399 TypeOrConstParam,
6400 InlineAsmOperand,
6401);
6402
6403macro_rules! impl_has_name_no_db {
6404 ( $( $ty:ident ),* $(,)? ) => {
6405 $(
6406 impl HasName for $ty {
6407 fn name(&self, _db: &dyn HirDatabase) -> Option<Name> {
6408 (*self).name().into()
6409 }
6410 }
6411 )*
6412 };
6413}
6414
6415impl_has_name_no_db!(StaticLifetime, BuiltinType, BuiltinAttr);
6416
6417impl HasName for Local<'_> {
6418 fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
6419 (*self).name(db).into()
6420 }
6421}
6422
6423impl HasName for TupleField<'_> {
6424 fn name(&self, _db: &dyn HirDatabase) -> Option<Name> {
6425 (*self).name().into()
6426 }
6427}
6428
6429impl HasName for Param<'_> {
6430 fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
6431 self.name(db)
6432 }
6433}
6434
6435fn container_id_to_hir(c: ItemContainerId) -> ItemContainer {
6436 match c {
6437 ItemContainerId::ExternBlockId(id) => ItemContainer::ExternBlock(ExternBlock { id }),
6438 ItemContainerId::ModuleId(id) => ItemContainer::Module(Module { id }),
6439 ItemContainerId::ImplId(id) => ItemContainer::Impl(id.into()),
6440 ItemContainerId::TraitId(id) => ItemContainer::Trait(Trait { id }),
6441 }
6442}
6443
6444#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6445pub enum ItemContainer {
6446 Trait(Trait),
6447 Impl(Impl),
6448 Module(Module),
6449 ExternBlock(ExternBlock),
6450 Crate(Crate),
6451}
6452
6453pub enum DocLinkDef {
6455 ModuleDef(ModuleDef),
6456 Field(Field),
6457 SelfType(Trait),
6458}
6459
6460pub trait MethodCandidateCallback {
6461 fn on_inherent_method(&mut self, f: Function) -> ControlFlow<()>;
6462
6463 fn on_trait_method(&mut self, f: Function) -> ControlFlow<()>;
6464}
6465
6466impl<F> MethodCandidateCallback for F
6467where
6468 F: FnMut(Function) -> ControlFlow<()>,
6469{
6470 fn on_inherent_method(&mut self, f: Function) -> ControlFlow<()> {
6471 self(f)
6472 }
6473
6474 fn on_trait_method(&mut self, f: Function) -> ControlFlow<()> {
6475 self(f)
6476 }
6477}
6478
6479pub trait PathCandidateCallback {
6480 fn on_inherent_item(&mut self, item: AssocItem) -> ControlFlow<()>;
6481
6482 fn on_trait_item(&mut self, item: AssocItem) -> ControlFlow<()>;
6483}
6484
6485impl<F> PathCandidateCallback for F
6486where
6487 F: FnMut(AssocItem) -> ControlFlow<()>,
6488{
6489 fn on_inherent_item(&mut self, item: AssocItem) -> ControlFlow<()> {
6490 self(item)
6491 }
6492
6493 fn on_trait_item(&mut self, item: AssocItem) -> ControlFlow<()> {
6494 self(item)
6495 }
6496}
6497
6498pub fn resolve_absolute_path<'a, I: Iterator<Item = Symbol> + Clone + 'a>(
6499 db: &'a dyn HirDatabase,
6500 mut segments: I,
6501) -> impl Iterator<Item = ItemInNs> + use<'a, I> {
6502 segments
6503 .next()
6504 .into_iter()
6505 .flat_map(move |crate_name| {
6506 all_crates(db)
6507 .iter()
6508 .filter(|&krate| {
6509 krate
6510 .extra_data(db)
6511 .display_name
6512 .as_ref()
6513 .is_some_and(|name| *name.crate_name().symbol() == crate_name)
6514 })
6515 .filter_map(|&krate| {
6516 let segments = segments.clone();
6517 let mut def_map = crate_def_map(db, krate);
6518 let mut module = &def_map[def_map.root_module_id()];
6519 let mut segments = segments.with_position().peekable();
6520 while let Some((_, segment)) =
6521 segments.next_if(|&(position, _)| !position.is_last)
6522 {
6523 let res = module
6524 .scope
6525 .get(&Name::new_symbol_root(segment))
6526 .take_types()
6527 .and_then(|res| match res {
6528 ModuleDefId::ModuleId(it) => Some(it),
6529 _ => None,
6530 })?;
6531 def_map = res.def_map(db);
6532 module = &def_map[res];
6533 }
6534 let (_, item_name) = segments.next()?;
6535 let res = module.scope.get(&Name::new_symbol_root(item_name));
6536 Some(res.iter_items().map(|(item, _)| item.into()))
6537 })
6538 .collect::<Vec<_>>()
6539 })
6540 .flatten()
6541}
6542
6543fn as_name_opt(name: Option<impl AsName>) -> Name {
6544 name.map_or_else(Name::missing, |name| name.as_name())
6545}
6546
6547#[track_caller]
6548fn generic_args_from_tys<'db>(
6549 interner: DbInterner<'db>,
6550 def_id: SolverDefId<'db>,
6551 args: impl IntoIterator<Item: Borrow<Type<'db>>>,
6552) -> (GenericArgs<'db>, TypeOwnerId<'db>) {
6553 let mut owner = None::<TypeOwnerId<'db>>;
6554 let mut args = args.into_iter();
6555 let args = GenericArgs::for_item(interner, def_id, |_, id, _, _| {
6556 if matches!(id, GenericParamId::TypeParamId(_))
6557 && let Some(arg) = args.next()
6558 {
6559 let arg = arg.borrow();
6560
6561 match &mut owner {
6562 Some(owner) => *owner = owner.must_unify(arg.owner),
6563 None => owner = Some(arg.owner),
6564 }
6565
6566 arg.ty.skip_binder().into()
6567 } else {
6568 next_solver::GenericArg::error_from_id(interner, id)
6569 }
6570 });
6571 let owner =
6572 owner.unwrap_or_else(|| TypeOwnerId::NoParams(Type::builtin_type_crate(interner.db())));
6573 (args, owner)
6574}
6575
6576fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId) -> bool {
6577 let params = GenericParams::of(db, generic_def);
6578 let defaults = db.generic_defaults(generic_def);
6579 params
6580 .iter_type_or_consts()
6581 .filter(|(_, param)| matches!(param, TypeOrConstParamData::TypeParamData(_)))
6582 .map(|(local_id, _)| TypeOrConstParamId { parent: generic_def, local_id })
6583 .any(|param| {
6584 let param = hir_ty::type_or_const_param_idx(db, param);
6585 defaults.get(param as usize).is_none()
6586 })
6587}
6588
6589fn param_env_from_has_crate<'db>(
6590 db: &'db dyn HirDatabase,
6591 id: impl hir_def::HasModule + Into<GenericDefId> + Copy,
6592) -> ParamEnvAndCrate<'db> {
6593 ParamEnvAndCrate { param_env: db.trait_environment(id.into()), krate: id.krate(db) }
6594}
6595
6596pub trait MacroCallIdExt {
6598 fn loc(self, db: &dyn HirDatabase) -> &hir_expand::MacroCallLoc;
6599}
6600impl MacroCallIdExt for span::MacroCallId {
6601 #[inline]
6602 fn loc(self, db: &dyn HirDatabase) -> &hir_expand::MacroCallLoc {
6603 hir_expand::MacroCallId::from(self).loc(db)
6604 }
6605}
6606
6607fn struct_tail_raw<'db>(
6609 db: &'db dyn HirDatabase,
6610 interner: DbInterner<'db>,
6611 mut ty: Ty<'db>,
6612 mut normalize: impl FnMut(Ty<'db>) -> Ty<'db>,
6613) -> Ty<'db> {
6614 let recursion_limit = 16;
6615 for iteration in 0.. {
6616 if iteration >= recursion_limit {
6617 return Ty::new_error(interner, ErrorGuaranteed);
6618 }
6619 match ty.kind() {
6620 TyKind::Adt(def, args) => {
6621 let AdtId::StructId(def_id) = def.def_id() else { break };
6622 let last_field = db.field_types(def_id.into()).iter().next_back();
6623 match last_field {
6624 Some((_, field)) => {
6625 ty = normalize(field.ty().instantiate(interner, args).skip_norm_wip())
6626 }
6627 None => break,
6628 }
6629 }
6630 TyKind::Tuple(tys) if let Some((&last_ty, _)) = tys.split_last() => {
6631 ty = last_ty;
6632 }
6633 TyKind::Tuple(_) => break,
6634 TyKind::Pat(inner, _) => {
6635 ty = inner;
6636 }
6637 _ => {
6638 break;
6639 }
6640 }
6641 }
6642 ty
6643}