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