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