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