cairo_lang_semantic/items/
imp.rs

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