@@ -1468,11 +1468,11 @@ jl_unionall_t *jl_rename_unionall(jl_unionall_t *u)
14681468 return (jl_unionall_t * )t ;
14691469}
14701470
1471- jl_value_t * jl_substitute_var_nothrow (jl_value_t * t , jl_tvar_t * var , jl_value_t * val )
1471+ jl_value_t * jl_substitute_var_nothrow (jl_value_t * t , jl_tvar_t * var , jl_value_t * val , int nothrow )
14721472{
14731473 if (val == (jl_value_t * )var )
14741474 return t ;
1475- int nothrow = jl_is_typevar (val ) ? 0 : 1 ;
1475+ nothrow = jl_is_typevar (val ) ? 0 : nothrow ;
14761476 jl_typeenv_t env = { var , val , NULL };
14771477 return inst_type_w_ (t , & env , NULL , 1 , nothrow );
14781478}
@@ -1694,7 +1694,7 @@ void jl_precompute_memoized_dt(jl_datatype_t *dt, int cacheable)
16941694 dt -> hash = typekey_hash (dt -> name , jl_svec_data (dt -> parameters ), l , cacheable );
16951695}
16961696
1697- static void check_datatype_parameters (jl_typename_t * tn , jl_value_t * * params , size_t np )
1697+ static int check_datatype_parameters (jl_typename_t * tn , jl_value_t * * params , size_t np , int nothrow )
16981698{
16991699 jl_value_t * wrapper = tn -> wrapper ;
17001700 jl_value_t * * bounds ;
@@ -1712,6 +1712,10 @@ static void check_datatype_parameters(jl_typename_t *tn, jl_value_t **params, si
17121712 assert (jl_is_unionall (wrapper ));
17131713 jl_tvar_t * tv = ((jl_unionall_t * )wrapper )-> var ;
17141714 if (!within_typevar (params [i ], bounds [2 * i ], bounds [2 * i + 1 ])) {
1715+ if (nothrow ) {
1716+ JL_GC_POP ();
1717+ return 1 ;
1718+ }
17151719 if (tv -> lb != bounds [2 * i ] || tv -> ub != bounds [2 * i + 1 ])
17161720 // pass a new version of `tv` containing the instantiated bounds
17171721 tv = jl_new_typevar (tv -> name , bounds [2 * i ], bounds [2 * i + 1 ]);
@@ -1721,12 +1725,26 @@ static void check_datatype_parameters(jl_typename_t *tn, jl_value_t **params, si
17211725 int j ;
17221726 for (j = 2 * i + 2 ; j < 2 * np ; j ++ ) {
17231727 jl_value_t * bj = bounds [j ];
1724- if (bj != (jl_value_t * )jl_any_type && bj != jl_bottom_type )
1725- bounds [j ] = jl_substitute_var (bj , tv , params [i ]);
1728+ if (bj != (jl_value_t * )jl_any_type && bj != jl_bottom_type ) {
1729+ int isub = j & 1 ;
1730+ // use different nothrow level for lb and ub substitution.
1731+ // TODO: This assuming the top instantiation could only start with
1732+ // `nothrow == 2` or `nothrow == 0`. If `nothrow` is initially set to 1
1733+ // then we might miss some inner error, perhaps the normal path should
1734+ // also follow this rule?
1735+ jl_value_t * nb = jl_substitute_var_nothrow (bj , tv , params [i ], nothrow ? (isub ? 2 : 1 ) : 0 );
1736+ if (nb == NULL ) {
1737+ assert (nothrow );
1738+ JL_GC_POP ();
1739+ return 1 ;
1740+ }
1741+ bounds [j ] = nb ;
1742+ }
17261743 }
17271744 wrapper = ((jl_unionall_t * )wrapper )-> body ;
17281745 }
17291746 JL_GC_POP ();
1747+ return 0 ;
17301748}
17311749
17321750jl_value_t * extract_wrapper (jl_value_t * t JL_PROPAGATES_ROOT ) JL_GLOBALLY_ROOTED
@@ -1943,13 +1961,8 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value
19431961 // for whether this is even valid
19441962 if (check && !istuple ) {
19451963 assert (ntp > 0 );
1946- JL_TRY {
1947- check_datatype_parameters (tn , iparams , ntp );
1948- }
1949- JL_CATCH {
1950- if (!nothrow ) jl_rethrow ();
1964+ if (check_datatype_parameters (tn , iparams , ntp , nothrow ))
19511965 return NULL ;
1952- }
19531966 }
19541967 else if (ntp == 0 && jl_emptytuple_type != NULL ) {
19551968 // empty tuple type case
@@ -2301,7 +2314,8 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_
23012314 jl_value_t * elt = jl_svecref (tp , i );
23022315 jl_value_t * pi = inst_type_w_ (elt , env , stack , check , nothrow );
23032316 if (pi == NULL ) {
2304- if (i == ntp - 1 && jl_is_vararg (elt )) {
2317+ assert (nothrow );
2318+ if (nothrow == 1 || (i == ntp - 1 && jl_is_vararg (elt ))) {
23052319 t = NULL ;
23062320 break ;
23072321 }
@@ -2320,6 +2334,10 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_
23202334 return t ;
23212335}
23222336
2337+ // `nothrow` means that when type checking fails, the type instantiation should
2338+ // return `NULL` instead of immediately throwing an error. If `nothrow` == 2 then
2339+ // we further assume that the imprecise instantiation for non invariant parameters
2340+ // is acceptable, and inner error (`NULL`) would be ignored.
23232341static jl_value_t * inst_type_w_ (jl_value_t * t , jl_typeenv_t * env , jl_typestack_t * stack , int check , int nothrow )
23242342{
23252343 size_t i ;
@@ -2340,11 +2358,10 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t
23402358 jl_value_t * var = NULL ;
23412359 jl_value_t * newbody = NULL ;
23422360 JL_GC_PUSH3 (& lb , & var , & newbody );
2343- JL_TRY {
2344- lb = inst_type_w_ (ua -> var -> lb , env , stack , check , 0 );
2345- }
2346- JL_CATCH {
2347- if (!nothrow ) jl_rethrow ();
2361+ // set nothrow <= 1 to ensure lb's accuracy.
2362+ lb = inst_type_w_ (ua -> var -> lb , env , stack , check , nothrow ? 1 : 0 );
2363+ if (lb == NULL ) {
2364+ assert (nothrow );
23482365 t = NULL ;
23492366 }
23502367 if (t != NULL ) {
@@ -2368,11 +2385,9 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t
23682385 if (newbody == NULL ) {
23692386 t = NULL ;
23702387 }
2371- else if (newbody == (jl_value_t * )jl_emptytuple_type ) {
2372- // NTuple{0} => Tuple{} can make a typevar disappear
2373- t = (jl_value_t * )jl_emptytuple_type ;
2374- }
2375- else if (nothrow && !jl_has_typevar (newbody , (jl_tvar_t * )var )) {
2388+ else if (!jl_has_typevar (newbody , (jl_tvar_t * )var )) {
2389+ // inner instantiation might make a typevar disappear, e.g.
2390+ // NTuple{0,T} => Tuple{}
23762391 t = newbody ;
23772392 }
23782393 else if (newbody != ua -> body || var != (jl_value_t * )ua -> var ) {
@@ -2389,16 +2404,21 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t
23892404 jl_value_t * b = NULL ;
23902405 JL_GC_PUSH2 (& a , & b );
23912406 b = inst_type_w_ (u -> b , env , stack , check , nothrow );
2407+ if (nothrow ) {
2408+ // ensure jl_type_union nothrow.
2409+ if (a && !(jl_is_typevar (a ) || jl_is_type (a )))
2410+ a = NULL ;
2411+ if (b && !(jl_is_typevar (b ) || jl_is_type (b )))
2412+ b = NULL ;
2413+ }
23922414 if (a != u -> a || b != u -> b ) {
23932415 if (!check ) {
23942416 // fast path for `jl_rename_unionall`.
23952417 t = jl_new_struct (jl_uniontype_type , a , b );
23962418 }
2397- else if (nothrow && a == NULL ) {
2398- t = b ;
2399- }
2400- else if (nothrow && b == NULL ) {
2401- t = a ;
2419+ else if (a == NULL || b == NULL ) {
2420+ assert (nothrow );
2421+ t = nothrow == 1 ? NULL : a == NULL ? b : a ;
24022422 }
24032423 else {
24042424 assert (a != NULL && b != NULL );
@@ -2416,15 +2436,21 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t
24162436 JL_GC_PUSH2 (& T , & N );
24172437 if (v -> T ) {
24182438 T = inst_type_w_ (v -> T , env , stack , check , nothrow );
2419- if (T == NULL )
2420- T = jl_bottom_type ;
2421- if (v -> N ) // This branch should never throw.
2422- N = inst_type_w_ (v -> N , env , stack , check , 0 );
2439+ if (T == NULL ) {
2440+ if (nothrow == 2 )
2441+ T = jl_bottom_type ;
2442+ else
2443+ t = NULL ;
2444+ }
2445+ if (t && v -> N ) {
2446+ // set nothrow <= 1 to ensure invariant parameter's accuracy.
2447+ N = inst_type_w_ (v -> N , env , stack , check , nothrow ? 1 : 0 );
2448+ if (N == NULL )
2449+ t = NULL ;
2450+ }
24232451 }
2424- if (T != v -> T || N != v -> N ) {
2425- // `Vararg` is special, we'd better handle inner error at Tuple level.
2452+ if (t && (T != v -> T || N != v -> N ))
24262453 t = (jl_value_t * )jl_wrap_vararg (T , N , check , nothrow );
2427- }
24282454 JL_GC_POP ();
24292455 return t ;
24302456 }
@@ -2443,16 +2469,15 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t
24432469 int bound = 0 ;
24442470 for (i = 0 ; i < ntp ; i ++ ) {
24452471 jl_value_t * elt = jl_svecref (tp , i );
2446- JL_TRY {
2447- jl_value_t * pi = inst_type_w_ (elt , env , stack , check , 0 );
2448- iparams [i ] = pi ;
2449- bound |= (pi != elt );
2450- }
2451- JL_CATCH {
2452- if (!nothrow ) jl_rethrow ();
2472+ // set nothrow <= 1 to ensure invariant parameter's accuracy.
2473+ jl_value_t * pi = inst_type_w_ (elt , env , stack , check , nothrow ? 1 : 0 );
2474+ if (pi == NULL ) {
2475+ assert (nothrow );
24532476 t = NULL ;
2477+ break ;
24542478 }
2455- if (t == NULL ) break ;
2479+ iparams [i ] = pi ;
2480+ bound |= (pi != elt );
24562481 }
24572482 // if t's parameters are not bound in the environment, return it uncopied (#9378)
24582483 if (t != NULL && bound )
0 commit comments