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