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