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 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 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#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
124#[debug_db(dyn SemanticGroup + 'static)]
125pub struct ConcreteTraitGenericFunctionLongId {
126 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#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
177#[debug_db(dyn SemanticGroup + 'static)]
178pub struct ConcreteTraitTypeLongId {
179 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#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
230#[debug_db(dyn SemanticGroup + 'static)]
231pub struct ConcreteTraitConstantLongId {
232 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#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
283#[debug_db(dyn SemanticGroup + 'static)]
284pub struct ConcreteTraitImplLongId {
285 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#[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
345pub 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
355pub 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}
359pub fn trait_generic_params_cycle(
361 db: &dyn SemanticGroup,
362 _cycle: &salsa::Cycle,
363 trait_id: &TraitId,
364) -> Maybe<Vec<GenericParam>> {
365 Ok(db.trait_generic_params_data(*trait_id, true)?.generic_params)
367}
368
369pub 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 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}
401pub 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 trait_generic_params_data(db, *trait_id, true)
410}
411pub fn trait_attributes(db: &dyn SemanticGroup, trait_id: TraitId) -> Maybe<Vec<Attribute>> {
413 Ok(db.priv_trait_declaration_data(trait_id)?.attributes)
414}
415
416pub 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
421pub 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 let trait_ast = db.module_trait_by_id(trait_id)?.to_maybe()?;
434
435 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 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#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
467#[debug_db(dyn SemanticGroup + 'static)]
468pub struct TraitDefinitionData {
469 diagnostics: Diagnostics<SemanticDiagnostic>,
474
475 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 item_id_by_name: Arc<OrderedHashMap<SmolStr, TraitItemInfo>>,
483}
484
485impl TraitDefinitionData {
486 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#[derive(Clone, Debug, PartialEq, Eq)]
493pub struct TraitItemInfo {
494 pub id: TraitItemId,
496 pub feature_kind: FeatureKind,
498}
499
500impl HasFeatureKind for TraitItemInfo {
501 fn feature_kind(&self) -> &FeatureKind {
503 &self.feature_kind
504 }
505}
506
507pub 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 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
540pub 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
561pub 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
570pub 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
580pub 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
595pub 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
611pub 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
620pub 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
636pub 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
645pub 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
661pub 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
670pub 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
686pub 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
695pub 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 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#[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
841pub 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
851pub 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
859pub 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
867pub 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
875pub 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 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
923pub 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#[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
967pub 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
977pub 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
985pub 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
993pub 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
1001pub 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
1032pub 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#[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
1057pub 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
1067pub 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
1075pub 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
1083pub 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
1091pub 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
1126pub 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
1139pub 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
1153pub 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
1161pub 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
1169pub 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
1207pub 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
1215pub 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
1223pub 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
1231pub 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
1239pub 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
1247pub 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 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
1337pub 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
1355pub 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
1368pub 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
1385pub 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
1396pub 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 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 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}