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