@@ -1406,7 +1406,6 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru
14061406 m -> flags |= MRB_FL_CLASS_IS_INHERITED ;
14071407 ins_pos -> super = ic ;
14081408 mrb_field_write_barrier (mrb , (struct RBasic * )ins_pos , (struct RBasic * )ic );
1409- mrb_mc_clear_by_class (mrb , ins_pos );
14101409 ins_pos = ic ;
14111410 skip :
14121411 m = m -> super ;
@@ -1415,24 +1414,71 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru
14151414 return 0 ;
14161415}
14171416
1417+ static int
1418+ fix_include_module (mrb_state * mrb , struct RBasic * obj , void * data )
1419+ {
1420+ struct RClass * * m = (struct RClass * * )data ;
1421+
1422+ if (obj -> tt == MRB_TT_ICLASS && obj -> c == m [0 ] && (obj -> flags & MRB_FL_CLASS_IS_ORIGIN ) == 0 ) {
1423+ struct RClass * ic = (struct RClass * )obj ;
1424+ include_module_at (mrb , ic , ic , m [1 ], 1 );
1425+ }
1426+ return MRB_EACH_OBJ_OK ;
1427+ }
1428+
14181429MRB_API void
14191430mrb_include_module (mrb_state * mrb , struct RClass * c , struct RClass * m )
14201431{
14211432 mrb_check_frozen (mrb , c );
14221433 if (include_module_at (mrb , c , find_origin (c ), m , 1 ) < 0 ) {
14231434 mrb_raise (mrb , E_ARGUMENT_ERROR , "cyclic include detected" );
14241435 }
1436+ if (c -> tt == MRB_TT_MODULE && (c -> flags & MRB_FL_CLASS_IS_INHERITED )) {
1437+ struct RClass * data [2 ];
1438+ data [0 ] = c ;
1439+ data [1 ] = m ;
1440+ mrb_objspace_each_objects (mrb , fix_include_module , data );
1441+ }
1442+ }
1443+
1444+ static int
1445+ fix_prepend_module (mrb_state * mrb , struct RBasic * obj , void * data )
1446+ {
1447+ struct RClass * * m = (struct RClass * * )data ;
1448+ struct RClass * c = (struct RClass * )obj ;
1449+
1450+ if (c -> tt == MRB_TT_CLASS || c -> tt == MRB_TT_MODULE ) {
1451+ struct RClass * p = c -> super ;
1452+ while (p ) {
1453+ if (c == m [0 ]) break ;
1454+ if (p -> tt == MRB_TT_CLASS ) break ;
1455+ if (p -> c == m [0 ]) {
1456+ include_module_at (mrb , c , c , m [1 ], 0 );
1457+ break ;
1458+ }
1459+ c = p ;
1460+ p = p -> super ;
1461+ }
1462+ }
1463+ return MRB_EACH_OBJ_OK ;
14251464}
14261465
14271466MRB_API void
14281467mrb_prepend_module (mrb_state * mrb , struct RClass * c , struct RClass * m )
14291468{
14301469 struct RClass * origin ;
1431- int changed = 0 ;
14321470
14331471 mrb_check_frozen (mrb , c );
14341472 if (!(c -> flags & MRB_FL_CLASS_IS_PREPENDED )) {
1435- origin = (struct RClass * )mrb_obj_alloc (mrb , MRB_TT_ICLASS , c );
1473+ struct RClass * c0 ;
1474+
1475+ if (c -> tt == MRB_TT_ICLASS ) {
1476+ c0 = c -> c ;
1477+ }
1478+ else {
1479+ c0 = c ;
1480+ }
1481+ origin = (struct RClass * )mrb_obj_alloc (mrb , MRB_TT_ICLASS , c0 );
14361482 origin -> flags |= MRB_FL_CLASS_IS_ORIGIN | MRB_FL_CLASS_IS_INHERITED ;
14371483 origin -> super = c -> super ;
14381484 c -> super = origin ;
@@ -1441,10 +1487,16 @@ mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
14411487 mrb_field_write_barrier (mrb , (struct RBasic * )c , (struct RBasic * )origin );
14421488 c -> flags |= MRB_FL_CLASS_IS_PREPENDED ;
14431489 }
1444- changed = include_module_at (mrb , c , c , m , 0 );
1445- if (changed < 0 ) {
1490+ if (include_module_at (mrb , c , c , m , 0 ) < 0 ) {
14461491 mrb_raise (mrb , E_ARGUMENT_ERROR , "cyclic prepend detected" );
14471492 }
1493+ if (c -> tt == MRB_TT_MODULE &&
1494+ (c -> flags & (MRB_FL_CLASS_IS_INHERITED |MRB_FL_CLASS_IS_PREPENDED ))) {
1495+ struct RClass * data [2 ];
1496+ data [0 ] = c ;
1497+ data [1 ] = m ;
1498+ mrb_objspace_each_objects (mrb , fix_prepend_module , data );
1499+ }
14481500}
14491501
14501502static mrb_value
@@ -1651,7 +1703,6 @@ mrb_mc_clear_by_class(mrb_state *mrb, struct RClass *c)
16511703
16521704 if (c -> flags & MRB_FL_CLASS_IS_INHERITED ) {
16531705 mc_clear (mrb );
1654- c -> flags &= ~MRB_FL_CLASS_IS_INHERITED ;
16551706 return ;
16561707 }
16571708 for (i = 0 ; i < MRB_METHOD_CACHE_SIZE ; i ++ ) {
0 commit comments