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