@@ -1694,36 +1694,48 @@ static int equiv_field_types(jl_value_t *old, jl_value_t *ft)
1694
1694
// inline it. The only way fields can reference this type (due to
1695
1695
// syntax-enforced restrictions) is via being passed as a type parameter. Thus
1696
1696
// we can conservatively check this by examining only the parameters of the
1697
- // dependent types.
1698
- // affects_layout is a hack introduced by #35275 to workaround a problem
1699
- // introduced by #34223: it checks whether we will potentially need to
1700
- // compute the layout of the object before we have fully computed the types of
1701
- // the fields during recursion over the allocation of the parameters for the
1702
- // field types (of the concrete subtypes)
1703
- static int references_name (jl_value_t * p , jl_typename_t * name , int affects_layout ) JL_NOTSAFEPOINT
1704
- {
1705
- if (jl_is_uniontype (p ))
1706
- return references_name (((jl_uniontype_t * )p )-> a , name , affects_layout ) ||
1707
- references_name (((jl_uniontype_t * )p )-> b , name , affects_layout );
1708
- if (jl_is_unionall (p ))
1709
- return references_name ((jl_value_t * )((jl_unionall_t * )p )-> var -> lb , name , 0 ) ||
1710
- references_name ((jl_value_t * )((jl_unionall_t * )p )-> var -> ub , name , 0 ) ||
1711
- references_name (((jl_unionall_t * )p )-> body , name , affects_layout );
1697
+ // dependent types. Additionally, a field might have already observed this
1698
+ // object for layout purposes before we got around to deciding if inlining
1699
+ // would be possible, so we cannot change the layout now if so.
1700
+ // affects_layout is a (conservative) analysis of layout_uses_free_typevars
1701
+ // freevars is a (conservative) analysis of what calling jl_has_bound_typevars from name->wrapper gives (TODO: just call this instead?)
1702
+ static int references_name (jl_value_t * p , jl_typename_t * name , int affects_layout , int freevars ) JL_NOTSAFEPOINT
1703
+ {
1704
+ if (freevars && !jl_has_free_typevars (p ))
1705
+ freevars = 0 ;
1706
+ while (jl_is_unionall (p )) {
1707
+ if (references_name ((jl_value_t * )((jl_unionall_t * )p )-> var -> lb , name , 0 , freevars ) ||
1708
+ references_name ((jl_value_t * )((jl_unionall_t * )p )-> var -> ub , name , 0 , freevars ))
1709
+ return 1 ;
1710
+ p = ((jl_unionall_t * )p )-> body ;
1711
+ }
1712
+ if (jl_is_uniontype (p )) {
1713
+ return references_name (((jl_uniontype_t * )p )-> a , name , affects_layout , freevars ) ||
1714
+ references_name (((jl_uniontype_t * )p )-> b , name , affects_layout , freevars );
1715
+ }
1712
1716
if (jl_is_typevar (p ))
1713
1717
return 0 ; // already checked by unionall, if applicable
1714
1718
if (jl_is_datatype (p )) {
1715
1719
jl_datatype_t * dp = (jl_datatype_t * )p ;
1716
1720
if (affects_layout && dp -> name == name )
1717
1721
return 1 ;
1718
- // affects_layout checks whether we will need to attempt to layout this
1719
- // type (based on whether all copies of it have the same layout) in
1720
- // that case, we still need to check the recursive parameters for
1721
- // layout recursion happening also, but we know it won't itself cause
1722
- // problems for the layout computation
1723
1722
affects_layout = ((jl_datatype_t * )jl_unwrap_unionall (dp -> name -> wrapper ))-> layout == NULL ;
1723
+ // and even if it has a layout, the fields themselves might trigger layouts if they use tparam i
1724
+ // rather than checking this for each field, we just assume it applies
1725
+ if (!affects_layout && freevars && jl_field_names (dp ) != jl_emptysvec ) {
1726
+ jl_svec_t * types = ((jl_datatype_t * )jl_unwrap_unionall (dp -> name -> wrapper ))-> types ;
1727
+ size_t i , l = jl_svec_len (types );
1728
+ for (i = 0 ; i < l ; i ++ ) {
1729
+ jl_value_t * ft = jl_svecref (types , i );
1730
+ if (!jl_is_typevar (ft ) && jl_has_free_typevars (ft )) {
1731
+ affects_layout = 1 ;
1732
+ break ;
1733
+ }
1734
+ }
1735
+ }
1724
1736
size_t i , l = jl_nparams (p );
1725
1737
for (i = 0 ; i < l ; i ++ ) {
1726
- if (references_name (jl_tparam (p , i ), name , affects_layout ))
1738
+ if (references_name (jl_tparam (p , i ), name , affects_layout , freevars ))
1727
1739
return 1 ;
1728
1740
}
1729
1741
}
@@ -1759,12 +1771,12 @@ JL_CALLABLE(jl_f__typebody)
1759
1771
// able to compute the layout of the object before needing to
1760
1772
// publish it, so we must assume it cannot be inlined, if that
1761
1773
// check passes, then we also still need to check the fields too.
1762
- if (!dt -> name -> mutabl && (nf == 0 || !references_name ((jl_value_t * )dt -> super , dt -> name , 1 ))) {
1774
+ if (!dt -> name -> mutabl && (nf == 0 || !references_name ((jl_value_t * )dt -> super , dt -> name , 0 , 1 ))) {
1763
1775
int mayinlinealloc = 1 ;
1764
1776
size_t i ;
1765
1777
for (i = 0 ; i < nf ; i ++ ) {
1766
1778
jl_value_t * fld = jl_svecref (ft , i );
1767
- if (references_name (fld , dt -> name , 1 )) {
1779
+ if (references_name (fld , dt -> name , 1 , 1 )) {
1768
1780
mayinlinealloc = 0 ;
1769
1781
break ;
1770
1782
}
0 commit comments