Skip to main content

cairo_lang_semantic/items/
imp.rs

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