@@ -38,6 +38,10 @@ pub struct SchemaEvalContext {
3838 pub config_meta : ValueRef ,
3939 pub optional_mapping : ValueRef ,
4040 pub is_sub_schema : bool ,
41+ /// Whether the schema body has been fully evaluated.
42+ /// This flag is used to avoid redundant calculations during
43+ /// schema attribute assignments.
44+ pub body_evaluated : bool ,
4145}
4246
4347impl SchemaEvalContext {
@@ -59,6 +63,7 @@ impl SchemaEvalContext {
5963 config_meta : ValueRef :: dict ( None ) ,
6064 optional_mapping : ValueRef :: dict ( None ) ,
6165 is_sub_schema : true ,
66+ body_evaluated : false ,
6267 }
6368 }
6469
@@ -76,6 +81,7 @@ impl SchemaEvalContext {
7681 config_meta,
7782 optional_mapping : ValueRef :: dict ( None ) ,
7883 is_sub_schema : true ,
84+ body_evaluated : false ,
7985 } ) )
8086 }
8187
@@ -93,6 +99,7 @@ impl SchemaEvalContext {
9399 config_meta : ValueRef :: dict ( None ) ,
94100 optional_mapping : ValueRef :: dict ( None ) ,
95101 is_sub_schema : true ,
102+ body_evaluated : false ,
96103 } ) )
97104 }
98105
@@ -505,6 +512,8 @@ pub(crate) fn schema_body(
505512 for stmt in & node. body {
506513 s. walk_stmt ( stmt) . expect ( kcl_error:: RUNTIME_ERROR_MSG ) ;
507514 }
515+ // Mark schema body as evaluated to avoid redundant calculations
516+ ctx. borrow_mut ( ) . body_evaluated = true ;
508517 // Schema decorators check
509518 for decorator in & node. decorators {
510519 s. walk_decorator_with_name ( & decorator. node , Some ( & schema_name) , true )
@@ -704,20 +713,30 @@ pub(crate) fn schema_with_config(
704713 }
705714
706715 {
707- let mut ctx = s. runtime_ctx . borrow_mut ( ) ;
716+ let mut runtime_ctx = s. runtime_ctx . borrow_mut ( ) ;
708717 // Record schema instance in the context
709- if !ctx. instances . contains_key ( & runtime_type) {
710- ctx. instances
718+ if !runtime_ctx. instances . contains_key ( & runtime_type) {
719+ runtime_ctx
720+ . instances
711721 . insert ( runtime_type. clone ( ) , IndexMap :: default ( ) ) ;
712722 }
713- let pkg_instance_map = ctx . instances . get_mut ( & runtime_type) . unwrap ( ) ;
723+ let pkg_instance_map = runtime_ctx . instances . get_mut ( & runtime_type) . unwrap ( ) ;
714724 if !pkg_instance_map. contains_key ( & instance_pkgpath) {
715725 pkg_instance_map. insert ( instance_pkgpath. clone ( ) , vec ! [ ] ) ;
716726 }
717- pkg_instance_map
718- . get_mut ( & instance_pkgpath)
719- . unwrap ( )
720- . push ( schema_ctx_value. clone ( ) ) ;
727+ // Only record the instance once after the schema body is fully evaluated
728+ // to avoid recording intermediate states during mixin/parent processing
729+ let should_record = ctx. borrow ( ) . body_evaluated ;
730+ if should_record {
731+ let instance_list = pkg_instance_map. get_mut ( & instance_pkgpath) . unwrap ( ) ;
732+ // Check by reference to avoid exact duplicates
733+ let is_duplicate = instance_list
734+ . iter ( )
735+ . any ( |existing| std:: ptr:: eq ( & existing. rc , & schema_ctx_value. rc ) ) ;
736+ if !is_duplicate {
737+ instance_list. push ( schema_ctx_value. clone ( ) ) ;
738+ }
739+ }
721740 }
722741 // Dict to schema
723742 if is_sub_schema {
0 commit comments