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 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 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#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
130#[debug_db(dyn SemanticGroup + 'static)]
131pub struct ConcreteTraitGenericFunctionLongId {
132 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#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
183#[debug_db(dyn SemanticGroup + 'static)]
184pub struct ConcreteTraitTypeLongId {
185 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#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
236#[debug_db(dyn SemanticGroup + 'static)]
237pub struct ConcreteTraitConstantLongId {
238 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#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
289#[debug_db(dyn SemanticGroup + 'static)]
290pub struct ConcreteTraitImplLongId {
291 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#[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
351pub 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
361pub 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}
365pub fn trait_generic_params_cycle(
367 db: &dyn SemanticGroup,
368 _cycle: &salsa::Cycle,
369 trait_id: &TraitId,
370) -> Maybe<Vec<GenericParam>> {
371 Ok(db.trait_generic_params_data(*trait_id, true)?.generic_params)
373}
374
375pub 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 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}
407pub 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 trait_generic_params_data(db, *trait_id, true)
416}
417pub fn trait_attributes(db: &dyn SemanticGroup, trait_id: TraitId) -> Maybe<Vec<Attribute>> {
419 Ok(db.priv_trait_declaration_data(trait_id)?.attributes)
420}
421
422pub 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
427pub 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 let trait_ast = db.module_trait_by_id(trait_id)?.to_maybe()?;
440
441 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 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#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
473#[debug_db(dyn SemanticGroup + 'static)]
474pub struct TraitDefinitionData {
475 diagnostics: Diagnostics<SemanticDiagnostic>,
480
481 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 item_id_by_name: Arc<OrderedHashMap<SmolStr, TraitItemId>>,
489}
490
491pub 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 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
524pub 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
545pub 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
554pub 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
569pub 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
585pub 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
594pub 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
610pub 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
619pub 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
635pub 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
644pub 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
660pub 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
669pub 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 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#[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
783pub 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
793pub 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
801pub 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
809pub 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
817pub 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 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
865pub 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#[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
909pub 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
919pub 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
927pub 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
935pub 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
943pub 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
974pub 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#[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
999pub 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
1009pub 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
1017pub 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
1025pub 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
1033pub 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
1069pub 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
1084pub 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
1098pub 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
1106pub 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
1114pub 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
1152pub 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
1160pub 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
1168pub 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
1176pub 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
1184pub 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
1192pub 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 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
1283pub 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
1301pub 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
1316pub 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
1333pub 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
1344pub 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 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 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}