cairo_lang_semantic/items/
trt.rs

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