@@ -77,9 +77,7 @@ typedef struct jl_varbinding_t {
7777 // intvalued: must be integer-valued; i.e. occurs as N in Vararg{_,N}
7878 // 0: No restriction
7979 // 1: must be unbounded/ or fixed to a `Int`/typevar
80- // 2: This var has been commandeered once.
81- // 3: This var has been commandeered more than once.
82- // 4: This var has been commandeered more than once, and it has no fixed ub/lb.
80+ // 2: we have some imprecise vararg length intersection that can be improved if this var is const valued.
8381 int8_t intvalued ;
8482 int8_t limited ;
8583 int16_t depth0 ; // # of invariant constructors nested around the UnionAll type for this var
@@ -2209,16 +2207,10 @@ static jl_value_t *bound_var_below(jl_tvar_t *tv, jl_varbinding_t *bb, jl_stenv_
22092207 return bb -> lb ;
22102208 return jl_box_long (jl_unbox_long (bb -> lb ) - bb -> offset );
22112209 }
2212- if (bb -> intvalued == 1 && bb -> offset > 0 )
2213- // We really should return `tv` here, but some subtype tests need it.
2214- // As a temparay fix, increase `intvalued` to 2.
2210+ if (bb -> offset > 0 ) {
22152211 bb -> intvalued = 2 ;
2216- else if (bb -> intvalued == 2 )
2217- // If bb has been commandeered, we should always increase `intvalued`.
2218- bb -> intvalued = 3 ;
2219- else if (bb -> intvalued == 4 && bb -> offset > 0 )
2220- // bb has no fixed bounds, return `NULL` if `tv` is not correct.
22212212 return NULL ;
2213+ }
22222214 return (jl_value_t * )tv ;
22232215}
22242216
@@ -2307,6 +2299,26 @@ static int check_unsat_bound(jl_value_t *t, jl_tvar_t *v, jl_stenv_t *e) JL_NOTS
23072299 return 0 ;
23082300}
23092301
2302+ static int has_null_vararg_length (jl_value_t * a ) {
2303+ int is_unionall = 0 ;
2304+ while (jl_is_unionall (a )) {
2305+ a = ((jl_unionall_t * )a )-> body ;
2306+ is_unionall = 1 ;
2307+ }
2308+ if (jl_is_datatype (a ) && jl_is_tuple_type ((jl_datatype_t * )a )) {
2309+ size_t lx = jl_nparams ((jl_datatype_t * )a );
2310+ if (lx > 0 ) {
2311+ jl_value_t * la = jl_tparam ((jl_datatype_t * )a , lx - 1 );
2312+ if (jl_is_vararg (la )) {
2313+ jl_value_t * len = jl_unwrap_vararg_num ((jl_vararg_t * )la );
2314+ if (!len ) return 1 ;
2315+ if (!jl_is_long (len )) return is_unionall ;
2316+ }
2317+ }
2318+ }
2319+ return 0 ;
2320+ }
2321+
23102322static jl_value_t * intersect_var (jl_tvar_t * b , jl_value_t * a , jl_stenv_t * e , int8_t R , int param )
23112323{
23122324 jl_varbinding_t * bb = lookup (e , b );
@@ -2353,6 +2365,10 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int
23532365 ub = (jl_value_t * )b ;
23542366 }
23552367 }
2368+ if (has_null_vararg_length (ub ) && !has_null_vararg_length (a )) {
2369+ bb -> ub = ub ;
2370+ ub = (jl_value_t * )b ;
2371+ }
23562372 if (ub != (jl_value_t * )b ) {
23572373 if (jl_has_free_typevars (ub )) {
23582374 if (check_unsat_bound (ub , b , e )) {
@@ -2470,12 +2486,9 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
24702486 }
24712487 }
24722488
2473- // This typevar has been commandeered by the other side once. Which is allowed if it's unbounded.
2474- if (vb -> intvalued == 2 && vb -> lb == jl_bottom_type && vb -> ub == ( jl_value_t * ) jl_any_type )
2489+ // vb is still unbounded.
2490+ if (vb -> intvalued == 2 && !( varval && jl_is_long ( varval )) )
24752491 vb -> intvalued = 1 ;
2476- // This typevar has been commandeered more than once. Set it to 4 if its not fixed.
2477- if (vb -> intvalued == 3 && !(varval && jl_is_long (varval )))
2478- vb -> intvalued = 4 ;
24792492
24802493 // TODO: this can prevent us from matching typevar identities later
24812494 if (!varval && (vb -> lb != vb -> var -> lb || vb -> ub != vb -> var -> ub ))
@@ -3080,10 +3093,10 @@ static jl_value_t *intersect(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int pa
30803093 }
30813094 JL_GC_POP ();
30823095 // Here we always return the shorter `Vararg`'s length.
3083- if ((xx && xx -> offset < 0 ) || (yy && yy -> offset > 0 ))
3096+ if ((xx && xx -> offset < 0 ) || (yy && yy -> offset > 0 )) {
3097+ if (yy ) yy -> intvalued = 2 ;
30843098 return x ;
3085- if ((xx && xx -> offset > 0 ) || (yy && yy -> offset < 0 ))
3086- return y ;
3099+ }
30873100 return y ;
30883101 }
30893102 record_var_occurrence (xx , e , param );
0 commit comments