cairo_lang_semantic/items/
trt.rs

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