1use crate::{
2 decl_engine::DeclRef,
3 language::{parsed::*, Visibility},
4 ty::{self, TyDecl},
5 Engines, Ident,
6};
7
8use super::{
9 module::Module, package::Package, trait_map::TraitMap, ModuleName, ModulePath, ModulePathBuf,
10 ResolvedDeclaration,
11};
12
13use rustc_hash::FxHasher;
14use std::hash::BuildHasherDefault;
15
16use sway_error::{
17 error::CompileError,
18 handler::{ErrorEmitted, Handler},
19};
20use sway_types::{
21 constants::{CONTRACT_ID, PRELUDE, STD},
22 span::Span,
23 Spanned,
24};
25use sway_utils::iter_prefixes;
26
27#[derive(Clone, Debug)]
29pub struct Namespace {
30 pub(crate) current_package: Package,
35 pub(crate) current_mod_path: ModulePathBuf,
41}
42
43impl Namespace {
44 pub fn new(
50 handler: &Handler,
51 engines: &Engines,
52 package: Package,
53 import_std_prelude_into_root: bool,
54 ) -> Result<Self, ErrorEmitted> {
55 let name = package.name().clone();
56 let mut res = Self {
57 current_package: package,
58 current_mod_path: vec![name],
59 };
60
61 if import_std_prelude_into_root {
62 res.import_implicits(handler, engines)?;
63 }
64 Ok(res)
65 }
66
67 pub fn current_package(self) -> Package {
68 self.current_package
69 }
70
71 pub fn current_package_ref(&self) -> &Package {
72 &self.current_package
73 }
74
75 fn module_in_current_package(&self, mod_path: &ModulePathBuf) -> Option<&Module> {
76 assert!(self.current_package.check_path_is_in_package(mod_path));
77 self.current_package.module_from_absolute_path(mod_path)
78 }
79
80 pub fn current_module(&self) -> &Module {
81 self.module_in_current_package(&self.current_mod_path)
82 .unwrap_or_else(|| {
83 panic!(
84 "Could not retrieve submodule for mod_path: {:?}",
85 self.current_mod_path
86 );
87 })
88 }
89
90 pub fn current_module_mut(&mut self) -> &mut Module {
91 let package_relative_path = Package::package_relative_path(&self.current_mod_path);
92 self.current_package_root_module_mut()
93 .submodule_mut(&package_relative_path)
94 .unwrap_or_else(|| {
95 panic!(
96 "Could not retrieve submodule for mod_path: {:?}",
97 package_relative_path
98 );
99 })
100 }
101
102 pub(crate) fn current_module_has_submodule(&self, submod_name: &Ident) -> bool {
103 self.current_module()
104 .submodule(&[submod_name.clone()])
105 .is_some()
106 }
107
108 pub fn current_package_name(&self) -> &Ident {
109 self.current_package.name()
110 }
111
112 pub fn current_mod_path(&self) -> &ModulePathBuf {
114 &self.current_mod_path
115 }
116
117 pub fn prepend_module_path<'a>(
119 &'a self,
120 prefixes: impl IntoIterator<Item = &'a Ident>,
121 ) -> ModulePathBuf {
122 self.current_mod_path
123 .iter()
124 .chain(prefixes)
125 .cloned()
126 .collect()
127 }
128
129 pub fn parsed_path_to_full_path(
131 &self,
132 _engines: &Engines,
133 parsed_path: &ModulePathBuf,
134 is_relative_to_package_root: bool,
135 ) -> ModulePathBuf {
136 if is_relative_to_package_root {
137 let mut path = vec![self.current_package_name().clone()];
139 for ident in parsed_path.iter() {
140 path.push(ident.clone())
141 }
142 path
143 } else if self.current_module_has_submodule(&parsed_path[0]) {
144 self.prepend_module_path(parsed_path)
147 } else if self.module_is_external(parsed_path) {
148 parsed_path.to_vec()
150 } else {
151 self.prepend_module_path(parsed_path)
154 }
155 }
156
157 pub fn current_package_root_module(&self) -> &Module {
158 self.current_package.root_module()
159 }
160
161 fn current_package_root_module_mut(&mut self) -> &mut Module {
162 self.current_package.root_module_mut()
163 }
164
165 pub fn external_packages(
166 &self,
167 ) -> &im::HashMap<ModuleName, Package, BuildHasherDefault<FxHasher>> {
168 &self.current_package.external_packages
169 }
170
171 pub(crate) fn get_external_package(&self, package_name: &String) -> Option<&Package> {
172 self.current_package.external_packages.get(package_name)
173 }
174
175 pub(super) fn exists_as_external(&self, package_name: &String) -> bool {
176 self.get_external_package(package_name).is_some()
177 }
178
179 pub fn module_from_absolute_path(&self, path: &ModulePathBuf) -> Option<&Module> {
180 self.current_package.module_from_absolute_path(path)
181 }
182
183 pub fn require_module_from_absolute_path(
185 &self,
186 handler: &Handler,
187 path: &ModulePathBuf,
188 ) -> Result<&Module, ErrorEmitted> {
189 if path.is_empty() {
190 return Err(handler.emit_err(CompileError::Internal(
191 "Found empty absolute mod path",
192 Span::dummy(),
193 )));
194 }
195 let is_in_current_package = self.current_package.check_path_is_in_package(path);
196 match self.module_from_absolute_path(path) {
197 Some(module) => Ok(module),
198 None => Err(handler.emit_err(crate::namespace::module::module_not_found(
199 path,
200 is_in_current_package,
201 ))),
202 }
203 }
204
205 pub(crate) fn module_is_submodule_of(
216 &self,
217 absolute_module_path: &ModulePath,
218 true_if_same: bool,
219 ) -> bool {
220 if self.current_mod_path.len() < absolute_module_path.len() {
221 return false;
222 }
223
224 let is_submodule = absolute_module_path
225 .iter()
226 .zip(self.current_mod_path.iter())
227 .all(|(left, right)| left == right);
228
229 if is_submodule {
230 if self.current_mod_path.len() == absolute_module_path.len() {
231 true_if_same
232 } else {
233 true
234 }
235 } else {
236 false
237 }
238 }
239
240 pub(crate) fn module_is_external(&self, absolute_module_path: &ModulePath) -> bool {
243 assert!(!absolute_module_path.is_empty(), "Absolute module path must have at least one element, because it always contains the package name.");
244
245 self.current_package_name() != &absolute_module_path[0]
246 }
247
248 pub fn package_exists(&self, name: &Ident) -> bool {
249 self.module_from_absolute_path(&vec![name.clone()])
250 .is_some()
251 }
252
253 pub(crate) fn module_has_binding(
254 &self,
255 engines: &Engines,
256 mod_path: &ModulePathBuf,
257 symbol: &Ident,
258 ) -> bool {
259 let dummy_handler = Handler::default();
260 if let Some(module) = self.module_from_absolute_path(mod_path) {
261 module
262 .resolve_symbol(&dummy_handler, engines, symbol)
263 .is_ok()
264 } else {
265 false
266 }
267 }
268
269 fn import_implicits(
271 &mut self,
272 handler: &Handler,
273 engines: &Engines,
274 ) -> Result<(), ErrorEmitted> {
275 let package_name = self.current_package_name().to_string();
277 let prelude_ident = Ident::new_no_span(PRELUDE.to_string());
278
279 if package_name == STD {
280 } else {
282 let std_string = STD.to_string();
284 if self.exists_as_external(&std_string) {
286 self.prelude_import(
287 handler,
288 engines,
289 &[Ident::new_no_span(std_string), prelude_ident],
290 )?
291 }
292 }
293
294 if self.current_package.is_contract_package() && self.current_mod_path.len() > 1 {
297 self.item_import_to_current_module(
299 handler,
300 engines,
301 &[Ident::new_no_span(package_name)],
302 &Ident::new_no_span(CONTRACT_ID.to_string()),
303 None,
304 Visibility::Private,
305 )?
306 }
307
308 Ok(())
309 }
310
311 pub(crate) fn enter_submodule(
312 &mut self,
313 handler: &Handler,
314 engines: &Engines,
315 mod_name: Ident,
316 visibility: Visibility,
317 module_span: Span,
318 check_implicits: bool,
319 ) -> Result<(), ErrorEmitted> {
320 let mut import_implicits = false;
321
322 if !self
324 .current_module()
325 .submodules()
326 .contains_key(&mod_name.to_string())
327 && check_implicits
328 {
329 self.current_module_mut()
331 .add_new_submodule(&mod_name, visibility, Some(module_span));
332 import_implicits = true;
333 }
334
335 self.current_mod_path.push(mod_name.clone());
337
338 if import_implicits {
340 self.import_implicits(handler, engines)?;
341 }
342
343 Ok(())
344 }
345
346 pub fn push_submodule(
348 &mut self,
349 handler: &Handler,
350 engines: &Engines,
351 mod_name: Ident,
352 visibility: Visibility,
353 module_span: Span,
354 check_implicits: bool,
355 ) -> Result<(), ErrorEmitted> {
356 match self.enter_submodule(
357 handler,
358 engines,
359 mod_name,
360 visibility,
361 module_span,
362 check_implicits,
363 ) {
364 Ok(_) => Ok(()),
365 Err(e) => Err(e),
366 }
367 }
368
369 pub fn pop_submodule(&mut self) {
371 self.current_mod_path.pop();
372 }
373
374 fn prelude_import(
384 &mut self,
385 handler: &Handler,
386 engines: &Engines,
387 src: &ModulePath,
388 ) -> Result<(), ErrorEmitted> {
389 let src_mod = self.require_module_from_absolute_path(handler, &src.to_vec())?;
390
391 let mut imports = vec![];
392
393 assert!(src_mod.root_items().symbols.is_empty());
395
396 let mut symbols = src_mod
398 .root_items()
399 .use_item_synonyms
400 .keys()
401 .clone()
402 .collect::<Vec<_>>();
403 symbols.sort();
404 for symbol in symbols {
405 let (_, path, decl, src_visibility) = &src_mod.root_items().use_item_synonyms[symbol];
406 assert!(matches!(src_visibility, Visibility::Public));
408 imports.push((symbol.clone(), decl.clone(), path.clone()))
409 }
410
411 let mut symbols = src_mod
415 .root_items()
416 .use_glob_synonyms
417 .keys()
418 .clone()
419 .collect::<Vec<_>>();
420 symbols.sort();
421 for symbol in symbols {
422 let bindings = &src_mod.root_items().use_glob_synonyms[symbol];
423 for (path, decl, src_visibility) in bindings.iter() {
424 assert!(matches!(src_visibility, Visibility::Public));
426 imports.push((symbol.clone(), decl.clone(), path.clone()))
427 }
428 }
429
430 let implemented_traits = src_mod.root_items().implemented_traits.clone();
431 let dst_mod = self.current_module_mut();
432
433 dst_mod
434 .current_items_mut()
435 .implemented_traits
436 .extend(implemented_traits, engines);
437
438 let dst_prelude_synonyms = &mut dst_mod.current_items_mut().prelude_synonyms;
439 imports.iter().for_each(|(symbol, decl, path)| {
440 assert!(!dst_prelude_synonyms.contains_key(symbol));
442 dst_prelude_synonyms.insert(symbol.clone(), (path.clone(), decl.clone()));
443 });
444
445 Ok(())
446 }
447
448 pub(crate) fn star_import_to_current_module(
455 &mut self,
456 handler: &Handler,
457 engines: &Engines,
458 src: &ModulePath,
459 visibility: Visibility,
460 ) -> Result<(), ErrorEmitted> {
461 self.check_module_visibility(handler, src)?;
462
463 let src_mod = self.require_module_from_absolute_path(handler, &src.to_vec())?;
464
465 let mut decls_and_item_imports = vec![];
466
467 let mut symbols = src_mod
469 .root_items()
470 .symbols
471 .keys()
472 .clone()
473 .collect::<Vec<_>>();
474 symbols.sort();
475 for symbol in symbols {
476 let decl = &src_mod.root_items().symbols[symbol];
477 if self.is_ancestor_of_current_module(src) || decl.visibility(engines).is_public() {
478 decls_and_item_imports.push((symbol.clone(), decl.clone(), src.to_vec()));
479 }
480 }
481 let mut symbols = src_mod
484 .root_items()
485 .use_item_synonyms
486 .keys()
487 .clone()
488 .collect::<Vec<_>>();
489 symbols.sort();
490 for symbol in symbols {
491 let (_, path, decl, src_visibility) = &src_mod.root_items().use_item_synonyms[symbol];
492 if src_visibility.is_public() {
493 decls_and_item_imports.push((symbol.clone(), decl.clone(), path.clone()))
494 }
495 }
496
497 let mut glob_imports = vec![];
501 let mut symbols = src_mod
502 .root_items()
503 .use_glob_synonyms
504 .keys()
505 .clone()
506 .collect::<Vec<_>>();
507 symbols.sort();
508 for symbol in symbols {
509 let bindings = &src_mod.root_items().use_glob_synonyms[symbol];
510 if !decls_and_item_imports
512 .iter()
513 .any(|(other_symbol, _, _)| symbol == other_symbol)
514 {
515 for (path, decl, src_visibility) in bindings.iter() {
516 if src_visibility.is_public() {
517 glob_imports.push((symbol.clone(), decl.clone(), path.clone()))
518 }
519 }
520 }
521 }
522
523 let implemented_traits = src_mod.root_items().implemented_traits.clone();
524 let dst_mod = self.current_module_mut();
525
526 dst_mod
527 .current_items_mut()
528 .implemented_traits
529 .extend(implemented_traits, engines);
530
531 decls_and_item_imports
532 .iter()
533 .chain(glob_imports.iter())
534 .for_each(|(symbol, decl, path)| {
535 dst_mod.current_items_mut().insert_glob_use_symbol(
536 engines,
537 symbol.clone(),
538 path.clone(),
539 decl,
540 visibility,
541 )
542 });
543
544 Ok(())
545 }
546
547 pub(crate) fn variant_star_import_to_current_module(
551 &mut self,
552 handler: &Handler,
553 engines: &Engines,
554 src: &ModulePath,
555 enum_name: &Ident,
556 visibility: Visibility,
557 ) -> Result<(), ErrorEmitted> {
558 self.check_module_visibility(handler, src)?;
559
560 let parsed_decl_engine = engines.pe();
561 let decl_engine = engines.de();
562
563 let (decl, path) = self.item_lookup(handler, engines, enum_name, src, false)?;
564
565 match decl {
566 ResolvedDeclaration::Parsed(Declaration::EnumDeclaration(decl_id)) => {
567 let enum_decl = parsed_decl_engine.get_enum(&decl_id);
568
569 for variant in enum_decl.variants.iter() {
570 let variant_name = &variant.name;
571 let variant_decl =
572 Declaration::EnumVariantDeclaration(EnumVariantDeclaration {
573 enum_ref: decl_id,
574 variant_name: variant_name.clone(),
575 variant_decl_span: variant.span.clone(),
576 });
577
578 self.current_module_mut()
580 .current_items_mut()
581 .insert_glob_use_symbol(
582 engines,
583 variant_name.clone(),
584 path.clone(),
585 &ResolvedDeclaration::Parsed(variant_decl),
586 visibility,
587 );
588 }
589 }
590 ResolvedDeclaration::Typed(TyDecl::EnumDecl(ty::EnumDecl { decl_id, .. })) => {
591 let enum_decl = decl_engine.get_enum(&decl_id);
592 let enum_ref = DeclRef::new(
593 enum_decl.call_path.suffix.clone(),
594 decl_id,
595 enum_decl.span(),
596 );
597
598 for variant_decl in enum_decl.variants.iter() {
599 let variant_name = &variant_decl.name;
600 let decl =
601 ResolvedDeclaration::Typed(TyDecl::EnumVariantDecl(ty::EnumVariantDecl {
602 enum_ref: enum_ref.clone(),
603 variant_name: variant_name.clone(),
604 variant_decl_span: variant_decl.span.clone(),
605 }));
606
607 self.current_module_mut()
609 .current_items_mut()
610 .insert_glob_use_symbol(
611 engines,
612 variant_name.clone(),
613 path.clone(),
614 &decl,
615 visibility,
616 );
617 }
618 }
619 _ => {
620 return Err(handler.emit_err(CompileError::Internal(
621 "Attempting to import variants of something that isn't an enum",
622 enum_name.span(),
623 )));
624 }
625 };
626
627 Ok(())
628 }
629
630 pub(crate) fn self_import_to_current_module(
634 &mut self,
635 handler: &Handler,
636 engines: &Engines,
637 src: &ModulePath,
638 alias: Option<Ident>,
639 visibility: Visibility,
640 ) -> Result<(), ErrorEmitted> {
641 let (last_item, src) = src.split_last().expect("guaranteed by grammar");
642 self.item_import_to_current_module(handler, engines, src, last_item, alias, visibility)
643 }
644
645 pub(crate) fn item_import_to_current_module(
649 &mut self,
650 handler: &Handler,
651 engines: &Engines,
652 src: &ModulePath,
653 item: &Ident,
654 alias: Option<Ident>,
655 visibility: Visibility,
656 ) -> Result<(), ErrorEmitted> {
657 self.check_module_visibility(handler, src)?;
658
659 let src_mod = self.require_module_from_absolute_path(handler, &src.to_vec())?;
660
661 let (decl, path) = self.item_lookup(handler, engines, item, src, false)?;
662
663 let mut impls_to_insert = TraitMap::default();
664 if decl.is_typed() {
665 if let Ok(type_id) = decl.return_type(&Handler::default(), engines) {
671 impls_to_insert.extend(
672 src_mod
673 .root_items()
674 .implemented_traits
675 .filter_by_type_item_import(type_id, engines),
676 engines,
677 );
678 }
679 let decl_span = decl.span(engines);
681 if decl.is_trait() {
682 impls_to_insert.extend(
685 src_mod
686 .root_items()
687 .implemented_traits
688 .filter_by_trait_decl_span(decl_span),
689 engines,
690 );
691 }
692 }
693
694 let dst_mod = self.current_module_mut();
696 let check_name_clash = |name| {
697 if dst_mod.current_items().use_item_synonyms.contains_key(name) {
698 handler.emit_err(CompileError::ShadowsOtherSymbol { name: name.into() });
699 }
700 };
701 match alias {
702 Some(alias) => {
703 check_name_clash(&alias);
704 dst_mod
705 .current_items_mut()
706 .use_item_synonyms
707 .insert(alias.clone(), (Some(item.clone()), path, decl, visibility))
708 }
709 None => {
710 check_name_clash(item);
711 dst_mod
712 .current_items_mut()
713 .use_item_synonyms
714 .insert(item.clone(), (None, path, decl, visibility))
715 }
716 };
717
718 dst_mod
719 .current_items_mut()
720 .implemented_traits
721 .extend(impls_to_insert, engines);
722
723 Ok(())
724 }
725
726 #[allow(clippy::too_many_arguments)]
731 pub(crate) fn variant_import_to_current_module(
732 &mut self,
733 handler: &Handler,
734 engines: &Engines,
735 src: &ModulePath,
736 enum_name: &Ident,
737 variant_name: &Ident,
738 alias: Option<Ident>,
739 visibility: Visibility,
740 ) -> Result<(), ErrorEmitted> {
741 self.check_module_visibility(handler, src)?;
742
743 let decl_engine = engines.de();
744 let parsed_decl_engine = engines.pe();
745
746 let (decl, path) = self.item_lookup(handler, engines, enum_name, src, false)?;
747
748 match decl {
749 ResolvedDeclaration::Parsed(decl) => {
750 if let Declaration::EnumDeclaration(decl_id) = decl {
751 let enum_decl = parsed_decl_engine.get_enum(&decl_id);
752
753 if let Some(variant_decl) =
754 enum_decl.variants.iter().find(|v| v.name == *variant_name)
755 {
756 let dst_mod = self.current_module_mut();
758 let check_name_clash = |name| {
759 if dst_mod.current_items().use_item_synonyms.contains_key(name) {
760 handler.emit_err(CompileError::ShadowsOtherSymbol {
761 name: name.into(),
762 });
763 }
764 };
765
766 match alias {
767 Some(alias) => {
768 check_name_clash(&alias);
769 dst_mod.current_items_mut().use_item_synonyms.insert(
770 alias.clone(),
771 (
772 Some(variant_name.clone()),
773 path,
774 ResolvedDeclaration::Parsed(
775 Declaration::EnumVariantDeclaration(
776 EnumVariantDeclaration {
777 enum_ref: decl_id,
778 variant_name: variant_name.clone(),
779 variant_decl_span: variant_decl.span.clone(),
780 },
781 ),
782 ),
783 visibility,
784 ),
785 );
786 }
787 None => {
788 check_name_clash(variant_name);
789 dst_mod.current_items_mut().use_item_synonyms.insert(
790 variant_name.clone(),
791 (
792 None,
793 path,
794 ResolvedDeclaration::Parsed(
795 Declaration::EnumVariantDeclaration(
796 EnumVariantDeclaration {
797 enum_ref: decl_id,
798 variant_name: variant_name.clone(),
799 variant_decl_span: variant_decl.span.clone(),
800 },
801 ),
802 ),
803 visibility,
804 ),
805 );
806 }
807 };
808 } else {
809 return Err(handler.emit_err(CompileError::SymbolNotFound {
810 name: variant_name.clone(),
811 span: variant_name.span(),
812 }));
813 }
814 }
815 }
816 ResolvedDeclaration::Typed(decl) => {
817 if let TyDecl::EnumDecl(ty::EnumDecl { decl_id, .. }) = decl {
818 let enum_decl = decl_engine.get_enum(&decl_id);
819 let enum_ref = DeclRef::new(
820 enum_decl.call_path.suffix.clone(),
821 decl_id,
822 enum_decl.span(),
823 );
824
825 if let Some(variant_decl) =
826 enum_decl.variants.iter().find(|v| v.name == *variant_name)
827 {
828 let dst_mod = self.current_module_mut();
830 let check_name_clash = |name| {
831 if dst_mod.current_items().use_item_synonyms.contains_key(name) {
832 handler.emit_err(CompileError::ShadowsOtherSymbol {
833 name: name.into(),
834 });
835 }
836 };
837
838 match alias {
839 Some(alias) => {
840 check_name_clash(&alias);
841 dst_mod.current_items_mut().use_item_synonyms.insert(
842 alias.clone(),
843 (
844 Some(variant_name.clone()),
845 path,
846 ResolvedDeclaration::Typed(TyDecl::EnumVariantDecl(
847 ty::EnumVariantDecl {
848 enum_ref: enum_ref.clone(),
849 variant_name: variant_name.clone(),
850 variant_decl_span: variant_decl.span.clone(),
851 },
852 )),
853 visibility,
854 ),
855 );
856 }
857 None => {
858 check_name_clash(variant_name);
859 dst_mod.current_items_mut().use_item_synonyms.insert(
860 variant_name.clone(),
861 (
862 None,
863 path,
864 ResolvedDeclaration::Typed(TyDecl::EnumVariantDecl(
865 ty::EnumVariantDecl {
866 enum_ref: enum_ref.clone(),
867 variant_name: variant_name.clone(),
868 variant_decl_span: variant_decl.span.clone(),
869 },
870 )),
871 visibility,
872 ),
873 );
874 }
875 };
876 } else {
877 return Err(handler.emit_err(CompileError::SymbolNotFound {
878 name: variant_name.clone(),
879 span: variant_name.span(),
880 }));
881 }
882 } else {
883 return Err(handler.emit_err(CompileError::Internal(
884 "Attempting to import variants of something that isn't an enum",
885 enum_name.span(),
886 )));
887 }
888 }
889 };
890
891 Ok(())
892 }
893
894 fn item_lookup(
897 &self,
898 handler: &Handler,
899 engines: &Engines,
900 item: &Ident,
901 src: &ModulePath,
902 ignore_visibility: bool,
903 ) -> Result<(ResolvedDeclaration, ModulePathBuf), ErrorEmitted> {
904 let src_mod = self.require_module_from_absolute_path(handler, &src.to_vec())?;
905 let src_items = src_mod.root_items();
906
907 let (decl, path, src_visibility) = if let Some(decl) = src_items.symbols.get(item) {
908 let visibility = if self.is_ancestor_of_current_module(src) {
909 Visibility::Public
910 } else {
911 decl.visibility(engines)
912 };
913 (decl.clone(), src.to_vec(), visibility)
914 } else if let Some((_, path, decl, reexport)) = src_items.use_item_synonyms.get(item) {
915 (decl.clone(), path.clone(), *reexport)
916 } else if let Some(decls) = src_items.use_glob_synonyms.get(item) {
917 if decls.len() == 1 {
918 let (path, decl, reexport) = &decls[0];
919 (decl.clone(), path.clone(), *reexport)
920 } else if decls.is_empty() {
921 return Err(handler.emit_err(CompileError::Internal(
922 "The name {symbol} was bound in a star import, but no corresponding module paths were found",
923 item.span(),
924 )));
925 } else {
926 return Err(handler.emit_err(CompileError::SymbolWithMultipleBindings {
927 name: item.clone(),
928 paths: decls
929 .iter()
930 .map(|(path, decl, _)| {
931 let mut path_strs = super::lexical_scope::get_path_for_decl(
932 path,
933 decl,
934 engines,
935 self.current_package_name(),
936 );
937 if let TyDecl::EnumVariantDecl(ty::EnumVariantDecl {
939 enum_ref, ..
940 }) = decl.expect_typed_ref()
941 {
942 path_strs.push(enum_ref.name().to_string())
943 };
944 path_strs.join("::")
945 })
946 .collect(),
947 span: item.span(),
948 }));
949 }
950 } else {
951 return Err(handler.emit_err(CompileError::SymbolNotFound {
953 name: item.clone(),
954 span: item.span(),
955 }));
956 };
957
958 if !ignore_visibility && !src_visibility.is_public() {
959 handler.emit_err(CompileError::ImportPrivateSymbol {
960 name: item.clone(),
961 span: item.span(),
962 });
963 }
964
965 Ok((decl, path))
966 }
967
968 pub(crate) fn check_module_visibility(
979 &self,
980 handler: &Handler,
981 src: &ModulePath,
982 ) -> Result<(), ErrorEmitted> {
983 let dst = &self.current_mod_path;
984
985 let mut ignored_prefixes = 0;
987
988 ignored_prefixes += src
990 .iter()
991 .zip(dst)
992 .position(|(src_id, dst_id)| src_id != dst_id)
993 .unwrap_or(dst.len());
994
995 if dst.len() == ignored_prefixes {
997 ignored_prefixes += 1;
998 }
999
1000 for prefix in iter_prefixes(src).skip(ignored_prefixes) {
1002 if let Some(module) = self.module_from_absolute_path(&prefix.to_vec()) {
1003 if module.visibility().is_private() {
1004 let prefix_last = prefix[prefix.len() - 1].clone();
1005 handler.emit_err(CompileError::ImportPrivateModule {
1006 span: prefix_last.span(),
1007 name: prefix_last,
1008 });
1009 }
1010 } else {
1011 return Ok(());
1012 }
1013 }
1014
1015 Ok(())
1016 }
1017
1018 fn is_ancestor_of_current_module(&self, src: &ModulePath) -> bool {
1019 let dst = &self.current_mod_path;
1020 dst.len() >= src.len() && src.iter().zip(dst).all(|(src, dst)| src == dst)
1021 }
1022}