Skip to main content

cairo_lang_semantic/items/
imp.rs

1use std::collections::BTreeSet;
2use std::hash::Hash;
3use std::mem;
4use std::sync::Arc;
5
6use cairo_lang_debug::DebugWithDb;
7use cairo_lang_defs::db::DefsGroup;
8use cairo_lang_defs::ids::{
9    FunctionTitleId, GenericKind, GenericParamId, GenericParamLongId, ImplAliasId,
10    ImplConstantDefId, ImplConstantDefLongId, ImplDefId, ImplFunctionId, ImplFunctionLongId,
11    ImplImplDefId, ImplImplDefLongId, ImplItemId, ImplTypeDefId, ImplTypeDefLongId,
12    LanguageElementId, LookupItemId, ModuleId, ModuleItemId, NamedLanguageElementId,
13    NamedLanguageElementLongId, TopLevelLanguageElementId, TraitConstantId, TraitFunctionId,
14    TraitId, TraitImplId, TraitTypeId, UseId,
15};
16use cairo_lang_diagnostics::{
17    DiagnosticAdded, Diagnostics, Maybe, MaybeAsRef, ToMaybe, skip_diagnostic,
18};
19use cairo_lang_filesystem::db::FilesGroup;
20use cairo_lang_filesystem::ids::{CrateId, CrateLongId, SmolStrId, Tracked, UnstableSalsaId};
21use cairo_lang_proc_macros::{DebugWithDb, HeapSize, SemanticObject};
22use cairo_lang_syntax as syntax;
23use cairo_lang_syntax::node::ast::{
24    OptionTypeClause, OptionWrappedGenericParamList, UnaryOperator,
25};
26use cairo_lang_syntax::node::helpers::GetIdentifier;
27use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
28use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
29use cairo_lang_utils::unordered_hash_map::UnorderedHashMap;
30use cairo_lang_utils::unordered_hash_set::UnorderedHashSet;
31use cairo_lang_utils::{Intern, define_short_id, extract_matches};
32use itertools::{Itertools, chain, izip};
33use salsa::Database;
34use syntax::attribute::structured::{Attribute, AttributeListStructurize};
35use syntax::node::ast::{self, GenericArg, ImplItem, MaybeImplBody, OptionReturnTypeClause};
36use syntax::node::helpers::OptionWrappedGenericParamListHelper;
37use syntax::node::ids::SyntaxStablePtrId;
38use syntax::node::{Terminal, TypedStablePtr, TypedSyntaxNode};
39
40use super::constant::{
41    ConstValue, ConstValueId, ConstantData, ImplConstantId, constant_semantic_data_cycle_helper,
42    constant_semantic_data_helper,
43};
44use super::enm::SemanticEnumEx;
45use super::feature_kind::{FeatureKind, HasFeatureKind};
46use super::function_with_body::{FunctionBody, FunctionBodyData, get_inline_config};
47use super::functions::{
48    FunctionDeclarationData, GenericFunctionId, ImplGenericFunctionId, InlineConfiguration,
49    forbid_inline_always_with_impl_generic_param,
50};
51use super::generics::{
52    GenericArgumentHead, GenericParamImpl, GenericParamsData, displayable_concrete,
53    generic_params_to_args, semantic_generic_params,
54};
55use super::impl_alias::{
56    ImplAliasData, impl_alias_generic_params_data_helper, impl_alias_semantic_data_cycle_helper,
57    impl_alias_semantic_data_helper,
58};
59use super::trt::{
60    ConcreteTraitConstantId, ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId,
61    ConcreteTraitImplId,
62};
63use super::type_aliases::{
64    TypeAliasData, type_alias_generic_params_data_helper, type_alias_semantic_data_cycle_helper,
65    type_alias_semantic_data_helper,
66};
67use super::visibility::peek_visible_in;
68use super::{TraitOrImplContext, resolve_trait_path};
69use crate::corelib::{CorelibSemantic, concrete_destruct_trait, concrete_drop_trait, core_crate};
70use crate::db::get_resolver_data_options;
71use crate::diagnostic::SemanticDiagnosticKind::{self, *};
72use crate::diagnostic::{NotFoundItemType, SemanticDiagnostics, SemanticDiagnosticsBuilder};
73use crate::expr::compute::{ComputationContext, ContextFunction, Environment, compute_root_expr};
74use crate::expr::inference::canonic::ResultNoErrEx;
75use crate::expr::inference::conform::InferenceConform;
76use crate::expr::inference::infers::InferenceEmbeddings;
77use crate::expr::inference::solver::{Ambiguity, SolutionSet, enrich_lookup_context_with_ty};
78use crate::expr::inference::{
79    ImplVarId, ImplVarTraitItemMappings, Inference, InferenceError, InferenceId, NegativeImplVarId,
80};
81use crate::items::function_with_body::get_implicit_precedence;
82use crate::items::functions::ImplicitPrecedence;
83use crate::items::generics::GenericParamSemantic;
84use crate::items::impl_alias::ImplAliasSemantic;
85use crate::items::implization::ImplizationSemantic;
86use crate::items::macro_call::{MacroCallSemantic, module_macro_modules};
87use crate::items::module::ModuleSemantic;
88use crate::items::structure::StructSemantic;
89use crate::items::trt::TraitSemantic;
90use crate::items::us::{SemanticUseEx, UseSemantic};
91use crate::resolve::{
92    AsSegments, ResolutionContext, ResolvedConcreteItem, ResolvedGenericItem, Resolver,
93    ResolverData,
94};
95use crate::substitution::{GenericSubstitution, SemanticRewriter};
96use crate::types::{
97    ImplTypeId, ShallowGenericArg, TypeHead, TypesSemantic, add_type_based_diagnostics,
98    get_impl_at_context, maybe_resolve_shallow_generic_arg_type, resolve_type,
99};
100use crate::{
101    ConcreteFunction, ConcreteTraitId, ConcreteTraitLongId, FunctionId, FunctionLongId,
102    GenericArgumentId, GenericParam, Mutability, SemanticDiagnostic, TypeId, TypeLongId, semantic,
103    semantic_object_for_id,
104};
105
106#[cfg(test)]
107#[path = "imp_test.rs"]
108mod test;
109
110#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update, HeapSize)]
111pub struct ConcreteImplLongId<'db> {
112    pub impl_def_id: ImplDefId<'db>,
113    pub generic_args: Vec<GenericArgumentId<'db>>,
114}
115define_short_id!(ConcreteImplId, ConcreteImplLongId<'db>);
116semantic_object_for_id!(ConcreteImplId, ConcreteImplLongId<'a>);
117impl<'db> DebugWithDb<'db> for ConcreteImplLongId<'db> {
118    type Db = dyn Database;
119
120    fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
121        write!(
122            f,
123            "{}",
124            displayable_concrete(db, &self.impl_def_id.full_path(db), &self.generic_args)
125        )
126    }
127}
128impl<'db> ConcreteImplId<'db> {
129    pub fn impl_def_id(&self, db: &'db dyn Database) -> ImplDefId<'db> {
130        self.long(db).impl_def_id
131    }
132    pub fn get_impl_function(
133        &self,
134        db: &'db dyn Database,
135        function: TraitFunctionId<'db>,
136    ) -> Maybe<Option<ImplFunctionId<'db>>> {
137        db.impl_function_by_trait_function(self.impl_def_id(db), function)
138    }
139    pub fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
140        self.impl_def_id(db).name(db)
141    }
142    pub fn full_path(&self, db: &dyn Database) -> String {
143        format!("{:?}", self.debug(db))
144    }
145    pub fn substitution(&self, db: &'db dyn Database) -> Maybe<GenericSubstitution<'db>> {
146        Ok(GenericSubstitution::from_impl(ImplLongId::Concrete(*self).intern(db)).concat(
147            GenericSubstitution::new(
148                db.impl_def_generic_params(self.impl_def_id(db))?,
149                &self.long(db).generic_args,
150            ),
151        ))
152    }
153    /// Returns true if the `impl` does not depend on any generics.
154    pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
155        self.long(db)
156            .generic_args
157            .iter()
158            .all(|generic_argument_id| generic_argument_id.is_fully_concrete(db))
159    }
160    /// Returns true if the `impl` does not depend on impl or type variables.
161    pub fn is_var_free(&self, db: &dyn Database) -> bool {
162        self.long(db)
163            .generic_args
164            .iter()
165            .all(|generic_argument_id| generic_argument_id.is_var_free(db))
166    }
167}
168
169/// Represents a "callee" impl that can be referred to in the code.
170/// Traits should be resolved to this.
171#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update, HeapSize)]
172pub enum ImplLongId<'db> {
173    Concrete(ConcreteImplId<'db>),
174    GenericParameter(GenericParamId<'db>),
175    ImplVar(ImplVarId<'db>),
176    ImplImpl(ImplImplId<'db>),
177    SelfImpl(ConcreteTraitId<'db>),
178    GeneratedImpl(GeneratedImplId<'db>),
179}
180impl<'db> ImplLongId<'db> {
181    /// Returns the [ImplHead] of an impl if available.
182    pub fn head(&self, db: &'db dyn Database) -> Option<ImplHead<'db>> {
183        Some(match self {
184            ImplLongId::Concrete(concrete) => ImplHead::Concrete(concrete.impl_def_id(db)),
185            ImplLongId::GenericParameter(_)
186            | ImplLongId::ImplVar(_)
187            | ImplLongId::ImplImpl(_)
188            | ImplLongId::SelfImpl(_)
189            | ImplLongId::GeneratedImpl(_) => {
190                return None;
191            }
192        })
193    }
194    pub fn name(&self, db: &dyn Database) -> String {
195        match self {
196            ImplLongId::Concrete(concrete_impl) => concrete_impl.name(db).to_string(db),
197            ImplLongId::GenericParameter(generic_param_impl) => {
198                generic_param_impl.name(db).map(|n| n.long(db).as_str()).unwrap_or("_").to_string()
199            }
200            ImplLongId::ImplVar(var) => {
201                format!("ImplVar({})", var.concrete_trait_id(db).full_path(db))
202            }
203            ImplLongId::ImplImpl(impl_impl) => format!(
204                "{}::{}",
205                impl_impl.impl_id().name(db),
206                db.impl_impl_concrete_trait(*impl_impl)
207                    .map(|trait_impl| trait_impl.full_path(db))
208                    .unwrap_or_else(|_| "_".into())
209            ),
210            ImplLongId::SelfImpl(trait_impl) => trait_impl.name(db).to_string(db),
211            ImplLongId::GeneratedImpl(generated_impl) => {
212                format!("{:?}", generated_impl.debug(db))
213            }
214        }
215    }
216    pub fn format(&self, db: &dyn Database) -> String {
217        format!("{:?}", self.debug(db))
218    }
219
220    /// Returns true if the `impl` does not depend on impl or type variables.
221    pub fn is_var_free(&self, db: &dyn Database) -> bool {
222        match self {
223            ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.is_var_free(db),
224            ImplLongId::SelfImpl(concrete_trait_id) => concrete_trait_id.is_var_free(db),
225            ImplLongId::GenericParameter(_) => true,
226            ImplLongId::ImplVar(_) => false,
227            ImplLongId::ImplImpl(impl_impl) => impl_impl.impl_id().is_var_free(db),
228            ImplLongId::GeneratedImpl(generated_impl) => {
229                generated_impl.concrete_trait(db).is_var_free(db)
230                    && generated_impl
231                        .long(db)
232                        .impl_items
233                        .0
234                        .values()
235                        .all(|type_id| type_id.is_var_free(db))
236            }
237        }
238    }
239
240    /// Returns true if the `impl` does not depend on any generics.
241    pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
242        match self {
243            ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.is_fully_concrete(db),
244            ImplLongId::GenericParameter(_) => false,
245            ImplLongId::ImplVar(_) => false,
246            ImplLongId::ImplImpl(_) | ImplLongId::SelfImpl(_) => false,
247            ImplLongId::GeneratedImpl(generated_impl) => {
248                generated_impl.concrete_trait(db).is_fully_concrete(db)
249                    && generated_impl
250                        .long(db)
251                        .impl_items
252                        .0
253                        .values()
254                        .all(|type_id| type_id.is_fully_concrete(db))
255            }
256        }
257    }
258}
259impl<'db> DebugWithDb<'db> for ImplLongId<'db> {
260    type Db = dyn Database;
261
262    fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
263        match self {
264            ImplLongId::Concrete(concrete_impl_id) => {
265                write!(f, "{:?}", concrete_impl_id.debug(db))
266            }
267            ImplLongId::GenericParameter(param) => write!(f, "{}", param.format(db).long(db)),
268            ImplLongId::ImplVar(var) => write!(f, "?{}", var.long(db).id.0),
269            ImplLongId::ImplImpl(impl_impl) => write!(f, "{:?}", impl_impl.debug(db)),
270            ImplLongId::SelfImpl(trait_impl) => write!(f, "{:?}", trait_impl.debug(db)),
271            ImplLongId::GeneratedImpl(generated_impl) => {
272                write!(f, "{:?}", generated_impl.debug(db))
273            }
274        }
275    }
276}
277
278define_short_id!(ImplId, ImplLongId<'db>);
279semantic_object_for_id!(ImplId, ImplLongId<'a>);
280impl<'db> ImplId<'db> {
281    pub fn concrete_trait(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitId<'db>> {
282        db.impl_concrete_trait(*self)
283    }
284
285    /// Returns true if the `impl` does not depend on any generics.
286    pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
287        impl_is_fully_concrete(db, *self)
288    }
289
290    /// Returns true if the `impl` does not depend on impl or type variables.
291    pub fn is_var_free(&self, db: &dyn Database) -> bool {
292        impl_is_var_free(db, *self)
293    }
294
295    /// Returns the [ImplHead] of an impl if available.
296    pub fn head(&self, db: &'db dyn Database) -> Option<ImplHead<'db>> {
297        self.long(db).head(db)
298    }
299
300    /// Returns the name of the impl.
301    pub fn name(&self, db: &dyn Database) -> String {
302        self.long(db).name(db)
303    }
304
305    pub fn format(&self, db: &dyn Database) -> String {
306        self.long(db).format(db)
307    }
308}
309
310define_short_id!(GeneratedImplId, GeneratedImplLongId<'db>);
311semantic_object_for_id!(GeneratedImplId, GeneratedImplLongId<'a>);
312
313impl<'db> GeneratedImplId<'db> {
314    pub fn concrete_trait(self, db: &'db dyn Database) -> ConcreteTraitId<'db> {
315        self.long(db).concrete_trait
316    }
317
318    pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
319        self.concrete_trait(db).trait_id(db)
320    }
321}
322
323/// An impl that is generated by the compiler for a specific trait.
324/// There can be only one such impl per concrete trait as otherwise there would be a
325/// MultipleImplsFound ambiguity.
326#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update, HeapSize)]
327pub struct GeneratedImplLongId<'db> {
328    pub concrete_trait: ConcreteTraitId<'db>,
329    /// The generic params required for the impl. Typically impls and negative impls.
330    /// We save the params so that we can validate negative impls.
331    pub generic_params: Vec<GenericParam<'db>>,
332    pub impl_items: GeneratedImplItems<'db>,
333}
334#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, SemanticObject, salsa::Update, HeapSize)]
335pub struct GeneratedImplItems<'db>(pub OrderedHashMap<TraitTypeId<'db>, TypeId<'db>>);
336
337pub enum GeneratedImplAssociatedTypes<'db> {
338    /// The associated types are not yet resolved.
339    Unresolved,
340    /// The associated types are resolved.
341    Resolved(OrderedHashMap<TraitTypeId<'db>, TypeId<'db>>),
342}
343
344impl<'db> DebugWithDb<'db> for GeneratedImplLongId<'db> {
345    type Db = dyn Database;
346
347    fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
348        write!(f, "Generated {:?}", self.concrete_trait.debug(db))
349    }
350}
351
352/// An impl item of kind impl.
353#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject, HeapSize, salsa::Update)]
354pub struct ImplImplId<'db> {
355    /// The impl the item impl is in.
356    impl_id: ImplId<'db>,
357    /// The trait impl this impl impl "implements".
358    trait_impl_id: TraitImplId<'db>,
359}
360
361impl<'db> ImplImplId<'db> {
362    /// Creates a new impl impl id. For an impl impl of a concrete impl, asserts that the
363    /// trait impl belongs to the same trait that the impl implements (panics if not).
364    pub fn new(impl_id: ImplId<'db>, trait_impl_id: TraitImplId<'db>, db: &dyn Database) -> Self {
365        if let ImplLongId::Concrete(concrete_impl) = impl_id.long(db) {
366            let impl_def_id = concrete_impl.impl_def_id(db);
367            assert_eq!(Ok(trait_impl_id.trait_id(db)), db.impl_def_trait(impl_def_id));
368        }
369
370        ImplImplId { impl_id, trait_impl_id }
371    }
372    pub fn impl_id(&self) -> ImplId<'db> {
373        self.impl_id
374    }
375    pub fn trait_impl_id(&self) -> TraitImplId<'db> {
376        self.trait_impl_id
377    }
378
379    pub fn concrete_trait_impl_id(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitImplId<'db>> {
380        Ok(ConcreteTraitImplId::new_from_data(
381            db,
382            self.impl_id.concrete_trait(db)?,
383            self.trait_impl_id,
384        ))
385    }
386
387    pub fn full_path(&self, db: &dyn Database) -> String {
388        format!("{:?}", self.debug(db))
389    }
390}
391impl<'db> DebugWithDb<'db> for ImplImplId<'db> {
392    type Db = dyn Database;
393
394    fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
395        write!(f, "{:?}::{}", self.impl_id.debug(db), self.trait_impl_id.name(db).long(db))
396    }
397}
398
399/// Represents a "callee" impl that can be referred to in the code.
400/// Traits should be resolved to this.
401#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update, HeapSize)]
402pub enum NegativeImplLongId<'db> {
403    Solved(ConcreteTraitId<'db>),
404    GenericParameter(GenericParamId<'db>),
405    NegativeImplVar(NegativeImplVarId<'db>),
406}
407
408impl<'db> NegativeImplLongId<'db> {
409    pub fn concrete_trait(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitId<'db>> {
410        match self {
411            NegativeImplLongId::Solved(concrete_trait_id) => Ok(*concrete_trait_id),
412            NegativeImplLongId::GenericParameter(param) => {
413                let param_impl =
414                    extract_matches!(db.generic_param_semantic(*param)?, GenericParam::NegImpl);
415                param_impl.concrete_trait
416            }
417            NegativeImplLongId::NegativeImplVar(negative_impl_var_id) => {
418                Ok(negative_impl_var_id.long(db).concrete_trait_id)
419            }
420        }
421    }
422    pub fn is_var_free(&self, db: &dyn Database) -> bool {
423        match self {
424            NegativeImplLongId::Solved(concrete_trait_id) => concrete_trait_id.is_var_free(db),
425            NegativeImplLongId::GenericParameter(_) => true,
426            NegativeImplLongId::NegativeImplVar(_) => false,
427        }
428    }
429    pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
430        match self {
431            NegativeImplLongId::Solved(concrete_trait_id) => concrete_trait_id.is_var_free(db),
432            NegativeImplLongId::GenericParameter(_) | NegativeImplLongId::NegativeImplVar(_) => {
433                false
434            }
435        }
436    }
437}
438
439define_short_id!(NegativeImplId, NegativeImplLongId<'db>);
440impl<'db> NegativeImplId<'db> {
441    pub fn concrete_trait(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitId<'db>> {
442        self.long(db).concrete_trait(db)
443    }
444    pub fn is_var_free(&self, db: &dyn Database) -> bool {
445        self.long(db).is_var_free(db)
446    }
447    pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
448        self.long(db).is_fully_concrete(db)
449    }
450}
451semantic_object_for_id!(NegativeImplId, NegativeImplLongId<'a>);
452
453impl<'db> UnstableSalsaId for ImplId<'db> {
454    fn get_internal_id(&self) -> salsa::Id {
455        self.as_intern_id()
456    }
457}
458
459/// Head of an impl.
460///
461/// A non-param non-variable impl has a head, which represents the kind of the root node in its tree
462/// representation. This is used for caching queries for fast lookups when the impl is not
463/// completely inferred yet.
464#[derive(Clone, Debug, Hash, PartialEq, Eq, salsa::Update)]
465pub enum ImplHead<'db> {
466    Concrete(ImplDefId<'db>),
467}
468
469// === Impl Declaration ===
470
471#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
472#[debug_db(dyn Database)]
473struct ImplDeclarationData<'db> {
474    diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
475    /// The concrete trait this impl implements, or Err if cannot be resolved.
476    concrete_trait: Maybe<ConcreteTraitId<'db>>,
477    attributes: Vec<Attribute<'db>>,
478    resolver_data: Arc<ResolverData<'db>>,
479}
480
481/// Returns the generic parameters data of an impl definition.
482#[salsa::tracked(returns(ref))]
483fn impl_def_generic_params_data<'db>(
484    db: &'db dyn Database,
485    impl_def_id: ImplDefId<'db>,
486) -> Maybe<GenericParamsData<'db>> {
487    let module_id = impl_def_id.parent_module(db);
488    let mut diagnostics = SemanticDiagnostics::new(module_id);
489
490    let impl_ast = db.module_impl_by_id(impl_def_id)?;
491    let inference_id =
492        InferenceId::LookupItemGenerics(LookupItemId::ModuleItem(ModuleItemId::Impl(impl_def_id)));
493
494    let mut resolver = Resolver::new(db, module_id, inference_id);
495    resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
496    let generic_params = semantic_generic_params(
497        db,
498        &mut diagnostics,
499        &mut resolver,
500        module_id,
501        &impl_ast.generic_params(db),
502    );
503    let inference = &mut resolver.inference();
504    inference.finalize(&mut diagnostics, impl_ast.stable_ptr(db).untyped());
505    let generic_params = inference.rewrite(generic_params).no_err();
506    let resolver_data = Arc::new(resolver.data);
507    Ok(GenericParamsData { generic_params, diagnostics: diagnostics.build(), resolver_data })
508}
509
510/// Implementation of [PrivImplSemantic::impl_def_substitution].
511#[salsa::tracked(returns(ref))]
512fn impl_def_substitution<'db>(
513    db: &'db dyn Database,
514    impl_def_id: ImplDefId<'db>,
515) -> Maybe<GenericSubstitution<'db>> {
516    let params = db.impl_def_generic_params(impl_def_id)?;
517    let generic_args = generic_params_to_args(params, db);
518    ConcreteImplLongId { impl_def_id, generic_args }.intern(db).substitution(db)
519}
520
521/// Implementation of [ImplSemantic::impl_def_trait].
522#[salsa::tracked]
523fn impl_def_trait<'db>(db: &'db dyn Database, impl_def_id: ImplDefId<'db>) -> Maybe<TraitId<'db>> {
524    let module_id = impl_def_id.parent_module(db);
525    let mut diagnostics = SemanticDiagnostics::new(module_id);
526
527    let impl_ast = db.module_impl_by_id(impl_def_id)?;
528    let inference_id = InferenceId::ImplDefTrait(impl_def_id);
529
530    let mut resolver = Resolver::new(db, module_id, inference_id);
531    resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
532
533    let trait_path_syntax = impl_ast.trait_path(db);
534
535    resolve_trait_path(db, &mut diagnostics, &mut resolver, &trait_path_syntax)
536}
537
538/// Query implementation of [PrivImplSemantic::impl_def_shallow_trait_generic_args].
539fn impl_def_shallow_trait_generic_args<'db>(
540    db: &'db dyn Database,
541    impl_def_id: ImplDefId<'db>,
542) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
543    Ok(impl_def_shallow_trait_generic_args_helper(db, impl_def_id).maybe_as_ref()?)
544}
545
546/// Helper for [ImplSemantic::impl_def_shallow_trait_generic_args].
547/// The actual query implementation, separated to allow returning a reference.
548#[salsa::tracked(returns(ref))]
549fn impl_def_shallow_trait_generic_args_helper<'db>(
550    db: &'db dyn Database,
551    impl_def_id: ImplDefId<'db>,
552) -> Maybe<Vec<(GenericParamId<'db>, ShallowGenericArg<'db>)>> {
553    let module_id = impl_def_id.parent_module(db);
554    let mut diagnostics = SemanticDiagnostics::new(module_id);
555
556    let impl_ast = db.module_impl_by_id(impl_def_id)?;
557    let inference_id = InferenceId::ImplDefTrait(impl_def_id);
558
559    let mut resolver = Resolver::new(db, module_id, inference_id);
560    resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
561
562    if let OptionWrappedGenericParamList::WrappedGenericParamList(params_list) =
563        impl_ast.generic_params(db)
564    {
565        params_list.generic_params(db).elements(db).for_each(|param_syntax| {
566            let generic_param_id =
567                GenericParamLongId(module_id, param_syntax.stable_ptr(db)).intern(db);
568            resolver.add_generic_param(generic_param_id);
569        })
570    }
571    let trait_path_syntax = impl_ast.trait_path(db);
572
573    let ResolvedGenericItem::Trait(trait_id) = resolver.resolve_generic_path_with_args(
574        &mut diagnostics,
575        &trait_path_syntax,
576        NotFoundItemType::Trait,
577        ResolutionContext::Default,
578    )?
579    else {
580        return Err(skip_diagnostic());
581    };
582    let generic_params = db
583        .trait_generic_params_ids(trait_id)?
584        .iter()
585        .map(|param_syntax| {
586            GenericParamLongId(trait_id.parent_module(db), param_syntax.stable_ptr(db)).intern(db)
587        })
588        .collect::<Vec<_>>();
589
590    let elements = trait_path_syntax.segments(db).elements(db);
591    let Some(last) = elements.last() else {
592        return Ok(Vec::new());
593    };
594    match last {
595        ast::PathSegment::Simple(_) => Ok(Vec::new()),
596        ast::PathSegment::WithGenericArgs(path_segment_with_generic_args) => {
597            let generic_args =
598                path_segment_with_generic_args.generic_args(db).generic_args(db).elements_vec(db);
599
600            let arg_syntax_per_param = resolver.get_arg_syntax_per_param(
601                &mut diagnostics,
602                &generic_params,
603                &generic_args,
604            )?;
605            Ok(generic_params
606                .iter()
607                .filter_map(|generic_param| {
608                    let expr = arg_syntax_per_param.get(generic_param)?;
609                    let arg_ty = maybe_resolve_shallow_generic_arg_type(
610                        db,
611                        &mut diagnostics,
612                        &mut resolver,
613                        expr,
614                    )?;
615                    Some((*generic_param, arg_ty))
616                })
617                .collect::<Vec<_>>())
618        }
619        ast::PathSegment::Missing(_) => Ok(Vec::new()),
620    }
621}
622
623/// Query implementation of [PrivImplSemantic::impl_alias_trait_generic_args].
624fn impl_alias_trait_generic_args<'db>(
625    db: &'db dyn Database,
626    impl_alias_id: ImplAliasId<'db>,
627) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
628    Ok(impl_alias_trait_generic_args_helper(db, impl_alias_id).maybe_as_ref()?)
629}
630
631#[salsa::tracked(returns(ref))]
632fn impl_alias_trait_generic_args_helper<'db>(
633    db: &'db dyn Database,
634    impl_alias_id: ImplAliasId<'db>,
635) -> Maybe<Vec<(GenericParamId<'db>, ShallowGenericArg<'db>)>> {
636    let module_id = impl_alias_id.parent_module(db);
637    let mut diagnostics = SemanticDiagnostics::new(module_id);
638
639    let impl_alias_ast = db.module_impl_alias_by_id(impl_alias_id)?;
640    let inference_id = InferenceId::ImplAliasImplDef(impl_alias_id);
641
642    let mut resolver = Resolver::new(db, module_id, inference_id);
643    resolver.set_feature_config(&impl_alias_id, &impl_alias_ast, &mut diagnostics);
644
645    if let OptionWrappedGenericParamList::WrappedGenericParamList(params_list) =
646        impl_alias_ast.generic_params(db)
647    {
648        params_list.generic_params(db).elements(db).for_each(|param_syntax| {
649            let generic_param_id =
650                GenericParamLongId(module_id, param_syntax.stable_ptr(db)).intern(db);
651            resolver.add_generic_param(generic_param_id);
652        })
653    }
654    let rhs_syntax = impl_alias_ast.impl_path(db);
655    let (shallow_args, rhs_generic_params) = match resolver.resolve_generic_path_with_args(
656        &mut diagnostics,
657        &rhs_syntax,
658        NotFoundItemType::Impl,
659        ResolutionContext::Default,
660    ) {
661        Ok(ResolvedGenericItem::Impl(impl_def_id)) => {
662            let shallow_args = db.impl_def_shallow_trait_generic_args(impl_def_id)?.to_vec();
663            let OptionWrappedGenericParamList::WrappedGenericParamList(params) =
664                db.module_impl_by_id(impl_def_id)?.generic_params(db)
665            else {
666                return Ok(shallow_args);
667            };
668            (
669                shallow_args,
670                params
671                    .generic_params(db)
672                    .elements(db)
673                    .map(|param_syntax| {
674                        GenericParamLongId(
675                            impl_def_id.parent_module(db),
676                            param_syntax.stable_ptr(db),
677                        )
678                        .intern(db)
679                    })
680                    .collect::<Vec<_>>(),
681            )
682        }
683        Ok(ResolvedGenericItem::GenericImplAlias(impl_alias)) => {
684            let shallow_args = db.impl_alias_trait_generic_args(impl_alias)?.to_vec();
685            let OptionWrappedGenericParamList::WrappedGenericParamList(params) =
686                db.module_impl_alias_by_id(impl_alias)?.generic_params(db)
687            else {
688                return Ok(shallow_args);
689            };
690            (
691                shallow_args,
692                params
693                    .generic_params(db)
694                    .elements(db)
695                    .map(|param_syntax| {
696                        GenericParamLongId(
697                            impl_alias.parent_module(db),
698                            param_syntax.stable_ptr(db),
699                        )
700                        .intern(db)
701                    })
702                    .collect::<Vec<_>>(),
703            )
704        }
705        _ => return Ok(Vec::new()),
706    };
707
708    let elements = rhs_syntax.segments(db).elements(db);
709    let Some(last) = elements.last() else {
710        return Ok(Vec::new());
711    };
712
713    match last {
714        ast::PathSegment::Simple(_) => Ok(shallow_args),
715        ast::PathSegment::WithGenericArgs(path_segment_with_generic_args) => {
716            let generic_args =
717                path_segment_with_generic_args.generic_args(db).generic_args(db).elements_vec(db);
718            let arg_syntax_per_param = resolver.get_arg_syntax_per_param(
719                &mut diagnostics,
720                &rhs_generic_params,
721                &generic_args,
722            )?;
723
724            Ok(shallow_args
725                .iter()
726                .filter_map(|(trait_param, arg)| {
727                    let ShallowGenericArg::GenericParameter(arg) = arg else {
728                        return Some((*trait_param, arg.clone()));
729                    };
730
731                    arg_syntax_per_param.get(arg).and_then(|expr| {
732                        let arg_ty = maybe_resolve_shallow_generic_arg_type(
733                            db,
734                            &mut diagnostics,
735                            &mut resolver,
736                            expr,
737                        )?;
738                        Some((*trait_param, arg_ty))
739                    })
740                })
741                .collect::<Vec<_>>())
742        }
743        ast::PathSegment::Missing(_) => Ok(shallow_args),
744    }
745}
746
747/// Implementation of [ImplSemantic::impl_concrete_trait].
748fn impl_concrete_trait<'db>(
749    db: &'db dyn Database,
750    impl_id: ImplId<'db>,
751) -> Maybe<ConcreteTraitId<'db>> {
752    match impl_id.long(db) {
753        ImplLongId::Concrete(concrete_impl_id) => {
754            let long_impl = concrete_impl_id.long(db);
755            let substitution = GenericSubstitution::new(
756                db.impl_def_generic_params(long_impl.impl_def_id)?,
757                &long_impl.generic_args,
758            );
759
760            let impl_concrete_trait_id = db.impl_def_concrete_trait(long_impl.impl_def_id)?;
761            substitution.substitute(db, impl_concrete_trait_id)
762        }
763        ImplLongId::GenericParameter(param) => {
764            let param_impl =
765                extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
766            param_impl.concrete_trait
767        }
768        ImplLongId::ImplVar(var) => Ok(var.long(db).concrete_trait_id),
769        ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(*impl_impl),
770        ImplLongId::SelfImpl(concrete_trait_id) => Ok(*concrete_trait_id),
771        ImplLongId::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
772    }
773}
774
775/// Query implementation of [ImplSemantic::impl_concrete_trait].
776#[salsa::tracked]
777fn impl_concrete_trait_tracked<'db>(
778    db: &'db dyn Database,
779    impl_id: ImplId<'db>,
780) -> Maybe<ConcreteTraitId<'db>> {
781    impl_concrete_trait(db, impl_id)
782}
783
784// --- Computation ---
785
786/// Cycle handling for [impl_declaration_data].
787fn impl_declaration_data_cycle<'db>(
788    db: &'db dyn Database,
789    _id: salsa::Id,
790    impl_def_id: ImplDefId<'db>,
791) -> Maybe<ImplDeclarationData<'db>> {
792    impl_declaration_data_inner(db, impl_def_id, false)
793}
794
795/// Computes impl declaration data.
796#[salsa::tracked(cycle_result=impl_declaration_data_cycle, returns(ref))]
797fn impl_declaration_data<'db>(
798    db: &'db dyn Database,
799    impl_def_id: ImplDefId<'db>,
800) -> Maybe<ImplDeclarationData<'db>> {
801    impl_declaration_data_inner(db, impl_def_id, true)
802}
803
804/// Shared code for the query and cycle handling.
805/// The cycle handling logic needs to pass resolve_trait=false to prevent the cycle.
806fn impl_declaration_data_inner<'db>(
807    db: &'db dyn Database,
808    impl_def_id: ImplDefId<'db>,
809    resolve_trait: bool,
810) -> Maybe<ImplDeclarationData<'db>> {
811    let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
812
813    // TODO(spapini): when code changes in a file, all the AST items change (as they contain a path
814    // to the green root that changes. Once ASTs are rooted on items, use a selector that picks only
815    // the item instead of all the module data.
816    let impl_ast = db.module_impl_by_id(impl_def_id)?;
817    let inference_id = InferenceId::LookupItemDeclaration(LookupItemId::ModuleItem(
818        ModuleItemId::Impl(impl_def_id),
819    ));
820
821    // Generic params.
822    let generic_params_data = impl_def_generic_params_data(db, impl_def_id).maybe_as_ref()?;
823    let mut resolver = Resolver::with_data(
824        db,
825        (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
826    );
827    resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
828    diagnostics.extend(generic_params_data.diagnostics.clone());
829    let trait_path_syntax = impl_ast.trait_path(db);
830
831    let concrete_trait = if resolve_trait {
832        resolver
833            .resolve_concrete_path(&mut diagnostics, &trait_path_syntax, NotFoundItemType::Trait)
834            .and_then(|resolved_item| match resolved_item {
835                ResolvedConcreteItem::Trait(id) | ResolvedConcreteItem::SelfTrait(id) => Ok(id),
836                _ => Err(diagnostics
837                    .report(trait_path_syntax.stable_ptr(db), SemanticDiagnosticKind::NotATrait)),
838            })
839    } else {
840        Err(diagnostics.report(trait_path_syntax.stable_ptr(db), ImplRequirementCycle))
841    };
842
843    let info = db.core_info();
844
845    // Check for reimplementation of compilers' Traits.
846    if let Ok(concrete_trait) = concrete_trait
847        && [
848            info.type_eq_trt,
849            info.fn_trt,
850            info.fn_once_trt,
851            info.felt252_dict_value_trt,
852            info.numeric_literal_trt,
853            info.string_literal_trt,
854        ]
855        .contains(&concrete_trait.trait_id(db))
856        && impl_def_id.parent_module(db).owning_crate(db) != core_crate(db)
857    {
858        diagnostics.report(
859            trait_path_syntax.stable_ptr(db),
860            CompilerTraitReImplementation { trait_id: concrete_trait.trait_id(db) },
861        );
862    }
863
864    // Check fully resolved.
865    let inference = &mut resolver.inference();
866    inference.finalize(&mut diagnostics, impl_ast.stable_ptr(db).untyped());
867
868    let concrete_trait: Result<ConcreteTraitId<'_>, DiagnosticAdded> =
869        inference.rewrite(concrete_trait).no_err();
870
871    let attributes = impl_ast.attributes(db).structurize(db);
872    let mut resolver_data = resolver.data;
873    resolver_data.trait_or_impl_ctx = TraitOrImplContext::Impl(impl_def_id);
874    Ok(ImplDeclarationData {
875        diagnostics: diagnostics.build(),
876        concrete_trait,
877        attributes,
878        resolver_data: Arc::new(resolver_data),
879    })
880}
881
882// === Impl Definition ===
883
884#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
885#[debug_db(dyn Database)]
886struct ImplDefinitionData<'db> {
887    /// The diagnostics here are "flat" - that is, only the diagnostics found on the impl level
888    /// itself, and don't include the diagnostics of its items. The reason it's this way is that
889    /// computing the items' diagnostics require a query about their impl, forming a cycle of
890    /// queries. Adding the items' diagnostics only after the whole computation breaks this cycle.
891    diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
892
893    // AST maps.
894    function_asts: OrderedHashMap<ImplFunctionId<'db>, ast::FunctionWithBody<'db>>,
895    item_type_asts: OrderedHashMap<ImplTypeDefId<'db>, ast::ItemTypeAlias<'db>>,
896    item_constant_asts: OrderedHashMap<ImplConstantDefId<'db>, ast::ItemConstant<'db>>,
897    item_impl_asts: OrderedHashMap<ImplImplDefId<'db>, ast::ItemImplAlias<'db>>,
898
899    /// Mapping of item names to their meta data info. All the IDs should appear in one of the AST
900    /// maps above.
901    item_id_by_name: OrderedHashMap<SmolStrId<'db>, ImplItemInfo<'db>>,
902
903    /// Mapping of missing impl names item names to the trait id.
904    implicit_impls_id_by_name: OrderedHashMap<SmolStrId<'db>, TraitImplId<'db>>,
905}
906
907impl<'db> ImplDefinitionData<'db> {
908    /// Retrieves impl item information by its name.
909    pub fn get_impl_item_info(&self, item_name: SmolStrId<'db>) -> Option<ImplItemInfo<'db>> {
910        self.item_id_by_name.get(&item_name).cloned()
911    }
912}
913/// Stores metadata for an impl item, including its ID and feature kind.
914#[derive(Clone, Debug, PartialEq, Eq, salsa::Update)]
915pub struct ImplItemInfo<'db> {
916    /// The unique identifier of the impl item.
917    pub id: ImplItemId<'db>,
918    /// The feature kind associated with this impl item.
919    pub feature_kind: FeatureKind<'db>,
920}
921
922impl<'db> HasFeatureKind<'db> for ImplItemInfo<'db> {
923    /// Returns the feature kind of this impl item.
924    fn feature_kind(&self) -> &FeatureKind<'db> {
925        &self.feature_kind
926    }
927}
928
929// --- Selectors ---
930
931/// Implementation of [ImplSemantic::impl_semantic_definition_diagnostics].
932fn impl_semantic_definition_diagnostics<'db>(
933    db: &'db dyn Database,
934    impl_def_id: ImplDefId<'db>,
935) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
936    let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
937
938    let Ok(data) = impl_definition_data(db, impl_def_id) else {
939        return Diagnostics::default();
940    };
941
942    // The diagnostics from `priv_impl_definition_data` are only the diagnostics from the impl
943    // level. They should be enriched with the items' diagnostics.
944    diagnostics.extend(data.diagnostics.clone());
945    for impl_function_id in data.function_asts.keys() {
946        diagnostics.extend(db.impl_function_declaration_diagnostics(*impl_function_id));
947        diagnostics.extend(db.impl_function_body_diagnostics(*impl_function_id));
948    }
949    for impl_item_type_id in data.item_type_asts.keys() {
950        diagnostics.extend(db.impl_type_def_semantic_diagnostics(*impl_item_type_id));
951        if let Ok(ty) = db.impl_type_def_resolved_type(*impl_item_type_id) {
952            add_type_based_diagnostics(db, &mut diagnostics, ty, impl_item_type_id.stable_ptr(db));
953        }
954    }
955    for impl_item_constant_id in data.item_constant_asts.keys() {
956        diagnostics.extend(db.impl_constant_def_semantic_diagnostics(*impl_item_constant_id));
957    }
958    for impl_item_impl_id in data.item_impl_asts.keys() {
959        diagnostics.extend(db.impl_impl_def_semantic_diagnostics(*impl_item_impl_id));
960    }
961    for implicit_impl_id in data.implicit_impls_id_by_name.values() {
962        diagnostics
963            .extend(db.implicit_impl_impl_semantic_diagnostics(impl_def_id, *implicit_impl_id));
964    }
965    // Diagnostics for special traits.
966    if diagnostics.error_count == 0 {
967        let concrete_trait =
968            impl_declaration_data(db, impl_def_id).as_ref().unwrap().concrete_trait.unwrap();
969
970        let trait_id = concrete_trait.trait_id(db);
971        if trait_id == db.core_info().deref_trt {
972            deref_impl_diagnostics(db, impl_def_id, concrete_trait, &mut diagnostics);
973        }
974    }
975    diagnostics.build()
976}
977
978/// Query implementation of [ImplSemantic::impl_semantic_definition_diagnostics].
979#[salsa::tracked]
980fn impl_semantic_definition_diagnostics_tracked<'db>(
981    db: &'db dyn Database,
982    impl_def_id: ImplDefId<'db>,
983) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
984    impl_semantic_definition_diagnostics(db, impl_def_id)
985}
986
987/// Represents a chain of dereferences.
988#[derive(Clone, Debug, Eq, PartialEq, salsa::Update)]
989pub struct DerefChain<'db> {
990    pub derefs: Arc<Vec<DerefInfo<'db>>>,
991}
992
993/// Represents a single steps in a deref chain.
994#[derive(Clone, Debug, Eq, PartialEq, salsa::Update)]
995pub struct DerefInfo<'db> {
996    /// The concrete `Deref::deref` or `MutDeref::mderef_mut` function.
997    pub function_id: FunctionId<'db>,
998    /// The mutability of the self argument of the deref function.
999    pub self_mutability: Mutability,
1000    /// The target type of the deref function.
1001    pub target_ty: TypeId<'db>,
1002}
1003
1004/// Cycle handling for  [ImplSemantic::deref_chain].
1005fn deref_chain_cycle<'db>(
1006    _db: &dyn Database,
1007    _id: salsa::Id,
1008    _ty: TypeId<'db>,
1009    _crate_id: CrateId<'db>,
1010    _try_deref_mut: bool,
1011) -> Maybe<DerefChain<'db>> {
1012    // `SemanticDiagnosticKind::DerefCycle` will be reported by `deref_impl_diagnostics`.
1013    Maybe::Err(skip_diagnostic())
1014}
1015
1016/// Query implementation of [ImplSemantic::deref_chain].
1017#[salsa::tracked(cycle_result=deref_chain_cycle, returns(ref))]
1018fn deref_chain<'db>(
1019    db: &'db dyn Database,
1020    ty: TypeId<'db>,
1021    crate_id: CrateId<'db>,
1022    try_deref_mut: bool,
1023) -> Maybe<DerefChain<'db>> {
1024    let mut opt_deref = None;
1025    if try_deref_mut {
1026        opt_deref = try_get_deref_func_and_target(db, ty, crate_id, true)?;
1027    }
1028    let self_mutability = if opt_deref.is_some() {
1029        Mutability::Reference
1030    } else {
1031        opt_deref = try_get_deref_func_and_target(db, ty, crate_id, false)?;
1032        Mutability::Immutable
1033    };
1034
1035    let Some((function_id, target_ty)) = opt_deref else {
1036        return Ok(DerefChain { derefs: Arc::new(vec![]) });
1037    };
1038
1039    let inner_chain = db.deref_chain(target_ty, crate_id, false)?;
1040
1041    Ok(DerefChain {
1042        derefs: Arc::new(
1043            chain!(
1044                [DerefInfo { function_id, target_ty, self_mutability }],
1045                inner_chain.derefs.iter().cloned()
1046            )
1047            .collect(),
1048        ),
1049    })
1050}
1051
1052/// Tries to find the deref function and the target type for a given type and deref trait.
1053fn try_get_deref_func_and_target<'db>(
1054    db: &'db dyn Database,
1055    ty: TypeId<'db>,
1056    crate_id: CrateId<'db>,
1057    is_mut_deref: bool,
1058) -> Result<Option<(FunctionId<'db>, TypeId<'db>)>, DiagnosticAdded> {
1059    let info = db.core_info();
1060    let (deref_trait_id, deref_method) = if is_mut_deref {
1061        (info.deref_mut_trt, info.deref_mut_fn)
1062    } else {
1063        (info.deref_trt, info.deref_fn)
1064    };
1065
1066    let mut lookup_context = ImplLookupContext::new_from_crate(crate_id);
1067    enrich_lookup_context_with_ty(db, ty, &mut lookup_context);
1068    let concrete_trait = ConcreteTraitLongId {
1069        trait_id: deref_trait_id,
1070        generic_args: vec![GenericArgumentId::Type(ty)],
1071    }
1072    .intern(db);
1073    let Ok(deref_impl) = get_impl_at_context(db, lookup_context.intern(db), concrete_trait, None)
1074    else {
1075        return Ok(None);
1076    };
1077    let concrete_impl_id: ConcreteImplId<'db> = match deref_impl.long(db) {
1078        ImplLongId::Concrete(concrete_impl_id) => *concrete_impl_id,
1079        _ => panic!("Expected concrete impl"),
1080    };
1081
1082    let function_id: FunctionId<'db> = FunctionLongId {
1083        function: ConcreteFunction {
1084            generic_function: GenericFunctionId::Impl(ImplGenericFunctionId {
1085                impl_id: deref_impl,
1086                function: deref_method,
1087            }),
1088            generic_args: vec![],
1089        },
1090    }
1091    .intern(db);
1092
1093    let data = impl_definition_data(db, concrete_impl_id.impl_def_id(db)).clone().unwrap();
1094    let mut types_iter = data.item_type_asts.iter();
1095    let (impl_item_type_id, _) = types_iter.next().unwrap();
1096    if types_iter.next().is_some() {
1097        panic!(
1098            "get_impl_based_on_single_impl_type called with an impl that has more than one type"
1099        );
1100    }
1101    let ty = db.impl_type_def_resolved_type(*impl_item_type_id).unwrap();
1102    let substitution: GenericSubstitution<'db> = concrete_impl_id.substitution(db)?;
1103    let ty: TypeId<'db> = substitution.substitute(db, ty).unwrap();
1104
1105    Ok(Some((function_id, ty)))
1106}
1107
1108/// Reports diagnostic for a deref impl.
1109fn deref_impl_diagnostics<'db>(
1110    db: &'db dyn Database,
1111    mut impl_def_id: ImplDefId<'db>,
1112    concrete_trait: ConcreteTraitId<'db>,
1113    diagnostics: &mut SemanticDiagnostics<'db>,
1114) {
1115    let mut visited_impls: OrderedHashSet<ImplDefId<'_>> = OrderedHashSet::default();
1116    let deref_trait_id = concrete_trait.trait_id(db);
1117
1118    let impl_module = impl_def_id.parent_module(db);
1119
1120    let mut impl_in_valid_location = false;
1121    if impl_module == deref_trait_id.parent_module(db) {
1122        impl_in_valid_location = true;
1123    }
1124
1125    let gargs = concrete_trait.generic_args(db);
1126    let deref_ty = extract_matches!(gargs[0], GenericArgumentId::Type);
1127    if let Some(module_id) = deref_ty.long(db).module_id(db)
1128        && module_id == impl_module
1129    {
1130        impl_in_valid_location = true;
1131    }
1132
1133    if !impl_in_valid_location {
1134        diagnostics.report(
1135            impl_def_id.stable_ptr(db),
1136            SemanticDiagnosticKind::MustBeNextToTypeOrTrait { trait_id: deref_trait_id },
1137        );
1138        return;
1139    }
1140
1141    loop {
1142        let Ok(impl_id) = get_impl_based_on_single_impl_type(db, impl_def_id, |ty| {
1143            ConcreteTraitLongId {
1144                trait_id: deref_trait_id,
1145                generic_args: vec![GenericArgumentId::Type(ty)],
1146            }
1147            .intern(db)
1148        }) else {
1149            // Inference errors are handled when the impl is in actual use. In here we only check
1150            // for cycles.
1151            return;
1152        };
1153
1154        impl_def_id = match impl_id.long(db) {
1155            ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.impl_def_id(db),
1156            _ => return,
1157        };
1158
1159        if !visited_impls.insert(impl_def_id) {
1160            let deref_chain = visited_impls
1161                .iter()
1162                .map(|visited_impl| {
1163                    format!("{:?}", db.impl_def_concrete_trait(*visited_impl).unwrap().debug(db))
1164                })
1165                .join(" -> ");
1166            diagnostics.report(
1167                impl_def_id.stable_ptr(db),
1168                SemanticDiagnosticKind::DerefCycle { deref_chain },
1169            );
1170            return;
1171        }
1172    }
1173}
1174
1175/// Assuming that an impl has a single impl type, extracts the type, and then infers another impl
1176/// based on it. If the inference fails, returns the inference error and the impl type definition
1177/// for diagnostics.
1178fn get_impl_based_on_single_impl_type<'db>(
1179    db: &'db dyn Database,
1180    impl_def_id: ImplDefId<'db>,
1181    concrete_trait_id: impl FnOnce(TypeId<'db>) -> ConcreteTraitId<'db>,
1182) -> Result<ImplId<'db>, (InferenceError<'db>, ImplTypeDefId<'db>)> {
1183    let data = impl_definition_data(db, impl_def_id).clone().unwrap();
1184    let mut types_iter = data.item_type_asts.iter();
1185    let (impl_item_type_id, _) = types_iter.next().unwrap();
1186    if types_iter.next().is_some() {
1187        panic!(
1188            "get_impl_based_on_single_impl_type called with an impl that has more than one type"
1189        );
1190    }
1191    let ty = db.impl_type_def_resolved_type(*impl_item_type_id).unwrap();
1192
1193    let module_id = impl_def_id.parent_module(db);
1194    let generic_params = db.impl_def_generic_params(impl_def_id).unwrap();
1195    let generic_params_ids =
1196        generic_params.iter().map(|generic_param| generic_param.id()).collect();
1197    let lookup_context = ImplLookupContext::new(module_id, generic_params_ids, db);
1198    get_impl_at_context(db, lookup_context.intern(db), concrete_trait_id(ty), None)
1199        .map_err(|err| (err, *impl_item_type_id))
1200}
1201
1202/// Query implementation of [ImplSemantic::impl_functions].
1203#[salsa::tracked(returns(ref))]
1204fn impl_functions<'db>(
1205    db: &'db dyn Database,
1206    impl_def_id: ImplDefId<'db>,
1207) -> Maybe<OrderedHashMap<SmolStrId<'db>, ImplFunctionId<'db>>> {
1208    Ok(impl_definition_data(db, impl_def_id)
1209        .maybe_as_ref()?
1210        .function_asts
1211        .keys()
1212        .map(|function_id| {
1213            let function_long_id = function_id.long(db);
1214            (function_long_id.name(db), *function_id)
1215        })
1216        .collect())
1217}
1218
1219/// Query implementation of [PrivImplSemantic::impl_function_by_trait_function].
1220#[salsa::tracked]
1221fn impl_function_by_trait_function<'db>(
1222    db: &'db dyn Database,
1223    impl_def_id: ImplDefId<'db>,
1224    trait_function_id: TraitFunctionId<'db>,
1225) -> Maybe<Option<ImplFunctionId<'db>>> {
1226    let name = trait_function_id.name(db);
1227    for impl_function_id in
1228        impl_definition_data(db, impl_def_id).maybe_as_ref()?.function_asts.keys()
1229    {
1230        if impl_function_id.long(db).name(db) == name {
1231            return Ok(Some(*impl_function_id));
1232        }
1233    }
1234    Ok(None)
1235}
1236
1237/// Implementation of [ImplSemantic::impl_item_info_by_name].
1238fn impl_item_info_by_name<'db>(
1239    db: &'db dyn Database,
1240    impl_def_id: ImplDefId<'db>,
1241    name: SmolStrId<'db>,
1242) -> Maybe<Option<ImplItemInfo<'db>>> {
1243    let impl_definition_data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
1244    Ok(impl_definition_data.get_impl_item_info(name))
1245}
1246
1247/// Query implementation of [ImplSemantic::impl_item_info_by_name].
1248#[salsa::tracked]
1249fn impl_item_info_by_name_tracked<'db>(
1250    db: &'db dyn Database,
1251    impl_def_id: ImplDefId<'db>,
1252    name: SmolStrId<'db>,
1253) -> Maybe<Option<ImplItemInfo<'db>>> {
1254    impl_item_info_by_name(db, impl_def_id, name)
1255}
1256
1257/// Query implementation of [ImplSemantic::impl_all_used_uses].
1258#[salsa::tracked(returns(ref))]
1259fn impl_all_used_uses<'db>(
1260    db: &'db dyn Database,
1261    impl_def_id: ImplDefId<'db>,
1262) -> Maybe<OrderedHashSet<UseId<'db>>> {
1263    let mut all_used_uses = db.impl_def_resolver_data(impl_def_id)?.used_uses.clone();
1264    let data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
1265    for item in data.item_id_by_name.values() {
1266        for resolver_data in get_resolver_data_options(LookupItemId::ImplItem(item.id), db) {
1267            all_used_uses.extend(resolver_data.used_uses.iter().cloned());
1268        }
1269    }
1270    Ok(all_used_uses)
1271}
1272
1273/// Query implementation of [PrivImplSemantic::impl_type_by_id].
1274#[salsa::tracked]
1275fn impl_type_by_id<'db>(
1276    db: &'db dyn Database,
1277    impl_type_id: ImplTypeDefId<'db>,
1278) -> Maybe<ast::ItemTypeAlias<'db>> {
1279    let impl_types = db.impl_types(impl_type_id.impl_def_id(db))?;
1280    impl_types.get(&impl_type_id).cloned().ok_or_else(skip_diagnostic)
1281}
1282
1283/// Implementation of [ImplSemantic::impl_type_by_trait_type].
1284fn impl_type_by_trait_type<'db>(
1285    db: &'db dyn Database,
1286    impl_def_id: ImplDefId<'db>,
1287    trait_type_id: TraitTypeId<'db>,
1288) -> Maybe<ImplTypeDefId<'db>> {
1289    if trait_type_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1290        unreachable!(
1291            "impl_type_by_trait_type called with a trait type that does not belong to the impl's \
1292             trait"
1293        )
1294    }
1295
1296    let name = trait_type_id.name(db);
1297    // If the trait type's name is not found, then a missing item diagnostic is reported.
1298    db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1299        Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Type)),
1300        None => Err(skip_diagnostic()),
1301    })
1302}
1303
1304/// Query implementation of [ImplSemantic::impl_type_by_trait_type].
1305#[salsa::tracked]
1306fn impl_type_by_trait_type_tracked<'db>(
1307    db: &'db dyn Database,
1308    impl_def_id: ImplDefId<'db>,
1309    trait_type_id: TraitTypeId<'db>,
1310) -> Maybe<ImplTypeDefId<'db>> {
1311    impl_type_by_trait_type(db, impl_def_id, trait_type_id)
1312}
1313
1314/// Query implementation of [PrivImplSemantic::impl_constant_by_trait_constant].
1315#[salsa::tracked]
1316fn impl_constant_by_trait_constant<'db>(
1317    db: &'db dyn Database,
1318    impl_def_id: ImplDefId<'db>,
1319    trait_constant_id: TraitConstantId<'db>,
1320) -> Maybe<ImplConstantDefId<'db>> {
1321    if trait_constant_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1322        unreachable!(
1323            "impl_constant_by_trait_constant called with a trait constant that does not belong to \
1324             the impl's trait"
1325        )
1326    }
1327
1328    let name = trait_constant_id.name(db);
1329    // If the trait constant's name is not found, then a missing item diagnostic is reported.
1330    db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1331        Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Constant)),
1332        None => Err(skip_diagnostic()),
1333    })
1334}
1335
1336/// Query implementation of [PrivImplSemantic::impl_impl_by_id].
1337#[salsa::tracked]
1338fn impl_impl_by_id<'db>(
1339    db: &'db dyn Database,
1340    impl_impl_id: ImplImplDefId<'db>,
1341) -> Maybe<ast::ItemImplAlias<'db>> {
1342    let impl_impls = db.impl_impls(impl_impl_id.impl_def_id(db))?;
1343    impl_impls.get(&impl_impl_id).cloned().ok_or_else(skip_diagnostic)
1344}
1345
1346/// Query implementation of [PrivImplSemantic::impl_impl_by_trait_impl].
1347#[salsa::tracked]
1348fn impl_impl_by_trait_impl<'db>(
1349    db: &'db dyn Database,
1350    impl_def_id: ImplDefId<'db>,
1351    trait_impl_id: TraitImplId<'db>,
1352) -> Maybe<ImplImplDefId<'db>> {
1353    if trait_impl_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1354        unreachable!(
1355            "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1356             trait"
1357        )
1358    }
1359
1360    let name = trait_impl_id.name(db);
1361    // If the trait impl's name is not found, then a missing item diagnostic is reported.
1362    db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1363        Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Impl)),
1364        None => Err(skip_diagnostic()),
1365    })
1366}
1367
1368/// Query implementation of [PrivImplSemantic::is_implicit_impl_impl].
1369#[salsa::tracked]
1370fn is_implicit_impl_impl<'db>(
1371    db: &'db dyn Database,
1372    impl_def_id: ImplDefId<'db>,
1373    trait_impl_id: TraitImplId<'db>,
1374) -> Maybe<bool> {
1375    if trait_impl_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1376        unreachable!(
1377            "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1378             trait"
1379        )
1380    }
1381
1382    let name = trait_impl_id.name(db);
1383    // If the trait impl's name is not found, then a missing item diagnostic is reported.
1384    Ok(db.impl_implicit_impl_by_name(impl_def_id, name)?.is_some())
1385}
1386
1387// --- Computation ---
1388
1389/// Returns data about an impl definition.
1390#[salsa::tracked(returns(ref))]
1391fn impl_definition_data<'db>(
1392    db: &'db dyn Database,
1393    impl_def_id: ImplDefId<'db>,
1394) -> Maybe<ImplDefinitionData<'db>> {
1395    let module_id = impl_def_id.parent_module(db);
1396    let mut diagnostics = SemanticDiagnostics::new(module_id);
1397
1398    let generic_params =
1399        impl_def_generic_params_data(db, impl_def_id).maybe_as_ref()?.generic_params.clone();
1400    let concrete_trait = impl_declaration_data(db, impl_def_id).maybe_as_ref()?.concrete_trait?;
1401
1402    let impl_ast = db.module_impl_by_id(impl_def_id)?;
1403
1404    let generic_params_ids =
1405        generic_params.iter().map(|generic_param| generic_param.id()).collect();
1406    let lookup_context = ImplLookupContext::new(module_id, generic_params_ids, db).intern(db);
1407    check_special_impls(
1408        db,
1409        &mut diagnostics,
1410        lookup_context,
1411        concrete_trait,
1412        impl_ast.stable_ptr(db).untyped(),
1413    )
1414    // Ignore the result.
1415    .ok();
1416
1417    let mut function_asts = OrderedHashMap::default();
1418    let mut item_type_asts = OrderedHashMap::default();
1419    let mut item_constant_asts = OrderedHashMap::default();
1420    let mut item_impl_asts = OrderedHashMap::default();
1421    let mut item_id_by_name = OrderedHashMap::default();
1422
1423    if let MaybeImplBody::Some(body) = impl_ast.body(db) {
1424        for item in body.items(db).elements(db) {
1425            match item {
1426                ImplItem::Module(module) => {
1427                    report_invalid_impl_item(db, &mut diagnostics, module.module_kw(db))
1428                }
1429
1430                ImplItem::Use(use_item) => {
1431                    report_invalid_impl_item(db, &mut diagnostics, use_item.use_kw(db))
1432                }
1433                ImplItem::ExternFunction(extern_func) => {
1434                    report_invalid_impl_item(db, &mut diagnostics, extern_func.extern_kw(db))
1435                }
1436                ImplItem::ExternType(extern_type) => {
1437                    report_invalid_impl_item(db, &mut diagnostics, extern_type.extern_kw(db))
1438                }
1439                ImplItem::Trait(trt) => {
1440                    report_invalid_impl_item(db, &mut diagnostics, trt.trait_kw(db))
1441                }
1442                ImplItem::Struct(structure) => {
1443                    report_invalid_impl_item(db, &mut diagnostics, structure.struct_kw(db))
1444                }
1445                ImplItem::Enum(enm) => {
1446                    report_invalid_impl_item(db, &mut diagnostics, enm.enum_kw(db))
1447                }
1448                ImplItem::Function(func) => {
1449                    let impl_function_id =
1450                        ImplFunctionLongId(module_id, func.stable_ptr(db)).intern(db);
1451                    let name_node = func.declaration(db).name(db);
1452                    let name = name_node.text(db);
1453                    let feature_kind =
1454                        FeatureKind::from_ast(db, &mut diagnostics, &func.attributes(db));
1455                    if item_id_by_name
1456                        .insert(
1457                            name,
1458                            ImplItemInfo {
1459                                id: ImplItemId::Function(impl_function_id),
1460                                feature_kind,
1461                            },
1462                        )
1463                        .is_some()
1464                    {
1465                        diagnostics
1466                            .report(name_node.stable_ptr(db), NameDefinedMultipleTimes(name));
1467                    }
1468                    function_asts.insert(impl_function_id, func);
1469                }
1470                ImplItem::Type(ty) => {
1471                    let impl_type_id = ImplTypeDefLongId(module_id, ty.stable_ptr(db)).intern(db);
1472                    let name_node = ty.name(db);
1473                    let name = name_node.text(db);
1474                    let feature_kind =
1475                        FeatureKind::from_ast(db, &mut diagnostics, &ty.attributes(db));
1476                    if item_id_by_name
1477                        .insert(
1478                            name,
1479                            ImplItemInfo { id: ImplItemId::Type(impl_type_id), feature_kind },
1480                        )
1481                        .is_some()
1482                    {
1483                        diagnostics
1484                            .report(name_node.stable_ptr(db), NameDefinedMultipleTimes(name));
1485                    }
1486                    item_type_asts.insert(impl_type_id, ty);
1487                }
1488                ImplItem::Constant(constant) => {
1489                    let impl_constant_id =
1490                        ImplConstantDefLongId(module_id, constant.stable_ptr(db)).intern(db);
1491                    let name_node = constant.name(db);
1492                    let name = name_node.text(db);
1493                    let feature_kind =
1494                        FeatureKind::from_ast(db, &mut diagnostics, &constant.attributes(db));
1495                    if item_id_by_name
1496                        .insert(
1497                            name,
1498                            ImplItemInfo {
1499                                id: ImplItemId::Constant(impl_constant_id),
1500                                feature_kind,
1501                            },
1502                        )
1503                        .is_some()
1504                    {
1505                        diagnostics.report(
1506                            name_node.stable_ptr(db),
1507                            SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1508                        );
1509                    }
1510                    item_constant_asts.insert(impl_constant_id, constant);
1511                }
1512                ImplItem::Impl(imp) => {
1513                    let impl_impl_id = ImplImplDefLongId(module_id, imp.stable_ptr(db)).intern(db);
1514                    let name_node = imp.name(db);
1515                    let name = name_node.text(db);
1516                    let feature_kind =
1517                        FeatureKind::from_ast(db, &mut diagnostics, &imp.attributes(db));
1518                    if item_id_by_name
1519                        .insert(
1520                            name,
1521                            ImplItemInfo { id: ImplItemId::Impl(impl_impl_id), feature_kind },
1522                        )
1523                        .is_some()
1524                    {
1525                        diagnostics.report(
1526                            name_node.stable_ptr(db),
1527                            SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1528                        );
1529                    }
1530                    item_impl_asts.insert(impl_impl_id, imp);
1531                }
1532                // Report nothing, a parser diagnostic is reported.
1533                ImplItem::Missing(_) => {}
1534            }
1535        }
1536    }
1537
1538    let mut implicit_impls_id_by_name = OrderedHashMap::default();
1539
1540    let trait_id = concrete_trait.long(db).trait_id;
1541    for (name, trait_impl_id) in db.trait_impls(trait_id)?.iter() {
1542        if item_id_by_name.contains_key(name) {
1543            continue;
1544        }
1545        implicit_impls_id_by_name.insert(*name, *trait_impl_id);
1546    }
1547
1548    // It is later verified that all items in this impl match items from `concrete_trait`.
1549    // To ensure exact match (up to trait functions with default implementation), it is sufficient
1550    // to verify here that all items in `concrete_trait` appear in this impl.
1551    let impl_item_names: OrderedHashSet<SmolStrId<'db>> = item_id_by_name.keys().copied().collect();
1552
1553    let trait_required_item_names = db.trait_required_item_names(trait_id)?;
1554    let missing_items_in_impl =
1555        trait_required_item_names.difference(&impl_item_names).cloned().collect::<Vec<_>>();
1556    if !missing_items_in_impl.is_empty() {
1557        diagnostics.report(
1558            // TODO(yuval): change this to point to impl declaration (need to add ImplDeclaration
1559            // in cairo_spec).
1560            // TODO(TomerStarkware): make sure we do not report missing if the trait item is
1561            // unsupported in impl.
1562            impl_ast.name(db).stable_ptr(db),
1563            SemanticDiagnosticKind::MissingItemsInImpl(missing_items_in_impl),
1564        );
1565    }
1566
1567    Ok(ImplDefinitionData {
1568        diagnostics: diagnostics.build(),
1569        function_asts,
1570        item_type_asts,
1571        item_id_by_name,
1572        item_constant_asts,
1573        item_impl_asts,
1574        implicit_impls_id_by_name,
1575    })
1576}
1577
1578/// A helper function to report diagnostics of items in an impl (used in
1579/// priv_impl_definition_data).
1580fn report_invalid_impl_item<'db, Terminal: syntax::node::Terminal<'db>>(
1581    db: &'db dyn Database,
1582    diagnostics: &mut SemanticDiagnostics<'db>,
1583    kw_terminal: Terminal,
1584) {
1585    diagnostics
1586        .report(kw_terminal.as_syntax_node().stable_ptr(db), InvalidImplItem(kw_terminal.text(db)));
1587}
1588
1589/// Handle special cases such as Copy and Drop checking.
1590fn check_special_impls<'db>(
1591    db: &'db dyn Database,
1592    diagnostics: &mut SemanticDiagnostics<'db>,
1593    lookup_context: ImplLookupContextId<'db>,
1594    concrete_trait: ConcreteTraitId<'db>,
1595    stable_ptr: SyntaxStablePtrId<'db>,
1596) -> Maybe<()> {
1597    let ConcreteTraitLongId { trait_id, generic_args } = concrete_trait.long(db);
1598    let info = db.core_info();
1599    let copy = info.copy_trt;
1600    let drop = info.drop_trt;
1601
1602    if *trait_id == copy {
1603        let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1604        for inference_error in tys
1605            .into_iter()
1606            .map(|ty| db.type_info(lookup_context, ty))
1607            .flat_map(|info| info.copyable.err())
1608        {
1609            if matches!(
1610                inference_error,
1611                InferenceError::Ambiguity(Ambiguity::MultipleImplsFound { .. })
1612            ) {
1613                // Having multiple drop implementations for a member is not an actual error.
1614                continue;
1615            }
1616            return Err(diagnostics.report(stable_ptr, InvalidCopyTraitImpl(inference_error)));
1617        }
1618    }
1619    if *trait_id == drop {
1620        let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1621        for inference_error in tys
1622            .into_iter()
1623            .map(|ty| db.type_info(lookup_context, ty))
1624            .flat_map(|info| info.droppable.err())
1625        {
1626            if matches!(
1627                inference_error,
1628                InferenceError::Ambiguity(Ambiguity::MultipleImplsFound { .. })
1629            ) {
1630                // Having multiple drop implementations for a member is not an actual error.
1631                continue;
1632            }
1633            return Err(diagnostics.report(stable_ptr, InvalidDropTraitImpl(inference_error)));
1634        }
1635    }
1636
1637    Ok(())
1638}
1639
1640/// Retrieves all the inner types (members of a struct / tuple or variants of an enum).
1641///
1642/// These are the types that are required to implement some trait,
1643/// in order for the original type to be able to implement this trait.
1644///
1645/// For example, a struct containing a type T can implement Drop only if T implements Drop.
1646fn get_inner_types<'db>(db: &'db dyn Database, ty: TypeId<'db>) -> Maybe<Vec<TypeId<'db>>> {
1647    Ok(match ty.long(db) {
1648        TypeLongId::Concrete(concrete_type_id) => {
1649            // Look for Copy and Drop trait in the defining module.
1650            match concrete_type_id {
1651                crate::ConcreteTypeId::Struct(concrete_struct_id) => db
1652                    .concrete_struct_members(*concrete_struct_id)?
1653                    .values()
1654                    .map(|member| member.ty)
1655                    .collect(),
1656                crate::ConcreteTypeId::Enum(concrete_enum_id) => db
1657                    .concrete_enum_variants(*concrete_enum_id)?
1658                    .into_iter()
1659                    .map(|variant| variant.ty)
1660                    .collect(),
1661                crate::ConcreteTypeId::Extern(_) => vec![],
1662            }
1663        }
1664        TypeLongId::Tuple(tys) => tys.to_vec(),
1665        TypeLongId::Snapshot(_) | TypeLongId::Closure(_) => vec![],
1666        TypeLongId::GenericParameter(_) => {
1667            return Err(skip_diagnostic());
1668        }
1669        TypeLongId::Var(_) | TypeLongId::ImplType(_) => {
1670            panic!("Types should be fully resolved at this point.")
1671        }
1672        TypeLongId::Coupon(_) => vec![],
1673        TypeLongId::FixedSizeArray { type_id, .. } => vec![*type_id],
1674        TypeLongId::Missing(diag_added) => {
1675            return Err(*diag_added);
1676        }
1677    })
1678}
1679
1680// === Trait Filter ===
1681
1682/// A filter for trait lookup that is not based on current inference state. This is
1683/// used for caching queries.
1684#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1685pub struct TraitFilter<'db> {
1686    pub trait_id: TraitId<'db>,
1687    /// The filter on the generic arguments.
1688    pub generics_filter: GenericsHeadFilter<'db>,
1689}
1690
1691/// A lookup filter on generic arguments that is not based on current inference state.
1692/// This is used for caching queries.
1693#[derive(Clone, Debug, Hash, PartialEq, Eq, salsa::Update)]
1694pub enum GenericsHeadFilter<'db> {
1695    /// No filter is applied. When nothing is known about the generics, this will lead to a
1696    /// wider search.
1697    NoFilter,
1698    /// Generics exists and the first generic parameter has a filter.
1699    /// This is usually enough to considerably reduce the number of searched items.
1700    FirstGenericFilter(GenericArgumentHead<'db>),
1701    /// Generics must not exist.
1702    NoGenerics,
1703}
1704
1705#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HeapSize, salsa::Update)]
1706pub struct UninferredImplById<'db>(pub UninferredImpl<'db>);
1707impl<'db> Ord for UninferredImplById<'db> {
1708    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1709        match (&self.0, &other.0) {
1710            (UninferredImpl::Def(impl_def_id), UninferredImpl::Def(other_impl_def_id)) => {
1711                impl_def_id.get_internal_id().cmp(&other_impl_def_id.get_internal_id())
1712            }
1713            (
1714                UninferredImpl::ImplAlias(impl_alias_id),
1715                UninferredImpl::ImplAlias(other_impl_alias_id),
1716            ) => impl_alias_id.get_internal_id().cmp(&other_impl_alias_id.get_internal_id()),
1717            (UninferredImpl::GenericParam(param), UninferredImpl::GenericParam(other_param)) => {
1718                param.get_internal_id().cmp(&other_param.get_internal_id())
1719            }
1720            (
1721                UninferredImpl::ImplImpl(impl_impl_id),
1722                UninferredImpl::ImplImpl(other_impl_impl_id),
1723            ) => {
1724                if impl_impl_id.impl_id() == other_impl_impl_id.impl_id() {
1725                    impl_impl_id
1726                        .trait_impl_id()
1727                        .get_internal_id()
1728                        .cmp(&other_impl_impl_id.trait_impl_id().get_internal_id())
1729                } else {
1730                    impl_impl_id
1731                        .impl_id()
1732                        .get_internal_id()
1733                        .cmp(&other_impl_impl_id.impl_id().get_internal_id())
1734                }
1735            }
1736            (
1737                UninferredImpl::GeneratedImpl(generated_impl),
1738                UninferredImpl::GeneratedImpl(other_generated_impl),
1739            ) => generated_impl.get_internal_id().cmp(&other_generated_impl.get_internal_id()),
1740            (UninferredImpl::Def(_), _) => std::cmp::Ordering::Less,
1741            (_, UninferredImpl::Def(_)) => std::cmp::Ordering::Greater,
1742            (UninferredImpl::ImplAlias(_), _) => std::cmp::Ordering::Less,
1743            (_, UninferredImpl::ImplAlias(_)) => std::cmp::Ordering::Greater,
1744            (UninferredImpl::GenericParam(_), _) => std::cmp::Ordering::Less,
1745            (_, UninferredImpl::GenericParam(_)) => std::cmp::Ordering::Greater,
1746            (UninferredImpl::ImplImpl(_), _) => std::cmp::Ordering::Less,
1747            (_, UninferredImpl::ImplImpl(_)) => std::cmp::Ordering::Greater,
1748        }
1749    }
1750}
1751impl<'db> PartialOrd for UninferredImplById<'db> {
1752    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1753        Some(self.cmp(other))
1754    }
1755}
1756impl<'db> From<UninferredImpl<'db>> for UninferredImplById<'db> {
1757    fn from(uninferred_impl: UninferredImpl<'db>) -> Self {
1758        UninferredImplById(uninferred_impl)
1759    }
1760}
1761
1762#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, salsa::Update, HeapSize)]
1763#[debug_db(dyn Database)]
1764pub struct ImplLookupContext<'db> {
1765    pub crate_id: CrateId<'db>,
1766    pub generic_params: Vec<GenericParamId<'db>>,
1767    pub inner_impls: BTreeSet<UninferredImplById<'db>>,
1768    pub negative_impls: Vec<GenericParamId<'db>>,
1769}
1770
1771define_short_id!(ImplLookupContextId, ImplLookupContext<'db>);
1772
1773impl<'db> ImplLookupContext<'db> {
1774    /// Creates a new [ImplLookupContext] from a [CrateId].
1775    pub fn new_from_crate(crate_id: CrateId<'db>) -> Self {
1776        Self {
1777            crate_id,
1778            generic_params: Default::default(),
1779            inner_impls: Default::default(),
1780            negative_impls: Default::default(),
1781        }
1782    }
1783    /// Creates a new [ImplLookupContext] from a [TypeId] with the crate being the crate of the
1784    /// type's module.
1785    pub fn new_from_type(ty: TypeId<'db>, db: &'db dyn Database) -> Self {
1786        Self::new_from_crate(
1787            ty.long(db)
1788                .module_id(db)
1789                .map(|m| m.owning_crate(db))
1790                .unwrap_or_else(|| db.core_crate()),
1791        )
1792    }
1793    /// Creates a new [ImplLookupContext] from a [ModuleId].
1794    pub fn new(
1795        module_id: ModuleId<'db>,
1796        generic_params: Vec<GenericParamId<'db>>,
1797        db: &'db dyn Database,
1798    ) -> ImplLookupContext<'db> {
1799        let crate_id = module_id.owning_crate(db);
1800        let negative_impls = generic_params
1801            .iter()
1802            .filter(|generic_param_id| matches!(generic_param_id.kind(db), GenericKind::NegImpl))
1803            .copied()
1804            .collect_vec();
1805        let generic_params = generic_params
1806            .iter()
1807            .filter(|generic_param_id| {
1808                if !matches!(generic_param_id.kind(db), GenericKind::Impl) {
1809                    return false;
1810                }
1811
1812                let uninferred_impl = UninferredImpl::GenericParam(**generic_param_id);
1813
1814                let Ok(trait_id) = uninferred_impl.trait_id(db) else {
1815                    return true;
1816                };
1817                let Some(set) = db.crate_global_impls(crate_id).get(&trait_id) else {
1818                    return true;
1819                };
1820                let uninferred_impl: UninferredImplById<'db> = uninferred_impl.into();
1821                if set.contains(&uninferred_impl) {
1822                    return false;
1823                };
1824                true
1825            })
1826            .copied()
1827            .collect_vec();
1828        let mut res = Self {
1829            crate_id,
1830            generic_params: generic_params
1831                .clone()
1832                .into_iter()
1833                .filter(|id| id.long(db).has_type_constraints_syntax(db))
1834                .collect_vec(),
1835            inner_impls: BTreeSet::from_iter(
1836                generic_params.into_iter().map(|id| UninferredImpl::GenericParam(id).into()),
1837            ),
1838            negative_impls,
1839        };
1840        res.insert_module(module_id, db);
1841        res
1842    }
1843    pub fn insert_lookup_scope(&mut self, db: &'db dyn Database, imp: &UninferredImpl<'db>) {
1844        match imp {
1845            UninferredImpl::Def(impl_def_id) => {
1846                self.insert_module(impl_def_id.parent_module(db), db)
1847            }
1848            UninferredImpl::ImplAlias(impl_alias_id) => {
1849                self.insert_module(impl_alias_id.parent_module(db), db)
1850            }
1851            UninferredImpl::GenericParam(param) => self.insert_module(param.parent_module(db), db),
1852            UninferredImpl::ImplImpl(impl_impl_id) => self.insert_impl(impl_impl_id.impl_id, db),
1853            UninferredImpl::GeneratedImpl(_) => {
1854                // GeneratedImpls do not extend the lookup context.
1855            }
1856        };
1857    }
1858    /// Inserts a module into the lookup context, extending the inner impls with the module's
1859    /// impls.
1860    pub fn insert_module(&mut self, module_id: ModuleId<'db>, db: &'db dyn Database) {
1861        // Make sure to use the module as perceived by the user, as it contains all the macros.
1862        let module_id = db.module_perceived_module(module_id);
1863        let crate_global_impls = db.crate_global_impls(self.crate_id);
1864        if let Ok(module_impls) = db.module_global_impls((), module_id) {
1865            module_impls.locals.iter().for_each(|imp| {
1866                if let Ok(trait_id) = imp.0.trait_id(db)
1867                    && let Some(set) = crate_global_impls.get(&trait_id)
1868                    && set.contains(imp)
1869                {
1870                    return;
1871                }
1872
1873                self.inner_impls.insert(*imp);
1874            });
1875            // If the module is not in the lookup context's crate, we add its global impls
1876            if !crate_dependencies(db, self.crate_id).contains(&module_id.owning_crate(db)) {
1877                module_impls.globals_by_trait.iter().for_each(|(_, imps)| {
1878                    imps.iter().for_each(|imp| {
1879                        if let Ok(trait_id) = imp.0.trait_id(db)
1880                            && let Some(set) = crate_global_impls.get(&trait_id)
1881                            && set.contains(imp)
1882                        {
1883                            return;
1884                        }
1885
1886                        self.inner_impls.insert(*imp);
1887                    });
1888                });
1889            }
1890        }
1891    }
1892
1893    /// Inserts an impl into the lookup context, extending the inner impls with the impl's
1894    /// trait impls.
1895    pub fn insert_impl(&mut self, impl_id: ImplId<'db>, db: &'db dyn Database) {
1896        let mut uninferred_impls = Vec::new();
1897        let Ok(concrete_trait) = impl_id.concrete_trait(db) else {
1898            return;
1899        };
1900        let Ok(trait_impls) = db.trait_impls(concrete_trait.trait_id(db)) else {
1901            return;
1902        };
1903        for (_, trait_impl_id) in trait_impls.iter() {
1904            uninferred_impls.push(UninferredImpl::ImplImpl(ImplImplId::new(
1905                impl_id,
1906                *trait_impl_id,
1907                db,
1908            )));
1909        }
1910        for uninferred_impl in uninferred_impls {
1911            self.inner_impls.insert(uninferred_impl.into());
1912        }
1913    }
1914
1915    /// Strips the lookup context of all impls that are not reachable in the dependency graph from
1916    /// the given trait.
1917    pub fn strip_for_trait_id(&mut self, db: &dyn Database, trait_id: TraitId<'db>) {
1918        let deps = db.reachable_trait_dependencies(trait_id, self.crate_id);
1919        let type_eq_trt = db.core_info().type_eq_trt;
1920        self.inner_impls.retain(|impl_by_id| {
1921            if let Ok(impl_trait_id) = impl_by_id.0.trait_id(db) {
1922                return trait_id == impl_trait_id
1923                    || trait_id == type_eq_trt
1924                    || deps.contains(&impl_trait_id);
1925            }
1926
1927            false
1928        });
1929    }
1930}
1931
1932/// A candidate impl for later inference.
1933#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject, HeapSize, salsa::Update)]
1934pub enum UninferredImpl<'db> {
1935    Def(ImplDefId<'db>),
1936    ImplAlias(ImplAliasId<'db>),
1937    GenericParam(GenericParamId<'db>),
1938    ImplImpl(ImplImplId<'db>),
1939    GeneratedImpl(UninferredGeneratedImplId<'db>),
1940}
1941impl<'db> UninferredImpl<'db> {
1942    pub fn concrete_trait(&self, db: &'db dyn Database) -> Maybe<ConcreteTraitId<'db>> {
1943        match self {
1944            UninferredImpl::Def(impl_def_id) => db.impl_def_concrete_trait(*impl_def_id),
1945            UninferredImpl::ImplAlias(impl_alias_id) => {
1946                let impl_id = db.impl_alias_resolved_impl(*impl_alias_id)?;
1947                impl_id.concrete_trait(db)
1948            }
1949            UninferredImpl::GenericParam(param) => {
1950                let param =
1951                    extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
1952                param.concrete_trait
1953            }
1954            UninferredImpl::ImplImpl(impl_impl_id) => db.impl_impl_concrete_trait(*impl_impl_id),
1955            UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
1956        }
1957    }
1958
1959    fn trait_id(&self, db: &'db dyn Database) -> Maybe<TraitId<'db>> {
1960        match self {
1961            UninferredImpl::Def(impl_def_id) => db.impl_def_trait(*impl_def_id),
1962            UninferredImpl::ImplAlias(impl_alias_id) => {
1963                let impl_def_id = db.impl_alias_impl_def(*impl_alias_id)?;
1964                db.impl_def_trait(impl_def_id)
1965            }
1966            UninferredImpl::GenericParam(param) => db.generic_impl_param_trait(*param),
1967            UninferredImpl::ImplImpl(impl_impl_id) => db
1968                .impl_impl_concrete_trait(*impl_impl_id)
1969                .map(|concrete_trait| concrete_trait.trait_id(db)),
1970            UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.trait_id(db)),
1971        }
1972    }
1973
1974    /// Returns the shallow generic arguments of the concrete trait of this impl.
1975    fn trait_shallow_generic_args(
1976        &self,
1977        db: &'db dyn Database,
1978    ) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
1979        match self {
1980            UninferredImpl::Def(impl_def_id) => {
1981                db.impl_def_shallow_trait_generic_args(*impl_def_id)
1982            }
1983
1984            UninferredImpl::ImplAlias(impl_alias_id) => {
1985                db.impl_alias_trait_generic_args(*impl_alias_id)
1986            }
1987            UninferredImpl::GenericParam(param) => {
1988                db.generic_impl_param_shallow_trait_generic_args(*param)
1989            }
1990            // Todo(TomerStarkware): Implement this for ImplImpl and GeneratedImpl.
1991            UninferredImpl::ImplImpl(_impl_impl_id) => Ok(&[]),
1992            UninferredImpl::GeneratedImpl(_generated_impl) => Ok(&[]),
1993        }
1994    }
1995}
1996
1997impl<'db> DebugWithDb<'db> for UninferredImpl<'db> {
1998    type Db = dyn Database;
1999
2000    fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
2001        match self {
2002            UninferredImpl::Def(impl_def) => write!(f, "{:?}", impl_def.full_path(db)),
2003            UninferredImpl::ImplAlias(impl_alias) => {
2004                write!(f, "{:?}", impl_alias.full_path(db))
2005            }
2006            UninferredImpl::GenericParam(param) => {
2007                write!(
2008                    f,
2009                    "generic param {}",
2010                    param.name(db).map(|name| name.long(db).as_str()).unwrap_or("_")
2011                )
2012            }
2013            UninferredImpl::ImplImpl(impl_impl) => impl_impl.fmt(f, db),
2014            UninferredImpl::GeneratedImpl(generated_impl) => generated_impl.fmt(f, db),
2015        }
2016    }
2017}
2018
2019define_short_id!(UninferredGeneratedImplId, UninferredGeneratedImplLongId<'db>);
2020impl<'db> UnstableSalsaId for UninferredGeneratedImplId<'db> {
2021    fn get_internal_id(&self) -> salsa::Id {
2022        self.0
2023    }
2024}
2025semantic_object_for_id!(UninferredGeneratedImplId, UninferredGeneratedImplLongId<'a>);
2026
2027impl<'db> UninferredGeneratedImplId<'db> {
2028    pub fn concrete_trait(self, db: &'db dyn Database) -> ConcreteTraitId<'db> {
2029        self.long(db).concrete_trait
2030    }
2031
2032    pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
2033        self.concrete_trait(db).trait_id(db)
2034    }
2035}
2036
2037/// Generated impls before inference, see GeneratedImplLongId for more details.
2038#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update, HeapSize)]
2039pub struct UninferredGeneratedImplLongId<'db> {
2040    pub concrete_trait: ConcreteTraitId<'db>,
2041    pub generic_params: Vec<GenericParam<'db>>,
2042    pub impl_items: GeneratedImplItems<'db>,
2043}
2044
2045impl<'db> DebugWithDb<'db> for UninferredGeneratedImplLongId<'db> {
2046    type Db = dyn Database;
2047
2048    fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
2049        write!(f, "Generated {:?}", self.concrete_trait.debug(db))
2050    }
2051}
2052
2053/// Query implementation of [ImplSemantic::trait_candidate_by_head].
2054#[salsa::tracked(returns(ref))]
2055fn trait_candidate_by_head<'db>(
2056    db: &'db dyn Database,
2057    crate_id: CrateId<'db>,
2058    trait_id: TraitId<'db>,
2059) -> OrderedHashMap<GenericsHeadFilter<'db>, OrderedHashSet<UninferredImplById<'db>>> {
2060    let mut res: OrderedHashMap<GenericsHeadFilter<'db>, OrderedHashSet<UninferredImplById<'db>>> =
2061        OrderedHashMap::default();
2062
2063    if let Some(candidates) = db.crate_global_impls(crate_id).get(&trait_id) {
2064        for candidate in candidates.iter() {
2065            let Ok(shallow_generic_args) = candidate.0.trait_shallow_generic_args(db) else {
2066                continue;
2067            };
2068            let Ok(trait_params) = db.trait_generic_params(trait_id) else {
2069                continue;
2070            };
2071            let Some(first_param) = trait_params.first() else {
2072                res.entry(GenericsHeadFilter::NoGenerics).or_default().insert(*candidate);
2073                continue;
2074            };
2075
2076            // look for the generic argument that matches the first generic parameter of the trait.
2077            let shallow_arg =
2078                shallow_generic_args.iter().find(|(param, _)| *param == first_param.id());
2079            if let Some(first_generic_head) = shallow_arg.map(|(_, arg)| arg.head()) {
2080                if !matches!(candidate.0, UninferredImpl::GenericParam(_)) {
2081                    let mut type_head = first_generic_head.clone();
2082                    while let TypeHead::Snapshot(inner) = type_head {
2083                        type_head = *inner;
2084                    }
2085                    if matches!(type_head, TypeHead::Generic(_)) {
2086                        res.entry(GenericsHeadFilter::NoFilter).or_default().insert(*candidate);
2087                        continue;
2088                    }
2089                }
2090                res.entry(GenericsHeadFilter::FirstGenericFilter(GenericArgumentHead::Type(
2091                    first_generic_head,
2092                )))
2093                .or_default()
2094                .insert(*candidate);
2095            } else {
2096                res.entry(GenericsHeadFilter::NoFilter).or_default().insert(*candidate);
2097            }
2098        }
2099    }
2100    res
2101}
2102
2103/// Finds all the implementations of a concrete trait, in a specific lookup context.
2104pub fn find_candidates_at_context<'db>(
2105    db: &'db dyn Database,
2106    lookup_context: ImplLookupContextId<'db>,
2107    filter: TraitFilter<'db>,
2108) -> Maybe<OrderedHashSet<UninferredImplById<'db>>> {
2109    let mut res = OrderedHashSet::default();
2110    let lookup = lookup_context.long(db);
2111    let crate_id = lookup.crate_id;
2112    let locals = lookup
2113        .inner_impls
2114        .iter()
2115        .filter(|uninferred_impl| {
2116            let Ok(trait_id) = uninferred_impl.0.trait_id(db) else { return false };
2117            trait_id == filter.trait_id
2118        })
2119        .cloned();
2120    match filter.generics_filter {
2121        GenericsHeadFilter::NoFilter => {
2122            let globals = db.crate_global_impls(crate_id);
2123            let globals = globals.get(&filter.trait_id);
2124            res.extend(locals);
2125            res.extend(globals.into_iter().flat_map(|s| s.iter().cloned()))
2126        }
2127        _ => {
2128            let candidates_by_head = db.trait_candidate_by_head(crate_id, filter.trait_id);
2129            let filtered = candidates_by_head.get(&filter.generics_filter).cloned();
2130            let no_filtered = candidates_by_head.get(&GenericsHeadFilter::NoFilter).cloned();
2131            res.extend(filtered.into_iter().flat_map(|s| s.into_iter()));
2132            res.extend(no_filtered.into_iter().flat_map(|s| s.into_iter()));
2133            res.extend(locals.filter(|uninferred_impl| {
2134                let Ok(_) = uninferred_impl.0.concrete_trait(db) else {
2135                    return false;
2136                };
2137                // TODO(TomerStarkware): Check if the concrete trait fits the trait filter.
2138                // Currently, light inference will invalidate this.
2139                true
2140            }));
2141        }
2142    }
2143    Ok(res)
2144}
2145
2146/// Finds the generated candidate for a concrete trait.
2147pub fn find_closure_generated_candidate<'db>(
2148    db: &'db dyn Database,
2149    concrete_trait_id: ConcreteTraitId<'db>,
2150) -> Option<UninferredImpl<'db>> {
2151    let GenericArgumentId::Type(closure_type) = *concrete_trait_id.generic_args(db).first()? else {
2152        return None;
2153    };
2154    let TypeLongId::Closure(closure_type_long) = closure_type.long(db) else {
2155        return None;
2156    };
2157
2158    let info = db.core_info();
2159
2160    // Handles the special cases of `Copy`, `Drop`, `Destruct` and `PanicDestruct`.
2161    let mem_trait_generic_params = |trait_id, neg_impl_trait: Option<_>| {
2162        let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
2163        chain!(
2164            closure_type_long.captured_types.iter().unique().map(|ty| {
2165                GenericParam::Impl(GenericParamImpl {
2166                    id,
2167                    concrete_trait: Maybe::Ok(ConcreteTraitId::new(
2168                        db,
2169                        ConcreteTraitLongId {
2170                            trait_id,
2171                            generic_args: vec![GenericArgumentId::Type(*ty)],
2172                        },
2173                    )),
2174                    type_constraints: Default::default(),
2175                })
2176            }),
2177            neg_impl_trait.map(|neg_impl_trait| {
2178                GenericParam::NegImpl(GenericParamImpl {
2179                    id,
2180                    concrete_trait: Maybe::Ok(neg_impl_trait),
2181                    type_constraints: Default::default(),
2182                })
2183            })
2184        )
2185        .collect()
2186    };
2187    let handle_mem_trait = |trait_id, neg_impl_trait: Option<_>| {
2188        (concrete_trait_id, mem_trait_generic_params(trait_id, neg_impl_trait), [].into())
2189    };
2190    let (concrete_trait, generic_params, impl_items) = match concrete_trait_id.trait_id(db) {
2191        trait_id if trait_id == info.fn_once_trt => {
2192            let concrete_trait = ConcreteTraitLongId {
2193                trait_id,
2194                generic_args: vec![
2195                    GenericArgumentId::Type(closure_type),
2196                    GenericArgumentId::Type(
2197                        TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2198                    ),
2199                ],
2200            }
2201            .intern(db);
2202            let ret_ty =
2203                db.trait_type_by_name(trait_id, SmolStrId::from(db, "Output")).unwrap().unwrap();
2204
2205            let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
2206            // FnOnce is generated only if there is no fn trait.
2207            let param: GenericParam<'_> = GenericParam::NegImpl(GenericParamImpl {
2208                id,
2209                concrete_trait: Maybe::Ok(
2210                    ConcreteTraitLongId {
2211                        trait_id: info.fn_trt,
2212                        generic_args: vec![
2213                            GenericArgumentId::Type(closure_type),
2214                            GenericArgumentId::Type(
2215                                TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2216                            ),
2217                        ],
2218                    }
2219                    .intern(db),
2220                ),
2221                type_constraints: Default::default(),
2222            });
2223            (concrete_trait, vec![param], [(ret_ty, closure_type_long.ret_ty)].into())
2224        }
2225        trait_id if trait_id == info.fn_trt => {
2226            let concrete_trait = ConcreteTraitLongId {
2227                trait_id,
2228                generic_args: vec![
2229                    GenericArgumentId::Type(closure_type),
2230                    GenericArgumentId::Type(
2231                        TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2232                    ),
2233                ],
2234            }
2235            .intern(db);
2236            let ret_ty =
2237                db.trait_type_by_name(trait_id, SmolStrId::from(db, "Output")).unwrap().unwrap();
2238
2239            (
2240                concrete_trait,
2241                // Makes the generated impl of fn_trait available only if the closure is copyable.
2242                mem_trait_generic_params(info.copy_trt, None),
2243                [(ret_ty, closure_type_long.ret_ty)].into(),
2244            )
2245        }
2246        trait_id if trait_id == info.drop_trt => handle_mem_trait(trait_id, None),
2247        trait_id if trait_id == info.destruct_trt => {
2248            handle_mem_trait(trait_id, Some(concrete_drop_trait(db, closure_type)))
2249        }
2250        trait_id if trait_id == info.panic_destruct_trt => {
2251            handle_mem_trait(trait_id, Some(concrete_destruct_trait(db, closure_type)))
2252        }
2253        trait_id if trait_id == info.copy_trt => handle_mem_trait(trait_id, None),
2254        _ => return None,
2255    };
2256    Some(UninferredImpl::GeneratedImpl(
2257        UninferredGeneratedImplLongId {
2258            concrete_trait,
2259            generic_params,
2260            impl_items: GeneratedImplItems(impl_items),
2261        }
2262        .intern(db),
2263    ))
2264}
2265
2266/// Checks if an impl of a trait function with a given self_ty exists.
2267/// This function does not change the state of the inference context.
2268///
2269/// `inference_errors` are aggregated here but are not reported here as diagnostics.
2270/// The caller has to make sure the diagnostics are reported appropriately.
2271pub fn can_infer_impl_by_self<'db>(
2272    ctx: &ComputationContext<'db, '_>,
2273    inference_errors: &mut Vec<(TraitFunctionId<'db>, InferenceError<'db>)>,
2274    trait_function_id: TraitFunctionId<'db>,
2275    self_ty: TypeId<'db>,
2276    stable_ptr: SyntaxStablePtrId<'db>,
2277) -> bool {
2278    let mut temp_inference_data = ctx.resolver.data.inference_data.temporary_clone();
2279    let mut temp_inference = temp_inference_data.inference(ctx.db);
2280    let lookup_context = ctx.resolver.impl_lookup_context();
2281
2282    let Some((concrete_trait_id, _)) = temp_inference.infer_concrete_trait_by_self(
2283        trait_function_id,
2284        self_ty,
2285        lookup_context,
2286        Some(stable_ptr),
2287        inference_errors,
2288    ) else {
2289        return false;
2290    };
2291    // Find impls for it.
2292    if let Err(err_set) = temp_inference.solve() {
2293        // Error is propagated and will be reported later.
2294        if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
2295            inference_errors.push((trait_function_id, err));
2296        }
2297    }
2298    match temp_inference.trait_solution_set(
2299        concrete_trait_id,
2300        ImplVarTraitItemMappings::default(),
2301        lookup_context,
2302    ) {
2303        Ok(SolutionSet::Unique(_) | SolutionSet::Ambiguous(_)) => true,
2304        Ok(SolutionSet::None) => {
2305            inference_errors
2306                .push((trait_function_id, InferenceError::NoImplsFound(concrete_trait_id)));
2307            false
2308        }
2309        Err(err_set) => {
2310            // Error is propagated and will be reported later.
2311            if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
2312                inference_errors.push((trait_function_id, err));
2313            }
2314            false
2315        }
2316    }
2317}
2318
2319/// Returns an impl of a given trait function with a given self_ty, as well as the number of
2320/// snapshots needed to be added to it.
2321pub fn infer_impl_by_self<'db>(
2322    ctx: &mut ComputationContext<'db, '_>,
2323    trait_function_id: TraitFunctionId<'db>,
2324    self_ty: TypeId<'db>,
2325    stable_ptr: SyntaxStablePtrId<'db>,
2326    generic_args_syntax: Option<Vec<GenericArg<'db>>>,
2327) -> Maybe<(FunctionId<'db>, usize)> {
2328    let lookup_context = ctx.resolver.impl_lookup_context();
2329    let (concrete_trait_id, n_snapshots) = ctx
2330        .resolver
2331        .inference()
2332        .infer_concrete_trait_by_self_without_errors(
2333            trait_function_id,
2334            self_ty,
2335            lookup_context,
2336            Some(stable_ptr),
2337        )
2338        .ok_or_else(skip_diagnostic)?;
2339
2340    let concrete_trait_function_id =
2341        ConcreteTraitGenericFunctionLongId::new(ctx.db, concrete_trait_id, trait_function_id)
2342            .intern(ctx.db);
2343    let trait_func_generic_params =
2344        ctx.db.concrete_trait_function_generic_params(concrete_trait_function_id).unwrap();
2345
2346    let impl_lookup_context = ctx.resolver.impl_lookup_context();
2347    let inference = &mut ctx.resolver.inference();
2348    let generic_function = inference.infer_trait_generic_function(
2349        concrete_trait_function_id,
2350        impl_lookup_context,
2351        Some(stable_ptr),
2352    );
2353    let generic_args = ctx.resolver.resolve_generic_args(
2354        ctx.diagnostics,
2355        GenericSubstitution::from_impl(generic_function.impl_id),
2356        trait_func_generic_params,
2357        &generic_args_syntax.unwrap_or_default(),
2358        stable_ptr,
2359    )?;
2360
2361    Ok((
2362        FunctionLongId {
2363            function: ConcreteFunction {
2364                generic_function: GenericFunctionId::Impl(generic_function),
2365                generic_args,
2366            },
2367        }
2368        .intern(ctx.db),
2369        n_snapshots,
2370    ))
2371}
2372
2373/// Returns all the trait functions that fit the given function name, can be called on the given
2374/// `self_ty`, and have at least one implementation in context.
2375///
2376/// `inference_errors` are aggregated here but are not reported here as diagnostics.
2377/// The caller has to make sure the diagnostics are reported appropriately.
2378pub fn filter_candidate_traits<'db>(
2379    ctx: &mut ComputationContext<'db, '_>,
2380    inference_errors: &mut Vec<(TraitFunctionId<'db>, InferenceError<'db>)>,
2381    self_ty: TypeId<'db>,
2382    candidate_traits: &[TraitId<'db>],
2383    function_name: SmolStrId<'db>,
2384    stable_ptr: SyntaxStablePtrId<'db>,
2385) -> Vec<TraitFunctionId<'db>> {
2386    let mut candidates = Vec::new();
2387    for trait_id in candidate_traits.iter().copied() {
2388        let Ok(trait_functions) = ctx.db.trait_functions(trait_id) else {
2389            continue;
2390        };
2391        for (&name, &trait_function) in trait_functions.iter() {
2392            if name == function_name
2393                && can_infer_impl_by_self(
2394                    ctx,
2395                    inference_errors,
2396                    trait_function,
2397                    self_ty,
2398                    stable_ptr,
2399                )
2400            {
2401                candidates.push(trait_function);
2402            }
2403        }
2404    }
2405    candidates
2406}
2407
2408// === Impl Item Type definition ===
2409
2410#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
2411#[debug_db(dyn Database)]
2412struct ImplItemTypeData<'db> {
2413    type_alias_data: TypeAliasData<'db>,
2414    trait_type_id: Maybe<TraitTypeId<'db>>,
2415    /// The diagnostics of the module type alias, including the ones for the type alias itself.
2416    diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
2417}
2418
2419// --- Selectors ---
2420
2421// --- Computation ---
2422
2423/// Returns data about an impl type definition.
2424#[salsa::tracked(cycle_result=impl_type_semantic_data_cycle, returns(ref))]
2425fn impl_type_semantic_data<'db>(
2426    db: &'db dyn Database,
2427    impl_type_def_id: ImplTypeDefId<'db>,
2428    in_cycle: bool,
2429) -> Maybe<ImplItemTypeData<'db>> {
2430    let mut diagnostics =
2431        SemanticDiagnostics::new(impl_type_def_id.impl_def_id(db).parent_module(db));
2432    let impl_type_def_ast = db.impl_type_by_id(impl_type_def_id)?;
2433    let generic_params_data =
2434        impl_type_def_generic_params_data(db, impl_type_def_id).maybe_as_ref()?.clone();
2435    let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2436
2437    let trait_type_id =
2438        validate_impl_item_type(db, &mut diagnostics, impl_type_def_id, &impl_type_def_ast);
2439
2440    if in_cycle {
2441        Ok(ImplItemTypeData {
2442            type_alias_data: type_alias_semantic_data_cycle_helper(
2443                db,
2444                &mut diagnostics,
2445                &impl_type_def_ast,
2446                lookup_item_id,
2447                generic_params_data,
2448            )?,
2449            trait_type_id,
2450            diagnostics: diagnostics.build(),
2451        })
2452    } else {
2453        // TODO(yuval): resolve type aliases later, like in module type aliases, to avoid cycles in
2454        // non-cyclic chains.
2455        Ok(ImplItemTypeData {
2456            type_alias_data: type_alias_semantic_data_helper(
2457                db,
2458                &mut diagnostics,
2459                &impl_type_def_ast,
2460                lookup_item_id,
2461                generic_params_data,
2462            )?,
2463            trait_type_id,
2464            diagnostics: diagnostics.build(),
2465        })
2466    }
2467}
2468
2469fn impl_type_semantic_data_cycle<'db>(
2470    db: &'db dyn Database,
2471    _id: salsa::Id,
2472    impl_type_def_id: ImplTypeDefId<'db>,
2473    _in_cycle: bool,
2474) -> Maybe<ImplItemTypeData<'db>> {
2475    impl_type_semantic_data(db, impl_type_def_id, true).clone()
2476}
2477
2478/// Returns the generic parameters data of an impl type definition.
2479#[salsa::tracked(returns(ref))]
2480fn impl_type_def_generic_params_data<'db>(
2481    db: &'db dyn Database,
2482    impl_type_def_id: ImplTypeDefId<'db>,
2483) -> Maybe<GenericParamsData<'db>> {
2484    let module_id = impl_type_def_id.parent_module(db);
2485    let impl_type_def_ast = db.impl_type_by_id(impl_type_def_id)?;
2486    let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2487
2488    let impl_resolver_data = db.impl_def_resolver_data(impl_type_def_id.impl_def_id(db))?;
2489    type_alias_generic_params_data_helper(
2490        db,
2491        module_id,
2492        &impl_type_def_ast,
2493        lookup_item_id,
2494        Some(impl_resolver_data),
2495    )
2496}
2497
2498/// Validates the impl item type, and returns the matching trait type id.
2499fn validate_impl_item_type<'db>(
2500    db: &'db dyn Database,
2501    diagnostics: &mut SemanticDiagnostics<'db>,
2502    impl_type_def_id: ImplTypeDefId<'db>,
2503    impl_type_ast: &ast::ItemTypeAlias<'db>,
2504) -> Maybe<TraitTypeId<'db>> {
2505    let impl_def_id = impl_type_def_id.impl_def_id(db);
2506    let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2507    let trait_id = concrete_trait_id.trait_id(db);
2508    let type_name = impl_type_def_id.name(db);
2509    let trait_type_id = db.trait_type_by_name(trait_id, type_name)?.ok_or_else(|| {
2510        diagnostics.report(
2511            impl_type_ast.stable_ptr(db),
2512            ImplItemNotInTrait {
2513                impl_def_id,
2514                impl_item_name: type_name,
2515                trait_id,
2516                item_kind: "type".into(),
2517            },
2518        )
2519    })?;
2520
2521    // TODO(yuval): add validations for generic parameters, then remove this.
2522    // Generic parameters are not yet supported, make sure there are none.
2523    let generic_params_node = impl_type_ast.generic_params(db);
2524    if !generic_params_node.is_empty(db) {
2525        diagnostics.report(
2526            generic_params_node.stable_ptr(db),
2527            GenericsNotSupportedInItem { scope: "Impl".into(), item_kind: "type".into() },
2528        );
2529    }
2530
2531    Ok(trait_type_id)
2532}
2533
2534// === Impl Type ===
2535
2536/// Implementation of [ImplSemantic::impl_type_concrete_implized].
2537fn impl_type_concrete_implized<'db>(
2538    db: &'db dyn Database,
2539    impl_type_id: ImplTypeId<'db>,
2540) -> Maybe<TypeId<'db>> {
2541    let concrete_impl = match impl_type_id.impl_id().long(db) {
2542        ImplLongId::Concrete(concrete_impl) => concrete_impl,
2543        ImplLongId::ImplImpl(imp_impl_id) => {
2544            let ImplLongId::Concrete(concrete_impl) =
2545                db.impl_impl_concrete_implized(*imp_impl_id)?.long(db)
2546            else {
2547                return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2548            };
2549            concrete_impl
2550        }
2551        ImplLongId::GenericParameter(_) | ImplLongId::SelfImpl(_) | ImplLongId::ImplVar(_) => {
2552            return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2553        }
2554        ImplLongId::GeneratedImpl(generated) => {
2555            return Ok(*generated.long(db).impl_items.0.get(&impl_type_id.ty()).unwrap());
2556        }
2557    };
2558
2559    let impl_def_id = concrete_impl.impl_def_id(db);
2560    let ty = db.trait_type_implized_by_context(impl_type_id.ty(), impl_def_id)?;
2561    concrete_impl.substitution(db)?.substitute(db, ty)
2562}
2563
2564#[salsa::tracked(cycle_result=impl_type_concrete_implized_cycle)]
2565fn impl_type_concrete_implized_helper<'db>(
2566    db: &'db dyn Database,
2567    _tracked: Tracked,
2568    impl_type_id: ImplTypeId<'db>,
2569) -> Maybe<TypeId<'db>> {
2570    impl_type_concrete_implized(db, impl_type_id)
2571}
2572
2573/// Query implementation of [ImplSemantic::impl_type_concrete_implized].
2574fn impl_type_concrete_implized_tracked<'db>(
2575    db: &'db dyn Database,
2576    impl_type_id: ImplTypeId<'db>,
2577) -> Maybe<TypeId<'db>> {
2578    impl_type_concrete_implized_helper(db, (), impl_type_id)
2579}
2580
2581/// Cycle handling for [ImplSemantic::impl_type_concrete_implized].
2582fn impl_type_concrete_implized_cycle<'db>(
2583    db: &'db dyn Database,
2584    _id: salsa::Id,
2585    _tracked: Tracked,
2586    impl_type_id: ImplTypeId<'db>,
2587) -> Maybe<TypeId<'db>> {
2588    // Forwarding cycle handling to `impl_type_semantic_data` handler.
2589    impl_type_concrete_implized(db, impl_type_id)
2590}
2591
2592// === Impl Item Constant definition ===
2593
2594#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
2595#[debug_db(dyn Database)]
2596struct ImplItemConstantData<'db> {
2597    constant_data: ConstantData<'db>,
2598    trait_constant_id: Maybe<TraitConstantId<'db>>,
2599    /// The diagnostics of the impl constant, including the ones for the constant itself.
2600    diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
2601}
2602
2603/// Returns data about an impl constant definition.
2604#[salsa::tracked(cycle_result=impl_constant_semantic_data_cycle, returns(ref))]
2605fn impl_constant_semantic_data<'db>(
2606    db: &'db dyn Database,
2607    impl_constant_def_id: ImplConstantDefId<'db>,
2608    in_cycle: bool,
2609) -> Maybe<ImplItemConstantData<'db>> {
2610    let impl_def_id = impl_constant_def_id.impl_def_id(db);
2611    let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
2612    let impl_constant_defs = db.impl_constants(impl_def_id)?;
2613    let impl_constant_def_ast = impl_constant_defs.get(&impl_constant_def_id).to_maybe()?;
2614    let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Constant(impl_constant_def_id));
2615
2616    let inference_id = InferenceId::LookupItemGenerics(LookupItemId::ImplItem(
2617        ImplItemId::Constant(impl_constant_def_id),
2618    ));
2619    let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2620    let mut resolver =
2621        Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2622
2623    let trait_constant_id = validate_impl_item_constant(
2624        db,
2625        &mut diagnostics,
2626        impl_constant_def_id,
2627        impl_constant_def_ast,
2628        &mut resolver,
2629    );
2630    let mut constant_data = if in_cycle {
2631        constant_semantic_data_cycle_helper(
2632            db,
2633            impl_constant_def_ast,
2634            lookup_item_id,
2635            Some(Arc::new(resolver.data)),
2636            &impl_def_id,
2637        )?
2638    } else {
2639        constant_semantic_data_helper(
2640            db,
2641            impl_constant_def_ast,
2642            lookup_item_id,
2643            Some(Arc::new(resolver.data)),
2644            &impl_def_id,
2645        )?
2646    };
2647    diagnostics.extend(mem::take(&mut constant_data.diagnostics));
2648    Ok(ImplItemConstantData { constant_data, trait_constant_id, diagnostics: diagnostics.build() })
2649}
2650
2651fn impl_constant_semantic_data_cycle<'db>(
2652    db: &'db dyn Database,
2653    _id: salsa::Id,
2654    impl_constant_def_id: ImplConstantDefId<'db>,
2655    _in_cycle: bool,
2656) -> Maybe<ImplItemConstantData<'db>> {
2657    impl_constant_semantic_data(db, impl_constant_def_id, true).clone()
2658}
2659
2660/// Validates the impl item constant, and returns the matching trait constant id.
2661fn validate_impl_item_constant<'db>(
2662    db: &'db dyn Database,
2663    diagnostics: &mut SemanticDiagnostics<'db>,
2664    impl_constant_def_id: ImplConstantDefId<'db>,
2665    impl_constant_ast: &ast::ItemConstant<'db>,
2666    resolver: &mut Resolver<'db>,
2667) -> Maybe<TraitConstantId<'db>> {
2668    let impl_def_id = impl_constant_def_id.impl_def_id(db);
2669    let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2670    let trait_id = concrete_trait_id.trait_id(db);
2671    let constant_name = impl_constant_def_id.name(db);
2672
2673    let trait_constant_id =
2674        db.trait_constant_by_name(trait_id, constant_name)?.ok_or_else(|| {
2675            diagnostics.report(
2676                impl_constant_ast.stable_ptr(db),
2677                ImplItemNotInTrait {
2678                    impl_def_id,
2679                    impl_item_name: constant_name,
2680                    trait_id,
2681                    item_kind: "const".into(),
2682                },
2683            )
2684        })?;
2685    let concrete_trait_constant =
2686        ConcreteTraitConstantId::new_from_data(db, concrete_trait_id, trait_constant_id);
2687    let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
2688    let concrete_trait_constant_ty = impl_def_substitution
2689        .substitute(db, db.concrete_trait_constant_type(concrete_trait_constant)?)?;
2690
2691    let impl_constant_type_clause_ast = impl_constant_ast.type_clause(db);
2692
2693    let constant_ty =
2694        resolve_type(db, diagnostics, resolver, &impl_constant_type_clause_ast.ty(db));
2695
2696    let inference = &mut resolver.inference();
2697
2698    let expected_ty = inference.rewrite(concrete_trait_constant_ty).no_err();
2699    let actual_ty = inference.rewrite(constant_ty).no_err();
2700    if expected_ty != actual_ty {
2701        diagnostics.report(
2702            impl_constant_type_clause_ast.ty(db).stable_ptr(db),
2703            WrongType { expected_ty, actual_ty },
2704        );
2705    }
2706    Ok(trait_constant_id)
2707}
2708
2709// === Impl Constant ===
2710
2711/// Query implementation of [PrivImplSemantic::impl_constant_implized_by_context].
2712fn impl_constant_implized_by_context<'db>(
2713    db: &'db dyn Database,
2714    impl_constant_id: ImplConstantId<'db>,
2715    impl_def_id: ImplDefId<'db>,
2716) -> Maybe<ConstValueId<'db>> {
2717    let impl_constant_def_id: ImplConstantDefId<'_> =
2718        db.impl_constant_by_trait_constant(impl_def_id, impl_constant_id.trait_constant_id())?;
2719
2720    db.impl_constant_def_value(impl_constant_def_id)
2721}
2722
2723/// Query implementation of [ImplSemantic::impl_constant_implized_by_context].
2724#[salsa::tracked(cycle_result=impl_constant_implized_by_context_cycle)]
2725fn impl_constant_implized_by_context_tracked<'db>(
2726    db: &'db dyn Database,
2727    impl_constant_id: ImplConstantId<'db>,
2728    impl_def_id: ImplDefId<'db>,
2729) -> Maybe<ConstValueId<'db>> {
2730    impl_constant_implized_by_context(db, impl_constant_id, impl_def_id)
2731}
2732
2733/// Cycle handling for [PrivImplSemantic::impl_constant_implized_by_context].
2734fn impl_constant_implized_by_context_cycle<'db>(
2735    db: &'db dyn Database,
2736    _id: salsa::Id,
2737    impl_constant_id: ImplConstantId<'db>,
2738    impl_def_id: ImplDefId<'db>,
2739) -> Maybe<ConstValueId<'db>> {
2740    // Forwarding cycle handling to `priv_impl_constant_semantic_data` handler.
2741    impl_constant_implized_by_context(db, impl_constant_id, impl_def_id)
2742}
2743
2744/// Query implementation of [ImplSemantic::impl_constant_concrete_implized_value].
2745fn impl_constant_concrete_implized_value<'db>(
2746    db: &'db dyn Database,
2747    impl_constant_id: ImplConstantId<'db>,
2748) -> Maybe<ConstValueId<'db>> {
2749    if let ImplLongId::Concrete(concrete_impl) = impl_constant_id.impl_id().long(db) {
2750        let impl_def_id = concrete_impl.impl_def_id(db);
2751        let constant: ConstValueId<'db> =
2752            db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?;
2753        return concrete_impl.substitution(db)?.substitute(db, constant);
2754    }
2755    let substitution: GenericSubstitution<'db> =
2756        GenericSubstitution::from_impl(impl_constant_id.impl_id());
2757    let substitution_id = substitution.substitute(db, impl_constant_id)?;
2758    let const_val: ConstValue<'db> = ConstValue::ImplConstant(substitution_id);
2759    Ok(const_val.intern(db))
2760}
2761
2762/// Query implementation of [ImplSemantic::impl_constant_concrete_implized_value].
2763fn impl_constant_concrete_implized_value_tracked<'db>(
2764    db: &'db dyn Database,
2765    impl_constant_id: ImplConstantId<'db>,
2766) -> Maybe<ConstValueId<'db>> {
2767    impl_constant_concrete_implized_value_helper(db, (), impl_constant_id)
2768}
2769
2770/// Tracked implementation of [ImplSemantic::impl_constant_concrete_implized_value].
2771/// Receives a dummy id to support salsa tracking.
2772#[salsa::tracked(cycle_result=impl_constant_concrete_implized_value_cycle)]
2773fn impl_constant_concrete_implized_value_helper<'db>(
2774    db: &'db dyn Database,
2775    _tracked: Tracked,
2776    impl_constant_id: ImplConstantId<'db>,
2777) -> Maybe<ConstValueId<'db>> {
2778    impl_constant_concrete_implized_value(db, impl_constant_id)
2779}
2780
2781/// Cycle handling for [ImplSemantic::impl_constant_concrete_implized_value].
2782fn impl_constant_concrete_implized_value_cycle<'db>(
2783    db: &'db dyn Database,
2784    _id: salsa::Id,
2785    _tracked: Tracked,
2786    impl_constant_id: ImplConstantId<'db>,
2787) -> Maybe<ConstValueId<'db>> {
2788    // Forwarding cycle handling to `priv_impl_const_semantic_data` handler.
2789    impl_constant_concrete_implized_value(db, impl_constant_id)
2790}
2791
2792/// Query implementation of [ImplSemantic::impl_constant_concrete_implized_type].
2793fn impl_constant_concrete_implized_type<'db>(
2794    db: &'db dyn Database,
2795    impl_constant_id: ImplConstantId<'db>,
2796) -> Maybe<TypeId<'db>> {
2797    let concrete_trait_id = match impl_constant_id.impl_id().long(db) {
2798        ImplLongId::Concrete(concrete_impl) => {
2799            let impl_def_id = concrete_impl.impl_def_id(db);
2800            let ty = db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?.ty(db)?;
2801            return concrete_impl.substitution(db)?.substitute(db, ty);
2802        }
2803        ImplLongId::GenericParameter(param) => {
2804            let param_impl =
2805                extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
2806            param_impl.concrete_trait?
2807        }
2808        ImplLongId::ImplVar(var) => var.long(db).concrete_trait_id,
2809        ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(*impl_impl)?,
2810        ImplLongId::SelfImpl(concrete_trait_id) => *concrete_trait_id,
2811        ImplLongId::GeneratedImpl(generated_impl) => generated_impl.concrete_trait(db),
2812    };
2813
2814    let ty = db.concrete_trait_constant_type(ConcreteTraitConstantId::new_from_data(
2815        db,
2816        concrete_trait_id,
2817        impl_constant_id.trait_constant_id(),
2818    ))?;
2819    GenericSubstitution::from_impl(impl_constant_id.impl_id()).substitute(db, ty)
2820}
2821
2822/// Query implementation of [ImplSemantic::impl_constant_concrete_implized_type].
2823fn impl_constant_concrete_implized_type_tracked<'db>(
2824    db: &'db dyn Database,
2825    impl_constant_id: ImplConstantId<'db>,
2826) -> Maybe<TypeId<'db>> {
2827    impl_constant_concrete_implized_type_helper(db, (), impl_constant_id)
2828}
2829
2830#[salsa::tracked(cycle_result=impl_constant_concrete_implized_type_cycle)]
2831fn impl_constant_concrete_implized_type_helper<'db>(
2832    db: &'db dyn Database,
2833    _tracked: Tracked,
2834    impl_constant_id: ImplConstantId<'db>,
2835) -> Maybe<TypeId<'db>> {
2836    impl_constant_concrete_implized_type(db, impl_constant_id)
2837}
2838
2839/// Cycle handling for [ImplSemantic::impl_constant_concrete_implized_type].
2840fn impl_constant_concrete_implized_type_cycle<'db>(
2841    db: &'db dyn Database,
2842    _id: salsa::Id,
2843    _tracked: Tracked,
2844    impl_constant_id: ImplConstantId<'db>,
2845) -> Maybe<TypeId<'db>> {
2846    // Forwarding cycle handling to `priv_impl_const_semantic_data` handler.
2847    impl_constant_concrete_implized_type(db, impl_constant_id)
2848}
2849
2850// === Impl Item Impl definition ===
2851
2852#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
2853#[debug_db(dyn Database)]
2854struct ImplItemImplData<'db> {
2855    impl_data: ImplAliasData<'db>,
2856    trait_impl_id: Maybe<TraitImplId<'db>>,
2857    /// The diagnostics of the impl impl, including the ones for the impl itself.
2858    diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
2859}
2860
2861/// Returns data about an impl impl definition.
2862#[salsa::tracked(cycle_result=impl_impl_semantic_data_cycle, returns(ref))]
2863fn impl_impl_semantic_data<'db>(
2864    db: &'db dyn Database,
2865    impl_impl_def_id: ImplImplDefId<'db>,
2866    in_cycle: bool,
2867) -> Maybe<ImplItemImplData<'db>> {
2868    let impl_def_id = impl_impl_def_id.impl_def_id(db);
2869    let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
2870    let impl_impl_defs = db.impl_impls(impl_def_id)?;
2871    let impl_impl_def_ast = impl_impl_defs.get(&impl_impl_def_id).to_maybe()?;
2872    let generic_params_data =
2873        impl_impl_def_generic_params_data(db, impl_impl_def_id).maybe_as_ref()?.clone();
2874    let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2875
2876    let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
2877    let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2878    let mut resolver =
2879        Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2880
2881    let mut impl_data = if in_cycle {
2882        impl_alias_semantic_data_cycle_helper(
2883            db,
2884            impl_impl_def_ast,
2885            lookup_item_id,
2886            generic_params_data,
2887        )?
2888    } else {
2889        impl_alias_semantic_data_helper(db, impl_impl_def_ast, lookup_item_id, generic_params_data)?
2890    };
2891
2892    diagnostics.extend(mem::take(&mut impl_data.diagnostics));
2893
2894    let trait_impl_id = validate_impl_item_impl(
2895        db,
2896        &mut diagnostics,
2897        impl_impl_def_id,
2898        impl_impl_def_ast,
2899        &impl_data,
2900        &mut resolver,
2901    );
2902
2903    Ok(ImplItemImplData { impl_data, trait_impl_id, diagnostics: diagnostics.build() })
2904}
2905
2906fn impl_impl_semantic_data_cycle<'db>(
2907    db: &'db dyn Database,
2908    _id: salsa::Id,
2909    impl_impl_def_id: ImplImplDefId<'db>,
2910    _in_cycle: bool,
2911) -> Maybe<ImplItemImplData<'db>> {
2912    impl_impl_semantic_data(db, impl_impl_def_id, true).clone()
2913}
2914
2915/// Returns the generic parameters data of an impl impl definition.
2916#[salsa::tracked(returns(ref))]
2917fn impl_impl_def_generic_params_data<'db>(
2918    db: &'db dyn Database,
2919    impl_impl_def_id: ImplImplDefId<'db>,
2920) -> Maybe<GenericParamsData<'db>> {
2921    let module_id = impl_impl_def_id.parent_module(db);
2922    let impl_impl_def_ast = db.impl_impl_by_id(impl_impl_def_id)?;
2923    let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2924
2925    let impl_resolver_data = db.impl_def_resolver_data(impl_impl_def_id.impl_def_id(db))?;
2926    impl_alias_generic_params_data_helper(
2927        db,
2928        module_id,
2929        &impl_impl_def_ast,
2930        lookup_item_id,
2931        Some(impl_resolver_data),
2932    )
2933}
2934
2935/// Validates the impl item impl, and returns the matching trait impl id.
2936fn validate_impl_item_impl<'db>(
2937    db: &'db dyn Database,
2938    diagnostics: &mut SemanticDiagnostics<'db>,
2939    impl_impl_def_id: ImplImplDefId<'db>,
2940    impl_impl_ast: &ast::ItemImplAlias<'db>,
2941    impl_data: &ImplAliasData<'db>,
2942    resolver: &mut Resolver<'db>,
2943) -> Maybe<TraitImplId<'db>> {
2944    let impl_def_id = impl_impl_def_id.impl_def_id(db);
2945    let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2946    let trait_id = concrete_trait_id.trait_id(db);
2947    let impl_item_name = impl_impl_def_id.name(db);
2948    let trait_impl_id = db.trait_impl_by_name(trait_id, impl_item_name)?.ok_or_else(|| {
2949        diagnostics.report(
2950            impl_impl_ast.stable_ptr(db),
2951            ImplItemNotInTrait { impl_def_id, impl_item_name, trait_id, item_kind: "impl".into() },
2952        )
2953    })?;
2954
2955    // TODO(TomerStarkware): add validations for generic parameters, then remove this.
2956    // Generic parameters are not yet supported, make sure there are none.
2957    let generic_params_node = impl_impl_ast.generic_params(db);
2958    if !generic_params_node.is_empty(db) {
2959        diagnostics.report(
2960            generic_params_node.stable_ptr(db),
2961            GenericsNotSupportedInItem { scope: "Impl".into(), item_kind: "impl".into() },
2962        );
2963    }
2964
2965    let concrete_trait_impl =
2966        ConcreteTraitImplId::new_from_data(db, concrete_trait_id, trait_impl_id);
2967    let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
2968
2969    let concrete_trait_impl_concrete_trait = db
2970        .concrete_trait_impl_concrete_trait(concrete_trait_impl)
2971        .and_then(|concrete_trait_id| impl_def_substitution.substitute(db, concrete_trait_id));
2972
2973    let resolved_impl_concrete_trait =
2974        impl_data.resolved_impl.and_then(|imp| imp.concrete_trait(db));
2975    // used an IIFE to allow the use of the `?` operator.
2976    let _ = (|| -> Result<(), DiagnosticAdded> {
2977        if resolver
2978            .inference()
2979            .conform_traits(resolved_impl_concrete_trait?, concrete_trait_impl_concrete_trait?)
2980            .is_err()
2981        {
2982            diagnostics.report(
2983                impl_impl_ast.stable_ptr(db),
2984                TraitMismatch {
2985                    expected_trt: concrete_trait_impl_concrete_trait?,
2986                    actual_trt: resolved_impl_concrete_trait?,
2987                },
2988            );
2989        }
2990        Ok(())
2991    })();
2992
2993    Ok(trait_impl_id)
2994}
2995
2996#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
2997#[debug_db(dyn Database)]
2998struct ImplicitImplImplData<'db> {
2999    resolved_impl: Maybe<ImplId<'db>>,
3000    trait_impl_id: TraitImplId<'db>,
3001    diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
3002}
3003
3004/// Computes implicit impl semantic data with cycle handling.
3005fn implicit_impl_impl_semantic_data<'db>(
3006    db: &'db dyn Database,
3007    impl_def_id: ImplDefId<'db>,
3008    trait_impl_id: TraitImplId<'db>,
3009    in_cycle: bool,
3010) -> Maybe<ImplicitImplImplData<'db>> {
3011    let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
3012    if in_cycle {
3013        let err = Err(diagnostics.report(impl_def_id.stable_ptr(db).untyped(), ImplAliasCycle));
3014        return Ok(ImplicitImplImplData {
3015            resolved_impl: err,
3016            trait_impl_id,
3017            diagnostics: diagnostics.build(),
3018        });
3019    }
3020    let lookup_item_id = LookupItemId::ModuleItem(ModuleItemId::Impl(impl_def_id));
3021
3022    let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
3023    let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
3024
3025    let mut resolver =
3026        Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
3027    // We cannot use `Self` as it will always find the implicit impl.
3028    resolver.trait_or_impl_ctx = TraitOrImplContext::None;
3029
3030    let concrete_trait_impl_concrete_trait = db
3031        .impl_def_concrete_trait(impl_def_id)
3032        .and_then(|concrete_trait_id| {
3033            db.concrete_trait_impl_concrete_trait(ConcreteTraitImplId::new_from_data(
3034                db,
3035                concrete_trait_id,
3036                trait_impl_id,
3037            ))
3038        })
3039        .and_then(|concrete_trait_id| {
3040            let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
3041            impl_def_substitution.substitute(db, concrete_trait_id)
3042        });
3043    let impl_lookup_context = resolver.impl_lookup_context();
3044    let resolved_impl = concrete_trait_impl_concrete_trait.and_then(|concrete_trait_id| {
3045        let imp = resolver.inference().new_impl_var(concrete_trait_id, None, impl_lookup_context);
3046        resolver.inference().finalize_without_reporting().map_err(|err_set| {
3047            diagnostics.report(
3048                impl_def_id.stable_ptr(db).untyped(),
3049                ImplicitImplNotInferred { trait_impl_id, concrete_trait_id },
3050            );
3051            resolver.inference().report_on_pending_error(
3052                err_set,
3053                &mut diagnostics,
3054                impl_def_id.stable_ptr(db).untyped(),
3055            )
3056        })?;
3057        resolver.inference().rewrite(imp).map_err(|_| skip_diagnostic())
3058    });
3059
3060    Ok(ImplicitImplImplData { resolved_impl, trait_impl_id, diagnostics: diagnostics.build() })
3061}
3062
3063/// Computes implicit impl semantic data with cycle handling.
3064#[salsa::tracked(cycle_result=implicit_impl_impl_semantic_data_cycle, returns(ref))]
3065fn implicit_impl_impl_semantic_data_tracked<'db>(
3066    db: &'db dyn Database,
3067    impl_def_id: ImplDefId<'db>,
3068    trait_impl_id: TraitImplId<'db>,
3069    in_cycle: bool,
3070) -> Maybe<ImplicitImplImplData<'db>> {
3071    implicit_impl_impl_semantic_data(db, impl_def_id, trait_impl_id, in_cycle)
3072}
3073
3074/// Cycle handling for implicit impl semantic data computation.
3075fn implicit_impl_impl_semantic_data_cycle<'db>(
3076    db: &'db dyn Database,
3077    _id: salsa::Id,
3078    impl_def_id: ImplDefId<'db>,
3079    trait_impl_id: TraitImplId<'db>,
3080    _in_cycle: bool,
3081) -> Maybe<ImplicitImplImplData<'db>> {
3082    // Forwarding cycle handling to `implicit_impl_impl_semantic_data` handler.
3083    implicit_impl_impl_semantic_data(db, impl_def_id, trait_impl_id, true)
3084}
3085
3086// === Impl Impl ===
3087
3088/// Query implementation of [PrivImplSemantic::impl_impl_implized_by_context].
3089fn impl_impl_implized_by_context<'db>(
3090    db: &'db dyn Database,
3091    impl_impl_id: ImplImplId<'db>,
3092    impl_def_id: ImplDefId<'db>,
3093    in_cycle: bool,
3094) -> Maybe<ImplId<'db>> {
3095    if db.is_implicit_impl_impl(impl_def_id, impl_impl_id.trait_impl_id())? {
3096        return db.implicit_impl_impl_impl(impl_def_id, impl_impl_id.trait_impl_id(), in_cycle);
3097    }
3098
3099    let impl_impl_def_id = db.impl_impl_by_trait_impl(impl_def_id, impl_impl_id.trait_impl_id())?;
3100
3101    db.impl_impl_def_impl(impl_impl_def_id, in_cycle)
3102}
3103
3104/// Query implementation of [ImplSemantic::impl_impl_implized_by_context].
3105#[salsa::tracked(cycle_result=impl_impl_implized_by_context_cycle)]
3106fn impl_impl_implized_by_context_tracked<'db>(
3107    db: &'db dyn Database,
3108    impl_impl_id: ImplImplId<'db>,
3109    impl_def_id: ImplDefId<'db>,
3110    in_cycle: bool,
3111) -> Maybe<ImplId<'db>> {
3112    impl_impl_implized_by_context(db, impl_impl_id, impl_def_id, in_cycle)
3113}
3114
3115/// Cycle handling for [PrivImplSemantic::impl_impl_implized_by_context].
3116fn impl_impl_implized_by_context_cycle<'db>(
3117    db: &'db dyn Database,
3118    _id: salsa::Id,
3119    impl_impl_id: ImplImplId<'db>,
3120    impl_def_id: ImplDefId<'db>,
3121    _in_cycle: bool,
3122) -> Maybe<ImplId<'db>> {
3123    // Forwarding cycle handling to `impl_impl_semantic_data` handler.
3124    impl_impl_implized_by_context(db, impl_impl_id, impl_def_id, true)
3125}
3126
3127/// Implementation of [ImplSemantic::impl_impl_concrete_implized].
3128fn impl_impl_concrete_implized<'db>(
3129    db: &'db dyn Database,
3130    impl_impl_id: ImplImplId<'db>,
3131) -> Maybe<ImplId<'db>> {
3132    impl_impl_concrete_implized_ex(db, impl_impl_id, false)
3133}
3134
3135/// Query implementation of [ImplSemantic::impl_impl_concrete_implized].
3136fn impl_impl_concrete_implized_tracked<'db>(
3137    db: &'db dyn Database,
3138    impl_impl_id: ImplImplId<'db>,
3139) -> Maybe<ImplId<'db>> {
3140    impl_impl_concrete_implized_helper(db, (), impl_impl_id)
3141}
3142
3143#[salsa::tracked(cycle_result=impl_impl_concrete_implized_cycle)]
3144fn impl_impl_concrete_implized_helper<'db>(
3145    db: &'db dyn Database,
3146    _tracked: Tracked,
3147    impl_impl_id: ImplImplId<'db>,
3148) -> Maybe<ImplId<'db>> {
3149    impl_impl_concrete_implized(db, impl_impl_id)
3150}
3151
3152/// Cycle handling for [ImplSemantic::impl_impl_concrete_implized].
3153fn impl_impl_concrete_implized_cycle<'db>(
3154    db: &'db dyn Database,
3155    _id: salsa::Id,
3156    _tracked: Tracked,
3157    impl_impl_id: ImplImplId<'db>,
3158) -> Maybe<ImplId<'db>> {
3159    impl_impl_concrete_implized_ex(db, impl_impl_id, true)
3160}
3161
3162fn impl_impl_concrete_implized_ex<'db>(
3163    db: &'db dyn Database,
3164    impl_impl_id: ImplImplId<'db>,
3165    in_cycle: bool,
3166) -> Maybe<ImplId<'db>> {
3167    if let ImplLongId::Concrete(concrete_impl) = impl_impl_id.impl_id().long(db) {
3168        let impl_def_id = concrete_impl.impl_def_id(db);
3169        let imp = db.impl_impl_implized_by_context(impl_impl_id, impl_def_id, in_cycle)?;
3170        return concrete_impl.substitution(db)?.substitute(db, imp);
3171    }
3172
3173    Ok(ImplLongId::ImplImpl(
3174        GenericSubstitution::from_impl(impl_impl_id.impl_id()).substitute(db, impl_impl_id)?,
3175    )
3176    .intern(db))
3177}
3178
3179/// Implementation of [PrivImplSemantic::impl_impl_concrete_trait].
3180fn impl_impl_concrete_trait<'db>(
3181    db: &'db dyn Database,
3182    impl_impl_id: ImplImplId<'db>,
3183) -> Maybe<ConcreteTraitId<'db>> {
3184    let concrete_trait_impl = impl_impl_id.concrete_trait_impl_id(db)?;
3185    db.concrete_trait_impl_concrete_trait(concrete_trait_impl).and_then(|concrete_trait_id| {
3186        GenericSubstitution::from_impl(impl_impl_id.impl_id()).substitute(db, concrete_trait_id)
3187    })
3188}
3189
3190/// Query implementation of [PrivImplSemantic::impl_impl_concrete_trait].
3191fn impl_impl_concrete_trait_tracked<'db>(
3192    db: &'db dyn Database,
3193    impl_impl_id: ImplImplId<'db>,
3194) -> Maybe<ConcreteTraitId<'db>> {
3195    impl_impl_concrete_trait_helper(db, (), impl_impl_id)
3196}
3197
3198#[salsa::tracked]
3199fn impl_impl_concrete_trait_helper<'db>(
3200    db: &'db dyn Database,
3201    _tracked: Tracked,
3202    impl_impl_id: ImplImplId<'db>,
3203) -> Maybe<ConcreteTraitId<'db>> {
3204    impl_impl_concrete_trait(db, impl_impl_id)
3205}
3206
3207// === Impl Function Declaration ===
3208
3209#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
3210#[debug_db(dyn Database)]
3211struct ImplFunctionDeclarationData<'db> {
3212    function_declaration_data: FunctionDeclarationData<'db>,
3213    trait_function_id: Maybe<TraitFunctionId<'db>>,
3214}
3215
3216/// Returns the generic parameters data of an impl function.
3217#[salsa::tracked(returns(ref))]
3218fn impl_function_generic_params_data<'db>(
3219    db: &'db dyn Database,
3220    impl_function_id: ImplFunctionId<'db>,
3221) -> Maybe<GenericParamsData<'db>> {
3222    let module_id = impl_function_id.parent_module(db);
3223    let mut diagnostics = SemanticDiagnostics::new(module_id);
3224    let impl_def_id = impl_function_id.impl_def_id(db);
3225    let data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
3226    let function_syntax = &data.function_asts[&impl_function_id];
3227    let declaration = function_syntax.declaration(db);
3228    let inference_id = InferenceId::LookupItemGenerics(LookupItemId::ImplItem(
3229        ImplItemId::Function(impl_function_id),
3230    ));
3231    let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
3232    let mut resolver =
3233        Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
3234    let generic_params = semantic_generic_params(
3235        db,
3236        &mut diagnostics,
3237        &mut resolver,
3238        module_id,
3239        &declaration.generic_params(db),
3240    );
3241    let inference = &mut resolver.inference();
3242    inference.finalize(&mut diagnostics, function_syntax.stable_ptr(db).untyped());
3243
3244    let generic_params = inference.rewrite(generic_params).no_err();
3245    let resolver_data = Arc::new(resolver.data);
3246    Ok(GenericParamsData { generic_params, diagnostics: diagnostics.build(), resolver_data })
3247}
3248
3249/// Returns data about an impl function declaration.
3250#[salsa::tracked(returns(ref))]
3251fn impl_function_declaration_data<'db>(
3252    db: &'db dyn Database,
3253    impl_function_id: ImplFunctionId<'db>,
3254) -> Maybe<ImplFunctionDeclarationData<'db>> {
3255    let impl_def_id = impl_function_id.impl_def_id(db);
3256    let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
3257    let data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
3258    let function_syntax = &data.function_asts[&impl_function_id];
3259    let declaration = function_syntax.declaration(db);
3260
3261    let generic_params_data =
3262        impl_function_generic_params_data(db, impl_function_id).maybe_as_ref()?.clone();
3263    let generic_params = generic_params_data.generic_params;
3264    let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Function(impl_function_id));
3265    let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
3266    let mut resolver = Resolver::with_data(
3267        db,
3268        (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
3269    );
3270    diagnostics.extend(generic_params_data.diagnostics);
3271    resolver.set_feature_config(&impl_function_id, function_syntax, &mut diagnostics);
3272
3273    let mut environment = Environment::empty();
3274    let signature = semantic::Signature::from_ast(
3275        &mut diagnostics,
3276        db,
3277        &mut resolver,
3278        &declaration,
3279        FunctionTitleId::Impl(impl_function_id),
3280        &mut environment,
3281    );
3282
3283    let attributes = function_syntax.attributes(db).structurize(db);
3284    let (implicit_precedence, _) =
3285        get_implicit_precedence(db, &mut diagnostics, &mut resolver, &attributes);
3286
3287    let inference = &mut resolver.inference();
3288    // Check fully resolved.
3289    inference.finalize(&mut diagnostics, function_syntax.stable_ptr(db).untyped());
3290    let signature_syntax = declaration.signature(db);
3291    let trait_function_id = validate_impl_function_signature(
3292        db,
3293        &mut diagnostics,
3294        inference,
3295        ValidateImplFunctionSignatureParams {
3296            impl_function_id,
3297            signature_syntax: &signature_syntax,
3298            signature: &signature,
3299            impl_function_syntax: function_syntax,
3300            impl_func_generics: &generic_params,
3301        },
3302    );
3303
3304    let inline_config = get_inline_config(db, &mut diagnostics, &attributes)?;
3305
3306    forbid_inline_always_with_impl_generic_param(&mut diagnostics, &generic_params, &inline_config);
3307
3308    let signature = inference.rewrite(signature).no_err();
3309
3310    let resolver_data = Arc::new(resolver.data);
3311    Ok(ImplFunctionDeclarationData {
3312        function_declaration_data: FunctionDeclarationData {
3313            diagnostics: diagnostics.build(),
3314            signature,
3315            environment,
3316            attributes,
3317            resolver_data,
3318            inline_config,
3319            implicit_precedence,
3320        },
3321        trait_function_id,
3322    })
3323}
3324
3325/// Struct for the parameters of [validate_impl_function_signature].
3326struct ValidateImplFunctionSignatureParams<'a, 'r> {
3327    /// The impl function to validate the signature of.
3328    impl_function_id: ImplFunctionId<'a>,
3329    /// The signature syntax.
3330    signature_syntax: &'r ast::FunctionSignature<'a>,
3331    // The semantic signature.
3332    signature: &'r semantic::Signature<'a>,
3333    /// The impl function syntax.
3334    impl_function_syntax: &'r ast::FunctionWithBody<'a>,
3335    /// The generic parameters of the impl function.
3336    impl_func_generics: &'r [GenericParam<'a>],
3337}
3338
3339/// Validates the impl function, and returns the matching trait function id.
3340fn validate_impl_function_signature<'db>(
3341    db: &'db dyn Database,
3342    diagnostics: &mut SemanticDiagnostics<'db>,
3343    inference: &mut Inference<'db, '_>,
3344    ValidateImplFunctionSignatureParams {
3345        impl_function_id,
3346        signature_syntax,
3347        signature,
3348        impl_function_syntax,
3349        impl_func_generics,
3350    }: ValidateImplFunctionSignatureParams<'db, '_>,
3351) -> Maybe<TraitFunctionId<'db>> {
3352    let impl_def_id = impl_function_id.impl_def_id(db);
3353    let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
3354    let trait_id = concrete_trait_id.trait_id(db);
3355    let function_name = impl_function_id.name(db);
3356    let trait_function_id =
3357        db.trait_function_by_name(trait_id, function_name)?.ok_or_else(|| {
3358            diagnostics.report(
3359                impl_function_syntax.stable_ptr(db),
3360                ImplItemNotInTrait {
3361                    impl_def_id,
3362                    impl_item_name: function_name,
3363                    trait_id,
3364                    item_kind: "function".into(),
3365                },
3366            )
3367        })?;
3368    let concrete_trait_function =
3369        ConcreteTraitGenericFunctionId::new_from_data(db, concrete_trait_id, trait_function_id);
3370    let concrete_trait_signature = db.concrete_trait_function_signature(concrete_trait_function)?;
3371
3372    // Match generics of the function.
3373    // TODO(spapini): Compare the actual kinds and traits for the generic params.
3374
3375    let func_generics = db.concrete_trait_function_generic_params(concrete_trait_function)?;
3376    if impl_func_generics.len() != func_generics.len() {
3377        diagnostics.report(
3378            impl_function_syntax.declaration(db).name(db).stable_ptr(db),
3379            WrongNumberOfGenericParamsForImplFunction {
3380                expected: func_generics.len(),
3381                actual: impl_func_generics.len(),
3382            },
3383        );
3384        return Ok(trait_function_id);
3385    }
3386    let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
3387    let func_generics: Vec<GenericParam<'_>> =
3388        impl_def_substitution.substitute(db, func_generics.to_vec())?;
3389
3390    let function_substitution =
3391        GenericSubstitution::new(&func_generics, &generic_params_to_args(impl_func_generics, db));
3392
3393    for (trait_generic_param, generic_param) in izip!(func_generics, impl_func_generics.iter()) {
3394        if let Some(name) = trait_generic_param.id().name(db)
3395            && Some(name) != generic_param.id().name(db)
3396        {
3397            diagnostics.report(
3398                generic_param.stable_ptr(db),
3399                WrongParameterName { impl_def_id, impl_function_id, trait_id, expected_name: name },
3400            );
3401        }
3402        match (generic_param, trait_generic_param) {
3403            (GenericParam::Type(_), GenericParam::Type(_)) => {}
3404            (GenericParam::Impl(generic_param), GenericParam::Impl(trait_generic_param))
3405            | (GenericParam::NegImpl(generic_param), GenericParam::NegImpl(trait_generic_param)) => {
3406                let rewritten_trait_param_trait =
3407                    function_substitution.substitute(db, trait_generic_param.concrete_trait)?;
3408                let rewritten_trait_param_type_constraints =
3409                    function_substitution.substitute(db, trait_generic_param.type_constraints)?;
3410                generic_param
3411                    .concrete_trait
3412                    .map(|actual_trait| {
3413                        rewritten_trait_param_trait
3414                            .map(|expected_trait| {
3415                                if actual_trait != expected_trait
3416                                    || generic_param.type_constraints
3417                                        != rewritten_trait_param_type_constraints
3418                                {
3419                                    diagnostics.report(
3420                                        generic_param.id.stable_ptr(db),
3421                                        WrongGenericParamTraitForImplFunction {
3422                                            impl_def_id,
3423                                            impl_function_id,
3424                                            trait_id,
3425                                            expected_trait,
3426                                            actual_trait,
3427                                        },
3428                                    );
3429                                }
3430                            })
3431                            .ok();
3432                    })
3433                    .ok();
3434            }
3435            (GenericParam::Const(generic_param), GenericParam::Const(trait_generic_param)) => {
3436                let expected_ty = function_substitution.substitute(db, trait_generic_param.ty)?;
3437                if generic_param.ty != expected_ty {
3438                    diagnostics.report(
3439                        generic_param.id.stable_ptr(db),
3440                        WrongParameterType {
3441                            impl_def_id,
3442                            impl_function_id,
3443                            trait_id,
3444                            expected_ty,
3445                            actual_ty: generic_param.ty,
3446                        },
3447                    );
3448                }
3449            }
3450            (generic_param, trait_generic_param) => {
3451                diagnostics.report(
3452                    generic_param.stable_ptr(db),
3453                    WrongGenericParamKindForImplFunction {
3454                        impl_def_id,
3455                        impl_function_id,
3456                        trait_id,
3457                        expected_kind: trait_generic_param.kind(),
3458                        actual_kind: generic_param.kind(),
3459                    },
3460                );
3461            }
3462        }
3463    }
3464
3465    let concrete_trait_signature =
3466        function_substitution.substitute(db, concrete_trait_signature.clone())?;
3467
3468    if signature.params.len() != concrete_trait_signature.params.len() {
3469        diagnostics.report(
3470            signature_syntax.parameters(db).stable_ptr(db),
3471            WrongNumberOfParameters {
3472                impl_def_id,
3473                impl_function_id,
3474                trait_id,
3475                expected: concrete_trait_signature.params.len(),
3476                actual: signature.params.len(),
3477            },
3478        );
3479    }
3480    let concrete_trait_signature =
3481        impl_def_substitution.substitute(db, concrete_trait_signature)?;
3482    for (param, trait_param) in
3483        izip!(signature.params.iter(), concrete_trait_signature.params.iter())
3484    {
3485        let expected_ty = inference.rewrite(trait_param.ty).no_err();
3486        let actual_ty = inference.rewrite(param.ty).no_err();
3487
3488        if expected_ty != actual_ty && !expected_ty.is_missing(db) && !actual_ty.is_missing(db) {
3489            diagnostics.report(
3490                extract_matches!(
3491                    param.stable_ptr(db).lookup(db).type_clause(db),
3492                    OptionTypeClause::TypeClause
3493                )
3494                .ty(db)
3495                .stable_ptr(db),
3496                WrongParameterType {
3497                    impl_def_id,
3498                    impl_function_id,
3499                    trait_id,
3500                    expected_ty,
3501                    actual_ty,
3502                },
3503            );
3504        }
3505
3506        if trait_param.mutability != param.mutability {
3507            if trait_param.mutability == Mutability::Reference {
3508                diagnostics.report(
3509                    param.stable_ptr(db).lookup(db).modifiers(db).stable_ptr(db),
3510                    ParameterShouldBeReference { impl_def_id, impl_function_id, trait_id },
3511                );
3512            }
3513
3514            if param.mutability == Mutability::Reference {
3515                diagnostics.report(
3516                    param.stable_ptr(db).lookup(db).modifiers(db).stable_ptr(db),
3517                    ParameterShouldNotBeReference { impl_def_id, impl_function_id, trait_id },
3518                );
3519            }
3520        }
3521
3522        if trait_param.name != param.name {
3523            diagnostics.report(
3524                param.stable_ptr(db).lookup(db).name(db).stable_ptr(db),
3525                WrongParameterName {
3526                    impl_def_id,
3527                    impl_function_id,
3528                    trait_id,
3529                    expected_name: trait_param.name,
3530                },
3531            );
3532        }
3533    }
3534
3535    if !concrete_trait_signature.panicable && signature.panicable {
3536        diagnostics.report(
3537            signature_syntax.stable_ptr(db),
3538            PassPanicAsNopanic { impl_function_id, trait_id },
3539        );
3540    }
3541
3542    if concrete_trait_signature.is_const && !signature.is_const {
3543        diagnostics.report(
3544            signature_syntax.stable_ptr(db),
3545            PassConstAsNonConst { impl_function_id, trait_id },
3546        );
3547    }
3548
3549    let expected_ty = inference.rewrite(concrete_trait_signature.return_type).no_err();
3550    let actual_ty = inference.rewrite(signature.return_type).no_err();
3551
3552    if expected_ty != actual_ty && !expected_ty.is_missing(db) && !actual_ty.is_missing(db) {
3553        let location_ptr = match signature_syntax.ret_ty(db) {
3554            OptionReturnTypeClause::ReturnTypeClause(ret_ty) => ret_ty.ty(db).as_syntax_node(),
3555            OptionReturnTypeClause::Empty(_) => {
3556                impl_function_syntax.body(db).lbrace(db).as_syntax_node()
3557            }
3558        }
3559        .stable_ptr(db);
3560        diagnostics.report(
3561            location_ptr,
3562            WrongReturnTypeForImpl {
3563                impl_def_id,
3564                impl_function_id,
3565                trait_id,
3566                expected_ty,
3567                actual_ty,
3568            },
3569        );
3570    }
3571    Ok(trait_function_id)
3572}
3573
3574/// Computes impl function body data including diagnostics and resolver data.
3575fn priv_impl_function_body_data<'db>(
3576    db: &'db dyn Database,
3577    impl_function_id: ImplFunctionId<'db>,
3578) -> Maybe<FunctionBodyData<'db>> {
3579    let impl_def_id = impl_function_id.impl_def_id(db);
3580    let mut diagnostics = SemanticDiagnostics::new(impl_def_id.parent_module(db));
3581    let data = impl_definition_data(db, impl_def_id).maybe_as_ref()?;
3582    let function_syntax = &data.function_asts[&impl_function_id];
3583    // Compute declaration semantic.
3584    let declaration = impl_function_declaration_data(db, impl_function_id).maybe_as_ref()?;
3585    let parent_resolver_data = declaration.function_declaration_data.resolver_data.clone();
3586    let inference_id = InferenceId::LookupItemDefinition(LookupItemId::ImplItem(
3587        ImplItemId::Function(impl_function_id),
3588    ));
3589    let mut resolver =
3590        Resolver::with_data(db, (*parent_resolver_data).clone_with_inference_id(db, inference_id));
3591    let environment: Environment<'_> = declaration.function_declaration_data.environment.clone();
3592
3593    let function_id = (|| {
3594        let trait_function_id = db.impl_function_trait_function(impl_function_id)?;
3595        let generic_parameters = db.impl_def_generic_params(impl_def_id)?;
3596
3597        let generic_function = GenericFunctionId::Impl(ImplGenericFunctionId {
3598            impl_id: ImplLongId::Concrete(
3599                ConcreteImplLongId {
3600                    impl_def_id,
3601                    generic_args: generic_params_to_args(generic_parameters, db),
3602                }
3603                .intern(db),
3604            )
3605            .intern(db),
3606            function: trait_function_id,
3607        });
3608
3609        Ok(FunctionLongId::from_generic(db, generic_function)?.intern(db))
3610    })();
3611    // Compute body semantic expr.
3612    let mut ctx = ComputationContext::new(
3613        db,
3614        &mut diagnostics,
3615        &mut resolver,
3616        Some(&declaration.function_declaration_data.signature),
3617        environment,
3618        ContextFunction::Function(function_id),
3619    );
3620    let function_body = function_syntax.body(db);
3621    let return_type = declaration.function_declaration_data.signature.return_type;
3622    let body_expr = compute_root_expr(&mut ctx, &function_body, return_type)?;
3623    let ComputationContext { arenas, .. } = ctx;
3624
3625    let expr_lookup: UnorderedHashMap<_, _> =
3626        arenas.exprs.iter().map(|(id, expr)| (expr.stable_ptr(), id)).collect();
3627    let pattern_lookup: UnorderedHashMap<_, _> =
3628        arenas.patterns.iter().map(|(id, pattern)| (pattern.stable_ptr(), id)).collect();
3629    let resolver_data = Arc::new(resolver.data);
3630    Ok(FunctionBodyData {
3631        diagnostics: diagnostics.build(),
3632        expr_lookup,
3633        pattern_lookup,
3634        resolver_data,
3635        body: FunctionBody { arenas, body_expr },
3636    })
3637}
3638
3639/// Computes impl function body data.
3640#[salsa::tracked(returns(ref))]
3641fn priv_impl_function_body_data_tracked<'db>(
3642    db: &'db dyn Database,
3643    impl_function_id: ImplFunctionId<'db>,
3644) -> Maybe<FunctionBodyData<'db>> {
3645    priv_impl_function_body_data(db, impl_function_id)
3646}
3647
3648#[salsa::tracked]
3649fn impl_is_fully_concrete<'db>(db: &'db dyn Database, impl_id: ImplId<'db>) -> bool {
3650    impl_id.long(db).is_fully_concrete(db)
3651}
3652
3653#[salsa::tracked]
3654fn impl_is_var_free<'db>(db: &'db dyn Database, impl_id: ImplId<'db>) -> bool {
3655    impl_id.long(db).is_var_free(db)
3656}
3657
3658/// Returns crate dependencies.
3659#[salsa::tracked(returns(ref))]
3660fn crate_dependencies<'db>(
3661    db: &'db dyn Database,
3662    crate_id: CrateId<'db>,
3663) -> OrderedHashSet<CrateId<'db>> {
3664    let mut crates = [crate_id, db.core_crate()].into_iter().unique().collect_vec();
3665    let mut crates_set: OrderedHashSet<CrateId<'db>, _> = OrderedHashSet::<
3666        CrateId<'db>,
3667        std::collections::hash_map::RandomState,
3668    >::from_iter(crates.iter().copied());
3669    while let Some(crate_id) = crates.pop() {
3670        let default_settings = Default::default();
3671        let settings =
3672            db.crate_config(crate_id).as_ref().map(|c| &c.settings).unwrap_or(&default_settings);
3673
3674        for (ident, dep) in &settings.dependencies {
3675            let dep_crate_id = CrateLongId::Real {
3676                name: SmolStrId::from(db, ident.clone()),
3677                discriminator: dep.discriminator.clone(),
3678            }
3679            .intern(db);
3680            if !crates_set.contains(&dep_crate_id) {
3681                crates.push(dep_crate_id);
3682                crates_set.insert(dep_crate_id);
3683            }
3684        }
3685    }
3686    crates_set
3687}
3688
3689#[salsa::tracked(returns(ref))]
3690/// Query implementation of [PrivImplSemantic::crate_global_impls].
3691fn crate_global_impls<'db>(
3692    db: &'db dyn Database,
3693    crate_id: CrateId<'db>,
3694) -> UnorderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>> {
3695    let mut crate_global_impls: UnorderedHashMap<
3696        TraitId<'db>,
3697        OrderedHashSet<UninferredImplById<'db>>,
3698    > = UnorderedHashMap::default();
3699    for crate_id in crate_dependencies(db, crate_id).iter() {
3700        let mut modules = vec![ModuleId::CrateRoot(*crate_id)];
3701        while let Some(module_id) = modules.pop() {
3702            if let Ok(module_impls) = db.module_global_impls((), module_id) {
3703                for (trait_id, impls) in module_impls.globals_by_trait.iter() {
3704                    crate_global_impls.entry(*trait_id).or_default().extend(impls.clone());
3705                }
3706            }
3707            if let Ok(x) = db.module_submodules_ids(module_id) {
3708                modules.extend(x.iter().map(|sub_module| ModuleId::Submodule(*sub_module)));
3709            }
3710            if let Ok(macro_call_ids) = db.module_macro_calls_ids(module_id) {
3711                modules.extend(
3712                    macro_call_ids
3713                        .iter()
3714                        .map(|id| db.macro_call_module_id(*id))
3715                        .filter_map(|x| x.ok()),
3716                )
3717            }
3718        }
3719    }
3720    crate_global_impls
3721}
3722
3723/// Query implementation of [PrivImplSemantic::crate_traits_dependencies].
3724#[salsa::tracked(returns(ref))]
3725fn crate_traits_dependencies<'db>(
3726    db: &'db dyn Database,
3727    crate_id: CrateId<'db>,
3728) -> UnorderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>> {
3729    let mut dependencies: UnorderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>> =
3730        UnorderedHashMap::default();
3731    for crate_id in crate_dependencies(db, crate_id).iter() {
3732        let mut modules = vec![ModuleId::CrateRoot(*crate_id)];
3733        while let Some(module_id) = modules.pop() {
3734            if let Ok(module_impls) = db.module_global_impls((), module_id) {
3735                for (trait_id, impls) in module_impls.trait_deps.iter() {
3736                    dependencies.entry(*trait_id).or_default().extend(impls.clone());
3737                }
3738            }
3739            if let Ok(x) = db.module_submodules_ids(module_id) {
3740                modules.extend(x.iter().map(|sub_module| ModuleId::Submodule(*sub_module)));
3741            }
3742        }
3743    }
3744
3745    dependencies
3746}
3747
3748/// Query implementation of [PrivImplSemantic::reachable_trait_dependencies].
3749#[salsa::tracked(returns(ref))]
3750fn reachable_trait_dependencies<'db>(
3751    db: &'db dyn Database,
3752    trait_id: TraitId<'db>,
3753    crate_id: CrateId<'db>,
3754) -> OrderedHashSet<TraitId<'db>> {
3755    let dependencies = db.crate_traits_dependencies(crate_id);
3756    let mut reachable_deps = OrderedHashSet::default();
3757    let mut to_visit = vec![trait_id];
3758    let mut visited: UnorderedHashSet<TraitId<'db>> = UnorderedHashSet::default();
3759    while let Some(current_trait) = to_visit.pop() {
3760        if visited.contains(&current_trait) {
3761            continue;
3762        }
3763        visited.insert(current_trait);
3764        if let Some(deps) = dependencies.get(&current_trait) {
3765            for dep in deps.iter() {
3766                reachable_deps.insert(*dep);
3767                if !visited.contains(dep) {
3768                    to_visit.push(*dep);
3769                }
3770            }
3771        }
3772    }
3773    reachable_deps
3774}
3775
3776/// Adds the trait dependencies of an uninferred impl to the trait_deps map.
3777fn uninferred_impl_trait_dependency<'db>(
3778    db: &'db dyn Database,
3779    impl_id: UninferredImpl<'db>,
3780    trait_deps: &mut OrderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>>,
3781) -> Maybe<()> {
3782    if let Ok(imp_trait_id) = impl_id.trait_id(db) {
3783        let (mut resolver, module_id, generic_params, mut diagnostics) = match impl_id {
3784            UninferredImpl::Def(impl_def_id) => {
3785                let module_id = impl_def_id.parent_module(db);
3786                let mut diagnostics = SemanticDiagnostics::new(module_id);
3787
3788                let impl_ast = db.module_impl_by_id(impl_def_id)?;
3789                let inference_id = InferenceId::ImplDefTrait(impl_def_id);
3790
3791                let mut resolver = Resolver::new(db, module_id, inference_id);
3792                resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
3793                (resolver, module_id, impl_ast.generic_params(db), diagnostics)
3794            }
3795            UninferredImpl::ImplAlias(impl_alias_id) => {
3796                let module_id = impl_alias_id.parent_module(db);
3797                let mut diagnostics = SemanticDiagnostics::new(module_id);
3798
3799                let impl_ast = db.module_impl_alias_by_id(impl_alias_id)?;
3800                let inference_id = InferenceId::ImplAliasImplDef(impl_alias_id);
3801
3802                let mut resolver = Resolver::new(db, module_id, inference_id);
3803                resolver.set_feature_config(&impl_alias_id, &impl_ast, &mut diagnostics);
3804                (resolver, module_id, impl_ast.generic_params(db), diagnostics)
3805            }
3806            _ => {
3807                return Ok(());
3808            }
3809        };
3810        if let OptionWrappedGenericParamList::WrappedGenericParamList(params_list) = generic_params
3811        {
3812            params_list.generic_params(db).elements(db).for_each(|param_syntax| {
3813                let generic_param_id =
3814                    GenericParamLongId(module_id, param_syntax.stable_ptr(db)).intern(db);
3815                resolver.add_generic_param(generic_param_id);
3816                let trait_path = match param_syntax {
3817                    ast::GenericParam::ImplNamed(param) => param.trait_path(db),
3818                    ast::GenericParam::ImplAnonymous(param) => param.trait_path(db),
3819                    ast::GenericParam::NegativeImpl(param) => param.trait_path(db),
3820
3821                    _ => return,
3822                };
3823                let dependant_trait_id =
3824                    resolve_trait_path(db, &mut diagnostics, &mut resolver, &trait_path);
3825
3826                let Ok(dependant_trait_id) = dependant_trait_id else {
3827                    return;
3828                };
3829                trait_deps.entry(imp_trait_id).or_default().insert(dependant_trait_id);
3830            })
3831        };
3832    };
3833    Ok(())
3834}
3835
3836#[derive(Default, Debug, Eq, PartialEq, salsa::Update)]
3837struct ModuleImpls<'db> {
3838    globals_by_trait: OrderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>>,
3839    trait_deps: OrderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>>,
3840    globals_by_type: OrderedHashMap<TypeId<'db>, Vec<UninferredImpl<'db>>>,
3841
3842    locals: BTreeSet<UninferredImplById<'db>>,
3843}
3844
3845#[salsa::tracked(returns(ref))]
3846fn module_global_impls<'db>(
3847    db: &'db dyn Database,
3848    _tracked: Tracked,
3849    module_id: ModuleId<'db>,
3850) -> Maybe<ModuleImpls<'db>> {
3851    let mut module_impls = ModuleImpls::default();
3852    for (containing_module, info) in db.module_imported_modules((), module_id).iter() {
3853        for defined_module in module_macro_modules(db, true, *containing_module) {
3854            let Ok(module_semantic_data) = db.priv_module_semantic_data(*defined_module) else {
3855                continue;
3856            };
3857            for item in module_semantic_data.items.values().filter(|item| {
3858                info.user_modules.iter().any(|user_module| {
3859                    peek_visible_in(db, item.visibility, *containing_module, *user_module)
3860                })
3861            }) {
3862                let imp = match item.item_id {
3863                    ModuleItemId::Use(use_id) => match db.use_resolved_item(use_id) {
3864                        Ok(ResolvedGenericItem::Impl(impl_def_id)) => {
3865                            UninferredImpl::Def(impl_def_id)
3866                        }
3867                        Ok(ResolvedGenericItem::GenericImplAlias(impl_alias_id)) => {
3868                            UninferredImpl::ImplAlias(impl_alias_id)
3869                        }
3870                        _ => continue,
3871                    },
3872                    ModuleItemId::Impl(impl_def_id) => {
3873                        if let Ok(impl_ast) = db.module_impl_by_id(impl_def_id) {
3874                            global_impls_insert_generic_impls(
3875                                db,
3876                                &impl_ast.generic_params(db),
3877                                impl_def_id.parent_module(db),
3878                                &mut module_impls.globals_by_trait,
3879                            );
3880                        }
3881
3882                        // TODO(TomerStarkware): Add the generic impls of the functions in the impl.
3883
3884                        UninferredImpl::Def(impl_def_id)
3885                    }
3886                    // TODO(TomerStarkware): Add the generic impls of the ImplAlias.
3887                    ModuleItemId::ImplAlias(impl_alias_id) => {
3888                        UninferredImpl::ImplAlias(impl_alias_id)
3889                    }
3890                    ModuleItemId::FreeFunction(free_function_id) => {
3891                        if let Ok(function_ast) = db.module_free_function_by_id(free_function_id) {
3892                            let declaration = function_ast.declaration(db);
3893                            global_impls_insert_generic_impls(
3894                                db,
3895                                &declaration.generic_params(db),
3896                                free_function_id.parent_module(db),
3897                                &mut module_impls.globals_by_trait,
3898                            );
3899                        }
3900                        continue;
3901                    }
3902                    _ => continue,
3903                };
3904
3905                uninferred_impl_trait_dependency(db, imp, &mut module_impls.trait_deps)?;
3906
3907                if let Ok(true) = is_global_impl(db, imp, module_id) {
3908                    let trait_id = imp.trait_id(db)?;
3909                    module_impls.globals_by_trait.entry(trait_id).or_default().insert(imp.into());
3910                } else {
3911                    module_impls.locals.insert(imp.into());
3912                }
3913            }
3914        }
3915    }
3916
3917    Ok(module_impls)
3918}
3919
3920/// Checks if an impl is global.
3921/// An impl is global if it is defined in the same module as the trait it implements or in the same
3922/// module as one of its concrete traits' types.
3923fn is_global_impl<'db>(
3924    db: &'db dyn Database,
3925    impl_id: UninferredImpl<'db>,
3926    impl_module: ModuleId<'db>,
3927) -> Maybe<bool> {
3928    let trait_id = impl_id.trait_id(db)?;
3929    if trait_id.parent_module(db) == impl_module {
3930        return Ok(true);
3931    }
3932
3933    Ok(impl_id
3934        .trait_shallow_generic_args(db)?
3935        .iter()
3936        .any(|(_, arg)| arg.module_id(db) == Some(impl_module)))
3937}
3938
3939/// Inserts the generic impls of a function or impl into the globals_by_trait map.
3940/// A generic impl is global if one of its generic arguments is a generic type which is defined in
3941/// the same parameter list as the impl.
3942fn global_impls_insert_generic_impls<'db>(
3943    db: &'db dyn Database,
3944    generic_params: &ast::OptionWrappedGenericParamList<'db>,
3945    module_id: ModuleId<'db>,
3946    globals_by_trait: &mut OrderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>>,
3947) {
3948    let ast::OptionWrappedGenericParamList::WrappedGenericParamList(generic_params) =
3949        generic_params
3950    else {
3951        return;
3952    };
3953    let mut generic_types = OrderedHashMap::<_, GenericParamId<'db>, _>::default();
3954    for param in generic_params.generic_params(db).elements(db) {
3955        let (trait_path, type_constraints) = match &param {
3956            ast::GenericParam::Type(_) => {
3957                let param_id = GenericParamLongId(module_id, param.stable_ptr(db)).intern(db);
3958                if let Some(name) = param_id.name(db) {
3959                    generic_types.insert(name, param_id);
3960                }
3961                continue;
3962            }
3963            ast::GenericParam::ImplNamed(impl_param) => {
3964                (impl_param.trait_path(db), impl_param.type_constrains(db))
3965            }
3966            ast::GenericParam::ImplAnonymous(impl_param) => {
3967                (impl_param.trait_path(db), impl_param.type_constrains(db))
3968            }
3969            _ => continue,
3970        };
3971        if is_global_impl_generic_param(db, &generic_types, &trait_path) {
3972            let uninferred_impl = UninferredImpl::GenericParam(
3973                GenericParamLongId(module_id, param.stable_ptr(db)).intern(db),
3974            );
3975            if let Ok(trait_id) = uninferred_impl.trait_id(db) {
3976                if trait_id == db.core_info().type_eq_trt {
3977                    continue;
3978                }
3979                if matches!(
3980                    type_constraints,
3981                    ast::OptionAssociatedItemConstraints::AssociatedItemConstraints(_)
3982                ) {
3983                    continue;
3984                }
3985                globals_by_trait.entry(trait_id).or_default().insert(uninferred_impl.into());
3986            }
3987        }
3988    }
3989}
3990
3991/// Returns true if a generic parameter impl is global.
3992fn is_global_impl_generic_param<'db>(
3993    db: &'db dyn Database,
3994    generic_types: &OrderedHashMap<SmolStrId<'db>, GenericParamId<'db>>,
3995    trait_syntax: &ast::ExprPath<'db>,
3996) -> bool {
3997    let trait_segments = trait_syntax.to_segments(db);
3998    let ast::PathSegment::WithGenericArgs(trait_segment) = trait_segments.last().unwrap() else {
3999        return false;
4000    };
4001
4002    let generic_args = trait_segment.generic_args(db);
4003
4004    for arg in generic_args.generic_args(db).elements(db) {
4005        let mut expr = match arg {
4006            ast::GenericArg::Unnamed(arg) => arg.value(db),
4007            ast::GenericArg::Named(arg) => arg.value(db),
4008        };
4009
4010        while let ast::Expr::Unary(unary_expr) = &expr {
4011            if !matches!(unary_expr.op(db), UnaryOperator::At(_)) {
4012                break;
4013            }
4014
4015            expr = unary_expr.expr(db);
4016        }
4017
4018        let ast::Expr::Path(path) = expr else {
4019            continue;
4020        };
4021        let path_segments = path.to_segments(db);
4022        let [segment] = path_segments.as_slice() else {
4023            continue;
4024        };
4025
4026        let ast::PathSegment::Simple(simple_segment) = segment else {
4027            continue;
4028        };
4029        if generic_types.contains_key(&simple_segment.identifier(db)) {
4030            return true;
4031        }
4032    }
4033
4034    false
4035}
4036
4037/// Trait for impl-related semantic queries.
4038pub trait ImplSemantic<'db>: Database {
4039    /// Returns the semantic declaration diagnostics of an impl.
4040    fn impl_semantic_declaration_diagnostics(
4041        &'db self,
4042        impl_def_id: ImplDefId<'db>,
4043    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4044        impl_declaration_data(self.as_dyn_database(), impl_def_id)
4045            .as_ref()
4046            .map(|data| data.diagnostics.clone())
4047            .unwrap_or_default()
4048    }
4049    /// Returns the generic parameters of an impl.
4050    fn impl_def_generic_params(
4051        &'db self,
4052        impl_def_id: ImplDefId<'db>,
4053    ) -> Maybe<&'db [GenericParam<'db>]> {
4054        Ok(&impl_def_generic_params_data(self.as_dyn_database(), impl_def_id)
4055            .maybe_as_ref()?
4056            .generic_params)
4057    }
4058    /// Returns the resolution resolved_items of an impl.
4059    fn impl_def_resolver_data(
4060        &'db self,
4061        impl_def_id: ImplDefId<'db>,
4062    ) -> Maybe<Arc<ResolverData<'db>>> {
4063        Ok(impl_declaration_data(self.as_dyn_database(), impl_def_id)
4064            .maybe_as_ref()?
4065            .resolver_data
4066            .clone())
4067    }
4068    /// Returns the concrete trait that is implemented by the impl.
4069    fn impl_def_concrete_trait(
4070        &'db self,
4071        impl_def_id: ImplDefId<'db>,
4072    ) -> Maybe<ConcreteTraitId<'db>> {
4073        impl_declaration_data(self.as_dyn_database(), impl_def_id).maybe_as_ref()?.concrete_trait
4074    }
4075    /// Returns the attributes attached to the impl.
4076    fn impl_def_attributes(&'db self, impl_def_id: ImplDefId<'db>) -> Maybe<&'db [Attribute<'db>]> {
4077        Ok(&impl_declaration_data(self.as_dyn_database(), impl_def_id).maybe_as_ref()?.attributes)
4078    }
4079    /// Returns the concrete trait that is implemented by the concrete impl.
4080    fn impl_concrete_trait(&'db self, impl_id: ImplId<'db>) -> Maybe<ConcreteTraitId<'db>> {
4081        impl_concrete_trait_tracked(self.as_dyn_database(), impl_id)
4082    }
4083    /// Returns the trait that is implemented by the impl, or an error if the RHS of the `of` is not
4084    /// a trait.
4085    fn impl_def_trait(&'db self, impl_def_id: ImplDefId<'db>) -> Maybe<TraitId<'db>> {
4086        impl_def_trait(self.as_dyn_database(), impl_def_id)
4087    }
4088    /// Returns the semantic definition diagnostics of an impl.
4089    fn impl_semantic_definition_diagnostics(
4090        &'db self,
4091        impl_def_id: ImplDefId<'db>,
4092    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4093        impl_semantic_definition_diagnostics_tracked(self.as_dyn_database(), impl_def_id)
4094    }
4095    /// Returns the metadata for an impl item, by the given `name`, if exists.
4096    fn impl_item_info_by_name(
4097        &'db self,
4098        impl_def_id: ImplDefId<'db>,
4099        name: SmolStrId<'db>,
4100    ) -> Maybe<Option<ImplItemInfo<'db>>> {
4101        impl_item_info_by_name_tracked(self.as_dyn_database(), impl_def_id, name)
4102    }
4103    /// Returns all the items used within the impl.
4104    fn impl_all_used_uses(
4105        &'db self,
4106        impl_def_id: ImplDefId<'db>,
4107    ) -> Maybe<&'db OrderedHashSet<UseId<'db>>> {
4108        impl_all_used_uses(self.as_dyn_database(), impl_def_id).maybe_as_ref()
4109    }
4110    /// Returns the type items in the impl.
4111    fn impl_types(
4112        &'db self,
4113        impl_def_id: ImplDefId<'db>,
4114    ) -> Maybe<&'db OrderedHashMap<ImplTypeDefId<'db>, ast::ItemTypeAlias<'db>>> {
4115        Ok(&impl_definition_data(self.as_dyn_database(), impl_def_id)
4116            .maybe_as_ref()?
4117            .item_type_asts)
4118    }
4119    /// Returns the impl type item that matches the given trait type item, if exists.
4120    fn impl_type_by_trait_type(
4121        &'db self,
4122        impl_def_id: ImplDefId<'db>,
4123        trait_type_id: TraitTypeId<'db>,
4124    ) -> Maybe<ImplTypeDefId<'db>> {
4125        impl_type_by_trait_type_tracked(self.as_dyn_database(), impl_def_id, trait_type_id)
4126    }
4127    /// Returns the constant items in the impl.
4128    fn impl_constants(
4129        &'db self,
4130        impl_def_id: ImplDefId<'db>,
4131    ) -> Maybe<&'db OrderedHashMap<ImplConstantDefId<'db>, ast::ItemConstant<'db>>> {
4132        Ok(&impl_definition_data(self.as_dyn_database(), impl_def_id)
4133            .maybe_as_ref()?
4134            .item_constant_asts)
4135    }
4136    /// Returns the functions in the impl.
4137    fn impl_functions(
4138        &'db self,
4139        impl_def_id: ImplDefId<'db>,
4140    ) -> Maybe<&'db OrderedHashMap<SmolStrId<'db>, ImplFunctionId<'db>>> {
4141        impl_functions(self.as_dyn_database(), impl_def_id).maybe_as_ref()
4142    }
4143
4144    // Impl type def.
4145    // ================
4146    /// Returns the resolved type of an impl item type.
4147    fn impl_type_def_resolved_type(&'db self, id: ImplTypeDefId<'db>) -> Maybe<TypeId<'db>> {
4148        impl_type_semantic_data(self.as_dyn_database(), id, false)
4149            .maybe_as_ref()?
4150            .type_alias_data
4151            .resolved_type
4152    }
4153    /// Returns the generic parameters of an impl item type.
4154    fn impl_type_def_generic_params(
4155        &'db self,
4156        id: ImplTypeDefId<'db>,
4157    ) -> Maybe<Vec<GenericParam<'db>>> {
4158        Ok(impl_type_def_generic_params_data(self.as_dyn_database(), id)
4159            .maybe_as_ref()?
4160            .generic_params
4161            .clone())
4162    }
4163    /// Returns the attributes of an impl type.
4164    fn impl_type_def_attributes(&'db self, id: ImplTypeDefId<'db>) -> Maybe<&'db [Attribute<'db>]> {
4165        Ok(&impl_type_semantic_data(self.as_dyn_database(), id, false)
4166            .maybe_as_ref()?
4167            .type_alias_data
4168            .attributes)
4169    }
4170    /// Returns the resolution resolved_items of an impl item type.
4171    fn impl_type_def_resolver_data(
4172        &'db self,
4173        id: ImplTypeDefId<'db>,
4174    ) -> Maybe<Arc<ResolverData<'db>>> {
4175        Ok(impl_type_semantic_data(self.as_dyn_database(), id, false)
4176            .maybe_as_ref()?
4177            .type_alias_data
4178            .resolver_data
4179            .clone())
4180    }
4181    /// Returns the deref chain and diagnostics for a given type.
4182    fn deref_chain(
4183        &'db self,
4184        ty: TypeId<'db>,
4185        crate_id: CrateId<'db>,
4186        try_deref_mut: bool,
4187    ) -> Maybe<&'db DerefChain<'db>> {
4188        deref_chain(self.as_dyn_database(), ty, crate_id, try_deref_mut).maybe_as_ref()
4189    }
4190
4191    // Impl type.
4192    // ================
4193    /// Returns the implized impl type if the impl is concrete. Returns a TypeId that's not an impl
4194    /// type with a concrete impl.
4195    // TODO(Gil): Consider removing the cycle handling here if we will upgrade the salsa version.
4196    fn impl_type_concrete_implized(
4197        &'db self,
4198        impl_type_def_id: ImplTypeId<'db>,
4199    ) -> Maybe<TypeId<'db>> {
4200        impl_type_concrete_implized_tracked(self.as_dyn_database(), impl_type_def_id)
4201    }
4202
4203    // Impl constant def.
4204    // ================
4205    /// Returns the resolved constant value of an impl item constant.
4206    fn impl_constant_def_value(&'db self, id: ImplConstantDefId<'db>) -> Maybe<ConstValueId<'db>> {
4207        Ok(impl_constant_semantic_data(self.as_dyn_database(), id, false)
4208            .maybe_as_ref()?
4209            .constant_data
4210            .const_value)
4211    }
4212    /// Returns the resolution resolved_items of an impl item constant.
4213    fn impl_constant_def_resolver_data(
4214        &'db self,
4215        id: ImplConstantDefId<'db>,
4216    ) -> Maybe<Arc<ResolverData<'db>>> {
4217        Ok(impl_constant_semantic_data(self.as_dyn_database(), id, false)
4218            .maybe_as_ref()?
4219            .constant_data
4220            .resolver_data
4221            .clone())
4222    }
4223
4224    // Impl constant.
4225    // ================
4226    /// Returns the implized impl constant value if the impl is concrete.
4227    // TODO(Gil): Consider removing the cycle handling here if we will upgrade the salsa version.
4228    fn impl_constant_concrete_implized_value(
4229        &'db self,
4230        impl_constant_id: ImplConstantId<'db>,
4231    ) -> Maybe<ConstValueId<'db>> {
4232        impl_constant_concrete_implized_value_tracked(self.as_dyn_database(), impl_constant_id)
4233    }
4234    /// Returns the implized impl constant type if the impl is concrete.
4235    // TODO(Gil): Consider removing the cycle handling here if we will upgrade the salsa version.
4236    fn impl_constant_concrete_implized_type(
4237        &'db self,
4238        impl_constant_id: ImplConstantId<'db>,
4239    ) -> Maybe<TypeId<'db>> {
4240        impl_constant_concrete_implized_type_tracked(self.as_dyn_database(), impl_constant_id)
4241    }
4242
4243    // Impl impl def.
4244    // ================
4245    /// Returns the resolution resolved_items of an impl item impl.
4246    fn impl_impl_def_resolver_data(
4247        &'db self,
4248        id: ImplImplDefId<'db>,
4249    ) -> Maybe<Arc<ResolverData<'db>>> {
4250        Ok(impl_impl_semantic_data(self.as_dyn_database(), id, false)
4251            .maybe_as_ref()?
4252            .impl_data
4253            .resolver_data
4254            .clone())
4255    }
4256
4257    // Impl impl.
4258    // ================
4259    /// Returns the implized impl impl value if the impl is concrete.
4260    fn impl_impl_concrete_implized(&'db self, impl_impl_id: ImplImplId<'db>) -> Maybe<ImplId<'db>> {
4261        impl_impl_concrete_implized_tracked(self.as_dyn_database(), impl_impl_id)
4262    }
4263
4264    // Impl function.
4265    // ================
4266    /// Returns the semantic diagnostics of an impl function's declaration (signature).
4267    fn impl_function_declaration_diagnostics(
4268        &'db self,
4269        id: ImplFunctionId<'db>,
4270    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4271        impl_function_declaration_data(self.as_dyn_database(), id)
4272            .as_ref()
4273            .map(|data| data.function_declaration_data.diagnostics.clone())
4274            .unwrap_or_default()
4275    }
4276    /// Returns the signature of an impl function.
4277    fn impl_function_signature(
4278        &'db self,
4279        id: ImplFunctionId<'db>,
4280    ) -> Maybe<&'db semantic::Signature<'db>> {
4281        Ok(&impl_function_declaration_data(self.as_dyn_database(), id)
4282            .maybe_as_ref()?
4283            .function_declaration_data
4284            .signature)
4285    }
4286    /// Returns the generic params of an impl function.
4287    fn impl_function_generic_params(
4288        &'db self,
4289        id: ImplFunctionId<'db>,
4290    ) -> Maybe<&'db [GenericParam<'db>]> {
4291        Ok(&impl_function_generic_params_data(self.as_dyn_database(), id)
4292            .maybe_as_ref()?
4293            .generic_params)
4294    }
4295    /// Returns the attributes of an impl function.
4296    fn impl_function_attributes(
4297        &'db self,
4298        id: ImplFunctionId<'db>,
4299    ) -> Maybe<&'db [Attribute<'db>]> {
4300        Ok(&impl_function_declaration_data(self.as_dyn_database(), id)
4301            .maybe_as_ref()?
4302            .function_declaration_data
4303            .attributes)
4304    }
4305    /// Returns the resolution resolved_items of an impl function's declaration.
4306    fn impl_function_resolver_data(
4307        &'db self,
4308        id: ImplFunctionId<'db>,
4309    ) -> Maybe<Arc<ResolverData<'db>>> {
4310        Ok(impl_function_declaration_data(self.as_dyn_database(), id)
4311            .maybe_as_ref()?
4312            .function_declaration_data
4313            .resolver_data
4314            .clone())
4315    }
4316    /// Returns the inline configuration of an impl function's declaration.
4317    fn impl_function_declaration_inline_config(
4318        &'db self,
4319        id: ImplFunctionId<'db>,
4320    ) -> Maybe<InlineConfiguration<'db>> {
4321        Ok(impl_function_declaration_data(self.as_dyn_database(), id)
4322            .maybe_as_ref()?
4323            .function_declaration_data
4324            .inline_config
4325            .clone())
4326    }
4327    /// Returns the implicits precedence of an impl function.
4328    fn impl_function_declaration_implicit_precedence(
4329        &'db self,
4330        id: ImplFunctionId<'db>,
4331    ) -> Maybe<&'db ImplicitPrecedence<'db>> {
4332        Ok(&impl_function_declaration_data(self.as_dyn_database(), id)
4333            .maybe_as_ref()?
4334            .function_declaration_data
4335            .implicit_precedence)
4336    }
4337    /// Returns the trait function of an impl function.
4338    fn impl_function_trait_function(
4339        &'db self,
4340        id: ImplFunctionId<'db>,
4341    ) -> Maybe<TraitFunctionId<'db>> {
4342        impl_function_declaration_data(self.as_dyn_database(), id).maybe_as_ref()?.trait_function_id
4343    }
4344    /// Returns the semantic diagnostics of an impl function definition (declaration + body).
4345    fn impl_function_body_diagnostics(
4346        &'db self,
4347        impl_function_id: ImplFunctionId<'db>,
4348    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4349        self.priv_impl_function_body_data(impl_function_id)
4350            .map(|data| data.diagnostics.clone())
4351            .unwrap_or_default()
4352    }
4353    /// Returns the definition of an impl function.
4354    fn impl_function_body(
4355        &'db self,
4356        impl_function_id: ImplFunctionId<'db>,
4357    ) -> Maybe<&'db FunctionBody<'db>> {
4358        Ok(&self.priv_impl_function_body_data(impl_function_id)?.body)
4359    }
4360    /// Returns the resolution resolved_items of an impl function's definition.
4361    fn impl_function_body_resolver_data(
4362        &'db self,
4363        impl_function_id: ImplFunctionId<'db>,
4364    ) -> Maybe<Arc<ResolverData<'db>>> {
4365        Ok(self.priv_impl_function_body_data(impl_function_id)?.resolver_data.clone())
4366    }
4367    /// Private query to compute data about an impl function definition (declaration + body)
4368    fn priv_impl_function_body_data(
4369        &'db self,
4370        impl_function_id: ImplFunctionId<'db>,
4371    ) -> Maybe<&'db FunctionBodyData<'db>> {
4372        priv_impl_function_body_data_tracked(self.as_dyn_database(), impl_function_id)
4373            .maybe_as_ref()
4374    }
4375}
4376impl<'db, T: Database + ?Sized> ImplSemantic<'db> for T {}
4377
4378/// Trait for private impl-related semantic queries.
4379trait PrivImplSemantic<'db>: Database {
4380    /// Returns the substitution for generics for the impl.
4381    fn impl_def_substitution(
4382        &'db self,
4383        impl_def_id: ImplDefId<'db>,
4384    ) -> Maybe<&'db GenericSubstitution<'db>> {
4385        impl_def_substitution(self.as_dyn_database(), impl_def_id).maybe_as_ref()
4386    }
4387    /// Returns the shallow trait generic arguments of an impl.
4388    fn impl_def_shallow_trait_generic_args(
4389        &'db self,
4390        impl_def_id: ImplDefId<'db>,
4391    ) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
4392        impl_def_shallow_trait_generic_args(self.as_dyn_database(), impl_def_id)
4393    }
4394    /// Returns the shallow trait generic arguments of an impl alias.
4395    fn impl_alias_trait_generic_args(
4396        &'db self,
4397        impl_def_id: ImplAliasId<'db>,
4398    ) -> Maybe<&'db [(GenericParamId<'db>, ShallowGenericArg<'db>)]> {
4399        impl_alias_trait_generic_args(self.as_dyn_database(), impl_def_id)
4400    }
4401    /// Returns the item of the impl, by the given `name`, if exists.
4402    fn impl_item_by_name(
4403        &'db self,
4404        impl_def_id: ImplDefId<'db>,
4405        name: SmolStrId<'db>,
4406    ) -> Maybe<Option<ImplItemId<'db>>> {
4407        Ok(impl_definition_data(self.as_dyn_database(), impl_def_id)
4408            .maybe_as_ref()?
4409            .item_id_by_name
4410            .get(&name)
4411            .map(|info| info.id))
4412    }
4413    /// Returns the trait impl of an implicit impl if `name` exists in trait and not in the impl.
4414    fn impl_implicit_impl_by_name(
4415        &'db self,
4416        impl_def_id: ImplDefId<'db>,
4417        name: SmolStrId<'db>,
4418    ) -> Maybe<Option<TraitImplId<'db>>> {
4419        Ok(impl_definition_data(self.as_dyn_database(), impl_def_id)
4420            .maybe_as_ref()?
4421            .implicit_impls_id_by_name
4422            .get(&name)
4423            .copied())
4424    }
4425    /// Returns the impl AST of the impl type that matches the given id, if exists.
4426    fn impl_type_by_id(
4427        &'db self,
4428        impl_type_id: ImplTypeDefId<'db>,
4429    ) -> Maybe<ast::ItemTypeAlias<'db>> {
4430        impl_type_by_id(self.as_dyn_database(), impl_type_id)
4431    }
4432    /// Returns the impls items in the impl.
4433    fn impl_impls(
4434        &'db self,
4435        impl_def_id: ImplDefId<'db>,
4436    ) -> Maybe<&'db OrderedHashMap<ImplImplDefId<'db>, ast::ItemImplAlias<'db>>> {
4437        Ok(&impl_definition_data(self.as_dyn_database(), impl_def_id)
4438            .maybe_as_ref()?
4439            .item_impl_asts)
4440    }
4441    /// Returns the impl AST of the impl impl that matches the given id, if exists.
4442    fn impl_impl_by_id(
4443        &'db self,
4444        impl_impl_id: ImplImplDefId<'db>,
4445    ) -> Maybe<ast::ItemImplAlias<'db>> {
4446        impl_impl_by_id(self.as_dyn_database(), impl_impl_id)
4447    }
4448    /// Returns the impl impl item that matches the given trait impl item, if exists.
4449    fn impl_impl_by_trait_impl(
4450        &'db self,
4451        impl_def_id: ImplDefId<'db>,
4452        trait_impl_id: TraitImplId<'db>,
4453    ) -> Maybe<ImplImplDefId<'db>> {
4454        impl_impl_by_trait_impl(self.as_dyn_database(), impl_def_id, trait_impl_id)
4455    }
4456    /// Returns whether `trait_impl_id` is an implicit impl in `impl_def_id`.
4457    fn is_implicit_impl_impl(
4458        &self,
4459        impl_def_id: ImplDefId<'db>,
4460        trait_impl_id: TraitImplId<'db>,
4461    ) -> Maybe<bool> {
4462        is_implicit_impl_impl(self.as_dyn_database(), impl_def_id, trait_impl_id)
4463    }
4464    /// Returns the impl constant item that matches the given trait constant item, if exists.
4465    fn impl_constant_by_trait_constant(
4466        &'db self,
4467        impl_def_id: ImplDefId<'db>,
4468        trait_constant_id: TraitConstantId<'db>,
4469    ) -> Maybe<ImplConstantDefId<'db>> {
4470        impl_constant_by_trait_constant(self.as_dyn_database(), impl_def_id, trait_constant_id)
4471    }
4472    /// Returns the impl function that matches the given trait function, if exists.
4473    /// Note that a function that doesn't exist in the impl doesn't necessarily indicate an error,
4474    /// as, e.g., a trait function that has a default implementation doesn't have to be
4475    /// implemented in the impl.
4476    fn impl_function_by_trait_function(
4477        &'db self,
4478        impl_def_id: ImplDefId<'db>,
4479        trait_function_id: TraitFunctionId<'db>,
4480    ) -> Maybe<Option<ImplFunctionId<'db>>> {
4481        impl_function_by_trait_function(self.as_dyn_database(), impl_def_id, trait_function_id)
4482    }
4483    /// Returns the semantic diagnostics of an impl item type.
4484    fn impl_type_def_semantic_diagnostics(
4485        &'db self,
4486        id: ImplTypeDefId<'db>,
4487    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4488        impl_type_semantic_data(self.as_dyn_database(), id, false)
4489            .as_ref()
4490            .map(|data| data.diagnostics.clone())
4491            .unwrap_or_default()
4492    }
4493    /// Returns the semantic diagnostics of an impl item constant.
4494    fn impl_constant_def_semantic_diagnostics(
4495        &'db self,
4496        id: ImplConstantDefId<'db>,
4497    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4498        impl_constant_semantic_data(self.as_dyn_database(), id, false)
4499            .as_ref()
4500            .map(|data| data.diagnostics.clone())
4501            .unwrap_or_default()
4502    }
4503    /// Returns the given impl constant, implized by the given impl context.
4504    fn impl_constant_implized_by_context(
4505        &'db self,
4506        impl_constant_id: ImplConstantId<'db>,
4507        impl_def_id: ImplDefId<'db>,
4508    ) -> Maybe<ConstValueId<'db>> {
4509        impl_constant_implized_by_context_tracked(
4510            self.as_dyn_database(),
4511            impl_constant_id,
4512            impl_def_id,
4513        )
4514    }
4515    /// Returns the semantic diagnostics of an impl item impl.
4516    fn impl_impl_def_semantic_diagnostics(
4517        &'db self,
4518        id: ImplImplDefId<'db>,
4519    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4520        impl_impl_semantic_data(self.as_dyn_database(), id, false)
4521            .as_ref()
4522            .map(|data| data.diagnostics.clone())
4523            .unwrap_or_default()
4524    }
4525    /// Returns the resolved impl of an impl item impl.
4526    fn impl_impl_def_impl(
4527        &'db self,
4528        impl_impl_def_id: ImplImplDefId<'db>,
4529        in_cycle: bool,
4530    ) -> Maybe<ImplId<'db>> {
4531        impl_impl_semantic_data(self.as_dyn_database(), impl_impl_def_id, in_cycle)
4532            .maybe_as_ref()?
4533            .impl_data
4534            .resolved_impl
4535    }
4536    /// Returns the semantic diagnostics of an implicit impl.
4537    fn implicit_impl_impl_semantic_diagnostics(
4538        &'db self,
4539        impl_def_id: ImplDefId<'db>,
4540        trait_impl_id: TraitImplId<'db>,
4541    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
4542        implicit_impl_impl_semantic_data_tracked(
4543            self.as_dyn_database(),
4544            impl_def_id,
4545            trait_impl_id,
4546            false,
4547        )
4548        .as_ref()
4549        .map(|data| data.diagnostics.clone())
4550        .unwrap_or_default()
4551    }
4552    /// Returns the resolved impl of an implicit impl.
4553    fn implicit_impl_impl_impl(
4554        &'db self,
4555        impl_def_id: ImplDefId<'db>,
4556        trait_impl_id: TraitImplId<'db>,
4557        in_cycle: bool,
4558    ) -> Maybe<ImplId<'db>> {
4559        implicit_impl_impl_semantic_data_tracked(
4560            self.as_dyn_database(),
4561            impl_def_id,
4562            trait_impl_id,
4563            in_cycle,
4564        )
4565        .maybe_as_ref()?
4566        .resolved_impl
4567    }
4568    /// Returns the implized impl impl if the impl is concrete.
4569    fn impl_impl_implized_by_context(
4570        &'db self,
4571        impl_impl_id: ImplImplId<'db>,
4572        impl_def_id: ImplDefId<'db>,
4573        in_cycle: bool,
4574    ) -> Maybe<ImplId<'db>> {
4575        impl_impl_implized_by_context_tracked(
4576            self.as_dyn_database(),
4577            impl_impl_id,
4578            impl_def_id,
4579            in_cycle,
4580        )
4581    }
4582    /// Returns the concrete trait of an impl impl.
4583    fn impl_impl_concrete_trait(
4584        &'db self,
4585        impl_impl_id: ImplImplId<'db>,
4586    ) -> Maybe<ConcreteTraitId<'db>> {
4587        impl_impl_concrete_trait_tracked(self.as_dyn_database(), impl_impl_id)
4588    }
4589    /// Returns the uninferred impls of a crate which are global.
4590    /// An impl is global if it is defined in the same module as the trait it implements or in the
4591    /// same module as one of its concrete traits' types.
4592    fn crate_global_impls(
4593        &'db self,
4594        crate_id: CrateId<'db>,
4595    ) -> &'db UnorderedHashMap<TraitId<'db>, OrderedHashSet<UninferredImplById<'db>>> {
4596        crate_global_impls(self.as_dyn_database(), crate_id)
4597    }
4598    /// Returns the traits which impls of a trait directly depend on.
4599    fn crate_traits_dependencies(
4600        &'db self,
4601        crate_id: CrateId<'db>,
4602    ) -> &'db UnorderedHashMap<TraitId<'db>, OrderedHashSet<TraitId<'db>>> {
4603        crate_traits_dependencies(self.as_dyn_database(), crate_id)
4604    }
4605    /// Returns the traits which are reachable from a trait.
4606    fn reachable_trait_dependencies(
4607        &'db self,
4608        trait_id: TraitId<'db>,
4609        crate_id: CrateId<'db>,
4610    ) -> &'db OrderedHashSet<TraitId<'db>> {
4611        reachable_trait_dependencies(self.as_dyn_database(), trait_id, crate_id)
4612    }
4613    /// Returns the global and local impls of a module.
4614    fn module_global_impls(
4615        &'db self,
4616        _tracked: Tracked,
4617        module_id: ModuleId<'db>,
4618    ) -> &'db Maybe<ModuleImpls<'db>> {
4619        module_global_impls(self.as_dyn_database(), _tracked, module_id)
4620    }
4621    /// Returns the candidates for a trait by its head.
4622    fn trait_candidate_by_head(
4623        &'db self,
4624        crate_id: CrateId<'db>,
4625        trait_id: TraitId<'db>,
4626    ) -> &'db OrderedHashMap<GenericsHeadFilter<'db>, OrderedHashSet<UninferredImplById<'db>>> {
4627        trait_candidate_by_head(self.as_dyn_database(), crate_id, trait_id)
4628    }
4629}
4630impl<'db, T: Database + ?Sized> PrivImplSemantic<'db> for T {}