@@ -1499,11 +1499,11 @@ jl_unionall_t *jl_rename_unionall(jl_unionall_t *u)
14991499 return (jl_unionall_t * )t ;
15001500}
15011501
1502- jl_value_t * jl_substitute_var_nothrow (jl_value_t * t , jl_tvar_t * var , jl_value_t * val )
1502+ jl_value_t * jl_substitute_var_nothrow (jl_value_t * t , jl_tvar_t * var , jl_value_t * val , int nothrow )
15031503{
15041504 if (val == (jl_value_t * )var )
15051505 return t ;
1506- int nothrow = jl_is_typevar (val ) ? 0 : 1 ;
1506+ nothrow = jl_is_typevar (val ) ? 0 : nothrow ;
15071507 jl_typeenv_t env = { var , val , NULL };
15081508 return inst_type_w_ (t , & env , NULL , 1 , nothrow );
15091509}
@@ -1725,7 +1725,7 @@ void jl_precompute_memoized_dt(jl_datatype_t *dt, int cacheable)
17251725 dt -> hash = typekey_hash (dt -> name , jl_svec_data (dt -> parameters ), l , cacheable );
17261726}
17271727
1728- static void check_datatype_parameters (jl_typename_t * tn , jl_value_t * * params , size_t np )
1728+ static int check_datatype_parameters (jl_typename_t * tn , jl_value_t * * params , size_t np , int nothrow )
17291729{
17301730 jl_value_t * wrapper = tn -> wrapper ;
17311731 jl_value_t * * bounds ;
@@ -1743,6 +1743,10 @@ static void check_datatype_parameters(jl_typename_t *tn, jl_value_t **params, si
17431743 assert (jl_is_unionall (wrapper ));
17441744 jl_tvar_t * tv = ((jl_unionall_t * )wrapper )-> var ;
17451745 if (!within_typevar (params [i ], bounds [2 * i ], bounds [2 * i + 1 ])) {
1746+ if (nothrow ) {
1747+ JL_GC_POP ();
1748+ return 1 ;
1749+ }
17461750 if (tv -> lb != bounds [2 * i ] || tv -> ub != bounds [2 * i + 1 ])
17471751 // pass a new version of `tv` containing the instantiated bounds
17481752 tv = jl_new_typevar (tv -> name , bounds [2 * i ], bounds [2 * i + 1 ]);
@@ -1752,12 +1756,26 @@ static void check_datatype_parameters(jl_typename_t *tn, jl_value_t **params, si
17521756 int j ;
17531757 for (j = 2 * i + 2 ; j < 2 * np ; j ++ ) {
17541758 jl_value_t * bj = bounds [j ];
1755- if (bj != (jl_value_t * )jl_any_type && bj != jl_bottom_type )
1756- bounds [j ] = jl_substitute_var (bj , tv , params [i ]);
1759+ if (bj != (jl_value_t * )jl_any_type && bj != jl_bottom_type ) {
1760+ int isub = j & 1 ;
1761+ // use different nothrow level for lb and ub substitution.
1762+ // TODO: This assuming the top instantiation could only start with
1763+ // `nothrow == 2` or `nothrow == 0`. If `nothrow` is initially set to 1
1764+ // then we might miss some inner error, perhaps the normal path should
1765+ // also follow this rule?
1766+ jl_value_t * nb = jl_substitute_var_nothrow (bj , tv , params [i ], nothrow ? (isub ? 2 : 1 ) : 0 );
1767+ if (nb == NULL ) {
1768+ assert (nothrow );
1769+ JL_GC_POP ();
1770+ return 1 ;
1771+ }
1772+ bounds [j ] = nb ;
1773+ }
17571774 }
17581775 wrapper = ((jl_unionall_t * )wrapper )-> body ;
17591776 }
17601777 JL_GC_POP ();
1778+ return 0 ;
17611779}
17621780
17631781static jl_value_t * extract_wrapper (jl_value_t * t JL_PROPAGATES_ROOT ) JL_NOTSAFEPOINT JL_GLOBALLY_ROOTED
@@ -2004,13 +2022,8 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value
20042022 // for whether this is even valid
20052023 if (check && !istuple ) {
20062024 assert (ntp > 0 );
2007- JL_TRY {
2008- check_datatype_parameters (tn , iparams , ntp );
2009- }
2010- JL_CATCH {
2011- if (!nothrow ) jl_rethrow ();
2025+ if (check_datatype_parameters (tn , iparams , ntp , nothrow ))
20122026 return NULL ;
2013- }
20142027 }
20152028 else if (ntp == 0 && jl_emptytuple_type != NULL ) {
20162029 // empty tuple type case
@@ -2401,7 +2414,8 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_
24012414 jl_value_t * elt = jl_svecref (tp , i );
24022415 jl_value_t * pi = inst_type_w_ (elt , env , stack , check , nothrow );
24032416 if (pi == NULL ) {
2404- if (i == ntp - 1 && jl_is_vararg (elt )) {
2417+ assert (nothrow );
2418+ if (nothrow == 1 || (i == ntp - 1 && jl_is_vararg (elt ))) {
24052419 t = NULL ;
24062420 break ;
24072421 }
@@ -2420,6 +2434,10 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_
24202434 return t ;
24212435}
24222436
2437+ // `nothrow` means that when type checking fails, the type instantiation should
2438+ // return `NULL` instead of immediately throwing an error. If `nothrow` == 2 then
2439+ // we further assume that the imprecise instantiation for non invariant parameters
2440+ // is acceptable, and inner error (`NULL`) would be ignored.
24232441static jl_value_t * inst_type_w_ (jl_value_t * t , jl_typeenv_t * env , jl_typestack_t * stack , int check , int nothrow )
24242442{
24252443 size_t i ;
@@ -2440,11 +2458,10 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t
24402458 jl_value_t * var = NULL ;
24412459 jl_value_t * newbody = NULL ;
24422460 JL_GC_PUSH3 (& lb , & var , & newbody );
2443- JL_TRY {
2444- lb = inst_type_w_ (ua -> var -> lb , env , stack , check , 0 );
2445- }
2446- JL_CATCH {
2447- if (!nothrow ) jl_rethrow ();
2461+ // set nothrow <= 1 to ensure lb's accuracy.
2462+ lb = inst_type_w_ (ua -> var -> lb , env , stack , check , nothrow ? 1 : 0 );
2463+ if (lb == NULL ) {
2464+ assert (nothrow );
24482465 t = NULL ;
24492466 }
24502467 if (t != NULL ) {
@@ -2468,11 +2485,9 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t
24682485 if (newbody == NULL ) {
24692486 t = NULL ;
24702487 }
2471- else if (newbody == (jl_value_t * )jl_emptytuple_type ) {
2472- // NTuple{0} => Tuple{} can make a typevar disappear
2473- t = (jl_value_t * )jl_emptytuple_type ;
2474- }
2475- else if (nothrow && !jl_has_typevar (newbody , (jl_tvar_t * )var )) {
2488+ else if (!jl_has_typevar (newbody , (jl_tvar_t * )var )) {
2489+ // inner instantiation might make a typevar disappear, e.g.
2490+ // NTuple{0,T} => Tuple{}
24762491 t = newbody ;
24772492 }
24782493 else if (newbody != ua -> body || var != (jl_value_t * )ua -> var ) {
@@ -2489,16 +2504,21 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t
24892504 jl_value_t * b = NULL ;
24902505 JL_GC_PUSH2 (& a , & b );
24912506 b = inst_type_w_ (u -> b , env , stack , check , nothrow );
2507+ if (nothrow ) {
2508+ // ensure jl_type_union nothrow.
2509+ if (a && !(jl_is_typevar (a ) || jl_is_type (a )))
2510+ a = NULL ;
2511+ if (b && !(jl_is_typevar (b ) || jl_is_type (b )))
2512+ b = NULL ;
2513+ }
24922514 if (a != u -> a || b != u -> b ) {
24932515 if (!check ) {
24942516 // fast path for `jl_rename_unionall`.
24952517 t = jl_new_struct (jl_uniontype_type , a , b );
24962518 }
2497- else if (nothrow && a == NULL ) {
2498- t = b ;
2499- }
2500- else if (nothrow && b == NULL ) {
2501- t = a ;
2519+ else if (a == NULL || b == NULL ) {
2520+ assert (nothrow );
2521+ t = nothrow == 1 ? NULL : a == NULL ? b : a ;
25022522 }
25032523 else {
25042524 assert (a != NULL && b != NULL );
@@ -2516,15 +2536,21 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t
25162536 JL_GC_PUSH2 (& T , & N );
25172537 if (v -> T ) {
25182538 T = inst_type_w_ (v -> T , env , stack , check , nothrow );
2519- if (T == NULL )
2520- T = jl_bottom_type ;
2521- if (v -> N ) // This branch should never throw.
2522- N = inst_type_w_ (v -> N , env , stack , check , 0 );
2539+ if (T == NULL ) {
2540+ if (nothrow == 2 )
2541+ T = jl_bottom_type ;
2542+ else
2543+ t = NULL ;
2544+ }
2545+ if (t && v -> N ) {
2546+ // set nothrow <= 1 to ensure invariant parameter's accuracy.
2547+ N = inst_type_w_ (v -> N , env , stack , check , nothrow ? 1 : 0 );
2548+ if (N == NULL )
2549+ t = NULL ;
2550+ }
25232551 }
2524- if (T != v -> T || N != v -> N ) {
2525- // `Vararg` is special, we'd better handle inner error at Tuple level.
2552+ if (t && (T != v -> T || N != v -> N ))
25262553 t = (jl_value_t * )jl_wrap_vararg (T , N , check , nothrow );
2527- }
25282554 JL_GC_POP ();
25292555 return t ;
25302556 }
@@ -2543,16 +2569,15 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t
25432569 int bound = 0 ;
25442570 for (i = 0 ; i < ntp ; i ++ ) {
25452571 jl_value_t * elt = jl_svecref (tp , i );
2546- JL_TRY {
2547- jl_value_t * pi = inst_type_w_ (elt , env , stack , check , 0 );
2548- iparams [i ] = pi ;
2549- bound |= (pi != elt );
2550- }
2551- JL_CATCH {
2552- if (!nothrow ) jl_rethrow ();
2572+ // set nothrow <= 1 to ensure invariant parameter's accuracy.
2573+ jl_value_t * pi = inst_type_w_ (elt , env , stack , check , nothrow ? 1 : 0 );
2574+ if (pi == NULL ) {
2575+ assert (nothrow );
25532576 t = NULL ;
2577+ break ;
25542578 }
2555- if (t == NULL ) break ;
2579+ iparams [i ] = pi ;
2580+ bound |= (pi != elt );
25562581 }
25572582 // if t's parameters are not bound in the environment, return it uncopied (#9378)
25582583 if (t != NULL && bound )
0 commit comments