Skip to main content

cairo_lang_semantic/items/
trt.rs

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