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};
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::inference::InferenceId;
39use crate::expr::inference::canonic::ResultNoErrEx;
40use crate::items::feature_kind::HasFeatureKind;
41use crate::resolve::{ResolvedConcreteItem, Resolver, ResolverData};
42use crate::substitution::{GenericSubstitution, SemanticRewriter};
43use crate::types::resolve_type;
44use crate::{
45    Arenas, FunctionBody, FunctionLongId, GenericArgumentId, GenericParam, Mutability,
46    SemanticDiagnostic, TypeId, semantic, semantic_object_for_id,
47};
48
49#[cfg(test)]
50#[path = "trt_test.rs"]
51mod test;
52
53#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
54pub struct ConcreteTraitLongId {
55    pub trait_id: TraitId,
56    pub generic_args: Vec<GenericArgumentId>,
57}
58impl DebugWithDb<dyn SemanticGroup> for ConcreteTraitLongId {
59    fn fmt(
60        &self,
61        f: &mut std::fmt::Formatter<'_>,
62        db: &(dyn SemanticGroup + 'static),
63    ) -> std::fmt::Result {
64        write!(f, "{}", self.trait_id.full_path(db.upcast()))?;
65        fmt_generic_args(&self.generic_args, f, db)
66    }
67}
68
69define_short_id!(
70    ConcreteTraitId,
71    ConcreteTraitLongId,
72    SemanticGroup,
73    lookup_intern_concrete_trait,
74    intern_concrete_trait
75);
76semantic_object_for_id!(
77    ConcreteTraitId,
78    lookup_intern_concrete_trait,
79    intern_concrete_trait,
80    ConcreteTraitLongId
81);
82impl ConcreteTraitId {
83    pub fn trait_id(&self, db: &dyn SemanticGroup) -> TraitId {
84        self.lookup_intern(db).trait_id
85    }
86    pub fn generic_args(&self, db: &dyn SemanticGroup) -> Vec<GenericArgumentId> {
87        self.lookup_intern(db).generic_args
88    }
89    pub fn name(&self, db: &dyn SemanticGroup) -> SmolStr {
90        self.trait_id(db).name(db.upcast())
91    }
92    pub fn full_path(&self, db: &dyn SemanticGroup) -> String {
93        format!("{:?}", self.debug(db.elongate()))
94    }
95    pub fn filter(&self, db: &dyn SemanticGroup) -> TraitFilter {
96        let generics_filter = match self.generic_args(db).first() {
97            Some(first_generic) => match first_generic.head(db) {
98                Some(head) => GenericsHeadFilter::FirstGenericFilter(head),
99                None => GenericsHeadFilter::NoFilter,
100            },
101            None => GenericsHeadFilter::NoGenerics,
102        };
103        TraitFilter { trait_id: self.trait_id(db), generics_filter }
104    }
105
106    /// Returns true if the `trait` does not depend on any generics.
107    pub fn is_fully_concrete(&self, db: &dyn SemanticGroup) -> bool {
108        self.lookup_intern(db)
109            .generic_args
110            .iter()
111            .all(|generic_argument_id| generic_argument_id.is_fully_concrete(db))
112    }
113    /// Returns true if the `trait` does not depend on impl or type variables.
114    pub fn is_var_free(&self, db: &dyn SemanticGroup) -> bool {
115        self.lookup_intern(db)
116            .generic_args
117            .iter()
118            .all(|generic_argument_id| generic_argument_id.is_var_free(db))
119    }
120}
121
122/// The ID of a generic function in a concrete trait.
123#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
124#[debug_db(dyn SemanticGroup + 'static)]
125pub struct ConcreteTraitGenericFunctionLongId {
126    // Note the members are private to prevent direct call to the constructor.
127    concrete_trait: ConcreteTraitId,
128    trait_function: TraitFunctionId,
129}
130impl ConcreteTraitGenericFunctionLongId {
131    pub fn new(
132        db: &dyn SemanticGroup,
133        concrete_trait: ConcreteTraitId,
134        trait_function: TraitFunctionId,
135    ) -> Self {
136        assert_eq!(
137            concrete_trait.trait_id(db),
138            trait_function.trait_id(db.upcast()),
139            "Concrete trait and trait function must belong to the same generic trait."
140        );
141        Self { concrete_trait, trait_function }
142    }
143}
144define_short_id!(
145    ConcreteTraitGenericFunctionId,
146    ConcreteTraitGenericFunctionLongId,
147    SemanticGroup,
148    lookup_intern_concrete_trait_function,
149    intern_concrete_trait_function
150);
151semantic_object_for_id!(
152    ConcreteTraitGenericFunctionId,
153    lookup_intern_concrete_trait_function,
154    intern_concrete_trait_function,
155    ConcreteTraitGenericFunctionLongId
156);
157impl ConcreteTraitGenericFunctionId {
158    pub fn new(
159        db: &dyn SemanticGroup,
160        concrete_trait: ConcreteTraitId,
161        trait_function: TraitFunctionId,
162    ) -> Self {
163        ConcreteTraitGenericFunctionLongId::new(db, concrete_trait, trait_function).intern(db)
164    }
165
166    pub fn trait_function(&self, db: &dyn SemanticGroup) -> TraitFunctionId {
167        self.lookup_intern(db).trait_function
168    }
169
170    pub fn concrete_trait(&self, db: &dyn SemanticGroup) -> ConcreteTraitId {
171        self.lookup_intern(db).concrete_trait
172    }
173}
174
175/// The ID of a type item in a concrete trait.
176#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
177#[debug_db(dyn SemanticGroup + 'static)]
178pub struct ConcreteTraitTypeLongId {
179    // Note the members are private to prevent direct call to the constructor.
180    concrete_trait: ConcreteTraitId,
181    trait_type: TraitTypeId,
182}
183impl ConcreteTraitTypeLongId {
184    pub fn new(
185        db: &dyn SemanticGroup,
186        concrete_trait: ConcreteTraitId,
187        trait_type: TraitTypeId,
188    ) -> Self {
189        assert_eq!(
190            concrete_trait.trait_id(db),
191            trait_type.trait_id(db.upcast()),
192            "Concrete trait and trait type must belong to the same generic trait."
193        );
194        Self { concrete_trait, trait_type }
195    }
196}
197define_short_id!(
198    ConcreteTraitTypeId,
199    ConcreteTraitTypeLongId,
200    SemanticGroup,
201    lookup_intern_concrete_trait_type,
202    intern_concrete_trait_type
203);
204semantic_object_for_id!(
205    ConcreteTraitTypeId,
206    lookup_intern_concrete_trait_type,
207    intern_concrete_trait_type,
208    ConcreteTraitTypeLongId
209);
210impl ConcreteTraitTypeId {
211    pub fn new(
212        db: &dyn SemanticGroup,
213        concrete_trait: ConcreteTraitId,
214        trait_type: TraitTypeId,
215    ) -> Self {
216        ConcreteTraitTypeLongId::new(db, concrete_trait, trait_type).intern(db)
217    }
218
219    pub fn trait_type(&self, db: &dyn SemanticGroup) -> TraitTypeId {
220        self.lookup_intern(db).trait_type
221    }
222
223    pub fn concrete_trait(&self, db: &dyn SemanticGroup) -> ConcreteTraitId {
224        self.lookup_intern(db).concrete_trait
225    }
226}
227
228/// The ID of a constant item in a concrete trait.
229#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
230#[debug_db(dyn SemanticGroup + 'static)]
231pub struct ConcreteTraitConstantLongId {
232    // Note the members are private to prevent direct call to the constructor.
233    concrete_trait: ConcreteTraitId,
234    trait_constant: TraitConstantId,
235}
236impl ConcreteTraitConstantLongId {
237    pub fn new(
238        db: &dyn SemanticGroup,
239        concrete_trait: ConcreteTraitId,
240        trait_constant: TraitConstantId,
241    ) -> Self {
242        assert_eq!(
243            concrete_trait.trait_id(db),
244            trait_constant.trait_id(db.upcast()),
245            "Concrete trait and trait constant must belong to the same generic trait."
246        );
247        Self { concrete_trait, trait_constant }
248    }
249}
250define_short_id!(
251    ConcreteTraitConstantId,
252    ConcreteTraitConstantLongId,
253    SemanticGroup,
254    lookup_intern_concrete_trait_constant,
255    intern_concrete_trait_constant
256);
257semantic_object_for_id!(
258    ConcreteTraitConstantId,
259    lookup_intern_concrete_trait_constant,
260    intern_concrete_trait_constant,
261    ConcreteTraitConstantLongId
262);
263impl ConcreteTraitConstantId {
264    pub fn new(
265        db: &dyn SemanticGroup,
266        concrete_trait: ConcreteTraitId,
267        trait_constant: TraitConstantId,
268    ) -> Self {
269        ConcreteTraitConstantLongId::new(db, concrete_trait, trait_constant).intern(db)
270    }
271
272    pub fn trait_constant(&self, db: &dyn SemanticGroup) -> TraitConstantId {
273        self.lookup_intern(db).trait_constant
274    }
275
276    pub fn concrete_trait(&self, db: &dyn SemanticGroup) -> ConcreteTraitId {
277        self.lookup_intern(db).concrete_trait
278    }
279}
280
281/// The ID of a impl item in a concrete trait.
282#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
283#[debug_db(dyn SemanticGroup + 'static)]
284pub struct ConcreteTraitImplLongId {
285    // Note the members are private to prevent direct call to the constructor.
286    concrete_trait: ConcreteTraitId,
287    trait_impl: TraitImplId,
288}
289impl ConcreteTraitImplLongId {
290    pub fn new(
291        db: &dyn SemanticGroup,
292        concrete_trait: ConcreteTraitId,
293        trait_impl: TraitImplId,
294    ) -> Self {
295        assert_eq!(
296            concrete_trait.trait_id(db),
297            trait_impl.trait_id(db.upcast()),
298            "Concrete trait and trait impl must belong to the same generic trait."
299        );
300        Self { concrete_trait, trait_impl }
301    }
302}
303define_short_id!(
304    ConcreteTraitImplId,
305    ConcreteTraitImplLongId,
306    SemanticGroup,
307    lookup_intern_concrete_trait_impl,
308    intern_concrete_trait_impl
309);
310semantic_object_for_id!(
311    ConcreteTraitImplId,
312    lookup_intern_concrete_trait_impl,
313    intern_concrete_trait_impl,
314    ConcreteTraitImplLongId
315);
316impl ConcreteTraitImplId {
317    pub fn new(
318        db: &dyn SemanticGroup,
319        concrete_trait: ConcreteTraitId,
320        trait_impl: TraitImplId,
321    ) -> Self {
322        ConcreteTraitImplLongId::new(db, concrete_trait, trait_impl).intern(db)
323    }
324
325    pub fn trait_impl(&self, db: &dyn SemanticGroup) -> TraitImplId {
326        self.lookup_intern(db).trait_impl
327    }
328
329    pub fn concrete_trait(&self, db: &dyn SemanticGroup) -> ConcreteTraitId {
330        self.lookup_intern(db).concrete_trait
331    }
332}
333
334// === Trait Declaration ===
335
336#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
337#[debug_db(dyn SemanticGroup + 'static)]
338pub struct TraitDeclarationData {
339    diagnostics: Diagnostics<SemanticDiagnostic>,
340    generic_params: Vec<GenericParam>,
341    attributes: Vec<Attribute>,
342    resolver_data: Arc<ResolverData>,
343}
344
345// --- Selectors ---
346
347/// Query implementation of [crate::db::SemanticGroup::trait_semantic_declaration_diagnostics].
348pub fn trait_semantic_declaration_diagnostics(
349    db: &dyn SemanticGroup,
350    trait_id: TraitId,
351) -> Diagnostics<SemanticDiagnostic> {
352    db.priv_trait_declaration_data(trait_id).map(|data| data.diagnostics).unwrap_or_default()
353}
354
355/// Query implementation of [crate::db::SemanticGroup::trait_generic_params].
356pub fn trait_generic_params(db: &dyn SemanticGroup, trait_id: TraitId) -> Maybe<Vec<GenericParam>> {
357    Ok(db.trait_generic_params_data(trait_id, false)?.generic_params)
358}
359/// Cycle handling for [crate::db::SemanticGroup::trait_generic_params].
360pub fn trait_generic_params_cycle(
361    db: &dyn SemanticGroup,
362    _cycle: &salsa::Cycle,
363    trait_id: &TraitId,
364) -> Maybe<Vec<GenericParam>> {
365    // Forwarding cycle handling to `priv_generic_param_data` handler.
366    Ok(db.trait_generic_params_data(*trait_id, true)?.generic_params)
367}
368
369/// Query implementation of [crate::db::SemanticGroup::trait_generic_params_data].
370pub fn trait_generic_params_data(
371    db: &dyn SemanticGroup,
372    trait_id: TraitId,
373    in_cycle: bool,
374) -> Maybe<GenericParamsData> {
375    let syntax_db: &dyn SyntaxGroup = db.upcast();
376    let module_file_id = trait_id.module_file_id(db.upcast());
377    let mut diagnostics = SemanticDiagnostics::default();
378    let trait_ast = db.module_trait_by_id(trait_id)?.to_maybe()?;
379
380    // Generic params.
381    let inference_id =
382        InferenceId::LookupItemGenerics(LookupItemId::ModuleItem(ModuleItemId::Trait(trait_id)));
383    let mut resolver = Resolver::new(db, module_file_id, inference_id);
384    resolver.set_feature_config(&trait_id, &trait_ast, &mut diagnostics);
385    let generic_params = semantic_generic_params_ex(
386        db,
387        &mut diagnostics,
388        &mut resolver,
389        module_file_id,
390        &trait_ast.generic_params(syntax_db),
391        in_cycle,
392    );
393
394    let inference = &mut resolver.inference();
395    inference.finalize(&mut diagnostics, trait_ast.stable_ptr().untyped());
396
397    let generic_params = inference.rewrite(generic_params).no_err();
398    let resolver_data = Arc::new(resolver.data);
399    Ok(GenericParamsData { diagnostics: diagnostics.build(), generic_params, resolver_data })
400}
401/// Cycle handling for [crate::db::SemanticGroup::trait_generic_params_data].
402pub fn trait_generic_params_data_cycle(
403    db: &dyn SemanticGroup,
404    _cycle: &salsa::Cycle,
405    trait_id: &TraitId,
406    _in_cycle: &bool,
407) -> Maybe<GenericParamsData> {
408    // Forwarding cycle handling to `priv_generic_param_data` handler.
409    trait_generic_params_data(db, *trait_id, true)
410}
411/// Query implementation of [crate::db::SemanticGroup::trait_attributes].
412pub fn trait_attributes(db: &dyn SemanticGroup, trait_id: TraitId) -> Maybe<Vec<Attribute>> {
413    Ok(db.priv_trait_declaration_data(trait_id)?.attributes)
414}
415
416/// Query implementation of [crate::db::SemanticGroup::trait_resolver_data].
417pub fn trait_resolver_data(db: &dyn SemanticGroup, trait_id: TraitId) -> Maybe<Arc<ResolverData>> {
418    Ok(db.priv_trait_declaration_data(trait_id)?.resolver_data)
419}
420
421// --- Computation ---
422
423/// Query implementation of [crate::db::SemanticGroup::priv_trait_declaration_data].
424pub fn priv_trait_declaration_data(
425    db: &dyn SemanticGroup,
426    trait_id: TraitId,
427) -> Maybe<TraitDeclarationData> {
428    let syntax_db: &dyn SyntaxGroup = db.upcast();
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(syntax_db).structurize(syntax_db);
447
448    // Check fully resolved.
449    let inference = &mut resolver.inference();
450    inference.finalize(&mut diagnostics, trait_ast.stable_ptr().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.upcast()).lookup(db.upcast()).body(db.upcast());
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_items].
581pub fn trait_all_used_items(
582    db: &dyn SemanticGroup,
583    trait_id: TraitId,
584) -> Maybe<Arc<OrderedHashSet<LookupItemId>>> {
585    let mut all_used_items = db.trait_resolver_data(trait_id)?.used_items.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_items.extend(resolver_data.used_items.iter().cloned());
590        }
591    }
592    Ok(all_used_items.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.upcast()), *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.upcast()), *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.upcast()), *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.upcast()), *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 syntax_db: &dyn SyntaxGroup = db.upcast();
703
704    let module_file_id = trait_id.module_file_id(db.upcast());
705    let mut diagnostics = SemanticDiagnostics::default();
706
707    // TODO(spapini): when code changes in a file, all the AST items change (as they contain a path
708    // to the green root that changes. Once ASTs are rooted on items, use a selector that picks only
709    // the item instead of all the module data.
710    let trait_ast = db.module_trait_by_id(trait_id)?.to_maybe()?;
711
712    let mut function_asts = OrderedHashMap::default();
713    let mut item_type_asts = OrderedHashMap::default();
714    let mut item_constant_asts = OrderedHashMap::default();
715    let mut item_impl_asts = OrderedHashMap::default();
716    let mut item_id_by_name: OrderedHashMap<SmolStr, TraitItemInfo> = OrderedHashMap::default();
717
718    if let ast::MaybeTraitBody::Some(body) = trait_ast.body(syntax_db) {
719        for item in body.items(syntax_db).elements(syntax_db) {
720            match item {
721                ast::TraitItem::Function(func) => {
722                    let trait_func_id =
723                        TraitFunctionLongId(module_file_id, func.stable_ptr()).intern(db);
724                    let name_node = func.declaration(syntax_db).name(syntax_db);
725                    let name = name_node.text(syntax_db);
726                    let attributes = func.attributes(syntax_db);
727                    let feature_kind =
728                        FeatureKind::from_ast(db.upcast(), &mut diagnostics, &attributes);
729                    if item_id_by_name
730                        .insert(
731                            name.clone(),
732                            TraitItemInfo {
733                                id: TraitItemId::Function(trait_func_id),
734                                feature_kind,
735                            },
736                        )
737                        .is_some()
738                    {
739                        diagnostics.report(
740                            &name_node,
741                            SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
742                        );
743                    }
744                    function_asts.insert(trait_func_id, func);
745                }
746                ast::TraitItem::Type(ty) => {
747                    let trait_type_id = TraitTypeLongId(module_file_id, ty.stable_ptr()).intern(db);
748                    let name_node = ty.name(syntax_db);
749                    let name = name_node.text(syntax_db);
750                    let attributes = ty.attributes(syntax_db);
751                    let feature_kind =
752                        FeatureKind::from_ast(db.upcast(), &mut diagnostics, &attributes);
753                    if item_id_by_name
754                        .insert(
755                            name.clone(),
756                            TraitItemInfo { id: TraitItemId::Type(trait_type_id), feature_kind },
757                        )
758                        .is_some()
759                    {
760                        diagnostics.report(
761                            &name_node,
762                            SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
763                        );
764                    }
765                    item_type_asts.insert(trait_type_id, ty);
766                }
767                ast::TraitItem::Constant(constant) => {
768                    let trait_constant =
769                        TraitConstantLongId(module_file_id, constant.stable_ptr()).intern(db);
770
771                    let name_node = constant.name(syntax_db);
772                    let name = name_node.text(syntax_db);
773                    let attributes = constant.attributes(syntax_db);
774                    let feature_kind =
775                        FeatureKind::from_ast(db.upcast(), &mut diagnostics, &attributes);
776                    if item_id_by_name
777                        .insert(
778                            name.clone(),
779                            TraitItemInfo {
780                                id: TraitItemId::Constant(trait_constant),
781                                feature_kind,
782                            },
783                        )
784                        .is_some()
785                    {
786                        diagnostics.report(
787                            &name_node,
788                            SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
789                        );
790                    }
791                    item_constant_asts.insert(trait_constant, constant);
792                }
793                ast::TraitItem::Impl(imp) => {
794                    let trait_impl = TraitImplLongId(module_file_id, imp.stable_ptr()).intern(db);
795
796                    let name_node = imp.name(syntax_db);
797                    let name = name_node.text(syntax_db);
798                    let attributes = imp.attributes(syntax_db);
799                    let feature_kind =
800                        FeatureKind::from_ast(db.upcast(), &mut diagnostics, &attributes);
801                    if item_id_by_name
802                        .insert(
803                            name.clone(),
804                            TraitItemInfo { id: TraitItemId::Impl(trait_impl), feature_kind },
805                        )
806                        .is_some()
807                    {
808                        diagnostics.report(
809                            &name_node,
810                            SemanticDiagnosticKind::NameDefinedMultipleTimes(name),
811                        );
812                    }
813                    item_impl_asts.insert(trait_impl, imp);
814                }
815                ast::TraitItem::Missing(_) => {}
816            }
817        }
818    }
819
820    Ok(TraitDefinitionData {
821        diagnostics: diagnostics.build(),
822        function_asts,
823        item_type_asts,
824        item_constant_asts,
825        item_impl_asts,
826        item_id_by_name: Arc::new(item_id_by_name),
827    })
828}
829
830// === Trait item type ===
831
832#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
833#[debug_db(dyn SemanticGroup + 'static)]
834pub struct TraitItemTypeData {
835    pub diagnostics: Diagnostics<SemanticDiagnostic>,
836    pub generic_params: Vec<semantic::GenericParam>,
837    pub attributes: Vec<Attribute>,
838    pub resolver_data: Arc<ResolverData>,
839}
840
841// --- Selectors ---
842
843/// Query implementation of [crate::db::SemanticGroup::trait_type_diagnostics].
844pub fn trait_type_diagnostics(
845    db: &dyn SemanticGroup,
846    trait_type_id: TraitTypeId,
847) -> Diagnostics<SemanticDiagnostic> {
848    db.priv_trait_type_data(trait_type_id).map(|data| data.diagnostics).unwrap_or_default()
849}
850
851/// Query implementation of [crate::db::SemanticGroup::trait_type_generic_params].
852pub fn trait_type_generic_params(
853    db: &dyn SemanticGroup,
854    trait_type_id: TraitTypeId,
855) -> Maybe<Vec<GenericParam>> {
856    Ok(db.priv_trait_type_generic_params_data(trait_type_id)?.generic_params)
857}
858
859/// Query implementation of [crate::db::SemanticGroup::trait_type_attributes].
860pub fn trait_type_attributes(
861    db: &dyn SemanticGroup,
862    trait_type_id: TraitTypeId,
863) -> Maybe<Vec<Attribute>> {
864    Ok(db.priv_trait_type_data(trait_type_id)?.attributes)
865}
866
867/// Query implementation of [crate::db::SemanticGroup::trait_type_resolver_data].
868pub fn trait_type_resolver_data(
869    db: &dyn SemanticGroup,
870    trait_type_id: TraitTypeId,
871) -> Maybe<Arc<ResolverData>> {
872    Ok(db.priv_trait_type_data(trait_type_id)?.resolver_data)
873}
874
875// --- Computation ---
876
877/// Query implementation of [crate::db::SemanticGroup::priv_trait_type_generic_params_data].
878pub fn priv_trait_type_generic_params_data(
879    db: &dyn SemanticGroup,
880    trait_type_id: TraitTypeId,
881) -> Maybe<GenericParamsData> {
882    let syntax_db = db.upcast();
883    let module_file_id = trait_type_id.module_file_id(db.upcast());
884    let mut diagnostics = SemanticDiagnostics::default();
885    let trait_id = trait_type_id.trait_id(db.upcast());
886    let data = db.priv_trait_definition_data(trait_id)?;
887    let trait_type_ast = &data.item_type_asts[&trait_type_id];
888    let inference_id =
889        InferenceId::LookupItemGenerics(LookupItemId::TraitItem(TraitItemId::Type(trait_type_id)));
890    let parent_resolver_data = db.trait_resolver_data(trait_id)?;
891    let mut resolver =
892        Resolver::with_data(db, parent_resolver_data.clone_with_inference_id(db, inference_id));
893    for trait_generic_param in db.trait_generic_params(trait_id)? {
894        resolver.add_generic_param(trait_generic_param.id());
895    }
896    let generic_params_node = trait_type_ast.generic_params(syntax_db);
897    let type_generic_params = semantic_generic_params(
898        db,
899        &mut diagnostics,
900        &mut resolver,
901        module_file_id,
902        &generic_params_node,
903    );
904    let type_generic_params = resolver.inference().rewrite(type_generic_params).no_err();
905
906    // TODO(yuval): support generics in impls (including validation), then remove this.
907    // Generic parameters are not yet supported, make sure there are none.
908    if !generic_params_node.is_empty(syntax_db) {
909        diagnostics.report(
910            &generic_params_node,
911            GenericsNotSupportedInItem { scope: "Trait".into(), item_kind: "type".into() },
912        );
913    }
914
915    let resolver_data = Arc::new(resolver.data);
916    Ok(GenericParamsData {
917        diagnostics: diagnostics.build(),
918        generic_params: type_generic_params,
919        resolver_data,
920    })
921}
922
923/// Query implementation of [crate::db::SemanticGroup::priv_trait_type_data].
924pub fn priv_trait_type_data(
925    db: &dyn SemanticGroup,
926    trait_type_id: TraitTypeId,
927) -> Maybe<TraitItemTypeData> {
928    let syntax_db = db.upcast();
929    let mut diagnostics = SemanticDiagnostics::default();
930    let trait_id = trait_type_id.trait_id(db.upcast());
931    let data = db.priv_trait_definition_data(trait_id)?;
932    let type_syntax = &data.item_type_asts[&trait_type_id];
933
934    let type_generic_params_data = db.priv_trait_type_generic_params_data(trait_type_id)?;
935    let type_generic_params = type_generic_params_data.generic_params;
936    let inference_id = InferenceId::LookupItemDeclaration(LookupItemId::TraitItem(
937        TraitItemId::Type(trait_type_id),
938    ));
939    let resolver = Resolver::with_data(
940        db,
941        (*type_generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
942    );
943    diagnostics.extend(type_generic_params_data.diagnostics);
944
945    let attributes = type_syntax.attributes(syntax_db).structurize(syntax_db);
946    let resolver_data = Arc::new(resolver.data);
947
948    Ok(TraitItemTypeData {
949        diagnostics: diagnostics.build(),
950        generic_params: type_generic_params,
951        attributes,
952        resolver_data,
953    })
954}
955
956// === Trait item constant ===
957
958#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
959#[debug_db(dyn SemanticGroup + 'static)]
960pub struct TraitItemConstantData {
961    pub diagnostics: Diagnostics<SemanticDiagnostic>,
962    pub ty: TypeId,
963    pub attributes: Vec<Attribute>,
964    pub resolver_data: Arc<ResolverData>,
965}
966
967// --- Selectors ---
968
969/// Query implementation of [crate::db::SemanticGroup::trait_constant_diagnostics].
970pub fn trait_constant_diagnostics(
971    db: &dyn SemanticGroup,
972    trait_constant: TraitConstantId,
973) -> Diagnostics<SemanticDiagnostic> {
974    db.priv_trait_constant_data(trait_constant).map(|data| data.diagnostics).unwrap_or_default()
975}
976
977/// Query implementation of [crate::db::SemanticGroup::trait_constant_resolver_data].
978pub fn trait_constant_resolver_data(
979    db: &dyn SemanticGroup,
980    trait_constant: TraitConstantId,
981) -> Maybe<Arc<ResolverData>> {
982    Ok(db.priv_trait_constant_data(trait_constant)?.resolver_data)
983}
984
985/// Query implementation of [crate::db::SemanticGroup::trait_constant_attributes].
986pub fn trait_constant_attributes(
987    db: &dyn SemanticGroup,
988    trait_constant: TraitConstantId,
989) -> Maybe<Vec<Attribute>> {
990    Ok(db.priv_trait_constant_data(trait_constant)?.attributes)
991}
992
993/// Query implementation of [crate::db::SemanticGroup::trait_constant_type].
994pub fn trait_constant_type(
995    db: &dyn SemanticGroup,
996    trait_constant_id: TraitConstantId,
997) -> Maybe<TypeId> {
998    Ok(db.priv_trait_constant_data(trait_constant_id)?.ty)
999}
1000
1001// --- Computation ---
1002
1003/// Query implementation of [crate::db::SemanticGroup::priv_trait_constant_data].
1004pub fn priv_trait_constant_data(
1005    db: &dyn SemanticGroup,
1006    trait_constant: TraitConstantId,
1007) -> Maybe<TraitItemConstantData> {
1008    let syntax_db = db.upcast();
1009    let mut diagnostics = SemanticDiagnostics::default();
1010    let trait_id = trait_constant.trait_id(db.upcast());
1011    let data = db.priv_trait_definition_data(trait_id)?;
1012    let constant_syntax = &data.item_constant_asts[&trait_constant];
1013    let inference_id = InferenceId::LookupItemDeclaration(LookupItemId::TraitItem(
1014        TraitItemId::Constant(trait_constant),
1015    ));
1016    let parent_resolver_data = db.trait_resolver_data(trait_id)?;
1017    let mut resolver =
1018        Resolver::with_data(db, parent_resolver_data.clone_with_inference_id(db, inference_id));
1019
1020    let ty = resolve_type(
1021        db,
1022        &mut diagnostics,
1023        &mut resolver,
1024        &constant_syntax.type_clause(syntax_db).ty(syntax_db),
1025    );
1026    let attributes = constant_syntax.attributes(syntax_db).structurize(syntax_db);
1027    let resolver_data = Arc::new(resolver.data);
1028
1029    Ok(TraitItemConstantData { diagnostics: diagnostics.build(), ty, attributes, resolver_data })
1030}
1031
1032/// Query implementation of [crate::db::SemanticGroup::concrete_trait_constant_type].
1033pub fn concrete_trait_constant_type(
1034    db: &dyn SemanticGroup,
1035    concrete_trait_constant_id: ConcreteTraitConstantId,
1036) -> Maybe<TypeId> {
1037    let concrete_trait_id = concrete_trait_constant_id.concrete_trait(db);
1038    let substitution = GenericSubstitution::new(
1039        &db.trait_generic_params(concrete_trait_id.trait_id(db))?,
1040        &concrete_trait_id.generic_args(db),
1041    );
1042    let generic_ty = db.trait_constant_type(concrete_trait_constant_id.trait_constant(db))?;
1043    substitution.substitute(db, generic_ty)
1044}
1045
1046// === Trait item impl ===
1047
1048#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
1049#[debug_db(dyn SemanticGroup + 'static)]
1050pub struct TraitItemImplData {
1051    pub diagnostics: Diagnostics<SemanticDiagnostic>,
1052    pub concrete_trait: Maybe<ConcreteTraitId>,
1053    pub attributes: Vec<Attribute>,
1054    pub resolver_data: Arc<ResolverData>,
1055}
1056
1057// --- Selectors ---
1058
1059/// Query implementation of [crate::db::SemanticGroup::trait_impl_diagnostics].
1060pub fn trait_impl_diagnostics(
1061    db: &dyn SemanticGroup,
1062    trait_impl: TraitImplId,
1063) -> Diagnostics<SemanticDiagnostic> {
1064    db.priv_trait_impl_data(trait_impl).map(|data| data.diagnostics).unwrap_or_default()
1065}
1066
1067/// Query implementation of [crate::db::SemanticGroup::trait_impl_resolver_data].
1068pub fn trait_impl_resolver_data(
1069    db: &dyn SemanticGroup,
1070    trait_impl: TraitImplId,
1071) -> Maybe<Arc<ResolverData>> {
1072    Ok(db.priv_trait_impl_data(trait_impl)?.resolver_data)
1073}
1074
1075/// Query implementation of [crate::db::SemanticGroup::trait_impl_attributes].
1076pub fn trait_impl_attributes(
1077    db: &dyn SemanticGroup,
1078    trait_impl: TraitImplId,
1079) -> Maybe<Vec<Attribute>> {
1080    Ok(db.priv_trait_impl_data(trait_impl)?.attributes)
1081}
1082
1083/// Query implementation of [crate::db::SemanticGroup::trait_impl_concrete_trait].
1084pub fn trait_impl_concrete_trait(
1085    db: &dyn SemanticGroup,
1086    trait_impl_id: TraitImplId,
1087) -> Maybe<ConcreteTraitId> {
1088    db.priv_trait_impl_data(trait_impl_id)?.concrete_trait
1089}
1090
1091// --- Computation ---
1092
1093/// Query implementation of [crate::db::SemanticGroup::priv_trait_impl_data].
1094pub fn priv_trait_impl_data(
1095    db: &dyn SemanticGroup,
1096    trait_impl: TraitImplId,
1097) -> Maybe<TraitItemImplData> {
1098    let syntax_db = db.upcast();
1099    let mut diagnostics = SemanticDiagnostics::default();
1100    let trait_id = trait_impl.trait_id(db.upcast());
1101    let data = db.priv_trait_definition_data(trait_id)?;
1102    let impl_syntax = &data.item_impl_asts[&trait_impl];
1103    let trait_path = impl_syntax.trait_path(syntax_db);
1104    let inference_id =
1105        InferenceId::LookupItemDeclaration(LookupItemId::TraitItem(TraitItemId::Impl(trait_impl)));
1106    let parent_resolver_data = db.trait_resolver_data(trait_id)?;
1107    let mut resolver =
1108        Resolver::with_data(db, parent_resolver_data.clone_with_inference_id(db, inference_id));
1109    let concrete_trait = resolver
1110        .resolve_concrete_path(&mut diagnostics, &trait_path, NotFoundItemType::Trait)
1111        .and_then(|resolved_item: crate::resolve::ResolvedConcreteItem| match resolved_item {
1112            ResolvedConcreteItem::Trait(id) | ResolvedConcreteItem::SelfTrait(id) => Ok(id),
1113            _ => Err(diagnostics.report(&trait_path, SemanticDiagnosticKind::UnknownTrait)),
1114        });
1115    let attributes = impl_syntax.attributes(syntax_db).structurize(syntax_db);
1116    let resolver_data = Arc::new(resolver.data);
1117
1118    Ok(TraitItemImplData {
1119        diagnostics: diagnostics.build(),
1120        concrete_trait,
1121        attributes,
1122        resolver_data,
1123    })
1124}
1125
1126/// Query implementation of [crate::db::SemanticGroup::concrete_trait_impl_concrete_trait].
1127pub fn concrete_trait_impl_concrete_trait(
1128    db: &dyn SemanticGroup,
1129    concrete_trait_impl_id: ConcreteTraitImplId,
1130) -> Maybe<ConcreteTraitId> {
1131    let concrete_trait_id = concrete_trait_impl_id.concrete_trait(db);
1132    GenericSubstitution::new(
1133        &db.trait_generic_params(concrete_trait_id.trait_id(db))?,
1134        &concrete_trait_id.generic_args(db),
1135    )
1136    .substitute(db, db.trait_impl_concrete_trait(concrete_trait_impl_id.trait_impl(db))?)
1137}
1138
1139// === Trait function Declaration ===
1140
1141// --- Selectors ---
1142
1143/// Query implementation of [crate::db::SemanticGroup::trait_function_declaration_diagnostics].
1144pub fn trait_function_declaration_diagnostics(
1145    db: &dyn SemanticGroup,
1146    trait_function_id: TraitFunctionId,
1147) -> Diagnostics<SemanticDiagnostic> {
1148    db.priv_trait_function_declaration_data(trait_function_id)
1149        .map(|data| data.diagnostics)
1150        .unwrap_or_default()
1151}
1152
1153/// Query implementation of [crate::db::SemanticGroup::trait_function_signature].
1154pub fn trait_function_signature(
1155    db: &dyn SemanticGroup,
1156    trait_function_id: TraitFunctionId,
1157) -> Maybe<semantic::Signature> {
1158    Ok(db.priv_trait_function_declaration_data(trait_function_id)?.signature)
1159}
1160
1161/// Query implementation of [crate::db::SemanticGroup::trait_function_generic_params].
1162pub fn trait_function_generic_params(
1163    db: &dyn SemanticGroup,
1164    trait_function_id: TraitFunctionId,
1165) -> Maybe<Vec<GenericParam>> {
1166    Ok(db.priv_trait_function_generic_params_data(trait_function_id)?.generic_params)
1167}
1168
1169/// Query implementation of [crate::db::SemanticGroup::priv_trait_function_generic_params_data].
1170pub fn priv_trait_function_generic_params_data(
1171    db: &dyn SemanticGroup,
1172    trait_function_id: TraitFunctionId,
1173) -> Maybe<GenericParamsData> {
1174    let syntax_db = db.upcast();
1175    let module_file_id = trait_function_id.module_file_id(db.upcast());
1176    let mut diagnostics = SemanticDiagnostics::default();
1177    let trait_id = trait_function_id.trait_id(db.upcast());
1178    let data = db.priv_trait_definition_data(trait_id)?;
1179    let function_syntax = &data.function_asts[&trait_function_id];
1180    let declaration = function_syntax.declaration(syntax_db);
1181    let inference_id = InferenceId::LookupItemGenerics(LookupItemId::TraitItem(
1182        TraitItemId::Function(trait_function_id),
1183    ));
1184    let parent_resolver_data = db.trait_resolver_data(trait_id)?;
1185    let mut resolver =
1186        Resolver::with_data(db, parent_resolver_data.clone_with_inference_id(db, inference_id));
1187    let trait_generic_params = db.trait_generic_params(trait_id)?;
1188    for generic_param in trait_generic_params {
1189        resolver.add_generic_param(generic_param.id());
1190    }
1191    let function_generic_params = semantic_generic_params(
1192        db,
1193        &mut diagnostics,
1194        &mut resolver,
1195        module_file_id,
1196        &declaration.generic_params(syntax_db),
1197    );
1198    let function_generic_params = resolver.inference().rewrite(function_generic_params).no_err();
1199    let resolver_data = Arc::new(resolver.data);
1200    Ok(GenericParamsData {
1201        diagnostics: diagnostics.build(),
1202        generic_params: function_generic_params,
1203        resolver_data,
1204    })
1205}
1206
1207/// Query implementation of [crate::db::SemanticGroup::trait_function_attributes].
1208pub fn trait_function_attributes(
1209    db: &dyn SemanticGroup,
1210    trait_function_id: TraitFunctionId,
1211) -> Maybe<Vec<Attribute>> {
1212    Ok(db.priv_trait_function_declaration_data(trait_function_id)?.attributes)
1213}
1214
1215/// Query implementation of [crate::db::SemanticGroup::trait_function_resolver_data].
1216pub fn trait_function_resolver_data(
1217    db: &dyn SemanticGroup,
1218    trait_function_id: TraitFunctionId,
1219) -> Maybe<Arc<ResolverData>> {
1220    Ok(db.priv_trait_function_declaration_data(trait_function_id)?.resolver_data)
1221}
1222
1223/// Query implementation of [crate::db::SemanticGroup::trait_function_declaration_inline_config].
1224pub fn trait_function_declaration_inline_config(
1225    db: &dyn SemanticGroup,
1226    trait_function_id: TraitFunctionId,
1227) -> Maybe<InlineConfiguration> {
1228    Ok(db.priv_trait_function_declaration_data(trait_function_id)?.inline_config)
1229}
1230
1231/// Query implementation of [SemanticGroup::trait_function_declaration_implicit_precedence].
1232pub fn trait_function_declaration_implicit_precedence(
1233    db: &dyn SemanticGroup,
1234    trait_function_id: TraitFunctionId,
1235) -> Maybe<ImplicitPrecedence> {
1236    Ok(db.priv_trait_function_declaration_data(trait_function_id)?.implicit_precedence)
1237}
1238
1239/// Query implementation of [crate::db::SemanticGroup::trait_function_declaration_implicits].
1240pub fn trait_function_declaration_implicits(
1241    db: &dyn SemanticGroup,
1242    trait_function_id: TraitFunctionId,
1243) -> Maybe<Vec<TypeId>> {
1244    Ok(db.priv_trait_function_declaration_data(trait_function_id)?.signature.implicits)
1245}
1246
1247// --- Computation ---
1248
1249/// Query implementation of [crate::db::SemanticGroup::priv_trait_function_declaration_data].
1250pub fn priv_trait_function_declaration_data(
1251    db: &dyn SemanticGroup,
1252    trait_function_id: TraitFunctionId,
1253) -> Maybe<FunctionDeclarationData> {
1254    let syntax_db = db.upcast();
1255    let mut diagnostics = SemanticDiagnostics::default();
1256    let trait_id = trait_function_id.trait_id(db.upcast());
1257    let data = db.priv_trait_definition_data(trait_id)?;
1258    let function_syntax = &data.function_asts[&trait_function_id];
1259    let declaration_syntax = function_syntax.declaration(syntax_db);
1260    let function_generic_params_data =
1261        db.priv_trait_function_generic_params_data(trait_function_id)?;
1262    let function_generic_params = function_generic_params_data.generic_params;
1263    let lookup_item_id = LookupItemId::TraitItem(TraitItemId::Function(trait_function_id));
1264    let inference_id = InferenceId::LookupItemDeclaration(lookup_item_id);
1265    let mut resolver = Resolver::with_data(
1266        db,
1267        (*function_generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
1268    );
1269    diagnostics.extend(function_generic_params_data.diagnostics);
1270    resolver.set_feature_config(&trait_function_id, function_syntax, &mut diagnostics);
1271    let mut environment = Environment::empty();
1272    let signature = semantic::Signature::from_ast(
1273        &mut diagnostics,
1274        db,
1275        &mut resolver,
1276        &declaration_syntax,
1277        FunctionTitleId::Trait(trait_function_id),
1278        &mut environment,
1279    );
1280
1281    // Check fully resolved.
1282    let inference = &mut resolver.inference();
1283    inference.finalize(&mut diagnostics, function_syntax.stable_ptr().untyped());
1284    let signature = inference.rewrite(signature).no_err();
1285    let function_generic_params = inference.rewrite(function_generic_params).no_err();
1286
1287    validate_trait_function_signature(
1288        db,
1289        &mut diagnostics,
1290        trait_id,
1291        trait_function_id,
1292        &signature,
1293        &declaration_syntax.signature(syntax_db),
1294    );
1295
1296    let attributes = function_syntax.attributes(syntax_db).structurize(syntax_db);
1297
1298    let inline_config = get_inline_config(db, &mut diagnostics, &attributes)?;
1299    let (implicit_precedence, _) =
1300        get_implicit_precedence(&mut diagnostics, &mut resolver, &attributes);
1301    let resolver_data = Arc::new(resolver.data);
1302
1303    Ok(FunctionDeclarationData {
1304        diagnostics: diagnostics.build(),
1305        signature,
1306        generic_params: function_generic_params,
1307        environment,
1308        attributes,
1309        resolver_data,
1310        inline_config,
1311        implicit_precedence,
1312    })
1313}
1314
1315fn validate_trait_function_signature(
1316    db: &dyn SemanticGroup,
1317    diagnostics: &mut SemanticDiagnostics,
1318    trait_id: TraitId,
1319    function_id: TraitFunctionId,
1320    sig: &semantic::Signature,
1321    sig_syntax: &ast::FunctionSignature,
1322) {
1323    let syntax_db = db.upcast();
1324    for (idx, param) in sig.params.iter().enumerate() {
1325        if param.mutability == Mutability::Mutable {
1326            diagnostics.report(
1327                &sig_syntax.parameters(syntax_db).elements(syntax_db)[idx].modifiers(syntax_db),
1328                crate::diagnostic::SemanticDiagnosticKind::TraitParamMutable {
1329                    trait_id,
1330                    function_id,
1331                },
1332            );
1333        }
1334    }
1335}
1336
1337// === Concrete Trait Function ===
1338
1339/// Query implementation of [crate::db::SemanticGroup::concrete_trait_function_generic_params].
1340pub fn concrete_trait_function_generic_params(
1341    db: &dyn SemanticGroup,
1342    concrete_trait_function_id: ConcreteTraitGenericFunctionId,
1343) -> Maybe<Vec<GenericParam>> {
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(
1350        db,
1351        db.trait_function_generic_params(concrete_trait_function_id.trait_function(db))?,
1352    )
1353}
1354
1355/// Query implementation of [crate::db::SemanticGroup::concrete_trait_function_signature].
1356pub fn concrete_trait_function_signature(
1357    db: &dyn SemanticGroup,
1358    concrete_trait_function_id: ConcreteTraitGenericFunctionId,
1359) -> Maybe<semantic::Signature> {
1360    let concrete_trait_id = concrete_trait_function_id.concrete_trait(db);
1361    GenericSubstitution::new(
1362        &db.trait_generic_params(concrete_trait_id.trait_id(db))?,
1363        &concrete_trait_id.generic_args(db),
1364    )
1365    .substitute(db, db.trait_function_signature(concrete_trait_function_id.trait_function(db))?)
1366}
1367
1368// === Body ===
1369
1370// --- Selectors ---
1371
1372/// Query implementation of [crate::db::SemanticGroup::trait_function_body_diagnostics].
1373pub fn trait_function_body_diagnostics(
1374    db: &dyn SemanticGroup,
1375    trait_function_id: TraitFunctionId,
1376) -> Diagnostics<SemanticDiagnostic> {
1377    db.priv_trait_function_body_data(trait_function_id)
1378        .map(|data| match data {
1379            Some(data) => data.diagnostics,
1380            None => Diagnostics::<SemanticDiagnostic>::new(),
1381        })
1382        .unwrap_or_default()
1383}
1384
1385/// Query implementation of [crate::db::SemanticGroup::trait_function_body].
1386pub fn trait_function_body(
1387    db: &dyn SemanticGroup,
1388    trait_function_id: TraitFunctionId,
1389) -> Maybe<Option<Arc<FunctionBody>>> {
1390    Ok(match db.priv_trait_function_body_data(trait_function_id)? {
1391        Some(body_data) => Some(body_data.body),
1392        None => None,
1393    })
1394}
1395
1396// --- Computation ---
1397
1398/// Query implementation of [crate::db::SemanticGroup::priv_trait_function_body_data].
1399pub fn priv_trait_function_body_data(
1400    db: &dyn SemanticGroup,
1401    trait_function_id: TraitFunctionId,
1402) -> Maybe<Option<FunctionBodyData>> {
1403    let defs_db = db.upcast();
1404    let mut diagnostics = SemanticDiagnostics::default();
1405    let trait_id = trait_function_id.trait_id(defs_db);
1406    let data = db.priv_trait_definition_data(trait_id)?;
1407    let function_syntax = &data.function_asts[&trait_function_id];
1408    // Compute declaration semantic.
1409    let trait_function_declaration_data =
1410        db.priv_trait_function_declaration_data(trait_function_id)?;
1411    let parent_resolver_data = trait_function_declaration_data.resolver_data;
1412    let inference_id = InferenceId::LookupItemDefinition(LookupItemId::TraitItem(
1413        TraitItemId::Function(trait_function_id),
1414    ));
1415    let mut resolver =
1416        Resolver::with_data(db, (*parent_resolver_data).clone_with_inference_id(db, inference_id));
1417    resolver.trait_or_impl_ctx = TraitOrImplContext::Trait(trait_id);
1418    let environment = trait_function_declaration_data.environment;
1419
1420    let function_id = (|| {
1421        let generic_parameters = db.trait_generic_params(trait_id)?;
1422        let concrete_trait = ConcreteTraitLongId {
1423            trait_id,
1424            generic_args: generic_params_to_args(&generic_parameters, db),
1425        }
1426        .intern(db);
1427        let generic_function = GenericFunctionId::Impl(ImplGenericFunctionId {
1428            impl_id: ImplLongId::SelfImpl(concrete_trait).intern(db),
1429            function: trait_function_id,
1430        });
1431
1432        Ok(FunctionLongId::from_generic(db, generic_function)?.intern(db))
1433    })();
1434    // Compute body semantic expr.
1435    let mut ctx = ComputationContext::new(
1436        db,
1437        &mut diagnostics,
1438        resolver,
1439        Some(&trait_function_declaration_data.signature),
1440        environment,
1441        ContextFunction::Function(function_id),
1442    );
1443    let function_body = match function_syntax.body(db.upcast()) {
1444        ast::MaybeTraitFunctionBody::Some(expr_block) => expr_block,
1445        ast::MaybeTraitFunctionBody::None(_) => return Ok(None),
1446    };
1447    let return_type = trait_function_declaration_data.signature.return_type;
1448    let body_expr = compute_root_expr(&mut ctx, &function_body, return_type)?;
1449    let ComputationContext { arenas: Arenas { exprs, patterns, statements }, resolver, .. } = ctx;
1450
1451    let expr_lookup: UnorderedHashMap<_, _> =
1452        exprs.iter().map(|(expr_id, expr)| (expr.stable_ptr(), expr_id)).collect();
1453    let pattern_lookup: UnorderedHashMap<_, _> =
1454        patterns.iter().map(|(pattern_id, pattern)| (pattern.stable_ptr(), pattern_id)).collect();
1455    let resolver_data = Arc::new(resolver.data);
1456    Ok(Some(FunctionBodyData {
1457        diagnostics: diagnostics.build(),
1458        expr_lookup,
1459        pattern_lookup,
1460        resolver_data,
1461        body: Arc::new(FunctionBody { arenas: Arenas { exprs, patterns, statements }, body_expr }),
1462    }))
1463}