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