1use std::fmt;
2
3use super::{module::Module, trait_map::TraitMap, Ident, ModuleName};
4use crate::{
5 decl_engine::{DeclEngine, DeclRef},
6 engine_threading::*,
7 language::{
8 parsed::*,
9 ty::{self, StructDecl, TyDecl},
10 Visibility,
11 },
12 namespace::{ModulePath, ModulePathBuf},
13 TypeId,
14};
15use rustc_hash::FxHasher;
16use std::hash::BuildHasherDefault;
17use sway_error::{
18 error::CompileError,
19 handler::{ErrorEmitted, Handler},
20};
21use sway_types::{span::Span, ProgramId, Spanned};
22use sway_utils::iter_prefixes;
23
24#[derive(Clone, Debug)]
25pub enum ResolvedDeclaration {
26 Parsed(Declaration),
27 Typed(ty::TyDecl),
28}
29
30impl DisplayWithEngines for ResolvedDeclaration {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
32 match self {
33 ResolvedDeclaration::Parsed(decl) => DisplayWithEngines::fmt(decl, f, engines),
34 ResolvedDeclaration::Typed(decl) => DisplayWithEngines::fmt(decl, f, engines),
35 }
36 }
37}
38
39impl DebugWithEngines for ResolvedDeclaration {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
41 match self {
42 ResolvedDeclaration::Parsed(decl) => DebugWithEngines::fmt(decl, f, engines),
43 ResolvedDeclaration::Typed(decl) => DebugWithEngines::fmt(decl, f, engines),
44 }
45 }
46}
47
48impl PartialEqWithEngines for ResolvedDeclaration {
49 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
50 match (self, other) {
51 (ResolvedDeclaration::Parsed(lhs), ResolvedDeclaration::Parsed(rhs)) => {
52 lhs.eq(rhs, ctx)
53 }
54 (ResolvedDeclaration::Typed(lhs), ResolvedDeclaration::Typed(rhs)) => lhs.eq(rhs, ctx),
55 (ResolvedDeclaration::Parsed(_lhs), ResolvedDeclaration::Typed(_rhs)) => false,
59 (ResolvedDeclaration::Typed(_lhs), ResolvedDeclaration::Parsed(_rhs)) => false,
60 }
61 }
62}
63
64impl ResolvedDeclaration {
65 pub fn is_typed(&self) -> bool {
66 match self {
67 ResolvedDeclaration::Parsed(_) => false,
68 ResolvedDeclaration::Typed(_) => true,
69 }
70 }
71
72 pub fn resolve_parsed(self, decl_engine: &DeclEngine) -> Declaration {
73 match self {
74 ResolvedDeclaration::Parsed(decl) => decl,
75 ResolvedDeclaration::Typed(ty_decl) => ty_decl
76 .get_parsed_decl(decl_engine)
77 .expect("expecting valid parsed declaration"),
78 }
79 }
80
81 pub fn expect_parsed(self) -> Declaration {
82 match self {
83 ResolvedDeclaration::Parsed(decl) => decl,
84 ResolvedDeclaration::Typed(_ty_decl) => panic!(),
85 }
86 }
87
88 pub fn expect_typed(self) -> ty::TyDecl {
89 match self {
90 ResolvedDeclaration::Parsed(_) => panic!(),
91 ResolvedDeclaration::Typed(ty_decl) => ty_decl,
92 }
93 }
94
95 pub fn expect_typed_ref(&self) -> &ty::TyDecl {
96 match self {
97 ResolvedDeclaration::Parsed(_) => panic!(),
98 ResolvedDeclaration::Typed(ty_decl) => ty_decl,
99 }
100 }
101
102 pub(crate) fn to_struct_decl(
103 &self,
104 handler: &Handler,
105 engines: &Engines,
106 ) -> Result<ResolvedDeclaration, ErrorEmitted> {
107 match self {
108 ResolvedDeclaration::Parsed(decl) => decl
109 .to_struct_decl(handler, engines)
110 .map(|id| ResolvedDeclaration::Parsed(Declaration::StructDeclaration(id))),
111 ResolvedDeclaration::Typed(decl) => decl.to_struct_decl(handler, engines).map(|id| {
112 ResolvedDeclaration::Typed(TyDecl::StructDecl(StructDecl { decl_id: id }))
113 }),
114 }
115 }
116
117 pub(crate) fn visibility(&self, engines: &Engines) -> Visibility {
118 match self {
119 ResolvedDeclaration::Parsed(decl) => decl.visibility(engines.pe()),
120 ResolvedDeclaration::Typed(decl) => decl.visibility(engines.de()),
121 }
122 }
123
124 fn span(&self, engines: &Engines) -> sway_types::Span {
125 match self {
126 ResolvedDeclaration::Parsed(decl) => decl.span(engines),
127 ResolvedDeclaration::Typed(decl) => decl.span(engines),
128 }
129 }
130
131 pub(crate) fn return_type(
132 &self,
133 handler: &Handler,
134 engines: &Engines,
135 ) -> Result<TypeId, ErrorEmitted> {
136 match self {
137 ResolvedDeclaration::Parsed(_decl) => unreachable!(),
138 ResolvedDeclaration::Typed(decl) => decl.return_type(handler, engines),
139 }
140 }
141
142 fn is_trait(&self) -> bool {
143 match self {
144 ResolvedDeclaration::Parsed(decl) => {
145 matches!(decl, Declaration::TraitDeclaration(_))
146 }
147 ResolvedDeclaration::Typed(decl) => {
148 matches!(decl, TyDecl::TraitDecl(_))
149 }
150 }
151 }
152}
153
154#[derive(Clone, Debug)]
163pub struct Root {
164 current_package: Module,
166 program_id: ProgramId,
168 is_contract_package: bool,
170 external_packages: im::HashMap<ModuleName, Root, BuildHasherDefault<FxHasher>>,
175}
176
177impl Root {
178 pub fn new(
185 package_name: Ident,
186 span: Option<Span>,
187 program_id: ProgramId,
188 is_contract_package: bool,
189 ) -> Self {
190 let module = Module::new(package_name, Visibility::Public, span, &vec![]);
192 Self {
193 current_package: module,
194 program_id,
195 is_contract_package,
196 external_packages: Default::default(),
197 }
198 }
199
200 pub fn add_external(&mut self, package_name: String, external_package: Root) {
204 assert!(!self.external_packages.contains_key(&package_name));
206 self.external_packages
207 .insert(package_name, external_package);
208 }
209
210 pub(crate) fn get_external_package(&self, package_name: &String) -> Option<&Root> {
211 self.external_packages.get(package_name)
212 }
213
214 pub(super) fn exists_as_external(&self, package_name: &String) -> bool {
215 self.get_external_package(package_name).is_some()
216 }
217
218 pub fn external_packages(
219 &self,
220 ) -> &im::HashMap<ModuleName, Root, BuildHasherDefault<FxHasher>> {
221 &self.external_packages
222 }
223
224 pub fn current_package_root_module(&self) -> &Module {
225 &self.current_package
226 }
227
228 pub fn current_package_root_module_mut(&mut self) -> &mut Module {
229 &mut self.current_package
230 }
231
232 pub fn current_package_name(&self) -> &Ident {
233 self.current_package.name()
234 }
235
236 pub fn program_id(&self) -> ProgramId {
237 self.program_id
238 }
239
240 fn check_path_is_in_current_package(&self, mod_path: &ModulePathBuf) -> bool {
241 !mod_path.is_empty() && mod_path[0] == *self.current_package.name()
242 }
243
244 fn package_relative_path(mod_path: &ModulePathBuf) -> ModulePathBuf {
245 mod_path[1..].to_vec()
246 }
247
248 pub(super) fn is_contract_package(&self) -> bool {
249 self.is_contract_package
250 }
251
252 pub fn module_from_absolute_path(&self, mod_path: &ModulePathBuf) -> Option<&Module> {
254 assert!(!mod_path.is_empty());
255 let package_relative_path = Self::package_relative_path(mod_path);
256 if mod_path[0] == *self.current_package.name() {
257 self.current_package.submodule(&package_relative_path)
258 } else if let Some(external_package) = self.external_packages.get(&mod_path[0].to_string())
259 {
260 external_package
261 .current_package_root_module()
262 .submodule(&package_relative_path)
263 } else {
264 None
265 }
266 }
267
268 pub(crate) fn require_module(
271 &self,
272 handler: &Handler,
273 mod_path: &ModulePathBuf,
274 ) -> Result<&Module, ErrorEmitted> {
275 if mod_path.is_empty() {
276 return Err(handler.emit_err(CompileError::Internal(
277 "Found empty absolute mod path",
278 Span::dummy(),
279 )));
280 }
281 let is_in_current_package = self.check_path_is_in_current_package(mod_path);
282 match self.module_from_absolute_path(mod_path) {
283 Some(module) => Ok(module),
284 None => Err(handler.emit_err(crate::namespace::module::module_not_found(
285 mod_path,
286 is_in_current_package,
287 ))),
288 }
289 }
290
291 pub(super) fn module_in_current_package(&self, mod_path: &ModulePathBuf) -> Option<&Module> {
293 assert!(self.check_path_is_in_current_package(mod_path));
294 self.module_from_absolute_path(mod_path)
295 }
296
297 pub(super) fn module_mut_from_absolute_path(
299 &mut self,
300 mod_path: &ModulePathBuf,
301 ) -> Option<&mut Module> {
302 assert!(!mod_path.is_empty());
303 let package_relative_path = Self::package_relative_path(mod_path);
304 if *self.current_package.name() == mod_path[0] {
305 self.current_package.submodule_mut(&package_relative_path)
306 } else if let Some(external_package) =
307 self.external_packages.get_mut(&mod_path[0].to_string())
308 {
309 external_package.module_mut_in_current_package(&package_relative_path)
310 } else {
311 None
312 }
313 }
314
315 pub(super) fn require_module_mut(
318 &mut self,
319 handler: &Handler,
320 mod_path: &ModulePathBuf,
321 ) -> Result<&mut Module, ErrorEmitted> {
322 let is_in_current_package = self.check_path_is_in_current_package(mod_path);
323 match self.module_mut_from_absolute_path(mod_path) {
324 Some(module) => Ok(module),
325 None => Err(handler.emit_err(crate::namespace::module::module_not_found(
326 mod_path,
327 is_in_current_package,
328 ))),
329 }
330 }
331
332 pub(super) fn module_mut_in_current_package(
334 &mut self,
335 mod_path: &ModulePathBuf,
336 ) -> Option<&mut Module> {
337 assert!(self.check_path_is_in_current_package(mod_path));
338 self.module_mut_from_absolute_path(mod_path)
339 }
340
341 pub(super) fn require_module_mut_in_current_package(
344 &mut self,
345 handler: &Handler,
346 mod_path: &ModulePathBuf,
347 ) -> Result<&mut Module, ErrorEmitted> {
348 assert!(self.check_path_is_in_current_package(mod_path));
349 self.require_module_mut(handler, mod_path)
350 }
351
352 pub fn star_import(
361 &mut self,
362 handler: &Handler,
363 engines: &Engines,
364 src: &ModulePath,
365 dst: &ModulePath,
366 visibility: Visibility,
367 ) -> Result<(), ErrorEmitted> {
368 self.check_module_privacy(handler, src, dst)?;
369
370 let src_mod = self.require_module(handler, &src.to_vec())?;
371
372 let mut decls_and_item_imports = vec![];
373
374 let mut symbols = src_mod
376 .root_items()
377 .symbols
378 .keys()
379 .clone()
380 .collect::<Vec<_>>();
381 symbols.sort();
382 for symbol in symbols {
383 let decl = &src_mod.root_items().symbols[symbol];
384 if is_ancestor(src, dst) || decl.visibility(engines).is_public() {
385 decls_and_item_imports.push((symbol.clone(), decl.clone(), src.to_vec()));
386 }
387 }
388 let mut symbols = src_mod
391 .root_items()
392 .use_item_synonyms
393 .keys()
394 .clone()
395 .collect::<Vec<_>>();
396 symbols.sort();
397 for symbol in symbols {
398 let (_, path, decl, src_visibility) = &src_mod.root_items().use_item_synonyms[symbol];
399 if src_visibility.is_public() {
400 decls_and_item_imports.push((symbol.clone(), decl.clone(), path.clone()))
401 }
402 }
403
404 let mut glob_imports = vec![];
408 let mut symbols = src_mod
409 .root_items()
410 .use_glob_synonyms
411 .keys()
412 .clone()
413 .collect::<Vec<_>>();
414 symbols.sort();
415 for symbol in symbols {
416 let bindings = &src_mod.root_items().use_glob_synonyms[symbol];
417 if !decls_and_item_imports
419 .iter()
420 .any(|(other_symbol, _, _)| symbol == other_symbol)
421 {
422 for (path, decl, src_visibility) in bindings.iter() {
423 if src_visibility.is_public() {
424 glob_imports.push((symbol.clone(), decl.clone(), path.clone()))
425 }
426 }
427 }
428 }
429
430 let implemented_traits = src_mod.root_items().implemented_traits.clone();
431 let dst_mod = self.require_module_mut_in_current_package(handler, &dst.to_vec())?;
432
433 dst_mod
434 .current_items_mut()
435 .implemented_traits
436 .extend(implemented_traits, engines);
437
438 decls_and_item_imports
439 .iter()
440 .chain(glob_imports.iter())
441 .for_each(|(symbol, decl, path)| {
442 dst_mod.current_items_mut().insert_glob_use_symbol(
443 engines,
444 symbol.clone(),
445 path.clone(),
446 decl,
447 visibility,
448 )
449 });
450
451 Ok(())
452 }
453
454 pub(crate) fn self_import(
459 &mut self,
460 handler: &Handler,
461 engines: &Engines,
462 src: &ModulePath,
463 dst: &ModulePath,
464 alias: Option<Ident>,
465 visibility: Visibility,
466 ) -> Result<(), ErrorEmitted> {
467 let (last_item, src) = src.split_last().expect("guaranteed by grammar");
468 self.item_import(handler, engines, src, last_item, dst, alias, visibility)
469 }
470
471 pub(super) fn item_lookup(
472 &self,
473 handler: &Handler,
474 engines: &Engines,
475 item: &Ident,
476 src: &ModulePath,
477 dst: &ModulePath,
478 ignore_visibility: bool,
479 ) -> Result<(ResolvedDeclaration, ModulePathBuf), ErrorEmitted> {
480 let src_mod = self.require_module(handler, &src.to_vec())?;
481 let src_items = src_mod.root_items();
482
483 let (decl, path, src_visibility) = if let Some(decl) = src_items.symbols.get(item) {
484 let visibility = if is_ancestor(src, dst) {
485 Visibility::Public
486 } else {
487 decl.visibility(engines)
488 };
489 (decl.clone(), src.to_vec(), visibility)
490 } else if let Some((_, path, decl, reexport)) = src_items.use_item_synonyms.get(item) {
491 (decl.clone(), path.clone(), *reexport)
492 } else if let Some(decls) = src_items.use_glob_synonyms.get(item) {
493 if decls.len() == 1 {
494 let (path, decl, reexport) = &decls[0];
495 (decl.clone(), path.clone(), *reexport)
496 } else if decls.is_empty() {
497 return Err(handler.emit_err(CompileError::Internal(
498 "The name {symbol} was bound in a star import, but no corresponding module paths were found",
499 item.span(),
500 )));
501 } else {
502 return Err(handler.emit_err(CompileError::SymbolWithMultipleBindings {
503 name: item.clone(),
504 paths: decls
505 .iter()
506 .map(|(path, decl, _)| {
507 let mut path_strs = super::lexical_scope::get_path_for_decl(
508 path,
509 decl,
510 engines,
511 self.current_package_name(),
512 );
513 if let TyDecl::EnumVariantDecl(ty::EnumVariantDecl {
515 enum_ref, ..
516 }) = decl.expect_typed_ref()
517 {
518 path_strs.push(enum_ref.name().to_string())
519 };
520 path_strs.join("::")
521 })
522 .collect(),
523 span: item.span(),
524 }));
525 }
526 } else {
527 return Err(handler.emit_err(CompileError::SymbolNotFound {
529 name: item.clone(),
530 span: item.span(),
531 }));
532 };
533
534 if !ignore_visibility && !src_visibility.is_public() {
535 handler.emit_err(CompileError::ImportPrivateSymbol {
536 name: item.clone(),
537 span: item.span(),
538 });
539 }
540
541 Ok((decl, path))
542 }
543
544 #[allow(clippy::too_many_arguments)]
548 pub(crate) fn item_import(
549 &mut self,
550 handler: &Handler,
551 engines: &Engines,
552 src: &ModulePath,
553 item: &Ident,
554 dst: &ModulePath,
555 alias: Option<Ident>,
556 visibility: Visibility,
557 ) -> Result<(), ErrorEmitted> {
558 self.check_module_privacy(handler, src, dst)?;
559 let src_mod = self.require_module(handler, &src.to_vec())?;
560
561 let (decl, path) = self.item_lookup(handler, engines, item, src, dst, false)?;
562
563 let mut impls_to_insert = TraitMap::default();
564 if decl.is_typed() {
565 if let Ok(type_id) = decl.return_type(&Handler::default(), engines) {
571 impls_to_insert.extend(
572 src_mod
573 .root_items()
574 .implemented_traits
575 .filter_by_type_item_import(type_id, engines),
576 engines,
577 );
578 }
579 let decl_span = decl.span(engines);
581 if decl.is_trait() {
582 impls_to_insert.extend(
585 src_mod
586 .root_items()
587 .implemented_traits
588 .filter_by_trait_decl_span(decl_span),
589 engines,
590 );
591 }
592 }
593
594 let dst_mod = self.require_module_mut_in_current_package(handler, &dst.to_vec())?;
596 let check_name_clash = |name| {
597 if dst_mod.current_items().use_item_synonyms.contains_key(name) {
598 handler.emit_err(CompileError::ShadowsOtherSymbol { name: name.into() });
599 }
600 };
601 match alias {
602 Some(alias) => {
603 check_name_clash(&alias);
604 dst_mod
605 .current_items_mut()
606 .use_item_synonyms
607 .insert(alias.clone(), (Some(item.clone()), path, decl, visibility))
608 }
609 None => {
610 check_name_clash(item);
611 dst_mod
612 .current_items_mut()
613 .use_item_synonyms
614 .insert(item.clone(), (None, path, decl, visibility))
615 }
616 };
617
618 dst_mod
619 .current_items_mut()
620 .implemented_traits
621 .extend(impls_to_insert, engines);
622
623 Ok(())
624 }
625
626 #[allow(clippy::too_many_arguments)] pub(crate) fn variant_import(
631 &mut self,
632 handler: &Handler,
633 engines: &Engines,
634 src: &ModulePath,
635 enum_name: &Ident,
636 variant_name: &Ident,
637 dst: &ModulePath,
638 alias: Option<Ident>,
639 visibility: Visibility,
640 ) -> Result<(), ErrorEmitted> {
641 self.check_module_privacy(handler, src, dst)?;
642
643 let decl_engine = engines.de();
644 let parsed_decl_engine = engines.pe();
645
646 let (decl, path) = self.item_lookup(handler, engines, enum_name, src, dst, false)?;
647
648 match decl {
649 ResolvedDeclaration::Parsed(decl) => {
650 if let Declaration::EnumDeclaration(decl_id) = decl {
651 let enum_decl = parsed_decl_engine.get_enum(&decl_id);
652
653 if let Some(variant_decl) =
654 enum_decl.variants.iter().find(|v| v.name == *variant_name)
655 {
656 let dst_mod =
658 self.require_module_mut_in_current_package(handler, &dst.to_vec())?;
659 let check_name_clash = |name| {
660 if dst_mod.current_items().use_item_synonyms.contains_key(name) {
661 handler.emit_err(CompileError::ShadowsOtherSymbol {
662 name: name.into(),
663 });
664 }
665 };
666
667 match alias {
668 Some(alias) => {
669 check_name_clash(&alias);
670 dst_mod.current_items_mut().use_item_synonyms.insert(
671 alias.clone(),
672 (
673 Some(variant_name.clone()),
674 path,
675 ResolvedDeclaration::Parsed(
676 Declaration::EnumVariantDeclaration(
677 EnumVariantDeclaration {
678 enum_ref: decl_id,
679 variant_name: variant_name.clone(),
680 variant_decl_span: variant_decl.span.clone(),
681 },
682 ),
683 ),
684 visibility,
685 ),
686 );
687 }
688 None => {
689 check_name_clash(variant_name);
690 dst_mod.current_items_mut().use_item_synonyms.insert(
691 variant_name.clone(),
692 (
693 None,
694 path,
695 ResolvedDeclaration::Parsed(
696 Declaration::EnumVariantDeclaration(
697 EnumVariantDeclaration {
698 enum_ref: decl_id,
699 variant_name: variant_name.clone(),
700 variant_decl_span: variant_decl.span.clone(),
701 },
702 ),
703 ),
704 visibility,
705 ),
706 );
707 }
708 };
709 } else {
710 return Err(handler.emit_err(CompileError::SymbolNotFound {
711 name: variant_name.clone(),
712 span: variant_name.span(),
713 }));
714 }
715 }
716 }
717 ResolvedDeclaration::Typed(decl) => {
718 if let TyDecl::EnumDecl(ty::EnumDecl { decl_id, .. }) = decl {
719 let enum_decl = decl_engine.get_enum(&decl_id);
720 let enum_ref = DeclRef::new(
721 enum_decl.call_path.suffix.clone(),
722 decl_id,
723 enum_decl.span(),
724 );
725
726 if let Some(variant_decl) =
727 enum_decl.variants.iter().find(|v| v.name == *variant_name)
728 {
729 let dst_mod =
731 self.require_module_mut_in_current_package(handler, &dst.to_vec())?;
732 let check_name_clash = |name| {
733 if dst_mod.current_items().use_item_synonyms.contains_key(name) {
734 handler.emit_err(CompileError::ShadowsOtherSymbol {
735 name: name.into(),
736 });
737 }
738 };
739
740 match alias {
741 Some(alias) => {
742 check_name_clash(&alias);
743 dst_mod.current_items_mut().use_item_synonyms.insert(
744 alias.clone(),
745 (
746 Some(variant_name.clone()),
747 path,
748 ResolvedDeclaration::Typed(TyDecl::EnumVariantDecl(
749 ty::EnumVariantDecl {
750 enum_ref: enum_ref.clone(),
751 variant_name: variant_name.clone(),
752 variant_decl_span: variant_decl.span.clone(),
753 },
754 )),
755 visibility,
756 ),
757 );
758 }
759 None => {
760 check_name_clash(variant_name);
761 dst_mod.current_items_mut().use_item_synonyms.insert(
762 variant_name.clone(),
763 (
764 None,
765 path,
766 ResolvedDeclaration::Typed(TyDecl::EnumVariantDecl(
767 ty::EnumVariantDecl {
768 enum_ref: enum_ref.clone(),
769 variant_name: variant_name.clone(),
770 variant_decl_span: variant_decl.span.clone(),
771 },
772 )),
773 visibility,
774 ),
775 );
776 }
777 };
778 } else {
779 return Err(handler.emit_err(CompileError::SymbolNotFound {
780 name: variant_name.clone(),
781 span: variant_name.span(),
782 }));
783 }
784 } else {
785 return Err(handler.emit_err(CompileError::Internal(
786 "Attempting to import variants of something that isn't an enum",
787 enum_name.span(),
788 )));
789 }
790 }
791 };
792
793 Ok(())
794 }
795
796 pub(crate) fn variant_star_import(
800 &mut self,
801 handler: &Handler,
802 engines: &Engines,
803 src: &ModulePath,
804 dst: &ModulePath,
805 enum_name: &Ident,
806 visibility: Visibility,
807 ) -> Result<(), ErrorEmitted> {
808 self.check_module_privacy(handler, src, dst)?;
809
810 let parsed_decl_engine = engines.pe();
811 let decl_engine = engines.de();
812
813 let (decl, path) = self.item_lookup(handler, engines, enum_name, src, dst, false)?;
814
815 match decl {
816 ResolvedDeclaration::Parsed(Declaration::EnumDeclaration(decl_id)) => {
817 let enum_decl = parsed_decl_engine.get_enum(&decl_id);
818
819 for variant in enum_decl.variants.iter() {
820 let variant_name = &variant.name;
821 let variant_decl =
822 Declaration::EnumVariantDeclaration(EnumVariantDeclaration {
823 enum_ref: decl_id,
824 variant_name: variant_name.clone(),
825 variant_decl_span: variant.span.clone(),
826 });
827
828 self.require_module_mut_in_current_package(handler, &dst.to_vec())?
830 .current_items_mut()
831 .insert_glob_use_symbol(
832 engines,
833 variant_name.clone(),
834 path.clone(),
835 &ResolvedDeclaration::Parsed(variant_decl),
836 visibility,
837 );
838 }
839 }
840 ResolvedDeclaration::Typed(TyDecl::EnumDecl(ty::EnumDecl { decl_id, .. })) => {
841 let enum_decl = decl_engine.get_enum(&decl_id);
842 let enum_ref = DeclRef::new(
843 enum_decl.call_path.suffix.clone(),
844 decl_id,
845 enum_decl.span(),
846 );
847
848 for variant_decl in enum_decl.variants.iter() {
849 let variant_name = &variant_decl.name;
850 let decl =
851 ResolvedDeclaration::Typed(TyDecl::EnumVariantDecl(ty::EnumVariantDecl {
852 enum_ref: enum_ref.clone(),
853 variant_name: variant_name.clone(),
854 variant_decl_span: variant_decl.span.clone(),
855 }));
856
857 self.require_module_mut_in_current_package(handler, &dst.to_vec())?
859 .current_items_mut()
860 .insert_glob_use_symbol(
861 engines,
862 variant_name.clone(),
863 path.clone(),
864 &decl,
865 visibility,
866 );
867 }
868 }
869 _ => {
870 return Err(handler.emit_err(CompileError::Internal(
871 "Attempting to import variants of something that isn't an enum",
872 enum_name.span(),
873 )));
874 }
875 };
876
877 Ok(())
878 }
879
880 pub(crate) fn check_module_privacy(
892 &self,
893 handler: &Handler,
894 src: &ModulePath,
895 dst: &ModulePath,
896 ) -> Result<(), ErrorEmitted> {
897 let mut ignored_prefixes = 0;
899
900 ignored_prefixes += src
902 .iter()
903 .zip(dst)
904 .position(|(src_id, dst_id)| src_id != dst_id)
905 .unwrap_or(dst.len());
906
907 if dst.len() == ignored_prefixes {
909 ignored_prefixes += 1;
910 }
911
912 for prefix in iter_prefixes(src).skip(ignored_prefixes) {
914 if let Some(module) = self.module_from_absolute_path(&prefix.to_vec()) {
915 if module.visibility().is_private() {
916 let prefix_last = prefix[prefix.len() - 1].clone();
917 handler.emit_err(CompileError::ImportPrivateModule {
918 span: prefix_last.span(),
919 name: prefix_last,
920 });
921 }
922 } else {
923 return Ok(());
924 }
925 }
926
927 Ok(())
928 }
929}
930
931fn is_ancestor(src: &ModulePath, dst: &ModulePath) -> bool {
932 dst.len() >= src.len() && src.iter().zip(dst).all(|(src, dst)| src == dst)
933}