Skip to main content

cairo_lang_semantic/items/
imp.rs

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