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.upcast());
93 if let Some(generic_item) = resolved_item.generic(db) {
94 self.generic.insert(identifier.stable_ptr(), generic_item);
96 }
97 self.concrete.insert(identifier.stable_ptr(), 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.upcast());
109 self.generic.insert(identifier.stable_ptr(), 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 =
236 extract_feature_config(self.db.upcast(), element_id, syntax, diagnostics);
237 }
238}
239
240enum UseStarResult {
242 UniquePathFound(ModuleItemInfo),
244 AmbiguousPath(Vec<ModuleItemId>),
246 PathNotFound,
248 ItemNotVisible(ModuleItemId, Vec<ModuleId>),
250}
251
252pub trait AsSegments {
254 fn to_segments(self, db: &dyn SyntaxGroup) -> Vec<ast::PathSegment>;
255}
256impl AsSegments for &ast::ExprPath {
257 fn to_segments(self, db: &dyn SyntaxGroup) -> Vec<ast::PathSegment> {
258 self.elements(db)
259 }
260}
261impl AsSegments for Vec<ast::PathSegment> {
262 fn to_segments(self, _: &dyn SyntaxGroup) -> Vec<ast::PathSegment> {
263 self
264 }
265}
266
267impl<'db> Resolver<'db> {
268 pub fn new(
269 db: &'db dyn SemanticGroup,
270 module_file_id: ModuleFileId,
271 inference_id: InferenceId,
272 ) -> Self {
273 Self::with_data(db, ResolverData::new(module_file_id, inference_id))
274 }
275
276 pub fn with_data(db: &'db dyn SemanticGroup, data: ResolverData) -> Self {
277 let owning_crate_id = data.module_file_id.0.owning_crate(db.upcast());
278 let settings = db.crate_config(owning_crate_id).map(|c| c.settings).unwrap_or_default();
279 Self { owning_crate_id, settings, db, data }
280 }
281
282 pub fn inference(&mut self) -> Inference<'_> {
283 self.data.inference_data.inference(self.db)
284 }
285
286 pub fn add_generic_param(&mut self, generic_param_id: GenericParamId) {
290 self.generic_params.push(generic_param_id);
291 let db = self.db.upcast();
292 if let Some(name) = generic_param_id.name(db) {
293 self.generic_param_by_name.insert(name, generic_param_id);
294 }
295 }
296
297 fn resolve_path_inner<ResolvedItem: Clone>(
300 &mut self,
301 diagnostics: &mut SemanticDiagnostics,
302 path: impl AsSegments,
303 item_type: NotFoundItemType,
304 statement_env: Option<&mut Environment>,
305 mut callbacks: ResolvePathInnerCallbacks<
306 ResolvedItem,
307 impl FnMut(
308 &mut Resolver<'_>,
309 &mut SemanticDiagnostics,
310 &mut Peekable<std::slice::Iter<'_, ast::PathSegment>>,
311 Option<&mut Environment>,
312 ) -> Maybe<ResolvedItem>,
313 impl FnMut(
314 &mut Resolver<'_>,
315 &mut SemanticDiagnostics,
316 &ResolvedItem,
317 &ast::PathSegment,
318 NotFoundItemType,
319 ) -> Maybe<ResolvedItem>,
320 impl FnMut(&mut SemanticDiagnostics, &ast::PathSegment) -> Maybe<()>,
321 impl FnMut(
322 &mut ResolvedItems,
323 &dyn SemanticGroup,
324 &syntax::node::ast::PathSegment,
325 ResolvedItem,
326 ),
327 >,
328 ) -> Maybe<ResolvedItem> {
329 let db = self.db;
330 let syntax_db = db.upcast();
331 let elements_vec = path.to_segments(syntax_db);
332 let mut segments = elements_vec.iter().peekable();
333
334 let mut item: ResolvedItem = (callbacks.resolve_path_first_segment)(
336 self,
337 diagnostics,
338 &mut segments,
339 statement_env,
340 )?;
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, None)
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 statement_env: Option<&mut Environment>,
384 ) -> Maybe<ResolvedConcreteItem> {
385 self.resolve_path_inner::<ResolvedConcreteItem>(
386 diagnostics,
387 path,
388 item_type,
389 statement_env,
390 ResolvePathInnerCallbacks {
391 resolved_item_type: PhantomData,
392 resolve_path_first_segment: |resolver, diagnostics, segments, statement_env| {
393 resolver.resolve_concrete_path_first_segment(
394 diagnostics,
395 segments,
396 statement_env,
397 )
398 },
399 resolve_path_next_segment: |resolver, diagnostics, item, segment, item_type| {
400 resolver.resolve_path_next_segment_concrete(
401 diagnostics,
402 item,
403 segment,
404 item_type,
405 )
406 },
407 validate_segment: |_, _| Ok(()),
408 mark: |resolved_items, db, segment, item| {
409 resolved_items.mark_concrete(db, segment, item);
410 },
411 },
412 )
413 }
414
415 fn specialize_generic_inner_item(
417 &mut self,
418 diagnostics: &mut SemanticDiagnostics,
419 module_id: ModuleId,
420 identifier: &TerminalIdentifier,
421 inner_item_info: ModuleItemInfo,
422 segment: &ast::PathSegment,
423 ) -> Maybe<ResolvedConcreteItem> {
424 let generic_args_syntax = segment.generic_args(self.db.upcast());
425 let segment_stable_ptr = segment.stable_ptr().untyped();
426 self.validate_module_item_usability(diagnostics, module_id, identifier, &inner_item_info);
427 self.data.used_items.insert(LookupItemId::ModuleItem(inner_item_info.item_id));
428 let inner_generic_item =
429 ResolvedGenericItem::from_module_item(self.db, inner_item_info.item_id)?;
430 let mut specialized_item = self.specialize_generic_module_item(
431 diagnostics,
432 identifier,
433 inner_generic_item.clone(),
434 generic_args_syntax.clone(),
435 )?;
436 self.data.resolved_items.generic.insert(identifier.stable_ptr(), inner_generic_item);
437 self.handle_same_impl_trait(
438 diagnostics,
439 &mut specialized_item,
440 &generic_args_syntax.unwrap_or_default(),
441 segment_stable_ptr,
442 );
443 Ok(specialized_item)
444 }
445
446 fn resolve_concrete_path_first_segment(
448 &mut self,
449 diagnostics: &mut SemanticDiagnostics,
450 segments: &mut Peekable<std::slice::Iter<'_, ast::PathSegment>>,
451 statement_env: Option<&mut Environment>,
452 ) -> Maybe<ResolvedConcreteItem> {
453 if let Some(base_module) = self.try_handle_super_segments(diagnostics, segments) {
454 return Ok(ResolvedConcreteItem::Module(base_module?));
455 }
456
457 let db = self.db;
458 let syntax_db = db.upcast();
459 Ok(match segments.peek().unwrap() {
460 syntax::node::ast::PathSegment::WithGenericArgs(generic_segment) => {
461 let identifier = generic_segment.ident(syntax_db);
462 match self.determine_base(&identifier, statement_env) {
464 ResolvedBase::Module(module_id) => ResolvedConcreteItem::Module(module_id),
465 ResolvedBase::Crate(_) => {
466 return Err(diagnostics.report(
468 &generic_segment.generic_args(syntax_db),
469 UnexpectedGenericArgs,
470 ));
471 }
472 ResolvedBase::StatementEnvironment(generic_item) => {
473 let segment = segments.next().unwrap();
474 self.specialize_generic_statement_arg(
475 segment,
476 diagnostics,
477 &identifier,
478 generic_item,
479 segment.generic_args(syntax_db),
480 )
481 }
482 ResolvedBase::FoundThroughGlobalUse {
483 item_info: inner_module_item,
484 containing_module: module_id,
485 } => {
486 let segment = segments.next().unwrap();
487 self.specialize_generic_inner_item(
488 diagnostics,
489 module_id,
490 &identifier,
491 inner_module_item,
492 segment,
493 )?
494 }
495 ResolvedBase::Ambiguous(module_items) => {
496 return Err(diagnostics.report(&identifier, AmbiguousPath(module_items)));
497 }
498 ResolvedBase::ItemNotVisible(module_item_id, containing_modules) => {
499 return Err(diagnostics.report(
500 &identifier,
501 ItemNotVisible(module_item_id, containing_modules),
502 ));
503 }
504 }
505 }
506 syntax::node::ast::PathSegment::Simple(simple_segment) => {
507 let identifier = simple_segment.ident(syntax_db);
508
509 if let Some(resolved_item) =
510 resolve_self_segment(db, diagnostics, &identifier, &self.data.trait_or_impl_ctx)
511 {
512 segments.next().unwrap();
514 return resolved_item;
515 }
516
517 if let Some(local_item) = self.determine_base_item_in_local_scope(&identifier) {
518 self.resolved_items.mark_concrete(db, segments.next().unwrap(), local_item)
519 } else {
520 match self.determine_base(&identifier, statement_env) {
521 ResolvedBase::Module(module_id) => ResolvedConcreteItem::Module(module_id),
523 ResolvedBase::Crate(crate_id) => self.resolved_items.mark_concrete(
524 db,
525 segments.next().unwrap(),
526 ResolvedConcreteItem::Module(ModuleId::CrateRoot(crate_id)),
527 ),
528 ResolvedBase::StatementEnvironment(generic_item) => {
529 let segment = segments.next().unwrap();
530 self.specialize_generic_statement_arg(
531 segment,
532 diagnostics,
533 &identifier,
534 generic_item,
535 segment.generic_args(syntax_db),
536 )
537 }
538 ResolvedBase::FoundThroughGlobalUse {
539 item_info: inner_module_item,
540 containing_module: module_id,
541 } => {
542 let segment = segments.next().unwrap();
543 self.specialize_generic_inner_item(
544 diagnostics,
545 module_id,
546 &identifier,
547 inner_module_item,
548 segment,
549 )?
550 }
551 ResolvedBase::Ambiguous(module_items) => {
552 return Err(
553 diagnostics.report(&identifier, AmbiguousPath(module_items))
554 );
555 }
556 ResolvedBase::ItemNotVisible(module_item_id, containing_modules) => {
557 return Err(diagnostics.report(
558 &identifier,
559 ItemNotVisible(module_item_id, containing_modules),
560 ));
561 }
562 }
563 }
564 }
565 syntax::node::ast::PathSegment::Missing(_) => {
566 return Err(skip_diagnostic());
569 }
570 })
571 }
572
573 pub fn resolve_generic_path(
576 &mut self,
577 diagnostics: &mut SemanticDiagnostics,
578 path: impl AsSegments,
579 item_type: NotFoundItemType,
580 statement_env: Option<&mut Environment>,
581 ) -> Maybe<ResolvedGenericItem> {
582 self.resolve_generic_path_inner(diagnostics, path, item_type, false, statement_env)
583 }
584 pub fn resolve_generic_path_with_args(
587 &mut self,
588 diagnostics: &mut SemanticDiagnostics,
589 path: impl AsSegments,
590 item_type: NotFoundItemType,
591 statement_env: Option<&mut Environment>,
592 ) -> Maybe<ResolvedGenericItem> {
593 self.resolve_generic_path_inner(diagnostics, path, item_type, true, statement_env)
594 }
595
596 fn resolve_generic_path_inner(
601 &mut self,
602 diagnostics: &mut SemanticDiagnostics,
603 path: impl AsSegments,
604 item_type: NotFoundItemType,
605 allow_generic_args: bool,
606 statement_env: Option<&mut Environment>,
607 ) -> Maybe<ResolvedGenericItem> {
608 let validate_segment =
609 |diagnostics: &mut SemanticDiagnostics, segment: &ast::PathSegment| match segment {
610 ast::PathSegment::WithGenericArgs(generic_args) if !allow_generic_args => {
611 Err(diagnostics.report(generic_args, UnexpectedGenericArgs))
612 }
613 _ => Ok(()),
614 };
615 self.resolve_path_inner::<ResolvedGenericItem>(
616 diagnostics,
617 path,
618 item_type,
619 statement_env,
620 ResolvePathInnerCallbacks {
621 resolved_item_type: PhantomData,
622 resolve_path_first_segment: |resolver, diagnostics, segments, statement_env| {
623 resolver.resolve_generic_path_first_segment(
624 diagnostics,
625 segments,
626 allow_generic_args,
627 statement_env,
628 )
629 },
630 resolve_path_next_segment: |resolver, diagnostics, item, segment, item_type| {
631 let identifier = segment.identifier_ast(self.db.upcast());
632 resolver.resolve_path_next_segment_generic(
633 diagnostics,
634 item,
635 &identifier,
636 item_type,
637 )
638 },
639 validate_segment,
640 mark: |resolved_items, db, segment, item| {
641 resolved_items.mark_generic(db, segment, item);
642 },
643 },
644 )
645 }
646
647 fn resolve_generic_path_first_segment(
650 &mut self,
651 diagnostics: &mut SemanticDiagnostics,
652 segments: &mut Peekable<std::slice::Iter<'_, ast::PathSegment>>,
653 allow_generic_args: bool,
654 statement_env: Option<&mut Environment>,
655 ) -> Maybe<ResolvedGenericItem> {
656 if let Some(base_module) = self.try_handle_super_segments(diagnostics, segments) {
657 return Ok(ResolvedGenericItem::Module(base_module?));
658 }
659 let db = self.db;
660 let syntax_db = db.upcast();
661 Ok(match segments.peek().unwrap() {
662 syntax::node::ast::PathSegment::WithGenericArgs(generic_segment) => {
663 if !allow_generic_args {
664 return Err(diagnostics
665 .report(&generic_segment.generic_args(syntax_db), UnexpectedGenericArgs));
666 }
667 let identifier = generic_segment.ident(syntax_db);
668 match self.determine_base(&identifier, statement_env) {
670 ResolvedBase::Module(module_id) => ResolvedGenericItem::Module(module_id),
671 ResolvedBase::Crate(_) => {
672 return Err(diagnostics.report(
674 &generic_segment.generic_args(syntax_db),
675 UnexpectedGenericArgs,
676 ));
677 }
678 ResolvedBase::StatementEnvironment(generic_item) => generic_item,
679 ResolvedBase::FoundThroughGlobalUse {
680 item_info: inner_module_item, ..
681 } => {
682 segments.next();
683 self.data
684 .used_items
685 .insert(LookupItemId::ModuleItem(inner_module_item.item_id));
686 ResolvedGenericItem::from_module_item(self.db, inner_module_item.item_id)?
687 }
688 ResolvedBase::Ambiguous(module_items) => {
689 return Err(diagnostics.report(&identifier, AmbiguousPath(module_items)));
690 }
691 ResolvedBase::ItemNotVisible(module_item_id, containing_modules) => {
692 return Err(diagnostics.report(
693 &identifier,
694 ItemNotVisible(module_item_id, containing_modules),
695 ));
696 }
697 }
698 }
699 syntax::node::ast::PathSegment::Simple(simple_segment) => {
700 let identifier = simple_segment.ident(syntax_db);
701 match self.determine_base(&identifier, statement_env) {
702 ResolvedBase::Module(module_id) => ResolvedGenericItem::Module(module_id),
704 ResolvedBase::Crate(crate_id) => self.resolved_items.mark_generic(
705 db,
706 segments.next().unwrap(),
707 ResolvedGenericItem::Module(ModuleId::CrateRoot(crate_id)),
708 ),
709 ResolvedBase::StatementEnvironment(generic_item) => {
710 segments.next();
711 generic_item
712 }
713 ResolvedBase::FoundThroughGlobalUse {
714 item_info: inner_module_item, ..
715 } => {
716 segments.next();
717 self.data
718 .used_items
719 .insert(LookupItemId::ModuleItem(inner_module_item.item_id));
720 ResolvedGenericItem::from_module_item(self.db, inner_module_item.item_id)?
721 }
722 ResolvedBase::Ambiguous(module_items) => {
723 return Err(diagnostics.report(&identifier, AmbiguousPath(module_items)));
724 }
725 ResolvedBase::ItemNotVisible(module_item_id, containing_modules) => {
726 return Err(diagnostics.report(
727 &identifier,
728 ItemNotVisible(module_item_id, containing_modules),
729 ));
730 }
731 }
732 }
733 syntax::node::ast::PathSegment::Missing(_) => {
734 return Err(skip_diagnostic());
737 }
738 })
739 }
740
741 fn try_handle_super_segments(
745 &self,
746 diagnostics: &mut SemanticDiagnostics,
747 segments: &mut Peekable<std::slice::Iter<'_, ast::PathSegment>>,
748 ) -> Option<Maybe<ModuleId>> {
749 let syntax_db = self.db.upcast();
750 let mut module_id = self.module_file_id.0;
751 for segment in segments.peeking_take_while(|segment| match segment {
752 ast::PathSegment::WithGenericArgs(_) | ast::PathSegment::Missing(_) => false,
753 ast::PathSegment::Simple(simple) => simple.ident(syntax_db).text(syntax_db) == SUPER_KW,
754 }) {
755 module_id = match module_id {
756 ModuleId::CrateRoot(_) => {
757 return Some(Err(diagnostics.report(segment, SuperUsedInRootModule)));
758 }
759 ModuleId::Submodule(submodule_id) => submodule_id.parent_module(self.db.upcast()),
760 };
761 }
762 (module_id != self.module_file_id.0).then_some(Ok(module_id))
763 }
764
765 fn resolve_module_inner_item(
767 &mut self,
768 module_id: &ModuleId,
769 ident: SmolStr,
770 diagnostics: &mut SemanticDiagnostics,
771 identifier: &TerminalIdentifier,
772 item_type: NotFoundItemType,
773 ) -> Maybe<ModuleItemInfo> {
774 match self.db.module_item_info_by_name(*module_id, ident)? {
775 Some(info) => Ok(info),
776 None => match self.resolve_path_using_use_star(*module_id, identifier) {
777 UseStarResult::UniquePathFound(item_info) => Ok(item_info),
778 UseStarResult::AmbiguousPath(module_items) => {
779 Err(diagnostics.report(identifier, AmbiguousPath(module_items)))
780 }
781 UseStarResult::PathNotFound => {
782 Err(diagnostics.report(identifier, PathNotFound(item_type)))
783 }
784 UseStarResult::ItemNotVisible(module_item_id, containing_modules) => {
785 Err(diagnostics
786 .report(identifier, ItemNotVisible(module_item_id, containing_modules)))
787 }
788 },
789 }
790 }
791
792 fn resolve_path_next_segment_concrete(
794 &mut self,
795 diagnostics: &mut SemanticDiagnostics,
796 containing_item: &ResolvedConcreteItem,
797 segment: &ast::PathSegment,
798 item_type: NotFoundItemType,
799 ) -> Maybe<ResolvedConcreteItem> {
800 let syntax_db = self.db.upcast();
801 let identifier = &segment.identifier_ast(syntax_db);
802 let generic_args_syntax = segment.generic_args(syntax_db);
803
804 let ident = identifier.text(syntax_db);
805
806 if identifier.text(syntax_db) == SELF_TYPE_KW {
807 return Err(diagnostics.report(identifier, SelfMustBeFirst));
808 }
809
810 match containing_item {
811 ResolvedConcreteItem::Module(module_id) => {
812 if ident == SUPER_KW {
815 return Err(diagnostics.report(identifier, InvalidPath));
816 }
817 let inner_item_info = self.resolve_module_inner_item(
818 module_id,
819 ident,
820 diagnostics,
821 identifier,
822 item_type,
823 )?;
824
825 self.specialize_generic_inner_item(
826 diagnostics,
827 *module_id,
828 identifier,
829 inner_item_info,
830 segment,
831 )
832 }
833 ResolvedConcreteItem::Type(ty) => {
834 if let TypeLongId::Concrete(ConcreteTypeId::Enum(concrete_enum_id)) =
835 ty.lookup_intern(self.db)
836 {
837 let enum_id = concrete_enum_id.enum_id(self.db);
838 let variants = self
839 .db
840 .enum_variants(enum_id)
841 .map_err(|_| diagnostics.report(identifier, UnknownEnum))?;
842 let variant_id = variants.get(&ident).ok_or_else(|| {
843 diagnostics
844 .report(identifier, NoSuchVariant { enum_id, variant_name: ident })
845 })?;
846 let variant = self.db.variant_semantic(enum_id, *variant_id)?;
847 let concrete_variant =
848 self.db.concrete_enum_variant(concrete_enum_id, &variant)?;
849 Ok(ResolvedConcreteItem::Variant(concrete_variant))
850 } else {
851 Err(diagnostics.report(identifier, InvalidPath))
852 }
853 }
854 ResolvedConcreteItem::SelfTrait(concrete_trait_id) => {
855 let impl_id = ImplLongId::SelfImpl(*concrete_trait_id).intern(self.db);
856 let Some(trait_item_id) = self
857 .db
858 .trait_item_by_name(concrete_trait_id.trait_id(self.db), ident.clone())?
859 else {
860 return Err(diagnostics.report(identifier, InvalidPath));
861 };
862 if let Ok(Some(trait_item_info)) =
863 self.db.trait_item_info_by_name(concrete_trait_id.trait_id(self.db), ident)
864 {
865 self.validate_feature_constraints(diagnostics, identifier, &trait_item_info);
866 }
867 self.data.used_items.insert(LookupItemId::TraitItem(trait_item_id));
868 Ok(match trait_item_id {
869 TraitItemId::Function(trait_function_id) => {
870 ResolvedConcreteItem::Function(self.specialize_function(
871 diagnostics,
872 identifier.stable_ptr().untyped(),
873 GenericFunctionId::Impl(ImplGenericFunctionId {
874 impl_id,
875 function: trait_function_id,
876 }),
877 &generic_args_syntax.unwrap_or_default(),
878 )?)
879 }
880 TraitItemId::Type(trait_type_id) => ResolvedConcreteItem::Type(
881 TypeLongId::ImplType(ImplTypeId::new(impl_id, trait_type_id, self.db))
882 .intern(self.db),
883 ),
884 TraitItemId::Constant(trait_constant_id) => ResolvedConcreteItem::Constant(
885 ConstValue::ImplConstant(ImplConstantId::new(
886 impl_id,
887 trait_constant_id,
888 self.db,
889 ))
890 .intern(self.db),
891 ),
892 TraitItemId::Impl(trait_impl_id) => ResolvedConcreteItem::Impl(
893 ImplLongId::ImplImpl(ImplImplId::new(impl_id, trait_impl_id, self.db))
894 .intern(self.db),
895 ),
896 })
897 }
898 ResolvedConcreteItem::Trait(concrete_trait_id) => {
899 let Some(trait_item_id) = self
900 .db
901 .trait_item_by_name(concrete_trait_id.trait_id(self.db), ident.clone())?
902 else {
903 return Err(diagnostics.report(identifier, InvalidPath));
904 };
905
906 if let Ok(Some(trait_item_info)) =
907 self.db.trait_item_info_by_name(concrete_trait_id.trait_id(self.db), ident)
908 {
909 self.validate_feature_constraints(diagnostics, identifier, &trait_item_info);
910 }
911 self.data.used_items.insert(LookupItemId::TraitItem(trait_item_id));
912
913 match trait_item_id {
914 TraitItemId::Function(trait_function_id) => {
915 let concrete_trait_function = ConcreteTraitGenericFunctionLongId::new(
916 self.db,
917 *concrete_trait_id,
918 trait_function_id,
919 )
920 .intern(self.db);
921 let identifier_stable_ptr = identifier.stable_ptr().untyped();
922 let impl_lookup_context = self.impl_lookup_context();
923 let generic_function =
924 GenericFunctionId::Impl(self.inference().infer_trait_generic_function(
925 concrete_trait_function,
926 &impl_lookup_context,
927 Some(identifier_stable_ptr),
928 ));
929
930 Ok(ResolvedConcreteItem::Function(self.specialize_function(
931 diagnostics,
932 identifier_stable_ptr,
933 generic_function,
934 &generic_args_syntax.unwrap_or_default(),
935 )?))
936 }
937 TraitItemId::Type(trait_type_id) => {
938 let concrete_trait_type =
939 ConcreteTraitTypeId::new(self.db, *concrete_trait_id, trait_type_id);
940
941 let impl_lookup_context = self.impl_lookup_context();
942 let identifier_stable_ptr = identifier.stable_ptr().untyped();
943 let ty = self.inference().infer_trait_type(
944 concrete_trait_type,
945 &impl_lookup_context,
946 Some(identifier_stable_ptr),
947 );
948 Ok(ResolvedConcreteItem::Type(self.inference().rewrite(ty).no_err()))
949 }
950 TraitItemId::Constant(trait_constant_id) => {
951 let concrete_trait_constant = ConcreteTraitConstantLongId::new(
952 self.db,
953 *concrete_trait_id,
954 trait_constant_id,
955 )
956 .intern(self.db);
957
958 let impl_lookup_context = self.impl_lookup_context();
959 let identifier_stable_ptr = identifier.stable_ptr().untyped();
960 let imp_constant_id = self.inference().infer_trait_constant(
961 concrete_trait_constant,
962 &impl_lookup_context,
963 Some(identifier_stable_ptr),
964 );
965 self.inference().solve().ok();
969
970 Ok(ResolvedConcreteItem::Constant(
971 ConstValue::ImplConstant(imp_constant_id).intern(self.db),
972 ))
973 }
974 TraitItemId::Impl(trait_impl_id) => {
975 let concrete_trait_impl = ConcreteTraitImplLongId::new(
976 self.db,
977 *concrete_trait_id,
978 trait_impl_id,
979 )
980 .intern(self.db);
981
982 let impl_lookup_context = self.impl_lookup_context();
983 let identifier_stable_ptr = identifier.stable_ptr().untyped();
984 let impl_impl_id = self.inference().infer_trait_impl(
985 concrete_trait_impl,
986 &impl_lookup_context,
987 Some(identifier_stable_ptr),
988 );
989 self.inference().solve().ok();
993
994 Ok(ResolvedConcreteItem::Impl(
995 ImplLongId::ImplImpl(impl_impl_id).intern(self.db),
996 ))
997 }
998 }
999 }
1000 ResolvedConcreteItem::Impl(impl_id) => {
1001 let concrete_trait_id = self.db.impl_concrete_trait(*impl_id)?;
1002 let trait_id = concrete_trait_id.trait_id(self.db);
1003 let Some(trait_item_id) = self.db.trait_item_by_name(trait_id, ident.clone())?
1004 else {
1005 return Err(diagnostics.report(identifier, InvalidPath));
1006 };
1007 if let Ok(Some(trait_item_info)) = self
1008 .db
1009 .trait_item_info_by_name(concrete_trait_id.trait_id(self.db), ident.clone())
1010 {
1011 self.validate_feature_constraints(diagnostics, identifier, &trait_item_info);
1012 }
1013 if let ImplLongId::Concrete(concrete_impl) = impl_id.lookup_intern(self.db) {
1014 let impl_def_id: ImplDefId = concrete_impl.impl_def_id(self.db);
1015
1016 if let Ok(Some(impl_item_info)) =
1017 self.db.impl_item_info_by_name(impl_def_id, ident)
1018 {
1019 self.validate_feature_constraints(diagnostics, identifier, &impl_item_info);
1020 }
1021 }
1022 self.data.used_items.insert(LookupItemId::TraitItem(trait_item_id));
1023
1024 match trait_item_id {
1025 TraitItemId::Function(trait_function_id) => {
1026 let generic_function_id = GenericFunctionId::Impl(ImplGenericFunctionId {
1027 impl_id: *impl_id,
1028 function: trait_function_id,
1029 });
1030
1031 Ok(ResolvedConcreteItem::Function(self.specialize_function(
1032 diagnostics,
1033 identifier.stable_ptr().untyped(),
1034 generic_function_id,
1035 &generic_args_syntax.unwrap_or_default(),
1036 )?))
1037 }
1038 TraitItemId::Type(trait_type_id) => {
1039 let impl_type_id = ImplTypeId::new(*impl_id, trait_type_id, self.db);
1040 let ty = self
1041 .inference()
1042 .reduce_impl_ty(impl_type_id)
1043 .unwrap_or_else(|_| TypeLongId::ImplType(impl_type_id).intern(self.db));
1044 Ok(ResolvedConcreteItem::Type(ty))
1045 }
1046 TraitItemId::Constant(trait_constant_id) => {
1047 let impl_constant_id =
1048 ImplConstantId::new(*impl_id, trait_constant_id, self.db);
1049
1050 let constant =
1051 self.inference().reduce_impl_constant(impl_constant_id).unwrap_or_else(
1052 |_| ConstValue::ImplConstant(impl_constant_id).intern(self.db),
1053 );
1054
1055 Ok(ResolvedConcreteItem::Constant(constant))
1056 }
1057 TraitItemId::Impl(trait_impl_id) => {
1058 let impl_impl_id = ImplImplId::new(*impl_id, trait_impl_id, self.db);
1059 let imp = self
1060 .inference()
1061 .reduce_impl_impl(impl_impl_id)
1062 .unwrap_or_else(|_| ImplLongId::ImplImpl(impl_impl_id).intern(self.db));
1063
1064 Ok(ResolvedConcreteItem::Impl(imp))
1065 }
1066 }
1067 }
1068 ResolvedConcreteItem::Function(function_id) if ident == "Coupon" => {
1069 if !are_coupons_enabled(self.db, self.module_file_id) {
1070 diagnostics.report(identifier, CouponsDisabled);
1071 }
1072 if matches!(
1073 function_id.get_concrete(self.db).generic_function,
1074 GenericFunctionId::Extern(_)
1075 ) {
1076 return Err(diagnostics.report(identifier, CouponForExternFunctionNotAllowed));
1077 }
1078 Ok(ResolvedConcreteItem::Type(TypeLongId::Coupon(*function_id).intern(self.db)))
1079 }
1080 _ => Err(diagnostics.report(identifier, InvalidPath)),
1081 }
1082 }
1083
1084 fn specialize_generic_module_item(
1086 &mut self,
1087 diagnostics: &mut SemanticDiagnostics,
1088 identifier: &syntax::node::ast::TerminalIdentifier,
1089 generic_item: ResolvedGenericItem,
1090 generic_args_syntax: Option<Vec<ast::GenericArg>>,
1091 ) -> Maybe<ResolvedConcreteItem> {
1092 Ok(match generic_item {
1093 ResolvedGenericItem::GenericConstant(id) => {
1094 ResolvedConcreteItem::Constant(self.db.constant_const_value(id)?)
1095 }
1096 ResolvedGenericItem::Module(module_id) => {
1097 if generic_args_syntax.is_some() {
1098 return Err(diagnostics.report(identifier, UnexpectedGenericArgs));
1099 }
1100 ResolvedConcreteItem::Module(module_id)
1101 }
1102 ResolvedGenericItem::GenericFunction(generic_function) => {
1103 ResolvedConcreteItem::Function(self.specialize_function(
1104 diagnostics,
1105 identifier.stable_ptr().untyped(),
1106 generic_function,
1107 &generic_args_syntax.unwrap_or_default(),
1108 )?)
1109 }
1110 ResolvedGenericItem::GenericType(generic_type) => {
1111 ResolvedConcreteItem::Type(self.specialize_type(
1112 diagnostics,
1113 identifier.stable_ptr().untyped(),
1114 generic_type,
1115 &generic_args_syntax.unwrap_or_default(),
1116 )?)
1117 }
1118 ResolvedGenericItem::GenericTypeAlias(module_type_alias_id) => {
1119 let ty = self.db.module_type_alias_resolved_type(module_type_alias_id)?;
1120 let generic_params =
1121 self.db.module_type_alias_generic_params(module_type_alias_id)?;
1122 let generic_args = self.resolve_generic_args(
1123 diagnostics,
1124 GenericSubstitution::default(),
1125 &generic_params,
1126 &generic_args_syntax.unwrap_or_default(),
1127 identifier.stable_ptr().untyped(),
1128 )?;
1129 ResolvedConcreteItem::Type(
1130 GenericSubstitution::new(&generic_params, &generic_args)
1131 .substitute(self.db, ty)?,
1132 )
1133 }
1134 ResolvedGenericItem::GenericImplAlias(impl_alias_id) => {
1135 let impl_id = self.db.impl_alias_resolved_impl(impl_alias_id)?;
1136 let generic_params = self.db.impl_alias_generic_params(impl_alias_id)?;
1137 let generic_args = self.resolve_generic_args(
1138 diagnostics,
1139 GenericSubstitution::default(),
1140 &generic_params,
1141 &generic_args_syntax.unwrap_or_default(),
1142 identifier.stable_ptr().untyped(),
1143 )?;
1144 ResolvedConcreteItem::Impl(
1145 GenericSubstitution::new(&generic_params, &generic_args)
1146 .substitute(self.db, impl_id)?,
1147 )
1148 }
1149 ResolvedGenericItem::Trait(trait_id) => {
1150 ResolvedConcreteItem::Trait(self.specialize_trait(
1151 diagnostics,
1152 identifier.stable_ptr().untyped(),
1153 trait_id,
1154 &generic_args_syntax.unwrap_or_default(),
1155 )?)
1156 }
1157 ResolvedGenericItem::Impl(impl_def_id) => ResolvedConcreteItem::Impl(
1158 ImplLongId::Concrete(self.specialize_impl(
1159 diagnostics,
1160 identifier.stable_ptr().untyped(),
1161 impl_def_id,
1162 &generic_args_syntax.unwrap_or_default(),
1163 )?)
1164 .intern(self.db),
1165 ),
1166 ResolvedGenericItem::Variant(var) => {
1167 ResolvedConcreteItem::Variant(self.specialize_variant(
1168 diagnostics,
1169 identifier.stable_ptr().untyped(),
1170 var.id,
1171 &generic_args_syntax.unwrap_or_default(),
1172 )?)
1173 }
1174 ResolvedGenericItem::Variable(_) => panic!("Variable is not a module item."),
1175 ResolvedGenericItem::TraitItem(id) => {
1176 panic!("`{}` is not a module item.", id.full_path(self.db.upcast()))
1177 }
1178 })
1179 }
1180
1181 fn resolve_path_using_use_star(
1183 &mut self,
1184 module_id: ModuleId,
1185 identifier: &ast::TerminalIdentifier,
1186 ) -> UseStarResult {
1187 let mut item_info = None;
1188 let mut module_items_found: OrderedHashSet<ModuleItemId> = OrderedHashSet::default();
1189 let imported_modules = self.db.priv_module_use_star_modules(module_id);
1190 for (star_module_id, item_module_id) in &imported_modules.accessible {
1191 if let Some(inner_item_info) =
1192 self.resolve_item_in_imported_module(*item_module_id, identifier)
1193 {
1194 if self.is_item_visible(*item_module_id, &inner_item_info, *star_module_id)
1195 && self.is_item_feature_usable(&inner_item_info)
1196 {
1197 item_info = Some(inner_item_info.clone());
1198 module_items_found.insert(inner_item_info.item_id);
1199 }
1200 }
1201 }
1202 if module_items_found.len() > 1 {
1203 return UseStarResult::AmbiguousPath(module_items_found.iter().cloned().collect());
1204 }
1205 match item_info {
1206 Some(item_info) => UseStarResult::UniquePathFound(item_info),
1207 None => {
1208 let mut containing_modules = vec![];
1209 for star_module_id in &imported_modules.all {
1210 if let Some(inner_item_info) =
1211 self.resolve_item_in_imported_module(*star_module_id, identifier)
1212 {
1213 item_info = Some(inner_item_info.clone());
1214 module_items_found.insert(inner_item_info.item_id);
1215 containing_modules.push(*star_module_id);
1216 }
1217 }
1218 if let Some(item_info) = item_info {
1219 if module_items_found.len() > 1 {
1220 UseStarResult::AmbiguousPath(module_items_found.iter().cloned().collect())
1221 } else {
1222 UseStarResult::ItemNotVisible(item_info.item_id, containing_modules)
1223 }
1224 } else {
1225 UseStarResult::PathNotFound
1226 }
1227 }
1228 }
1229 }
1230
1231 fn resolve_item_in_imported_module(
1233 &mut self,
1234 module_id: ModuleId,
1235 identifier: &ast::TerminalIdentifier,
1236 ) -> Option<ModuleItemInfo> {
1237 let inner_item_info =
1238 self.db.module_item_info_by_name(module_id, identifier.text(self.db.upcast()));
1239 if let Ok(Some(inner_item_info)) = inner_item_info {
1240 self.data.used_items.insert(LookupItemId::ModuleItem(inner_item_info.item_id));
1241 return Some(inner_item_info);
1242 }
1243 None
1244 }
1245
1246 fn resolve_path_next_segment_generic(
1248 &mut self,
1249 diagnostics: &mut SemanticDiagnostics,
1250 containing_item: &ResolvedGenericItem,
1251 identifier: &ast::TerminalIdentifier,
1252 item_type: NotFoundItemType,
1253 ) -> Maybe<ResolvedGenericItem> {
1254 let syntax_db = self.db.upcast();
1255 let ident = identifier.text(syntax_db);
1256 match containing_item {
1257 ResolvedGenericItem::Module(module_id) => {
1258 let inner_item_info = self.resolve_module_inner_item(
1259 module_id,
1260 ident,
1261 diagnostics,
1262 identifier,
1263 item_type,
1264 )?;
1265
1266 self.validate_module_item_usability(
1267 diagnostics,
1268 *module_id,
1269 identifier,
1270 &inner_item_info,
1271 );
1272 self.data.used_items.insert(LookupItemId::ModuleItem(inner_item_info.item_id));
1273 ResolvedGenericItem::from_module_item(self.db, inner_item_info.item_id)
1274 }
1275 ResolvedGenericItem::GenericType(GenericTypeId::Enum(enum_id)) => {
1276 let variants = self.db.enum_variants(*enum_id)?;
1277 let variant_id = variants.get(&ident).ok_or_else(|| {
1278 diagnostics.report(
1279 identifier,
1280 NoSuchVariant { enum_id: *enum_id, variant_name: ident },
1281 )
1282 })?;
1283 let variant = self.db.variant_semantic(*enum_id, *variant_id)?;
1284 Ok(ResolvedGenericItem::Variant(variant))
1285 }
1286 _ => Err(diagnostics.report(identifier, InvalidPath)),
1287 }
1288 }
1289
1290 fn determine_base_item_in_local_scope(
1292 &mut self,
1293 identifier: &ast::TerminalIdentifier,
1294 ) -> Option<ResolvedConcreteItem> {
1295 let syntax_db = self.db.upcast();
1296 let ident = identifier.text(syntax_db);
1297
1298 if let Some(generic_param_id) = self.data.generic_param_by_name.get(&ident) {
1300 let item = match generic_param_id.kind(self.db.upcast()) {
1301 GenericKind::Type => ResolvedConcreteItem::Type(
1302 TypeLongId::GenericParameter(*generic_param_id).intern(self.db),
1303 ),
1304 GenericKind::Const => ResolvedConcreteItem::Constant(
1305 ConstValue::Generic(*generic_param_id).intern(self.db),
1306 ),
1307 GenericKind::Impl => ResolvedConcreteItem::Impl(
1308 ImplLongId::GenericParameter(*generic_param_id).intern(self.db),
1309 ),
1310 GenericKind::NegImpl => return None,
1311 };
1312 return Some(item);
1313 }
1314 None
1317 }
1318
1319 fn determine_base(
1322 &mut self,
1323 identifier: &ast::TerminalIdentifier,
1324 statement_env: Option<&mut Environment>,
1325 ) -> ResolvedBase {
1326 let syntax_db = self.db.upcast();
1327 let ident = identifier.text(syntax_db);
1328 let module_id = self.module_file_id.0;
1329 if let Some(env) = statement_env {
1330 if let Some(inner_generic_arg) = get_statement_item_by_name(env, &ident) {
1331 return ResolvedBase::StatementEnvironment(inner_generic_arg);
1332 }
1333 }
1334
1335 if let Ok(Some(_)) = self.db.module_item_by_name(module_id, ident.clone()) {
1337 return ResolvedBase::Module(module_id);
1338 }
1339
1340 if ident == CRATE_KW {
1342 return ResolvedBase::Crate(self.owning_crate_id);
1343 }
1344 if let Some(dep) = self.settings.dependencies.get(ident.as_str()) {
1347 let dep_crate_id =
1348 CrateLongId::Real { name: ident, discriminator: dep.discriminator.clone() }
1349 .intern(self.db);
1350 let configs = self.db.crate_configs();
1351 if !configs.contains_key(&dep_crate_id) {
1352 let get_long_id = |crate_id: CrateId| crate_id.lookup_intern(self.db);
1353 panic!(
1354 "Invalid crate dependency: {:?}\nconfigured crates: {:#?}",
1355 get_long_id(dep_crate_id),
1356 configs.keys().cloned().map(get_long_id).collect_vec()
1357 );
1358 }
1359
1360 return ResolvedBase::Crate(dep_crate_id);
1361 }
1362 if ident == CORELIB_CRATE_NAME {
1364 return ResolvedBase::Crate(CrateId::core(self.db));
1365 }
1366 if ident == STARKNET_CRATE_NAME {
1368 return ResolvedBase::Module(self.prelude_submodule());
1370 }
1371 match self.resolve_path_using_use_star(module_id, identifier) {
1373 UseStarResult::UniquePathFound(inner_module_item) => {
1374 return ResolvedBase::FoundThroughGlobalUse {
1375 item_info: inner_module_item,
1376 containing_module: module_id,
1377 };
1378 }
1379 UseStarResult::AmbiguousPath(module_items) => {
1380 return ResolvedBase::Ambiguous(module_items);
1381 }
1382 UseStarResult::PathNotFound => {}
1383 UseStarResult::ItemNotVisible(module_item_id, containing_modules) => {
1384 let prelude = self.prelude_submodule();
1385 if let Ok(Some(_)) = self.db.module_item_by_name(prelude, ident) {
1386 return ResolvedBase::Module(prelude);
1387 }
1388 return ResolvedBase::ItemNotVisible(module_item_id, containing_modules);
1389 }
1390 }
1391 ResolvedBase::Module(self.prelude_submodule())
1392 }
1393
1394 pub fn prelude_submodule(&self) -> ModuleId {
1396 let prelude_submodule_name = self.settings.edition.prelude_submodule_name();
1397 let core_prelude_submodule = core_submodule(self.db, "prelude");
1398 get_submodule(self.db, core_prelude_submodule, prelude_submodule_name).unwrap_or_else(
1399 || {
1400 panic!(
1401 "expected prelude submodule `{prelude_submodule_name}` not found in \
1402 `core::prelude`."
1403 )
1404 },
1405 )
1406 }
1407
1408 fn specialize_trait(
1410 &mut self,
1411 diagnostics: &mut SemanticDiagnostics,
1412 stable_ptr: SyntaxStablePtrId,
1413 trait_id: TraitId,
1414 generic_args: &[ast::GenericArg],
1415 ) -> Maybe<ConcreteTraitId> {
1416 let generic_params = self
1418 .db
1419 .trait_generic_params(trait_id)
1420 .map_err(|_| diagnostics.report(stable_ptr, UnknownTrait))?;
1421 let generic_args = self.resolve_generic_args(
1422 diagnostics,
1423 GenericSubstitution::default(),
1424 &generic_params,
1425 generic_args,
1426 stable_ptr,
1427 )?;
1428
1429 Ok(ConcreteTraitLongId { trait_id, generic_args }.intern(self.db))
1430 }
1431
1432 fn specialize_impl(
1434 &mut self,
1435 diagnostics: &mut SemanticDiagnostics,
1436 stable_ptr: SyntaxStablePtrId,
1437 impl_def_id: ImplDefId,
1438 generic_args: &[ast::GenericArg],
1439 ) -> Maybe<ConcreteImplId> {
1440 let generic_params = self
1442 .db
1443 .impl_def_generic_params(impl_def_id)
1444 .map_err(|_| diagnostics.report(stable_ptr, UnknownImpl))?;
1445 let generic_args = self.resolve_generic_args(
1446 diagnostics,
1447 GenericSubstitution::default(),
1448 &generic_params,
1449 generic_args,
1450 stable_ptr,
1451 )?;
1452
1453 Ok(ConcreteImplLongId { impl_def_id, generic_args }.intern(self.db))
1454 }
1455
1456 fn specialize_variant(
1458 &mut self,
1459 diagnostics: &mut SemanticDiagnostics,
1460 stable_ptr: SyntaxStablePtrId,
1461 variant_id: VariantId,
1462 generic_args: &[ast::GenericArg],
1463 ) -> Maybe<ConcreteVariant> {
1464 let concrete_enum_id = ConcreteEnumLongId {
1465 enum_id: variant_id.enum_id(self.db.upcast()),
1466 generic_args: self.resolve_generic_args(
1467 diagnostics,
1468 GenericSubstitution::default(),
1469 &self.db.enum_generic_params(variant_id.enum_id(self.db.upcast()))?,
1470 generic_args,
1471 stable_ptr,
1472 )?,
1473 }
1474 .intern(self.db);
1475 self.db.concrete_enum_variant(
1476 concrete_enum_id,
1477 &self.db.variant_semantic(variant_id.enum_id(self.db.upcast()), variant_id)?,
1478 )
1479 }
1480
1481 pub fn specialize_function(
1483 &mut self,
1484 diagnostics: &mut SemanticDiagnostics,
1485 stable_ptr: SyntaxStablePtrId,
1486 generic_function: GenericFunctionId,
1487 generic_args: &[ast::GenericArg],
1488 ) -> Maybe<FunctionId> {
1489 let generic_params: Vec<_> = generic_function.generic_params(self.db)?;
1491 let generic_args = self.resolve_generic_args(
1492 diagnostics,
1493 GenericSubstitution::default(),
1494 &generic_params,
1495 generic_args,
1496 stable_ptr,
1497 )?;
1498
1499 Ok(FunctionLongId { function: ConcreteFunction { generic_function, generic_args } }
1500 .intern(self.db))
1501 }
1502
1503 pub fn specialize_type(
1505 &mut self,
1506 diagnostics: &mut SemanticDiagnostics,
1507 stable_ptr: SyntaxStablePtrId,
1508 generic_type: GenericTypeId,
1509 generic_args: &[ast::GenericArg],
1510 ) -> Maybe<TypeId> {
1511 let generic_params = self
1512 .db
1513 .generic_type_generic_params(generic_type)
1514 .map_err(|_| diagnostics.report(stable_ptr, UnknownType))?;
1515 let generic_args = self.resolve_generic_args(
1516 diagnostics,
1517 GenericSubstitution::default(),
1518 &generic_params,
1519 generic_args,
1520 stable_ptr,
1521 )?;
1522
1523 Ok(TypeLongId::Concrete(ConcreteTypeId::new(self.db, generic_type, generic_args))
1524 .intern(self.db))
1525 }
1526
1527 pub fn impl_lookup_context(&self) -> ImplLookupContext {
1528 let mut lookup_context =
1529 ImplLookupContext::new(self.module_file_id.0, self.generic_params.clone());
1530
1531 if let TraitOrImplContext::Impl(impl_def_id) = &self.trait_or_impl_ctx {
1532 let Ok(generic_params) = self.db.impl_def_generic_params(*impl_def_id) else {
1533 return lookup_context;
1534 };
1535 let generic_args = generic_params_to_args(generic_params.as_slice(), self.db);
1536 let impl_id: ConcreteImplId =
1537 ConcreteImplLongId { impl_def_id: *impl_def_id, generic_args }.intern(self.db);
1538 lookup_context.insert_impl(ImplLongId::Concrete(impl_id).intern(self.db));
1539 }
1540 lookup_context
1541 }
1542
1543 pub fn resolve_generic_args(
1547 &mut self,
1548 diagnostics: &mut SemanticDiagnostics,
1549 mut substitution: GenericSubstitution,
1550 generic_params: &[GenericParam],
1551 generic_args_syntax: &[ast::GenericArg],
1552 stable_ptr: SyntaxStablePtrId,
1553 ) -> Maybe<Vec<GenericArgumentId>> {
1554 let mut resolved_args = vec![];
1555 let arg_syntax_per_param =
1556 self.get_arg_syntax_per_param(diagnostics, generic_params, generic_args_syntax)?;
1557
1558 for generic_param in generic_params.iter() {
1559 let generic_param = substitution.substitute(self.db, generic_param.clone())?;
1560 let generic_arg = self.resolve_generic_arg(
1561 &generic_param,
1562 arg_syntax_per_param
1563 .get(&generic_param.id())
1564 .and_then(|arg_syntax| {
1565 if let ast::GenericArgValue::Expr(expr) = arg_syntax {
1566 Some(expr.expr(self.db.upcast()))
1567 } else {
1568 None
1569 }
1570 })
1571 .as_ref(),
1572 stable_ptr,
1573 diagnostics,
1574 )?;
1575 resolved_args.push(generic_arg);
1576 substitution.insert(generic_param.id(), generic_arg);
1577 }
1578
1579 Ok(resolved_args)
1580 }
1581
1582 fn get_arg_syntax_per_param(
1584 &self,
1585 diagnostics: &mut SemanticDiagnostics,
1586 generic_params: &[GenericParam],
1587 generic_args_syntax: &[ast::GenericArg],
1588 ) -> Maybe<UnorderedHashMap<GenericParamId, ast::GenericArgValue>> {
1589 let syntax_db = self.db.upcast();
1590 let mut arg_syntax_per_param =
1591 UnorderedHashMap::<GenericParamId, ast::GenericArgValue>::default();
1592 let mut last_named_arg_index = None;
1593 let generic_param_by_name = generic_params
1594 .iter()
1595 .enumerate()
1596 .filter_map(|(i, param)| Some((param.id().name(self.db.upcast())?, (i, param.id()))))
1597 .collect::<UnorderedHashMap<_, _>>();
1598 for (idx, generic_arg_syntax) in generic_args_syntax.iter().enumerate() {
1599 match generic_arg_syntax {
1600 ast::GenericArg::Named(arg_syntax) => {
1601 let name = arg_syntax.name(syntax_db).text(syntax_db);
1602 let Some((index, generic_param_id)) = generic_param_by_name.get(&name) else {
1603 return Err(diagnostics.report(arg_syntax, UnknownGenericParam(name)));
1604 };
1605 if let Some(prev_index) = last_named_arg_index {
1606 if prev_index > index {
1607 return Err(diagnostics.report(arg_syntax, GenericArgOutOfOrder(name)));
1608 }
1609 }
1610 last_named_arg_index = Some(index);
1611 if arg_syntax_per_param
1612 .insert(*generic_param_id, arg_syntax.value(syntax_db))
1613 .is_some()
1614 {
1615 return Err(diagnostics.report(arg_syntax, GenericArgDuplicate(name)));
1616 }
1617 }
1618 ast::GenericArg::Unnamed(arg_syntax) => {
1619 if last_named_arg_index.is_some() {
1620 return Err(diagnostics.report(arg_syntax, PositionalGenericAfterNamed));
1621 }
1622 let generic_param = generic_params.get(idx).ok_or_else(|| {
1623 diagnostics.report(
1624 arg_syntax,
1625 TooManyGenericArguments {
1626 expected: generic_params.len(),
1627 actual: generic_args_syntax.len(),
1628 },
1629 )
1630 })?;
1631 assert_eq!(
1632 arg_syntax_per_param
1633 .insert(generic_param.id(), arg_syntax.value(syntax_db)),
1634 None,
1635 "Unexpected duplication in ordered params."
1636 );
1637 }
1638 }
1639 }
1640 Ok(arg_syntax_per_param)
1641 }
1642
1643 fn resolve_generic_arg(
1647 &mut self,
1648 generic_param: &GenericParam,
1649 generic_arg_syntax_opt: Option<&ast::Expr>,
1650 stable_ptr: SyntaxStablePtrId,
1651 diagnostics: &mut SemanticDiagnostics,
1652 ) -> Result<GenericArgumentId, cairo_lang_diagnostics::DiagnosticAdded> {
1653 let Some(generic_arg_syntax) = generic_arg_syntax_opt else {
1654 let lookup_context = self.impl_lookup_context();
1655 let inference = &mut self.data.inference_data.inference(self.db);
1656 return inference
1657 .infer_generic_arg(generic_param, lookup_context, Some(stable_ptr))
1658 .map_err(|err_set| {
1659 inference.report_on_pending_error(err_set, diagnostics, stable_ptr)
1660 });
1661 };
1662 Ok(match generic_param {
1663 GenericParam::Type(_) => {
1664 let ty = resolve_type(self.db, diagnostics, self, generic_arg_syntax);
1665 GenericArgumentId::Type(ty)
1666 }
1667 GenericParam::Const(const_param) => {
1668 let environment = Environment::empty();
1672
1673 let mut resolver_data =
1676 ResolverData::new(self.module_file_id, self.inference_data.inference_id);
1677 std::mem::swap(&mut self.data, &mut resolver_data);
1678
1679 let mut ctx = ComputationContext::new(
1680 self.db,
1681 diagnostics,
1682 Resolver::with_data(self.db, resolver_data),
1683 None,
1684 environment,
1685 ContextFunction::Global,
1686 );
1687 let value = compute_expr_semantic(&mut ctx, generic_arg_syntax);
1688
1689 let const_value = resolve_const_expr_and_evaluate(
1690 self.db,
1691 &mut ctx,
1692 &value,
1693 generic_arg_syntax.stable_ptr().untyped(),
1694 const_param.ty,
1695 false,
1696 );
1697
1698 std::mem::swap(&mut ctx.resolver.data, &mut self.data);
1700
1701 GenericArgumentId::Constant(const_value.intern(self.db))
1702 }
1703
1704 GenericParam::Impl(param) => {
1705 let expr_path = try_extract_matches!(generic_arg_syntax, ast::Expr::Path)
1706 .ok_or_else(|| diagnostics.report(generic_arg_syntax, UnknownImpl))?;
1707 let resolved_impl = match self.resolve_concrete_path(
1708 diagnostics,
1709 expr_path,
1710 NotFoundItemType::Impl,
1711 )? {
1712 ResolvedConcreteItem::Impl(resolved_impl) => resolved_impl,
1713 ResolvedConcreteItem::SelfTrait(concrete_trait_id) => {
1714 ImplLongId::SelfImpl(concrete_trait_id).intern(self.db)
1715 }
1716 _ => return Err(diagnostics.report(generic_arg_syntax, UnknownImpl)),
1717 };
1718 let impl_def_concrete_trait = self.db.impl_concrete_trait(resolved_impl)?;
1719 let expected_concrete_trait = param.concrete_trait?;
1720 if let Err(err_set) = self
1721 .inference()
1722 .conform_traits(impl_def_concrete_trait, expected_concrete_trait)
1723 {
1724 let diag_added = diagnostics.report(
1725 generic_arg_syntax,
1726 TraitMismatch {
1727 expected_trt: expected_concrete_trait,
1728 actual_trt: impl_def_concrete_trait,
1729 },
1730 );
1731 self.inference().consume_reported_error(err_set, diag_added);
1732 } else {
1733 for (trait_ty, ty1) in param.type_constraints.iter() {
1734 let ty0 = TypeLongId::ImplType(ImplTypeId::new(
1735 resolved_impl,
1736 *trait_ty,
1737 self.db,
1738 ))
1739 .intern(self.db);
1740 let _ = self.inference().conform_ty(ty0, *ty1).map_err(|err_set| {
1741 self.inference().report_on_pending_error(
1742 err_set,
1743 diagnostics,
1744 stable_ptr,
1745 )
1746 });
1747 }
1748 }
1749 GenericArgumentId::Impl(resolved_impl)
1750 }
1751 GenericParam::NegImpl(_) => {
1752 return Err(diagnostics.report(generic_arg_syntax, ArgPassedToNegativeImpl));
1753 }
1754 })
1755 }
1756 pub fn ignore_visibility_checks(&self, module_id: ModuleId) -> bool {
1759 let module_crate = module_id.owning_crate(self.db.upcast());
1760 let module_edition =
1761 self.db.crate_config(module_crate).map(|c| c.settings.edition).unwrap_or_default();
1762 module_edition.ignore_visibility()
1763 || self.settings.edition.ignore_visibility() && module_crate == self.db.core_crate()
1764 }
1765
1766 pub fn validate_feature_constraints<T: HasFeatureKind>(
1771 &self,
1772 diagnostics: &mut SemanticDiagnostics,
1773 identifier: &ast::TerminalIdentifier,
1774 item_info: &T,
1775 ) {
1776 match &item_info.feature_kind() {
1777 FeatureKind::Unstable { feature, note }
1778 if !self.data.feature_config.allowed_features.contains(feature) =>
1779 {
1780 diagnostics.report(
1781 identifier,
1782 UnstableFeature { feature_name: feature.clone(), note: note.clone() },
1783 );
1784 }
1785 FeatureKind::Deprecated { feature, note }
1786 if !self.data.feature_config.allow_deprecated
1787 && !self.data.feature_config.allowed_features.contains(feature) =>
1788 {
1789 diagnostics.report(
1790 identifier,
1791 DeprecatedFeature { feature_name: feature.clone(), note: note.clone() },
1792 );
1793 }
1794 FeatureKind::Internal { feature, note }
1795 if !self.data.feature_config.allowed_features.contains(feature) =>
1796 {
1797 diagnostics.report(
1798 identifier,
1799 InternalFeature { feature_name: feature.clone(), note: note.clone() },
1800 );
1801 }
1802 _ => {}
1803 }
1804 }
1805
1806 fn validate_module_item_usability(
1809 &self,
1810 diagnostics: &mut SemanticDiagnostics,
1811 containing_module_id: ModuleId,
1812 identifier: &ast::TerminalIdentifier,
1813 item_info: &ModuleItemInfo,
1814 ) {
1815 if !self.is_item_visible(containing_module_id, item_info, self.module_file_id.0) {
1816 diagnostics.report(identifier, ItemNotVisible(item_info.item_id, vec![]));
1817 }
1818
1819 self.validate_feature_constraints(diagnostics, identifier, item_info);
1820 }
1821
1822 fn is_item_visible(
1824 &self,
1825 containing_module_id: ModuleId,
1826 item_info: &ModuleItemInfo,
1827 user_module: ModuleId,
1828 ) -> bool {
1829 let db = self.db.upcast();
1830 self.ignore_visibility_checks(containing_module_id)
1831 || visibility::peek_visible_in(
1832 db,
1833 item_info.visibility,
1834 containing_module_id,
1835 user_module,
1836 )
1837 }
1838
1839 fn is_item_feature_usable(&self, item_info: &ModuleItemInfo) -> bool {
1841 match &item_info.feature_kind {
1842 FeatureKind::Unstable { feature, .. }
1843 | FeatureKind::Deprecated { feature, .. }
1844 | FeatureKind::Internal { feature, .. } => {
1845 self.data.feature_config.allowed_features.contains(feature)
1846 }
1847 _ => true,
1848 }
1849 }
1850
1851 fn handle_same_impl_trait(
1857 &mut self,
1858 diagnostics: &mut SemanticDiagnostics,
1859 specialized_item: &mut ResolvedConcreteItem,
1860 generic_args_syntax_slice: &[ast::GenericArg],
1861 segment_stable_ptr: SyntaxStablePtrId,
1862 ) {
1863 match *specialized_item {
1864 ResolvedConcreteItem::Trait(current_segment_concrete_trait) => {
1865 match self.trait_or_impl_ctx {
1866 TraitOrImplContext::None => {}
1867 TraitOrImplContext::Trait(ctx_trait) => {
1868 if self
1869 .warn_trait_in_same_trait(
1870 diagnostics,
1871 current_segment_concrete_trait.trait_id(self.db),
1872 generic_args_syntax_slice,
1873 ctx_trait,
1874 segment_stable_ptr,
1875 )
1876 .is_err()
1877 {
1878 *specialized_item =
1879 ResolvedConcreteItem::SelfTrait(current_segment_concrete_trait);
1880 }
1881 }
1882 TraitOrImplContext::Impl(ctx_impl_def_id) => {
1883 self.warn_trait_in_its_impl(
1884 diagnostics,
1885 current_segment_concrete_trait,
1886 ctx_impl_def_id,
1887 segment_stable_ptr,
1888 )
1889 .ok();
1890 }
1891 };
1892 }
1893 ResolvedConcreteItem::Impl(current_segment_impl_id) => {
1894 if let TraitOrImplContext::Impl(ctx_impl) = self.trait_or_impl_ctx {
1895 let current_segment_concrete_impl_id = extract_matches!(
1898 current_segment_impl_id.lookup_intern(self.db),
1899 ImplLongId::Concrete
1900 );
1901 self.warn_impl_in_same_impl(
1902 diagnostics,
1903 current_segment_concrete_impl_id.impl_def_id(self.db),
1904 generic_args_syntax_slice,
1905 ctx_impl,
1906 segment_stable_ptr,
1907 )
1908 .ok();
1909 }
1910 }
1911 _ => {}
1912 };
1913 }
1914
1915 fn warn_impl_in_same_impl(
1918 &mut self,
1919 diagnostics: &mut SemanticDiagnostics,
1920 current_segment_impl_def_id: ImplDefId,
1921 current_segment_generic_args: &[ast::GenericArg],
1922 ctx_impl: ImplDefId,
1923 segment_stable_ptr: SyntaxStablePtrId,
1924 ) -> Maybe<()> {
1925 if current_segment_impl_def_id != ctx_impl {
1926 return Ok(());
1927 }
1928
1929 let generic_params = self.db.impl_def_generic_params(ctx_impl)?;
1930 self.compare_segment_args_to_params(
1931 diagnostics,
1932 current_segment_generic_args,
1933 generic_params,
1934 segment_stable_ptr,
1935 ImplInImplMustBeExplicit,
1936 ImplItemForbiddenInTheImpl,
1937 )
1938 }
1939
1940 fn warn_trait_in_its_impl(
1943 &mut self,
1944 diagnostics: &mut SemanticDiagnostics,
1945 current_segment_concrete_trait_id: ConcreteTraitId,
1946 impl_ctx: ImplDefId,
1947 segment_stable_ptr: SyntaxStablePtrId,
1948 ) -> Maybe<()> {
1949 let ctx_impl_trait = self.db.impl_def_trait(impl_ctx)?;
1950 if current_segment_concrete_trait_id.trait_id(self.db) != ctx_impl_trait {
1951 return Ok(());
1952 }
1953
1954 let ctx_impl_concrete_trait = self.db.impl_def_concrete_trait(impl_ctx)?;
1955 if ctx_impl_concrete_trait.generic_args(self.db)
1956 == current_segment_concrete_trait_id.generic_args(self.db)
1957 {
1958 return Err(diagnostics.report(segment_stable_ptr, TraitItemForbiddenInItsImpl));
1959 }
1960 Ok(())
1961 }
1962
1963 fn warn_trait_in_same_trait(
1966 &mut self,
1967 diagnostics: &mut SemanticDiagnostics,
1968 current_segment_trait_id: TraitId,
1969 current_segment_generic_args: &[ast::GenericArg],
1970 ctx_trait: TraitId,
1971 segment_stable_ptr: SyntaxStablePtrId,
1972 ) -> Maybe<()> {
1973 if current_segment_trait_id != ctx_trait {
1974 return Ok(());
1975 }
1976
1977 let generic_params = self.db.trait_generic_params(ctx_trait)?;
1978 self.compare_segment_args_to_params(
1979 diagnostics,
1980 current_segment_generic_args,
1981 generic_params,
1982 segment_stable_ptr,
1983 TraitInTraitMustBeExplicit,
1984 TraitItemForbiddenInTheTrait,
1985 )
1986 }
1987
1988 fn compare_segment_args_to_params(
1995 &mut self,
1996 diagnostics: &mut SemanticDiagnostics,
1997 current_segment_generic_args: &[ast::GenericArg],
1998 generic_params: Vec<GenericParam>,
1999 segment_stable_ptr: SyntaxStablePtrId,
2000 must_be_explicit_error: SemanticDiagnosticKind,
2001 item_forbidden_in_itself_explicit_error: SemanticDiagnosticKind,
2002 ) -> Maybe<()> {
2003 if current_segment_generic_args.len() < generic_params.len() {
2006 return Err(diagnostics.report(segment_stable_ptr, must_be_explicit_error));
2007 }
2008 let resolved_args = self.resolve_generic_args(
2009 diagnostics,
2010 GenericSubstitution::default(),
2011 &generic_params,
2012 current_segment_generic_args,
2013 segment_stable_ptr,
2014 )?;
2015
2016 if generic_params
2017 .iter()
2018 .zip_eq(resolved_args.iter())
2019 .all(|(gparam, garg)| gparam.as_arg(self.db) == *garg)
2020 {
2021 return Err(
2022 diagnostics.report(segment_stable_ptr, item_forbidden_in_itself_explicit_error)
2023 );
2024 }
2025 Ok(())
2026 }
2027
2028 fn specialize_generic_statement_arg(
2030 &mut self,
2031 segment: &ast::PathSegment,
2032 diagnostics: &mut SemanticDiagnostics,
2033 identifier: &ast::TerminalIdentifier,
2034 inner_generic_item: ResolvedGenericItem,
2035 generic_args_syntax: Option<Vec<ast::GenericArg>>,
2036 ) -> ResolvedConcreteItem {
2037 let segment_stable_ptr = segment.stable_ptr().untyped();
2038 let mut specialized_item = self
2039 .specialize_generic_module_item(
2040 diagnostics,
2041 identifier,
2042 inner_generic_item,
2043 generic_args_syntax.clone(),
2044 )
2045 .unwrap();
2046 self.handle_same_impl_trait(
2047 diagnostics,
2048 &mut specialized_item,
2049 &generic_args_syntax.unwrap_or_default(),
2050 segment_stable_ptr,
2051 );
2052 specialized_item
2053 }
2054}
2055
2056fn resolve_self_segment(
2059 db: &dyn SemanticGroup,
2060 diagnostics: &mut SemanticDiagnostics,
2061 identifier: &ast::TerminalIdentifier,
2062 trait_or_impl_ctx: &TraitOrImplContext,
2063) -> Option<Maybe<ResolvedConcreteItem>> {
2064 require(identifier.text(db.upcast()) == SELF_TYPE_KW)?;
2065 Some(resolve_actual_self_segment(db, diagnostics, identifier, trait_or_impl_ctx))
2066}
2067
2068fn resolve_actual_self_segment(
2070 db: &dyn SemanticGroup,
2071 diagnostics: &mut SemanticDiagnostics,
2072 identifier: &ast::TerminalIdentifier,
2073 trait_or_impl_ctx: &TraitOrImplContext,
2074) -> Maybe<ResolvedConcreteItem> {
2075 match trait_or_impl_ctx {
2076 TraitOrImplContext::None => Err(diagnostics.report(identifier, SelfNotSupportedInContext)),
2077 TraitOrImplContext::Trait(trait_id) => {
2078 let generic_parameters = db.trait_generic_params(*trait_id)?;
2079 let concrete_trait_id = ConcreteTraitLongId {
2080 trait_id: *trait_id,
2081 generic_args: generic_params_to_args(&generic_parameters, db),
2082 }
2083 .intern(db);
2084 Ok(ResolvedConcreteItem::SelfTrait(concrete_trait_id))
2085 }
2086 TraitOrImplContext::Impl(impl_def_id) => {
2087 let generic_parameters = db.impl_def_generic_params(*impl_def_id)?;
2088 let impl_id = ImplLongId::Concrete(
2089 ConcreteImplLongId {
2090 impl_def_id: *impl_def_id,
2091 generic_args: generic_params_to_args(&generic_parameters, db),
2092 }
2093 .intern(db),
2094 );
2095 Ok(ResolvedConcreteItem::Impl(impl_id.intern(db)))
2096 }
2097 }
2098}
2099
2100enum ResolvedBase {
2102 Module(ModuleId),
2104 Crate(CrateId),
2106 StatementEnvironment(ResolvedGenericItem),
2108 FoundThroughGlobalUse { item_info: ModuleItemInfo, containing_module: ModuleId },
2110 Ambiguous(Vec<ModuleItemId>),
2112 ItemNotVisible(ModuleItemId, Vec<ModuleId>),
2114}
2115
2116struct ResolvePathInnerCallbacks<ResolvedItem, ResolveFirst, ResolveNext, Validate, Mark>
2118where
2119 ResolveFirst: FnMut(
2120 &mut Resolver<'_>,
2121 &mut SemanticDiagnostics,
2122 &mut Peekable<std::slice::Iter<'_, ast::PathSegment>>,
2123 Option<&mut Environment>,
2124 ) -> Maybe<ResolvedItem>,
2125 ResolveNext: FnMut(
2126 &mut Resolver<'_>,
2127 &mut SemanticDiagnostics,
2128 &ResolvedItem,
2129 &ast::PathSegment,
2130 NotFoundItemType,
2131 ) -> Maybe<ResolvedItem>,
2132 Validate: FnMut(&mut SemanticDiagnostics, &ast::PathSegment) -> Maybe<()>,
2133 Mark: FnMut(
2134 &mut ResolvedItems,
2135 &dyn SemanticGroup,
2136 &syntax::node::ast::PathSegment,
2137 ResolvedItem,
2138 ),
2139{
2140 resolved_item_type: PhantomData<ResolvedItem>,
2142 resolve_path_first_segment: ResolveFirst,
2144 resolve_path_next_segment: ResolveNext,
2146 validate_segment: Validate,
2149 mark: Mark,
2150}