@@ -1607,6 +1607,118 @@ 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_GC_PUSH1 (& sv );
1648
+ jl_value_t * * vals = jl_svec_data (sv );
1649
+ // no JL_GC_PUSHARGS(vals, ...) since GC is already aware of sv
1650
+ for (long i = 0 ; i < i_firstnewparam ; i ++ ) { // copy the identical parameters
1651
+ vals [i ] = jl_svecref (typ -> parameters , i ); // value
1652
+ }
1653
+ if (i_firstnewparam != -1 ) { // insert the first non-identical parameter
1654
+ vals [i_firstnewparam ] = firstnewparam ;
1655
+ }
1656
+ for (size_t i = i_firstnewparam + 1 ; i < nparams ; i ++ ) { // insert the remaining parameters
1657
+ vals [i ] = jl_substitute_datatype (jl_svecref (typ -> parameters , i ), x , y );
1658
+ }
1659
+ if (jl_is_tuple_type (wrapper )) {
1660
+ // special case for tuples, since the wrapper (Tuple) does not have as
1661
+ // many parameters as t (it only has a Vararg instead).
1662
+ t = jl_apply_tuple_type (sv , 0 );
1663
+ } else {
1664
+ t = jl_instantiate_type_in_env ((jl_value_t * )w , (jl_unionall_t * )wrapper , vals );
1665
+ }
1666
+ JL_GC_POP ();
1667
+ }
1668
+ JL_GC_POP ();
1669
+ }
1670
+ else if jl_is_unionall (t ) { // recursively call itself on body and var bounds
1671
+ jl_unionall_t * ut = (jl_unionall_t * )t ;
1672
+ jl_value_t * lb = NULL ;
1673
+ jl_value_t * ub = NULL ;
1674
+ jl_value_t * body = NULL ;
1675
+ JL_GC_PUSH3 (& lb , & ub , & body );
1676
+ lb = jl_substitute_datatype (ut -> var -> lb , x , y );
1677
+ ub = jl_substitute_datatype (ut -> var -> ub , x , y );
1678
+ body = jl_substitute_datatype (ut -> body , x , y );
1679
+ if (lb != ut -> var -> lb || ub != ut -> var -> ub ) {
1680
+ jl_tvar_t * newtvar = jl_new_typevar (ut -> var -> name , lb , ub );
1681
+ JL_GC_PUSH1 (& newtvar );
1682
+ body = jl_substitute_var (body , ut -> var , (jl_value_t * )newtvar );
1683
+ t = jl_new_struct (jl_unionall_type , newtvar , body );
1684
+ JL_GC_POP ();
1685
+ }
1686
+ else if (body != ut -> body ) {
1687
+ t = jl_new_struct (jl_unionall_type , ut -> var , body );
1688
+ }
1689
+ JL_GC_POP ();
1690
+ }
1691
+ else if jl_is_uniontype (t ) { // recursively call itself on a and b
1692
+ jl_uniontype_t * u = (jl_uniontype_t * )t ;
1693
+ jl_value_t * a = NULL ;
1694
+ jl_value_t * b = NULL ;
1695
+ JL_GC_PUSH2 (& a , & b );
1696
+ a = jl_substitute_datatype (u -> a , x , y );
1697
+ b = jl_substitute_datatype (u -> b , x , y );
1698
+ if (a != u -> a || b != u -> b ) {
1699
+ t = jl_new_struct (jl_uniontype_type , a , b );
1700
+ }
1701
+ JL_GC_POP ();
1702
+ }
1703
+ else if jl_is_vararg (t ) { // recursively call itself on T
1704
+ jl_vararg_t * vt = (jl_vararg_t * )t ;
1705
+ if (vt -> T ) { // vt->T could be NULL
1706
+ jl_value_t * rT = NULL ;
1707
+ JL_GC_PUSH1 (& rT );
1708
+ rT = jl_substitute_datatype (vt -> T , x , y );
1709
+ if (rT != vt -> T ) {
1710
+ jl_task_t * ct = jl_current_task ;
1711
+ t = jl_gc_alloc (ct -> ptls , sizeof (jl_vararg_t ), jl_vararg_type );
1712
+ jl_set_typetagof ((jl_vararg_t * )t , jl_vararg_tag , 0 );
1713
+ ((jl_vararg_t * )t )-> T = rT ;
1714
+ ((jl_vararg_t * )t )-> N = vt -> N ;
1715
+ }
1716
+ JL_GC_POP ();
1717
+ }
1718
+ }
1719
+ return t ;
1720
+ }
1721
+
1610
1722
static jl_value_t * lookup_type_stack (jl_typestack_t * stack , jl_datatype_t * tt , size_t ntp ,
1611
1723
jl_value_t * * iparams )
1612
1724
{
0 commit comments