@@ -1694,36 +1694,48 @@ static int equiv_field_types(jl_value_t *old, jl_value_t *ft)
16941694// inline it. The only way fields can reference this type (due to
16951695// syntax-enforced restrictions) is via being passed as a type parameter. Thus
16961696// 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+ }
17121716 if (jl_is_typevar (p ))
17131717 return 0 ; // already checked by unionall, if applicable
17141718 if (jl_is_datatype (p )) {
17151719 jl_datatype_t * dp = (jl_datatype_t * )p ;
17161720 if (affects_layout && dp -> name == name )
17171721 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
17231722 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+ }
17241736 size_t i , l = jl_nparams (p );
17251737 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 ))
17271739 return 1 ;
17281740 }
17291741 }
@@ -1759,12 +1771,12 @@ JL_CALLABLE(jl_f__typebody)
17591771 // able to compute the layout of the object before needing to
17601772 // publish it, so we must assume it cannot be inlined, if that
17611773 // 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 ))) {
17631775 int mayinlinealloc = 1 ;
17641776 size_t i ;
17651777 for (i = 0 ; i < nf ; i ++ ) {
17661778 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 )) {
17681780 mayinlinealloc = 0 ;
17691781 break ;
17701782 }
0 commit comments