@@ -570,7 +570,8 @@ impl ModuleLinker {
570570 let Some ( linked_func_ref) = self . builder . lookup_func ( sig. name ( ) ) else {
571571 // If the function is not defined in the linked module, declare it and
572572 // make the mapping.
573- let linked_func_ref = self . builder . declare_function ( sig) ;
573+ // Safe unwrap: no existing function with this name, so declare_function won’t conflict.
574+ let linked_func_ref = self . builder . declare_function ( sig) . unwrap ( ) ;
574575 ref_map. func_mapping . insert ( func_ref, linked_func_ref) ;
575576 return Ok ( linked_func_ref) ;
576577 } ;
@@ -604,3 +605,131 @@ impl ModuleLinker {
604605 Ok ( linked_func_ref)
605606 }
606607}
608+
609+ #[ cfg( test) ]
610+ mod tests {
611+ use super :: * ;
612+ use crate :: { builder:: test_util:: test_module_builder, types:: Type , Linkage } ;
613+
614+ #[ test]
615+ fn test_linker_conflicting_function_signature_should_fail ( ) {
616+ let mod1 = {
617+ let builder = test_module_builder ( ) ;
618+ let sig = Signature :: new ( "foo" , Linkage :: Public , & [ Type :: I32 ] , Type :: I32 ) ;
619+ builder. declare_function ( sig) . unwrap ( ) ;
620+ builder. build ( )
621+ } ;
622+
623+ let mod2 = {
624+ let builder = test_module_builder ( ) ;
625+ let sig = Signature :: new ( "foo" , Linkage :: Public , & [ Type :: I64 ] , Type :: I64 ) ;
626+ builder. declare_function ( sig) . unwrap ( ) ;
627+ builder. build ( )
628+ } ;
629+
630+ let result = LinkedModule :: link ( vec ! [ mod1, mod2] ) ;
631+
632+ match result {
633+ Err ( LinkError :: InconsistentFuncSignature { name } ) => {
634+ assert_eq ! ( name, "foo" ) ;
635+ }
636+ _ => panic ! ( "Expected InconsistentFuncSignature error for function 'foo'" ) ,
637+ }
638+ }
639+
640+ #[ test]
641+ fn test_linker_duplicate_public_functions_should_fail ( ) {
642+ let sig = Signature :: new ( "foo" , Linkage :: Public , & [ Type :: I32 ] , Type :: I32 ) ;
643+
644+ let mod1 = {
645+ let builder = test_module_builder ( ) ;
646+ builder. declare_function ( sig. clone ( ) ) . unwrap ( ) ;
647+ builder. build ( )
648+ } ;
649+
650+ let mod2 = {
651+ let builder = test_module_builder ( ) ;
652+ builder. declare_function ( sig) . unwrap ( ) ;
653+ builder. build ( )
654+ } ;
655+
656+ let result = LinkedModule :: link ( vec ! [ mod1, mod2] ) ;
657+
658+ assert ! (
659+ matches!( result, Err ( LinkError :: InconsistentFuncSignature { name } ) if name == "foo" ) ,
660+ "Expected InconsistentFuncSignature error on duplicate Public function 'foo'"
661+ ) ;
662+ }
663+
664+ #[ test]
665+ fn test_linker_duplicate_private_should_fail ( ) {
666+ let sig = Signature :: new ( "foo" , Linkage :: Private , & [ Type :: I32 ] , Type :: I32 ) ;
667+
668+ let mod1 = {
669+ let builder = test_module_builder ( ) ;
670+ builder. declare_function ( sig. clone ( ) ) . unwrap ( ) ;
671+ builder. build ( )
672+ } ;
673+
674+ let mod2 = {
675+ let builder = test_module_builder ( ) ;
676+ builder. declare_function ( sig) . unwrap ( ) ;
677+ builder. build ( )
678+ } ;
679+
680+ let result = LinkedModule :: link ( vec ! [ mod1, mod2] ) ;
681+
682+ assert ! (
683+ matches!( result, Err ( LinkError :: InconsistentFuncSignature { name } ) if name == "foo" ) ,
684+ "Expected InconsistentFuncSignature error on duplicate Private function 'foo'"
685+ ) ;
686+ }
687+
688+ #[ test]
689+ fn test_linker_public_and_external_should_succeed ( ) {
690+ let sig_public = Signature :: new ( "foo" , Linkage :: Public , & [ Type :: I32 ] , Type :: I32 ) ;
691+ let sig_external = Signature :: new ( "foo" , Linkage :: External , & [ Type :: I32 ] , Type :: I32 ) ;
692+
693+ let mod1 = {
694+ let builder = test_module_builder ( ) ;
695+ builder. declare_function ( sig_public) . unwrap ( ) ;
696+ builder. build ( )
697+ } ;
698+
699+ let mod2 = {
700+ let builder = test_module_builder ( ) ;
701+ builder. declare_function ( sig_external) . unwrap ( ) ;
702+ builder. build ( )
703+ } ;
704+
705+ let result = LinkedModule :: link ( vec ! [ mod1, mod2] ) ;
706+ assert ! (
707+ result. is_ok( ) ,
708+ "Expected successful link for Public + External"
709+ ) ;
710+ }
711+
712+ #[ test]
713+ fn test_linker_different_names_should_succeed ( ) {
714+ let sig1 = Signature :: new ( "foo_mod1" , Linkage :: Private , & [ Type :: I32 ] , Type :: I32 ) ;
715+ let sig2 = Signature :: new ( "foo_mod2" , Linkage :: Private , & [ Type :: I32 ] , Type :: I32 ) ;
716+
717+ let mod1 = {
718+ let builder = test_module_builder ( ) ;
719+ builder. declare_function ( sig1) . unwrap ( ) ;
720+ builder. build ( )
721+ } ;
722+
723+ let mod2 = {
724+ let builder = test_module_builder ( ) ;
725+ builder. declare_function ( sig2) . unwrap ( ) ;
726+ builder. build ( )
727+ } ;
728+
729+ let result = LinkedModule :: link ( vec ! [ mod1, mod2] ) ;
730+ assert ! (
731+ result. is_ok( ) ,
732+ "Expected successful link for different function names"
733+ ) ;
734+ }
735+ }
0 commit comments