@@ -259,6 +259,9 @@ pub struct SymbolTable {
259259 /// External function link names (alias -> ZRTL symbol)
260260 /// e.g., "tensor_add" -> "$Tensor$add"
261261 pub extern_link_names : indexmap:: IndexMap < InternedString , String > ,
262+ /// Default parameter info for functions with optional parameters
263+ /// Maps function name -> Vec<TypedParameter> (for filling in defaults at call sites)
264+ pub function_default_params : indexmap:: IndexMap < InternedString , Vec < zyntax_typed_ast:: typed_ast:: TypedParameter > > ,
262265}
263266
264267/// Import metadata for debugging and error messages
@@ -408,6 +411,33 @@ impl LoweringContext {
408411 log:: trace!( "[LOWERING] Added builtin: '{}' -> '{}'" , alias, target) ;
409412 }
410413
414+ // Pre-register extern type trait methods as extern link names.
415+ // Trait impls for extern types (e.g., impl Clone for Tensor) dispatch to ZRTL
416+ // symbols. Register these before lowering functions so SSA can resolve them.
417+ for ( trait_id, impls) in type_registry. iter_implementations ( ) {
418+ for impl_def in impls {
419+ if let zyntax_typed_ast:: Type :: Extern { name, .. } = & impl_def. for_type {
420+ let type_name = name. resolve_global ( ) . unwrap_or_default ( ) ;
421+ let base_type_name = type_name. strip_prefix ( '$' ) . unwrap_or ( & type_name) . to_string ( ) ;
422+ let trait_def = type_registry. get_trait_by_id ( * trait_id) ;
423+ let trait_name = trait_def
424+ . and_then ( |td| td. name . resolve_global ( ) )
425+ . unwrap_or_default ( ) ;
426+
427+ for method in & impl_def. methods {
428+ let method_name = method. signature . name . resolve_global ( ) . unwrap_or_default ( ) ;
429+ // SSA generates trait-mangled name: TypeName$TraitName$method
430+ let mangled = format ! ( "{}${}${}" , base_type_name, trait_name, method_name) ;
431+ // ZRTL exports inherent name: $TypeName$method (no trait name)
432+ let symbol = format ! ( "${}${}" , base_type_name, method_name) ;
433+ symbols
434+ . extern_link_names
435+ . insert ( InternedString :: new_global ( & mangled) , symbol) ;
436+ }
437+ }
438+ }
439+ }
440+
411441 Self {
412442 module : HirModule :: new ( module_name) ,
413443 type_registry,
@@ -587,21 +617,24 @@ impl LoweringContext {
587617 let total_errors = diagnostics_collector. error_count ( ) ;
588618 let total_warnings = diagnostics_collector. warning_count ( ) ;
589619
620+ // Check if errors include stdlib (prelude/tensor) — known false positives.
621+ // The stdlib is concatenated into the user's source, so check for import
622+ // declarations or stdlib/ paths as indicators.
623+ let has_stdlib = program
624+ . source_files
625+ . iter ( )
626+ . any ( |sf| sf. name . contains ( "stdlib/" ) )
627+ || program. declarations . iter ( ) . any ( |d| {
628+ matches ! ( & d. node, TypedDeclaration :: Import ( _) )
629+ } ) ;
630+
590631 // Display diagnostics using the built-in pretty formatter
591- // Suppress stdlib errors (known false positives in impl blocks)
592632 if total_errors > 0 || total_warnings > 0 {
593- use zyntax_typed_ast:: diagnostics:: { ConsoleDiagnosticDisplay , DiagnosticDisplay } ;
594- use zyntax_typed_ast:: source:: SourceMap ;
595-
596- // Check if errors are only from stdlib
597- let has_stdlib_sources = program
598- . source_files
599- . iter ( )
600- . any ( |sf| sf. name . contains ( "stdlib/" ) ) ;
601-
602- // If we have stdlib sources, suppress the diagnostic output
603- // (these are known false positives from trait impl type checking)
604- if !has_stdlib_sources {
633+ // If stdlib is included, suppress diagnostic output
634+ // (these are known false positives from generic/trait type checking)
635+ if !has_stdlib {
636+ use zyntax_typed_ast:: diagnostics:: { ConsoleDiagnosticDisplay , DiagnosticDisplay } ;
637+ use zyntax_typed_ast:: source:: SourceMap ;
605638 eprintln ! ( "\n === Type Checking Diagnostics ===" ) ;
606639
607640 // Create a source map and populate it with source files from the program
@@ -619,13 +652,9 @@ impl LoweringContext {
619652 }
620653 }
621654
622- // Suppress error count if only stdlib errors
623- let has_stdlib_sources = program
624- . source_files
625- . iter ( )
626- . any ( |sf| sf. name . contains ( "stdlib/" ) ) ;
627- let ( error_count, warning_count) = if has_stdlib_sources {
628- ( 0 , 0 ) // Suppress stdlib type errors (known false positives)
655+ // Suppress error count if stdlib errors (known false positives from generics)
656+ let ( error_count, warning_count) = if has_stdlib {
657+ ( 0 , 0 )
629658 } else {
630659 ( total_errors, total_warnings)
631660 } ;
@@ -1576,6 +1605,10 @@ impl LoweringContext {
15761605 TypedDeclaration :: Function ( func) => {
15771606 let func_id = crate :: hir:: HirId :: new ( ) ;
15781607 self . symbols . functions . insert ( func. name , func_id) ;
1608+ // Record default parameter info for functions with optional params
1609+ if func. params . iter ( ) . any ( |p| p. default_value . is_some ( ) ) {
1610+ self . symbols . function_default_params . insert ( func. name , func. params . clone ( ) ) ;
1611+ }
15791612 }
15801613
15811614 TypedDeclaration :: Class ( class_decl) => {
@@ -1861,7 +1894,8 @@ impl LoweringContext {
18611894 self . symbols . functions . clone ( ) ,
18621895 )
18631896 . with_return_type ( func. return_type . clone ( ) )
1864- . with_extern_link_names ( self . symbols . extern_link_names . clone ( ) ) ;
1897+ . with_extern_link_names ( self . symbols . extern_link_names . clone ( ) )
1898+ . with_function_default_params ( self . symbols . function_default_params . clone ( ) ) ;
18651899 let ssa = ssa_builder. build_from_typed_cfg ( & typed_cfg) ?;
18661900
18671901 // Debug: check SSA result
@@ -2765,7 +2799,7 @@ impl LoweringContext {
27652799 ) -> zyntax_typed_ast:: TypedBlock {
27662800 use zyntax_typed_ast:: TypedBlock ;
27672801
2768- eprintln ! (
2802+ log :: trace !(
27692803 "[RETYPE_BLOCK] Processing {} statements" ,
27702804 block. statements. len( )
27712805 ) ;
@@ -2774,7 +2808,7 @@ impl LoweringContext {
27742808 . iter ( )
27752809 . enumerate ( )
27762810 . map ( |( idx, stmt_node) | {
2777- eprintln ! ( "[RETYPE_BLOCK] Processing statement {}" , idx) ;
2811+ log :: trace !( "[RETYPE_BLOCK] Processing statement {}" , idx) ;
27782812 self . retype_statement_with_self ( stmt_node, self_params)
27792813 } )
27802814 . collect ( ) ;
@@ -2795,9 +2829,7 @@ impl LoweringContext {
27952829
27962830 let retyped_stmt = match & stmt_node. node {
27972831 TypedStatement :: Expression ( expr) => {
2798- eprintln ! ( "[RETYPE_STMT] Retyping expression statement" ) ;
27992832 let retyped = self . retype_expression_node_with_self ( expr, self_params) ;
2800- eprintln ! ( "[RETYPE_STMT] Expression retyping done" ) ;
28012833 TypedStatement :: Expression ( Box :: new ( retyped) )
28022834 }
28032835 TypedStatement :: Let ( let_stmt) => TypedStatement :: Let ( TypedLet {
@@ -2891,19 +2923,12 @@ impl LoweringContext {
28912923
28922924 // Field access - retype the object expression and possibly update field type
28932925 TypedExpression :: Field ( field_access) => {
2894- eprintln ! (
2895- "[RETYPE] Field access starting: object.ty={:?}, field={:?}" ,
2896- field_access. object. ty, field_access. field
2897- ) ;
28982926 let retyped_object =
28992927 self . retype_expression_node_with_self ( & field_access. object , self_params) ;
2900- eprintln ! ( "[RETYPE] Field access: object before={:?}, after={:?}, field={:?}, expr_ty={:?}" ,
2901- field_access. object. ty, retyped_object. ty, field_access. field, expr_node. ty) ;
29022928 let retyped_field_access = TypedFieldAccess {
29032929 object : Box :: new ( retyped_object) ,
29042930 field : field_access. field ,
29052931 } ;
2906- eprintln ! ( "[RETYPE] Field access done, returning" ) ;
29072932 // Keep the original field result type - it should have been correctly typed by the parser
29082933 (
29092934 TypedExpression :: Field ( retyped_field_access) ,
@@ -3019,7 +3044,7 @@ impl LoweringContext {
30193044 ) -> CompilerResult < ( ) > {
30203045 use zyntax_typed_ast:: { Type , TypeId , TypedFunction } ;
30213046
3022- eprintln ! (
3047+ log :: trace !(
30233048 "[LOWERING IMPL] Starting lower_impl_block for_type={:?}, trait_name={:?}, {} methods" ,
30243049 impl_block. for_type,
30253050 impl_block. trait_name,
@@ -3031,12 +3056,12 @@ impl LoweringContext {
30313056 let implementing_type = match & impl_block. for_type {
30323057 Type :: Unresolved ( name) => {
30333058 // Look up the type by name in the registry
3034- eprintln ! ( "[LOWERING] Looking up unresolved type: {:?}" , name) ;
3059+ log :: trace !( "[LOWERING] Looking up unresolved type: {:?}" , name) ;
30353060
30363061 // Find the type in the registry
30373062 if let Some ( type_def) = self . type_registry . get_type_by_name ( * name) {
30383063 let type_id = type_def. id ;
3039- eprintln ! ( "[LOWERING] Found TypeId: {:?}" , type_id) ;
3064+ log :: trace !( "[LOWERING] Found TypeId: {:?}" , type_id) ;
30403065 Type :: Named {
30413066 id : type_id,
30423067 type_args : vec ! [ ] ,
@@ -3061,7 +3086,7 @@ impl LoweringContext {
30613086 }
30623087 _ => impl_block. for_type . clone ( ) ,
30633088 } ;
3064- eprintln ! (
3089+ log :: trace !(
30653090 "[LOWERING] Impl block implementing_type after resolution: {:?}" ,
30663091 implementing_type
30673092 ) ;
@@ -3076,7 +3101,7 @@ impl LoweringContext {
30763101 } ;
30773102
30783103 let is_inherent = trait_name_str. is_empty ( ) ;
3079- eprintln ! (
3104+ log :: trace !(
30803105 "[LOWERING] Impl block is_inherent: {}, trait_name: '{}'" ,
30813106 is_inherent, trait_name_str
30823107 ) ;
@@ -3093,7 +3118,7 @@ impl LoweringContext {
30933118 } else {
30943119 None
30953120 } ;
3096- eprintln ! (
3121+ log :: trace !(
30973122 "[LOWERING] is_extern_struct: {}, extern_type_name: {:?}" ,
30983123 is_extern_struct, extern_type_name
30993124 ) ;
@@ -3218,18 +3243,18 @@ impl LoweringContext {
32183243 // TODO: Register impl in type registry before lowering starts
32193244 // self.type_registry is Arc (immutable), so we can't register here
32203245 // For now, method resolution relies on mangled names being available in SSA phase
3221- eprintln ! (
3246+ log :: trace !(
32223247 "[LOWERING] Built impl def for trait {:?} for type {:?} (registration TODO)" ,
32233248 tid, implementing_type
32243249 ) ;
3225- eprintln ! ( "[LOWERING] ImplDef has {} methods" , impl_def. methods. len( ) ) ;
3250+ log :: trace !( "[LOWERING] ImplDef has {} methods" , impl_def. methods. len( ) ) ;
32263251 } else {
3227- eprintln ! ( "[LOWERING] Skipping ImplDef creation for inherent impl (no trait)" ) ;
3252+ log :: trace !( "[LOWERING] Skipping ImplDef creation for inherent impl (no trait)" ) ;
32283253 }
32293254
32303255 // For each method in the impl block, convert it to a function and lower it
32313256 for ( method_idx, method) in impl_block. methods . iter ( ) . enumerate ( ) {
3232- eprintln ! (
3257+ log :: trace !(
32333258 "[LOWERING] Processing method {} of {}: {}" ,
32343259 method_idx + 1 ,
32353260 impl_block. methods. len( ) ,
@@ -3243,12 +3268,12 @@ impl LoweringContext {
32433268 . params
32443269 . iter ( )
32453270 . map ( |p| {
3246- eprintln ! ( "[LOWERING] Param is_self={}, ty={:?}" , p. is_self, p. ty) ;
3271+ log :: trace !( "[LOWERING] Param is_self={}, ty={:?}" , p. is_self, p. ty) ;
32473272 let resolved_ty = if p. is_self
32483273 && ( matches ! ( p. ty, Type :: Any ) || matches ! ( p. ty, Type :: Unresolved ( _) ) )
32493274 {
32503275 // Self parameter without explicit type -> use implementing type
3251- eprintln ! ( "[LOWERING] Resolving self param to {:?}" , implementing_type) ;
3276+ log :: trace !( "[LOWERING] Resolving self param to {:?}" , implementing_type) ;
32523277 let resolved = implementing_type. clone ( ) ;
32533278 // Track this parameter for body retyping
32543279 self_param_mappings. push ( ( p. name , resolved. clone ( ) ) ) ;
@@ -3270,21 +3295,21 @@ impl LoweringContext {
32703295 . collect ( ) ;
32713296
32723297 // Re-type the method body to update self references
3273- eprintln ! (
3298+ log :: trace !(
32743299 "[LOWERING] Retyping method body, self_param_mappings: {:?}" ,
32753300 self_param_mappings
32763301 ) ;
32773302 let retyped_body = method. body . as_ref ( ) . map ( |body| {
32783303 let result = self . retype_block_with_self ( body, & self_param_mappings) ;
3279- eprintln ! ( "[LOWERING] Retyping complete" ) ;
3304+ log :: trace !( "[LOWERING] Retyping complete" ) ;
32803305 result
32813306 } ) ;
32823307
32833308 // Resolve return type: convert Self -> implementing_type, Unresolved -> lookup
32843309 let resolved_return_type = match & method. return_type {
32853310 Type :: Any => {
32863311 // Self type in return position -> use implementing type
3287- eprintln ! (
3312+ log :: trace !(
32883313 "[LOWERING] Resolving return type Self -> {:?}" ,
32893314 implementing_type
32903315 ) ;
@@ -3347,13 +3372,13 @@ impl LoweringContext {
33473372 }
33483373 } ;
33493374
3350- eprintln ! ( "[LOWERING] Mangled method name: {:?}" , mangled_name) ;
3375+ log :: trace !( "[LOWERING] Mangled method name: {:?}" , mangled_name) ;
33513376
33523377 // Get the existing function_id from collect_declarations, or create new if missing
33533378 // This ensures consistency between the two phases
33543379 let function_id = if let Some ( & existing_id) = self . symbols . functions . get ( & mangled_name)
33553380 {
3356- eprintln ! (
3381+ log :: trace !(
33573382 "[LOWERING] Using existing function_id for {:?}" ,
33583383 mangled_name
33593384 ) ;
@@ -3374,7 +3399,7 @@ impl LoweringContext {
33743399 let method_name_str = method. name . resolve_global ( ) . unwrap_or_default ( ) ;
33753400 // ZRTL symbol format: $TypeName$method_name (e.g., $Tensor$matmul)
33763401 let zrtl_symbol = format ! ( "${}${}" , type_name, method_name_str) ;
3377- eprintln ! (
3402+ log :: trace !(
33783403 "[LOWERING] Extern struct method: {} -> ZRTL symbol: {} (params: {})" ,
33793404 mangled_name. resolve_global( ) . unwrap_or_default( ) ,
33803405 zrtl_symbol,
@@ -4675,13 +4700,9 @@ impl LoweringContext {
46754700 // Step 2: Extract type_id from for_type (nominal types only)
46764701 let type_id = match & impl_def. for_type {
46774702 zyntax_typed_ast:: Type :: Named { id, .. } => * id,
4678- zyntax_typed_ast:: Type :: Extern { name, .. } => {
4679- // Extern types (like $Tensor) don't have TypeIds - they're handled by ZRTL
4680- // Skip trait impl lowering for extern types as they use runtime dispatch
4681- eprintln ! (
4682- "[LOWERING WARN] Skipping trait impl for extern type '{}' - ZRTL handles these" ,
4683- name. resolve_global( ) . unwrap_or_default( )
4684- ) ;
4703+ zyntax_typed_ast:: Type :: Extern { .. } => {
4704+ // Extern types use ZRTL for trait dispatch — already registered
4705+ // in LoweringContext::new() during early extern link name setup.
46854706 return Ok ( ( ) ) ;
46864707 }
46874708 zyntax_typed_ast:: Type :: Unresolved ( name) => {
0 commit comments