1use std::iter::Peekable;
2use std::marker::PhantomData;
3use std::ops::{Deref, DerefMut};
4use std::sync::Arc;
5
6use cairo_lang_defs::ids::{
7 GenericKind, GenericParamId, GenericTypeId, ImplDefId, LanguageElementId, LookupItemId,
8 ModuleFileId, ModuleId, ModuleItemId, TopLevelLanguageElementId, TraitId, TraitItemId,
9 VariantId,
10};
11use cairo_lang_diagnostics::{Maybe, skip_diagnostic};
12use cairo_lang_filesystem::db::{CORELIB_CRATE_NAME, CrateSettings};
13use cairo_lang_filesystem::ids::{CrateId, CrateLongId};
14use cairo_lang_proc_macros::DebugWithDb;
15use cairo_lang_syntax as syntax;
16use cairo_lang_syntax::node::ast::TerminalIdentifier;
17use cairo_lang_syntax::node::helpers::PathSegmentEx;
18use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
19use cairo_lang_syntax::node::{Terminal, TypedSyntaxNode, ast};
20use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
21use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
22use cairo_lang_utils::unordered_hash_map::UnorderedHashMap;
23use cairo_lang_utils::{Intern, LookupIntern, extract_matches, require, try_extract_matches};
24pub use item::{ResolvedConcreteItem, ResolvedGenericItem};
25use itertools::Itertools;
26use smol_str::SmolStr;
27use syntax::node::TypedStablePtr;
28use syntax::node::db::SyntaxGroup;
29use syntax::node::helpers::QueryAttrs;
30
31use crate::corelib::{core_submodule, get_submodule};
32use crate::db::SemanticGroup;
33use crate::diagnostic::SemanticDiagnosticKind::{self, *};
34use crate::diagnostic::{NotFoundItemType, SemanticDiagnostics, SemanticDiagnosticsBuilder};
35use crate::expr::compute::{
36 ComputationContext, ContextFunction, Environment, compute_expr_semantic,
37 get_statement_item_by_name,
38};
39use crate::expr::inference::canonic::ResultNoErrEx;
40use crate::expr::inference::conform::InferenceConform;
41use crate::expr::inference::infers::InferenceEmbeddings;
42use crate::expr::inference::{Inference, InferenceData, InferenceId};
43use crate::items::constant::{ConstValue, ImplConstantId, resolve_const_expr_and_evaluate};
44use crate::items::enm::SemanticEnumEx;
45use crate::items::feature_kind::{
46 FeatureConfig, FeatureKind, HasFeatureKind, extract_feature_config,
47};
48use crate::items::functions::{GenericFunctionId, ImplGenericFunctionId};
49use crate::items::generics::generic_params_to_args;
50use crate::items::imp::{
51 ConcreteImplId, ConcreteImplLongId, DerefInfo, ImplImplId, ImplLongId, ImplLookupContext,
52};
53use crate::items::module::ModuleItemInfo;
54use crate::items::trt::{
55 ConcreteTraitConstantLongId, ConcreteTraitGenericFunctionLongId, ConcreteTraitId,
56 ConcreteTraitImplLongId, ConcreteTraitLongId, ConcreteTraitTypeId,
57};
58use crate::items::{TraitOrImplContext, visibility};
59use crate::keyword::{CRATE_KW, SELF_TYPE_KW, SUPER_KW};
60use crate::substitution::{GenericSubstitution, SemanticRewriter};
61use crate::types::{ConcreteEnumLongId, ImplTypeId, are_coupons_enabled, resolve_type};
62use crate::{
63 ConcreteFunction, ConcreteTypeId, ConcreteVariant, FunctionId, FunctionLongId,
64 GenericArgumentId, GenericParam, Member, Mutability, TypeId, TypeLongId,
65};
66
67#[cfg(test)]
68mod test;
69
70mod item;
71
72const STARKNET_CRATE_NAME: &str = "starknet";
74
75#[derive(Clone, Default, Debug, PartialEq, Eq, DebugWithDb)]
78#[debug_db(dyn SemanticGroup + 'static)]
79pub struct ResolvedItems {
80 pub concrete: UnorderedHashMap<ast::TerminalIdentifierPtr, ResolvedConcreteItem>,
81 pub generic: UnorderedHashMap<ast::TerminalIdentifierPtr, ResolvedGenericItem>,
82}
83impl ResolvedItems {
84 pub fn mark_concrete(
87 &mut self,
88 db: &dyn SemanticGroup,
89 segment: &syntax::node::ast::PathSegment,
90 resolved_item: ResolvedConcreteItem,
91 ) -> ResolvedConcreteItem {
92 let identifier = segment.identifier_ast(db);
93 if let Some(generic_item) = resolved_item.generic(db) {
94 self.generic.insert(identifier.stable_ptr(db), generic_item);
96 }
97 self.concrete.insert(identifier.stable_ptr(db), resolved_item.clone());
98 resolved_item
99 }
100 pub fn mark_generic(
103 &mut self,
104 db: &dyn SemanticGroup,
105 segment: &syntax::node::ast::PathSegment,
106 resolved_item: ResolvedGenericItem,
107 ) -> ResolvedGenericItem {
108 let identifier = segment.identifier_ast(db);
109 self.generic.insert(identifier.stable_ptr(db), resolved_item.clone());
110 resolved_item
111 }
112}
113
114#[derive(Debug, PartialEq, Eq, DebugWithDb, Clone)]
117#[debug_db(dyn SemanticGroup + 'static)]
118pub struct EnrichedMembers {
119 pub members: OrderedHashMap<SmolStr, (Member, usize)>,
122 pub deref_chain: Arc<[DerefInfo]>,
124 pub explored_derefs: usize,
126}
127impl EnrichedMembers {
128 pub fn get_member(&self, name: &str) -> Option<EnrichedTypeMemberAccess> {
130 let (member, n_derefs) = self.members.get(name)?;
131 Some(EnrichedTypeMemberAccess {
132 member: member.clone(),
133 deref_functions: self
134 .deref_chain
135 .iter()
136 .map(|deref_info| (deref_info.function_id, deref_info.self_mutability))
137 .take(*n_derefs)
138 .collect(),
139 })
140 }
141}
142
143pub struct EnrichedTypeMemberAccess {
146 pub member: Member,
148 pub deref_functions: Vec<(FunctionId, Mutability)>,
150}
151
152#[derive(Debug, PartialEq, Eq, DebugWithDb)]
153#[debug_db(dyn SemanticGroup + 'static)]
154pub struct ResolverData {
155 pub module_file_id: ModuleFileId,
157 generic_param_by_name: OrderedHashMap<SmolStr, GenericParamId>,
159 pub generic_params: Vec<GenericParamId>,
161 pub type_enriched_members: OrderedHashMap<(TypeId, bool), EnrichedMembers>,
163 pub resolved_items: ResolvedItems,
165 pub inference_data: InferenceData,
167 pub trait_or_impl_ctx: TraitOrImplContext,
169 pub feature_config: FeatureConfig,
171 pub used_items: OrderedHashSet<LookupItemId>,
173}
174impl ResolverData {
175 pub fn new(module_file_id: ModuleFileId, inference_id: InferenceId) -> Self {
176 Self {
177 module_file_id,
178 generic_param_by_name: Default::default(),
179 generic_params: Default::default(),
180 type_enriched_members: Default::default(),
181 resolved_items: Default::default(),
182 inference_data: InferenceData::new(inference_id),
183 trait_or_impl_ctx: TraitOrImplContext::None,
184 feature_config: Default::default(),
185 used_items: Default::default(),
186 }
187 }
188 pub fn clone_with_inference_id(
189 &self,
190 db: &dyn SemanticGroup,
191 inference_id: InferenceId,
192 ) -> Self {
193 Self {
194 module_file_id: self.module_file_id,
195 generic_param_by_name: self.generic_param_by_name.clone(),
196 generic_params: self.generic_params.clone(),
197 type_enriched_members: self.type_enriched_members.clone(),
198 resolved_items: self.resolved_items.clone(),
199 inference_data: self.inference_data.clone_with_inference_id(db, inference_id),
200 trait_or_impl_ctx: self.trait_or_impl_ctx,
201 feature_config: self.feature_config.clone(),
202 used_items: self.used_items.clone(),
203 }
204 }
205}
206
207pub struct Resolver<'db> {
209 db: &'db dyn SemanticGroup,
210 pub data: ResolverData,
211 pub owning_crate_id: CrateId,
212 pub settings: CrateSettings,
213}
214impl Deref for Resolver<'_> {
215 type Target = ResolverData;
216
217 fn deref(&self) -> &Self::Target {
218 &self.data
219 }
220}
221impl DerefMut for Resolver<'_> {
222 fn deref_mut(&mut self) -> &mut Self::Target {
223 &mut self.data
224 }
225}
226impl Resolver<'_> {
227 pub fn set_feature_config(
230 &mut self,
231 element_id: &impl LanguageElementId,
232 syntax: &impl QueryAttrs,
233 diagnostics: &mut SemanticDiagnostics,
234 ) {
235 self.feature_config = extract_feature_config(self.db, element_id, syntax, diagnostics);
236 }
237}
238
239pub enum ResolutionContext<'a> {
240 Default,
242 ModuleItem(ModuleItemId),
244 Statement(&'a mut Environment),
246}
247
248enum UseStarResult {
250 UniquePathFound(ModuleItemInfo),
252 AmbiguousPath(Vec<ModuleItemId>),
254 PathNotFound,
256 ItemNotVisible(ModuleItemId, Vec<ModuleId>),
258}
259
260pub trait AsSegments {
262 fn to_segments(self, db: &dyn SyntaxGroup) -> Vec<ast::PathSegment>;
263}
264impl AsSegments for &ast::ExprPath {
265 fn to_segments(self, db: &dyn SyntaxGroup) -> Vec<ast::PathSegment> {
266 self.elements(db)
267 }
268}
269impl AsSegments for Vec<ast::PathSegment> {
270 fn to_segments(self, _: &dyn SyntaxGroup) -> Vec<ast::PathSegment> {
271 self
272 }
273}
274
275impl<'db> Resolver<'db> {
276 pub fn new(
277 db: &'db dyn SemanticGroup,
278 module_file_id: ModuleFileId,
279 inference_id: InferenceId,
280 ) -> Self {
281 Self::with_data(db, ResolverData::new(module_file_id, inference_id))
282 }
283
284 pub fn with_data(db: &'db dyn SemanticGroup, data: ResolverData) -> Self {
285 let owning_crate_id = data.module_file_id.0.owning_crate(db);
286 let settings = db.crate_config(owning_crate_id).map(|c| c.settings).unwrap_or_default();
287 Self { owning_crate_id, settings, db, data }
288 }
289
290 pub fn inference(&mut self) -> Inference<'_> {
291 self.data.inference_data.inference(self.db)
292 }
293
294 pub fn add_generic_param(&mut self, generic_param_id: GenericParamId) {
298 self.generic_params.push(generic_param_id);
299 if let Some(name) = generic_param_id.name(self.db) {
300 self.generic_param_by_name.insert(name, generic_param_id);
301 }
302 }
303
304 fn resolve_path_inner<ResolvedItem: Clone>(
307 &mut self,
308 diagnostics: &mut SemanticDiagnostics,
309 path: impl AsSegments,
310 item_type: NotFoundItemType,
311 mut callbacks: ResolvePathInnerCallbacks<
312 ResolvedItem,
313 impl FnOnce(
314 &mut Resolver<'_>,
315 &mut SemanticDiagnostics,
316 &mut Peekable<std::slice::Iter<'_, ast::PathSegment>>,
317 ) -> Maybe<ResolvedItem>,
318 impl FnMut(
319 &mut Resolver<'_>,
320 &mut SemanticDiagnostics,
321 &ResolvedItem,
322 &ast::PathSegment,
323 NotFoundItemType,
324 ) -> Maybe<ResolvedItem>,
325 impl FnMut(&mut SemanticDiagnostics, &ast::PathSegment) -> Maybe<()>,
326 impl FnMut(
327 &mut ResolvedItems,
328 &dyn SemanticGroup,
329 &syntax::node::ast::PathSegment,
330 ResolvedItem,
331 ),
332 >,
333 ) -> Maybe<ResolvedItem> {
334 let db = self.db;
335 let elements_vec = path.to_segments(db);
336 let mut segments = elements_vec.iter().peekable();
337
338 let mut item: ResolvedItem =
340 (callbacks.resolve_path_first_segment)(self, diagnostics, &mut segments)?;
341
342 while let Some(segment) = segments.next() {
344 (callbacks.validate_segment)(diagnostics, segment)?;
345
346 let cur_item_type =
349 if segments.peek().is_some() { NotFoundItemType::Identifier } else { item_type };
350 item = (callbacks.resolve_path_next_segment)(
353 self,
354 diagnostics,
355 &item,
356 segment,
357 cur_item_type,
358 )?;
359 (callbacks.mark)(&mut self.resolved_items, db, segment, item.clone());
360 }
361 Ok(item)
362 }
363
364 pub fn resolve_concrete_path(
368 &mut self,
369 diagnostics: &mut SemanticDiagnostics,
370 path: impl AsSegments,
371 item_type: NotFoundItemType,
372 ) -> Maybe<ResolvedConcreteItem> {
373 self.resolve_concrete_path_ex(diagnostics, path, item_type, ResolutionContext::Default)
374 }
375
376 pub fn resolve_concrete_path_ex(
379 &mut self,
380 diagnostics: &mut SemanticDiagnostics,
381 path: impl AsSegments,
382 item_type: NotFoundItemType,
383 ctx: ResolutionContext<'_>,
384 ) -> Maybe<ResolvedConcreteItem> {
385 self.resolve_path_inner::<ResolvedConcreteItem>(
386 diagnostics,
387 path,
388 item_type,
389 ResolvePathInnerCallbacks {
390 resolved_item_type: PhantomData,
391 resolve_path_first_segment: |resolver, diagnostics, segments| {
392 resolver.resolve_concrete_path_first_segment(diagnostics, segments, ctx)
393 },
394 resolve_path_next_segment: |resolver, diagnostics, item, segment, item_type| {
395 resolver.resolve_path_next_segment_concrete(
396 diagnostics,
397 item,
398 segment,
399 item_type,
400 )
401 },
402 validate_segment: |_, _| Ok(()),
403 mark: |resolved_items, db, segment, item| {
404 resolved_items.mark_concrete(db, segment, item);
405 },
406 },
407 )
408 }
409
410 fn specialize_generic_inner_item(
412 &mut self,
413 diagnostics: &mut SemanticDiagnostics,
414 module_id: ModuleId,
415 identifier: &TerminalIdentifier,
416 inner_item_info: ModuleItemInfo,
417 segment: &ast::PathSegment,
418 ) -> Maybe<ResolvedConcreteItem> {
419 let db = self.db;
420 let generic_args_syntax = segment.generic_args(db);
421 let segment_stable_ptr = segment.stable_ptr(db).untyped();
422 self.validate_module_item_usability(diagnostics, module_id, identifier, &inner_item_info);
423 self.data.used_items.insert(LookupItemId::ModuleItem(inner_item_info.item_id));
424 let inner_generic_item =
425 ResolvedGenericItem::from_module_item(self.db, inner_item_info.item_id)?;
426 let mut specialized_item = self.specialize_generic_module_item(
427 diagnostics,
428 identifier,
429 inner_generic_item.clone(),
430 generic_args_syntax.clone(),
431 )?;
432 self.data.resolved_items.generic.insert(identifier.stable_ptr(db), inner_generic_item);
433 self.handle_same_impl_trait(
434 diagnostics,
435 &mut specialized_item,
436 &generic_args_syntax.unwrap_or_default(),
437 segment_stable_ptr,
438 );
439 Ok(specialized_item)
440 }
441
442 fn resolve_concrete_path_first_segment(
444 &mut self,
445 diagnostics: &mut SemanticDiagnostics,
446 segments: &mut Peekable<std::slice::Iter<'_, ast::PathSegment>>,
447 ctx: ResolutionContext<'_>,
448 ) -> Maybe<ResolvedConcreteItem> {
449 if let Some(base_module) = self.try_handle_super_segments(
450 diagnostics,
451 segments,
452 |resolved_items, db, segment, module_id| {
453 resolved_items.mark_concrete(db, segment, ResolvedConcreteItem::Module(module_id));
454 },
455 ) {
456 return Ok(ResolvedConcreteItem::Module(base_module?));
457 }
458
459 let db = self.db;
460 Ok(match segments.peek().unwrap() {
461 syntax::node::ast::PathSegment::WithGenericArgs(generic_segment) => {
462 let identifier = generic_segment.ident(db);
463 match self.determine_base(&identifier, ctx) {
465 ResolvedBase::Module(module_id) => ResolvedConcreteItem::Module(module_id),
466 ResolvedBase::Crate(_) => {
467 return Err(diagnostics.report(
469 generic_segment.generic_args(db).stable_ptr(db),
470 UnexpectedGenericArgs,
471 ));
472 }
473 ResolvedBase::StatementEnvironment(generic_item) => {
474 let segment = segments.next().unwrap();
475 let concrete_item = self.specialize_generic_statement_arg(
476 segment,
477 diagnostics,
478 &identifier,
479 generic_item,
480 segment.generic_args(db),
481 );
482 self.resolved_items.mark_concrete(db, segment, concrete_item)
483 }
484 ResolvedBase::FoundThroughGlobalUse {
485 item_info: inner_module_item,
486 containing_module: module_id,
487 } => {
488 let segment = segments.next().unwrap();
489
490 let concrete_item = self.specialize_generic_inner_item(
491 diagnostics,
492 module_id,
493 &identifier,
494 inner_module_item,
495 segment,
496 )?;
497 self.resolved_items.mark_concrete(db, segment, concrete_item)
498 }
499 ResolvedBase::Ambiguous(module_items) => {
500 return Err(diagnostics
501 .report(identifier.stable_ptr(db), AmbiguousPath(module_items)));
502 }
503 ResolvedBase::ItemNotVisible(module_item_id, containing_modules) => {
504 return Err(diagnostics.report(
505 identifier.stable_ptr(db),
506 ItemNotVisible(module_item_id, containing_modules),
507 ));
508 }
509 }
510 }
511 syntax::node::ast::PathSegment::Simple(simple_segment) => {
512 let identifier = simple_segment.ident(db);
513
514 if let Some(resolved_item) =
515 resolve_self_segment(db, diagnostics, &identifier, &self.data.trait_or_impl_ctx)
516 {
517 return Ok(self.resolved_items.mark_concrete(
519 db,
520 segments.next().unwrap(),
521 resolved_item?,
522 ));
523 }
524
525 if let Some(local_item) = self.determine_base_item_in_local_scope(&identifier) {
526 self.resolved_items.mark_concrete(db, segments.next().unwrap(), local_item)
527 } else {
528 match self.determine_base(&identifier, ctx) {
529 ResolvedBase::Module(module_id) => ResolvedConcreteItem::Module(module_id),
531 ResolvedBase::Crate(crate_id) => self.resolved_items.mark_concrete(
532 db,
533 segments.next().unwrap(),
534 ResolvedConcreteItem::Module(ModuleId::CrateRoot(crate_id)),
535 ),
536 ResolvedBase::StatementEnvironment(generic_item) => {
537 let segment = segments.next().unwrap();
538
539 let concrete_item = self.specialize_generic_statement_arg(
540 segment,
541 diagnostics,
542 &identifier,
543 generic_item,
544 segment.generic_args(db),
545 );
546 self.resolved_items.mark_concrete(db, segment, concrete_item)
547 }
548 ResolvedBase::FoundThroughGlobalUse {
549 item_info: inner_module_item,
550 containing_module: module_id,
551 } => {
552 let segment = segments.next().unwrap();
553 let concrete_item = self.specialize_generic_inner_item(
554 diagnostics,
555 module_id,
556 &identifier,
557 inner_module_item,
558 segment,
559 )?;
560 self.resolved_items.mark_concrete(db, segment, concrete_item)
561 }
562 ResolvedBase::Ambiguous(module_items) => {
563 return Err(diagnostics
564 .report(identifier.stable_ptr(db), AmbiguousPath(module_items)));
565 }
566 ResolvedBase::ItemNotVisible(module_item_id, containing_modules) => {
567 return Err(diagnostics.report(
568 identifier.stable_ptr(db),
569 ItemNotVisible(module_item_id, containing_modules),
570 ));
571 }
572 }
573 }
574 }
575 syntax::node::ast::PathSegment::Missing(_) => {
576 return Err(skip_diagnostic());
579 }
580 })
581 }
582
583 pub fn resolve_generic_path(
586 &mut self,
587 diagnostics: &mut SemanticDiagnostics,
588 path: impl AsSegments,
589 item_type: NotFoundItemType,
590 ctx: ResolutionContext<'_>,
591 ) -> Maybe<ResolvedGenericItem> {
592 self.resolve_generic_path_inner(diagnostics, path, item_type, false, ctx)
593 }
594 pub fn resolve_generic_path_with_args(
597 &mut self,
598 diagnostics: &mut SemanticDiagnostics,
599 path: impl AsSegments,
600 item_type: NotFoundItemType,
601 ) -> Maybe<ResolvedGenericItem> {
602 self.resolve_generic_path_inner(
603 diagnostics,
604 path,
605 item_type,
606 true,
607 ResolutionContext::Default,
608 )
609 }
610
611 fn resolve_generic_path_inner(
616 &mut self,
617 diagnostics: &mut SemanticDiagnostics,
618 path: impl AsSegments,
619 item_type: NotFoundItemType,
620 allow_generic_args: bool,
621 ctx: ResolutionContext<'_>,
622 ) -> Maybe<ResolvedGenericItem> {
623 let validate_segment =
624 |diagnostics: &mut SemanticDiagnostics, segment: &ast::PathSegment| match segment {
625 ast::PathSegment::WithGenericArgs(generic_args) if !allow_generic_args => {
626 Err(diagnostics.report(generic_args.stable_ptr(self.db), UnexpectedGenericArgs))
627 }
628 _ => Ok(()),
629 };
630 self.resolve_path_inner::<ResolvedGenericItem>(
631 diagnostics,
632 path,
633 item_type,
634 ResolvePathInnerCallbacks {
635 resolved_item_type: PhantomData,
636 resolve_path_first_segment: |resolver, diagnostics, segments| {
637 resolver.resolve_generic_path_first_segment(
638 diagnostics,
639 segments,
640 allow_generic_args,
641 ctx,
642 )
643 },
644 resolve_path_next_segment: |resolver, diagnostics, item, segment, item_type| {
645 let identifier = segment.identifier_ast(self.db);
646 resolver.resolve_path_next_segment_generic(
647 diagnostics,
648 item,
649 &identifier,
650 item_type,
651 )
652 },
653 validate_segment,
654 mark: |resolved_items, db, segment, item| {
655 resolved_items.mark_generic(db, segment, item);
656 },
657 },
658 )
659 }
660
661 fn resolve_generic_path_first_segment(
664 &mut self,
665 diagnostics: &mut SemanticDiagnostics,
666 segments: &mut Peekable<std::slice::Iter<'_, ast::PathSegment>>,
667 allow_generic_args: bool,
668 ctx: ResolutionContext<'_>,
669 ) -> Maybe<ResolvedGenericItem> {
670 if let Some(base_module) = self.try_handle_super_segments(
671 diagnostics,
672 segments,
673 |resolved_items, db, segment, module_id| {
674 resolved_items.mark_generic(db, segment, ResolvedGenericItem::Module(module_id));
675 },
676 ) {
677 return Ok(ResolvedGenericItem::Module(base_module?));
678 }
679 let db = self.db;
680 Ok(match segments.peek().unwrap() {
681 syntax::node::ast::PathSegment::WithGenericArgs(generic_segment) => {
682 if !allow_generic_args {
683 return Err(diagnostics.report(
684 generic_segment.generic_args(db).stable_ptr(db),
685 UnexpectedGenericArgs,
686 ));
687 }
688 let identifier = generic_segment.ident(db);
689 match self.determine_base(&identifier, ctx) {
691 ResolvedBase::Module(module_id) => ResolvedGenericItem::Module(module_id),
692 ResolvedBase::Crate(_) => {
693 return Err(diagnostics.report(
695 generic_segment.generic_args(db).stable_ptr(db),
696 UnexpectedGenericArgs,
697 ));
698 }
699 ResolvedBase::StatementEnvironment(generic_item) => generic_item,
700 ResolvedBase::FoundThroughGlobalUse {
701 item_info: inner_module_item, ..
702 } => {
703 self.data
704 .used_items
705 .insert(LookupItemId::ModuleItem(inner_module_item.item_id));
706 let generic_item = ResolvedGenericItem::from_module_item(
707 self.db,
708 inner_module_item.item_id,
709 )?;
710 self.resolved_items.mark_generic(db, segments.next().unwrap(), generic_item)
711 }
712 ResolvedBase::Ambiguous(module_items) => {
713 return Err(diagnostics
714 .report(identifier.stable_ptr(db), AmbiguousPath(module_items)));
715 }
716 ResolvedBase::ItemNotVisible(module_item_id, containing_modules) => {
717 return Err(diagnostics.report(
718 identifier.stable_ptr(db),
719 ItemNotVisible(module_item_id, containing_modules),
720 ));
721 }
722 }
723 }
724 syntax::node::ast::PathSegment::Simple(simple_segment) => {
725 let identifier = simple_segment.ident(db);
726 match self.determine_base(&identifier, ctx) {
727 ResolvedBase::Module(module_id) => ResolvedGenericItem::Module(module_id),
729 ResolvedBase::Crate(crate_id) => self.resolved_items.mark_generic(
730 db,
731 segments.next().unwrap(),
732 ResolvedGenericItem::Module(ModuleId::CrateRoot(crate_id)),
733 ),
734 ResolvedBase::StatementEnvironment(generic_item) => {
735 self.resolved_items.mark_generic(db, segments.next().unwrap(), generic_item)
736 }
737 ResolvedBase::FoundThroughGlobalUse {
738 item_info: inner_module_item, ..
739 } => {
740 self.data
741 .used_items
742 .insert(LookupItemId::ModuleItem(inner_module_item.item_id));
743
744 let generic_item = ResolvedGenericItem::from_module_item(
745 self.db,
746 inner_module_item.item_id,
747 )?;
748 self.resolved_items.mark_generic(db, segments.next().unwrap(), generic_item)
749 }
750 ResolvedBase::Ambiguous(module_items) => {
751 return Err(diagnostics
752 .report(identifier.stable_ptr(db), AmbiguousPath(module_items)));
753 }
754 ResolvedBase::ItemNotVisible(module_item_id, containing_modules) => {
755 return Err(diagnostics.report(
756 identifier.stable_ptr(db),
757 ItemNotVisible(module_item_id, containing_modules),
758 ));
759 }
760 }
761 }
762 syntax::node::ast::PathSegment::Missing(_) => {
763 return Err(skip_diagnostic());
766 }
767 })
768 }
769
770 fn try_handle_super_segments(
774 &mut self,
775 diagnostics: &mut SemanticDiagnostics,
776 segments: &mut Peekable<std::slice::Iter<'_, ast::PathSegment>>,
777 mut mark: impl FnMut(
778 &mut ResolvedItems,
779 &dyn SemanticGroup,
780 &syntax::node::ast::PathSegment,
781 ModuleId,
782 ),
783 ) -> Option<Maybe<ModuleId>> {
784 let db = self.db;
785 let mut module_id = self.module_file_id.0;
786 for segment in segments.peeking_take_while(|segment| match segment {
787 ast::PathSegment::WithGenericArgs(_) | ast::PathSegment::Missing(_) => false,
788 ast::PathSegment::Simple(simple) => simple.ident(db).text(db) == SUPER_KW,
789 }) {
790 module_id = match module_id {
791 ModuleId::CrateRoot(_) => {
792 return Some(Err(
793 diagnostics.report(segment.stable_ptr(db), SuperUsedInRootModule)
794 ));
795 }
796 ModuleId::Submodule(submodule_id) => {
797 let db = self.db;
798 let parent = submodule_id.parent_module(self.db);
799 mark(&mut self.resolved_items, db, segment, parent);
800 parent
801 }
802 };
803 }
804 (module_id != self.module_file_id.0).then_some(Ok(module_id))
805 }
806
807 fn resolve_module_inner_item(
809 &mut self,
810 module_id: &ModuleId,
811 ident: SmolStr,
812 diagnostics: &mut SemanticDiagnostics,
813 identifier: &TerminalIdentifier,
814 item_type: NotFoundItemType,
815 ) -> Maybe<ModuleItemInfo> {
816 let db = self.db;
817 match self.db.module_item_info_by_name(*module_id, ident)? {
818 Some(info) => Ok(info),
819 None => match self.resolve_path_using_use_star(*module_id, identifier) {
820 UseStarResult::UniquePathFound(item_info) => Ok(item_info),
821 UseStarResult::AmbiguousPath(module_items) => {
822 Err(diagnostics.report(identifier.stable_ptr(db), AmbiguousPath(module_items)))
823 }
824 UseStarResult::PathNotFound => {
825 Err(diagnostics.report(identifier.stable_ptr(db), PathNotFound(item_type)))
826 }
827 UseStarResult::ItemNotVisible(module_item_id, containing_modules) => {
828 Err(diagnostics.report(
829 identifier.stable_ptr(db),
830 ItemNotVisible(module_item_id, containing_modules),
831 ))
832 }
833 },
834 }
835 }
836
837 fn resolve_path_next_segment_concrete(
839 &mut self,
840 diagnostics: &mut SemanticDiagnostics,
841 containing_item: &ResolvedConcreteItem,
842 segment: &ast::PathSegment,
843 item_type: NotFoundItemType,
844 ) -> Maybe<ResolvedConcreteItem> {
845 let db = self.db;
846 let identifier = &segment.identifier_ast(db);
847 let generic_args_syntax = segment.generic_args(db);
848
849 let ident = identifier.text(db);
850
851 if identifier.text(db) == SELF_TYPE_KW {
852 return Err(diagnostics.report(identifier.stable_ptr(db), SelfMustBeFirst));
853 }
854
855 match containing_item {
856 ResolvedConcreteItem::Module(module_id) => {
857 if ident == SUPER_KW {
860 return Err(diagnostics.report(identifier.stable_ptr(db), InvalidPath));
861 }
862 let inner_item_info = self.resolve_module_inner_item(
863 module_id,
864 ident,
865 diagnostics,
866 identifier,
867 item_type,
868 )?;
869
870 self.specialize_generic_inner_item(
871 diagnostics,
872 *module_id,
873 identifier,
874 inner_item_info,
875 segment,
876 )
877 }
878 ResolvedConcreteItem::Type(ty) => {
879 if let TypeLongId::Concrete(ConcreteTypeId::Enum(concrete_enum_id)) =
880 ty.lookup_intern(self.db)
881 {
882 let enum_id = concrete_enum_id.enum_id(self.db);
883 let variants = self
884 .db
885 .enum_variants(enum_id)
886 .map_err(|_| diagnostics.report(identifier.stable_ptr(db), UnknownEnum))?;
887 let variant_id = variants.get(&ident).ok_or_else(|| {
888 diagnostics.report(
889 identifier.stable_ptr(db),
890 NoSuchVariant { enum_id, variant_name: ident },
891 )
892 })?;
893 let variant = self.db.variant_semantic(enum_id, *variant_id)?;
894 let concrete_variant =
895 self.db.concrete_enum_variant(concrete_enum_id, &variant)?;
896 Ok(ResolvedConcreteItem::Variant(concrete_variant))
897 } else {
898 Err(diagnostics.report(identifier.stable_ptr(db), InvalidPath))
899 }
900 }
901 ResolvedConcreteItem::SelfTrait(concrete_trait_id) => {
902 let impl_id = ImplLongId::SelfImpl(*concrete_trait_id).intern(self.db);
903 let Some(trait_item_id) = self
904 .db
905 .trait_item_by_name(concrete_trait_id.trait_id(self.db), ident.clone())?
906 else {
907 return Err(diagnostics.report(identifier.stable_ptr(db), InvalidPath));
908 };
909 if let Ok(Some(trait_item_info)) =
910 self.db.trait_item_info_by_name(concrete_trait_id.trait_id(self.db), ident)
911 {
912 self.validate_feature_constraints(diagnostics, identifier, &trait_item_info);
913 }
914 self.data.used_items.insert(LookupItemId::TraitItem(trait_item_id));
915 Ok(match trait_item_id {
916 TraitItemId::Function(trait_function_id) => {
917 ResolvedConcreteItem::Function(self.specialize_function(
918 diagnostics,
919 identifier.stable_ptr(db).untyped(),
920 GenericFunctionId::Impl(ImplGenericFunctionId {
921 impl_id,
922 function: trait_function_id,
923 }),
924 &generic_args_syntax.unwrap_or_default(),
925 )?)
926 }
927 TraitItemId::Type(trait_type_id) => ResolvedConcreteItem::Type(
928 TypeLongId::ImplType(ImplTypeId::new(impl_id, trait_type_id, self.db))
929 .intern(self.db),
930 ),
931 TraitItemId::Constant(trait_constant_id) => ResolvedConcreteItem::Constant(
932 ConstValue::ImplConstant(ImplConstantId::new(
933 impl_id,
934 trait_constant_id,
935 self.db,
936 ))
937 .intern(self.db),
938 ),
939 TraitItemId::Impl(trait_impl_id) => ResolvedConcreteItem::Impl(
940 ImplLongId::ImplImpl(ImplImplId::new(impl_id, trait_impl_id, self.db))
941 .intern(self.db),
942 ),
943 })
944 }
945 ResolvedConcreteItem::Trait(concrete_trait_id) => {
946 let Some(trait_item_id) = self
947 .db
948 .trait_item_by_name(concrete_trait_id.trait_id(self.db), ident.clone())?
949 else {
950 return Err(diagnostics.report(identifier.stable_ptr(db), InvalidPath));
951 };
952
953 if let Ok(Some(trait_item_info)) =
954 self.db.trait_item_info_by_name(concrete_trait_id.trait_id(self.db), ident)
955 {
956 self.validate_feature_constraints(diagnostics, identifier, &trait_item_info);
957 }
958 self.data.used_items.insert(LookupItemId::TraitItem(trait_item_id));
959
960 match trait_item_id {
961 TraitItemId::Function(trait_function_id) => {
962 let concrete_trait_function = ConcreteTraitGenericFunctionLongId::new(
963 self.db,
964 *concrete_trait_id,
965 trait_function_id,
966 )
967 .intern(self.db);
968 let identifier_stable_ptr = identifier.stable_ptr(db).untyped();
969 let impl_lookup_context = self.impl_lookup_context();
970 let generic_function =
971 GenericFunctionId::Impl(self.inference().infer_trait_generic_function(
972 concrete_trait_function,
973 &impl_lookup_context,
974 Some(identifier_stable_ptr),
975 ));
976
977 Ok(ResolvedConcreteItem::Function(self.specialize_function(
978 diagnostics,
979 identifier_stable_ptr,
980 generic_function,
981 &generic_args_syntax.unwrap_or_default(),
982 )?))
983 }
984 TraitItemId::Type(trait_type_id) => {
985 let concrete_trait_type =
986 ConcreteTraitTypeId::new(self.db, *concrete_trait_id, trait_type_id);
987
988 let impl_lookup_context = self.impl_lookup_context();
989 let identifier_stable_ptr = identifier.stable_ptr(db).untyped();
990 let ty = self.inference().infer_trait_type(
991 concrete_trait_type,
992 &impl_lookup_context,
993 Some(identifier_stable_ptr),
994 );
995 Ok(ResolvedConcreteItem::Type(self.inference().rewrite(ty).no_err()))
996 }
997 TraitItemId::Constant(trait_constant_id) => {
998 let concrete_trait_constant = ConcreteTraitConstantLongId::new(
999 self.db,
1000 *concrete_trait_id,
1001 trait_constant_id,
1002 )
1003 .intern(self.db);
1004
1005 let impl_lookup_context = self.impl_lookup_context();
1006 let identifier_stable_ptr = identifier.stable_ptr(db).untyped();
1007 let imp_constant_id = self.inference().infer_trait_constant(
1008 concrete_trait_constant,
1009 &impl_lookup_context,
1010 Some(identifier_stable_ptr),
1011 );
1012 self.inference().solve().ok();
1016
1017 Ok(ResolvedConcreteItem::Constant(
1018 ConstValue::ImplConstant(imp_constant_id).intern(self.db),
1019 ))
1020 }
1021 TraitItemId::Impl(trait_impl_id) => {
1022 let concrete_trait_impl = ConcreteTraitImplLongId::new(
1023 self.db,
1024 *concrete_trait_id,
1025 trait_impl_id,
1026 )
1027 .intern(self.db);
1028
1029 let impl_lookup_context = self.impl_lookup_context();
1030 let identifier_stable_ptr = identifier.stable_ptr(db).untyped();
1031 let impl_impl_id = self.inference().infer_trait_impl(
1032 concrete_trait_impl,
1033 &impl_lookup_context,
1034 Some(identifier_stable_ptr),
1035 );
1036 self.inference().solve().ok();
1040
1041 Ok(ResolvedConcreteItem::Impl(
1042 ImplLongId::ImplImpl(impl_impl_id).intern(self.db),
1043 ))
1044 }
1045 }
1046 }
1047 ResolvedConcreteItem::Impl(impl_id) => {
1048 let concrete_trait_id = self.db.impl_concrete_trait(*impl_id)?;
1049 let trait_id = concrete_trait_id.trait_id(self.db);
1050 let Some(trait_item_id) = self.db.trait_item_by_name(trait_id, ident.clone())?
1051 else {
1052 return Err(diagnostics.report(identifier.stable_ptr(db), InvalidPath));
1053 };
1054 if let Ok(Some(trait_item_info)) = self
1055 .db
1056 .trait_item_info_by_name(concrete_trait_id.trait_id(self.db), ident.clone())
1057 {
1058 self.validate_feature_constraints(diagnostics, identifier, &trait_item_info);
1059 }
1060 if let ImplLongId::Concrete(concrete_impl) = impl_id.lookup_intern(self.db) {
1061 let impl_def_id: ImplDefId = concrete_impl.impl_def_id(self.db);
1062
1063 if let Ok(Some(impl_item_info)) =
1064 self.db.impl_item_info_by_name(impl_def_id, ident)
1065 {
1066 self.validate_feature_constraints(diagnostics, identifier, &impl_item_info);
1067 }
1068 }
1069 self.data.used_items.insert(LookupItemId::TraitItem(trait_item_id));
1070
1071 match trait_item_id {
1072 TraitItemId::Function(trait_function_id) => {
1073 let generic_function_id = GenericFunctionId::Impl(ImplGenericFunctionId {
1074 impl_id: *impl_id,
1075 function: trait_function_id,
1076 });
1077
1078 Ok(ResolvedConcreteItem::Function(self.specialize_function(
1079 diagnostics,
1080 identifier.stable_ptr(db).untyped(),
1081 generic_function_id,
1082 &generic_args_syntax.unwrap_or_default(),
1083 )?))
1084 }
1085 TraitItemId::Type(trait_type_id) => {
1086 let impl_type_id = ImplTypeId::new(*impl_id, trait_type_id, self.db);
1087 let ty = self
1088 .inference()
1089 .reduce_impl_ty(impl_type_id)
1090 .unwrap_or_else(|_| TypeLongId::ImplType(impl_type_id).intern(self.db));
1091 Ok(ResolvedConcreteItem::Type(ty))
1092 }
1093 TraitItemId::Constant(trait_constant_id) => {
1094 let impl_constant_id =
1095 ImplConstantId::new(*impl_id, trait_constant_id, self.db);
1096
1097 let constant =
1098 self.inference().reduce_impl_constant(impl_constant_id).unwrap_or_else(
1099 |_| ConstValue::ImplConstant(impl_constant_id).intern(self.db),
1100 );
1101
1102 Ok(ResolvedConcreteItem::Constant(constant))
1103 }
1104 TraitItemId::Impl(trait_impl_id) => {
1105 let impl_impl_id = ImplImplId::new(*impl_id, trait_impl_id, self.db);
1106 let imp = self
1107 .inference()
1108 .reduce_impl_impl(impl_impl_id)
1109 .unwrap_or_else(|_| ImplLongId::ImplImpl(impl_impl_id).intern(self.db));
1110
1111 Ok(ResolvedConcreteItem::Impl(imp))
1112 }
1113 }
1114 }
1115 ResolvedConcreteItem::Function(function_id) if ident == "Coupon" => {
1116 if !are_coupons_enabled(self.db, self.module_file_id) {
1117 diagnostics.report(identifier.stable_ptr(db), CouponsDisabled);
1118 }
1119 if matches!(
1120 function_id.get_concrete(self.db).generic_function,
1121 GenericFunctionId::Extern(_)
1122 ) {
1123 return Err(diagnostics
1124 .report(identifier.stable_ptr(db), CouponForExternFunctionNotAllowed));
1125 }
1126 Ok(ResolvedConcreteItem::Type(TypeLongId::Coupon(*function_id).intern(self.db)))
1127 }
1128 _ => Err(diagnostics.report(identifier.stable_ptr(db), InvalidPath)),
1129 }
1130 }
1131
1132 fn specialize_generic_module_item(
1134 &mut self,
1135 diagnostics: &mut SemanticDiagnostics,
1136 identifier: &syntax::node::ast::TerminalIdentifier,
1137 generic_item: ResolvedGenericItem,
1138 generic_args_syntax: Option<Vec<ast::GenericArg>>,
1139 ) -> Maybe<ResolvedConcreteItem> {
1140 let db = self.db;
1141 Ok(match generic_item {
1142 ResolvedGenericItem::GenericConstant(id) => {
1143 ResolvedConcreteItem::Constant(self.db.constant_const_value(id)?)
1144 }
1145 ResolvedGenericItem::Module(module_id) => {
1146 if generic_args_syntax.is_some() {
1147 return Err(
1148 diagnostics.report(identifier.stable_ptr(db), UnexpectedGenericArgs)
1149 );
1150 }
1151 ResolvedConcreteItem::Module(module_id)
1152 }
1153 ResolvedGenericItem::GenericFunction(generic_function) => {
1154 ResolvedConcreteItem::Function(self.specialize_function(
1155 diagnostics,
1156 identifier.stable_ptr(db).untyped(),
1157 generic_function,
1158 &generic_args_syntax.unwrap_or_default(),
1159 )?)
1160 }
1161 ResolvedGenericItem::GenericType(generic_type) => {
1162 ResolvedConcreteItem::Type(self.specialize_type(
1163 diagnostics,
1164 identifier.stable_ptr(db).untyped(),
1165 generic_type,
1166 &generic_args_syntax.unwrap_or_default(),
1167 )?)
1168 }
1169 ResolvedGenericItem::GenericTypeAlias(module_type_alias_id) => {
1170 let ty = self.db.module_type_alias_resolved_type(module_type_alias_id)?;
1171 let generic_params =
1172 self.db.module_type_alias_generic_params(module_type_alias_id)?;
1173 let generic_args = self.resolve_generic_args(
1174 diagnostics,
1175 GenericSubstitution::default(),
1176 &generic_params,
1177 &generic_args_syntax.unwrap_or_default(),
1178 identifier.stable_ptr(db).untyped(),
1179 )?;
1180 ResolvedConcreteItem::Type(
1181 GenericSubstitution::new(&generic_params, &generic_args)
1182 .substitute(self.db, ty)?,
1183 )
1184 }
1185 ResolvedGenericItem::GenericImplAlias(impl_alias_id) => {
1186 let impl_id = self.db.impl_alias_resolved_impl(impl_alias_id)?;
1187 let generic_params = self.db.impl_alias_generic_params(impl_alias_id)?;
1188 let generic_args = self.resolve_generic_args(
1189 diagnostics,
1190 GenericSubstitution::default(),
1191 &generic_params,
1192 &generic_args_syntax.unwrap_or_default(),
1193 identifier.stable_ptr(db).untyped(),
1194 )?;
1195 ResolvedConcreteItem::Impl(
1196 GenericSubstitution::new(&generic_params, &generic_args)
1197 .substitute(self.db, impl_id)?,
1198 )
1199 }
1200 ResolvedGenericItem::Trait(trait_id) => {
1201 ResolvedConcreteItem::Trait(self.specialize_trait(
1202 diagnostics,
1203 identifier.stable_ptr(db).untyped(),
1204 trait_id,
1205 &generic_args_syntax.unwrap_or_default(),
1206 )?)
1207 }
1208 ResolvedGenericItem::Impl(impl_def_id) => ResolvedConcreteItem::Impl(
1209 ImplLongId::Concrete(self.specialize_impl(
1210 diagnostics,
1211 identifier.stable_ptr(db).untyped(),
1212 impl_def_id,
1213 &generic_args_syntax.unwrap_or_default(),
1214 )?)
1215 .intern(self.db),
1216 ),
1217 ResolvedGenericItem::Variant(var) => {
1218 ResolvedConcreteItem::Variant(self.specialize_variant(
1219 diagnostics,
1220 identifier.stable_ptr(db).untyped(),
1221 var.id,
1222 &generic_args_syntax.unwrap_or_default(),
1223 )?)
1224 }
1225 ResolvedGenericItem::Variable(_) => panic!("Variable is not a module item."),
1226 ResolvedGenericItem::TraitItem(id) => {
1227 panic!("`{}` is not a module item.", id.full_path(self.db))
1228 }
1229 })
1230 }
1231
1232 fn resolve_path_using_use_star(
1234 &mut self,
1235 module_id: ModuleId,
1236 identifier: &ast::TerminalIdentifier,
1237 ) -> UseStarResult {
1238 let mut item_info = None;
1239 let mut module_items_found: OrderedHashSet<ModuleItemId> = OrderedHashSet::default();
1240 let imported_modules = self.db.priv_module_use_star_modules(module_id);
1241 for (star_module_id, item_module_id) in &imported_modules.accessible {
1242 if let Some(inner_item_info) =
1243 self.resolve_item_in_imported_module(*item_module_id, identifier)
1244 {
1245 if self.is_item_visible(*item_module_id, &inner_item_info, *star_module_id)
1246 && self.is_item_feature_usable(&inner_item_info)
1247 {
1248 item_info = Some(inner_item_info.clone());
1249 module_items_found.insert(inner_item_info.item_id);
1250 }
1251 }
1252 }
1253 if module_items_found.len() > 1 {
1254 return UseStarResult::AmbiguousPath(module_items_found.iter().cloned().collect());
1255 }
1256 match item_info {
1257 Some(item_info) => UseStarResult::UniquePathFound(item_info),
1258 None => {
1259 let mut containing_modules = vec![];
1260 for star_module_id in &imported_modules.all {
1261 if let Some(inner_item_info) =
1262 self.resolve_item_in_imported_module(*star_module_id, identifier)
1263 {
1264 item_info = Some(inner_item_info.clone());
1265 module_items_found.insert(inner_item_info.item_id);
1266 containing_modules.push(*star_module_id);
1267 }
1268 }
1269 if let Some(item_info) = item_info {
1270 if module_items_found.len() > 1 {
1271 UseStarResult::AmbiguousPath(module_items_found.iter().cloned().collect())
1272 } else {
1273 UseStarResult::ItemNotVisible(item_info.item_id, containing_modules)
1274 }
1275 } else {
1276 UseStarResult::PathNotFound
1277 }
1278 }
1279 }
1280 }
1281
1282 fn resolve_item_in_imported_module(
1284 &mut self,
1285 module_id: ModuleId,
1286 identifier: &ast::TerminalIdentifier,
1287 ) -> Option<ModuleItemInfo> {
1288 let inner_item_info = self.db.module_item_info_by_name(module_id, identifier.text(self.db));
1289 if let Ok(Some(inner_item_info)) = inner_item_info {
1290 self.data.used_items.insert(LookupItemId::ModuleItem(inner_item_info.item_id));
1291 return Some(inner_item_info);
1292 }
1293 None
1294 }
1295
1296 fn resolve_path_next_segment_generic(
1298 &mut self,
1299 diagnostics: &mut SemanticDiagnostics,
1300 containing_item: &ResolvedGenericItem,
1301 identifier: &ast::TerminalIdentifier,
1302 item_type: NotFoundItemType,
1303 ) -> Maybe<ResolvedGenericItem> {
1304 let db = self.db;
1305 let ident = identifier.text(db);
1306 match containing_item {
1307 ResolvedGenericItem::Module(module_id) => {
1308 let inner_item_info = self.resolve_module_inner_item(
1309 module_id,
1310 ident,
1311 diagnostics,
1312 identifier,
1313 item_type,
1314 )?;
1315
1316 self.validate_module_item_usability(
1317 diagnostics,
1318 *module_id,
1319 identifier,
1320 &inner_item_info,
1321 );
1322 self.data.used_items.insert(LookupItemId::ModuleItem(inner_item_info.item_id));
1323 ResolvedGenericItem::from_module_item(self.db, inner_item_info.item_id)
1324 }
1325 ResolvedGenericItem::GenericType(GenericTypeId::Enum(enum_id)) => {
1326 let variants = self.db.enum_variants(*enum_id)?;
1327 let variant_id = variants.get(&ident).ok_or_else(|| {
1328 diagnostics.report(
1329 identifier.stable_ptr(db),
1330 NoSuchVariant { enum_id: *enum_id, variant_name: ident },
1331 )
1332 })?;
1333 let variant = self.db.variant_semantic(*enum_id, *variant_id)?;
1334 Ok(ResolvedGenericItem::Variant(variant))
1335 }
1336 _ => Err(diagnostics.report(identifier.stable_ptr(db), InvalidPath)),
1337 }
1338 }
1339
1340 fn determine_base_item_in_local_scope(
1342 &mut self,
1343 identifier: &ast::TerminalIdentifier,
1344 ) -> Option<ResolvedConcreteItem> {
1345 let db = self.db;
1346 let ident = identifier.text(db);
1347
1348 if let Some(generic_param_id) = self.data.generic_param_by_name.get(&ident) {
1350 let item = match generic_param_id.kind(self.db) {
1351 GenericKind::Type => ResolvedConcreteItem::Type(
1352 TypeLongId::GenericParameter(*generic_param_id).intern(self.db),
1353 ),
1354 GenericKind::Const => ResolvedConcreteItem::Constant(
1355 ConstValue::Generic(*generic_param_id).intern(self.db),
1356 ),
1357 GenericKind::Impl => ResolvedConcreteItem::Impl(
1358 ImplLongId::GenericParameter(*generic_param_id).intern(self.db),
1359 ),
1360 GenericKind::NegImpl => return None,
1361 };
1362 return Some(item);
1363 }
1364 None
1367 }
1368
1369 fn determine_base(
1372 &mut self,
1373 identifier: &ast::TerminalIdentifier,
1374 mut ctx: ResolutionContext<'_>,
1375 ) -> ResolvedBase {
1376 let db = self.db;
1377 let ident = identifier.text(db);
1378 let module_id = self.module_file_id.0;
1379 if let ResolutionContext::Statement(ref mut env) = ctx {
1380 if let Some(inner_generic_arg) = get_statement_item_by_name(env, &ident) {
1381 return ResolvedBase::StatementEnvironment(inner_generic_arg);
1382 }
1383 }
1384
1385 if let Ok(Some(item_id)) = self.db.module_item_by_name(module_id, ident.clone()) {
1387 if !matches!(ctx, ResolutionContext::ModuleItem(id) if id == item_id) {
1388 return ResolvedBase::Module(module_id);
1389 }
1390 }
1391
1392 if ident == CRATE_KW {
1394 return ResolvedBase::Crate(self.owning_crate_id);
1395 }
1396 if let Some(dep) = self.settings.dependencies.get(ident.as_str()) {
1399 let dep_crate_id =
1400 CrateLongId::Real { name: ident, discriminator: dep.discriminator.clone() }
1401 .intern(self.db);
1402 let configs = self.db.crate_configs();
1403 if !configs.contains_key(&dep_crate_id) {
1404 let get_long_id = |crate_id: CrateId| crate_id.lookup_intern(self.db);
1405 panic!(
1406 "Invalid crate dependency: {:?}\nconfigured crates: {:#?}",
1407 get_long_id(dep_crate_id),
1408 configs.keys().cloned().map(get_long_id).collect_vec()
1409 );
1410 }
1411
1412 return ResolvedBase::Crate(dep_crate_id);
1413 }
1414 if ident == CORELIB_CRATE_NAME {
1416 return ResolvedBase::Crate(CrateId::core(self.db));
1417 }
1418 if ident == STARKNET_CRATE_NAME {
1420 return ResolvedBase::Module(self.prelude_submodule());
1422 }
1423 match self.resolve_path_using_use_star(module_id, identifier) {
1425 UseStarResult::UniquePathFound(inner_module_item) => {
1426 return ResolvedBase::FoundThroughGlobalUse {
1427 item_info: inner_module_item,
1428 containing_module: module_id,
1429 };
1430 }
1431 UseStarResult::AmbiguousPath(module_items) => {
1432 return ResolvedBase::Ambiguous(module_items);
1433 }
1434 UseStarResult::PathNotFound => {}
1435 UseStarResult::ItemNotVisible(module_item_id, containing_modules) => {
1436 let prelude = self.prelude_submodule();
1437 if let Ok(Some(_)) = self.db.module_item_by_name(prelude, ident) {
1438 return ResolvedBase::Module(prelude);
1439 }
1440 return ResolvedBase::ItemNotVisible(module_item_id, containing_modules);
1441 }
1442 }
1443 ResolvedBase::Module(self.prelude_submodule())
1444 }
1445
1446 pub fn prelude_submodule(&self) -> ModuleId {
1448 let prelude_submodule_name = self.settings.edition.prelude_submodule_name();
1449 let core_prelude_submodule = core_submodule(self.db, "prelude");
1450 get_submodule(self.db, core_prelude_submodule, prelude_submodule_name).unwrap_or_else(
1451 || {
1452 panic!(
1453 "expected prelude submodule `{prelude_submodule_name}` not found in \
1454 `core::prelude`."
1455 )
1456 },
1457 )
1458 }
1459
1460 fn specialize_trait(
1462 &mut self,
1463 diagnostics: &mut SemanticDiagnostics,
1464 stable_ptr: SyntaxStablePtrId,
1465 trait_id: TraitId,
1466 generic_args: &[ast::GenericArg],
1467 ) -> Maybe<ConcreteTraitId> {
1468 let generic_params = self
1470 .db
1471 .trait_generic_params(trait_id)
1472 .map_err(|_| diagnostics.report(stable_ptr, UnknownTrait))?;
1473 let generic_args = self.resolve_generic_args(
1474 diagnostics,
1475 GenericSubstitution::default(),
1476 &generic_params,
1477 generic_args,
1478 stable_ptr,
1479 )?;
1480
1481 Ok(ConcreteTraitLongId { trait_id, generic_args }.intern(self.db))
1482 }
1483
1484 fn specialize_impl(
1486 &mut self,
1487 diagnostics: &mut SemanticDiagnostics,
1488 stable_ptr: SyntaxStablePtrId,
1489 impl_def_id: ImplDefId,
1490 generic_args: &[ast::GenericArg],
1491 ) -> Maybe<ConcreteImplId> {
1492 let generic_params = self
1494 .db
1495 .impl_def_generic_params(impl_def_id)
1496 .map_err(|_| diagnostics.report(stable_ptr, UnknownImpl))?;
1497 let generic_args = self.resolve_generic_args(
1498 diagnostics,
1499 GenericSubstitution::default(),
1500 &generic_params,
1501 generic_args,
1502 stable_ptr,
1503 )?;
1504
1505 Ok(ConcreteImplLongId { impl_def_id, generic_args }.intern(self.db))
1506 }
1507
1508 fn specialize_variant(
1510 &mut self,
1511 diagnostics: &mut SemanticDiagnostics,
1512 stable_ptr: SyntaxStablePtrId,
1513 variant_id: VariantId,
1514 generic_args: &[ast::GenericArg],
1515 ) -> Maybe<ConcreteVariant> {
1516 let concrete_enum_id = ConcreteEnumLongId {
1517 enum_id: variant_id.enum_id(self.db),
1518 generic_args: self.resolve_generic_args(
1519 diagnostics,
1520 GenericSubstitution::default(),
1521 &self.db.enum_generic_params(variant_id.enum_id(self.db))?,
1522 generic_args,
1523 stable_ptr,
1524 )?,
1525 }
1526 .intern(self.db);
1527 self.db.concrete_enum_variant(
1528 concrete_enum_id,
1529 &self.db.variant_semantic(variant_id.enum_id(self.db), variant_id)?,
1530 )
1531 }
1532
1533 pub fn specialize_function(
1535 &mut self,
1536 diagnostics: &mut SemanticDiagnostics,
1537 stable_ptr: SyntaxStablePtrId,
1538 generic_function: GenericFunctionId,
1539 generic_args: &[ast::GenericArg],
1540 ) -> Maybe<FunctionId> {
1541 let generic_params: Vec<_> = generic_function.generic_params(self.db)?;
1543 let generic_args = self.resolve_generic_args(
1544 diagnostics,
1545 GenericSubstitution::default(),
1546 &generic_params,
1547 generic_args,
1548 stable_ptr,
1549 )?;
1550
1551 Ok(FunctionLongId { function: ConcreteFunction { generic_function, generic_args } }
1552 .intern(self.db))
1553 }
1554
1555 pub fn specialize_type(
1557 &mut self,
1558 diagnostics: &mut SemanticDiagnostics,
1559 stable_ptr: SyntaxStablePtrId,
1560 generic_type: GenericTypeId,
1561 generic_args: &[ast::GenericArg],
1562 ) -> Maybe<TypeId> {
1563 let generic_params = self
1564 .db
1565 .generic_type_generic_params(generic_type)
1566 .map_err(|_| diagnostics.report(stable_ptr, UnknownType))?;
1567 let generic_args = self.resolve_generic_args(
1568 diagnostics,
1569 GenericSubstitution::default(),
1570 &generic_params,
1571 generic_args,
1572 stable_ptr,
1573 )?;
1574
1575 Ok(TypeLongId::Concrete(ConcreteTypeId::new(self.db, generic_type, generic_args))
1576 .intern(self.db))
1577 }
1578
1579 pub fn impl_lookup_context(&self) -> ImplLookupContext {
1580 let mut lookup_context =
1581 ImplLookupContext::new(self.module_file_id.0, self.generic_params.clone());
1582
1583 if let TraitOrImplContext::Impl(impl_def_id) = &self.trait_or_impl_ctx {
1584 let Ok(generic_params) = self.db.impl_def_generic_params(*impl_def_id) else {
1585 return lookup_context;
1586 };
1587 let generic_args = generic_params_to_args(generic_params.as_slice(), self.db);
1588 let impl_id: ConcreteImplId =
1589 ConcreteImplLongId { impl_def_id: *impl_def_id, generic_args }.intern(self.db);
1590 lookup_context.insert_impl(ImplLongId::Concrete(impl_id).intern(self.db));
1591 }
1592 lookup_context
1593 }
1594
1595 pub fn resolve_generic_args(
1599 &mut self,
1600 diagnostics: &mut SemanticDiagnostics,
1601 mut substitution: GenericSubstitution,
1602 generic_params: &[GenericParam],
1603 generic_args_syntax: &[ast::GenericArg],
1604 stable_ptr: SyntaxStablePtrId,
1605 ) -> Maybe<Vec<GenericArgumentId>> {
1606 let mut resolved_args = vec![];
1607 let arg_syntax_per_param =
1608 self.get_arg_syntax_per_param(diagnostics, generic_params, generic_args_syntax)?;
1609
1610 for generic_param in generic_params {
1611 let generic_param = substitution.substitute(self.db, generic_param.clone())?;
1612 let generic_arg = self.resolve_generic_arg(
1613 &generic_param,
1614 arg_syntax_per_param
1615 .get(&generic_param.id())
1616 .and_then(|arg_syntax| {
1617 if let ast::GenericArgValue::Expr(expr) = arg_syntax {
1618 Some(expr.expr(self.db))
1619 } else {
1620 None
1621 }
1622 })
1623 .as_ref(),
1624 stable_ptr,
1625 diagnostics,
1626 )?;
1627 resolved_args.push(generic_arg);
1628 substitution.insert(generic_param.id(), generic_arg);
1629 }
1630
1631 Ok(resolved_args)
1632 }
1633
1634 fn get_arg_syntax_per_param(
1636 &self,
1637 diagnostics: &mut SemanticDiagnostics,
1638 generic_params: &[GenericParam],
1639 generic_args_syntax: &[ast::GenericArg],
1640 ) -> Maybe<UnorderedHashMap<GenericParamId, ast::GenericArgValue>> {
1641 let db = self.db;
1642 let mut arg_syntax_per_param =
1643 UnorderedHashMap::<GenericParamId, ast::GenericArgValue>::default();
1644 let mut last_named_arg_index = None;
1645 let generic_param_by_name = generic_params
1646 .iter()
1647 .enumerate()
1648 .filter_map(|(i, param)| Some((param.id().name(self.db)?, (i, param.id()))))
1649 .collect::<UnorderedHashMap<_, _>>();
1650 for (idx, generic_arg_syntax) in generic_args_syntax.iter().enumerate() {
1651 match generic_arg_syntax {
1652 ast::GenericArg::Named(arg_syntax) => {
1653 let name = arg_syntax.name(db).text(db);
1654 let Some((index, generic_param_id)) = generic_param_by_name.get(&name) else {
1655 return Err(diagnostics
1656 .report(arg_syntax.stable_ptr(db), UnknownGenericParam(name)));
1657 };
1658 if let Some(prev_index) = last_named_arg_index {
1659 if prev_index > index {
1660 return Err(diagnostics
1661 .report(arg_syntax.stable_ptr(db), GenericArgOutOfOrder(name)));
1662 }
1663 }
1664 last_named_arg_index = Some(index);
1665 if arg_syntax_per_param
1666 .insert(*generic_param_id, arg_syntax.value(db))
1667 .is_some()
1668 {
1669 return Err(diagnostics
1670 .report(arg_syntax.stable_ptr(db), GenericArgDuplicate(name)));
1671 }
1672 }
1673 ast::GenericArg::Unnamed(arg_syntax) => {
1674 if last_named_arg_index.is_some() {
1675 return Err(diagnostics
1676 .report(arg_syntax.stable_ptr(db), PositionalGenericAfterNamed));
1677 }
1678 let generic_param = generic_params.get(idx).ok_or_else(|| {
1679 diagnostics.report(
1680 arg_syntax.stable_ptr(db),
1681 TooManyGenericArguments {
1682 expected: generic_params.len(),
1683 actual: generic_args_syntax.len(),
1684 },
1685 )
1686 })?;
1687 assert_eq!(
1688 arg_syntax_per_param.insert(generic_param.id(), arg_syntax.value(db)),
1689 None,
1690 "Unexpected duplication in ordered params."
1691 );
1692 }
1693 }
1694 }
1695 Ok(arg_syntax_per_param)
1696 }
1697
1698 fn resolve_generic_arg(
1702 &mut self,
1703 generic_param: &GenericParam,
1704 generic_arg_syntax_opt: Option<&ast::Expr>,
1705 stable_ptr: SyntaxStablePtrId,
1706 diagnostics: &mut SemanticDiagnostics,
1707 ) -> Result<GenericArgumentId, cairo_lang_diagnostics::DiagnosticAdded> {
1708 let Some(generic_arg_syntax) = generic_arg_syntax_opt else {
1709 let lookup_context = self.impl_lookup_context();
1710 let inference = &mut self.data.inference_data.inference(self.db);
1711 return inference
1712 .infer_generic_arg(generic_param, lookup_context, Some(stable_ptr))
1713 .map_err(|err_set| {
1714 inference.report_on_pending_error(err_set, diagnostics, stable_ptr)
1715 });
1716 };
1717 let db = self.db;
1718 Ok(match generic_param {
1719 GenericParam::Type(_) => {
1720 let ty = resolve_type(self.db, diagnostics, self, generic_arg_syntax);
1721 GenericArgumentId::Type(ty)
1722 }
1723 GenericParam::Const(const_param) => {
1724 let environment = Environment::empty();
1728
1729 let mut resolver_data =
1732 ResolverData::new(self.module_file_id, self.inference_data.inference_id);
1733 std::mem::swap(&mut self.data, &mut resolver_data);
1734
1735 let mut ctx = ComputationContext::new(
1736 self.db,
1737 diagnostics,
1738 Resolver::with_data(self.db, resolver_data),
1739 None,
1740 environment,
1741 ContextFunction::Global,
1742 );
1743 let value = compute_expr_semantic(&mut ctx, generic_arg_syntax);
1744
1745 let const_value = resolve_const_expr_and_evaluate(
1746 self.db,
1747 &mut ctx,
1748 &value,
1749 generic_arg_syntax.stable_ptr(db).untyped(),
1750 const_param.ty,
1751 false,
1752 );
1753
1754 std::mem::swap(&mut ctx.resolver.data, &mut self.data);
1756
1757 GenericArgumentId::Constant(const_value.intern(self.db))
1758 }
1759
1760 GenericParam::Impl(param) => {
1761 let expr_path = try_extract_matches!(generic_arg_syntax, ast::Expr::Path)
1762 .ok_or_else(|| {
1763 diagnostics.report(generic_arg_syntax.stable_ptr(db), UnknownImpl)
1764 })?;
1765 let resolved_impl = match self.resolve_concrete_path(
1766 diagnostics,
1767 expr_path,
1768 NotFoundItemType::Impl,
1769 )? {
1770 ResolvedConcreteItem::Impl(resolved_impl) => resolved_impl,
1771 ResolvedConcreteItem::SelfTrait(concrete_trait_id) => {
1772 ImplLongId::SelfImpl(concrete_trait_id).intern(self.db)
1773 }
1774 _ => {
1775 return Err(
1776 diagnostics.report(generic_arg_syntax.stable_ptr(db), UnknownImpl)
1777 );
1778 }
1779 };
1780 let impl_def_concrete_trait = self.db.impl_concrete_trait(resolved_impl)?;
1781 let expected_concrete_trait = param.concrete_trait?;
1782 if let Err(err_set) = self
1783 .inference()
1784 .conform_traits(impl_def_concrete_trait, expected_concrete_trait)
1785 {
1786 let diag_added = diagnostics.report(
1787 generic_arg_syntax.stable_ptr(db),
1788 TraitMismatch {
1789 expected_trt: expected_concrete_trait,
1790 actual_trt: impl_def_concrete_trait,
1791 },
1792 );
1793 self.inference().consume_reported_error(err_set, diag_added);
1794 } else {
1795 for (trait_ty, ty1) in param.type_constraints.iter() {
1796 let ty0 = TypeLongId::ImplType(ImplTypeId::new(
1797 resolved_impl,
1798 *trait_ty,
1799 self.db,
1800 ))
1801 .intern(self.db);
1802 let _ = self.inference().conform_ty(ty0, *ty1).map_err(|err_set| {
1803 self.inference().report_on_pending_error(
1804 err_set,
1805 diagnostics,
1806 stable_ptr,
1807 )
1808 });
1809 }
1810 }
1811 GenericArgumentId::Impl(resolved_impl)
1812 }
1813 GenericParam::NegImpl(_) => {
1814 return Err(
1815 diagnostics.report(generic_arg_syntax.stable_ptr(db), ArgPassedToNegativeImpl)
1816 );
1817 }
1818 })
1819 }
1820 pub fn ignore_visibility_checks(&self, module_id: ModuleId) -> bool {
1823 let module_crate = module_id.owning_crate(self.db);
1824 let module_edition =
1825 self.db.crate_config(module_crate).map(|c| c.settings.edition).unwrap_or_default();
1826 module_edition.ignore_visibility()
1827 || self.settings.edition.ignore_visibility() && module_crate == self.db.core_crate()
1828 }
1829
1830 pub fn validate_feature_constraints<T: HasFeatureKind>(
1835 &self,
1836 diagnostics: &mut SemanticDiagnostics,
1837 identifier: &ast::TerminalIdentifier,
1838 item_info: &T,
1839 ) {
1840 let db = self.db;
1841 match &item_info.feature_kind() {
1842 FeatureKind::Unstable { feature, note }
1843 if !self.data.feature_config.allowed_features.contains(feature) =>
1844 {
1845 diagnostics.report(
1846 identifier.stable_ptr(db),
1847 UnstableFeature { feature_name: feature.clone(), note: note.clone() },
1848 );
1849 }
1850 FeatureKind::Deprecated { feature, note }
1851 if !self.data.feature_config.allow_deprecated
1852 && !self.data.feature_config.allowed_features.contains(feature) =>
1853 {
1854 diagnostics.report(
1855 identifier.stable_ptr(db),
1856 DeprecatedFeature { feature_name: feature.clone(), note: note.clone() },
1857 );
1858 }
1859 FeatureKind::Internal { feature, note }
1860 if !self.data.feature_config.allowed_features.contains(feature) =>
1861 {
1862 diagnostics.report(
1863 identifier.stable_ptr(db),
1864 InternalFeature { feature_name: feature.clone(), note: note.clone() },
1865 );
1866 }
1867 _ => {}
1868 }
1869 }
1870
1871 fn validate_module_item_usability(
1874 &self,
1875 diagnostics: &mut SemanticDiagnostics,
1876 containing_module_id: ModuleId,
1877 identifier: &ast::TerminalIdentifier,
1878 item_info: &ModuleItemInfo,
1879 ) {
1880 if !self.is_item_visible(containing_module_id, item_info, self.module_file_id.0) {
1881 diagnostics
1882 .report(identifier.stable_ptr(self.db), ItemNotVisible(item_info.item_id, vec![]));
1883 }
1884
1885 self.validate_feature_constraints(diagnostics, identifier, item_info);
1886 }
1887
1888 pub fn is_item_visible(
1890 &self,
1891 containing_module_id: ModuleId,
1892 item_info: &ModuleItemInfo,
1893 user_module: ModuleId,
1894 ) -> bool {
1895 self.ignore_visibility_checks(containing_module_id)
1896 || visibility::peek_visible_in(
1897 self.db,
1898 item_info.visibility,
1899 containing_module_id,
1900 user_module,
1901 )
1902 }
1903
1904 fn is_item_feature_usable(&self, item_info: &ModuleItemInfo) -> bool {
1906 match &item_info.feature_kind {
1907 FeatureKind::Unstable { feature, .. }
1908 | FeatureKind::Deprecated { feature, .. }
1909 | FeatureKind::Internal { feature, .. } => {
1910 self.data.feature_config.allowed_features.contains(feature)
1911 }
1912 _ => true,
1913 }
1914 }
1915
1916 fn handle_same_impl_trait(
1922 &mut self,
1923 diagnostics: &mut SemanticDiagnostics,
1924 specialized_item: &mut ResolvedConcreteItem,
1925 generic_args_syntax_slice: &[ast::GenericArg],
1926 segment_stable_ptr: SyntaxStablePtrId,
1927 ) {
1928 match *specialized_item {
1929 ResolvedConcreteItem::Trait(current_segment_concrete_trait) => {
1930 match self.trait_or_impl_ctx {
1931 TraitOrImplContext::None => {}
1932 TraitOrImplContext::Trait(ctx_trait) => {
1933 if self
1934 .warn_trait_in_same_trait(
1935 diagnostics,
1936 current_segment_concrete_trait.trait_id(self.db),
1937 generic_args_syntax_slice,
1938 ctx_trait,
1939 segment_stable_ptr,
1940 )
1941 .is_err()
1942 {
1943 *specialized_item =
1944 ResolvedConcreteItem::SelfTrait(current_segment_concrete_trait);
1945 }
1946 }
1947 TraitOrImplContext::Impl(ctx_impl_def_id) => {
1948 self.warn_trait_in_its_impl(
1949 diagnostics,
1950 current_segment_concrete_trait,
1951 ctx_impl_def_id,
1952 segment_stable_ptr,
1953 )
1954 .ok();
1955 }
1956 };
1957 }
1958 ResolvedConcreteItem::Impl(current_segment_impl_id) => {
1959 if let TraitOrImplContext::Impl(ctx_impl) = self.trait_or_impl_ctx {
1960 let current_segment_concrete_impl_id = extract_matches!(
1963 current_segment_impl_id.lookup_intern(self.db),
1964 ImplLongId::Concrete
1965 );
1966 self.warn_impl_in_same_impl(
1967 diagnostics,
1968 current_segment_concrete_impl_id.impl_def_id(self.db),
1969 generic_args_syntax_slice,
1970 ctx_impl,
1971 segment_stable_ptr,
1972 )
1973 .ok();
1974 }
1975 }
1976 _ => {}
1977 };
1978 }
1979
1980 fn warn_impl_in_same_impl(
1983 &mut self,
1984 diagnostics: &mut SemanticDiagnostics,
1985 current_segment_impl_def_id: ImplDefId,
1986 current_segment_generic_args: &[ast::GenericArg],
1987 ctx_impl: ImplDefId,
1988 segment_stable_ptr: SyntaxStablePtrId,
1989 ) -> Maybe<()> {
1990 if current_segment_impl_def_id != ctx_impl {
1991 return Ok(());
1992 }
1993
1994 let generic_params = self.db.impl_def_generic_params(ctx_impl)?;
1995 self.compare_segment_args_to_params(
1996 diagnostics,
1997 current_segment_generic_args,
1998 generic_params,
1999 segment_stable_ptr,
2000 ImplInImplMustBeExplicit,
2001 ImplItemForbiddenInTheImpl,
2002 )
2003 }
2004
2005 fn warn_trait_in_its_impl(
2008 &mut self,
2009 diagnostics: &mut SemanticDiagnostics,
2010 current_segment_concrete_trait_id: ConcreteTraitId,
2011 impl_ctx: ImplDefId,
2012 segment_stable_ptr: SyntaxStablePtrId,
2013 ) -> Maybe<()> {
2014 let ctx_impl_trait = self.db.impl_def_trait(impl_ctx)?;
2015 if current_segment_concrete_trait_id.trait_id(self.db) != ctx_impl_trait {
2016 return Ok(());
2017 }
2018
2019 let ctx_impl_concrete_trait = self.db.impl_def_concrete_trait(impl_ctx)?;
2020 if ctx_impl_concrete_trait.generic_args(self.db)
2021 == current_segment_concrete_trait_id.generic_args(self.db)
2022 {
2023 return Err(diagnostics.report(segment_stable_ptr, TraitItemForbiddenInItsImpl));
2024 }
2025 Ok(())
2026 }
2027
2028 fn warn_trait_in_same_trait(
2031 &mut self,
2032 diagnostics: &mut SemanticDiagnostics,
2033 current_segment_trait_id: TraitId,
2034 current_segment_generic_args: &[ast::GenericArg],
2035 ctx_trait: TraitId,
2036 segment_stable_ptr: SyntaxStablePtrId,
2037 ) -> Maybe<()> {
2038 if current_segment_trait_id != ctx_trait {
2039 return Ok(());
2040 }
2041
2042 let generic_params = self.db.trait_generic_params(ctx_trait)?;
2043 self.compare_segment_args_to_params(
2044 diagnostics,
2045 current_segment_generic_args,
2046 generic_params,
2047 segment_stable_ptr,
2048 TraitInTraitMustBeExplicit,
2049 TraitItemForbiddenInTheTrait,
2050 )
2051 }
2052
2053 fn compare_segment_args_to_params(
2060 &mut self,
2061 diagnostics: &mut SemanticDiagnostics,
2062 current_segment_generic_args: &[ast::GenericArg],
2063 generic_params: Vec<GenericParam>,
2064 segment_stable_ptr: SyntaxStablePtrId,
2065 must_be_explicit_error: SemanticDiagnosticKind,
2066 item_forbidden_in_itself_explicit_error: SemanticDiagnosticKind,
2067 ) -> Maybe<()> {
2068 if current_segment_generic_args.len() < generic_params.len() {
2071 return Err(diagnostics.report(segment_stable_ptr, must_be_explicit_error));
2072 }
2073 let resolved_args = self.resolve_generic_args(
2074 diagnostics,
2075 GenericSubstitution::default(),
2076 &generic_params,
2077 current_segment_generic_args,
2078 segment_stable_ptr,
2079 )?;
2080
2081 if generic_params
2082 .iter()
2083 .zip_eq(resolved_args.iter())
2084 .all(|(gparam, garg)| gparam.as_arg(self.db) == *garg)
2085 {
2086 return Err(
2087 diagnostics.report(segment_stable_ptr, item_forbidden_in_itself_explicit_error)
2088 );
2089 }
2090 Ok(())
2091 }
2092
2093 fn specialize_generic_statement_arg(
2095 &mut self,
2096 segment: &ast::PathSegment,
2097 diagnostics: &mut SemanticDiagnostics,
2098 identifier: &ast::TerminalIdentifier,
2099 inner_generic_item: ResolvedGenericItem,
2100 generic_args_syntax: Option<Vec<ast::GenericArg>>,
2101 ) -> ResolvedConcreteItem {
2102 let segment_stable_ptr = segment.stable_ptr(self.db).untyped();
2103 let mut specialized_item = self
2104 .specialize_generic_module_item(
2105 diagnostics,
2106 identifier,
2107 inner_generic_item,
2108 generic_args_syntax.clone(),
2109 )
2110 .unwrap();
2111 self.handle_same_impl_trait(
2112 diagnostics,
2113 &mut specialized_item,
2114 &generic_args_syntax.unwrap_or_default(),
2115 segment_stable_ptr,
2116 );
2117 specialized_item
2118 }
2119}
2120
2121fn resolve_self_segment(
2124 db: &dyn SemanticGroup,
2125 diagnostics: &mut SemanticDiagnostics,
2126 identifier: &ast::TerminalIdentifier,
2127 trait_or_impl_ctx: &TraitOrImplContext,
2128) -> Option<Maybe<ResolvedConcreteItem>> {
2129 require(identifier.text(db) == SELF_TYPE_KW)?;
2130 Some(resolve_actual_self_segment(db, diagnostics, identifier, trait_or_impl_ctx))
2131}
2132
2133fn resolve_actual_self_segment(
2135 db: &dyn SemanticGroup,
2136 diagnostics: &mut SemanticDiagnostics,
2137 identifier: &ast::TerminalIdentifier,
2138 trait_or_impl_ctx: &TraitOrImplContext,
2139) -> Maybe<ResolvedConcreteItem> {
2140 match trait_or_impl_ctx {
2141 TraitOrImplContext::None => {
2142 Err(diagnostics.report(identifier.stable_ptr(db), SelfNotSupportedInContext))
2143 }
2144 TraitOrImplContext::Trait(trait_id) => {
2145 let generic_parameters = db.trait_generic_params(*trait_id)?;
2146 let concrete_trait_id = ConcreteTraitLongId {
2147 trait_id: *trait_id,
2148 generic_args: generic_params_to_args(&generic_parameters, db),
2149 }
2150 .intern(db);
2151 Ok(ResolvedConcreteItem::SelfTrait(concrete_trait_id))
2152 }
2153 TraitOrImplContext::Impl(impl_def_id) => {
2154 let generic_parameters = db.impl_def_generic_params(*impl_def_id)?;
2155 let impl_id = ImplLongId::Concrete(
2156 ConcreteImplLongId {
2157 impl_def_id: *impl_def_id,
2158 generic_args: generic_params_to_args(&generic_parameters, db),
2159 }
2160 .intern(db),
2161 );
2162 Ok(ResolvedConcreteItem::Impl(impl_id.intern(db)))
2163 }
2164 }
2165}
2166
2167enum ResolvedBase {
2169 Module(ModuleId),
2171 Crate(CrateId),
2173 StatementEnvironment(ResolvedGenericItem),
2175 FoundThroughGlobalUse { item_info: ModuleItemInfo, containing_module: ModuleId },
2177 Ambiguous(Vec<ModuleItemId>),
2179 ItemNotVisible(ModuleItemId, Vec<ModuleId>),
2181}
2182
2183struct ResolvePathInnerCallbacks<ResolvedItem, ResolveFirst, ResolveNext, Validate, Mark>
2185where
2186 ResolveFirst: FnOnce(
2187 &mut Resolver<'_>,
2188 &mut SemanticDiagnostics,
2189 &mut Peekable<std::slice::Iter<'_, ast::PathSegment>>,
2190 ) -> Maybe<ResolvedItem>,
2191 ResolveNext: FnMut(
2192 &mut Resolver<'_>,
2193 &mut SemanticDiagnostics,
2194 &ResolvedItem,
2195 &ast::PathSegment,
2196 NotFoundItemType,
2197 ) -> Maybe<ResolvedItem>,
2198 Validate: FnMut(&mut SemanticDiagnostics, &ast::PathSegment) -> Maybe<()>,
2199 Mark: FnMut(
2200 &mut ResolvedItems,
2201 &dyn SemanticGroup,
2202 &syntax::node::ast::PathSegment,
2203 ResolvedItem,
2204 ),
2205{
2206 resolved_item_type: PhantomData<ResolvedItem>,
2208 resolve_path_first_segment: ResolveFirst,
2210 resolve_path_next_segment: ResolveNext,
2212 validate_segment: Validate,
2215 mark: Mark,
2216}