Skip to main content

cairo_lang_semantic/items/
imp.rs

1use std::collections::BTreeSet;
2use std::fmt::Write;
3use std::hash::Hash;
4use std::sync::Arc;
5use std::{mem, panic, vec};
6
7use cairo_lang_debug::DebugWithDb;
8use cairo_lang_defs::ids::{
9    FunctionTitleId, GenericKind, GenericParamId, ImplAliasId, ImplConstantDefId,
10    ImplConstantDefLongId, ImplDefId, ImplFunctionId, ImplFunctionLongId, ImplImplDefId,
11    ImplImplDefLongId, ImplItemId, ImplTypeDefId, ImplTypeDefLongId, LanguageElementId,
12    LookupItemId, ModuleId, ModuleItemId, NamedLanguageElementId, NamedLanguageElementLongId,
13    TopLevelLanguageElementId, TraitConstantId, TraitFunctionId, TraitId, TraitImplId, TraitTypeId,
14    UseId,
15};
16use cairo_lang_diagnostics::{
17    DiagnosticAdded, Diagnostics, DiagnosticsBuilder, Maybe, ToMaybe, skip_diagnostic,
18};
19use cairo_lang_filesystem::ids::UnstableSalsaId;
20use cairo_lang_proc_macros::{DebugWithDb, SemanticObject};
21use cairo_lang_syntax as syntax;
22use cairo_lang_syntax::node::ast::OptionTypeClause;
23use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
24use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
25use cairo_lang_utils::unordered_hash_map::UnorderedHashMap;
26use cairo_lang_utils::{Intern, LookupIntern, define_short_id, extract_matches};
27use itertools::{Itertools, chain, izip};
28use smol_str::SmolStr;
29use syntax::attribute::structured::{Attribute, AttributeListStructurize};
30use syntax::node::ast::{self, GenericArg, ImplItem, MaybeImplBody, OptionReturnTypeClause};
31use syntax::node::db::SyntaxGroup;
32use syntax::node::helpers::OptionWrappedGenericParamListHelper;
33use syntax::node::ids::SyntaxStablePtrId;
34use syntax::node::{Terminal, TypedStablePtr, TypedSyntaxNode};
35
36use super::constant::{
37    ConstValue, ConstValueId, ConstantData, ImplConstantId, constant_semantic_data_cycle_helper,
38    constant_semantic_data_helper,
39};
40use super::enm::SemanticEnumEx;
41use super::feature_kind::{FeatureKind, HasFeatureKind};
42use super::function_with_body::{FunctionBody, FunctionBodyData, get_inline_config};
43use super::functions::{
44    FunctionDeclarationData, GenericFunctionId, ImplGenericFunctionId, InlineConfiguration,
45    forbid_inline_always_with_impl_generic_param,
46};
47use super::generics::{
48    GenericArgumentHead, GenericParamImpl, GenericParamsData, fmt_generic_args,
49    generic_params_to_args, semantic_generic_params,
50};
51use super::impl_alias::{
52    ImplAliasData, impl_alias_generic_params_data_helper, impl_alias_semantic_data_cycle_helper,
53    impl_alias_semantic_data_helper,
54};
55use super::trt::{
56    ConcreteTraitConstantId, ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId,
57    ConcreteTraitImplId,
58};
59use super::type_aliases::{
60    TypeAliasData, type_alias_generic_params_data_helper, type_alias_semantic_data_cycle_helper,
61    type_alias_semantic_data_helper,
62};
63use super::visibility::peek_visible_in;
64use super::{TraitOrImplContext, resolve_trait_path};
65use crate::corelib::{concrete_destruct_trait, concrete_drop_trait, core_crate};
66use crate::db::{SemanticGroup, get_resolver_data_options};
67use crate::diagnostic::SemanticDiagnosticKind::{self, *};
68use crate::diagnostic::{NotFoundItemType, SemanticDiagnostics, SemanticDiagnosticsBuilder};
69use crate::expr::compute::{ComputationContext, ContextFunction, Environment, compute_root_expr};
70use crate::expr::fmt::CountingWriter;
71use crate::expr::inference::canonic::ResultNoErrEx;
72use crate::expr::inference::conform::InferenceConform;
73use crate::expr::inference::infers::InferenceEmbeddings;
74use crate::expr::inference::solver::{Ambiguity, SolutionSet, enrich_lookup_context_with_ty};
75use crate::expr::inference::{
76    ImplVarId, ImplVarTraitItemMappings, Inference, InferenceError, InferenceId,
77};
78use crate::items::function_with_body::get_implicit_precedence;
79use crate::items::functions::ImplicitPrecedence;
80use crate::items::us::SemanticUseEx;
81use crate::resolve::{ResolvedConcreteItem, ResolvedGenericItem, Resolver, ResolverData};
82use crate::substitution::{GenericSubstitution, SemanticRewriter};
83use crate::types::{ImplTypeId, add_type_based_diagnostics, get_impl_at_context, resolve_type};
84use crate::{
85    Arenas, ConcreteFunction, ConcreteTraitId, ConcreteTraitLongId, FunctionId, FunctionLongId,
86    GenericArgumentId, GenericParam, Mutability, SemanticDiagnostic, TypeId, TypeLongId, semantic,
87    semantic_object_for_id,
88};
89
90#[cfg(test)]
91#[path = "imp_test.rs"]
92mod test;
93
94#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
95pub struct ConcreteImplLongId {
96    pub impl_def_id: ImplDefId,
97    pub generic_args: Vec<GenericArgumentId>,
98}
99define_short_id!(
100    ConcreteImplId,
101    ConcreteImplLongId,
102    SemanticGroup,
103    lookup_intern_concrete_impl,
104    intern_concrete_impl
105);
106semantic_object_for_id!(
107    ConcreteImplId,
108    lookup_intern_concrete_impl,
109    intern_concrete_impl,
110    ConcreteImplLongId
111);
112impl DebugWithDb<dyn SemanticGroup> for ConcreteImplLongId {
113    fn fmt(
114        &self,
115        f: &mut std::fmt::Formatter<'_>,
116        db: &(dyn SemanticGroup + 'static),
117    ) -> std::fmt::Result {
118        let mut f = CountingWriter::new(f);
119        write!(f, "{}", self.impl_def_id.full_path(db))?;
120        fmt_generic_args(&self.generic_args, &mut f, db)
121    }
122}
123impl ConcreteImplId {
124    pub fn impl_def_id(&self, db: &dyn SemanticGroup) -> ImplDefId {
125        self.lookup_intern(db).impl_def_id
126    }
127    pub fn get_impl_function(
128        &self,
129        db: &dyn SemanticGroup,
130        function: TraitFunctionId,
131    ) -> Maybe<Option<ImplFunctionId>> {
132        db.impl_function_by_trait_function(self.impl_def_id(db), function)
133    }
134    pub fn name(&self, db: &dyn SemanticGroup) -> SmolStr {
135        self.impl_def_id(db).name(db)
136    }
137    pub fn full_path(&self, db: &dyn SemanticGroup) -> String {
138        format!("{:?}", self.debug(db.elongate()))
139    }
140    pub fn substitution(&self, db: &dyn SemanticGroup) -> Maybe<GenericSubstitution> {
141        Ok(GenericSubstitution::from_impl(ImplLongId::Concrete(*self).intern(db)).concat(
142            GenericSubstitution::new(
143                &db.impl_def_generic_params(self.impl_def_id(db))?,
144                &self.lookup_intern(db).generic_args,
145            ),
146        ))
147    }
148    /// Returns true if the `impl` does not depend on any generics.
149    pub fn is_fully_concrete(&self, db: &dyn SemanticGroup) -> bool {
150        self.lookup_intern(db)
151            .generic_args
152            .iter()
153            .all(|generic_argument_id| generic_argument_id.is_fully_concrete(db))
154    }
155    /// Returns true if the `impl` does not depend on impl or type variables.
156    pub fn is_var_free(&self, db: &dyn SemanticGroup) -> bool {
157        self.lookup_intern(db)
158            .generic_args
159            .iter()
160            .all(|generic_argument_id| generic_argument_id.is_var_free(db))
161    }
162}
163
164/// Represents a "callee" impl that can be referred to in the code.
165/// Traits should be resolved to this.
166#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
167pub enum ImplLongId {
168    Concrete(ConcreteImplId),
169    GenericParameter(GenericParamId),
170    ImplVar(ImplVarId),
171    ImplImpl(ImplImplId),
172    SelfImpl(ConcreteTraitId),
173    GeneratedImpl(GeneratedImplId),
174}
175impl ImplLongId {
176    /// Returns the [ImplHead] of an impl if available.
177    pub fn head(&self, db: &dyn SemanticGroup) -> Option<ImplHead> {
178        Some(match self {
179            ImplLongId::Concrete(concrete) => ImplHead::Concrete(concrete.impl_def_id(db)),
180            ImplLongId::GenericParameter(_)
181            | ImplLongId::ImplVar(_)
182            | ImplLongId::ImplImpl(_)
183            | ImplLongId::SelfImpl(_)
184            | ImplLongId::GeneratedImpl(_) => {
185                return None;
186            }
187        })
188    }
189    pub fn name(&self, db: &dyn SemanticGroup) -> SmolStr {
190        match self {
191            ImplLongId::Concrete(concrete_impl) => concrete_impl.name(db),
192            ImplLongId::GenericParameter(generic_param_impl) => {
193                generic_param_impl.name(db).unwrap_or_else(|| "_".into())
194            }
195            ImplLongId::ImplVar(var) => {
196                format!("ImplVar({})", var.concrete_trait_id(db).full_path(db)).into()
197            }
198            ImplLongId::ImplImpl(impl_impl) => format!(
199                "{}::{}",
200                impl_impl.impl_id().name(db),
201                db.impl_impl_concrete_trait(*impl_impl)
202                    .map(|trait_impl| trait_impl.full_path(db))
203                    .unwrap_or_else(|_| "_".into())
204            )
205            .into(),
206            ImplLongId::SelfImpl(trait_impl) => trait_impl.name(db),
207            ImplLongId::GeneratedImpl(generated_impl) => {
208                format!("{:?}", generated_impl.debug(db.elongate())).into()
209            }
210        }
211    }
212    pub fn format(&self, db: &dyn SemanticGroup) -> String {
213        match self {
214            ImplLongId::Concrete(concrete_impl) => {
215                format!("{:?}", concrete_impl.debug(db.elongate()))
216            }
217            ImplLongId::GenericParameter(generic_param_impl) => generic_param_impl.format(db),
218            ImplLongId::ImplVar(var) => format!("{var:?}"),
219            ImplLongId::ImplImpl(impl_impl) => format!("{:?}", impl_impl.debug(db.elongate())),
220            ImplLongId::SelfImpl(concrete_trait_id) => {
221                format!("{:?}", concrete_trait_id.debug(db.elongate()))
222            }
223            ImplLongId::GeneratedImpl(generated_impl) => {
224                format!("{:?}", generated_impl.debug(db.elongate()))
225            }
226        }
227    }
228
229    /// Returns true if the `impl` does not depend on impl or type variables.
230    pub fn is_var_free(&self, db: &dyn SemanticGroup) -> bool {
231        match self {
232            ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.is_var_free(db),
233            ImplLongId::SelfImpl(concrete_trait_id) => concrete_trait_id.is_var_free(db),
234            ImplLongId::GenericParameter(_) => true,
235            ImplLongId::ImplVar(_) => false,
236            ImplLongId::ImplImpl(impl_impl) => impl_impl.impl_id().is_var_free(db),
237            ImplLongId::GeneratedImpl(generated_impl) => {
238                generated_impl.concrete_trait(db).is_var_free(db)
239                    && generated_impl
240                        .lookup_intern(db)
241                        .impl_items
242                        .0
243                        .values()
244                        .all(|type_id| type_id.is_var_free(db))
245            }
246        }
247    }
248
249    /// Returns true if the `impl` does not depend on any generics.
250    pub fn is_fully_concrete(&self, db: &dyn SemanticGroup) -> bool {
251        match self {
252            ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.is_fully_concrete(db),
253            ImplLongId::GenericParameter(_) => false,
254            ImplLongId::ImplVar(_) => false,
255            ImplLongId::ImplImpl(_) | ImplLongId::SelfImpl(_) => false,
256            ImplLongId::GeneratedImpl(generated_impl) => {
257                generated_impl.concrete_trait(db).is_fully_concrete(db)
258                    && generated_impl
259                        .lookup_intern(db)
260                        .impl_items
261                        .0
262                        .values()
263                        .all(|type_id| type_id.is_fully_concrete(db))
264            }
265        }
266    }
267}
268impl DebugWithDb<dyn SemanticGroup> for ImplLongId {
269    fn fmt(
270        &self,
271        f: &mut std::fmt::Formatter<'_>,
272        db: &(dyn SemanticGroup + 'static),
273    ) -> std::fmt::Result {
274        match self {
275            ImplLongId::Concrete(concrete_impl_id) => write!(f, "{:?}", concrete_impl_id.debug(db)),
276            ImplLongId::GenericParameter(param) => write!(f, "{}", param.debug_name(db)),
277            ImplLongId::ImplVar(var) => write!(f, "?{}", var.lookup_intern(db).id.0),
278            ImplLongId::ImplImpl(impl_impl) => write!(f, "{:?}", impl_impl.debug(db)),
279            ImplLongId::SelfImpl(trait_impl) => write!(f, "{:?}", trait_impl.debug(db)),
280            ImplLongId::GeneratedImpl(generated_impl) => {
281                write!(f, "{:?}", generated_impl.debug(db))
282            }
283        }
284    }
285}
286
287define_short_id!(ImplId, ImplLongId, SemanticGroup, lookup_intern_impl, intern_impl);
288semantic_object_for_id!(ImplId, lookup_intern_impl, intern_impl, ImplLongId);
289impl ImplId {
290    pub fn concrete_trait(&self, db: &dyn SemanticGroup) -> Maybe<ConcreteTraitId> {
291        db.impl_concrete_trait(*self)
292    }
293
294    /// Returns true if the `impl` does not depend on any generics.
295    pub fn is_fully_concrete(&self, db: &dyn SemanticGroup) -> bool {
296        db.priv_impl_is_fully_concrete(*self)
297    }
298
299    /// Returns true if the `impl` does not depend on impl or type variables.
300    pub fn is_var_free(&self, db: &dyn SemanticGroup) -> bool {
301        db.priv_impl_is_var_free(*self)
302    }
303
304    /// Returns the [ImplHead] of an impl if available.
305    pub fn head(&self, db: &dyn SemanticGroup) -> Option<ImplHead> {
306        self.lookup_intern(db).head(db)
307    }
308
309    /// Returns the name of the impl.
310    pub fn name(&self, db: &dyn SemanticGroup) -> SmolStr {
311        self.lookup_intern(db).name(db)
312    }
313
314    pub fn format(&self, db: &dyn SemanticGroup) -> String {
315        self.lookup_intern(db).format(db)
316    }
317}
318
319define_short_id!(
320    GeneratedImplId,
321    GeneratedImplLongId,
322    SemanticGroup,
323    lookup_intern_generated_impl,
324    intern_generated_impl
325);
326semantic_object_for_id!(
327    GeneratedImplId,
328    lookup_intern_generated_impl,
329    intern_generated_impl,
330    GeneratedImplLongId
331);
332
333impl GeneratedImplId {
334    pub fn concrete_trait(self, db: &dyn SemanticGroup) -> ConcreteTraitId {
335        db.lookup_intern_generated_impl(self).concrete_trait
336    }
337
338    pub fn trait_id(&self, db: &dyn SemanticGroup) -> TraitId {
339        self.concrete_trait(db).trait_id(db)
340    }
341}
342
343/// An impl that is generated by the compiler for a specific trait.
344/// There can be only one such impl per concrete trait as otherwise there would be a
345/// MultipleImplsFound ambiguity.
346#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
347pub struct GeneratedImplLongId {
348    pub concrete_trait: ConcreteTraitId,
349    /// The generic params required for the impl. Typically impls and negative impls.
350    /// We save the params so that we can validate negative impls.
351    pub generic_params: Vec<GenericParam>,
352    pub impl_items: GeneratedImplItems,
353}
354#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, SemanticObject)]
355pub struct GeneratedImplItems(pub OrderedHashMap<TraitTypeId, TypeId>);
356
357pub enum GeneratedImplAssociatedTypes {
358    /// The associated types are not yet resolved.
359    Unresolved,
360    /// The associated types are resolved.
361    Resolved(OrderedHashMap<TraitTypeId, TypeId>),
362}
363
364impl DebugWithDb<dyn SemanticGroup> for GeneratedImplLongId {
365    fn fmt(
366        &self,
367        f: &mut std::fmt::Formatter<'_>,
368        db: &(dyn SemanticGroup + 'static),
369    ) -> std::fmt::Result {
370        write!(f, "Generated {:?}", self.concrete_trait.debug(db))
371    }
372}
373
374/// An impl item of kind impl.
375#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
376pub struct ImplImplId {
377    /// The impl the item impl is in.
378    impl_id: ImplId,
379    /// The trait impl this impl impl "implements".
380    trait_impl_id: TraitImplId,
381}
382
383impl ImplImplId {
384    /// Creates a new impl impl id. For an impl impl of a concrete impl, asserts that the
385    /// trait impl belongs to the same trait that the impl implements (panics if not).
386    pub fn new(impl_id: ImplId, trait_impl_id: TraitImplId, db: &dyn SemanticGroup) -> Self {
387        if let crate::items::imp::ImplLongId::Concrete(concrete_impl) = impl_id.lookup_intern(db) {
388            let impl_def_id = concrete_impl.impl_def_id(db);
389            assert_eq!(Ok(trait_impl_id.trait_id(db)), db.impl_def_trait(impl_def_id));
390        }
391
392        ImplImplId { impl_id, trait_impl_id }
393    }
394    pub fn impl_id(&self) -> ImplId {
395        self.impl_id
396    }
397    pub fn trait_impl_id(&self) -> TraitImplId {
398        self.trait_impl_id
399    }
400
401    pub fn concrete_trait_impl_id(&self, db: &dyn SemanticGroup) -> Maybe<ConcreteTraitImplId> {
402        Ok(ConcreteTraitImplId::new(db, self.impl_id.concrete_trait(db)?, self.trait_impl_id))
403    }
404
405    pub fn full_path(&self, db: &dyn SemanticGroup) -> String {
406        format!("{:?}", self.debug(db.elongate()))
407    }
408}
409impl DebugWithDb<dyn SemanticGroup> for ImplImplId {
410    fn fmt(
411        &self,
412        f: &mut std::fmt::Formatter<'_>,
413        db: &(dyn SemanticGroup + 'static),
414    ) -> std::fmt::Result {
415        write!(f, "{:?}::{}", self.impl_id.debug(db), self.trait_impl_id.name(db))
416    }
417}
418
419impl UnstableSalsaId for ImplId {
420    fn get_internal_id(&self) -> &salsa::InternId {
421        &self.0
422    }
423}
424
425/// Head of an impl.
426///
427/// A non-param non-variable impl has a head, which represents the kind of the root node in its tree
428/// representation. This is used for caching queries for fast lookups when the impl is not
429/// completely inferred yet.
430#[derive(Clone, Debug, Hash, PartialEq, Eq)]
431pub enum ImplHead {
432    Concrete(ImplDefId),
433}
434
435// === Impl Declaration ===
436
437#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
438#[debug_db(dyn SemanticGroup + 'static)]
439pub struct ImplDeclarationData {
440    diagnostics: Diagnostics<SemanticDiagnostic>,
441    generic_params: Vec<semantic::GenericParam>,
442    /// The concrete trait this impl implements, or Err if cannot be resolved.
443    concrete_trait: Maybe<ConcreteTraitId>,
444    attributes: Vec<Attribute>,
445    resolver_data: Arc<ResolverData>,
446}
447
448// --- Selectors ---
449
450/// Query implementation of [crate::db::SemanticGroup::impl_semantic_declaration_diagnostics].
451pub fn impl_semantic_declaration_diagnostics(
452    db: &dyn SemanticGroup,
453    impl_def_id: ImplDefId,
454) -> Diagnostics<SemanticDiagnostic> {
455    db.priv_impl_declaration_data(impl_def_id).map(|data| data.diagnostics).unwrap_or_default()
456}
457
458/// Query implementation of [crate::db::SemanticGroup::impl_def_generic_params_data].
459pub fn impl_def_generic_params_data(
460    db: &dyn SemanticGroup,
461    impl_def_id: ImplDefId,
462) -> Maybe<GenericParamsData> {
463    let module_file_id = impl_def_id.module_file_id(db);
464    let mut diagnostics = SemanticDiagnostics::default();
465
466    let impl_ast = db.module_impl_by_id(impl_def_id)?.to_maybe()?;
467    let inference_id =
468        InferenceId::LookupItemGenerics(LookupItemId::ModuleItem(ModuleItemId::Impl(impl_def_id)));
469
470    let mut resolver = Resolver::new(db, module_file_id, inference_id);
471    resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
472    let generic_params = semantic_generic_params(
473        db,
474        &mut diagnostics,
475        &mut resolver,
476        module_file_id,
477        &impl_ast.generic_params(db),
478    );
479    let inference = &mut resolver.inference();
480    inference.finalize(&mut diagnostics, impl_ast.stable_ptr(db).untyped());
481
482    let generic_params = inference.rewrite(generic_params).no_err();
483    let resolver_data = Arc::new(resolver.data);
484    Ok(GenericParamsData { generic_params, diagnostics: diagnostics.build(), resolver_data })
485}
486
487/// Query implementation of [crate::db::SemanticGroup::impl_def_generic_params].
488pub fn impl_def_generic_params(
489    db: &dyn SemanticGroup,
490    impl_def_id: ImplDefId,
491) -> Maybe<Vec<semantic::GenericParam>> {
492    Ok(db.impl_def_generic_params_data(impl_def_id)?.generic_params)
493}
494
495/// Query implementation of [crate::db::SemanticGroup::impl_def_resolver_data].
496pub fn impl_def_resolver_data(
497    db: &dyn SemanticGroup,
498    impl_def_id: ImplDefId,
499) -> Maybe<Arc<ResolverData>> {
500    Ok(db.priv_impl_declaration_data(impl_def_id)?.resolver_data)
501}
502
503/// Trivial cycle handler for [crate::db::SemanticGroup::impl_def_resolver_data].
504pub fn impl_def_resolver_data_cycle(
505    db: &dyn SemanticGroup,
506    _cycle: &salsa::Cycle,
507    impl_def_id: &ImplDefId,
508) -> Maybe<Arc<ResolverData>> {
509    // Forwarding (not as a query) cycle handling to `priv_impl_declaration_data` cycle handler.
510    impl_def_resolver_data(db, *impl_def_id)
511}
512
513/// Query implementation of [crate::db::SemanticGroup::impl_def_concrete_trait].
514pub fn impl_def_concrete_trait(
515    db: &dyn SemanticGroup,
516    impl_def_id: ImplDefId,
517) -> Maybe<ConcreteTraitId> {
518    db.priv_impl_declaration_data(impl_def_id)?.concrete_trait
519}
520
521/// Trivial cycle handler for [crate::db::SemanticGroup::impl_def_concrete_trait].
522pub fn impl_def_concrete_trait_cycle(
523    db: &dyn SemanticGroup,
524    _cycle: &salsa::Cycle,
525    impl_def_id: &ImplDefId,
526) -> Maybe<ConcreteTraitId> {
527    // Forwarding (not as a query) cycle handling to `priv_impl_declaration_data` cycle handler.
528    impl_def_concrete_trait(db, *impl_def_id)
529}
530
531/// Query implementation of [crate::db::SemanticGroup::impl_def_substitution].
532pub fn impl_def_substitution(
533    db: &dyn SemanticGroup,
534    impl_def_id: ImplDefId,
535) -> Maybe<Arc<GenericSubstitution>> {
536    let params = db.impl_def_generic_params(impl_def_id)?;
537    let generic_args = generic_params_to_args(&params, db);
538    Ok(Arc::new(ConcreteImplLongId { impl_def_id, generic_args }.intern(db).substitution(db)?))
539}
540
541/// Query implementation of [crate::db::SemanticGroup::impl_def_attributes].
542pub fn impl_def_attributes(
543    db: &dyn SemanticGroup,
544    impl_def_id: ImplDefId,
545) -> Maybe<Vec<Attribute>> {
546    Ok(db.priv_impl_declaration_data(impl_def_id)?.attributes)
547}
548
549/// Query implementation of [crate::db::SemanticGroup::impl_def_trait].
550pub fn impl_def_trait(db: &dyn SemanticGroup, impl_def_id: ImplDefId) -> Maybe<TraitId> {
551    let module_file_id = impl_def_id.module_file_id(db);
552    let mut diagnostics = SemanticDiagnostics::default();
553
554    let impl_ast = db.module_impl_by_id(impl_def_id)?.to_maybe()?;
555    let inference_id = InferenceId::ImplDefTrait(impl_def_id);
556
557    let mut resolver = Resolver::new(db, module_file_id, inference_id);
558    resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
559
560    let trait_path_syntax = impl_ast.trait_path(db);
561
562    resolve_trait_path(db, &mut diagnostics, &mut resolver, &trait_path_syntax)
563}
564
565/// Query implementation of [crate::db::SemanticGroup::impl_concrete_trait].
566pub fn impl_concrete_trait(db: &dyn SemanticGroup, impl_id: ImplId) -> Maybe<ConcreteTraitId> {
567    match impl_id.lookup_intern(db) {
568        ImplLongId::Concrete(concrete_impl_id) => {
569            let long_impl = concrete_impl_id.lookup_intern(db);
570            let substitution = GenericSubstitution::new(
571                &db.impl_def_generic_params(long_impl.impl_def_id)?,
572                &long_impl.generic_args,
573            );
574
575            let impl_concrete_trait_id = db.impl_def_concrete_trait(long_impl.impl_def_id)?;
576            substitution.substitute(db, impl_concrete_trait_id)
577        }
578        ImplLongId::GenericParameter(param) => {
579            let param_impl =
580                extract_matches!(db.generic_param_semantic(param)?, GenericParam::Impl);
581            param_impl.concrete_trait
582        }
583        ImplLongId::ImplVar(var) => Ok(var.lookup_intern(db).concrete_trait_id),
584        ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(impl_impl),
585        ImplLongId::SelfImpl(concrete_trait_id) => Ok(concrete_trait_id),
586        ImplLongId::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
587    }
588}
589
590// --- Computation ---
591
592/// Cycle handling for [crate::db::SemanticGroup::priv_impl_declaration_data].
593pub fn priv_impl_declaration_data_cycle(
594    db: &dyn SemanticGroup,
595    _cycle: &salsa::Cycle,
596    impl_def_id: &ImplDefId,
597) -> Maybe<ImplDeclarationData> {
598    priv_impl_declaration_data_inner(db, *impl_def_id, false)
599}
600
601/// Query implementation of [crate::db::SemanticGroup::priv_impl_declaration_data].
602pub fn priv_impl_declaration_data(
603    db: &dyn SemanticGroup,
604    impl_def_id: ImplDefId,
605) -> Maybe<ImplDeclarationData> {
606    priv_impl_declaration_data_inner(db, impl_def_id, true)
607}
608
609/// Shared code for the query and cycle handling.
610/// The cycle handling logic needs to pass resolve_trait=false to prevent the cycle.
611pub fn priv_impl_declaration_data_inner(
612    db: &dyn SemanticGroup,
613    impl_def_id: ImplDefId,
614    resolve_trait: bool,
615) -> Maybe<ImplDeclarationData> {
616    let mut diagnostics = SemanticDiagnostics::default();
617
618    // TODO(spapini): when code changes in a file, all the AST items change (as they contain a path
619    // to the green root that changes. Once ASTs are rooted on items, use a selector that picks only
620    // the item instead of all the module data.
621    let impl_ast = db.module_impl_by_id(impl_def_id)?.to_maybe()?;
622    let inference_id = InferenceId::LookupItemDeclaration(LookupItemId::ModuleItem(
623        ModuleItemId::Impl(impl_def_id),
624    ));
625
626    // Generic params.
627    let generic_params_data = db.impl_def_generic_params_data(impl_def_id)?;
628    let generic_params = generic_params_data.generic_params;
629    let mut resolver = Resolver::with_data(
630        db,
631        (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
632    );
633    resolver.set_feature_config(&impl_def_id, &impl_ast, &mut diagnostics);
634    diagnostics.extend(generic_params_data.diagnostics);
635    let trait_path_syntax = impl_ast.trait_path(db);
636
637    let concrete_trait = if resolve_trait {
638        resolver
639            .resolve_concrete_path(&mut diagnostics, &trait_path_syntax, NotFoundItemType::Trait)
640            .and_then(|resolved_item| match resolved_item {
641                ResolvedConcreteItem::Trait(id) | ResolvedConcreteItem::SelfTrait(id) => Ok(id),
642                _ => Err(diagnostics
643                    .report(trait_path_syntax.stable_ptr(db), SemanticDiagnosticKind::NotATrait)),
644            })
645    } else {
646        Err(diagnostics.report(trait_path_syntax.stable_ptr(db), ImplRequirementCycle))
647    };
648
649    let info = db.core_info();
650
651    // Check for reimplementation of compilers' Traits.
652    if let Ok(concrete_trait) = concrete_trait {
653        if [
654            info.type_eq_trt,
655            info.fn_trt,
656            info.fn_once_trt,
657            info.felt252_dict_value_trt,
658            info.numeric_literal_trt,
659            info.string_literal_trt,
660        ]
661        .contains(&concrete_trait.trait_id(db))
662            && impl_def_id.parent_module(db).owning_crate(db) != core_crate(db)
663        {
664            diagnostics.report(
665                trait_path_syntax.stable_ptr(db),
666                CompilerTraitReImplementation { trait_id: concrete_trait.trait_id(db) },
667            );
668        }
669    }
670
671    // Check fully resolved.
672    let inference = &mut resolver.inference();
673    inference.finalize(&mut diagnostics, impl_ast.stable_ptr(db).untyped());
674
675    let concrete_trait: Result<ConcreteTraitId, DiagnosticAdded> =
676        inference.rewrite(concrete_trait).no_err();
677    let generic_params: Vec<GenericParam> = inference.rewrite(generic_params).no_err();
678
679    let attributes = impl_ast.attributes(db).structurize(db);
680    let mut resolver_data = resolver.data;
681    resolver_data.trait_or_impl_ctx = TraitOrImplContext::Impl(impl_def_id);
682    Ok(ImplDeclarationData {
683        diagnostics: diagnostics.build(),
684        generic_params,
685        concrete_trait,
686        attributes,
687        resolver_data: Arc::new(resolver_data),
688    })
689}
690
691// === Impl Definition ===
692
693#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
694#[debug_db(dyn SemanticGroup + 'static)]
695pub struct ImplDefinitionData {
696    /// The diagnostics here are "flat" - that is, only the diagnostics found on the impl level
697    /// itself, and don't include the diagnostics of its items. The reason it's this way is that
698    /// computing the items' diagnostics require a query about their impl, forming a cycle of
699    /// queries. Adding the items' diagnostics only after the whole computation breaks this cycle.
700    diagnostics: Diagnostics<SemanticDiagnostic>,
701
702    // AST maps.
703    function_asts: OrderedHashMap<ImplFunctionId, ast::FunctionWithBody>,
704    item_type_asts: Arc<OrderedHashMap<ImplTypeDefId, ast::ItemTypeAlias>>,
705    item_constant_asts: Arc<OrderedHashMap<ImplConstantDefId, ast::ItemConstant>>,
706    item_impl_asts: Arc<OrderedHashMap<ImplImplDefId, ast::ItemImplAlias>>,
707
708    /// Mapping of item names to their meta data info. All the IDs should appear in one of the AST
709    /// maps above.
710    item_id_by_name: Arc<OrderedHashMap<SmolStr, ImplItemInfo>>,
711
712    /// Mapping of missing impl names item names to the trait id.
713    implicit_impls_id_by_name: Arc<OrderedHashMap<SmolStr, TraitImplId>>,
714}
715
716impl ImplDefinitionData {
717    /// Retrieves impl item information by its name.
718    pub fn get_impl_item_info(&self, item_name: &SmolStr) -> Option<ImplItemInfo> {
719        self.item_id_by_name.get(item_name).cloned()
720    }
721}
722/// Stores metadata for a impl item, including its ID and feature kind.
723#[derive(Clone, Debug, PartialEq, Eq)]
724pub struct ImplItemInfo {
725    /// The unique identifier of the impl item.
726    pub id: ImplItemId,
727    /// The feature kind associated with this impl item.
728    pub feature_kind: FeatureKind,
729}
730
731impl HasFeatureKind for ImplItemInfo {
732    /// Returns the feature kind of this impl item.
733    fn feature_kind(&self) -> &FeatureKind {
734        &self.feature_kind
735    }
736}
737
738// --- Selectors ---
739
740/// Query implementation of [crate::db::SemanticGroup::impl_semantic_definition_diagnostics].
741pub fn impl_semantic_definition_diagnostics(
742    db: &dyn SemanticGroup,
743    impl_def_id: ImplDefId,
744) -> Diagnostics<SemanticDiagnostic> {
745    let mut diagnostics = DiagnosticsBuilder::default();
746
747    let Ok(data) = db.priv_impl_definition_data(impl_def_id) else {
748        return Diagnostics::default();
749    };
750
751    // The diagnostics from `priv_impl_definition_data` are only the diagnostics from the impl
752    // level. They should be enriched with the items' diagnostics.
753    diagnostics.extend(data.diagnostics);
754    for impl_function_id in data.function_asts.keys() {
755        diagnostics.extend(db.impl_function_declaration_diagnostics(*impl_function_id));
756        diagnostics.extend(db.impl_function_body_diagnostics(*impl_function_id));
757    }
758    for impl_item_type_id in data.item_type_asts.keys() {
759        diagnostics.extend(db.impl_type_def_semantic_diagnostics(*impl_item_type_id));
760        if let Ok(ty) = db.impl_type_def_resolved_type(*impl_item_type_id) {
761            add_type_based_diagnostics(db, &mut diagnostics, ty, impl_item_type_id.stable_ptr(db));
762        }
763    }
764    for impl_item_constant_id in data.item_constant_asts.keys() {
765        diagnostics.extend(db.impl_constant_def_semantic_diagnostics(*impl_item_constant_id));
766    }
767    for impl_item_impl_id in data.item_impl_asts.keys() {
768        diagnostics.extend(db.impl_impl_def_semantic_diagnostics(*impl_item_impl_id));
769    }
770    for implicit_impl_id in data.implicit_impls_id_by_name.values() {
771        diagnostics
772            .extend(db.implicit_impl_impl_semantic_diagnostics(impl_def_id, *implicit_impl_id));
773    }
774    // Diagnostics for special traits.
775    if diagnostics.error_count == 0 {
776        let concrete_trait =
777            db.priv_impl_declaration_data(impl_def_id).unwrap().concrete_trait.unwrap();
778
779        let trait_id = concrete_trait.trait_id(db);
780        if trait_id == db.core_info().deref_trt {
781            deref_impl_diagnostics(db, impl_def_id, concrete_trait, &mut diagnostics);
782        }
783    }
784    diagnostics.build()
785}
786
787/// Represents a chain of dereferences.
788#[derive(Clone, Debug, Eq, PartialEq)]
789pub struct DerefChain {
790    pub derefs: Arc<[DerefInfo]>,
791}
792
793/// Represents a single steps in a deref chain.
794#[derive(Clone, Debug, Eq, PartialEq)]
795pub struct DerefInfo {
796    /// The concrete `Deref::deref` or `MutDeref::mderef_mut` function.
797    pub function_id: FunctionId,
798    /// The mutability of the self argument of the deref function.
799    pub self_mutability: Mutability,
800    /// The target type of the deref function.
801    pub target_ty: TypeId,
802}
803
804/// Cycle handling for  [crate::db::SemanticGroup::deref_chain].
805pub fn deref_chain_cycle(
806    _db: &dyn SemanticGroup,
807    _cycle: &salsa::Cycle,
808    _ty: &TypeId,
809    _try_deref_mut: &bool,
810) -> Maybe<DerefChain> {
811    // `SemanticDiagnosticKind::DerefCycle` will be reported by `deref_impl_diagnostics`.
812    Maybe::Err(skip_diagnostic())
813}
814
815/// Query implementation of [crate::db::SemanticGroup::deref_chain].
816pub fn deref_chain(db: &dyn SemanticGroup, ty: TypeId, try_deref_mut: bool) -> Maybe<DerefChain> {
817    let mut opt_deref = None;
818    if try_deref_mut {
819        opt_deref = try_get_deref_func_and_target(db, ty, true)?;
820    }
821    let self_mutability = if opt_deref.is_some() {
822        Mutability::Reference
823    } else {
824        opt_deref = try_get_deref_func_and_target(db, ty, false)?;
825        Mutability::Immutable
826    };
827
828    let Some((function_id, target_ty)) = opt_deref else {
829        return Ok(DerefChain { derefs: Arc::new([]) });
830    };
831
832    let inner_chain = db.deref_chain(target_ty, false)?;
833
834    Ok(DerefChain {
835        derefs: chain!(
836            [DerefInfo { function_id, target_ty, self_mutability }],
837            inner_chain.derefs.iter().cloned()
838        )
839        .collect(),
840    })
841}
842
843/// Tries to find the deref function and the target type for a given type and deref trait.
844fn try_get_deref_func_and_target(
845    db: &dyn SemanticGroup,
846    ty: TypeId,
847    is_mut_deref: bool,
848) -> Result<Option<(FunctionId, TypeId)>, DiagnosticAdded> {
849    let info = db.core_info();
850    let (deref_trait_id, deref_method) = if is_mut_deref {
851        (info.deref_mut_trt, info.deref_mut_fn)
852    } else {
853        (info.deref_trt, info.deref_fn)
854    };
855
856    let mut lookup_context = ImplLookupContext::new(deref_trait_id.module_file_id(db).0, vec![]);
857    enrich_lookup_context_with_ty(db, ty, &mut lookup_context);
858    let concrete_trait = ConcreteTraitLongId {
859        trait_id: deref_trait_id,
860        generic_args: vec![GenericArgumentId::Type(ty)],
861    }
862    .intern(db);
863    let Ok(deref_impl) = get_impl_at_context(db, lookup_context, concrete_trait, None) else {
864        return Ok(None);
865    };
866    let concrete_impl_id = match deref_impl.lookup_intern(db) {
867        ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id,
868        _ => panic!("Expected concrete impl"),
869    };
870
871    let function_id = FunctionLongId {
872        function: ConcreteFunction {
873            generic_function: GenericFunctionId::Impl(ImplGenericFunctionId {
874                impl_id: deref_impl,
875                function: deref_method,
876            }),
877            generic_args: vec![],
878        },
879    }
880    .intern(db);
881
882    let data = db.priv_impl_definition_data(concrete_impl_id.impl_def_id(db)).unwrap();
883    let mut types_iter = data.item_type_asts.iter();
884    let (impl_item_type_id, _) = types_iter.next().unwrap();
885    if types_iter.next().is_some() {
886        panic!(
887            "get_impl_based_on_single_impl_type called with an impl that has more than one type"
888        );
889    }
890    let ty = db.impl_type_def_resolved_type(*impl_item_type_id).unwrap();
891    let ty = concrete_impl_id.substitution(db)?.substitute(db, ty).unwrap();
892
893    Ok(Some((function_id, ty)))
894}
895
896/// Reports diagnostic for a deref impl.
897fn deref_impl_diagnostics(
898    db: &dyn SemanticGroup,
899    mut impl_def_id: ImplDefId,
900    concrete_trait: ConcreteTraitId,
901    diagnostics: &mut DiagnosticsBuilder<SemanticDiagnostic>,
902) {
903    let mut visited_impls: OrderedHashSet<ImplDefId> = OrderedHashSet::default();
904    let deref_trait_id = concrete_trait.trait_id(db);
905
906    let impl_module = impl_def_id.module_file_id(db).0;
907
908    let mut impl_in_valid_location = false;
909    if impl_module == deref_trait_id.module_file_id(db).0 {
910        impl_in_valid_location = true;
911    }
912
913    let gargs = concrete_trait.generic_args(db);
914    let deref_ty = extract_matches!(gargs[0], GenericArgumentId::Type);
915    if let Some(module_id) = deref_ty.lookup_intern(db).module_id(db) {
916        if module_id == impl_module {
917            impl_in_valid_location = true;
918        }
919    }
920
921    if !impl_in_valid_location {
922        diagnostics.report(
923            impl_def_id.stable_ptr(db),
924            SemanticDiagnosticKind::MustBeNextToTypeOrTrait { trait_id: deref_trait_id },
925        );
926        return;
927    }
928
929    loop {
930        let Ok(impl_id) = get_impl_based_on_single_impl_type(db, impl_def_id, |ty| {
931            ConcreteTraitLongId {
932                trait_id: deref_trait_id,
933                generic_args: vec![GenericArgumentId::Type(ty)],
934            }
935            .intern(db)
936        }) else {
937            // Inference errors are handled when the impl is in actual use. In here we only check
938            // for cycles.
939            return;
940        };
941
942        impl_def_id = match impl_id.lookup_intern(db) {
943            ImplLongId::Concrete(concrete_impl_id) => concrete_impl_id.impl_def_id(db),
944            _ => return,
945        };
946
947        if !visited_impls.insert(impl_def_id) {
948            let deref_chain = visited_impls
949                .iter()
950                .map(|visited_impl| {
951                    format!(
952                        "{:?}",
953                        db.impl_def_concrete_trait(*visited_impl).unwrap().debug(db.elongate())
954                    )
955                })
956                .join(" -> ");
957            diagnostics.report(
958                impl_def_id.stable_ptr(db),
959                SemanticDiagnosticKind::DerefCycle { deref_chain },
960            );
961            return;
962        }
963    }
964}
965
966/// Assuming that an impl has a single impl type, extracts the type, and then infers another impl
967/// based on it. If the inference fails, returns the inference error and the impl type definition
968/// for diagnostics.
969fn get_impl_based_on_single_impl_type(
970    db: &dyn SemanticGroup,
971    impl_def_id: ImplDefId,
972    concrete_trait_id: impl FnOnce(TypeId) -> ConcreteTraitId,
973) -> Result<ImplId, (InferenceError, ImplTypeDefId)> {
974    let data = db.priv_impl_definition_data(impl_def_id).unwrap();
975    let mut types_iter = data.item_type_asts.iter();
976    let (impl_item_type_id, _) = types_iter.next().unwrap();
977    if types_iter.next().is_some() {
978        panic!(
979            "get_impl_based_on_single_impl_type called with an impl that has more than one type"
980        );
981    }
982    let ty = db.impl_type_def_resolved_type(*impl_item_type_id).unwrap();
983
984    let module_file_id = impl_def_id.module_file_id(db);
985    let generic_params = db.impl_def_generic_params(impl_def_id).unwrap();
986    let generic_params_ids =
987        generic_params.iter().map(|generic_param| generic_param.id()).collect();
988    let lookup_context = ImplLookupContext::new(module_file_id.0, generic_params_ids);
989    get_impl_at_context(db, lookup_context, concrete_trait_id(ty), None)
990        .map_err(|err| (err, *impl_item_type_id))
991}
992
993/// Query implementation of [crate::db::SemanticGroup::impl_functions].
994pub fn impl_functions(
995    db: &dyn SemanticGroup,
996    impl_def_id: ImplDefId,
997) -> Maybe<OrderedHashMap<SmolStr, ImplFunctionId>> {
998    Ok(db
999        .priv_impl_definition_data(impl_def_id)?
1000        .function_asts
1001        .keys()
1002        .map(|function_id| {
1003            let function_long_id = function_id.lookup_intern(db);
1004            (function_long_id.name(db), *function_id)
1005        })
1006        .collect())
1007}
1008
1009/// Query implementation of [crate::db::SemanticGroup::impl_function_by_trait_function].
1010pub fn impl_function_by_trait_function(
1011    db: &dyn SemanticGroup,
1012    impl_def_id: ImplDefId,
1013    trait_function_id: TraitFunctionId,
1014) -> Maybe<Option<ImplFunctionId>> {
1015    let name = trait_function_id.name(db);
1016    for impl_function_id in db.priv_impl_definition_data(impl_def_id)?.function_asts.keys() {
1017        if impl_function_id.lookup_intern(db).name(db) == name {
1018            return Ok(Some(*impl_function_id));
1019        }
1020    }
1021    Ok(None)
1022}
1023
1024/// Query implementation of [crate::db::SemanticGroup::impl_item_by_name].
1025pub fn impl_item_by_name(
1026    db: &dyn SemanticGroup,
1027    impl_def_id: ImplDefId,
1028    name: SmolStr,
1029) -> Maybe<Option<ImplItemId>> {
1030    Ok(db.priv_impl_definition_data(impl_def_id)?.item_id_by_name.get(&name).map(|info| info.id))
1031}
1032
1033/// Query implementation of [crate::db::SemanticGroup::impl_item_info_by_name].
1034pub fn impl_item_info_by_name(
1035    db: &dyn SemanticGroup,
1036    impl_def_id: ImplDefId,
1037    name: SmolStr,
1038) -> Maybe<Option<ImplItemInfo>> {
1039    let impl_definition_data = db.priv_impl_definition_data(impl_def_id)?;
1040    Ok(impl_definition_data.get_impl_item_info(&name))
1041}
1042
1043/// Query implementation of [crate::db::SemanticGroup::impl_implicit_impl_by_name].
1044pub fn impl_implicit_impl_by_name(
1045    db: &dyn SemanticGroup,
1046    impl_def_id: ImplDefId,
1047    name: SmolStr,
1048) -> Maybe<Option<TraitImplId>> {
1049    Ok(db.priv_impl_definition_data(impl_def_id)?.implicit_impls_id_by_name.get(&name).cloned())
1050}
1051
1052/// Query implementation of [SemanticGroup::impl_all_used_uses].
1053pub fn impl_all_used_uses(
1054    db: &dyn SemanticGroup,
1055    impl_def_id: ImplDefId,
1056) -> Maybe<Arc<OrderedHashSet<UseId>>> {
1057    let mut all_used_uses = db.impl_def_resolver_data(impl_def_id)?.used_uses.clone();
1058    let data = db.priv_impl_definition_data(impl_def_id)?;
1059    for item in data.item_id_by_name.values() {
1060        for resolver_data in get_resolver_data_options(LookupItemId::ImplItem(item.id), db) {
1061            all_used_uses.extend(resolver_data.used_uses.iter().cloned());
1062        }
1063    }
1064    Ok(all_used_uses.into())
1065}
1066
1067/// Query implementation of [crate::db::SemanticGroup::impl_types].
1068pub fn impl_types(
1069    db: &dyn SemanticGroup,
1070    impl_def_id: ImplDefId,
1071) -> Maybe<Arc<OrderedHashMap<ImplTypeDefId, ast::ItemTypeAlias>>> {
1072    Ok(db.priv_impl_definition_data(impl_def_id)?.item_type_asts)
1073}
1074
1075/// Query implementation of [crate::db::SemanticGroup::impl_type_ids].
1076pub fn impl_type_ids(
1077    db: &dyn SemanticGroup,
1078    impl_def_id: ImplDefId,
1079) -> Maybe<Arc<[ImplTypeDefId]>> {
1080    Ok(db.impl_types(impl_def_id)?.keys().copied().collect_vec().into())
1081}
1082
1083/// Query implementation of [crate::db::SemanticGroup::impl_type_by_id].
1084pub fn impl_type_by_id(
1085    db: &dyn SemanticGroup,
1086    impl_type_id: ImplTypeDefId,
1087) -> Maybe<Option<ast::ItemTypeAlias>> {
1088    let impl_types = db.impl_types(impl_type_id.impl_def_id(db))?;
1089    Ok(impl_types.get(&impl_type_id).cloned())
1090}
1091
1092/// Query implementation of [crate::db::SemanticGroup::impl_type_by_trait_type].
1093pub fn impl_type_by_trait_type(
1094    db: &dyn SemanticGroup,
1095    impl_def_id: ImplDefId,
1096    trait_type_id: TraitTypeId,
1097) -> Maybe<ImplTypeDefId> {
1098    if trait_type_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1099        unreachable!(
1100            "impl_type_by_trait_type called with a trait type that does not belong to the impl's \
1101             trait"
1102        )
1103    }
1104
1105    let name = trait_type_id.name(db);
1106    // If the trait type's name is not found, then a missing item diagnostic is reported.
1107    db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1108        Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Type)),
1109        None => Err(skip_diagnostic()),
1110    })
1111}
1112
1113/// Query implementation of [crate::db::SemanticGroup::impl_constants].
1114pub fn impl_constants(
1115    db: &dyn SemanticGroup,
1116    impl_def_id: ImplDefId,
1117) -> Maybe<Arc<OrderedHashMap<ImplConstantDefId, ast::ItemConstant>>> {
1118    Ok(db.priv_impl_definition_data(impl_def_id)?.item_constant_asts)
1119}
1120
1121/// Query implementation of [crate::db::SemanticGroup::impl_constant_by_trait_constant].
1122pub fn impl_constant_by_trait_constant(
1123    db: &dyn SemanticGroup,
1124    impl_def_id: ImplDefId,
1125    trait_constant_id: TraitConstantId,
1126) -> Maybe<ImplConstantDefId> {
1127    if trait_constant_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1128        unreachable!(
1129            "impl_constant_by_trait_constant called with a trait constant that does not belong to \
1130             the impl's trait"
1131        )
1132    }
1133
1134    let name = trait_constant_id.name(db);
1135    // If the trait constant's name is not found, then a missing item diagnostic is reported.
1136    db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1137        Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Constant)),
1138        None => Err(skip_diagnostic()),
1139    })
1140}
1141
1142/// Query implementation of [crate::db::SemanticGroup::impl_impls].
1143pub fn impl_impls(
1144    db: &dyn SemanticGroup,
1145    impl_def_id: ImplDefId,
1146) -> Maybe<Arc<OrderedHashMap<ImplImplDefId, ast::ItemImplAlias>>> {
1147    Ok(db.priv_impl_definition_data(impl_def_id)?.item_impl_asts)
1148}
1149
1150/// Query implementation of [crate::db::SemanticGroup::impl_impl_ids].
1151pub fn impl_impl_ids(
1152    db: &dyn SemanticGroup,
1153    impl_def_id: ImplDefId,
1154) -> Maybe<Arc<[ImplImplDefId]>> {
1155    Ok(db.impl_impls(impl_def_id)?.keys().copied().collect_vec().into())
1156}
1157
1158/// Query implementation of [crate::db::SemanticGroup::impl_impl_by_id].
1159pub fn impl_impl_by_id(
1160    db: &dyn SemanticGroup,
1161    impl_impl_id: ImplImplDefId,
1162) -> Maybe<Option<ast::ItemImplAlias>> {
1163    let impl_impls = db.impl_impls(impl_impl_id.impl_def_id(db))?;
1164    Ok(impl_impls.get(&impl_impl_id).cloned())
1165}
1166
1167/// Query implementation of [crate::db::SemanticGroup::impl_impl_by_trait_impl].
1168pub fn impl_impl_by_trait_impl(
1169    db: &dyn SemanticGroup,
1170    impl_def_id: ImplDefId,
1171    trait_impl_id: TraitImplId,
1172) -> Maybe<ImplImplDefId> {
1173    if trait_impl_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1174        unreachable!(
1175            "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1176             trait"
1177        )
1178    }
1179
1180    let name = trait_impl_id.name(db);
1181    // If the trait impl's name is not found, then a missing item diagnostic is reported.
1182    db.impl_item_by_name(impl_def_id, name).and_then(|maybe_item_id| match maybe_item_id {
1183        Some(item_id) => Ok(extract_matches!(item_id, ImplItemId::Impl)),
1184        None => Err(skip_diagnostic()),
1185    })
1186}
1187
1188/// Query implementation of [crate::db::SemanticGroup::is_implicit_impl_impl].
1189pub fn is_implicit_impl_impl(
1190    db: &dyn SemanticGroup,
1191    impl_def_id: ImplDefId,
1192    trait_impl_id: TraitImplId,
1193) -> Maybe<bool> {
1194    if trait_impl_id.trait_id(db) != db.impl_def_trait(impl_def_id)? {
1195        unreachable!(
1196            "impl_impl_by_trait_impl called with a trait impl that does not belong to the impl's \
1197             trait"
1198        )
1199    }
1200
1201    let name = trait_impl_id.name(db);
1202    // If the trait impl's name is not found, then a missing item diagnostic is reported.
1203    Ok(db.impl_implicit_impl_by_name(impl_def_id, name)?.is_some())
1204}
1205
1206// --- Computation ---
1207
1208/// Query implementation of [crate::db::SemanticGroup::priv_impl_definition_data].
1209pub fn priv_impl_definition_data(
1210    db: &dyn SemanticGroup,
1211    impl_def_id: ImplDefId,
1212) -> Maybe<ImplDefinitionData> {
1213    let module_file_id = impl_def_id.module_file_id(db);
1214    let mut diagnostics = SemanticDiagnostics::default();
1215
1216    let generic_params = db.impl_def_generic_params(impl_def_id)?;
1217    let concrete_trait = db.priv_impl_declaration_data(impl_def_id)?.concrete_trait?;
1218
1219    let impl_ast = db.module_impl_by_id(impl_def_id)?.to_maybe()?;
1220
1221    let generic_params_ids =
1222        generic_params.iter().map(|generic_param| generic_param.id()).collect();
1223    let lookup_context = ImplLookupContext::new(module_file_id.0, generic_params_ids);
1224    check_special_impls(
1225        db,
1226        &mut diagnostics,
1227        lookup_context,
1228        concrete_trait,
1229        impl_ast.stable_ptr(db).untyped(),
1230    )
1231    // Ignore the result.
1232    .ok();
1233
1234    let mut function_asts = OrderedHashMap::default();
1235    let mut item_type_asts = OrderedHashMap::default();
1236    let mut item_constant_asts = OrderedHashMap::default();
1237    let mut item_impl_asts = OrderedHashMap::default();
1238    let mut item_id_by_name: OrderedHashMap<SmolStr, ImplItemInfo> = OrderedHashMap::default();
1239
1240    if let MaybeImplBody::Some(body) = impl_ast.body(db) {
1241        for item in body.items(db).elements(db) {
1242            match item {
1243                ImplItem::Module(module) => {
1244                    report_invalid_impl_item(db, &mut diagnostics, module.module_kw(db))
1245                }
1246
1247                ImplItem::Use(use_item) => {
1248                    report_invalid_impl_item(db, &mut diagnostics, use_item.use_kw(db))
1249                }
1250                ImplItem::ExternFunction(extern_func) => {
1251                    report_invalid_impl_item(db, &mut diagnostics, extern_func.extern_kw(db))
1252                }
1253                ImplItem::ExternType(extern_type) => {
1254                    report_invalid_impl_item(db, &mut diagnostics, extern_type.extern_kw(db))
1255                }
1256                ImplItem::Trait(trt) => {
1257                    report_invalid_impl_item(db, &mut diagnostics, trt.trait_kw(db))
1258                }
1259                ImplItem::Struct(structure) => {
1260                    report_invalid_impl_item(db, &mut diagnostics, structure.struct_kw(db))
1261                }
1262                ImplItem::Enum(enm) => {
1263                    report_invalid_impl_item(db, &mut diagnostics, enm.enum_kw(db))
1264                }
1265                ImplItem::Function(func) => {
1266                    let impl_function_id =
1267                        ImplFunctionLongId(module_file_id, func.stable_ptr(db)).intern(db);
1268                    let name_node = func.declaration(db).name(db);
1269                    let name = name_node.text(db);
1270                    let feature_kind =
1271                        FeatureKind::from_ast(db, &mut diagnostics, &func.attributes(db));
1272                    if item_id_by_name
1273                        .insert(
1274                            name.clone(),
1275                            ImplItemInfo {
1276                                id: ImplItemId::Function(impl_function_id),
1277                                feature_kind,
1278                            },
1279                        )
1280                        .is_some()
1281                    {
1282                        diagnostics
1283                            .report(name_node.stable_ptr(db), NameDefinedMultipleTimes(name));
1284                    }
1285                    function_asts.insert(impl_function_id, func);
1286                }
1287                ImplItem::Type(ty) => {
1288                    let impl_type_id =
1289                        ImplTypeDefLongId(module_file_id, ty.stable_ptr(db)).intern(db);
1290                    let name_node = ty.name(db);
1291                    let name = name_node.text(db);
1292                    let feature_kind =
1293                        FeatureKind::from_ast(db, &mut diagnostics, &ty.attributes(db));
1294                    if item_id_by_name
1295                        .insert(
1296                            name.clone(),
1297                            ImplItemInfo { id: ImplItemId::Type(impl_type_id), feature_kind },
1298                        )
1299                        .is_some()
1300                    {
1301                        diagnostics
1302                            .report(name_node.stable_ptr(db), NameDefinedMultipleTimes(name));
1303                    }
1304                    item_type_asts.insert(impl_type_id, ty);
1305                }
1306                ImplItem::Constant(constant) => {
1307                    let impl_constant_id =
1308                        ImplConstantDefLongId(module_file_id, constant.stable_ptr(db)).intern(db);
1309                    let name_node = constant.name(db);
1310                    let name = name_node.text(db);
1311                    let feature_kind =
1312                        FeatureKind::from_ast(db, &mut diagnostics, &constant.attributes(db));
1313                    if item_id_by_name
1314                        .insert(
1315                            name.clone(),
1316                            ImplItemInfo {
1317                                id: ImplItemId::Constant(impl_constant_id),
1318                                feature_kind,
1319                            },
1320                        )
1321                        .is_some()
1322                    {
1323                        diagnostics.report(
1324                            name_node.stable_ptr(db),
1325                            SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1326                        );
1327                    }
1328                    item_constant_asts.insert(impl_constant_id, constant);
1329                }
1330                ImplItem::Impl(imp) => {
1331                    let impl_impl_id =
1332                        ImplImplDefLongId(module_file_id, imp.stable_ptr(db)).intern(db);
1333                    let name_node = imp.name(db);
1334                    let name = name_node.text(db);
1335                    let feature_kind =
1336                        FeatureKind::from_ast(db, &mut diagnostics, &imp.attributes(db));
1337                    if item_id_by_name
1338                        .insert(
1339                            name.clone(),
1340                            ImplItemInfo { id: ImplItemId::Impl(impl_impl_id), feature_kind },
1341                        )
1342                        .is_some()
1343                    {
1344                        diagnostics.report(
1345                            name_node.stable_ptr(db),
1346                            SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
1347                        );
1348                    }
1349                    item_impl_asts.insert(impl_impl_id, imp);
1350                }
1351                // Report nothing, a parser diagnostic is reported.
1352                ImplItem::Missing(_) => {}
1353            }
1354        }
1355    }
1356
1357    let mut implicit_impls_id_by_name = OrderedHashMap::default();
1358
1359    let trait_id = concrete_trait.lookup_intern(db).trait_id;
1360    for trait_impl_id in db.trait_impls(trait_id)? {
1361        if item_id_by_name.contains_key(&trait_impl_id.0) {
1362            continue;
1363        }
1364        implicit_impls_id_by_name.insert(trait_impl_id.0, trait_impl_id.1);
1365    }
1366
1367    // It is later verified that all items in this impl match items from `concrete_trait`.
1368    // To ensure exact match (up to trait functions with default implementation), it is sufficient
1369    // to verify here that all items in `concrete_trait` appear in this impl.
1370    let impl_item_names: OrderedHashSet<SmolStr> = item_id_by_name.keys().cloned().collect();
1371
1372    let trait_required_item_names = db.trait_required_item_names(trait_id)?;
1373    let missing_items_in_impl =
1374        trait_required_item_names.difference(&impl_item_names).cloned().collect::<Vec<_>>();
1375    if !missing_items_in_impl.is_empty() {
1376        diagnostics.report(
1377            // TODO(yuval): change this to point to impl declaration (need to add ImplDeclaration
1378            // in cairo_spec).
1379            // TODO(TomerStarkware): make sure we do not report missing if the trait item is
1380            // unsupported in impl.
1381            impl_ast.name(db).stable_ptr(db),
1382            SemanticDiagnosticKind::MissingItemsInImpl(missing_items_in_impl),
1383        );
1384    }
1385
1386    Ok(ImplDefinitionData {
1387        diagnostics: diagnostics.build(),
1388        function_asts,
1389        item_type_asts: item_type_asts.into(),
1390        item_id_by_name: item_id_by_name.into(),
1391        item_constant_asts: item_constant_asts.into(),
1392        item_impl_asts: item_impl_asts.into(),
1393        implicit_impls_id_by_name: implicit_impls_id_by_name.into(),
1394    })
1395}
1396
1397/// A helper function to report diagnostics of items in an impl (used in
1398/// priv_impl_definition_data).
1399fn report_invalid_impl_item<Terminal: syntax::node::Terminal>(
1400    db: &dyn SyntaxGroup,
1401    diagnostics: &mut SemanticDiagnostics,
1402    kw_terminal: Terminal,
1403) {
1404    diagnostics
1405        .report(kw_terminal.as_syntax_node().stable_ptr(db), InvalidImplItem(kw_terminal.text(db)));
1406}
1407
1408/// Handle special cases such as Copy and Drop checking.
1409fn check_special_impls(
1410    db: &dyn SemanticGroup,
1411    diagnostics: &mut SemanticDiagnostics,
1412    lookup_context: ImplLookupContext,
1413    concrete_trait: ConcreteTraitId,
1414    stable_ptr: SyntaxStablePtrId,
1415) -> Maybe<()> {
1416    let ConcreteTraitLongId { trait_id, generic_args } = concrete_trait.lookup_intern(db);
1417    let info = db.core_info();
1418    let copy = info.copy_trt;
1419    let drop = info.drop_trt;
1420
1421    if trait_id == copy {
1422        let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1423        for inference_error in tys
1424            .into_iter()
1425            .map(|ty| db.type_info(lookup_context.clone(), ty))
1426            .flat_map(|info| info.copyable.err())
1427        {
1428            if matches!(
1429                inference_error,
1430                InferenceError::Ambiguity(Ambiguity::MultipleImplsFound { .. })
1431            ) {
1432                // Having multiple drop implementations for a member is not an actual error.
1433                continue;
1434            }
1435            return Err(diagnostics.report(stable_ptr, InvalidCopyTraitImpl(inference_error)));
1436        }
1437    }
1438    if trait_id == drop {
1439        let tys = get_inner_types(db, extract_matches!(generic_args[0], GenericArgumentId::Type))?;
1440        for inference_error in tys
1441            .into_iter()
1442            .map(|ty| db.type_info(lookup_context.clone(), ty))
1443            .flat_map(|info| info.droppable.err())
1444        {
1445            if matches!(
1446                inference_error,
1447                InferenceError::Ambiguity(Ambiguity::MultipleImplsFound { .. })
1448            ) {
1449                // Having multiple drop implementations for a member is not an actual error.
1450                continue;
1451            }
1452            return Err(diagnostics.report(stable_ptr, InvalidDropTraitImpl(inference_error)));
1453        }
1454    }
1455
1456    Ok(())
1457}
1458
1459/// Retrieves all the inner types (members of a struct / tuple or variants of an enum).
1460///
1461/// These are the types that are required to implement some trait,
1462/// in order for the original type to be able to implement this trait.
1463///
1464/// For example, a struct containing a type T can implement Drop only if T implements Drop.
1465fn get_inner_types(db: &dyn SemanticGroup, ty: TypeId) -> Maybe<Vec<TypeId>> {
1466    Ok(match ty.lookup_intern(db) {
1467        TypeLongId::Concrete(concrete_type_id) => {
1468            // Look for Copy and Drop trait in the defining module.
1469            match concrete_type_id {
1470                crate::ConcreteTypeId::Struct(concrete_struct_id) => db
1471                    .concrete_struct_members(concrete_struct_id)?
1472                    .values()
1473                    .map(|member| member.ty)
1474                    .collect(),
1475                crate::ConcreteTypeId::Enum(concrete_enum_id) => db
1476                    .concrete_enum_variants(concrete_enum_id)?
1477                    .into_iter()
1478                    .map(|variant| variant.ty)
1479                    .collect(),
1480                crate::ConcreteTypeId::Extern(_) => vec![],
1481            }
1482        }
1483        TypeLongId::Tuple(tys) => tys,
1484        TypeLongId::Snapshot(_) | TypeLongId::Closure(_) => vec![],
1485        TypeLongId::GenericParameter(_) => {
1486            return Err(skip_diagnostic());
1487        }
1488        TypeLongId::Var(_) | TypeLongId::ImplType(_) => {
1489            panic!("Types should be fully resolved at this point.")
1490        }
1491        TypeLongId::Coupon(_) => vec![],
1492        TypeLongId::FixedSizeArray { type_id, .. } => vec![type_id],
1493        TypeLongId::Missing(diag_added) => {
1494            return Err(diag_added);
1495        }
1496    })
1497}
1498
1499// === Trait Filter ===
1500
1501/// A filter for trait lookup that is not based on current inference state. This is
1502/// used for caching queries.
1503#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1504pub struct TraitFilter {
1505    pub trait_id: TraitId,
1506    /// The filter on the generic arguments.
1507    pub generics_filter: GenericsHeadFilter,
1508}
1509
1510/// A lookup filter on generic arguments that is not based on current inference state.
1511/// This is used for caching queries.
1512#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1513pub enum GenericsHeadFilter {
1514    /// No filter is applied. When nothing is known about the generics, this will lead to a
1515    /// wider search.
1516    NoFilter,
1517    /// Generics exists and the first generic parameter has a filter.
1518    /// This is usually enough to considerably reduce the number of searched items.
1519    FirstGenericFilter(GenericArgumentHead),
1520    /// Generics must not exist.
1521    NoGenerics,
1522}
1523
1524/// Query implementation of [crate::db::SemanticGroup::module_impl_ids_for_trait_filter].
1525pub fn module_impl_ids_for_trait_filter(
1526    db: &dyn SemanticGroup,
1527    module_id: ModuleId,
1528    trait_filter: TraitFilter,
1529) -> Maybe<Vec<UninferredImpl>> {
1530    // Get the impls first from the module, do not change this order.
1531    let mut uninferred_impls: OrderedHashSet<UninferredImpl> =
1532        OrderedHashSet::from_iter(module_impl_ids(db, module_id, module_id)?);
1533    for (user_module, containing_module) in &db.priv_module_use_star_modules(module_id).accessible {
1534        if let Ok(star_module_uninferred_impls) =
1535            module_impl_ids(db, *user_module, *containing_module)
1536        {
1537            uninferred_impls.extend(star_module_uninferred_impls);
1538        }
1539    }
1540    let mut res = Vec::new();
1541    for uninferred_impl in uninferred_impls {
1542        let Ok(trait_id) = uninferred_impl.trait_id(db) else { continue };
1543        if trait_id != trait_filter.trait_id {
1544            continue;
1545        }
1546        let Ok(concrete_trait_id) = uninferred_impl.concrete_trait(db) else {
1547            continue;
1548        };
1549        if let Ok(true) = concrete_trait_fits_trait_filter(db, concrete_trait_id, &trait_filter) {
1550            res.push(uninferred_impl);
1551        }
1552    }
1553    Ok(res)
1554}
1555
1556/// Returns the uninferred impls in a module.
1557fn module_impl_ids(
1558    db: &dyn SemanticGroup,
1559    user_module: ModuleId,
1560    containing_module: ModuleId,
1561) -> Maybe<Vec<UninferredImpl>> {
1562    let mut uninferred_impls = Vec::new();
1563    for item in db.priv_module_semantic_data(containing_module)?.items.values() {
1564        if !matches!(
1565            item.item_id,
1566            ModuleItemId::Impl(_) | ModuleItemId::ImplAlias(_) | ModuleItemId::Use(_)
1567        ) {
1568            continue;
1569        }
1570        if !peek_visible_in(db, item.visibility, containing_module, user_module) {
1571            continue;
1572        }
1573        match item.item_id {
1574            ModuleItemId::Impl(impl_def_id) => {
1575                uninferred_impls.push(UninferredImpl::Def(impl_def_id));
1576            }
1577            ModuleItemId::ImplAlias(impl_alias_id) => {
1578                uninferred_impls.push(UninferredImpl::ImplAlias(impl_alias_id));
1579            }
1580            ModuleItemId::Use(use_id) => match db.use_resolved_item(use_id) {
1581                Ok(ResolvedGenericItem::Impl(impl_def_id)) => {
1582                    uninferred_impls.push(UninferredImpl::Def(impl_def_id));
1583                }
1584                Ok(ResolvedGenericItem::GenericImplAlias(impl_alias_id)) => {
1585                    uninferred_impls.push(UninferredImpl::ImplAlias(impl_alias_id));
1586                }
1587                _ => {}
1588            },
1589            _ => {}
1590        }
1591    }
1592    Ok(uninferred_impls)
1593}
1594
1595/// Cycle handling for [crate::db::SemanticGroup::module_impl_ids_for_trait_filter].
1596pub fn module_impl_ids_for_trait_filter_cycle(
1597    _db: &dyn SemanticGroup,
1598    _cycle: &salsa::Cycle,
1599    _module_id: &ModuleId,
1600    _trait_filter: &TraitFilter,
1601) -> Maybe<Vec<UninferredImpl>> {
1602    // The diagnostics will be reported from the calling function, specifically from
1603    // `priv_impl_declaration_data_inner`.
1604    Err(skip_diagnostic())
1605}
1606
1607/// Query implementation of [crate::db::SemanticGroup::impl_impl_ids_for_trait_filter].
1608pub fn impl_impl_ids_for_trait_filter(
1609    db: &dyn SemanticGroup,
1610    impl_id: ImplId,
1611    trait_filter: TraitFilter,
1612) -> Maybe<Vec<UninferredImpl>> {
1613    let mut uninferred_impls = Vec::new();
1614    for (_, trait_impl_id) in db.trait_impls(impl_id.concrete_trait(db)?.trait_id(db))?.iter() {
1615        uninferred_impls.push(UninferredImpl::ImplImpl(ImplImplId::new(
1616            impl_id,
1617            *trait_impl_id,
1618            db,
1619        )));
1620    }
1621    let mut res = Vec::new();
1622    for uninferred_impl in uninferred_impls {
1623        let Ok(trait_id) = uninferred_impl.trait_id(db) else { continue };
1624        if trait_id != trait_filter.trait_id {
1625            continue;
1626        }
1627        let Ok(concrete_trait_id) = uninferred_impl.concrete_trait(db) else {
1628            continue;
1629        };
1630        if let Ok(true) = concrete_trait_fits_trait_filter(db, concrete_trait_id, &trait_filter) {
1631            res.push(uninferred_impl);
1632        }
1633    }
1634
1635    Ok(res)
1636}
1637/// Cycle handling for [crate::db::SemanticGroup::impl_impl_ids_for_trait_filter].
1638pub fn impl_impl_ids_for_trait_filter_cycle(
1639    _db: &dyn SemanticGroup,
1640    _cycle: &salsa::Cycle,
1641    _imp: &ImplId,
1642    _trait_filter: &TraitFilter,
1643) -> Maybe<Vec<UninferredImpl>> {
1644    // The diagnostics will be reported from the calling function, specifically from
1645    // `priv_impl_declaration_data_inner`.
1646    Err(skip_diagnostic())
1647}
1648
1649/// Checks whether an [ImplDefId] passes a [TraitFilter].
1650fn concrete_trait_fits_trait_filter(
1651    db: &dyn SemanticGroup,
1652    concrete_trait_id: ConcreteTraitId,
1653    trait_filter: &TraitFilter,
1654) -> Maybe<bool> {
1655    if trait_filter.trait_id != concrete_trait_id.trait_id(db) {
1656        return Ok(false);
1657    }
1658    let generic_args = concrete_trait_id.generic_args(db);
1659    let first_generic = generic_args.first();
1660    Ok(match &trait_filter.generics_filter {
1661        GenericsHeadFilter::NoFilter => true,
1662        GenericsHeadFilter::FirstGenericFilter(constraint_head) => {
1663            let Some(first_generic) = first_generic else {
1664                return Ok(false);
1665            };
1666            let Some(first_generic_head) = first_generic.head(db) else {
1667                return Ok(true);
1668            };
1669            &first_generic_head == constraint_head
1670        }
1671        GenericsHeadFilter::NoGenerics => first_generic.is_none(),
1672    })
1673}
1674
1675#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
1676pub enum ImplOrModuleById {
1677    Impl(ImplId),
1678    Module(ModuleId),
1679}
1680impl From<ImplId> for ImplOrModuleById {
1681    fn from(impl_id: ImplId) -> Self {
1682        ImplOrModuleById::Impl(impl_id)
1683    }
1684}
1685impl From<ModuleId> for ImplOrModuleById {
1686    fn from(module_id: ModuleId) -> Self {
1687        ImplOrModuleById::Module(module_id)
1688    }
1689}
1690
1691impl Ord for ImplOrModuleById {
1692    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1693        match (self, other) {
1694            (ImplOrModuleById::Impl(imp), ImplOrModuleById::Impl(other_impl)) => {
1695                imp.get_internal_id().cmp(other_impl.get_internal_id())
1696            }
1697            (ImplOrModuleById::Module(module), ImplOrModuleById::Module(other_module)) => {
1698                match (module, other_module) {
1699                    (ModuleId::CrateRoot(crate_id), ModuleId::CrateRoot(other_crate_id)) => {
1700                        crate_id.get_internal_id().cmp(other_crate_id.get_internal_id())
1701                    }
1702                    (ModuleId::CrateRoot(_), ModuleId::Submodule(_)) => std::cmp::Ordering::Less,
1703                    (ModuleId::Submodule(_), ModuleId::CrateRoot(_)) => std::cmp::Ordering::Greater,
1704                    (ModuleId::Submodule(module_id), ModuleId::Submodule(other_module_id)) => {
1705                        module_id.get_internal_id().cmp(other_module_id.get_internal_id())
1706                    }
1707                }
1708            }
1709            (ImplOrModuleById::Impl(_), ImplOrModuleById::Module(_)) => std::cmp::Ordering::Less,
1710            (ImplOrModuleById::Module(_), ImplOrModuleById::Impl(_)) => std::cmp::Ordering::Greater,
1711        }
1712    }
1713}
1714impl PartialOrd for ImplOrModuleById {
1715    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1716        Some(self.cmp(other))
1717    }
1718}
1719
1720#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, DebugWithDb)]
1721#[debug_db(dyn SemanticGroup + 'static)]
1722pub struct ImplLookupContext {
1723    pub modules_and_impls: BTreeSet<ImplOrModuleById>,
1724    pub generic_params: Vec<GenericParamId>,
1725}
1726impl ImplLookupContext {
1727    pub fn new(module_id: ModuleId, generic_params: Vec<GenericParamId>) -> ImplLookupContext {
1728        Self { modules_and_impls: [ImplOrModuleById::Module(module_id)].into(), generic_params }
1729    }
1730    pub fn insert_lookup_scope(&mut self, db: &dyn SemanticGroup, imp: &UninferredImpl) {
1731        let item = match imp {
1732            UninferredImpl::Def(impl_def_id) => impl_def_id.module_file_id(db).0.into(),
1733            UninferredImpl::ImplAlias(impl_alias_id) => impl_alias_id.module_file_id(db).0.into(),
1734            UninferredImpl::GenericParam(param) => param.module_file_id(db).0.into(),
1735            UninferredImpl::ImplImpl(impl_impl_id) => impl_impl_id.impl_id.into(),
1736            UninferredImpl::GeneratedImpl(_) => {
1737                // GeneratedImpls do not extend the lookup context.
1738                return;
1739            }
1740        };
1741        self.modules_and_impls.insert(item);
1742    }
1743    pub fn insert_module(&mut self, module_id: ModuleId) -> bool {
1744        self.modules_and_impls.insert(ImplOrModuleById::Module(module_id))
1745    }
1746
1747    pub fn insert_impl(&mut self, impl_id: ImplId) -> bool {
1748        self.modules_and_impls.insert(ImplOrModuleById::Impl(impl_id))
1749    }
1750}
1751
1752/// A candidate impl for later inference.
1753#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
1754pub enum UninferredImpl {
1755    Def(ImplDefId),
1756    ImplAlias(ImplAliasId),
1757    GenericParam(GenericParamId),
1758    ImplImpl(ImplImplId),
1759    GeneratedImpl(UninferredGeneratedImplId),
1760}
1761impl UninferredImpl {
1762    pub fn concrete_trait(&self, db: &dyn SemanticGroup) -> Maybe<ConcreteTraitId> {
1763        match self {
1764            UninferredImpl::Def(impl_def_id) => db.impl_def_concrete_trait(*impl_def_id),
1765            UninferredImpl::ImplAlias(impl_alias_id) => {
1766                let impl_id = db.impl_alias_resolved_impl(*impl_alias_id)?;
1767                impl_id.concrete_trait(db)
1768            }
1769            UninferredImpl::GenericParam(param) => {
1770                let param =
1771                    extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
1772                param.concrete_trait
1773            }
1774            UninferredImpl::ImplImpl(impl_impl_id) => db.impl_impl_concrete_trait(*impl_impl_id),
1775            UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
1776        }
1777    }
1778
1779    fn trait_id(&self, db: &dyn SemanticGroup) -> Maybe<TraitId> {
1780        match self {
1781            UninferredImpl::Def(impl_def_id) => db.impl_def_trait(*impl_def_id),
1782            UninferredImpl::ImplAlias(impl_alias_id) => {
1783                let impl_def_id = db.impl_alias_impl_def(*impl_alias_id)?;
1784                db.impl_def_trait(impl_def_id)
1785            }
1786            UninferredImpl::GenericParam(param) => {
1787                let param =
1788                    extract_matches!(db.generic_param_semantic(*param)?, GenericParam::Impl);
1789                param.concrete_trait.map(|concrete_trait| concrete_trait.trait_id(db))
1790            }
1791            UninferredImpl::ImplImpl(impl_impl_id) => db
1792                .impl_impl_concrete_trait(*impl_impl_id)
1793                .map(|concrete_trait| concrete_trait.trait_id(db)),
1794            UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.trait_id(db)),
1795        }
1796    }
1797
1798    pub fn lookup_scope(&self, db: &dyn SemanticGroup) -> ImplOrModuleById {
1799        match self {
1800            UninferredImpl::Def(impl_def_id) => impl_def_id.module_file_id(db).0.into(),
1801            UninferredImpl::ImplAlias(impl_alias_id) => impl_alias_id.module_file_id(db).0.into(),
1802            UninferredImpl::GenericParam(param) => param.module_file_id(db).0.into(),
1803            UninferredImpl::ImplImpl(impl_impl_id) => impl_impl_id.impl_id.into(),
1804            UninferredImpl::GeneratedImpl(generated_impl) => {
1805                generated_impl.concrete_trait(db).trait_id(db).module_file_id(db).0.into()
1806            }
1807        }
1808    }
1809}
1810impl DebugWithDb<dyn SemanticGroup> for UninferredImpl {
1811    fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &dyn SemanticGroup) -> std::fmt::Result {
1812        match self {
1813            UninferredImpl::Def(impl_def) => write!(f, "{:?}", impl_def.full_path(db)),
1814            UninferredImpl::ImplAlias(impl_alias) => {
1815                write!(f, "{:?}", impl_alias.full_path(db))
1816            }
1817            UninferredImpl::GenericParam(param) => {
1818                write!(f, "generic param {}", param.name(db).unwrap_or_else(|| "_".into()))
1819            }
1820            UninferredImpl::ImplImpl(impl_impl) => impl_impl.fmt(f, db.elongate()),
1821            UninferredImpl::GeneratedImpl(generated_impl) => generated_impl.fmt(f, db.elongate()),
1822        }
1823    }
1824}
1825
1826define_short_id!(
1827    UninferredGeneratedImplId,
1828    UninferredGeneratedImplLongId,
1829    SemanticGroup,
1830    lookup_intern_uninferred_generated_impl,
1831    intern_uninferred_generated_impl
1832);
1833semantic_object_for_id!(
1834    UninferredGeneratedImplId,
1835    lookup_intern_uninferred_generated_impl,
1836    intern_uninferred_generated_impl,
1837    UninferredGeneratedImplLongId
1838);
1839
1840impl UninferredGeneratedImplId {
1841    pub fn concrete_trait(self, db: &dyn SemanticGroup) -> ConcreteTraitId {
1842        db.lookup_intern_uninferred_generated_impl(self).concrete_trait
1843    }
1844
1845    pub fn trait_id(&self, db: &dyn SemanticGroup) -> TraitId {
1846        self.concrete_trait(db).trait_id(db)
1847    }
1848}
1849
1850/// Generated impls before inference, see GeneratedImplLongId for more details.
1851#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
1852pub struct UninferredGeneratedImplLongId {
1853    pub concrete_trait: ConcreteTraitId,
1854    pub generic_params: Vec<GenericParam>,
1855    pub impl_items: GeneratedImplItems,
1856}
1857
1858impl DebugWithDb<dyn SemanticGroup> for UninferredGeneratedImplLongId {
1859    fn fmt(
1860        &self,
1861        f: &mut std::fmt::Formatter<'_>,
1862        db: &(dyn SemanticGroup + 'static),
1863    ) -> std::fmt::Result {
1864        write!(f, "Generated {:?}", self.concrete_trait.debug(db))
1865    }
1866}
1867
1868/// Finds all the implementations of a concrete trait, in a specific lookup context.
1869pub fn find_candidates_at_context(
1870    db: &dyn SemanticGroup,
1871    lookup_context: &ImplLookupContext,
1872    filter: &TraitFilter,
1873) -> Maybe<OrderedHashSet<UninferredImpl>> {
1874    let mut res = OrderedHashSet::default();
1875    for generic_param_id in &lookup_context.generic_params {
1876        if !matches!(generic_param_id.kind(db), GenericKind::Impl) {
1877            continue;
1878        };
1879        let Ok(trait_id) = db.generic_impl_param_trait(*generic_param_id) else {
1880            continue;
1881        };
1882        if filter.trait_id != trait_id {
1883            continue;
1884        }
1885        let Ok(generic_param_semantic) = db.generic_param_semantic(*generic_param_id) else {
1886            continue;
1887        };
1888        let param = extract_matches!(generic_param_semantic, GenericParam::Impl);
1889        let Ok(imp_concrete_trait_id) = param.concrete_trait else { continue };
1890        let Ok(trait_fits_filter) =
1891            concrete_trait_fits_trait_filter(db, imp_concrete_trait_id, filter)
1892        else {
1893            continue;
1894        };
1895        if !trait_fits_filter {
1896            continue;
1897        }
1898        res.insert(UninferredImpl::GenericParam(*generic_param_id));
1899    }
1900    for module_or_impl_id in &lookup_context.modules_and_impls {
1901        let Ok(imps) = (match module_or_impl_id {
1902            ImplOrModuleById::Module(module_id) => {
1903                db.module_impl_ids_for_trait_filter(*module_id, filter.clone())
1904            }
1905            ImplOrModuleById::Impl(impl_id) => {
1906                db.impl_impl_ids_for_trait_filter(*impl_id, filter.clone())
1907            }
1908        }) else {
1909            continue;
1910        };
1911        for imp in imps {
1912            res.insert(imp);
1913        }
1914    }
1915    Ok(res)
1916}
1917
1918/// Finds the generated candidate for a concrete trait.
1919pub fn find_closure_generated_candidate(
1920    db: &dyn SemanticGroup,
1921    concrete_trait_id: ConcreteTraitId,
1922) -> Option<UninferredImpl> {
1923    let GenericArgumentId::Type(closure_type) = *concrete_trait_id.generic_args(db).first()? else {
1924        return None;
1925    };
1926    let TypeLongId::Closure(closure_type_long) = closure_type.lookup_intern(db) else {
1927        return None;
1928    };
1929
1930    let info = db.core_info();
1931
1932    // Handles the special cases of `Copy`, `Drop`, `Destruct` and `PanicDestruct`.
1933    let mem_trait_generic_params = |trait_id, neg_impl_trait: Option<_>| {
1934        let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
1935        chain!(
1936            closure_type_long.captured_types.iter().unique().map(|ty| {
1937                GenericParam::Impl(GenericParamImpl {
1938                    id,
1939                    concrete_trait: Maybe::Ok(db.intern_concrete_trait(ConcreteTraitLongId {
1940                        trait_id,
1941                        generic_args: vec![GenericArgumentId::Type(*ty)],
1942                    })),
1943                    type_constraints: Default::default(),
1944                })
1945            }),
1946            neg_impl_trait.map(|neg_impl_trait| {
1947                GenericParam::NegImpl(GenericParamImpl {
1948                    id,
1949                    concrete_trait: Maybe::Ok(neg_impl_trait),
1950                    type_constraints: Default::default(),
1951                })
1952            })
1953        )
1954        .collect()
1955    };
1956    let handle_mem_trait = |trait_id, neg_impl_trait: Option<_>| {
1957        (concrete_trait_id, mem_trait_generic_params(trait_id, neg_impl_trait), [].into())
1958    };
1959    let (concrete_trait, generic_params, impl_items) = match concrete_trait_id.trait_id(db) {
1960        trait_id if trait_id == info.fn_once_trt => {
1961            let concrete_trait = ConcreteTraitLongId {
1962                trait_id,
1963                generic_args: vec![
1964                    GenericArgumentId::Type(closure_type),
1965                    GenericArgumentId::Type(
1966                        TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
1967                    ),
1968                ],
1969            }
1970            .intern(db);
1971            let ret_ty = db.trait_type_by_name(trait_id, "Output".into()).unwrap().unwrap();
1972
1973            let id = db.trait_generic_params(trait_id).unwrap().first().unwrap().id();
1974            // FnOnce is generated only if there is no fn trait.
1975            let param: GenericParam = GenericParam::NegImpl(GenericParamImpl {
1976                id,
1977                concrete_trait: Maybe::Ok(
1978                    ConcreteTraitLongId {
1979                        trait_id: info.fn_trt,
1980                        generic_args: vec![
1981                            GenericArgumentId::Type(closure_type),
1982                            GenericArgumentId::Type(
1983                                TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
1984                            ),
1985                        ],
1986                    }
1987                    .intern(db),
1988                ),
1989                type_constraints: Default::default(),
1990            });
1991            (concrete_trait, vec![param], [(ret_ty, closure_type_long.ret_ty)].into())
1992        }
1993        trait_id if trait_id == info.fn_trt => {
1994            let concrete_trait = ConcreteTraitLongId {
1995                trait_id,
1996                generic_args: vec![
1997                    GenericArgumentId::Type(closure_type),
1998                    GenericArgumentId::Type(
1999                        TypeLongId::Tuple(closure_type_long.param_tys.clone()).intern(db),
2000                    ),
2001                ],
2002            }
2003            .intern(db);
2004            let ret_ty = db.trait_type_by_name(trait_id, "Output".into()).unwrap().unwrap();
2005
2006            (
2007                concrete_trait,
2008                // Makes the generated impl of fn_trait available only if the closure is copyable.
2009                mem_trait_generic_params(info.copy_trt, None),
2010                [(ret_ty, closure_type_long.ret_ty)].into(),
2011            )
2012        }
2013        trait_id if trait_id == info.drop_trt => handle_mem_trait(trait_id, None),
2014        trait_id if trait_id == info.destruct_trt => {
2015            handle_mem_trait(trait_id, Some(concrete_drop_trait(db, closure_type)))
2016        }
2017        trait_id if trait_id == info.panic_destruct_trt => {
2018            handle_mem_trait(trait_id, Some(concrete_destruct_trait(db, closure_type)))
2019        }
2020        trait_id if trait_id == info.copy_trt => handle_mem_trait(trait_id, None),
2021        _ => return None,
2022    };
2023    Some(UninferredImpl::GeneratedImpl(
2024        UninferredGeneratedImplLongId {
2025            concrete_trait,
2026            generic_params,
2027            impl_items: GeneratedImplItems(impl_items),
2028        }
2029        .intern(db),
2030    ))
2031}
2032
2033/// Checks if an impl of a trait function with a given self_ty exists.
2034/// This function does not change the state of the inference context.
2035///
2036/// `inference_errors` are aggregated here but are not reported here as diagnostics.
2037/// The caller has to make sure the diagnostics are reported appropriately.
2038pub fn can_infer_impl_by_self(
2039    ctx: &ComputationContext<'_>,
2040    inference_errors: &mut Vec<(TraitFunctionId, InferenceError)>,
2041    trait_function_id: TraitFunctionId,
2042    self_ty: TypeId,
2043    stable_ptr: SyntaxStablePtrId,
2044) -> bool {
2045    let mut temp_inference_data = ctx.resolver.data.inference_data.temporary_clone();
2046    let mut temp_inference = temp_inference_data.inference(ctx.db);
2047    let lookup_context = ctx.resolver.impl_lookup_context();
2048
2049    let Some((concrete_trait_id, _)) = temp_inference.infer_concrete_trait_by_self(
2050        trait_function_id,
2051        self_ty,
2052        &lookup_context,
2053        Some(stable_ptr),
2054        |err| inference_errors.push((trait_function_id, err)),
2055    ) else {
2056        return false;
2057    };
2058    // Find impls for it.
2059    if let Err(err_set) = temp_inference.solve() {
2060        // Error is propagated and will be reported later.
2061        if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
2062            inference_errors.push((trait_function_id, err));
2063        }
2064    }
2065    match temp_inference.trait_solution_set(
2066        concrete_trait_id,
2067        ImplVarTraitItemMappings::default(),
2068        lookup_context.clone(),
2069    ) {
2070        Ok(SolutionSet::Unique(_) | SolutionSet::Ambiguous(_)) => true,
2071        Ok(SolutionSet::None) => {
2072            inference_errors
2073                .push((trait_function_id, InferenceError::NoImplsFound(concrete_trait_id)));
2074            false
2075        }
2076        Err(err_set) => {
2077            // Error is propagated and will be reported later.
2078            if let Some(err) = temp_inference.consume_error_without_reporting(err_set) {
2079                inference_errors.push((trait_function_id, err));
2080            }
2081            false
2082        }
2083    }
2084}
2085
2086/// Returns an impl of a given trait function with a given self_ty, as well as the number of
2087/// snapshots needed to be added to it.
2088pub fn infer_impl_by_self(
2089    ctx: &mut ComputationContext<'_>,
2090    trait_function_id: TraitFunctionId,
2091    self_ty: TypeId,
2092    stable_ptr: SyntaxStablePtrId,
2093    generic_args_syntax: Option<Vec<GenericArg>>,
2094) -> Maybe<(FunctionId, usize)> {
2095    let lookup_context = ctx.resolver.impl_lookup_context();
2096    let (concrete_trait_id, n_snapshots) = ctx
2097        .resolver
2098        .inference()
2099        .infer_concrete_trait_by_self(
2100            trait_function_id,
2101            self_ty,
2102            &lookup_context,
2103            Some(stable_ptr),
2104            |_| {},
2105        )
2106        .ok_or_else(skip_diagnostic)?;
2107
2108    let concrete_trait_function_id =
2109        ConcreteTraitGenericFunctionLongId::new(ctx.db, concrete_trait_id, trait_function_id)
2110            .intern(ctx.db);
2111    let trait_func_generic_params =
2112        ctx.db.concrete_trait_function_generic_params(concrete_trait_function_id).unwrap();
2113
2114    let impl_lookup_context = ctx.resolver.impl_lookup_context();
2115    let inference = &mut ctx.resolver.inference();
2116    let generic_function = inference.infer_trait_generic_function(
2117        concrete_trait_function_id,
2118        &impl_lookup_context,
2119        Some(stable_ptr),
2120    );
2121    let generic_args = ctx.resolver.resolve_generic_args(
2122        ctx.diagnostics,
2123        GenericSubstitution::from_impl(generic_function.impl_id),
2124        &trait_func_generic_params,
2125        &generic_args_syntax.unwrap_or_default(),
2126        stable_ptr,
2127    )?;
2128
2129    Ok((
2130        FunctionLongId {
2131            function: ConcreteFunction {
2132                generic_function: GenericFunctionId::Impl(generic_function),
2133                generic_args,
2134            },
2135        }
2136        .intern(ctx.db),
2137        n_snapshots,
2138    ))
2139}
2140
2141/// Returns all the trait functions that fit the given function name, can be called on the given
2142/// `self_ty`, and have at least one implementation in context.
2143///
2144/// `inference_errors` are aggregated here but are not reported here as diagnostics.
2145/// The caller has to make sure the diagnostics are reported appropriately.
2146pub fn filter_candidate_traits(
2147    ctx: &mut ComputationContext<'_>,
2148    inference_errors: &mut Vec<(TraitFunctionId, InferenceError)>,
2149    self_ty: TypeId,
2150    candidate_traits: &[TraitId],
2151    function_name: SmolStr,
2152    stable_ptr: SyntaxStablePtrId,
2153) -> Vec<TraitFunctionId> {
2154    let mut candidates = Vec::new();
2155    for trait_id in candidate_traits.iter().copied() {
2156        let Ok(trait_functions) = ctx.db.trait_functions(trait_id) else {
2157            continue;
2158        };
2159        for (name, trait_function) in trait_functions {
2160            if name == function_name
2161                && can_infer_impl_by_self(
2162                    ctx,
2163                    inference_errors,
2164                    trait_function,
2165                    self_ty,
2166                    stable_ptr,
2167                )
2168            {
2169                candidates.push(trait_function);
2170            }
2171        }
2172    }
2173    candidates
2174}
2175
2176// === Impl Item Type definition ===
2177
2178#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
2179#[debug_db(dyn SemanticGroup + 'static)]
2180pub struct ImplItemTypeData {
2181    type_alias_data: TypeAliasData,
2182    trait_type_id: Maybe<TraitTypeId>,
2183    /// The diagnostics of the module type alias, including the ones for the type alias itself.
2184    diagnostics: Diagnostics<SemanticDiagnostic>,
2185}
2186
2187// --- Selectors ---
2188
2189/// Query implementation of [crate::db::SemanticGroup::impl_type_def_semantic_diagnostics].
2190pub fn impl_type_def_semantic_diagnostics(
2191    db: &dyn SemanticGroup,
2192    impl_type_def_id: ImplTypeDefId,
2193) -> Diagnostics<SemanticDiagnostic> {
2194    db.priv_impl_type_semantic_data(impl_type_def_id, false)
2195        .map(|data| data.diagnostics)
2196        .unwrap_or_default()
2197}
2198
2199/// Query implementation of [crate::db::SemanticGroup::impl_type_def_resolved_type].
2200pub fn impl_type_def_resolved_type(
2201    db: &dyn SemanticGroup,
2202    impl_type_def_id: ImplTypeDefId,
2203) -> Maybe<TypeId> {
2204    db.priv_impl_type_semantic_data(impl_type_def_id, false)?.type_alias_data.resolved_type
2205}
2206
2207/// Cycle handling for [crate::db::SemanticGroup::impl_type_def_resolved_type].
2208pub fn impl_type_def_resolved_type_cycle(
2209    db: &dyn SemanticGroup,
2210    _cycle: &salsa::Cycle,
2211    impl_type_def_id: &ImplTypeDefId,
2212) -> Maybe<TypeId> {
2213    db.priv_impl_type_semantic_data(*impl_type_def_id, true)?.type_alias_data.resolved_type
2214}
2215
2216/// Query implementation of [crate::db::SemanticGroup::impl_type_def_generic_params].
2217pub fn impl_type_def_generic_params(
2218    db: &dyn SemanticGroup,
2219    impl_type_def_id: ImplTypeDefId,
2220) -> Maybe<Vec<GenericParam>> {
2221    Ok(db.priv_impl_type_def_generic_params_data(impl_type_def_id)?.generic_params)
2222}
2223
2224/// Query implementation of [crate::db::SemanticGroup::impl_type_def_attributes].
2225pub fn impl_type_def_attributes(
2226    db: &dyn SemanticGroup,
2227    impl_type_def_id: ImplTypeDefId,
2228) -> Maybe<Vec<Attribute>> {
2229    Ok(db.priv_impl_type_semantic_data(impl_type_def_id, false)?.type_alias_data.attributes)
2230}
2231
2232/// Query implementation of [crate::db::SemanticGroup::impl_type_def_resolver_data].
2233pub fn impl_type_def_resolver_data(
2234    db: &dyn SemanticGroup,
2235    impl_type_def_id: ImplTypeDefId,
2236) -> Maybe<Arc<ResolverData>> {
2237    Ok(db.priv_impl_type_semantic_data(impl_type_def_id, false)?.type_alias_data.resolver_data)
2238}
2239
2240/// Query implementation of [crate::db::SemanticGroup::impl_type_def_trait_type].
2241pub fn impl_type_def_trait_type(
2242    db: &dyn SemanticGroup,
2243    impl_type_def_id: ImplTypeDefId,
2244) -> Maybe<TraitTypeId> {
2245    db.priv_impl_type_semantic_data(impl_type_def_id, false)?.trait_type_id
2246}
2247
2248// --- Computation ---
2249
2250/// Query implementation of [crate::db::SemanticGroup::priv_impl_type_semantic_data].
2251pub fn priv_impl_type_semantic_data(
2252    db: &dyn SemanticGroup,
2253    impl_type_def_id: ImplTypeDefId,
2254    in_cycle: bool,
2255) -> Maybe<ImplItemTypeData> {
2256    let mut diagnostics = SemanticDiagnostics::default();
2257    let impl_type_defs = db.impl_types(impl_type_def_id.impl_def_id(db))?;
2258    let impl_type_def_ast = impl_type_defs.get(&impl_type_def_id).to_maybe()?;
2259    let generic_params_data = db.priv_impl_type_def_generic_params_data(impl_type_def_id)?;
2260    let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2261
2262    let trait_type_id =
2263        validate_impl_item_type(db, &mut diagnostics, impl_type_def_id, impl_type_def_ast);
2264
2265    if in_cycle {
2266        Ok(ImplItemTypeData {
2267            type_alias_data: type_alias_semantic_data_cycle_helper(
2268                db,
2269                &mut diagnostics,
2270                impl_type_def_ast,
2271                lookup_item_id,
2272                generic_params_data,
2273            )?,
2274            trait_type_id,
2275            diagnostics: diagnostics.build(),
2276        })
2277    } else {
2278        // TODO(yuval): resolve type aliases later, like in module type aliases, to avoid cycles in
2279        // non-cyclic chains.
2280        Ok(ImplItemTypeData {
2281            type_alias_data: type_alias_semantic_data_helper(
2282                db,
2283                &mut diagnostics,
2284                impl_type_def_ast,
2285                lookup_item_id,
2286                generic_params_data,
2287            )?,
2288            trait_type_id,
2289            diagnostics: diagnostics.build(),
2290        })
2291    }
2292}
2293
2294/// Cycle handling for [crate::db::SemanticGroup::priv_impl_type_semantic_data].
2295pub fn priv_impl_type_semantic_data_cycle(
2296    db: &dyn SemanticGroup,
2297    _cycle: &salsa::Cycle,
2298    impl_type_def_id: &ImplTypeDefId,
2299    _in_cycle: &bool,
2300) -> Maybe<ImplItemTypeData> {
2301    // Forwarding cycle handling to `priv_impl_type_semantic_data` handler.
2302    priv_impl_type_semantic_data(db, *impl_type_def_id, true)
2303}
2304
2305/// Query implementation of [crate::db::SemanticGroup::priv_impl_type_def_generic_params_data].
2306pub fn priv_impl_type_def_generic_params_data(
2307    db: &dyn SemanticGroup,
2308    impl_type_def_id: ImplTypeDefId,
2309) -> Maybe<GenericParamsData> {
2310    let module_file_id = impl_type_def_id.module_file_id(db);
2311    let impl_type_def_ast = db.impl_type_by_id(impl_type_def_id)?.to_maybe()?;
2312    let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Type(impl_type_def_id));
2313
2314    let impl_resolver_data = db.impl_def_resolver_data(impl_type_def_id.impl_def_id(db))?;
2315    type_alias_generic_params_data_helper(
2316        db,
2317        module_file_id,
2318        &impl_type_def_ast,
2319        lookup_item_id,
2320        Some(impl_resolver_data),
2321    )
2322}
2323
2324/// Validates the impl item type, and returns the matching trait type id.
2325fn validate_impl_item_type(
2326    db: &dyn SemanticGroup,
2327    diagnostics: &mut SemanticDiagnostics,
2328    impl_type_def_id: ImplTypeDefId,
2329    impl_type_ast: &ast::ItemTypeAlias,
2330) -> Maybe<TraitTypeId> {
2331    let impl_def_id = impl_type_def_id.impl_def_id(db);
2332    let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2333    let trait_id = concrete_trait_id.trait_id(db);
2334    let type_name = impl_type_def_id.name(db);
2335    let trait_type_id = db.trait_type_by_name(trait_id, type_name.clone())?.ok_or_else(|| {
2336        diagnostics.report(
2337            impl_type_ast.stable_ptr(db),
2338            ImplItemNotInTrait {
2339                impl_def_id,
2340                impl_item_name: type_name,
2341                trait_id,
2342                item_kind: "type".into(),
2343            },
2344        )
2345    })?;
2346
2347    // TODO(yuval): add validations for generic parameters, then remove this.
2348    // Generic parameters are not yet supported, make sure there are none.
2349    let generic_params_node = impl_type_ast.generic_params(db);
2350    if !generic_params_node.is_empty(db) {
2351        diagnostics.report(
2352            generic_params_node.stable_ptr(db),
2353            GenericsNotSupportedInItem { scope: "Impl".into(), item_kind: "type".into() },
2354        );
2355    }
2356
2357    Ok(trait_type_id)
2358}
2359
2360// === Impl Type ===
2361
2362/// Query implementation of [crate::db::SemanticGroup::impl_type_concrete_implized].
2363pub fn impl_type_concrete_implized(
2364    db: &dyn SemanticGroup,
2365    impl_type_id: ImplTypeId,
2366) -> Maybe<TypeId> {
2367    let concrete_impl = match impl_type_id.impl_id().lookup_intern(db) {
2368        ImplLongId::Concrete(concrete_impl) => concrete_impl,
2369        ImplLongId::ImplImpl(imp_impl_id) => {
2370            let ImplLongId::Concrete(concrete_impl) =
2371                db.impl_impl_concrete_implized(imp_impl_id)?.lookup_intern(db)
2372            else {
2373                return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2374            };
2375            concrete_impl
2376        }
2377        ImplLongId::GenericParameter(_) | ImplLongId::SelfImpl(_) | ImplLongId::ImplVar(_) => {
2378            return Ok(TypeLongId::ImplType(impl_type_id).intern(db));
2379        }
2380        ImplLongId::GeneratedImpl(generated) => {
2381            return Ok(*generated.lookup_intern(db).impl_items.0.get(&impl_type_id.ty()).unwrap());
2382        }
2383    };
2384
2385    let impl_def_id = concrete_impl.impl_def_id(db);
2386    let ty = db.trait_type_implized_by_context(impl_type_id.ty(), impl_def_id);
2387    let Ok(ty) = ty else {
2388        return ty;
2389    };
2390    concrete_impl.substitution(db)?.substitute(db, ty)
2391}
2392
2393/// Cycle handling for [crate::db::SemanticGroup::impl_type_concrete_implized].
2394pub fn impl_type_concrete_implized_cycle(
2395    db: &dyn SemanticGroup,
2396    _cycle: &salsa::Cycle,
2397    impl_type_id: &ImplTypeId,
2398) -> Maybe<TypeId> {
2399    // Forwarding cycle handling to `priv_impl_type_semantic_data` handler.
2400    impl_type_concrete_implized(db, *impl_type_id)
2401}
2402
2403// === Impl Item Constant definition ===
2404
2405#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
2406#[debug_db(dyn SemanticGroup + 'static)]
2407pub struct ImplItemConstantData {
2408    constant_data: ConstantData,
2409    trait_constant_id: Maybe<TraitConstantId>,
2410    /// The diagnostics of the impl constant, including the ones for the constant itself.
2411    diagnostics: Diagnostics<SemanticDiagnostic>,
2412}
2413
2414// --- Selectors ---
2415
2416/// Query implementation of [crate::db::SemanticGroup::impl_constant_def_semantic_diagnostics].
2417pub fn impl_constant_def_semantic_diagnostics(
2418    db: &dyn SemanticGroup,
2419    impl_constant_def_id: ImplConstantDefId,
2420) -> Diagnostics<SemanticDiagnostic> {
2421    db.priv_impl_constant_semantic_data(impl_constant_def_id, false)
2422        .map(|data| data.diagnostics)
2423        .unwrap_or_default()
2424}
2425
2426/// Query implementation of [crate::db::SemanticGroup::impl_constant_def_value].
2427pub fn impl_constant_def_value(
2428    db: &dyn SemanticGroup,
2429    impl_constant_def_id: ImplConstantDefId,
2430) -> Maybe<ConstValueId> {
2431    Ok(db.priv_impl_constant_semantic_data(impl_constant_def_id, false)?.constant_data.const_value)
2432}
2433
2434/// Cycle handling for [crate::db::SemanticGroup::impl_constant_def_value].
2435pub fn impl_constant_def_value_cycle(
2436    db: &dyn SemanticGroup,
2437    _cycle: &salsa::Cycle,
2438    impl_constant_def_id: &ImplConstantDefId,
2439) -> Maybe<ConstValueId> {
2440    Ok(db.priv_impl_constant_semantic_data(*impl_constant_def_id, true)?.constant_data.const_value)
2441}
2442
2443/// Query implementation of [crate::db::SemanticGroup::impl_constant_def_resolver_data].
2444pub fn impl_constant_def_resolver_data(
2445    db: &dyn SemanticGroup,
2446    impl_constant_def_id: ImplConstantDefId,
2447) -> Maybe<Arc<ResolverData>> {
2448    Ok(db
2449        .priv_impl_constant_semantic_data(impl_constant_def_id, false)?
2450        .constant_data
2451        .resolver_data)
2452}
2453
2454/// Query implementation of [crate::db::SemanticGroup::impl_constant_def_trait_constant].
2455pub fn impl_constant_def_trait_constant(
2456    db: &dyn SemanticGroup,
2457    impl_constant_def_id: ImplConstantDefId,
2458) -> Maybe<TraitConstantId> {
2459    db.priv_impl_constant_semantic_data(impl_constant_def_id, false)?.trait_constant_id
2460}
2461
2462// --- Computation ---
2463
2464/// Query implementation of [crate::db::SemanticGroup::priv_impl_constant_semantic_data].
2465pub fn priv_impl_constant_semantic_data(
2466    db: &dyn SemanticGroup,
2467    impl_constant_def_id: ImplConstantDefId,
2468    in_cycle: bool,
2469) -> Maybe<ImplItemConstantData> {
2470    let mut diagnostics = SemanticDiagnostics::default();
2471    let impl_def_id = impl_constant_def_id.impl_def_id(db);
2472    let impl_constant_defs = db.impl_constants(impl_def_id)?;
2473    let impl_constant_def_ast = impl_constant_defs.get(&impl_constant_def_id).to_maybe()?;
2474    let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Constant(impl_constant_def_id));
2475
2476    let inference_id = InferenceId::LookupItemGenerics(LookupItemId::ImplItem(
2477        ImplItemId::Constant(impl_constant_def_id),
2478    ));
2479    let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2480    let mut resolver =
2481        Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2482
2483    let trait_constant_id = validate_impl_item_constant(
2484        db,
2485        &mut diagnostics,
2486        impl_constant_def_id,
2487        impl_constant_def_ast,
2488        &mut resolver,
2489    );
2490    let mut constant_data = if in_cycle {
2491        constant_semantic_data_cycle_helper(
2492            db,
2493            impl_constant_def_ast,
2494            lookup_item_id,
2495            Some(Arc::new(resolver.data)),
2496            &impl_def_id,
2497        )?
2498    } else {
2499        constant_semantic_data_helper(
2500            db,
2501            impl_constant_def_ast,
2502            lookup_item_id,
2503            Some(Arc::new(resolver.data)),
2504            &impl_def_id,
2505        )?
2506    };
2507    diagnostics.extend(mem::take(&mut constant_data.diagnostics));
2508    Ok(ImplItemConstantData { constant_data, trait_constant_id, diagnostics: diagnostics.build() })
2509}
2510
2511/// Cycle handling for [crate::db::SemanticGroup::priv_impl_constant_semantic_data].
2512pub fn priv_impl_constant_semantic_data_cycle(
2513    db: &dyn SemanticGroup,
2514    _cycle: &salsa::Cycle,
2515    impl_constant_def_id: &ImplConstantDefId,
2516    _in_cycle: &bool,
2517) -> Maybe<ImplItemConstantData> {
2518    // Forwarding cycle handling to `priv_impl_constant_semantic_data` handler.
2519    priv_impl_constant_semantic_data(db, *impl_constant_def_id, true)
2520}
2521
2522/// Validates the impl item constant, and returns the matching trait constant id.
2523fn validate_impl_item_constant(
2524    db: &dyn SemanticGroup,
2525    diagnostics: &mut SemanticDiagnostics,
2526    impl_constant_def_id: ImplConstantDefId,
2527    impl_constant_ast: &ast::ItemConstant,
2528    resolver: &mut Resolver<'_>,
2529) -> Maybe<TraitConstantId> {
2530    let impl_def_id = impl_constant_def_id.impl_def_id(db);
2531    let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2532    let trait_id = concrete_trait_id.trait_id(db);
2533    let constant_name = impl_constant_def_id.name(db);
2534
2535    let trait_constant_id =
2536        db.trait_constant_by_name(trait_id, constant_name.clone())?.ok_or_else(|| {
2537            diagnostics.report(
2538                impl_constant_ast.stable_ptr(db),
2539                ImplItemNotInTrait {
2540                    impl_def_id,
2541                    impl_item_name: constant_name,
2542                    trait_id,
2543                    item_kind: "const".into(),
2544                },
2545            )
2546        })?;
2547    let concrete_trait_constant =
2548        ConcreteTraitConstantId::new(db, concrete_trait_id, trait_constant_id);
2549    let concrete_trait_constant_ty = db.concrete_trait_constant_type(concrete_trait_constant)?;
2550
2551    let impl_constant_type_clause_ast = impl_constant_ast.type_clause(db);
2552
2553    let constant_ty =
2554        resolve_type(db, diagnostics, resolver, &impl_constant_type_clause_ast.ty(db));
2555
2556    let inference = &mut resolver.inference();
2557
2558    let expected_ty = inference.rewrite(concrete_trait_constant_ty).no_err();
2559    let actual_ty = inference.rewrite(constant_ty).no_err();
2560    if expected_ty != actual_ty {
2561        diagnostics.report(
2562            impl_constant_type_clause_ast.stable_ptr(db),
2563            WrongType { expected_ty, actual_ty },
2564        );
2565    }
2566    Ok(trait_constant_id)
2567}
2568
2569// === Impl Constant ===
2570
2571/// Query implementation of [crate::db::SemanticGroup::impl_constant_implized_by_context].
2572pub fn impl_constant_implized_by_context(
2573    db: &dyn SemanticGroup,
2574    impl_constant_id: ImplConstantId,
2575    impl_def_id: ImplDefId,
2576) -> Maybe<ConstValueId> {
2577    let impl_constant_def_id: ImplConstantDefId =
2578        db.impl_constant_by_trait_constant(impl_def_id, impl_constant_id.trait_constant_id())?;
2579
2580    db.impl_constant_def_value(impl_constant_def_id)
2581}
2582
2583/// Cycle handling for [crate::db::SemanticGroup::impl_constant_implized_by_context].
2584pub fn impl_constant_implized_by_context_cycle(
2585    db: &dyn SemanticGroup,
2586    _cycle: &salsa::Cycle,
2587    impl_constant_id: &ImplConstantId,
2588    impl_def_id: &ImplDefId,
2589) -> Maybe<ConstValueId> {
2590    // Forwarding cycle handling to `priv_impl_constant_semantic_data` handler.
2591    impl_constant_implized_by_context(db, *impl_constant_id, *impl_def_id)
2592}
2593
2594/// Query implementation of [crate::db::SemanticGroup::impl_constant_concrete_implized_value].
2595pub fn impl_constant_concrete_implized_value(
2596    db: &dyn SemanticGroup,
2597    impl_constant_id: ImplConstantId,
2598) -> Maybe<ConstValueId> {
2599    if let ImplLongId::Concrete(concrete_impl) = impl_constant_id.impl_id().lookup_intern(db) {
2600        let impl_def_id = concrete_impl.impl_def_id(db);
2601        let constant = db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?;
2602        return concrete_impl.substitution(db)?.substitute(db, constant);
2603    }
2604    Ok(ConstValue::ImplConstant(
2605        GenericSubstitution::from_impl(impl_constant_id.impl_id())
2606            .substitute(db, impl_constant_id)?,
2607    )
2608    .intern(db))
2609}
2610
2611/// Cycle handling for [crate::db::SemanticGroup::impl_constant_concrete_implized_value].
2612pub fn impl_constant_concrete_implized_value_cycle(
2613    db: &dyn SemanticGroup,
2614    _cycle: &salsa::Cycle,
2615    impl_constant_id: &ImplConstantId,
2616) -> Maybe<ConstValueId> {
2617    // Forwarding cycle handling to `priv_impl_const_semantic_data` handler.
2618    impl_constant_concrete_implized_value(db, *impl_constant_id)
2619}
2620
2621/// Query implementation of [crate::db::SemanticGroup::impl_constant_concrete_implized_type].
2622pub fn impl_constant_concrete_implized_type(
2623    db: &dyn SemanticGroup,
2624    impl_constant_id: ImplConstantId,
2625) -> Maybe<TypeId> {
2626    let concrete_trait_id = match impl_constant_id.impl_id().lookup_intern(db) {
2627        ImplLongId::Concrete(concrete_impl) => {
2628            let impl_def_id = concrete_impl.impl_def_id(db);
2629            let ty = db.impl_constant_implized_by_context(impl_constant_id, impl_def_id)?.ty(db)?;
2630            return concrete_impl.substitution(db)?.substitute(db, ty);
2631        }
2632        ImplLongId::GenericParameter(param) => {
2633            let param_impl =
2634                extract_matches!(db.generic_param_semantic(param)?, GenericParam::Impl);
2635            param_impl.concrete_trait?
2636        }
2637        ImplLongId::ImplVar(var) => var.lookup_intern(db).concrete_trait_id,
2638        ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(impl_impl)?,
2639        ImplLongId::SelfImpl(concrete_trait_id) => concrete_trait_id,
2640        ImplLongId::GeneratedImpl(generated_impl) => generated_impl.concrete_trait(db),
2641    };
2642
2643    let ty = db.concrete_trait_constant_type(ConcreteTraitConstantId::new(
2644        db,
2645        concrete_trait_id,
2646        impl_constant_id.trait_constant_id(),
2647    ))?;
2648    GenericSubstitution::from_impl(impl_constant_id.impl_id()).substitute(db, ty)
2649}
2650
2651/// Cycle handling for [crate::db::SemanticGroup::impl_constant_concrete_implized_type].
2652pub fn impl_constant_concrete_implized_type_cycle(
2653    db: &dyn SemanticGroup,
2654    _cycle: &salsa::Cycle,
2655    impl_constant_id: &ImplConstantId,
2656) -> Maybe<TypeId> {
2657    // Forwarding cycle handling to `priv_impl_const_semantic_data` handler.
2658    impl_constant_concrete_implized_type(db, *impl_constant_id)
2659}
2660
2661// === Impl Item Impl definition ===
2662
2663#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
2664#[debug_db(dyn SemanticGroup + 'static)]
2665pub struct ImplItemImplData {
2666    impl_data: ImplAliasData,
2667    trait_impl_id: Maybe<TraitImplId>,
2668    /// The diagnostics of the impl impl, including the ones for the impl itself.
2669    diagnostics: Diagnostics<SemanticDiagnostic>,
2670}
2671
2672// --- Selectors ---
2673
2674/// Query implementation of [crate::db::SemanticGroup::impl_impl_def_semantic_diagnostics].
2675pub fn impl_impl_def_semantic_diagnostics(
2676    db: &dyn SemanticGroup,
2677    impl_impl_def_id: ImplImplDefId,
2678) -> Diagnostics<SemanticDiagnostic> {
2679    db.priv_impl_impl_semantic_data(impl_impl_def_id, false)
2680        .map(|data| data.diagnostics)
2681        .unwrap_or_default()
2682}
2683
2684/// Query implementation of [crate::db::SemanticGroup::impl_impl_def_resolver_data].
2685pub fn impl_impl_def_resolver_data(
2686    db: &dyn SemanticGroup,
2687    impl_impl_def_id: ImplImplDefId,
2688) -> Maybe<Arc<ResolverData>> {
2689    Ok(db.priv_impl_impl_semantic_data(impl_impl_def_id, false)?.impl_data.resolver_data)
2690}
2691
2692/// Query implementation of [crate::db::SemanticGroup::impl_impl_def_trait_impl].
2693pub fn impl_impl_def_trait_impl(
2694    db: &dyn SemanticGroup,
2695    impl_impl_def_id: ImplImplDefId,
2696) -> Maybe<TraitImplId> {
2697    db.priv_impl_impl_semantic_data(impl_impl_def_id, false)?.trait_impl_id
2698}
2699
2700/// Query implementation of [crate::db::SemanticGroup::impl_impl_def_impl].
2701pub fn impl_impl_def_impl(
2702    db: &dyn SemanticGroup,
2703    impl_impl_def_id: ImplImplDefId,
2704    in_cycle: bool,
2705) -> Maybe<ImplId> {
2706    db.priv_impl_impl_semantic_data(impl_impl_def_id, in_cycle)?.impl_data.resolved_impl
2707}
2708/// Cycle handling for [crate::db::SemanticGroup::impl_impl_def_impl].
2709pub fn impl_impl_def_impl_cycle(
2710    db: &dyn SemanticGroup,
2711    _cycle: &salsa::Cycle,
2712    impl_impl_def_id: &ImplImplDefId,
2713    _in_cycle: &bool,
2714) -> Maybe<ImplId> {
2715    db.priv_impl_impl_semantic_data(*impl_impl_def_id, true)?.impl_data.resolved_impl
2716}
2717
2718// --- Computation ---
2719
2720/// Query implementation of [crate::db::SemanticGroup::priv_impl_impl_semantic_data].
2721pub fn priv_impl_impl_semantic_data(
2722    db: &dyn SemanticGroup,
2723    impl_impl_def_id: ImplImplDefId,
2724    in_cycle: bool,
2725) -> Maybe<ImplItemImplData> {
2726    let mut diagnostics = SemanticDiagnostics::default();
2727    let impl_def_id = impl_impl_def_id.impl_def_id(db);
2728    let impl_impl_defs = db.impl_impls(impl_def_id)?;
2729    let impl_impl_def_ast = impl_impl_defs.get(&impl_impl_def_id).to_maybe()?;
2730    let generic_params_data = db.priv_impl_impl_def_generic_params_data(impl_impl_def_id)?;
2731    let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2732
2733    let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
2734    let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2735    let mut resolver =
2736        Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2737
2738    let mut impl_data = if in_cycle {
2739        impl_alias_semantic_data_cycle_helper(
2740            db,
2741            impl_impl_def_ast,
2742            lookup_item_id,
2743            generic_params_data,
2744        )?
2745    } else {
2746        impl_alias_semantic_data_helper(db, impl_impl_def_ast, lookup_item_id, generic_params_data)?
2747    };
2748
2749    diagnostics.extend(mem::take(&mut impl_data.diagnostics));
2750
2751    let trait_impl_id = validate_impl_item_impl(
2752        db,
2753        &mut diagnostics,
2754        impl_impl_def_id,
2755        impl_impl_def_ast,
2756        &impl_data,
2757        &mut resolver,
2758    );
2759
2760    Ok(ImplItemImplData { impl_data, trait_impl_id, diagnostics: diagnostics.build() })
2761}
2762
2763/// Cycle handling for [crate::db::SemanticGroup::priv_impl_impl_semantic_data].
2764pub fn priv_impl_impl_semantic_data_cycle(
2765    db: &dyn SemanticGroup,
2766    _cycle: &salsa::Cycle,
2767    impl_impl_def_id: &ImplImplDefId,
2768    _in_cycle: &bool,
2769) -> Maybe<ImplItemImplData> {
2770    // Forwarding cycle handling to `priv_impl_impl_semantic_data` handler.
2771    priv_impl_impl_semantic_data(db, *impl_impl_def_id, true)
2772}
2773
2774/// Query implementation of [crate::db::SemanticGroup::priv_impl_impl_def_generic_params_data].
2775pub fn priv_impl_impl_def_generic_params_data(
2776    db: &dyn SemanticGroup,
2777    impl_impl_def_id: ImplImplDefId,
2778) -> Maybe<GenericParamsData> {
2779    let module_file_id = impl_impl_def_id.module_file_id(db);
2780    let impl_impl_def_ast = db.impl_impl_by_id(impl_impl_def_id)?.to_maybe()?;
2781    let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Impl(impl_impl_def_id));
2782
2783    let impl_resolver_data = db.impl_def_resolver_data(impl_impl_def_id.impl_def_id(db))?;
2784    impl_alias_generic_params_data_helper(
2785        db,
2786        module_file_id,
2787        &impl_impl_def_ast,
2788        lookup_item_id,
2789        Some(impl_resolver_data),
2790    )
2791}
2792
2793/// Validates the impl item impl, and returns the matching trait impl id.
2794fn validate_impl_item_impl(
2795    db: &dyn SemanticGroup,
2796    diagnostics: &mut SemanticDiagnostics,
2797    impl_impl_def_id: ImplImplDefId,
2798    impl_impl_ast: &ast::ItemImplAlias,
2799    impl_data: &ImplAliasData,
2800    resolver: &mut Resolver<'_>,
2801) -> Maybe<TraitImplId> {
2802    let impl_def_id = impl_impl_def_id.impl_def_id(db);
2803    let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
2804    let trait_id = concrete_trait_id.trait_id(db);
2805    let impl_name = impl_impl_def_id.name(db);
2806    let trait_impl_id = db.trait_impl_by_name(trait_id, impl_name.clone())?.ok_or_else(|| {
2807        diagnostics.report(
2808            impl_impl_ast.stable_ptr(db),
2809            ImplItemNotInTrait {
2810                impl_def_id,
2811                impl_item_name: impl_name,
2812                trait_id,
2813                item_kind: "impl".into(),
2814            },
2815        )
2816    })?;
2817
2818    // TODO(TomerStarkware): add validations for generic parameters, then remove this.
2819    // Generic parameters are not yet supported, make sure there are none.
2820    let generic_params_node = impl_impl_ast.generic_params(db);
2821    if !generic_params_node.is_empty(db) {
2822        diagnostics.report(
2823            generic_params_node.stable_ptr(db),
2824            GenericsNotSupportedInItem { scope: "Impl".into(), item_kind: "impl".into() },
2825        );
2826    }
2827
2828    let concrete_trait_impl = ConcreteTraitImplId::new(db, concrete_trait_id, trait_impl_id);
2829    let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
2830
2831    let concrete_trait_impl_concrete_trait = db
2832        .concrete_trait_impl_concrete_trait(concrete_trait_impl)
2833        .and_then(|concrete_trait_id| impl_def_substitution.substitute(db, concrete_trait_id));
2834
2835    let resolved_impl_concrete_trait =
2836        impl_data.resolved_impl.and_then(|imp| imp.concrete_trait(db));
2837    // used an IIFE to allow the use of the `?` operator.
2838    let _ = (|| -> Result<(), DiagnosticAdded> {
2839        if resolver
2840            .inference()
2841            .conform_traits(resolved_impl_concrete_trait?, concrete_trait_impl_concrete_trait?)
2842            .is_err()
2843        {
2844            diagnostics.report(
2845                impl_impl_ast.stable_ptr(db),
2846                TraitMismatch {
2847                    expected_trt: concrete_trait_impl_concrete_trait?,
2848                    actual_trt: resolved_impl_concrete_trait?,
2849                },
2850            );
2851        }
2852        Ok(())
2853    })();
2854
2855    Ok(trait_impl_id)
2856}
2857
2858#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
2859#[debug_db(dyn SemanticGroup + 'static)]
2860pub struct ImplicitImplImplData {
2861    resolved_impl: Maybe<ImplId>,
2862    trait_impl_id: TraitImplId,
2863    diagnostics: Diagnostics<SemanticDiagnostic>,
2864}
2865
2866/// Query implementation of [crate::db::SemanticGroup::implicit_impl_impl_semantic_diagnostics].
2867pub fn implicit_impl_impl_semantic_diagnostics(
2868    db: &dyn SemanticGroup,
2869    impl_def_id: ImplDefId,
2870    trait_impl_id: TraitImplId,
2871) -> Diagnostics<SemanticDiagnostic> {
2872    db.priv_implicit_impl_impl_semantic_data(impl_def_id, trait_impl_id, false)
2873        .map(|data| data.diagnostics)
2874        .unwrap_or_default()
2875}
2876/// Query implementation of [crate::db::SemanticGroup::implicit_impl_impl_impl].
2877pub fn implicit_impl_impl_impl(
2878    db: &dyn SemanticGroup,
2879    impl_def_id: ImplDefId,
2880    trait_impl_id: TraitImplId,
2881    in_cycle: bool,
2882) -> Maybe<ImplId> {
2883    db.priv_implicit_impl_impl_semantic_data(impl_def_id, trait_impl_id, in_cycle)?.resolved_impl
2884}
2885/// Cycle handling for [crate::db::SemanticGroup::implicit_impl_impl_impl].
2886pub fn implicit_impl_impl_impl_cycle(
2887    db: &dyn SemanticGroup,
2888    _cycle: &salsa::Cycle,
2889    impl_def_id: &ImplDefId,
2890    trait_impl_id: &TraitImplId,
2891    _in_cycle: &bool,
2892) -> Maybe<ImplId> {
2893    db.priv_implicit_impl_impl_semantic_data(*impl_def_id, *trait_impl_id, true)?.resolved_impl
2894}
2895
2896/// Query implementation of [crate::db::SemanticGroup::priv_implicit_impl_impl_semantic_data].
2897pub fn priv_implicit_impl_impl_semantic_data(
2898    db: &dyn SemanticGroup,
2899    impl_def_id: ImplDefId,
2900    trait_impl_id: TraitImplId,
2901    in_cycle: bool,
2902) -> Maybe<ImplicitImplImplData> {
2903    let mut diagnostics = SemanticDiagnostics::default();
2904    if in_cycle {
2905        let err = Err(diagnostics.report(impl_def_id.stable_ptr(db).untyped(), ImplAliasCycle));
2906        return Ok(ImplicitImplImplData {
2907            resolved_impl: err,
2908            trait_impl_id,
2909            diagnostics: diagnostics.build(),
2910        });
2911    }
2912    let lookup_item_id = LookupItemId::ModuleItem(ModuleItemId::Impl(impl_def_id));
2913
2914    let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
2915    let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
2916
2917    let mut resolver =
2918        Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
2919    // We cannot use `Self` as it will always find the implicit impl.
2920    resolver.trait_or_impl_ctx = TraitOrImplContext::None;
2921
2922    let concrete_trait_impl_concrete_trait = db
2923        .impl_def_concrete_trait(impl_def_id)
2924        .and_then(|concrete_trait_id| {
2925            db.concrete_trait_impl_concrete_trait(ConcreteTraitImplId::new(
2926                db,
2927                concrete_trait_id,
2928                trait_impl_id,
2929            ))
2930        })
2931        .and_then(|concrete_trait_id| {
2932            let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
2933            impl_def_substitution.substitute(db, concrete_trait_id)
2934        });
2935    let impl_lookup_context = resolver.impl_lookup_context();
2936    let resolved_impl = concrete_trait_impl_concrete_trait.and_then(|concrete_trait_id| {
2937        let imp = resolver.inference().new_impl_var(concrete_trait_id, None, impl_lookup_context);
2938        resolver.inference().finalize_without_reporting().map_err(|(err_set, _)| {
2939            diagnostics.report(
2940                impl_def_id.stable_ptr(db).untyped(),
2941                ImplicitImplNotInferred { trait_impl_id, concrete_trait_id },
2942            );
2943            resolver.inference().report_on_pending_error(
2944                err_set,
2945                &mut diagnostics,
2946                impl_def_id.stable_ptr(db).untyped(),
2947            )
2948        })?;
2949        resolver.inference().rewrite(imp).map_err(|_| skip_diagnostic())
2950    });
2951
2952    Ok(ImplicitImplImplData { resolved_impl, trait_impl_id, diagnostics: diagnostics.build() })
2953}
2954/// Cycle handling for [crate::db::SemanticGroup::priv_implicit_impl_impl_semantic_data].
2955pub fn priv_implicit_impl_impl_semantic_data_cycle(
2956    db: &dyn SemanticGroup,
2957    _cycle: &salsa::Cycle,
2958    impl_def_id: &ImplDefId,
2959    trait_impl_id: &TraitImplId,
2960    _in_cycle: &bool,
2961) -> Maybe<ImplicitImplImplData> {
2962    // Forwarding cycle handling to `priv_implicit_impl_impl_semantic_data` handler.
2963    priv_implicit_impl_impl_semantic_data(db, *impl_def_id, *trait_impl_id, true)
2964}
2965
2966// === Impl Impl ===
2967
2968/// Query implementation of [crate::db::SemanticGroup::impl_impl_implized_by_context].
2969pub fn impl_impl_implized_by_context(
2970    db: &dyn SemanticGroup,
2971    impl_impl_id: ImplImplId,
2972    impl_def_id: ImplDefId,
2973    in_cycle: bool,
2974) -> Maybe<ImplId> {
2975    if db.is_implicit_impl_impl(impl_def_id, impl_impl_id.trait_impl_id())? {
2976        return db.implicit_impl_impl_impl(impl_def_id, impl_impl_id.trait_impl_id(), in_cycle);
2977    }
2978
2979    let impl_impl_def_id = db.impl_impl_by_trait_impl(impl_def_id, impl_impl_id.trait_impl_id())?;
2980
2981    db.impl_impl_def_impl(impl_impl_def_id, in_cycle)
2982}
2983
2984/// Cycle handling for [crate::db::SemanticGroup::impl_impl_implized_by_context].
2985pub fn impl_impl_implized_by_context_cycle(
2986    db: &dyn SemanticGroup,
2987    _cycle: &salsa::Cycle,
2988    impl_impl_id: &ImplImplId,
2989    impl_def_id: &ImplDefId,
2990    _in_cycle: &bool,
2991) -> Maybe<ImplId> {
2992    // Forwarding cycle handling to `priv_impl_impl_semantic_data` handler.
2993    impl_impl_implized_by_context(db, *impl_impl_id, *impl_def_id, true)
2994}
2995
2996/// Query implementation of [crate::db::SemanticGroup::impl_impl_concrete_implized].
2997pub fn impl_impl_concrete_implized(
2998    db: &dyn SemanticGroup,
2999    impl_impl_id: ImplImplId,
3000) -> Maybe<ImplId> {
3001    impl_impl_concrete_implized_ex(db, impl_impl_id, false)
3002}
3003
3004/// Cycle handling for [crate::db::SemanticGroup::impl_impl_concrete_implized].
3005pub fn impl_impl_concrete_implized_cycle(
3006    db: &dyn SemanticGroup,
3007    _cycle: &salsa::Cycle,
3008    impl_impl_id: &ImplImplId,
3009) -> Maybe<ImplId> {
3010    impl_impl_concrete_implized_ex(db, *impl_impl_id, true)
3011}
3012
3013fn impl_impl_concrete_implized_ex(
3014    db: &dyn SemanticGroup,
3015    impl_impl_id: ImplImplId,
3016    in_cycle: bool,
3017) -> Maybe<ImplId> {
3018    if let ImplLongId::Concrete(concrete_impl) = impl_impl_id.impl_id().lookup_intern(db) {
3019        let impl_def_id = concrete_impl.impl_def_id(db);
3020        let imp = db.impl_impl_implized_by_context(impl_impl_id, impl_def_id, in_cycle)?;
3021        return concrete_impl.substitution(db)?.substitute(db, imp);
3022    }
3023
3024    Ok(ImplLongId::ImplImpl(
3025        GenericSubstitution::from_impl(impl_impl_id.impl_id()).substitute(db, impl_impl_id)?,
3026    )
3027    .intern(db))
3028}
3029
3030/// Query implementation of [crate::db::SemanticGroup::impl_impl_concrete_trait].
3031pub fn impl_impl_concrete_trait(
3032    db: &dyn SemanticGroup,
3033    impl_impl_id: ImplImplId,
3034) -> Maybe<ConcreteTraitId> {
3035    let concrete_trait_impl = impl_impl_id.concrete_trait_impl_id(db)?;
3036    db.concrete_trait_impl_concrete_trait(concrete_trait_impl).and_then(|concrete_trait_id| {
3037        GenericSubstitution::from_impl(impl_impl_id.impl_id()).substitute(db, concrete_trait_id)
3038    })
3039}
3040
3041// === Impl Function Declaration ===
3042
3043#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
3044#[debug_db(dyn SemanticGroup + 'static)]
3045pub struct ImplFunctionDeclarationData {
3046    pub function_declaration_data: FunctionDeclarationData,
3047    trait_function_id: Maybe<TraitFunctionId>,
3048}
3049
3050// --- Selectors ---
3051
3052/// Query implementation of [crate::db::SemanticGroup::impl_function_declaration_diagnostics].
3053pub fn impl_function_declaration_diagnostics(
3054    db: &dyn SemanticGroup,
3055    impl_function_id: ImplFunctionId,
3056) -> Diagnostics<SemanticDiagnostic> {
3057    db.priv_impl_function_declaration_data(impl_function_id)
3058        .map(|data| data.function_declaration_data.diagnostics)
3059        .unwrap_or_default()
3060}
3061
3062/// Query implementation of [crate::db::SemanticGroup::impl_function_signature].
3063pub fn impl_function_signature(
3064    db: &dyn SemanticGroup,
3065    impl_function_id: ImplFunctionId,
3066) -> Maybe<semantic::Signature> {
3067    Ok(db
3068        .priv_impl_function_declaration_data(impl_function_id)?
3069        .function_declaration_data
3070        .signature)
3071}
3072
3073/// Query implementation of [crate::db::SemanticGroup::impl_function_generic_params].
3074pub fn impl_function_generic_params(
3075    db: &dyn SemanticGroup,
3076    impl_function_id: ImplFunctionId,
3077) -> Maybe<Vec<semantic::GenericParam>> {
3078    Ok(db.priv_impl_function_generic_params_data(impl_function_id)?.generic_params)
3079}
3080
3081/// Query implementation of [crate::db::SemanticGroup::priv_impl_function_generic_params_data].
3082pub fn priv_impl_function_generic_params_data(
3083    db: &dyn SemanticGroup,
3084    impl_function_id: ImplFunctionId,
3085) -> Maybe<GenericParamsData> {
3086    let module_file_id = impl_function_id.module_file_id(db);
3087    let mut diagnostics = SemanticDiagnostics::default();
3088    let impl_def_id = impl_function_id.impl_def_id(db);
3089    let data = db.priv_impl_definition_data(impl_def_id)?;
3090    let function_syntax = &data.function_asts[&impl_function_id];
3091    let declaration = function_syntax.declaration(db);
3092    let inference_id = InferenceId::LookupItemGenerics(LookupItemId::ImplItem(
3093        ImplItemId::Function(impl_function_id),
3094    ));
3095    let resolver_data = db.impl_def_resolver_data(impl_def_id)?;
3096    let mut resolver =
3097        Resolver::with_data(db, resolver_data.clone_with_inference_id(db, inference_id));
3098    let generic_params = semantic_generic_params(
3099        db,
3100        &mut diagnostics,
3101        &mut resolver,
3102        module_file_id,
3103        &declaration.generic_params(db),
3104    );
3105    let inference = &mut resolver.inference();
3106    inference.finalize(&mut diagnostics, function_syntax.stable_ptr(db).untyped());
3107
3108    let generic_params = inference.rewrite(generic_params).no_err();
3109    let resolver_data = Arc::new(resolver.data);
3110    Ok(GenericParamsData { generic_params, diagnostics: diagnostics.build(), resolver_data })
3111}
3112
3113/// Query implementation of [crate::db::SemanticGroup::impl_function_attributes].
3114pub fn impl_function_attributes(
3115    db: &dyn SemanticGroup,
3116    impl_function_id: ImplFunctionId,
3117) -> Maybe<Vec<Attribute>> {
3118    Ok(db
3119        .priv_impl_function_declaration_data(impl_function_id)?
3120        .function_declaration_data
3121        .attributes)
3122}
3123
3124/// Query implementation of [crate::db::SemanticGroup::impl_function_resolver_data].
3125pub fn impl_function_resolver_data(
3126    db: &dyn SemanticGroup,
3127    impl_function_id: ImplFunctionId,
3128) -> Maybe<Arc<ResolverData>> {
3129    Ok(db
3130        .priv_impl_function_declaration_data(impl_function_id)?
3131        .function_declaration_data
3132        .resolver_data)
3133}
3134
3135/// Query implementation of [crate::db::SemanticGroup::impl_function_declaration_inline_config].
3136pub fn impl_function_declaration_inline_config(
3137    db: &dyn SemanticGroup,
3138    impl_function_id: ImplFunctionId,
3139) -> Maybe<InlineConfiguration> {
3140    Ok(db
3141        .priv_impl_function_declaration_data(impl_function_id)?
3142        .function_declaration_data
3143        .inline_config)
3144}
3145
3146/// Query implementation of [SemanticGroup::impl_function_declaration_implicit_precedence].
3147pub fn impl_function_declaration_implicit_precedence(
3148    db: &dyn SemanticGroup,
3149    impl_function_id: ImplFunctionId,
3150) -> Maybe<ImplicitPrecedence> {
3151    Ok(db
3152        .priv_impl_function_declaration_data(impl_function_id)?
3153        .function_declaration_data
3154        .implicit_precedence)
3155}
3156
3157/// Query implementation of [crate::db::SemanticGroup::impl_function_declaration_implicits].
3158pub fn impl_function_declaration_implicits(
3159    db: &dyn SemanticGroup,
3160    impl_function_id: ImplFunctionId,
3161) -> Maybe<Vec<TypeId>> {
3162    Ok(db
3163        .priv_impl_function_declaration_data(impl_function_id)?
3164        .function_declaration_data
3165        .signature
3166        .implicits)
3167}
3168
3169/// Query implementation of [crate::db::SemanticGroup::impl_function_trait_function].
3170pub fn impl_function_trait_function(
3171    db: &dyn SemanticGroup,
3172    impl_function_id: ImplFunctionId,
3173) -> Maybe<TraitFunctionId> {
3174    db.priv_impl_function_declaration_data(impl_function_id)?.trait_function_id
3175}
3176
3177// --- Computation ---
3178
3179/// Query implementation of [crate::db::SemanticGroup::priv_impl_function_declaration_data].
3180pub fn priv_impl_function_declaration_data(
3181    db: &dyn SemanticGroup,
3182    impl_function_id: ImplFunctionId,
3183) -> Maybe<ImplFunctionDeclarationData> {
3184    let mut diagnostics = SemanticDiagnostics::default();
3185    let impl_def_id = impl_function_id.impl_def_id(db);
3186    let data = db.priv_impl_definition_data(impl_def_id)?;
3187    let function_syntax = &data.function_asts[&impl_function_id];
3188    let declaration = function_syntax.declaration(db);
3189
3190    let generic_params_data = db.priv_impl_function_generic_params_data(impl_function_id)?;
3191    let generic_params = generic_params_data.generic_params;
3192    let lookup_item_id = LookupItemId::ImplItem(ImplItemId::Function(impl_function_id));
3193    let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
3194    let mut resolver = Resolver::with_data(
3195        db,
3196        (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
3197    );
3198    diagnostics.extend(generic_params_data.diagnostics);
3199    resolver.set_feature_config(&impl_function_id, function_syntax, &mut diagnostics);
3200
3201    let mut environment = Environment::empty();
3202    let signature = semantic::Signature::from_ast(
3203        &mut diagnostics,
3204        db,
3205        &mut resolver,
3206        &declaration,
3207        FunctionTitleId::Impl(impl_function_id),
3208        &mut environment,
3209    );
3210
3211    let attributes = function_syntax.attributes(db).structurize(db);
3212    let (implicit_precedence, _) =
3213        get_implicit_precedence(db, &mut diagnostics, &mut resolver, &attributes);
3214
3215    let inference = &mut resolver.inference();
3216    // Check fully resolved.
3217    inference.finalize(&mut diagnostics, function_syntax.stable_ptr(db).untyped());
3218    let trait_function_id = validate_impl_function_signature(
3219        db,
3220        &mut diagnostics,
3221        inference,
3222        ValidateImplFunctionSignatureParams {
3223            impl_function_id,
3224            signature_syntax: &declaration.signature(db),
3225            signature: &signature,
3226            impl_function_syntax: function_syntax,
3227            impl_func_generics: &generic_params,
3228        },
3229    );
3230
3231    let inline_config = get_inline_config(db, &mut diagnostics, &attributes)?;
3232
3233    forbid_inline_always_with_impl_generic_param(&mut diagnostics, &generic_params, &inline_config);
3234
3235    let signature = inference.rewrite(signature).no_err();
3236    let generic_params = inference.rewrite(generic_params).no_err();
3237
3238    let resolver_data = Arc::new(resolver.data);
3239    Ok(ImplFunctionDeclarationData {
3240        function_declaration_data: FunctionDeclarationData {
3241            diagnostics: diagnostics.build(),
3242            signature,
3243            generic_params,
3244            environment,
3245            attributes,
3246            resolver_data,
3247            inline_config,
3248            implicit_precedence,
3249        },
3250        trait_function_id,
3251    })
3252}
3253
3254/// Struct for the parameters of [validate_impl_function_signature].
3255struct ValidateImplFunctionSignatureParams<'a> {
3256    /// The impl function to validate the signature of.
3257    impl_function_id: ImplFunctionId,
3258    /// The signature syntax.
3259    signature_syntax: &'a ast::FunctionSignature,
3260    // The semantic signature.
3261    signature: &'a semantic::Signature,
3262    /// The impl function syntax.
3263    impl_function_syntax: &'a ast::FunctionWithBody,
3264    /// The generic parameters of the impl function.
3265    impl_func_generics: &'a [GenericParam],
3266}
3267
3268/// Validates the impl function, and returns the matching trait function id.
3269fn validate_impl_function_signature(
3270    db: &dyn SemanticGroup,
3271    diagnostics: &mut SemanticDiagnostics,
3272    inference: &mut Inference<'_>,
3273    ValidateImplFunctionSignatureParams {
3274        impl_function_id,
3275        signature_syntax,
3276        signature,
3277        impl_function_syntax,
3278        impl_func_generics,
3279    }: ValidateImplFunctionSignatureParams<'_>,
3280) -> Maybe<TraitFunctionId> {
3281    let impl_def_id = impl_function_id.impl_def_id(db);
3282    let concrete_trait_id = db.impl_def_concrete_trait(impl_def_id)?;
3283    let trait_id = concrete_trait_id.trait_id(db);
3284    let function_name = impl_function_id.name(db);
3285    let trait_function_id =
3286        db.trait_function_by_name(trait_id, function_name.clone())?.ok_or_else(|| {
3287            diagnostics.report(
3288                impl_function_syntax.stable_ptr(db),
3289                ImplItemNotInTrait {
3290                    impl_def_id,
3291                    impl_item_name: function_name,
3292                    trait_id,
3293                    item_kind: "function".into(),
3294                },
3295            )
3296        })?;
3297    let concrete_trait_function =
3298        ConcreteTraitGenericFunctionId::new(db, concrete_trait_id, trait_function_id);
3299    let concrete_trait_signature = db.concrete_trait_function_signature(concrete_trait_function)?;
3300
3301    // Match generics of the function.
3302    // TODO(spapini): Compare the actual kinds and traits for the generic params.
3303
3304    let func_generics = db.concrete_trait_function_generic_params(concrete_trait_function)?;
3305    if impl_func_generics.len() != func_generics.len() {
3306        diagnostics.report(
3307            impl_function_syntax.declaration(db).name(db).stable_ptr(db),
3308            WrongNumberOfGenericParamsForImplFunction {
3309                expected: func_generics.len(),
3310                actual: impl_func_generics.len(),
3311            },
3312        );
3313        return Ok(trait_function_id);
3314    }
3315    let impl_def_substitution = db.impl_def_substitution(impl_def_id)?;
3316    let func_generics: Vec<GenericParam> = impl_def_substitution.substitute(db, func_generics)?;
3317
3318    let function_substitution =
3319        GenericSubstitution::new(&func_generics, &generic_params_to_args(impl_func_generics, db));
3320
3321    for (trait_generic_param, generic_param) in izip!(func_generics, impl_func_generics.iter()) {
3322        if let Some(name) = trait_generic_param.id().name(db) {
3323            if Some(name.clone()) != generic_param.id().name(db) {
3324                diagnostics.report(
3325                    generic_param.stable_ptr(db),
3326                    WrongParameterName {
3327                        impl_def_id,
3328                        impl_function_id,
3329                        trait_id,
3330                        expected_name: name,
3331                    },
3332                );
3333            }
3334        }
3335        match (generic_param, trait_generic_param) {
3336            (GenericParam::Type(_), GenericParam::Type(_)) => {}
3337            (GenericParam::Impl(generic_param), GenericParam::Impl(trait_generic_param))
3338            | (GenericParam::NegImpl(generic_param), GenericParam::NegImpl(trait_generic_param)) => {
3339                let rewritten_trait_param_trait =
3340                    function_substitution.substitute(db, trait_generic_param.concrete_trait)?;
3341                let rewritten_trait_param_type_constraints =
3342                    function_substitution.substitute(db, trait_generic_param.type_constraints)?;
3343                generic_param
3344                    .concrete_trait
3345                    .map(|actual_trait| {
3346                        rewritten_trait_param_trait
3347                            .map(|expected_trait| {
3348                                if actual_trait != expected_trait
3349                                    || generic_param.type_constraints
3350                                        != rewritten_trait_param_type_constraints
3351                                {
3352                                    diagnostics.report(
3353                                        generic_param.id.stable_ptr(db),
3354                                        WrongGenericParamTraitForImplFunction {
3355                                            impl_def_id,
3356                                            impl_function_id,
3357                                            trait_id,
3358                                            expected_trait,
3359                                            actual_trait,
3360                                        },
3361                                    );
3362                                }
3363                            })
3364                            .ok();
3365                    })
3366                    .ok();
3367            }
3368            (GenericParam::Const(generic_param), GenericParam::Const(trait_generic_param)) => {
3369                let expected_ty = function_substitution.substitute(db, trait_generic_param.ty)?;
3370                if generic_param.ty != expected_ty {
3371                    diagnostics.report(
3372                        generic_param.id.stable_ptr(db),
3373                        WrongParameterType {
3374                            impl_def_id,
3375                            impl_function_id,
3376                            trait_id,
3377                            expected_ty,
3378                            actual_ty: generic_param.ty,
3379                        },
3380                    );
3381                }
3382            }
3383            (generic_param, trait_generic_param) => {
3384                diagnostics.report(
3385                    generic_param.stable_ptr(db),
3386                    WrongGenericParamKindForImplFunction {
3387                        impl_def_id,
3388                        impl_function_id,
3389                        trait_id,
3390                        expected_kind: trait_generic_param.kind(),
3391                        actual_kind: generic_param.kind(),
3392                    },
3393                );
3394            }
3395        }
3396    }
3397
3398    let concrete_trait_signature =
3399        function_substitution.substitute(db, concrete_trait_signature)?;
3400
3401    if signature.params.len() != concrete_trait_signature.params.len() {
3402        diagnostics.report(
3403            signature_syntax.parameters(db).stable_ptr(db),
3404            WrongNumberOfParameters {
3405                impl_def_id,
3406                impl_function_id,
3407                trait_id,
3408                expected: concrete_trait_signature.params.len(),
3409                actual: signature.params.len(),
3410            },
3411        );
3412    }
3413    let concrete_trait_signature =
3414        impl_def_substitution.substitute(db, concrete_trait_signature)?;
3415    for (param, trait_param) in
3416        izip!(signature.params.iter(), concrete_trait_signature.params.iter())
3417    {
3418        let expected_ty = inference.rewrite(trait_param.ty).no_err();
3419        let actual_ty = inference.rewrite(param.ty).no_err();
3420
3421        if expected_ty != actual_ty && !expected_ty.is_missing(db) && !actual_ty.is_missing(db) {
3422            diagnostics.report(
3423                extract_matches!(
3424                    param.stable_ptr(db).lookup(db).type_clause(db),
3425                    OptionTypeClause::TypeClause
3426                )
3427                .ty(db)
3428                .stable_ptr(db),
3429                WrongParameterType {
3430                    impl_def_id,
3431                    impl_function_id,
3432                    trait_id,
3433                    expected_ty,
3434                    actual_ty,
3435                },
3436            );
3437        }
3438
3439        if trait_param.mutability != param.mutability {
3440            if trait_param.mutability == Mutability::Reference {
3441                diagnostics.report(
3442                    param.stable_ptr(db).lookup(db).modifiers(db).stable_ptr(db),
3443                    ParameterShouldBeReference { impl_def_id, impl_function_id, trait_id },
3444                );
3445            }
3446
3447            if param.mutability == Mutability::Reference {
3448                diagnostics.report(
3449                    param.stable_ptr(db).lookup(db).modifiers(db).stable_ptr(db),
3450                    ParameterShouldNotBeReference { impl_def_id, impl_function_id, trait_id },
3451                );
3452            }
3453        }
3454
3455        if trait_param.name != param.name {
3456            diagnostics.report(
3457                param.stable_ptr(db).lookup(db).name(db).stable_ptr(db),
3458                WrongParameterName {
3459                    impl_def_id,
3460                    impl_function_id,
3461                    trait_id,
3462                    expected_name: trait_param.name.clone(),
3463                },
3464            );
3465        }
3466    }
3467
3468    if !concrete_trait_signature.panicable && signature.panicable {
3469        diagnostics.report(
3470            signature_syntax.stable_ptr(db),
3471            PassPanicAsNopanic { impl_function_id, trait_id },
3472        );
3473    }
3474
3475    if concrete_trait_signature.is_const && !signature.is_const {
3476        diagnostics.report(
3477            signature_syntax.stable_ptr(db),
3478            PassConstAsNonConst { impl_function_id, trait_id },
3479        );
3480    }
3481
3482    let expected_ty = inference.rewrite(concrete_trait_signature.return_type).no_err();
3483    let actual_ty = inference.rewrite(signature.return_type).no_err();
3484
3485    if expected_ty != actual_ty && !expected_ty.is_missing(db) && !actual_ty.is_missing(db) {
3486        let location_ptr = match signature_syntax.ret_ty(db) {
3487            OptionReturnTypeClause::ReturnTypeClause(ret_ty) => ret_ty.ty(db).as_syntax_node(),
3488            OptionReturnTypeClause::Empty(_) => {
3489                impl_function_syntax.body(db).lbrace(db).as_syntax_node()
3490            }
3491        }
3492        .stable_ptr(db);
3493        diagnostics.report(
3494            location_ptr,
3495            WrongReturnTypeForImpl {
3496                impl_def_id,
3497                impl_function_id,
3498                trait_id,
3499                expected_ty,
3500                actual_ty,
3501            },
3502        );
3503    }
3504    Ok(trait_function_id)
3505}
3506
3507// === Impl Function Body ===
3508
3509// --- Selectors ---
3510
3511/// Query implementation of [crate::db::SemanticGroup::impl_function_body_diagnostics].
3512pub fn impl_function_body_diagnostics(
3513    db: &dyn SemanticGroup,
3514    impl_function_id: ImplFunctionId,
3515) -> Diagnostics<SemanticDiagnostic> {
3516    db.priv_impl_function_body_data(impl_function_id)
3517        .map(|data| data.diagnostics)
3518        .unwrap_or_default()
3519}
3520
3521/// Query implementation of [crate::db::SemanticGroup::impl_function_body].
3522pub fn impl_function_body(
3523    db: &dyn SemanticGroup,
3524    impl_function_id: ImplFunctionId,
3525) -> Maybe<Arc<FunctionBody>> {
3526    Ok(db.priv_impl_function_body_data(impl_function_id)?.body)
3527}
3528
3529/// Query implementation of [crate::db::SemanticGroup::impl_function_body_resolver_data].
3530pub fn impl_function_body_resolver_data(
3531    db: &dyn SemanticGroup,
3532    impl_function_id: ImplFunctionId,
3533) -> Maybe<Arc<ResolverData>> {
3534    Ok(db.priv_impl_function_body_data(impl_function_id)?.resolver_data)
3535}
3536
3537// --- Computation ---
3538
3539/// Query implementation of [crate::db::SemanticGroup::priv_impl_function_body_data].
3540pub fn priv_impl_function_body_data(
3541    db: &dyn SemanticGroup,
3542    impl_function_id: ImplFunctionId,
3543) -> Maybe<FunctionBodyData> {
3544    let mut diagnostics = SemanticDiagnostics::default();
3545    let impl_def_id = impl_function_id.impl_def_id(db);
3546    let data = db.priv_impl_definition_data(impl_def_id)?;
3547    let function_syntax = &data.function_asts[&impl_function_id];
3548    // Compute declaration semantic.
3549    let declaration = db.priv_impl_function_declaration_data(impl_function_id)?;
3550    let parent_resolver_data = declaration.function_declaration_data.resolver_data;
3551    let inference_id = InferenceId::LookupItemDefinition(LookupItemId::ImplItem(
3552        ImplItemId::Function(impl_function_id),
3553    ));
3554    let resolver =
3555        Resolver::with_data(db, (*parent_resolver_data).clone_with_inference_id(db, inference_id));
3556    let environment: Environment = declaration.function_declaration_data.environment;
3557
3558    let function_id = (|| {
3559        let trait_function_id = db.impl_function_trait_function(impl_function_id)?;
3560        let generic_parameters = db.impl_def_generic_params(impl_def_id)?;
3561
3562        let generic_function = GenericFunctionId::Impl(ImplGenericFunctionId {
3563            impl_id: ImplLongId::Concrete(
3564                ConcreteImplLongId {
3565                    impl_def_id,
3566                    generic_args: generic_params_to_args(&generic_parameters, db),
3567                }
3568                .intern(db),
3569            )
3570            .intern(db),
3571            function: trait_function_id,
3572        });
3573
3574        Ok(FunctionLongId::from_generic(db, generic_function)?.intern(db))
3575    })();
3576    // Compute body semantic expr.
3577    let mut ctx = ComputationContext::new(
3578        db,
3579        &mut diagnostics,
3580        resolver,
3581        Some(&declaration.function_declaration_data.signature),
3582        environment,
3583        ContextFunction::Function(function_id),
3584    );
3585    let function_body = function_syntax.body(db);
3586    let return_type = declaration.function_declaration_data.signature.return_type;
3587    let body_expr = compute_root_expr(&mut ctx, &function_body, return_type)?;
3588    let ComputationContext { arenas: Arenas { exprs, patterns, statements }, resolver, .. } = ctx;
3589
3590    let expr_lookup: UnorderedHashMap<_, _> =
3591        exprs.iter().map(|(expr_id, expr)| (expr.stable_ptr(), expr_id)).collect();
3592    let pattern_lookup: UnorderedHashMap<_, _> =
3593        patterns.iter().map(|(pattern_id, pattern)| (pattern.stable_ptr(), pattern_id)).collect();
3594    let resolver_data = Arc::new(resolver.data);
3595    Ok(FunctionBodyData {
3596        diagnostics: diagnostics.build(),
3597        expr_lookup,
3598        pattern_lookup,
3599        resolver_data,
3600        body: Arc::new(FunctionBody { arenas: Arenas { exprs, patterns, statements }, body_expr }),
3601    })
3602}
3603
3604pub fn priv_impl_is_fully_concrete(db: &dyn SemanticGroup, impl_id: ImplId) -> bool {
3605    impl_id.lookup_intern(db).is_fully_concrete(db)
3606}
3607
3608pub fn priv_impl_is_var_free(db: &dyn SemanticGroup, impl_id: ImplId) -> bool {
3609    impl_id.lookup_intern(db).is_var_free(db)
3610}