cairo_lang_semantic/items/
trt.rs

1use std::fmt::Write;
2use std::sync::Arc;
3
4use cairo_lang_debug::DebugWithDb;
5use cairo_lang_defs::db::DefsGroup;
6use cairo_lang_defs::ids::{
7    FunctionTitleId, GenericParamId, GenericParamLongId, LanguageElementId, LookupItemId,
8    ModuleItemId, NamedLanguageElementId, NamedLanguageElementLongId, TopLevelLanguageElementId,
9    TraitConstantId, TraitConstantLongId, TraitFunctionId, TraitFunctionLongId, TraitId,
10    TraitImplId, TraitImplLongId, TraitItemId, TraitTypeId, TraitTypeLongId, UseId,
11};
12use cairo_lang_diagnostics::{Diagnostics, DiagnosticsBuilder, Maybe, MaybeAsRef};
13use cairo_lang_filesystem::ids::SmolStrId;
14use cairo_lang_proc_macros::{DebugWithDb, SemanticObject};
15use cairo_lang_syntax as syntax;
16use cairo_lang_syntax::attribute::structured::{Attribute, AttributeListStructurize};
17use cairo_lang_syntax::node::helpers::OptionWrappedGenericParamListHelper;
18use cairo_lang_syntax::node::{Terminal, TypedStablePtr, TypedSyntaxNode, ast};
19use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
20use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
21use cairo_lang_utils::unordered_hash_map::UnorderedHashMap;
22use cairo_lang_utils::{Intern, define_short_id};
23use salsa::Database;
24
25use super::TraitOrImplContext;
26use super::feature_kind::FeatureKind;
27use super::function_with_body::{FunctionBodyData, get_implicit_precedence, get_inline_config};
28use super::functions::{
29    FunctionDeclarationData, GenericFunctionId, ImplGenericFunctionId, ImplicitPrecedence,
30    InlineConfiguration,
31};
32use super::generics::{
33    GenericParamsData, fmt_generic_args, generic_params_to_args, semantic_generic_params,
34    semantic_generic_params_ex,
35};
36use super::imp::{GenericsHeadFilter, ImplLongId, TraitFilter};
37use crate::db::get_resolver_data_options;
38use crate::diagnostic::SemanticDiagnosticKind::{self, *};
39use crate::diagnostic::{NotFoundItemType, SemanticDiagnostics, SemanticDiagnosticsBuilder};
40use crate::expr::compute::{ComputationContext, ContextFunction, Environment, compute_root_expr};
41use crate::expr::fmt::CountingWriter;
42use crate::expr::inference::InferenceId;
43use crate::expr::inference::canonic::ResultNoErrEx;
44use crate::items::feature_kind::HasFeatureKind;
45use crate::resolve::{ResolvedConcreteItem, Resolver, ResolverData};
46use crate::substitution::{GenericSubstitution, SemanticRewriter};
47use crate::types::resolve_type;
48use crate::{
49    FunctionBody, FunctionLongId, GenericArgumentId, GenericParam, Mutability, SemanticDiagnostic,
50    TypeId, semantic, semantic_object_for_id,
51};
52
53#[cfg(test)]
54#[path = "trt_test.rs"]
55mod test;
56
57#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
58pub struct ConcreteTraitLongId<'db> {
59    pub trait_id: TraitId<'db>,
60    pub generic_args: Vec<GenericArgumentId<'db>>,
61}
62impl<'db> DebugWithDb<'db> for ConcreteTraitLongId<'db> {
63    type Db = dyn Database;
64
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
66        let mut f = CountingWriter::new(f);
67        write!(f, "{}", self.trait_id.full_path(db))?;
68        fmt_generic_args(&self.generic_args, &mut f, db)
69    }
70}
71
72define_short_id!(ConcreteTraitId, ConcreteTraitLongId<'db>);
73semantic_object_for_id!(ConcreteTraitId, ConcreteTraitLongId<'a>);
74impl<'db> ConcreteTraitId<'db> {
75    pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
76        self.long(db).trait_id
77    }
78    pub fn generic_args(&self, db: &'db dyn Database) -> &'db [GenericArgumentId<'db>] {
79        &self.long(db).generic_args
80    }
81    pub fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
82        self.trait_id(db).name(db)
83    }
84    pub fn full_path(&self, db: &dyn Database) -> String {
85        format!("{:?}", self.debug(db))
86    }
87    pub fn filter(&self, db: &'db dyn Database) -> TraitFilter<'db> {
88        let generics_filter = match self.generic_args(db).first() {
89            Some(first_generic) => match first_generic.head(db) {
90                Some(head) => GenericsHeadFilter::FirstGenericFilter(head),
91                None => GenericsHeadFilter::NoFilter,
92            },
93            None => GenericsHeadFilter::NoGenerics,
94        };
95        TraitFilter { trait_id: self.trait_id(db), generics_filter }
96    }
97
98    /// Returns true if the `trait` does not depend on any generics.
99    pub fn is_fully_concrete(&self, db: &dyn Database) -> bool {
100        self.long(db)
101            .generic_args
102            .iter()
103            .all(|generic_argument_id| generic_argument_id.is_fully_concrete(db))
104    }
105    /// Returns true if the `trait` does not depend on impl or type variables.
106    pub fn is_var_free(&self, db: &dyn Database) -> bool {
107        self.long(db)
108            .generic_args
109            .iter()
110            .all(|generic_argument_id| generic_argument_id.is_var_free(db))
111    }
112}
113
114/// The ID of a generic function in a concrete trait.
115#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
116#[debug_db(dyn Database)]
117pub struct ConcreteTraitGenericFunctionLongId<'db> {
118    // Note the members are private to prevent direct call to the constructor.
119    concrete_trait: ConcreteTraitId<'db>,
120    trait_function: TraitFunctionId<'db>,
121}
122impl<'db> ConcreteTraitGenericFunctionLongId<'db> {
123    pub fn new(
124        db: &dyn Database,
125        concrete_trait: ConcreteTraitId<'db>,
126        trait_function: TraitFunctionId<'db>,
127    ) -> Self {
128        assert_eq!(
129            concrete_trait.trait_id(db),
130            trait_function.trait_id(db),
131            "Concrete trait and trait function must belong to the same generic trait."
132        );
133        Self { concrete_trait, trait_function }
134    }
135}
136define_short_id!(ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId<'db>);
137semantic_object_for_id!(ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId<'a>);
138impl<'db> ConcreteTraitGenericFunctionId<'db> {
139    pub fn new_from_data(
140        db: &'db dyn Database,
141        concrete_trait: ConcreteTraitId<'db>,
142        trait_function: TraitFunctionId<'db>,
143    ) -> Self {
144        ConcreteTraitGenericFunctionLongId::new(db, concrete_trait, trait_function).intern(db)
145    }
146
147    pub fn trait_function(&self, db: &'db dyn Database) -> TraitFunctionId<'db> {
148        self.long(db).trait_function
149    }
150
151    pub fn concrete_trait(&self, db: &'db dyn Database) -> ConcreteTraitId<'db> {
152        self.long(db).concrete_trait
153    }
154}
155
156/// The ID of a type item in a concrete trait.
157#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
158#[debug_db(dyn Database)]
159pub struct ConcreteTraitTypeLongId<'db> {
160    // Note the members are private to prevent direct call to the constructor.
161    concrete_trait: ConcreteTraitId<'db>,
162    trait_type: TraitTypeId<'db>,
163}
164impl<'db> ConcreteTraitTypeLongId<'db> {
165    pub fn new(
166        db: &dyn Database,
167        concrete_trait: ConcreteTraitId<'db>,
168        trait_type: TraitTypeId<'db>,
169    ) -> Self {
170        assert_eq!(
171            concrete_trait.trait_id(db),
172            trait_type.trait_id(db),
173            "Concrete trait and trait type must belong to the same generic trait."
174        );
175        Self { concrete_trait, trait_type }
176    }
177}
178define_short_id!(ConcreteTraitTypeId, ConcreteTraitTypeLongId<'db>);
179semantic_object_for_id!(ConcreteTraitTypeId, ConcreteTraitTypeLongId<'a>);
180impl<'db> ConcreteTraitTypeId<'db> {
181    pub fn new_from_data(
182        db: &'db dyn Database,
183        concrete_trait: ConcreteTraitId<'db>,
184        trait_type: TraitTypeId<'db>,
185    ) -> Self {
186        ConcreteTraitTypeLongId::new(db, concrete_trait, trait_type).intern(db)
187    }
188
189    pub fn trait_type(&self, db: &'db dyn Database) -> TraitTypeId<'db> {
190        self.long(db).trait_type
191    }
192
193    pub fn concrete_trait(&self, db: &'db dyn Database) -> ConcreteTraitId<'db> {
194        self.long(db).concrete_trait
195    }
196}
197
198/// The ID of a constant item in a concrete trait.
199#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
200#[debug_db(dyn Database)]
201pub struct ConcreteTraitConstantLongId<'db> {
202    // Note the members are private to prevent direct call to the constructor.
203    concrete_trait: ConcreteTraitId<'db>,
204    trait_constant: TraitConstantId<'db>,
205}
206impl<'db> ConcreteTraitConstantLongId<'db> {
207    pub fn new(
208        db: &'db dyn Database,
209        concrete_trait: ConcreteTraitId<'db>,
210        trait_constant: TraitConstantId<'db>,
211    ) -> Self {
212        assert_eq!(
213            concrete_trait.trait_id(db),
214            trait_constant.trait_id(db),
215            "Concrete trait and trait constant must belong to the same generic trait."
216        );
217        Self { concrete_trait, trait_constant }
218    }
219}
220define_short_id!(ConcreteTraitConstantId, ConcreteTraitConstantLongId<'db>);
221semantic_object_for_id!(ConcreteTraitConstantId, ConcreteTraitConstantLongId<'a>);
222impl<'db> ConcreteTraitConstantId<'db> {
223    pub fn new_from_data(
224        db: &'db dyn Database,
225        concrete_trait: ConcreteTraitId<'db>,
226        trait_constant: TraitConstantId<'db>,
227    ) -> Self {
228        ConcreteTraitConstantLongId::new(db, concrete_trait, trait_constant).intern(db)
229    }
230
231    pub fn trait_constant(&self, db: &'db dyn Database) -> TraitConstantId<'db> {
232        self.long(db).trait_constant
233    }
234
235    pub fn concrete_trait(&self, db: &'db dyn Database) -> ConcreteTraitId<'db> {
236        self.long(db).concrete_trait
237    }
238}
239
240/// The ID of a impl item in a concrete trait.
241#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
242#[debug_db(dyn Database)]
243pub struct ConcreteTraitImplLongId<'db> {
244    // Note the members are private to prevent direct call to the constructor.
245    concrete_trait: ConcreteTraitId<'db>,
246    trait_impl: TraitImplId<'db>,
247}
248impl<'db> ConcreteTraitImplLongId<'db> {
249    pub fn new_from_data(
250        db: &dyn Database,
251        concrete_trait: ConcreteTraitId<'db>,
252        trait_impl: TraitImplId<'db>,
253    ) -> Self {
254        assert_eq!(
255            concrete_trait.trait_id(db),
256            trait_impl.trait_id(db),
257            "Concrete trait and trait impl must belong to the same generic trait."
258        );
259        Self { concrete_trait, trait_impl }
260    }
261}
262define_short_id!(ConcreteTraitImplId, ConcreteTraitImplLongId<'db>);
263semantic_object_for_id!(ConcreteTraitImplId, ConcreteTraitImplLongId<'a>);
264impl<'db> ConcreteTraitImplId<'db> {
265    pub fn new_from_data(
266        db: &'db dyn Database,
267        concrete_trait: ConcreteTraitId<'db>,
268        trait_impl: TraitImplId<'db>,
269    ) -> Self {
270        ConcreteTraitImplLongId::new_from_data(db, concrete_trait, trait_impl).intern(db)
271    }
272
273    pub fn trait_impl(&self, db: &'db dyn Database) -> TraitImplId<'db> {
274        self.long(db).trait_impl
275    }
276
277    pub fn concrete_trait(&self, db: &'db dyn Database) -> ConcreteTraitId<'db> {
278        self.long(db).concrete_trait
279    }
280}
281
282// === Trait Declaration ===
283
284#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
285#[debug_db(dyn Database)]
286struct TraitDeclarationData<'db> {
287    diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
288    attributes: Vec<Attribute<'db>>,
289    resolver_data: Arc<ResolverData<'db>>,
290}
291
292/// Implementation of [PrivTraitSemantic::trait_generic_params_data].
293fn trait_generic_params_data<'db>(
294    db: &'db dyn Database,
295    trait_id: TraitId<'db>,
296    in_cycle: bool,
297) -> Maybe<GenericParamsData<'db>> {
298    let module_id = trait_id.module_id(db);
299    let mut diagnostics = SemanticDiagnostics::default();
300    let trait_ast = db.module_trait_by_id(trait_id)?;
301
302    // Generic params.
303    let inference_id =
304        InferenceId::LookupItemGenerics(LookupItemId::ModuleItem(ModuleItemId::Trait(trait_id)));
305    let mut resolver = Resolver::new(db, module_id, inference_id);
306    resolver.set_feature_config(&trait_id, &trait_ast, &mut diagnostics);
307    let generic_params = semantic_generic_params_ex(
308        db,
309        &mut diagnostics,
310        &mut resolver,
311        module_id,
312        &trait_ast.generic_params(db),
313        in_cycle,
314    );
315
316    let inference = &mut resolver.inference();
317    inference.finalize(&mut diagnostics, trait_ast.stable_ptr(db).untyped());
318
319    let generic_params = inference.rewrite(generic_params).no_err();
320    let resolver_data = Arc::new(resolver.data);
321    Ok(GenericParamsData { diagnostics: diagnostics.build(), generic_params, resolver_data })
322}
323
324/// Query implementation of [TraitSemantic::trait_generic_params_data].
325#[salsa::tracked(cycle_result=trait_generic_params_data_cycle, returns(ref))]
326fn trait_generic_params_data_tracked<'db>(
327    db: &'db dyn Database,
328    trait_id: TraitId<'db>,
329    in_cycle: bool,
330) -> Maybe<GenericParamsData<'db>> {
331    trait_generic_params_data(db, trait_id, in_cycle)
332}
333
334/// Cycle handling for [PrivTraitSemantic::trait_generic_params_data].
335fn trait_generic_params_data_cycle<'db>(
336    db: &'db dyn Database,
337    trait_id: TraitId<'db>,
338    _in_cycle: bool,
339) -> Maybe<GenericParamsData<'db>> {
340    // Forwarding cycle handling to `priv_generic_param_data` handler.
341    trait_generic_params_data(db, trait_id, true)
342}
343
344/// Query implementation of [TraitSemantic::trait_generic_params_ids].
345#[salsa::tracked(returns(ref))]
346fn trait_generic_params_ids<'db>(
347    db: &'db dyn Database,
348    trait_id: TraitId<'db>,
349) -> Maybe<Vec<GenericParamId<'db>>> {
350    let module_id = trait_id.module_id(db);
351    let trait_ast = db.module_trait_by_id(trait_id)?;
352
353    let generic_params = &trait_ast.generic_params(db);
354
355    let syntax_db = db;
356    Ok(match generic_params {
357        syntax::node::ast::OptionWrappedGenericParamList::Empty(_) => vec![],
358        syntax::node::ast::OptionWrappedGenericParamList::WrappedGenericParamList(syntax) => syntax
359            .generic_params(syntax_db)
360            .elements(syntax_db)
361            .map(|param_syntax| {
362                GenericParamLongId(module_id, param_syntax.stable_ptr(syntax_db)).intern(db)
363            })
364            .collect(),
365    })
366}
367
368/// Query implementation of [TraitSemantic::priv_trait_declaration_data].
369#[salsa::tracked(returns(ref))]
370fn priv_trait_declaration_data<'db>(
371    db: &'db dyn Database,
372    trait_id: TraitId<'db>,
373) -> Maybe<TraitDeclarationData<'db>> {
374    let mut diagnostics = SemanticDiagnostics::default();
375    // TODO(spapini): when code changes in a file, all the AST items change (as they contain a path
376    // to the green root that changes. Once ASTs are rooted on items, use a selector that picks only
377    // the item instead of all the module data.
378    let trait_ast = db.module_trait_by_id(trait_id)?;
379
380    // Generic params.
381    let generic_params_data = db.trait_generic_params_data(trait_id, false)?;
382    let inference_id =
383        InferenceId::LookupItemDeclaration(LookupItemId::ModuleItem(ModuleItemId::Trait(trait_id)));
384    let mut resolver = Resolver::with_data(
385        db,
386        (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
387    );
388    diagnostics.extend(generic_params_data.diagnostics.clone());
389
390    let attributes = trait_ast.attributes(db).structurize(db);
391
392    // Check fully resolved.
393    let inference = &mut resolver.inference();
394    inference.finalize(&mut diagnostics, trait_ast.stable_ptr(db).untyped());
395
396    let mut resolver_data = resolver.data;
397    resolver_data.trait_or_impl_ctx = TraitOrImplContext::Trait(trait_id);
398    Ok(TraitDeclarationData {
399        diagnostics: diagnostics.build(),
400        attributes,
401        resolver_data: Arc::new(resolver_data),
402    })
403}
404
405// === Trait Definition ===
406
407#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
408#[debug_db(dyn Database)]
409struct TraitDefinitionData<'db> {
410    /// The diagnostics here are "flat" - that is, only the diagnostics found on the trait level
411    /// itself, and don't include the diagnostics of its items. The reason it's this way is that
412    /// computing the items' diagnostics require a query about their trait, forming a cycle of
413    /// queries. Adding the items' diagnostics only after the whole computation breaks this cycle.
414    diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
415
416    // AST maps.
417    function_asts: OrderedHashMap<TraitFunctionId<'db>, ast::TraitItemFunction<'db>>,
418    item_type_asts: OrderedHashMap<TraitTypeId<'db>, ast::TraitItemType<'db>>,
419    item_constant_asts: OrderedHashMap<TraitConstantId<'db>, ast::TraitItemConstant<'db>>,
420    item_impl_asts: OrderedHashMap<TraitImplId<'db>, ast::TraitItemImpl<'db>>,
421
422    /// Mapping of item names to their IDs. All the IDs should appear in one of the AST maps above.
423    item_id_by_name: OrderedHashMap<SmolStrId<'db>, TraitItemInfo<'db>>,
424}
425
426/// Stores metadata for a trait item, including its ID and feature kind.
427#[derive(Clone, Debug, PartialEq, Eq, salsa::Update)]
428pub struct TraitItemInfo<'db> {
429    /// The unique identifier of the trait item.
430    pub id: TraitItemId<'db>,
431    /// The feature kind associated with this trait item.
432    pub feature_kind: FeatureKind<'db>,
433}
434
435impl<'db> HasFeatureKind<'db> for TraitItemInfo<'db> {
436    /// Returns the feature kind of this trait item.
437    fn feature_kind(&self) -> &FeatureKind<'db> {
438        &self.feature_kind
439    }
440}
441
442// --- Selectors ---
443
444/// Implementation of [TraitSemantic::trait_semantic_definition_diagnostics].
445fn trait_semantic_definition_diagnostics<'db>(
446    db: &'db dyn Database,
447    trait_id: TraitId<'db>,
448) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
449    let mut diagnostics = DiagnosticsBuilder::default();
450
451    let Ok(data) = db.priv_trait_definition_data(trait_id) else {
452        return Diagnostics::default();
453    };
454
455    // The diagnostics from `priv_trait_definition_data` are only the diagnostics from the trait
456    // level. They should be enriched with the items' diagnostics.
457    diagnostics.extend(data.diagnostics.clone());
458    for trait_function_id in data.function_asts.keys() {
459        diagnostics.extend(db.trait_function_declaration_diagnostics(*trait_function_id));
460        diagnostics.extend(db.trait_function_body_diagnostics(*trait_function_id));
461    }
462    for trait_type_id in data.item_type_asts.keys() {
463        diagnostics.extend(db.trait_type_diagnostics(*trait_type_id));
464    }
465    for trait_constant in data.item_constant_asts.keys() {
466        diagnostics.extend(db.trait_constant_diagnostics(*trait_constant));
467    }
468    for trait_impl in data.item_impl_asts.keys() {
469        diagnostics.extend(db.trait_impl_diagnostics(*trait_impl));
470    }
471
472    diagnostics.build()
473}
474
475/// Query implementation of [TraitSemantic::trait_semantic_definition_diagnostics].
476#[salsa::tracked]
477fn trait_semantic_definition_diagnostics_tracked<'db>(
478    db: &'db dyn Database,
479    trait_id: TraitId<'db>,
480) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
481    trait_semantic_definition_diagnostics(db, trait_id)
482}
483
484/// Query implementation of [TraitSemantic::trait_required_item_names].
485#[salsa::tracked(returns(ref))]
486fn trait_required_item_names<'db>(
487    db: &'db dyn Database,
488    trait_id: TraitId<'db>,
489) -> Maybe<OrderedHashSet<SmolStrId<'db>>> {
490    let mut required_items = OrderedHashSet::<_>::default();
491    for (item_name, item_id) in db.priv_trait_definition_data(trait_id)?.item_id_by_name.iter() {
492        if match item_id.id {
493            TraitItemId::Function(id) => {
494                let body = id.stable_ptr(db).lookup(db).body(db);
495                matches!(body, ast::MaybeTraitFunctionBody::None(_))
496            }
497            TraitItemId::Type(_) | TraitItemId::Constant(_) => true,
498            TraitItemId::Impl(_) => false,
499        } {
500            required_items.insert(*item_name);
501        }
502    }
503    Ok(required_items)
504}
505
506/// Query implementation of [TraitSemantic::trait_all_used_uses].
507#[salsa::tracked(returns(ref))]
508fn trait_all_used_uses<'db>(
509    db: &'db dyn Database,
510    trait_id: TraitId<'db>,
511) -> Maybe<OrderedHashSet<UseId<'db>>> {
512    let mut all_used_uses = db.trait_resolver_data(trait_id)?.used_uses.clone();
513    let data = db.priv_trait_definition_data(trait_id)?;
514    for item in data.item_id_by_name.values() {
515        for resolver_data in get_resolver_data_options(LookupItemId::TraitItem(item.id), db) {
516            all_used_uses.extend(resolver_data.used_uses.iter().cloned());
517        }
518    }
519    Ok(all_used_uses)
520}
521
522/// Query implementation of [TraitSemantic::trait_functions].
523#[salsa::tracked(returns(ref))]
524fn trait_functions<'db>(
525    db: &'db dyn Database,
526    trait_id: TraitId<'db>,
527) -> Maybe<OrderedHashMap<SmolStrId<'db>, TraitFunctionId<'db>>> {
528    Ok(db
529        .priv_trait_definition_data(trait_id)?
530        .function_asts
531        .keys()
532        .map(|function_id| {
533            let function_long_id = function_id.long(db);
534            (function_long_id.name(db), *function_id)
535        })
536        .collect())
537}
538
539/// Query implementation of [TraitSemantic::trait_types].
540#[salsa::tracked(returns(ref))]
541fn trait_types<'db>(
542    db: &'db dyn Database,
543    trait_id: TraitId<'db>,
544) -> Maybe<OrderedHashMap<SmolStrId<'db>, TraitTypeId<'db>>> {
545    Ok(db
546        .priv_trait_definition_data(trait_id)?
547        .item_type_asts
548        .keys()
549        .map(|type_id| {
550            let type_long_id = type_id.long(db);
551            (type_long_id.name(db), *type_id)
552        })
553        .collect())
554}
555
556/// Query implementation of [TraitSemantic::trait_constants].
557#[salsa::tracked(returns(ref))]
558fn trait_constants<'db>(
559    db: &'db dyn Database,
560    trait_id: TraitId<'db>,
561) -> Maybe<OrderedHashMap<SmolStrId<'db>, TraitConstantId<'db>>> {
562    Ok(db
563        .priv_trait_definition_data(trait_id)?
564        .item_constant_asts
565        .keys()
566        .map(|constant_id| {
567            let constant_long_id = constant_id.long(db);
568            (constant_long_id.name(db), *constant_id)
569        })
570        .collect())
571}
572
573/// Query implementation of [TraitSemantic::trait_impls].
574#[salsa::tracked(returns(ref))]
575fn trait_impls<'db>(
576    db: &'db dyn Database,
577    trait_id: TraitId<'db>,
578) -> Maybe<OrderedHashMap<SmolStrId<'db>, TraitImplId<'db>>> {
579    Ok(db
580        .priv_trait_definition_data(trait_id)?
581        .item_impl_asts
582        .keys()
583        .map(|impl_id| {
584            let impl_long_id = impl_id.long(db);
585            (impl_long_id.name(db), *impl_id)
586        })
587        .collect())
588}
589
590// --- Computation ---
591
592/// Query implementation of [PrivTraitSemantic::priv_trait_definition_data].
593#[salsa::tracked(returns(ref))]
594fn priv_trait_definition_data<'db>(
595    db: &'db dyn Database,
596    trait_id: TraitId<'db>,
597) -> Maybe<TraitDefinitionData<'db>> {
598    let module_id = trait_id.module_id(db);
599    let mut diagnostics = SemanticDiagnostics::default();
600
601    // TODO(spapini): when code changes in a file, all the AST items change (as they contain a path
602    // to the green root that changes. Once ASTs are rooted on items, use a selector that picks only
603    // the item instead of all the module data.
604    let trait_ast = db.module_trait_by_id(trait_id)?;
605
606    let mut function_asts = OrderedHashMap::default();
607    let mut item_type_asts = OrderedHashMap::default();
608    let mut item_constant_asts = OrderedHashMap::default();
609    let mut item_impl_asts = OrderedHashMap::default();
610    let mut item_id_by_name: OrderedHashMap<SmolStrId<'db>, TraitItemInfo<'db>> =
611        OrderedHashMap::default();
612
613    if let ast::MaybeTraitBody::Some(body) = trait_ast.body(db) {
614        for item in body.items(db).elements(db) {
615            match item {
616                ast::TraitItem::Function(func) => {
617                    let trait_func_id =
618                        TraitFunctionLongId(module_id, func.stable_ptr(db)).intern(db);
619                    let name_node = func.declaration(db).name(db);
620                    let name = name_node.text(db);
621                    let attributes = func.attributes(db);
622                    let feature_kind = FeatureKind::from_ast(db, &mut diagnostics, &attributes);
623                    if item_id_by_name
624                        .insert(
625                            name,
626                            TraitItemInfo {
627                                id: TraitItemId::Function(trait_func_id),
628                                feature_kind,
629                            },
630                        )
631                        .is_some()
632                    {
633                        diagnostics.report(
634                            name_node.stable_ptr(db),
635                            SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
636                        );
637                    }
638                    function_asts.insert(trait_func_id, func);
639                }
640                ast::TraitItem::Type(ty) => {
641                    let trait_type_id = TraitTypeLongId(module_id, ty.stable_ptr(db)).intern(db);
642                    let name_node = ty.name(db);
643                    let name = name_node.text(db);
644                    let attributes = ty.attributes(db);
645                    let feature_kind = FeatureKind::from_ast(db, &mut diagnostics, &attributes);
646                    if item_id_by_name
647                        .insert(
648                            name,
649                            TraitItemInfo { id: TraitItemId::Type(trait_type_id), feature_kind },
650                        )
651                        .is_some()
652                    {
653                        diagnostics.report(
654                            name_node.stable_ptr(db),
655                            SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
656                        );
657                    }
658                    item_type_asts.insert(trait_type_id, ty);
659                }
660                ast::TraitItem::Constant(constant) => {
661                    let trait_constant =
662                        TraitConstantLongId(module_id, constant.stable_ptr(db)).intern(db);
663
664                    let name_node = constant.name(db);
665                    let name = name_node.text(db);
666                    let attributes = constant.attributes(db);
667                    let feature_kind = FeatureKind::from_ast(db, &mut diagnostics, &attributes);
668                    if item_id_by_name
669                        .insert(
670                            name,
671                            TraitItemInfo {
672                                id: TraitItemId::Constant(trait_constant),
673                                feature_kind,
674                            },
675                        )
676                        .is_some()
677                    {
678                        diagnostics.report(
679                            name_node.stable_ptr(db),
680                            SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
681                        );
682                    }
683                    item_constant_asts.insert(trait_constant, constant);
684                }
685                ast::TraitItem::Impl(imp) => {
686                    let trait_impl = TraitImplLongId(module_id, imp.stable_ptr(db)).intern(db);
687
688                    let name_node = imp.name(db);
689                    let name = name_node.text(db);
690                    let attributes = imp.attributes(db);
691                    let feature_kind = FeatureKind::from_ast(db, &mut diagnostics, &attributes);
692                    if item_id_by_name
693                        .insert(
694                            name,
695                            TraitItemInfo { id: TraitItemId::Impl(trait_impl), feature_kind },
696                        )
697                        .is_some()
698                    {
699                        diagnostics.report(
700                            name_node.stable_ptr(db),
701                            SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
702                        );
703                    }
704                    item_impl_asts.insert(trait_impl, imp);
705                }
706                ast::TraitItem::Missing(_) => {}
707            }
708        }
709    }
710
711    Ok(TraitDefinitionData {
712        diagnostics: diagnostics.build(),
713        function_asts,
714        item_type_asts,
715        item_constant_asts,
716        item_impl_asts,
717        item_id_by_name,
718    })
719}
720
721// === Trait item type ===
722
723#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
724#[debug_db(dyn Database)]
725struct TraitItemTypeData<'db> {
726    pub diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
727    pub attributes: Vec<Attribute<'db>>,
728    pub resolver_data: Arc<ResolverData<'db>>,
729}
730
731/// Query implementation of [PrivTraitSemantic::priv_trait_type_generic_params_data].
732#[salsa::tracked(returns(ref))]
733fn priv_trait_type_generic_params_data<'db>(
734    db: &'db dyn Database,
735    trait_type_id: TraitTypeId<'db>,
736) -> Maybe<GenericParamsData<'db>> {
737    let module_id = trait_type_id.module_id(db);
738    let mut diagnostics = SemanticDiagnostics::default();
739    let trait_id = trait_type_id.trait_id(db);
740    let data = db.priv_trait_definition_data(trait_id)?;
741    let trait_type_ast = &data.item_type_asts[&trait_type_id];
742    let inference_id =
743        InferenceId::LookupItemGenerics(LookupItemId::TraitItem(TraitItemId::Type(trait_type_id)));
744    let parent_resolver_data = db.trait_resolver_data(trait_id)?;
745    let mut resolver =
746        Resolver::with_data(db, parent_resolver_data.clone_with_inference_id(db, inference_id));
747    for trait_generic_param in db.trait_generic_params(trait_id)? {
748        resolver.add_generic_param(trait_generic_param.id());
749    }
750    let generic_params_node = trait_type_ast.generic_params(db);
751    let type_generic_params = semantic_generic_params(
752        db,
753        &mut diagnostics,
754        &mut resolver,
755        module_id,
756        &generic_params_node,
757    );
758    let type_generic_params = resolver.inference().rewrite(type_generic_params).no_err();
759
760    // TODO(yuval): support generics in impls (including validation), then remove this.
761    // Generic parameters are not yet supported, make sure there are none.
762    if !generic_params_node.is_empty(db) {
763        diagnostics.report(
764            generic_params_node.stable_ptr(db),
765            GenericsNotSupportedInItem { scope: "Trait".into(), item_kind: "type".into() },
766        );
767    }
768
769    let resolver_data = Arc::new(resolver.data);
770    Ok(GenericParamsData {
771        diagnostics: diagnostics.build(),
772        generic_params: type_generic_params,
773        resolver_data,
774    })
775}
776
777/// Query implementation of [PrivTraitSemantic::priv_trait_type_data].
778#[salsa::tracked(returns(ref))]
779fn priv_trait_type_data<'db>(
780    db: &'db dyn Database,
781    trait_type_id: TraitTypeId<'db>,
782) -> Maybe<TraitItemTypeData<'db>> {
783    let mut diagnostics = SemanticDiagnostics::default();
784    let trait_id = trait_type_id.trait_id(db);
785    let data = db.priv_trait_definition_data(trait_id)?;
786    let type_syntax = &data.item_type_asts[&trait_type_id];
787
788    let type_generic_params_data = db.priv_trait_type_generic_params_data(trait_type_id)?;
789    let inference_id = InferenceId::LookupItemDeclaration(LookupItemId::TraitItem(
790        TraitItemId::Type(trait_type_id),
791    ));
792    let resolver = Resolver::with_data(
793        db,
794        (*type_generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
795    );
796    diagnostics.extend(type_generic_params_data.diagnostics.clone());
797
798    let attributes = type_syntax.attributes(db).structurize(db);
799    let resolver_data = Arc::new(resolver.data);
800
801    Ok(TraitItemTypeData { diagnostics: diagnostics.build(), attributes, resolver_data })
802}
803
804// === Trait item constant ===
805
806#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
807#[debug_db(dyn Database)]
808struct TraitItemConstantData<'db> {
809    pub diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
810    pub ty: TypeId<'db>,
811    pub attributes: Vec<Attribute<'db>>,
812    pub resolver_data: Arc<ResolverData<'db>>,
813}
814
815// --- Computation ---
816
817/// Query implementation of [PrivTraitSemantic::priv_trait_constant_data].
818#[salsa::tracked(returns(ref))]
819fn priv_trait_constant_data<'db>(
820    db: &'db dyn Database,
821    trait_constant: TraitConstantId<'db>,
822) -> Maybe<TraitItemConstantData<'db>> {
823    let mut diagnostics = SemanticDiagnostics::default();
824    let trait_id = trait_constant.trait_id(db);
825    let data = db.priv_trait_definition_data(trait_id)?;
826    let constant_syntax = &data.item_constant_asts[&trait_constant];
827    let inference_id = InferenceId::LookupItemDeclaration(LookupItemId::TraitItem(
828        TraitItemId::Constant(trait_constant),
829    ));
830    let parent_resolver_data = db.trait_resolver_data(trait_id)?;
831    let mut resolver =
832        Resolver::with_data(db, parent_resolver_data.clone_with_inference_id(db, inference_id));
833
834    let ty =
835        resolve_type(db, &mut diagnostics, &mut resolver, &constant_syntax.type_clause(db).ty(db));
836    let attributes = constant_syntax.attributes(db).structurize(db);
837    let resolver_data = Arc::new(resolver.data);
838
839    Ok(TraitItemConstantData { diagnostics: diagnostics.build(), ty, attributes, resolver_data })
840}
841
842/// Implementation of [TraitSemantic::concrete_trait_constant_type].
843fn concrete_trait_constant_type<'db>(
844    db: &'db dyn Database,
845    concrete_trait_constant_id: ConcreteTraitConstantId<'db>,
846) -> Maybe<TypeId<'db>> {
847    let concrete_trait_id = concrete_trait_constant_id.concrete_trait(db);
848    let substitution = GenericSubstitution::new(
849        db.trait_generic_params(concrete_trait_id.trait_id(db))?,
850        concrete_trait_id.generic_args(db),
851    );
852    let generic_ty = db.trait_constant_type(concrete_trait_constant_id.trait_constant(db))?;
853    substitution.substitute(db, generic_ty)
854}
855
856/// Query implementation of [TraitSemantic::concrete_trait_constant_type].
857#[salsa::tracked]
858fn concrete_trait_constant_type_tracked<'db>(
859    db: &'db dyn Database,
860    concrete_trait_constant_id: ConcreteTraitConstantId<'db>,
861) -> Maybe<TypeId<'db>> {
862    concrete_trait_constant_type(db, concrete_trait_constant_id)
863}
864
865// === Trait item impl ===
866
867#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, salsa::Update)]
868#[debug_db(dyn Database)]
869struct TraitItemImplData<'db> {
870    diagnostics: Diagnostics<'db, SemanticDiagnostic<'db>>,
871    concrete_trait: Maybe<ConcreteTraitId<'db>>,
872    attributes: Vec<Attribute<'db>>,
873    resolver_data: Arc<ResolverData<'db>>,
874}
875
876/// Query implementation of [PrivTraitSemantic::priv_trait_impl_data].
877#[salsa::tracked(returns(ref))]
878fn priv_trait_impl_data<'db>(
879    db: &'db dyn Database,
880    trait_impl: TraitImplId<'db>,
881) -> Maybe<TraitItemImplData<'db>> {
882    let mut diagnostics = SemanticDiagnostics::default();
883    let trait_id = trait_impl.trait_id(db);
884    let data = db.priv_trait_definition_data(trait_id)?;
885    let impl_syntax = &data.item_impl_asts[&trait_impl];
886    let trait_path = impl_syntax.trait_path(db);
887    let inference_id =
888        InferenceId::LookupItemDeclaration(LookupItemId::TraitItem(TraitItemId::Impl(trait_impl)));
889    let parent_resolver_data = db.trait_resolver_data(trait_id)?;
890    let mut resolver =
891        Resolver::with_data(db, parent_resolver_data.clone_with_inference_id(db, inference_id));
892    let concrete_trait = resolver
893        .resolve_concrete_path(&mut diagnostics, &trait_path, NotFoundItemType::Trait)
894        .and_then(|resolved_item: crate::resolve::ResolvedConcreteItem<'_>| match resolved_item {
895            ResolvedConcreteItem::Trait(id) | ResolvedConcreteItem::SelfTrait(id) => Ok(id),
896            _ => {
897                Err(diagnostics
898                    .report(trait_path.stable_ptr(db), SemanticDiagnosticKind::UnknownTrait))
899            }
900        });
901    let attributes = impl_syntax.attributes(db).structurize(db);
902    let resolver_data = Arc::new(resolver.data);
903
904    Ok(TraitItemImplData {
905        diagnostics: diagnostics.build(),
906        concrete_trait,
907        attributes,
908        resolver_data,
909    })
910}
911
912/// Implementation of [TraitSemantic::concrete_trait_impl_concrete_trait].
913fn concrete_trait_impl_concrete_trait<'db>(
914    db: &'db dyn Database,
915    concrete_trait_impl_id: ConcreteTraitImplId<'db>,
916) -> Maybe<ConcreteTraitId<'db>> {
917    let concrete_trait_id = concrete_trait_impl_id.concrete_trait(db);
918    GenericSubstitution::new(
919        db.trait_generic_params(concrete_trait_id.trait_id(db))?,
920        concrete_trait_id.generic_args(db),
921    )
922    .substitute(db, db.trait_impl_concrete_trait(concrete_trait_impl_id.trait_impl(db))?)
923}
924
925/// Query implementation of [TraitSemantic::concrete_trait_impl_concrete_trait].
926#[salsa::tracked]
927fn concrete_trait_impl_concrete_trait_tracked<'db>(
928    db: &'db dyn Database,
929    concrete_trait_impl_id: ConcreteTraitImplId<'db>,
930) -> Maybe<ConcreteTraitId<'db>> {
931    concrete_trait_impl_concrete_trait(db, concrete_trait_impl_id)
932}
933
934// === Trait function Declaration ===
935
936/// Query implementation of [TraitSemantic::priv_trait_function_generic_params_data].
937#[salsa::tracked(returns(ref))]
938fn priv_trait_function_generic_params_data<'db>(
939    db: &'db dyn Database,
940    trait_function_id: TraitFunctionId<'db>,
941) -> Maybe<GenericParamsData<'db>> {
942    let module_id = trait_function_id.module_id(db);
943    let mut diagnostics = SemanticDiagnostics::default();
944    let trait_id = trait_function_id.trait_id(db);
945    let data = db.priv_trait_definition_data(trait_id)?;
946    let function_syntax = &data.function_asts[&trait_function_id];
947    let declaration = function_syntax.declaration(db);
948    let inference_id = InferenceId::LookupItemGenerics(LookupItemId::TraitItem(
949        TraitItemId::Function(trait_function_id),
950    ));
951    let parent_resolver_data = db.trait_resolver_data(trait_id)?;
952    let mut resolver =
953        Resolver::with_data(db, parent_resolver_data.clone_with_inference_id(db, inference_id));
954    let trait_generic_params = db.trait_generic_params(trait_id)?;
955    for generic_param in trait_generic_params {
956        resolver.add_generic_param(generic_param.id());
957    }
958    let function_generic_params = semantic_generic_params(
959        db,
960        &mut diagnostics,
961        &mut resolver,
962        module_id,
963        &declaration.generic_params(db),
964    );
965    let function_generic_params = resolver.inference().rewrite(function_generic_params).no_err();
966    let resolver_data = Arc::new(resolver.data);
967    Ok(GenericParamsData {
968        diagnostics: diagnostics.build(),
969        generic_params: function_generic_params,
970        resolver_data,
971    })
972}
973
974/// Query implementation of [PrivTraitSemantic::priv_trait_function_declaration_data].
975#[salsa::tracked(returns(ref))]
976fn priv_trait_function_declaration_data<'db>(
977    db: &'db dyn Database,
978    trait_function_id: TraitFunctionId<'db>,
979) -> Maybe<FunctionDeclarationData<'db>> {
980    let mut diagnostics = SemanticDiagnostics::default();
981    let trait_id = trait_function_id.trait_id(db);
982    let data = db.priv_trait_definition_data(trait_id)?;
983    let function_syntax = &data.function_asts[&trait_function_id];
984    let declaration_syntax = function_syntax.declaration(db);
985    let function_generic_params_data =
986        db.priv_trait_function_generic_params_data(trait_function_id)?;
987    let lookup_item_id = LookupItemId::TraitItem(TraitItemId::Function(trait_function_id));
988    let inference_id = InferenceId::LookupItemDeclaration(lookup_item_id);
989    let mut resolver = Resolver::with_data(
990        db,
991        (*function_generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
992    );
993    diagnostics.extend(function_generic_params_data.diagnostics.clone());
994    resolver.set_feature_config(&trait_function_id, function_syntax, &mut diagnostics);
995    let mut environment = Environment::empty();
996    let signature = semantic::Signature::from_ast(
997        &mut diagnostics,
998        db,
999        &mut resolver,
1000        &declaration_syntax,
1001        FunctionTitleId::Trait(trait_function_id),
1002        &mut environment,
1003    );
1004
1005    // Check fully resolved.
1006    let inference = &mut resolver.inference();
1007    inference.finalize(&mut diagnostics, function_syntax.stable_ptr(db).untyped());
1008    let signature = inference.rewrite(signature).no_err();
1009
1010    validate_trait_function_signature(
1011        db,
1012        &mut diagnostics,
1013        trait_id,
1014        trait_function_id,
1015        &signature,
1016    );
1017
1018    let attributes = function_syntax.attributes(db).structurize(db);
1019
1020    let inline_config = get_inline_config(db, &mut diagnostics, &attributes)?;
1021    let (implicit_precedence, _) =
1022        get_implicit_precedence(db, &mut diagnostics, &mut resolver, &attributes);
1023    let resolver_data = Arc::new(resolver.data);
1024
1025    Ok(FunctionDeclarationData {
1026        diagnostics: diagnostics.build(),
1027        signature,
1028        environment,
1029        attributes,
1030        resolver_data,
1031        inline_config,
1032        implicit_precedence,
1033    })
1034}
1035
1036fn validate_trait_function_signature<'db>(
1037    db: &'db dyn Database,
1038    diagnostics: &mut SemanticDiagnostics<'db>,
1039    trait_id: TraitId<'db>,
1040    function_id: TraitFunctionId<'db>,
1041    sig: &semantic::Signature<'db>,
1042) {
1043    for param in &sig.params {
1044        if param.mutability == Mutability::Mutable {
1045            diagnostics.report(
1046                param.stable_ptr(db).lookup(db).modifiers(db).stable_ptr(db),
1047                crate::diagnostic::SemanticDiagnosticKind::TraitParamMutable {
1048                    trait_id,
1049                    function_id,
1050                },
1051            );
1052        }
1053    }
1054}
1055
1056// === Concrete Trait Function ===
1057
1058/// Implementation of [TraitSemantic::concrete_trait_function_generic_params].
1059fn concrete_trait_function_generic_params<'db>(
1060    db: &'db dyn Database,
1061    concrete_trait_function_id: ConcreteTraitGenericFunctionId<'db>,
1062) -> Maybe<Vec<GenericParam<'db>>> {
1063    let concrete_trait_id = concrete_trait_function_id.concrete_trait(db);
1064    GenericSubstitution::new(
1065        db.trait_generic_params(concrete_trait_id.trait_id(db))?,
1066        concrete_trait_id.generic_args(db),
1067    )
1068    .substitute(
1069        db,
1070        db.trait_function_generic_params(concrete_trait_function_id.trait_function(db))?.to_vec(),
1071    )
1072}
1073
1074/// Query implementation of [TraitSemantic::concrete_trait_function_generic_params].
1075#[salsa::tracked(returns(ref))]
1076fn concrete_trait_function_generic_params_tracked<'db>(
1077    db: &'db dyn Database,
1078    concrete_trait_function_id: ConcreteTraitGenericFunctionId<'db>,
1079) -> Maybe<Vec<GenericParam<'db>>> {
1080    concrete_trait_function_generic_params(db, concrete_trait_function_id)
1081}
1082
1083/// Query implementation of [TraitSemantic::concrete_trait_function_signature].
1084#[salsa::tracked(returns(ref))]
1085fn concrete_trait_function_signature<'db>(
1086    db: &'db dyn Database,
1087    concrete_trait_function_id: ConcreteTraitGenericFunctionId<'db>,
1088) -> Maybe<semantic::Signature<'db>> {
1089    let concrete_trait_id = concrete_trait_function_id.concrete_trait(db);
1090    GenericSubstitution::new(
1091        db.trait_generic_params(concrete_trait_id.trait_id(db))?,
1092        concrete_trait_id.generic_args(db),
1093    )
1094    .substitute(
1095        db,
1096        db.trait_function_signature(concrete_trait_function_id.trait_function(db))?.clone(),
1097    )
1098}
1099
1100// === Body ===
1101
1102/// Query implementation of [TraitSemantic::priv_trait_function_body_data].
1103#[salsa::tracked(returns(ref))]
1104fn priv_trait_function_body_data<'db>(
1105    db: &'db dyn Database,
1106    trait_function_id: TraitFunctionId<'db>,
1107) -> Maybe<Option<FunctionBodyData<'db>>> {
1108    let mut diagnostics = SemanticDiagnostics::default();
1109    let trait_id = trait_function_id.trait_id(db);
1110    let data = db.priv_trait_definition_data(trait_id)?;
1111    let function_syntax = &data.function_asts[&trait_function_id];
1112    // Compute declaration semantic.
1113    let trait_function_declaration_data =
1114        db.priv_trait_function_declaration_data(trait_function_id)?;
1115    let parent_resolver_data = &trait_function_declaration_data.resolver_data;
1116    let inference_id = InferenceId::LookupItemDefinition(LookupItemId::TraitItem(
1117        TraitItemId::Function(trait_function_id),
1118    ));
1119    let mut resolver =
1120        Resolver::with_data(db, (*parent_resolver_data).clone_with_inference_id(db, inference_id));
1121    resolver.trait_or_impl_ctx = TraitOrImplContext::Trait(trait_id);
1122    let environment = trait_function_declaration_data.environment.clone();
1123
1124    let function_id: Result<crate::FunctionId<'db>, cairo_lang_diagnostics::DiagnosticAdded> =
1125        (|| {
1126            let generic_parameters = db.trait_generic_params(trait_id)?;
1127            let concrete_trait = ConcreteTraitLongId {
1128                trait_id,
1129                generic_args: generic_params_to_args(generic_parameters, db),
1130            }
1131            .intern(db);
1132            let generic_function = GenericFunctionId::Impl(ImplGenericFunctionId {
1133                impl_id: ImplLongId::SelfImpl(concrete_trait).intern(db),
1134                function: trait_function_id,
1135            });
1136
1137            Ok(FunctionLongId::from_generic(db, generic_function)?.intern(db))
1138        })();
1139    // Compute body semantic expr.
1140    let mut ctx: ComputationContext<'db, '_> = ComputationContext::new(
1141        db,
1142        &mut diagnostics,
1143        &mut resolver,
1144        Some(&trait_function_declaration_data.signature),
1145        environment,
1146        ContextFunction::Function(function_id),
1147    );
1148    let function_body = match function_syntax.body(db) {
1149        ast::MaybeTraitFunctionBody::Some(expr_block) => expr_block,
1150        ast::MaybeTraitFunctionBody::None(_) => return Ok(None),
1151    };
1152    let return_type = trait_function_declaration_data.signature.return_type;
1153    let body_expr = compute_root_expr(&mut ctx, &function_body, return_type)?;
1154    let ComputationContext { arenas, .. } = ctx;
1155
1156    let expr_lookup: UnorderedHashMap<_, _> =
1157        arenas.exprs.iter().map(|(id, expr)| (expr.stable_ptr(), id)).collect();
1158    let pattern_lookup: UnorderedHashMap<_, _> =
1159        arenas.patterns.iter().map(|(id, pattern)| (pattern.stable_ptr(), id)).collect();
1160    let resolver_data = Arc::new(resolver.data);
1161    Ok(Some(FunctionBodyData {
1162        diagnostics: diagnostics.build(),
1163        expr_lookup,
1164        pattern_lookup,
1165        resolver_data,
1166        body: FunctionBody { arenas, body_expr },
1167    }))
1168}
1169
1170/// Trait for trait-related semantic queries.
1171pub trait TraitSemantic<'db>: Database {
1172    /// Returns the semantic declaration diagnostics of a trait.
1173    fn trait_semantic_declaration_diagnostics(
1174        &'db self,
1175        trait_id: TraitId<'db>,
1176    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
1177        self.priv_trait_declaration_data(trait_id)
1178            .map(|data| data.diagnostics.clone())
1179            .unwrap_or_default()
1180    }
1181    /// Returns the generic parameters of a trait.
1182    fn trait_generic_params(&'db self, trait_id: TraitId<'db>) -> Maybe<&'db [GenericParam<'db>]> {
1183        Ok(&self.trait_generic_params_data(trait_id, false)?.generic_params)
1184    }
1185    /// Returns the ids of the generic parameters of a trait.
1186    fn trait_generic_params_ids(
1187        &'db self,
1188        trait_id: TraitId<'db>,
1189    ) -> Maybe<&'db [GenericParamId<'db>]> {
1190        Ok(trait_generic_params_ids(self.as_dyn_database(), trait_id).maybe_as_ref()?)
1191    }
1192    /// Returns the attributes of a trait.
1193    fn trait_attributes(&'db self, trait_id: TraitId<'db>) -> Maybe<&'db [Attribute<'db>]> {
1194        Ok(&self.priv_trait_declaration_data(trait_id)?.attributes)
1195    }
1196    /// Returns the resolution resolved_items of a trait.
1197    fn trait_resolver_data(&'db self, trait_id: TraitId<'db>) -> Maybe<Arc<ResolverData<'db>>> {
1198        Ok(self.priv_trait_declaration_data(trait_id)?.resolver_data.clone())
1199    }
1200    /// Returns the semantic definition diagnostics of a trait.
1201    fn trait_semantic_definition_diagnostics(
1202        &'db self,
1203        trait_id: TraitId<'db>,
1204    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
1205        trait_semantic_definition_diagnostics_tracked(self.as_dyn_database(), trait_id)
1206    }
1207    /// Returns the names of all the non default implemented items of a trait.
1208    fn trait_required_item_names(
1209        &'db self,
1210        trait_id: TraitId<'db>,
1211    ) -> Maybe<&'db OrderedHashSet<SmolStrId<'db>>> {
1212        trait_required_item_names(self.as_dyn_database(), trait_id).maybe_as_ref()
1213    }
1214    /// Returns the item of the trait, by the given `name`, if exists.
1215    fn trait_item_by_name(
1216        &'db self,
1217        trait_id: TraitId<'db>,
1218        name: SmolStrId<'db>,
1219    ) -> Maybe<Option<TraitItemId<'db>>> {
1220        Ok(self
1221            .priv_trait_definition_data(trait_id)?
1222            .item_id_by_name
1223            .get(&name)
1224            .map(|info| info.id))
1225    }
1226    /// Returns the metadata for a trait item, by the given `name`, if exists.
1227    fn trait_item_info_by_name(
1228        &'db self,
1229        trait_id: TraitId<'db>,
1230        name: SmolStrId<'db>,
1231    ) -> Maybe<Option<TraitItemInfo<'db>>> {
1232        Ok(self.priv_trait_definition_data(trait_id)?.item_id_by_name.get(&name).cloned())
1233    }
1234    /// Returns all the items used within the trait.
1235    fn trait_all_used_uses(
1236        &'db self,
1237        trait_id: TraitId<'db>,
1238    ) -> Maybe<&'db OrderedHashSet<UseId<'db>>> {
1239        trait_all_used_uses(self.as_dyn_database(), trait_id).maybe_as_ref()
1240    }
1241    /// Returns the functions of a trait.
1242    fn trait_functions(
1243        &'db self,
1244        trait_id: TraitId<'db>,
1245    ) -> Maybe<&'db OrderedHashMap<SmolStrId<'db>, TraitFunctionId<'db>>> {
1246        trait_functions(self.as_dyn_database(), trait_id).maybe_as_ref()
1247    }
1248    /// Returns the function with the given name of the given trait, if exists.
1249    fn trait_function_by_name(
1250        &'db self,
1251        trait_id: TraitId<'db>,
1252        name: SmolStrId<'db>,
1253    ) -> Maybe<Option<TraitFunctionId<'db>>> {
1254        Ok(self.trait_functions(trait_id)?.get(&name).copied())
1255    }
1256    /// Returns the types of a trait.
1257    fn trait_types(
1258        &'db self,
1259        trait_id: TraitId<'db>,
1260    ) -> Maybe<&'db OrderedHashMap<SmolStrId<'db>, TraitTypeId<'db>>> {
1261        trait_types(self.as_dyn_database(), trait_id).maybe_as_ref()
1262    }
1263    /// Returns the item type with the given name of the given trait, if exists.
1264    fn trait_type_by_name(
1265        &'db self,
1266        trait_id: TraitId<'db>,
1267        name: SmolStrId<'db>,
1268    ) -> Maybe<Option<TraitTypeId<'db>>> {
1269        Ok(self.trait_types(trait_id)?.get(&name).copied())
1270    }
1271    /// Returns the constants of a trait.
1272    fn trait_constants(
1273        &'db self,
1274        trait_id: TraitId<'db>,
1275    ) -> Maybe<&'db OrderedHashMap<SmolStrId<'db>, TraitConstantId<'db>>> {
1276        trait_constants(self.as_dyn_database(), trait_id).maybe_as_ref()
1277    }
1278    /// Returns the item constants with the given name of the given trait, if exists.
1279    fn trait_constant_by_name(
1280        &'db self,
1281        trait_id: TraitId<'db>,
1282        name: SmolStrId<'db>,
1283    ) -> Maybe<Option<TraitConstantId<'db>>> {
1284        Ok(self.trait_constants(trait_id)?.get(&name).copied())
1285    }
1286    /// Returns the constants of a trait.
1287    fn trait_impls(
1288        &'db self,
1289        trait_id: TraitId<'db>,
1290    ) -> Maybe<&'db OrderedHashMap<SmolStrId<'db>, TraitImplId<'db>>> {
1291        trait_impls(self.as_dyn_database(), trait_id).maybe_as_ref()
1292    }
1293    /// Returns the item impls with the given name of the given trait, if exists.
1294    fn trait_impl_by_name(
1295        &'db self,
1296        trait_id: TraitId<'db>,
1297        name: SmolStrId<'db>,
1298    ) -> Maybe<Option<TraitImplId<'db>>> {
1299        Ok(self.trait_impls(trait_id)?.get(&name).copied())
1300    }
1301
1302    // Trait type.
1303    // ================
1304    /// Returns the generic params of a trait type.
1305    fn trait_type_generic_params(
1306        &'db self,
1307        trait_type_id: TraitTypeId<'db>,
1308    ) -> Maybe<&'db [GenericParam<'db>]> {
1309        Ok(&self.priv_trait_type_generic_params_data(trait_type_id)?.generic_params)
1310    }
1311    /// Returns the attributes of a trait type.
1312    fn trait_type_attributes(
1313        &'db self,
1314        trait_type_id: TraitTypeId<'db>,
1315    ) -> Maybe<&'db [Attribute<'db>]> {
1316        Ok(&self.priv_trait_type_data(trait_type_id).maybe_as_ref()?.attributes)
1317    }
1318    /// Returns the resolution resolved_items of a trait type.
1319    fn trait_type_resolver_data(
1320        &'db self,
1321        trait_type_id: TraitTypeId<'db>,
1322    ) -> Maybe<Arc<ResolverData<'db>>> {
1323        Ok(self.priv_trait_type_data(trait_type_id)?.resolver_data.clone())
1324    }
1325
1326    // Trait constants.
1327    // ================
1328    /// Returns the attributes of a trait constants.
1329    fn trait_constant_attributes(
1330        &'db self,
1331        id: TraitConstantId<'db>,
1332    ) -> Maybe<Vec<Attribute<'db>>> {
1333        Ok(self.priv_trait_constant_data(id)?.attributes.clone())
1334    }
1335    /// Returns the type of a trait constant.
1336    fn trait_constant_type(&'db self, id: TraitConstantId<'db>) -> Maybe<TypeId<'db>> {
1337        Ok(self.priv_trait_constant_data(id)?.ty)
1338    }
1339    /// Returns the resolution resolved_items of a trait constants.
1340    fn trait_constant_resolver_data(
1341        &'db self,
1342        id: TraitConstantId<'db>,
1343    ) -> Maybe<Arc<ResolverData<'db>>> {
1344        Ok(self.priv_trait_constant_data(id)?.resolver_data.clone())
1345    }
1346    /// Returns the type of a trait constant.
1347    fn concrete_trait_constant_type(
1348        &'db self,
1349        concrete_trait_constant_id: ConcreteTraitConstantId<'db>,
1350    ) -> Maybe<TypeId<'db>> {
1351        concrete_trait_constant_type_tracked(self.as_dyn_database(), concrete_trait_constant_id)
1352    }
1353
1354    // Trait impls.
1355    // ================
1356    /// Returns the concrete trait of a trait impl.
1357    fn trait_impl_concrete_trait(&'db self, id: TraitImplId<'db>) -> Maybe<ConcreteTraitId<'db>> {
1358        self.priv_trait_impl_data(id)?.concrete_trait
1359    }
1360    /// Returns the resolution resolved_items of a trait impls.
1361    fn trait_impl_resolver_data(&'db self, id: TraitImplId<'db>) -> Maybe<Arc<ResolverData<'db>>> {
1362        Ok(self.priv_trait_impl_data(id)?.resolver_data.clone())
1363    }
1364    /// Returns the concrete trait of a concrete trait impl.
1365    fn concrete_trait_impl_concrete_trait(
1366        &'db self,
1367        concrete_trait_impl_id: ConcreteTraitImplId<'db>,
1368    ) -> Maybe<ConcreteTraitId<'db>> {
1369        concrete_trait_impl_concrete_trait_tracked(self.as_dyn_database(), concrete_trait_impl_id)
1370    }
1371
1372    // Trait function.
1373    // ================
1374    /// Returns the semantic diagnostics of a trait function.
1375    fn trait_function_declaration_diagnostics(
1376        &'db self,
1377        trait_function_id: TraitFunctionId<'db>,
1378    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
1379        self.priv_trait_function_declaration_data(trait_function_id)
1380            .map(|data| data.diagnostics.clone())
1381            .unwrap_or_default()
1382    }
1383    /// Returns the signature of a trait function.
1384    fn trait_function_signature(
1385        &'db self,
1386        trait_function_id: TraitFunctionId<'db>,
1387    ) -> Maybe<&'db semantic::Signature<'db>> {
1388        Ok(&self.priv_trait_function_declaration_data(trait_function_id)?.signature)
1389    }
1390    /// Returns the generic params of a trait function.
1391    fn trait_function_generic_params(
1392        &'db self,
1393        trait_function_id: TraitFunctionId<'db>,
1394    ) -> Maybe<&'db [GenericParam<'db>]> {
1395        Ok(&self.priv_trait_function_generic_params_data(trait_function_id)?.generic_params)
1396    }
1397    /// Returns the attributes of a trait function.
1398    fn trait_function_attributes(
1399        &'db self,
1400        trait_function_id: TraitFunctionId<'db>,
1401    ) -> Maybe<&'db [Attribute<'db>]> {
1402        Ok(&self.priv_trait_function_declaration_data(trait_function_id)?.attributes)
1403    }
1404    /// Returns the resolver data of a trait function.
1405    fn trait_function_resolver_data(
1406        &'db self,
1407        trait_function_id: TraitFunctionId<'db>,
1408    ) -> Maybe<Arc<ResolverData<'db>>> {
1409        Ok(self.priv_trait_function_declaration_data(trait_function_id)?.resolver_data.clone())
1410    }
1411    /// Returns the inline configuration of a trait function's declaration.
1412    fn trait_function_declaration_inline_config(
1413        &'db self,
1414        trait_function_id: TraitFunctionId<'db>,
1415    ) -> Maybe<InlineConfiguration<'db>> {
1416        Ok(self.priv_trait_function_declaration_data(trait_function_id)?.inline_config.clone())
1417    }
1418    /// Returns the implicits precedence of a trait function.
1419    fn trait_function_declaration_implicit_precedence(
1420        &'db self,
1421        trait_function_id: TraitFunctionId<'db>,
1422    ) -> Maybe<&'db ImplicitPrecedence<'db>> {
1423        Ok(&self.priv_trait_function_declaration_data(trait_function_id)?.implicit_precedence)
1424    }
1425    /// Returns the semantic diagnostics of a trait function definition (declaration + body).
1426    fn trait_function_body_diagnostics(
1427        &'db self,
1428        trait_function_id: TraitFunctionId<'db>,
1429    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
1430        self.priv_trait_function_body_data(trait_function_id)
1431            .ok()
1432            .flatten()
1433            .map(|data| data.diagnostics.clone())
1434            .unwrap_or_default()
1435    }
1436    /// Returns the body of a trait function, if any.
1437    fn trait_function_body(
1438        &'db self,
1439        trait_function_id: TraitFunctionId<'db>,
1440    ) -> Maybe<Option<&'db FunctionBody<'db>>> {
1441        Ok(self.priv_trait_function_body_data(trait_function_id)?.map(|data| &data.body))
1442    }
1443    /// Returns the resolution resolved_items of a trait function.
1444    fn trait_function_body_resolver_data(
1445        &'db self,
1446        trait_function_id: TraitFunctionId<'db>,
1447    ) -> Maybe<Option<Arc<ResolverData<'db>>>> {
1448        self.priv_trait_function_body_data(trait_function_id)
1449            .map(|x| x.map(|y| y.resolver_data.clone()))
1450    }
1451    /// Private query to compute data about a trait function definition (declaration + body)
1452    fn priv_trait_function_body_data(
1453        &'db self,
1454        trait_function_id: TraitFunctionId<'db>,
1455    ) -> Maybe<Option<&'db FunctionBodyData<'db>>> {
1456        priv_trait_function_body_data(self.as_dyn_database(), trait_function_id)
1457            .maybe_as_ref()
1458            .map(Option::as_ref)
1459    }
1460
1461    // Concrete Trait function.
1462    // ========================
1463    /// Returns the generic params of a concrete trait function.
1464    fn concrete_trait_function_generic_params(
1465        &'db self,
1466        concrete_trait_function_id: ConcreteTraitGenericFunctionId<'db>,
1467    ) -> Maybe<&'db [GenericParam<'db>]> {
1468        Ok(concrete_trait_function_generic_params_tracked(
1469            self.as_dyn_database(),
1470            concrete_trait_function_id,
1471        )
1472        .maybe_as_ref()?)
1473    }
1474    /// Returns the signature of a concrete trait function.
1475    fn concrete_trait_function_signature(
1476        &'db self,
1477        concrete_trait_function_id: ConcreteTraitGenericFunctionId<'db>,
1478    ) -> Maybe<&'db semantic::Signature<'db>> {
1479        concrete_trait_function_signature(self.as_dyn_database(), concrete_trait_function_id)
1480            .maybe_as_ref()
1481    }
1482}
1483impl<'db, T: Database + ?Sized> TraitSemantic<'db> for T {}
1484
1485/// Trait for private trait-related semantic queries.
1486trait PrivTraitSemantic<'db>: Database {
1487    /// Returns the generic parameters data of a trait.
1488    fn trait_generic_params_data(
1489        &'db self,
1490        trait_id: TraitId<'db>,
1491        in_cycle: bool,
1492    ) -> Maybe<&'db GenericParamsData<'db>> {
1493        trait_generic_params_data_tracked(self.as_dyn_database(), trait_id, in_cycle).maybe_as_ref()
1494    }
1495    /// Private query to compute declaration data about a trait.
1496    fn priv_trait_declaration_data(
1497        &'db self,
1498        trait_id: TraitId<'db>,
1499    ) -> Maybe<&'db TraitDeclarationData<'db>> {
1500        priv_trait_declaration_data(self.as_dyn_database(), trait_id).maybe_as_ref()
1501    }
1502    /// Private query to compute definition data about a trait.
1503    fn priv_trait_definition_data(
1504        &'db self,
1505        trait_id: TraitId<'db>,
1506    ) -> Maybe<&'db TraitDefinitionData<'db>> {
1507        priv_trait_definition_data(self.as_dyn_database(), trait_id).maybe_as_ref()
1508    }
1509    /// Returns the semantic diagnostics of a trait type.
1510    fn trait_type_diagnostics(
1511        &'db self,
1512        id: TraitTypeId<'db>,
1513    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
1514        self.priv_trait_type_data(id).map(|data| data.diagnostics.clone()).unwrap_or_default()
1515    }
1516    /// Returns the semantic diagnostics of a trait impls.
1517    fn trait_impl_diagnostics(
1518        &'db self,
1519        id: TraitImplId<'db>,
1520    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
1521        self.priv_trait_impl_data(id).map(|data| data.diagnostics.clone()).unwrap_or_default()
1522    }
1523    /// Private query to compute the generic params data of a trait type.
1524    fn priv_trait_type_generic_params_data(
1525        &'db self,
1526        trait_type_id: TraitTypeId<'db>,
1527    ) -> Maybe<&'db GenericParamsData<'db>> {
1528        priv_trait_type_generic_params_data(self.as_dyn_database(), trait_type_id).maybe_as_ref()
1529    }
1530    /// Private query to compute data about a trait type.
1531    fn priv_trait_type_data(
1532        &'db self,
1533        type_id: TraitTypeId<'db>,
1534    ) -> Maybe<&'db TraitItemTypeData<'db>> {
1535        priv_trait_type_data(self.as_dyn_database(), type_id).maybe_as_ref()
1536    }
1537    /// Returns the semantic diagnostics of a trait type.
1538    fn trait_constant_diagnostics(
1539        &'db self,
1540        id: TraitConstantId<'db>,
1541    ) -> Diagnostics<'db, SemanticDiagnostic<'db>> {
1542        self.priv_trait_constant_data(id).map(|data| data.diagnostics.clone()).unwrap_or_default()
1543    }
1544    /// Private query to compute data about a trait constant.
1545    fn priv_trait_constant_data(
1546        &'db self,
1547        trait_constant: TraitConstantId<'db>,
1548    ) -> Maybe<&'db TraitItemConstantData<'db>> {
1549        priv_trait_constant_data(self.as_dyn_database(), trait_constant).maybe_as_ref()
1550    }
1551    /// Private query to compute data about a trait impl.
1552    fn priv_trait_impl_data(
1553        &'db self,
1554        trait_impl: TraitImplId<'db>,
1555    ) -> Maybe<&'db TraitItemImplData<'db>> {
1556        priv_trait_impl_data(self.as_dyn_database(), trait_impl).maybe_as_ref()
1557    }
1558    /// Returns the generic params data of a trait function.
1559    fn priv_trait_function_generic_params_data(
1560        &'db self,
1561        trait_function_id: TraitFunctionId<'db>,
1562    ) -> Maybe<&'db GenericParamsData<'db>> {
1563        priv_trait_function_generic_params_data(self.as_dyn_database(), trait_function_id)
1564            .maybe_as_ref()
1565    }
1566    /// Private query to compute data about a trait function declaration.
1567    fn priv_trait_function_declaration_data(
1568        &'db self,
1569        function_id: TraitFunctionId<'db>,
1570    ) -> Maybe<&'db FunctionDeclarationData<'db>> {
1571        priv_trait_function_declaration_data(self.as_dyn_database(), function_id).maybe_as_ref()
1572    }
1573}
1574impl<'db, T: Database + ?Sized> PrivTraitSemantic<'db> for T {}