@@ -1607,6 +1607,113 @@ jl_value_t *jl_rewrap_unionall_(jl_value_t *t, jl_value_t *u)
1607
1607
return t ;
1608
1608
}
1609
1609
1610
+ // Create a copy of type expression t where any occurrence of data type x is replaced by y.
1611
+ // If x does not occur in t, return t without any copy.
1612
+ // For example, jl_substitute_datatype(Foo{Bar}, Foo{T}, Qux{S}) is Qux{Bar}, with T and S
1613
+ // free type variables.
1614
+ // To substitute type variables, use jl_substitute_var instead.
1615
+ jl_value_t * jl_substitute_datatype (jl_value_t * t , jl_datatype_t * x , jl_datatype_t * y )
1616
+ {
1617
+ if jl_is_datatype (t ) {
1618
+ jl_datatype_t * typ = (jl_datatype_t * )t ;
1619
+ // For datatypes call itself recursively on the parameters to form new parameters.
1620
+ // Then, if typename(t) == typename(x), rewrap the wrapper of y around the new
1621
+ // parameters. Otherwise, do the same around the wrapper of t.
1622
+ // This ensures that the types and supertype are properly set.
1623
+ // Start by check whether there is a parameter that needs replacing.
1624
+ long i_firstnewparam = -1 ;
1625
+ size_t nparams = jl_svec_len (typ -> parameters );
1626
+ jl_value_t * firstnewparam = NULL ;
1627
+ JL_GC_PUSH1 (& firstnewparam );
1628
+ for (size_t i = 0 ; i < nparams ; i ++ ) {
1629
+ jl_value_t * param = NULL ;
1630
+ JL_GC_PUSH1 (& param );
1631
+ param = jl_svecref (typ -> parameters , i );
1632
+ firstnewparam = jl_substitute_datatype (param , x , y );
1633
+ if (param != firstnewparam ) {
1634
+ i_firstnewparam = i ;
1635
+ JL_GC_POP ();
1636
+ break ;
1637
+ }
1638
+ JL_GC_POP ();
1639
+ }
1640
+ // If one of the parameters needs to be updated, or if the type name is that to
1641
+ // substitute, create a new datataype
1642
+ if (i_firstnewparam != -1 || typ -> name == x -> name ) {
1643
+ jl_datatype_t * uw = typ -> name == x -> name ? y : typ ; // substitution occurs here
1644
+ jl_value_t * wrapper = uw -> name -> wrapper ;
1645
+ jl_datatype_t * w = (jl_datatype_t * )jl_unwrap_unionall (wrapper );
1646
+ jl_svec_t * sv = jl_alloc_svec_uninit (jl_svec_len (uw -> parameters ));
1647
+ jl_value_t * * vals = jl_svec_data (sv );
1648
+ // no JL_GC_PUSHARGS(vals, ...) since GC is already aware of sv
1649
+ for (long i = 0 ; i < i_firstnewparam ; i ++ ) { // copy the identical parameters
1650
+ vals [i ] = jl_svecref (typ -> parameters , i ); // value
1651
+ }
1652
+ if (i_firstnewparam != -1 ) { // insert the first non-identical parameter
1653
+ vals [i_firstnewparam ] = firstnewparam ;
1654
+ }
1655
+ for (size_t i = i_firstnewparam + 1 ; i < nparams ; i ++ ) { // insert the remaining parameters
1656
+ vals [i ] = jl_substitute_datatype (jl_svecref (typ -> parameters , i ), x , y );
1657
+ }
1658
+ if (jl_is_tuple_type (wrapper )) {
1659
+ // special case for tuples, since the wrapper (Tuple) does not have as
1660
+ // many parameters as t (it only has a Vararg instead).
1661
+ t = jl_apply_tuple_type (sv , 0 );
1662
+ } else {
1663
+ t = jl_instantiate_type_in_env ((jl_value_t * )w , (jl_unionall_t * )wrapper , vals );
1664
+ }
1665
+ }
1666
+ JL_GC_POP ();
1667
+ }
1668
+ else if jl_is_unionall (t ) { // recursively call itself on body and var bounds
1669
+ jl_unionall_t * ut = (jl_unionall_t * )t ;
1670
+ jl_value_t * lb = NULL ;
1671
+ jl_value_t * ub = NULL ;
1672
+ jl_value_t * body = NULL ;
1673
+ JL_GC_PUSH3 (& lb , & ub , & body );
1674
+ lb = jl_substitute_datatype (ut -> var -> lb , x , y );
1675
+ ub = jl_substitute_datatype (ut -> var -> ub , x , y );
1676
+ body = jl_substitute_datatype (ut -> body , x , y );
1677
+ if (lb != ut -> var -> lb || ub != ut -> var -> ub ) {
1678
+ jl_tvar_t * newtvar = jl_new_typevar (ut -> var -> name , lb , ub );
1679
+ JL_GC_PUSH1 (& newtvar );
1680
+ t = jl_new_struct (jl_unionall_type , newtvar , body );
1681
+ JL_GC_POP ();
1682
+ }
1683
+ else if (body != ut -> body ) {
1684
+ t = jl_new_struct (jl_unionall_type , ut -> var , body );
1685
+ }
1686
+ JL_GC_POP ();
1687
+ }
1688
+ else if jl_is_uniontype (t ) { // recursively call itself on a and b
1689
+ jl_uniontype_t * u = (jl_uniontype_t * )t ;
1690
+ jl_value_t * a = NULL ;
1691
+ jl_value_t * b = NULL ;
1692
+ JL_GC_PUSH2 (& a , & b );
1693
+ a = jl_substitute_datatype (u -> a , x , y );
1694
+ b = jl_substitute_datatype (u -> b , x , y );
1695
+ if (a != u -> a || b != u -> b ) {
1696
+ t = jl_new_struct (jl_uniontype_type , a , b );
1697
+ }
1698
+ JL_GC_POP ();
1699
+ }
1700
+ else if jl_is_vararg (t ) { // recursively call itself on T
1701
+ jl_vararg_t * vt = (jl_vararg_t * )t ;
1702
+ jl_value_t * rT = NULL ;
1703
+ JL_GC_PUSH1 (& rT );
1704
+ rT = jl_substitute_datatype (vt -> T , x , y );
1705
+ if (rT != vt -> T ) {
1706
+ jl_task_t * ct = jl_current_task ;
1707
+ t = jl_gc_alloc (ct -> ptls , sizeof (jl_vararg_t ), jl_vararg_type );
1708
+ jl_set_typetagof ((jl_vararg_t * )t , jl_vararg_tag , 0 );
1709
+ ((jl_vararg_t * )t )-> T = rT ;
1710
+ ((jl_vararg_t * )t )-> N = vt -> N ;
1711
+ }
1712
+ JL_GC_POP ();
1713
+ }
1714
+ return t ;
1715
+ }
1716
+
1610
1717
static jl_value_t * lookup_type_stack (jl_typestack_t * stack , jl_datatype_t * tt , size_t ntp ,
1611
1718
jl_value_t * * iparams )
1612
1719
{
0 commit comments