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