1use crate::{
2 decl_engine::{parsed_engine::ParsedDeclEngineGet, parsed_id::ParsedDeclId, *},
3 engine_threading::{Engines, PartialEqWithEngines, PartialEqWithEnginesContext},
4 language::{
5 parsed::{Declaration, FunctionDeclaration},
6 ty::{self, TyDecl, TyStorageDecl},
7 Visibility,
8 },
9 namespace::*,
10 semantic_analysis::{ast_node::ConstShadowingMode, GenericShadowingMode},
11 type_system::*,
12};
13
14use super::{ResolvedDeclaration, TraitMap};
15
16use parking_lot::RwLock;
17use sway_error::{
18 error::{CompileError, ShadowingSource},
19 handler::{ErrorEmitted, Handler},
20};
21use sway_types::{span::Span, IdentUnique, Named, Spanned};
22
23use std::{collections::HashMap, sync::Arc};
24
25pub enum ResolvedFunctionDecl {
26 Parsed(ParsedDeclId<FunctionDeclaration>),
27 Typed(DeclRefFunction),
28}
29
30impl ResolvedFunctionDecl {
31 pub fn expect_typed(self) -> DeclRefFunction {
32 match self {
33 ResolvedFunctionDecl::Parsed(_) => panic!(),
34 ResolvedFunctionDecl::Typed(fn_ref) => fn_ref,
35 }
36 }
37}
38
39pub(super) type SymbolMap = HashMap<Ident, ResolvedDeclaration>;
42pub(super) type SymbolUniqueMap = HashMap<IdentUnique, ResolvedDeclaration>;
43
44type SourceIdent = Ident;
45
46pub(super) type PreludeSynonyms = HashMap<Ident, (ModulePathBuf, ResolvedDeclaration)>;
47pub(super) type GlobSynonyms =
48 HashMap<Ident, Vec<(ModulePathBuf, ResolvedDeclaration, Visibility)>>;
49pub(super) type ItemSynonyms = HashMap<
50 Ident,
51 (
52 Option<SourceIdent>,
53 ModulePathBuf,
54 ResolvedDeclaration,
55 Visibility,
56 ),
57>;
58
59pub type LexicalScopeId = usize;
62
63pub type LexicalScopePath = Vec<LexicalScopeId>;
66
67#[derive(Clone, Debug, Default)]
70pub struct LexicalScope {
71 pub items: Items,
73 pub children: Vec<LexicalScopeId>,
75 pub parent: Option<LexicalScopeId>,
77 pub visitor_parent: Option<LexicalScopeId>,
80 pub declaration: Option<ResolvedDeclaration>,
83}
84
85#[derive(Clone, Debug, Default)]
87pub struct Items {
88 pub(crate) symbols: SymbolMap,
90
91 pub(crate) symbols_unique_while_collecting_unifications: Arc<RwLock<SymbolUniqueMap>>,
96
97 pub(crate) implemented_traits: TraitMap,
98 pub(crate) prelude_synonyms: PreludeSynonyms,
105 pub(crate) use_glob_synonyms: GlobSynonyms,
112 pub(crate) use_item_synonyms: ItemSynonyms,
117 pub(crate) declared_storage: Option<DeclRefStorage>,
119}
120
121impl Items {
122 pub fn symbols(&self) -> &SymbolMap {
124 &self.symbols
125 }
126
127 #[allow(clippy::too_many_arguments)]
128 pub fn apply_storage_load(
129 &self,
130 handler: &Handler,
131 engines: &Engines,
132 namespace: &Namespace,
133 namespace_names: &[Ident],
134 fields: &[Ident],
135 storage_fields: &[ty::TyStorageField],
136 storage_keyword_span: Span,
137 ) -> Result<(ty::TyStorageAccess, TypeId), ErrorEmitted> {
138 match self.declared_storage {
139 Some(ref decl_ref) => {
140 let storage = engines.de().get_storage(&decl_ref.id().clone());
141 storage.apply_storage_load(
142 handler,
143 engines,
144 namespace,
145 namespace_names,
146 fields,
147 storage_fields,
148 storage_keyword_span,
149 )
150 }
151 None => Err(handler.emit_err(CompileError::NoDeclaredStorage {
152 span: fields[0].span(),
153 })),
154 }
155 }
156
157 pub fn set_storage_declaration(
158 &mut self,
159 handler: &Handler,
160 decl_ref: DeclRefStorage,
161 ) -> Result<(), ErrorEmitted> {
162 if self.declared_storage.is_some() {
163 return Err(handler.emit_err(CompileError::MultipleStorageDeclarations {
164 span: decl_ref.span(),
165 }));
166 }
167 self.declared_storage = Some(decl_ref);
168 Ok(())
169 }
170
171 pub fn get_all_declared_symbols(&self) -> Vec<&Ident> {
172 let mut keys: Vec<_> = self.symbols().keys().collect();
173 keys.sort();
174 keys
175 }
176
177 pub fn resolve_symbol(
178 &self,
179 handler: &Handler,
180 engines: &Engines,
181 symbol: &Ident,
182 current_mod_path: &ModulePathBuf,
183 ) -> Result<Option<(ResolvedDeclaration, ModulePathBuf)>, ErrorEmitted> {
184 if let Some(decl) = self.symbols.get(symbol) {
186 return Ok(Some((decl.clone(), current_mod_path.clone())));
187 }
188
189 if let Some((_, decl_path, decl, _)) = self.use_item_synonyms.get(symbol) {
191 return Ok(Some((decl.clone(), decl_path.clone())));
192 }
193
194 if let Some(decls) = self.use_glob_synonyms.get(symbol) {
196 if decls.len() == 1 {
197 return Ok(Some((decls[0].1.clone(), decls[0].0.clone())));
198 } else if decls.is_empty() {
199 return Err(handler.emit_err(CompileError::Internal(
200 "The name {symbol} was bound in a star import, but no corresponding module paths were found",
201 symbol.span(),
202 )));
203 } else {
204 return Err(handler.emit_err(CompileError::SymbolWithMultipleBindings {
205 name: symbol.clone(),
206 paths: decls
207 .iter()
208 .map(|(path, decl, _)| {
209 get_path_for_decl(path, decl, engines, ¤t_mod_path[0]).join("::")
210 })
211 .collect(),
212 span: symbol.span(),
213 }));
214 }
215 }
216
217 if let Some((decl_path, decl)) = self.prelude_synonyms.get(symbol) {
219 return Ok(Some((decl.clone(), decl_path.clone())));
220 }
221
222 Ok(None)
223 }
224
225 pub(crate) fn insert_parsed_symbol(
226 handler: &Handler,
227 engines: &Engines,
228 module: &mut Module,
229 name: Ident,
230 item: Declaration,
231 const_shadowing_mode: ConstShadowingMode,
232 generic_shadowing_mode: GenericShadowingMode,
233 ) -> Result<(), ErrorEmitted> {
234 Self::insert_symbol(
235 handler,
236 engines,
237 module,
238 name,
239 ResolvedDeclaration::Parsed(item),
240 const_shadowing_mode,
241 generic_shadowing_mode,
242 false,
243 )
244 }
245
246 #[allow(clippy::too_many_arguments)]
247 pub(crate) fn insert_typed_symbol(
248 handler: &Handler,
249 engines: &Engines,
250 module: &mut Module,
251 name: Ident,
252 item: ty::TyDecl,
253 const_shadowing_mode: ConstShadowingMode,
254 generic_shadowing_mode: GenericShadowingMode,
255 collecting_unifications: bool,
256 ) -> Result<(), ErrorEmitted> {
257 Self::insert_symbol(
258 handler,
259 engines,
260 module,
261 name,
262 ResolvedDeclaration::Typed(item),
263 const_shadowing_mode,
264 generic_shadowing_mode,
265 collecting_unifications,
266 )
267 }
268
269 #[allow(clippy::too_many_arguments)]
270 pub(crate) fn insert_symbol(
271 handler: &Handler,
272 engines: &Engines,
273 module: &mut Module,
274 name: Ident,
275 item: ResolvedDeclaration,
276 const_shadowing_mode: ConstShadowingMode,
277 generic_shadowing_mode: GenericShadowingMode,
278 collecting_unifications: bool,
279 ) -> Result<(), ErrorEmitted> {
280 let parsed_decl_engine = engines.pe();
281 let decl_engine = engines.de();
282
283 #[allow(unused)]
284 let append_shadowing_error_parsed =
285 |ident: &Ident,
286 decl: &Declaration,
287 is_use: bool,
288 is_alias: bool,
289 item: &Declaration,
290 const_shadowing_mode: ConstShadowingMode| {
291 use Declaration::*;
292 match (
293 ident,
294 decl,
295 is_use,
296 is_alias,
297 &item,
298 const_shadowing_mode,
299 generic_shadowing_mode,
300 ) {
301 (
310 constant_ident,
311 ConstantDeclaration(decl_id),
312 is_imported_constant,
313 is_alias,
314 VariableDeclaration { .. },
315 _,
316 _,
317 ) => {
318 handler.emit_err(CompileError::ConstantsCannotBeShadowed {
319 shadowing_source: ShadowingSource::LetVar,
320 name: (&name).into(),
321 constant_span: constant_ident.span(),
322 constant_decl_span: if is_imported_constant {
323 parsed_decl_engine.get(decl_id).span.clone()
324 } else {
325 Span::dummy()
326 },
327 is_alias,
328 });
329 }
330 (
332 configurable_ident,
333 ConfigurableDeclaration(_),
334 _,
335 _,
336 VariableDeclaration { .. },
337 _,
338 _,
339 ) => {
340 handler.emit_err(CompileError::ConfigurablesCannotBeShadowed {
341 shadowing_source: ShadowingSource::LetVar,
342 name: (&name).into(),
343 configurable_span: configurable_ident.span(),
344 });
345 }
346 (
348 constant_ident,
349 ConstantDeclaration(decl_id),
350 is_imported_constant,
351 is_alias,
352 ConstantDeclaration { .. },
353 ConstShadowingMode::Sequential,
354 _,
355 ) => {
356 handler.emit_err(CompileError::ConstantsCannotBeShadowed {
357 shadowing_source: ShadowingSource::Const,
358 name: (&name).into(),
359 constant_span: constant_ident.span(),
360 constant_decl_span: if is_imported_constant {
361 parsed_decl_engine.get(decl_id).span.clone()
362 } else {
363 Span::dummy()
364 },
365 is_alias,
366 });
367 }
368 (
370 configurable_ident,
371 ConfigurableDeclaration(_),
372 _,
373 _,
374 ConstantDeclaration { .. },
375 ConstShadowingMode::Sequential,
376 _,
377 ) => {
378 handler.emit_err(CompileError::ConfigurablesCannotBeShadowed {
379 shadowing_source: ShadowingSource::Const,
380 name: (&name).into(),
381 configurable_span: configurable_ident.span(),
382 });
383 }
384 (_, VariableDeclaration(decl_id), _, _, ConstantDeclaration { .. }, _, _) => {
386 handler.emit_err(CompileError::ConstantShadowsVariable {
387 name: (&name).into(),
388 variable_span: parsed_decl_engine.get(decl_id).name.span(),
389 });
390 }
391 (
393 constant_ident,
394 ConstantDeclaration { .. },
395 _,
396 _,
397 ConstantDeclaration { .. },
398 ConstShadowingMode::ItemStyle,
399 _,
400 ) => {
401 handler.emit_err(CompileError::ConstantDuplicatesConstantOrConfigurable {
402 existing_constant_or_configurable: "Constant",
403 new_constant_or_configurable: "Constant",
404 name: (&name).into(),
405 existing_span: constant_ident.span(),
406 });
407 }
408 (
410 configurable_ident,
411 ConfigurableDeclaration { .. },
412 _,
413 _,
414 ConstantDeclaration { .. },
415 ConstShadowingMode::ItemStyle,
416 _,
417 ) => {
418 handler.emit_err(CompileError::ConstantDuplicatesConstantOrConfigurable {
419 existing_constant_or_configurable: "Configurable",
420 new_constant_or_configurable: "Constant",
421 name: (&name).into(),
422 existing_span: configurable_ident.span(),
423 });
424 }
425 (
427 constant_ident,
428 ConstantDeclaration { .. },
429 _,
430 _,
431 ConfigurableDeclaration { .. },
432 ConstShadowingMode::ItemStyle,
433 _,
434 ) => {
435 handler.emit_err(CompileError::ConstantDuplicatesConstantOrConfigurable {
436 existing_constant_or_configurable: "Constant",
437 new_constant_or_configurable: "Configurable",
438 name: (&name).into(),
439 existing_span: constant_ident.span(),
440 });
441 }
442 (
446 _,
447 StructDeclaration { .. }
448 | EnumDeclaration { .. }
449 | TypeAliasDeclaration { .. }
450 | TraitDeclaration { .. }
451 | AbiDeclaration { .. },
452 _,
453 _,
454 StructDeclaration { .. }
455 | EnumDeclaration { .. }
456 | TypeAliasDeclaration { .. }
457 | TraitDeclaration { .. }
458 | AbiDeclaration { .. },
459 _,
460 _,
461 ) => {
462 handler.emit_err(CompileError::MultipleDefinitionsOfName {
463 name: name.clone(),
464 span: name.span(),
465 });
466 }
467 _ => {}
468 }
469 };
470
471 let append_shadowing_error_typed =
472 |ident: &Ident,
473 decl: &ty::TyDecl,
474 is_use: bool,
475 is_alias: bool,
476 item: &ty::TyDecl,
477 const_shadowing_mode: ConstShadowingMode| {
478 use ty::TyDecl::*;
479 match (
480 ident,
481 decl,
482 is_use,
483 is_alias,
484 &item,
485 const_shadowing_mode,
486 generic_shadowing_mode,
487 ) {
488 (
497 constant_ident,
498 ConstantDecl(constant_decl),
499 is_imported_constant,
500 is_alias,
501 VariableDecl { .. },
502 _,
503 _,
504 ) => {
505 handler.emit_err(CompileError::ConstantsCannotBeShadowed {
506 shadowing_source: ShadowingSource::LetVar,
507 name: (&name).into(),
508 constant_span: constant_ident.span(),
509 constant_decl_span: if is_imported_constant {
510 decl_engine.get(&constant_decl.decl_id).span.clone()
511 } else {
512 Span::dummy()
513 },
514 is_alias,
515 });
516 }
517 (configurable_ident, ConfigurableDecl(_), _, _, VariableDecl { .. }, _, _) => {
519 handler.emit_err(CompileError::ConfigurablesCannotBeShadowed {
520 shadowing_source: ShadowingSource::LetVar,
521 name: (&name).into(),
522 configurable_span: configurable_ident.span(),
523 });
524 }
525 (
527 constant_ident,
528 ConstantDecl(constant_decl),
529 is_imported_constant,
530 is_alias,
531 ConstantDecl { .. },
532 ConstShadowingMode::Sequential,
533 _,
534 ) => {
535 handler.emit_err(CompileError::ConstantsCannotBeShadowed {
536 shadowing_source: ShadowingSource::Const,
537 name: (&name).into(),
538 constant_span: constant_ident.span(),
539 constant_decl_span: if is_imported_constant {
540 decl_engine.get(&constant_decl.decl_id).span.clone()
541 } else {
542 Span::dummy()
543 },
544 is_alias,
545 });
546 }
547 (
549 configurable_ident,
550 ConfigurableDecl(_),
551 _,
552 _,
553 ConstantDecl { .. },
554 ConstShadowingMode::Sequential,
555 _,
556 ) => {
557 handler.emit_err(CompileError::ConfigurablesCannotBeShadowed {
558 shadowing_source: ShadowingSource::Const,
559 name: (&name).into(),
560 configurable_span: configurable_ident.span(),
561 });
562 }
563 (_, VariableDecl(variable_decl), _, _, ConstantDecl { .. }, _, _) => {
565 handler.emit_err(CompileError::ConstantShadowsVariable {
566 name: (&name).into(),
567 variable_span: variable_decl.name.span(),
568 });
569 }
570 (
572 constant_ident,
573 ConstantDecl { .. },
574 _,
575 _,
576 ConstantDecl { .. },
577 ConstShadowingMode::ItemStyle,
578 _,
579 ) => {
580 handler.emit_err(CompileError::ConstantDuplicatesConstantOrConfigurable {
581 existing_constant_or_configurable: "Constant",
582 new_constant_or_configurable: "Constant",
583 name: (&name).into(),
584 existing_span: constant_ident.span(),
585 });
586 }
587 (
589 configurable_ident,
590 ConfigurableDecl { .. },
591 _,
592 _,
593 ConstantDecl { .. },
594 ConstShadowingMode::ItemStyle,
595 _,
596 ) => {
597 handler.emit_err(CompileError::ConstantDuplicatesConstantOrConfigurable {
598 existing_constant_or_configurable: "Configurable",
599 new_constant_or_configurable: "Constant",
600 name: (&name).into(),
601 existing_span: configurable_ident.span(),
602 });
603 }
604 (
606 constant_ident,
607 ConstantDecl { .. },
608 _,
609 _,
610 ConfigurableDecl { .. },
611 ConstShadowingMode::ItemStyle,
612 _,
613 ) => {
614 handler.emit_err(CompileError::ConstantDuplicatesConstantOrConfigurable {
615 existing_constant_or_configurable: "Constant",
616 new_constant_or_configurable: "Configurable",
617 name: (&name).into(),
618 existing_span: constant_ident.span(),
619 });
620 }
621 (
625 _,
626 StructDecl { .. }
627 | EnumDecl { .. }
628 | TypeAliasDecl { .. }
629 | TraitDecl { .. }
630 | AbiDecl { .. },
631 _,
632 _,
633 StructDecl { .. }
634 | EnumDecl { .. }
635 | TypeAliasDecl { .. }
636 | TraitDecl { .. }
637 | AbiDecl { .. },
638 _,
639 _,
640 ) => {
641 handler.emit_err(CompileError::MultipleDefinitionsOfName {
642 name: name.clone(),
643 span: name.span(),
644 });
645 }
646 (
648 _,
649 GenericTypeForFunctionScope { .. },
650 _,
651 _,
652 GenericTypeForFunctionScope { .. },
653 _,
654 GenericShadowingMode::Disallow,
655 ) => {
656 handler.emit_err(CompileError::GenericShadowsGeneric {
657 name: (&name).into(),
658 });
659 }
660 _ => {}
661 }
662 };
663
664 let append_shadowing_error =
665 |ident: &Ident,
666 decl: &ResolvedDeclaration,
667 is_use: bool,
668 is_alias: bool,
669 item: &ResolvedDeclaration,
670 const_shadowing_mode: ConstShadowingMode| {
671 if const_shadowing_mode == ConstShadowingMode::Allow {
672 return;
673 }
674 match (decl, item) {
675 (ResolvedDeclaration::Typed(_decl), ResolvedDeclaration::Parsed(_item)) => {}
679 (ResolvedDeclaration::Parsed(_decl), ResolvedDeclaration::Parsed(_item)) => {}
680 (ResolvedDeclaration::Typed(decl), ResolvedDeclaration::Typed(item)) => {
681 append_shadowing_error_typed(
682 ident,
683 decl,
684 is_use,
685 is_alias,
686 item,
687 const_shadowing_mode,
688 )
689 }
690 _ => unreachable!(),
691 }
692 };
693
694 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
695 if let Some((ident, decl)) = lexical_scope.items.symbols.get_key_value(&name) {
696 append_shadowing_error(
697 ident,
698 decl,
699 false,
700 false,
701 &item.clone(),
702 const_shadowing_mode,
703 );
704 }
705
706 if let Some((ident, (imported_ident, _, decl, _))) =
707 lexical_scope.items.use_item_synonyms.get_key_value(&name)
708 {
709 append_shadowing_error(
710 ident,
711 decl,
712 true,
713 imported_ident.is_some(),
714 &item,
715 const_shadowing_mode,
716 );
717 }
718 Ok(None::<()>)
719 });
720
721 if collecting_unifications {
722 module
723 .current_items_mut()
724 .symbols_unique_while_collecting_unifications
725 .write()
726 .insert(name.clone().into(), item.clone());
727 }
728
729 module.current_items_mut().symbols.insert(name, item);
730
731 Ok(())
732 }
733
734 pub(crate) fn insert_glob_use_symbol(
741 &mut self,
742 engines: &Engines,
743 symbol: Ident,
744 src_path: ModulePathBuf,
745 decl: &ResolvedDeclaration,
746 visibility: Visibility,
747 ) {
748 if let Some(cur_decls) = self.use_glob_synonyms.get_mut(&symbol) {
749 let ctx = PartialEqWithEnginesContext::new(engines);
751 match cur_decls
752 .iter()
753 .position(|(_cur_path, cur_decl, _cur_visibility)| cur_decl.eq(decl, &ctx))
754 {
755 Some(index) if matches!(visibility, Visibility::Public) => {
756 cur_decls[index] = (src_path.to_vec(), decl.clone(), visibility);
759 }
760 Some(_) => {
761 }
763 None => {
764 cur_decls.push((src_path.to_vec(), decl.clone(), visibility));
766 }
767 }
768 } else {
769 let new_vec = vec![(src_path.to_vec(), decl.clone(), visibility)];
770 self.use_glob_synonyms.insert(symbol, new_vec);
771 }
772 }
773
774 pub(crate) fn check_symbol(&self, name: &Ident) -> Result<ResolvedDeclaration, CompileError> {
775 self.symbols
776 .get(name)
777 .cloned()
778 .ok_or_else(|| CompileError::SymbolNotFound {
779 name: name.clone(),
780 span: name.span(),
781 })
782 }
783
784 pub(crate) fn check_symbols_unique_while_collecting_unifications(
785 &self,
786 name: &Ident,
787 ) -> Result<ResolvedDeclaration, CompileError> {
788 self.symbols_unique_while_collecting_unifications
789 .read()
790 .get(&name.into())
791 .cloned()
792 .ok_or_else(|| CompileError::SymbolNotFound {
793 name: name.clone(),
794 span: name.span(),
795 })
796 }
797
798 pub(crate) fn clear_symbols_unique_while_collecting_unifications(&self) {
799 self.symbols_unique_while_collecting_unifications
800 .write()
801 .clear();
802 }
803
804 pub(crate) fn has_storage_declared(&self) -> bool {
805 self.declared_storage.is_some()
806 }
807
808 pub fn get_declared_storage(&self, decl_engine: &DeclEngine) -> Option<TyStorageDecl> {
809 self.declared_storage
810 .as_ref()
811 .map(|decl_ref| (*decl_engine.get_storage(decl_ref)).clone())
812 }
813
814 pub(crate) fn get_storage_field_descriptors(
815 &self,
816 handler: &Handler,
817 decl_engine: &DeclEngine,
818 ) -> Result<Vec<ty::TyStorageField>, ErrorEmitted> {
819 match self.get_declared_storage(decl_engine) {
820 Some(storage) => Ok(storage.fields.clone()),
821 None => {
822 let msg = "unknown source location";
823 let span = Span::new(msg.into(), 0, msg.len(), None).unwrap();
824 Err(handler.emit_err(CompileError::NoDeclaredStorage { span }))
825 }
826 }
827 }
828}
829
830pub(super) fn get_path_for_decl(
831 path: &[sway_types::BaseIdent],
832 decl: &ResolvedDeclaration,
833 engines: &Engines,
834 package_name: &Ident,
835) -> Vec<String> {
836 let skip_package_name = path[0] == *package_name;
838 let mut path_names = path
839 .iter()
840 .skip(if skip_package_name { 1 } else { 0 })
841 .map(|x| x.to_string())
842 .collect::<Vec<_>>();
843 match decl {
844 ResolvedDeclaration::Parsed(decl) => {
845 if let Declaration::EnumVariantDeclaration(decl) = decl {
846 let enum_decl = engines.pe().get_enum(&decl.enum_ref);
847 path_names.push(enum_decl.name().to_string())
848 };
849 }
850 ResolvedDeclaration::Typed(decl) => {
851 if let TyDecl::EnumVariantDecl(ty::EnumVariantDecl { enum_ref, .. }) = decl {
852 path_names.push(enum_ref.name().to_string())
853 };
854 }
855 }
856 path_names
857}