@@ -74,7 +74,13 @@ typedef struct jl_varbinding_t {
7474 // 1 - var.ub = ub; return var
7575 // 2 - either (var.ub = ub; return var), or return ub
7676 int8_t constraintkind ;
77- int8_t intvalued ; // must be integer-valued; i.e. occurs as N in Vararg{_,N}
77+ // intvalued: must be integer-valued; i.e. occurs as N in Vararg{_,N}
78+ // 0: No restriction
79+ // 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.
83+ int8_t intvalued ;
7884 int8_t limited ;
7985 int16_t depth0 ; // # of invariant constructors nested around the UnionAll type for this var
8086 // when this variable's integer value is compared to that of another,
@@ -2196,12 +2202,23 @@ static jl_value_t *bound_var_below(jl_tvar_t *tv, jl_varbinding_t *bb, jl_stenv_
21962202 if (jl_is_long (bb -> lb )) {
21972203 size_t blb = jl_unbox_long (bb -> lb );
21982204 if (blb < bb -> offset || blb < 0 )
2205+ if (jl_unbox_long (bb -> lb ) < bb -> offset || jl_unbox_long (bb -> lb ) < 0 )
21992206 return jl_bottom_type ;
22002207 // Here we always return the shorter `Vararg`'s length.
22012208 if (bb -> offset <= 0 )
22022209 return bb -> lb ;
22032210 return jl_box_long (jl_unbox_long (bb -> lb ) - bb -> offset );
22042211 }
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.
2215+ 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.
2221+ return NULL ;
22052222 return (jl_value_t * )tv ;
22062223}
22072224
@@ -2453,6 +2470,13 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
24532470 }
24542471 }
24552472
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 )
2475+ 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 ;
2479+
24562480 // TODO: this can prevent us from matching typevar identities later
24572481 if (!varval && (vb -> lb != vb -> var -> lb || vb -> ub != vb -> var -> ub ))
24582482 newvar = jl_new_typevar (vb -> var -> name , vb -> lb , vb -> ub );
@@ -2645,7 +2669,7 @@ static jl_value_t *intersect_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_
26452669 e -> vars -> limited = 1 ;
26462670 }
26472671 else if (res != jl_bottom_type ) {
2648- if (vb .concrete || vb .occurs_inv > 1 || u -> var -> lb != jl_bottom_type || (vb .occurs_inv && vb .occurs_cov )) {
2672+ if (vb .concrete || vb .occurs_inv > 1 || vb . intvalued > 1 || u -> var -> lb != jl_bottom_type || (vb .occurs_inv && vb .occurs_cov )) {
26492673 restore_env (e , NULL , & se );
26502674 vb .occurs_cov = vb .occurs_inv = 0 ;
26512675 vb .constraintkind = vb .concrete ? 1 : 2 ;
@@ -2702,7 +2726,7 @@ static jl_value_t *intersect_varargs(jl_vararg_t *vmx, jl_vararg_t *vmy, size_t
27022726 if (xp2 && jl_is_typevar (xp2 )) {
27032727 xb = lookup (e , (jl_tvar_t * )xp2 );
27042728 if (xb ) {
2705- xb -> intvalued = 1 ;
2729+ if ( xb -> intvalued == 0 ) xb -> intvalued = 1 ;
27062730 xb -> offset = offset ;
27072731 }
27082732 if (!yp2 )
@@ -2711,7 +2735,7 @@ static jl_value_t *intersect_varargs(jl_vararg_t *vmx, jl_vararg_t *vmy, size_t
27112735 if (yp2 && jl_is_typevar (yp2 )) {
27122736 yb = lookup (e , (jl_tvar_t * )yp2 );
27132737 if (yb ) {
2714- yb -> intvalued = 1 ;
2738+ if ( yb -> intvalued == 0 ) yb -> intvalued = 1 ;
27152739 yb -> offset = - offset ;
27162740 }
27172741 if (!xp2 )
0 commit comments