@@ -249,6 +249,9 @@ pub struct SymbolTable {
249249 pub effects : indexmap:: IndexMap < InternedString , crate :: hir:: HirId > ,
250250 /// Effect handlers by name
251251 pub handlers : indexmap:: IndexMap < InternedString , crate :: hir:: HirId > ,
252+ /// External function link names (alias -> ZRTL symbol)
253+ /// e.g., "tensor_add" -> "$Tensor$add"
254+ pub extern_link_names : indexmap:: IndexMap < InternedString , String > ,
252255}
253256
254257/// Import metadata for debugging and error messages
@@ -955,6 +958,9 @@ impl LoweringContext {
955958 // Pre-register impl block methods in symbol table WITH MANGLED NAMES
956959 // This must match the mangling done in lower_impl_block
957960
961+ // Check if implementing type is extern struct
962+ let is_extern_struct = matches ! ( & impl_block. for_type, zyntax_typed_ast:: Type :: Extern { .. } ) ;
963+
958964 // Get the implementing type name
959965 let type_name = match & impl_block. for_type {
960966 zyntax_typed_ast:: Type :: Named { id, .. } => {
@@ -982,7 +988,8 @@ impl LoweringContext {
982988 if let Some ( type_def) = self . type_registry . get_type_by_name ( fresh_name) {
983989 type_def. name
984990 } else {
985- continue ; // Can't resolve type, skip
991+ // For extern struct, use the name directly
992+ * name
986993 }
987994 }
988995 }
@@ -998,12 +1005,16 @@ impl LoweringContext {
9981005
9991006 // Generate mangled name matching lower_impl_block
10001007 let mangled_name = if is_inherent {
1001- // Inherent method: {TypeName}${method_name}
10021008 let type_name_str = type_name. resolve_global ( )
10031009 . unwrap_or_else ( || "UnknownType" . to_string ( ) ) ;
1010+ // Strip $ prefix if present (extern struct names have runtime_prefix)
1011+ let base_type_name = type_name_str. strip_prefix ( '$' ) . unwrap_or ( & type_name_str) ;
10041012 let method_name_str = method. name . resolve_global ( )
10051013 . unwrap_or_else ( || "unknown_method" . to_string ( ) ) ;
1006- InternedString :: new_global ( & format ! ( "{}${}" , type_name_str, method_name_str) )
1014+
1015+ // Use consistent TypeName$method naming for all extern struct methods
1016+ // ZRTL symbols start with $ (e.g., $Tensor$sum_f32), so no collision
1017+ InternedString :: new_global ( & format ! ( "{}${}" , base_type_name, method_name_str) )
10071018 } else {
10081019 // Trait method: {TypeName}${TraitName}${method_name}
10091020 self . mangle_trait_method_name ( type_name, impl_block. trait_name , method. name )
@@ -1126,7 +1137,10 @@ impl LoweringContext {
11261137 if let Some ( ref link_name) = func. link_name {
11271138 let link_name_str = link_name. resolve_global ( )
11281139 . unwrap_or_else ( || link_name. to_string ( ) ) ;
1129- hir_func. link_name = Some ( link_name_str) ;
1140+ hir_func. link_name = Some ( link_name_str. clone ( ) ) ;
1141+
1142+ // Register the alias -> link_name mapping for SSA call resolution
1143+ self . symbols . extern_link_names . insert ( func. name , link_name_str) ;
11301144 }
11311145
11321146 // Extern functions have no body - clear the default entry block
@@ -1160,7 +1174,9 @@ impl LoweringContext {
11601174 self . type_registry . clone ( ) ,
11611175 self . arena . clone ( ) ,
11621176 self . symbols . functions . clone ( )
1163- ) . with_return_type ( func. return_type . clone ( ) ) ;
1177+ )
1178+ . with_return_type ( func. return_type . clone ( ) )
1179+ . with_extern_link_names ( self . symbols . extern_link_names . clone ( ) ) ;
11641180 let ssa = ssa_builder. build_from_typed_cfg ( & typed_cfg) ?;
11651181
11661182 // Debug: check SSA result
@@ -2169,6 +2185,20 @@ impl LoweringContext {
21692185 let is_inherent = trait_name_str. is_empty ( ) ;
21702186 eprintln ! ( "[LOWERING] Impl block is_inherent: {}, trait_name: '{}'" , is_inherent, trait_name_str) ;
21712187
2188+ // Check if the implementing type is an extern struct
2189+ // For extern structs, methods should automatically map to ZRTL symbols
2190+ let is_extern_struct = matches ! ( & implementing_type, Type :: Extern { .. } ) ;
2191+ let extern_type_name = if let Type :: Extern { name, .. } = & implementing_type {
2192+ let name_str = name. resolve_global ( ) . unwrap_or_default ( ) ;
2193+ // The extern type name may have a leading $ (runtime_prefix) - strip it for the base name
2194+ // e.g., "$Tensor" -> "Tensor"
2195+ let base_name = name_str. strip_prefix ( '$' ) . unwrap_or ( & name_str) ;
2196+ Some ( base_name. to_string ( ) )
2197+ } else {
2198+ None
2199+ } ;
2200+ eprintln ! ( "[LOWERING] is_extern_struct: {}, extern_type_name: {:?}" , is_extern_struct, extern_type_name) ;
2201+
21722202 // For trait impls, register the implementation in the type registry
21732203 let trait_id = if !is_inherent {
21742204 let trait_def = self . type_registry . get_trait_by_name ( impl_block. trait_name )
@@ -2337,8 +2367,9 @@ impl LoweringContext {
23372367 } ;
23382368
23392369 // Mangle the method name to include trait and type info
2340- // Format for inherent: {TypeName}${method_name}
2341- // Format for trait: {TypeName}${TraitName}${method_name}
2370+ // For extern struct methods WITH bodies (wrappers): use _zynml_{Type}_{method} to avoid ZRTL collision
2371+ // For extern struct methods WITHOUT bodies: auto-map creates external function with ZRTL link
2372+ // For regular structs: {TypeName}${method_name} or {TypeName}${TraitName}${method_name}
23422373 let mangled_name = {
23432374 let type_name = match & implementing_type {
23442375 Type :: Named { id, .. } => {
@@ -2348,16 +2379,22 @@ impl LoweringContext {
23482379 method. name // Fallback to original name
23492380 }
23502381 }
2351- _ => method. name , // For non-named types, use original name
2382+ Type :: Extern { name, .. } => * name, // Use the extern struct's name
2383+ _ => method. name , // For other types, use original name
23522384 } ;
23532385
23542386 // For inherent impls (empty trait name), use simpler mangling
23552387 if is_inherent {
23562388 let type_name_str = type_name. resolve_global ( )
23572389 . unwrap_or_else ( || "UnknownType" . to_string ( ) ) ;
2390+ // Strip $ prefix if present (extern struct names have runtime_prefix)
2391+ let base_type_name = type_name_str. strip_prefix ( '$' ) . unwrap_or ( & type_name_str) ;
23582392 let method_name_str = method. name . resolve_global ( )
23592393 . unwrap_or_else ( || "unknown_method" . to_string ( ) ) ;
2360- let mangled = format ! ( "{}${}" , type_name_str, method_name_str) ;
2394+
2395+ // Use consistent TypeName$method naming for all extern struct methods
2396+ // ZRTL symbols start with $ (e.g., $Tensor$sum_f32), so no collision
2397+ let mangled = format ! ( "{}${}" , base_type_name, method_name_str) ;
23612398 InternedString :: new_global ( & mangled)
23622399 } else {
23632400 // For trait impls, include trait name
@@ -2381,7 +2418,44 @@ impl LoweringContext {
23812418 new_id
23822419 } ;
23832420
2384- // Create a function from the method
2421+ // For extern struct methods WITHOUT a body, create external function declaration
2422+ // that automatically maps to ZRTL symbol: $TypeName$method_name
2423+ // If the method has an explicit body, use that body as an override
2424+ if is_extern_struct && method. body . is_none ( ) {
2425+ if let Some ( ref type_name) = extern_type_name {
2426+ let method_name_str = method. name . resolve_global ( ) . unwrap_or_default ( ) ;
2427+ // ZRTL symbol format: $TypeName$method_name (e.g., $Tensor$matmul)
2428+ let zrtl_symbol = format ! ( "${}${}" , type_name, method_name_str) ;
2429+ eprintln ! ( "[LOWERING] Extern struct method: {} -> ZRTL symbol: {} (params: {})" ,
2430+ mangled_name. resolve_global( ) . unwrap_or_default( ) , zrtl_symbol, params. len( ) ) ;
2431+
2432+ let func = TypedFunction {
2433+ name : mangled_name,
2434+ annotations : vec ! [ ] ,
2435+ effects : vec ! [ ] ,
2436+ type_params : vec ! [ ] ,
2437+ params,
2438+ return_type : resolved_return_type,
2439+ body : None , // No body - external function
2440+ visibility : zyntax_typed_ast:: type_registry:: Visibility :: Public ,
2441+ is_async : method. is_async ,
2442+ is_pure : false ,
2443+ is_external : true , // Mark as external
2444+ calling_convention : zyntax_typed_ast:: type_registry:: CallingConvention :: Default ,
2445+ link_name : Some ( InternedString :: new_global ( & zrtl_symbol) ) , // Link to ZRTL symbol
2446+ } ;
2447+
2448+ if let Err ( e) = self . lower_function ( & func) {
2449+ let method_name_str = mangled_name. resolve_global ( ) . unwrap_or_default ( ) ;
2450+ eprintln ! ( "[LOWERING WARN] Skipping extern method '{}': {:?}" , method_name_str, e) ;
2451+ self . symbols . functions . remove ( & mangled_name) ;
2452+ continue ;
2453+ }
2454+ continue ; // Skip regular function lowering
2455+ }
2456+ }
2457+
2458+ // Create a function from the method (regular, non-extern struct)
23852459 let func = TypedFunction {
23862460 name : mangled_name, // Use mangled name for trait method
23872461 annotations : vec ! [ ] ,
@@ -3131,9 +3205,24 @@ impl LoweringContext {
31313205 self . lower_function ( & func)
31323206 }
31333207
3134- /// Resolve associated function call (Type::method) to mangled trait method name
3208+ /// Resolve associated function call (Type::method) to mangled method name
31353209 /// Returns None if the function cannot be resolved
31363210 fn resolve_associated_function_to_mangled ( & self , type_name : & str , method_name : & str ) -> Option < String > {
3211+ // First, check for inherent impl methods (including extern struct methods)
3212+ // Try wrapper method name first: _zynml_{Type}_{method}
3213+ let wrapper_name = format ! ( "_zynml_{}_{}" , type_name, method_name) ;
3214+ let wrapper_interned = InternedString :: new_global ( & wrapper_name) ;
3215+ if self . symbols . functions . contains_key ( & wrapper_interned) {
3216+ return Some ( wrapper_name) ;
3217+ }
3218+
3219+ // Try standard inherent method: {Type}${method}
3220+ let inherent_name = format ! ( "{}${}" , type_name, method_name) ;
3221+ let inherent_interned = InternedString :: new_global ( & inherent_name) ;
3222+ if self . symbols . functions . contains_key ( & inherent_interned) {
3223+ return Some ( inherent_name) ;
3224+ }
3225+
31373226 // Search through all trait implementations to find the method
31383227 for ( _trait_id, impls) in self . type_registry . iter_implementations ( ) {
31393228 for impl_def in impls {
0 commit comments