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(std::slice::from_ref(submod_name))
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(std::slice::from_ref(name))
248 .is_some()
249 }
250
251 pub(crate) fn module_has_binding(
252 &self,
253 engines: &Engines,
254 mod_path: &ModulePathBuf,
255 symbol: &Ident,
256 ) -> bool {
257 let dummy_handler = Handler::default();
258 if let Some(module) = self.module_from_absolute_path(mod_path) {
259 module
260 .resolve_symbol(&dummy_handler, engines, symbol)
261 .is_ok()
262 } else {
263 false
264 }
265 }
266
267 fn import_implicits(
269 &mut self,
270 handler: &Handler,
271 engines: &Engines,
272 ) -> Result<(), ErrorEmitted> {
273 let package_name = self.current_package_name().to_string();
275 let prelude_ident = Ident::new_no_span(PRELUDE.to_string());
276
277 if package_name == STD {
278 } else {
280 let std_string = STD.to_string();
282 if self.exists_as_external(&std_string) {
284 self.prelude_import(
285 handler,
286 engines,
287 &[Ident::new_no_span(std_string), prelude_ident],
288 )?
289 }
290 }
291
292 if self.current_package.is_contract_package() && self.current_mod_path.len() > 1 {
295 self.item_import_to_current_module(
297 handler,
298 engines,
299 &[Ident::new_no_span(package_name)],
300 &Ident::new_no_span(CONTRACT_ID.to_string()),
301 None,
302 Visibility::Private,
303 )?
304 }
305
306 Ok(())
307 }
308
309 pub(crate) fn enter_submodule(
310 &mut self,
311 handler: &Handler,
312 engines: &Engines,
313 mod_name: Ident,
314 visibility: Visibility,
315 module_span: Span,
316 check_implicits: bool,
317 ) -> Result<(), ErrorEmitted> {
318 let mut import_implicits = false;
319
320 if !self
322 .current_module()
323 .submodules()
324 .contains_key(&mod_name.to_string())
325 && check_implicits
326 {
327 self.current_module_mut()
329 .add_new_submodule(&mod_name, visibility, Some(module_span));
330 import_implicits = true;
331 }
332
333 self.current_mod_path.push(mod_name.clone());
335
336 if import_implicits {
338 self.import_implicits(handler, engines)?;
339 }
340
341 Ok(())
342 }
343
344 pub fn push_submodule(
346 &mut self,
347 handler: &Handler,
348 engines: &Engines,
349 mod_name: Ident,
350 visibility: Visibility,
351 module_span: Span,
352 check_implicits: bool,
353 ) -> Result<(), ErrorEmitted> {
354 match self.enter_submodule(
355 handler,
356 engines,
357 mod_name,
358 visibility,
359 module_span,
360 check_implicits,
361 ) {
362 Ok(_) => Ok(()),
363 Err(e) => Err(e),
364 }
365 }
366
367 pub fn pop_submodule(&mut self) {
369 self.current_mod_path.pop();
370 }
371
372 fn prelude_import(
382 &mut self,
383 handler: &Handler,
384 engines: &Engines,
385 src: &ModulePath,
386 ) -> Result<(), ErrorEmitted> {
387 let src_mod = self.require_module_from_absolute_path(handler, src)?;
388
389 let mut imports = vec![];
390
391 assert!(src_mod.root_items().symbols.is_empty());
393
394 let mut symbols = src_mod
396 .root_items()
397 .use_item_synonyms
398 .keys()
399 .clone()
400 .collect::<Vec<_>>();
401 symbols.sort();
402 for symbol in symbols {
403 let (_, path, decl, src_visibility) = &src_mod.root_items().use_item_synonyms[symbol];
404 assert!(matches!(src_visibility, Visibility::Public));
406 imports.push((symbol.clone(), decl.clone(), path.clone()))
407 }
408
409 let mut symbols = src_mod
413 .root_items()
414 .use_glob_synonyms
415 .keys()
416 .clone()
417 .collect::<Vec<_>>();
418 symbols.sort();
419 for symbol in symbols {
420 let bindings = &src_mod.root_items().use_glob_synonyms[symbol];
421 for (path, decl, src_visibility) in bindings.iter() {
422 assert!(matches!(src_visibility, Visibility::Public));
424 imports.push((symbol.clone(), decl.clone(), path.clone()))
425 }
426 }
427
428 let implemented_traits = src_mod.root_items().implemented_traits.clone();
429 let dst_mod = self.current_module_mut();
430
431 dst_mod
432 .current_items_mut()
433 .implemented_traits
434 .extend(implemented_traits, engines);
435
436 let dst_prelude_synonyms = &mut dst_mod.current_items_mut().prelude_synonyms;
437 imports.iter().for_each(|(symbol, decl, path)| {
438 assert!(!dst_prelude_synonyms.contains_key(symbol));
440 dst_prelude_synonyms.insert(symbol.clone(), (path.clone(), decl.clone()));
441 });
442
443 Ok(())
444 }
445
446 pub(crate) fn star_import_to_current_module(
453 &mut self,
454 handler: &Handler,
455 engines: &Engines,
456 src: &ModulePath,
457 visibility: Visibility,
458 ) -> Result<(), ErrorEmitted> {
459 self.check_module_visibility(handler, src)?;
460
461 let src_mod = self.require_module_from_absolute_path(handler, src)?;
462
463 let mut decls_and_item_imports = vec![];
464
465 let mut symbols = src_mod
467 .root_items()
468 .symbols
469 .keys()
470 .clone()
471 .collect::<Vec<_>>();
472 symbols.sort();
473 for symbol in symbols {
474 let decl = &src_mod.root_items().symbols[symbol];
475 if self.is_ancestor_of_current_module(src) || decl.visibility(engines).is_public() {
476 decls_and_item_imports.push((symbol.clone(), decl.clone(), src.to_vec()));
477 }
478 }
479 let mut symbols = src_mod
482 .root_items()
483 .use_item_synonyms
484 .keys()
485 .clone()
486 .collect::<Vec<_>>();
487 symbols.sort();
488 for symbol in symbols {
489 let (_, path, decl, src_visibility) = &src_mod.root_items().use_item_synonyms[symbol];
490 if src_visibility.is_public() {
491 decls_and_item_imports.push((symbol.clone(), decl.clone(), path.clone()))
492 }
493 }
494
495 let mut glob_imports = vec![];
499 let mut symbols = src_mod
500 .root_items()
501 .use_glob_synonyms
502 .keys()
503 .clone()
504 .collect::<Vec<_>>();
505 symbols.sort();
506 for symbol in symbols {
507 let bindings = &src_mod.root_items().use_glob_synonyms[symbol];
508 if !decls_and_item_imports
510 .iter()
511 .any(|(other_symbol, _, _)| symbol == other_symbol)
512 {
513 for (path, decl, src_visibility) in bindings.iter() {
514 if src_visibility.is_public() {
515 glob_imports.push((symbol.clone(), decl.clone(), path.clone()))
516 }
517 }
518 }
519 }
520
521 let implemented_traits = src_mod.root_items().implemented_traits.clone();
522 let dst_mod = self.current_module_mut();
523
524 dst_mod
525 .current_items_mut()
526 .implemented_traits
527 .extend(implemented_traits, engines);
528
529 decls_and_item_imports
530 .iter()
531 .chain(glob_imports.iter())
532 .for_each(|(symbol, decl, path)| {
533 dst_mod.current_items_mut().insert_glob_use_symbol(
534 engines,
535 symbol.clone(),
536 path.clone(),
537 decl,
538 visibility,
539 )
540 });
541
542 Ok(())
543 }
544
545 pub(crate) fn variant_star_import_to_current_module(
549 &mut self,
550 handler: &Handler,
551 engines: &Engines,
552 src: &ModulePath,
553 enum_name: &Ident,
554 visibility: Visibility,
555 ) -> Result<(), ErrorEmitted> {
556 self.check_module_visibility(handler, src)?;
557
558 let parsed_decl_engine = engines.pe();
559 let decl_engine = engines.de();
560
561 let (decl, path) = self.item_lookup(handler, engines, enum_name, src, false)?;
562
563 match decl {
564 ResolvedDeclaration::Parsed(Declaration::EnumDeclaration(decl_id)) => {
565 let enum_decl = parsed_decl_engine.get_enum(&decl_id);
566
567 for variant in enum_decl.variants.iter() {
568 let variant_name = &variant.name;
569 let variant_decl =
570 Declaration::EnumVariantDeclaration(EnumVariantDeclaration {
571 enum_ref: decl_id,
572 variant_name: variant_name.clone(),
573 variant_decl_span: variant.span.clone(),
574 });
575
576 self.current_module_mut()
578 .current_items_mut()
579 .insert_glob_use_symbol(
580 engines,
581 variant_name.clone(),
582 path.clone(),
583 &ResolvedDeclaration::Parsed(variant_decl),
584 visibility,
585 );
586 }
587 }
588 ResolvedDeclaration::Typed(TyDecl::EnumDecl(ty::EnumDecl { decl_id, .. })) => {
589 let enum_decl = decl_engine.get_enum(&decl_id);
590 let enum_ref = DeclRef::new(
591 enum_decl.call_path.suffix.clone(),
592 decl_id,
593 enum_decl.span(),
594 );
595
596 for variant_decl in enum_decl.variants.iter() {
597 let variant_name = &variant_decl.name;
598 let decl =
599 ResolvedDeclaration::Typed(TyDecl::EnumVariantDecl(ty::EnumVariantDecl {
600 enum_ref: enum_ref.clone(),
601 variant_name: variant_name.clone(),
602 variant_decl_span: variant_decl.span.clone(),
603 }));
604
605 self.current_module_mut()
607 .current_items_mut()
608 .insert_glob_use_symbol(
609 engines,
610 variant_name.clone(),
611 path.clone(),
612 &decl,
613 visibility,
614 );
615 }
616 }
617 _ => {
618 return Err(handler.emit_err(CompileError::Internal(
619 "Attempting to import variants of something that isn't an enum",
620 enum_name.span(),
621 )));
622 }
623 };
624
625 Ok(())
626 }
627
628 pub(crate) fn self_import_to_current_module(
632 &mut self,
633 handler: &Handler,
634 engines: &Engines,
635 src: &ModulePath,
636 alias: Option<Ident>,
637 visibility: Visibility,
638 ) -> Result<(), ErrorEmitted> {
639 let (last_item, src) = src.split_last().expect("guaranteed by grammar");
640 self.item_import_to_current_module(handler, engines, src, last_item, alias, visibility)
641 }
642
643 pub(crate) fn item_import_to_current_module(
647 &mut self,
648 handler: &Handler,
649 engines: &Engines,
650 src: &ModulePath,
651 item: &Ident,
652 alias: Option<Ident>,
653 visibility: Visibility,
654 ) -> Result<(), ErrorEmitted> {
655 self.check_module_visibility(handler, src)?;
656
657 let src_mod = self.require_module_from_absolute_path(handler, src)?;
658
659 let (decl, path) = self.item_lookup(handler, engines, item, src, false)?;
660
661 let mut impls_to_insert = TraitMap::default();
662 if decl.is_typed() {
663 if let Ok(type_id) = decl.return_type(&Handler::default(), engines) {
669 impls_to_insert.extend(
670 src_mod
671 .root_items()
672 .implemented_traits
673 .filter_by_type_item_import(type_id, engines),
674 engines,
675 );
676 }
677 let decl_span = decl.span(engines);
679 if decl.is_trait() {
680 impls_to_insert.extend(
683 src_mod
684 .root_items()
685 .implemented_traits
686 .filter_by_trait_decl_span(decl_span),
687 engines,
688 );
689 }
690 }
691
692 let dst_mod = self.current_module_mut();
694 let check_name_clash = |name| {
695 if dst_mod.current_items().use_item_synonyms.contains_key(name) {
696 handler.emit_err(CompileError::ShadowsOtherSymbol { name: name.into() });
697 }
698 };
699 match alias {
700 Some(alias) => {
701 check_name_clash(&alias);
702 dst_mod
703 .current_items_mut()
704 .use_item_synonyms
705 .insert(alias.clone(), (Some(item.clone()), path, decl, visibility))
706 }
707 None => {
708 check_name_clash(item);
709 dst_mod
710 .current_items_mut()
711 .use_item_synonyms
712 .insert(item.clone(), (None, path, decl, visibility))
713 }
714 };
715
716 dst_mod
717 .current_items_mut()
718 .implemented_traits
719 .extend(impls_to_insert, engines);
720
721 Ok(())
722 }
723
724 #[allow(clippy::too_many_arguments)]
729 pub(crate) fn variant_import_to_current_module(
730 &mut self,
731 handler: &Handler,
732 engines: &Engines,
733 src: &ModulePath,
734 enum_name: &Ident,
735 variant_name: &Ident,
736 alias: Option<Ident>,
737 visibility: Visibility,
738 ) -> Result<(), ErrorEmitted> {
739 self.check_module_visibility(handler, src)?;
740
741 let decl_engine = engines.de();
742 let parsed_decl_engine = engines.pe();
743
744 let (decl, path) = self.item_lookup(handler, engines, enum_name, src, false)?;
745
746 match decl {
747 ResolvedDeclaration::Parsed(decl) => {
748 if let Declaration::EnumDeclaration(decl_id) = decl {
749 let enum_decl = parsed_decl_engine.get_enum(&decl_id);
750
751 if let Some(variant_decl) =
752 enum_decl.variants.iter().find(|v| v.name == *variant_name)
753 {
754 let dst_mod = self.current_module_mut();
756 let check_name_clash = |name| {
757 if dst_mod.current_items().use_item_synonyms.contains_key(name) {
758 handler.emit_err(CompileError::ShadowsOtherSymbol {
759 name: name.into(),
760 });
761 }
762 };
763
764 match alias {
765 Some(alias) => {
766 check_name_clash(&alias);
767 dst_mod.current_items_mut().use_item_synonyms.insert(
768 alias.clone(),
769 (
770 Some(variant_name.clone()),
771 path,
772 ResolvedDeclaration::Parsed(
773 Declaration::EnumVariantDeclaration(
774 EnumVariantDeclaration {
775 enum_ref: decl_id,
776 variant_name: variant_name.clone(),
777 variant_decl_span: variant_decl.span.clone(),
778 },
779 ),
780 ),
781 visibility,
782 ),
783 );
784 }
785 None => {
786 check_name_clash(variant_name);
787 dst_mod.current_items_mut().use_item_synonyms.insert(
788 variant_name.clone(),
789 (
790 None,
791 path,
792 ResolvedDeclaration::Parsed(
793 Declaration::EnumVariantDeclaration(
794 EnumVariantDeclaration {
795 enum_ref: decl_id,
796 variant_name: variant_name.clone(),
797 variant_decl_span: variant_decl.span.clone(),
798 },
799 ),
800 ),
801 visibility,
802 ),
803 );
804 }
805 };
806 } else {
807 return Err(handler.emit_err(CompileError::SymbolNotFound {
808 name: variant_name.clone(),
809 span: variant_name.span(),
810 }));
811 }
812 }
813 }
814 ResolvedDeclaration::Typed(decl) => {
815 if let TyDecl::EnumDecl(ty::EnumDecl { decl_id, .. }) = decl {
816 let enum_decl = decl_engine.get_enum(&decl_id);
817 let enum_ref = DeclRef::new(
818 enum_decl.call_path.suffix.clone(),
819 decl_id,
820 enum_decl.span(),
821 );
822
823 if let Some(variant_decl) =
824 enum_decl.variants.iter().find(|v| v.name == *variant_name)
825 {
826 let dst_mod = self.current_module_mut();
828 let check_name_clash = |name| {
829 if dst_mod.current_items().use_item_synonyms.contains_key(name) {
830 handler.emit_err(CompileError::ShadowsOtherSymbol {
831 name: name.into(),
832 });
833 }
834 };
835
836 match alias {
837 Some(alias) => {
838 check_name_clash(&alias);
839 dst_mod.current_items_mut().use_item_synonyms.insert(
840 alias.clone(),
841 (
842 Some(variant_name.clone()),
843 path,
844 ResolvedDeclaration::Typed(TyDecl::EnumVariantDecl(
845 ty::EnumVariantDecl {
846 enum_ref: enum_ref.clone(),
847 variant_name: variant_name.clone(),
848 variant_decl_span: variant_decl.span.clone(),
849 },
850 )),
851 visibility,
852 ),
853 );
854 }
855 None => {
856 check_name_clash(variant_name);
857 dst_mod.current_items_mut().use_item_synonyms.insert(
858 variant_name.clone(),
859 (
860 None,
861 path,
862 ResolvedDeclaration::Typed(TyDecl::EnumVariantDecl(
863 ty::EnumVariantDecl {
864 enum_ref: enum_ref.clone(),
865 variant_name: variant_name.clone(),
866 variant_decl_span: variant_decl.span.clone(),
867 },
868 )),
869 visibility,
870 ),
871 );
872 }
873 };
874 } else {
875 return Err(handler.emit_err(CompileError::SymbolNotFound {
876 name: variant_name.clone(),
877 span: variant_name.span(),
878 }));
879 }
880 } else {
881 return Err(handler.emit_err(CompileError::Internal(
882 "Attempting to import variants of something that isn't an enum",
883 enum_name.span(),
884 )));
885 }
886 }
887 };
888
889 Ok(())
890 }
891
892 fn item_lookup(
895 &self,
896 handler: &Handler,
897 engines: &Engines,
898 item: &Ident,
899 src: &ModulePath,
900 ignore_visibility: bool,
901 ) -> Result<(ResolvedDeclaration, ModulePathBuf), ErrorEmitted> {
902 let src_mod = self.require_module_from_absolute_path(handler, src)?;
903 let src_items = src_mod.root_items();
904
905 let (decl, path, src_visibility) = if let Some(decl) = src_items.symbols.get(item) {
906 let visibility = if self.is_ancestor_of_current_module(src) {
907 Visibility::Public
908 } else {
909 decl.visibility(engines)
910 };
911 (decl.clone(), src.to_vec(), visibility)
912 } else if let Some((_, path, decl, reexport)) = src_items.use_item_synonyms.get(item) {
913 (decl.clone(), path.clone(), *reexport)
914 } else if let Some(decls) = src_items.use_glob_synonyms.get(item) {
915 if decls.len() == 1 {
916 let (path, decl, reexport) = &decls[0];
917 (decl.clone(), path.clone(), *reexport)
918 } else if decls.is_empty() {
919 return Err(handler.emit_err(CompileError::Internal(
920 "The name {symbol} was bound in a star import, but no corresponding module paths were found",
921 item.span(),
922 )));
923 } else {
924 return Err(handler.emit_err(CompileError::SymbolWithMultipleBindings {
925 name: item.clone(),
926 paths: decls
927 .iter()
928 .map(|(path, decl, _)| {
929 let mut path_strs = super::lexical_scope::get_path_for_decl(
930 path,
931 decl,
932 engines,
933 self.current_package_name(),
934 );
935 if let TyDecl::EnumVariantDecl(ty::EnumVariantDecl {
937 enum_ref, ..
938 }) = decl.expect_typed_ref()
939 {
940 path_strs.push(enum_ref.name().to_string())
941 };
942 path_strs.join("::")
943 })
944 .collect(),
945 span: item.span(),
946 }));
947 }
948 } else {
949 return Err(handler.emit_err(CompileError::SymbolNotFound {
951 name: item.clone(),
952 span: item.span(),
953 }));
954 };
955
956 if !ignore_visibility && !src_visibility.is_public() {
957 handler.emit_err(CompileError::ImportPrivateSymbol {
958 name: item.clone(),
959 span: item.span(),
960 });
961 }
962
963 Ok((decl, path))
964 }
965
966 pub(crate) fn check_module_visibility(
977 &self,
978 handler: &Handler,
979 src: &ModulePath,
980 ) -> Result<(), ErrorEmitted> {
981 let dst = &self.current_mod_path;
982
983 let mut ignored_prefixes = 0;
985
986 ignored_prefixes += src
988 .iter()
989 .zip(dst)
990 .position(|(src_id, dst_id)| src_id != dst_id)
991 .unwrap_or(dst.len());
992
993 if dst.len() == ignored_prefixes {
995 ignored_prefixes += 1;
996 }
997
998 for prefix in iter_prefixes(src).skip(ignored_prefixes) {
1000 if let Some(module) = self.module_from_absolute_path(prefix) {
1001 if module.visibility().is_private() {
1002 let prefix_last = prefix[prefix.len() - 1].clone();
1003 handler.emit_err(CompileError::ImportPrivateModule {
1004 span: prefix_last.span(),
1005 name: prefix_last,
1006 });
1007 }
1008 } else {
1009 return Ok(());
1010 }
1011 }
1012
1013 Ok(())
1014 }
1015
1016 fn is_ancestor_of_current_module(&self, src: &ModulePath) -> bool {
1017 let dst = &self.current_mod_path;
1018 dst.len() >= src.len() && src.iter().zip(dst).all(|(src, dst)| src == dst)
1019 }
1020}