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