cairo_lang_semantic/items/
imp.rs

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