@@ -1499,11 +1499,11 @@ jl_unionall_t *jl_rename_unionall(jl_unionall_t *u)
1499
1499
return (jl_unionall_t * )t ;
1500
1500
}
1501
1501
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 )
1503
1503
{
1504
1504
if (val == (jl_value_t * )var )
1505
1505
return t ;
1506
- int nothrow = jl_is_typevar (val ) ? 0 : 1 ;
1506
+ nothrow = jl_is_typevar (val ) ? 0 : nothrow ;
1507
1507
jl_typeenv_t env = { var , val , NULL };
1508
1508
return inst_type_w_ (t , & env , NULL , 1 , nothrow );
1509
1509
}
@@ -1725,7 +1725,7 @@ void jl_precompute_memoized_dt(jl_datatype_t *dt, int cacheable)
1725
1725
dt -> hash = typekey_hash (dt -> name , jl_svec_data (dt -> parameters ), l , cacheable );
1726
1726
}
1727
1727
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 )
1729
1729
{
1730
1730
jl_value_t * wrapper = tn -> wrapper ;
1731
1731
jl_value_t * * bounds ;
@@ -1743,6 +1743,10 @@ static void check_datatype_parameters(jl_typename_t *tn, jl_value_t **params, si
1743
1743
assert (jl_is_unionall (wrapper ));
1744
1744
jl_tvar_t * tv = ((jl_unionall_t * )wrapper )-> var ;
1745
1745
if (!within_typevar (params [i ], bounds [2 * i ], bounds [2 * i + 1 ])) {
1746
+ if (nothrow ) {
1747
+ JL_GC_POP ();
1748
+ return 1 ;
1749
+ }
1746
1750
if (tv -> lb != bounds [2 * i ] || tv -> ub != bounds [2 * i + 1 ])
1747
1751
// pass a new version of `tv` containing the instantiated bounds
1748
1752
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
1752
1756
int j ;
1753
1757
for (j = 2 * i + 2 ; j < 2 * np ; j ++ ) {
1754
1758
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
+ }
1757
1774
}
1758
1775
wrapper = ((jl_unionall_t * )wrapper )-> body ;
1759
1776
}
1760
1777
JL_GC_POP ();
1778
+ return 0 ;
1761
1779
}
1762
1780
1763
1781
static 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
2004
2022
// for whether this is even valid
2005
2023
if (check && !istuple ) {
2006
2024
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 ))
2012
2026
return NULL ;
2013
- }
2014
2027
}
2015
2028
else if (ntp == 0 && jl_emptytuple_type != NULL ) {
2016
2029
// 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_
2401
2414
jl_value_t * elt = jl_svecref (tp , i );
2402
2415
jl_value_t * pi = inst_type_w_ (elt , env , stack , check , nothrow );
2403
2416
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 ))) {
2405
2419
t = NULL ;
2406
2420
break ;
2407
2421
}
@@ -2420,6 +2434,10 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_
2420
2434
return t ;
2421
2435
}
2422
2436
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.
2423
2441
static jl_value_t * inst_type_w_ (jl_value_t * t , jl_typeenv_t * env , jl_typestack_t * stack , int check , int nothrow )
2424
2442
{
2425
2443
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
2440
2458
jl_value_t * var = NULL ;
2441
2459
jl_value_t * newbody = NULL ;
2442
2460
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 );
2448
2465
t = NULL ;
2449
2466
}
2450
2467
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
2468
2485
if (newbody == NULL ) {
2469
2486
t = NULL ;
2470
2487
}
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{}
2476
2491
t = newbody ;
2477
2492
}
2478
2493
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
2489
2504
jl_value_t * b = NULL ;
2490
2505
JL_GC_PUSH2 (& a , & b );
2491
2506
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
+ }
2492
2514
if (a != u -> a || b != u -> b ) {
2493
2515
if (!check ) {
2494
2516
// fast path for `jl_rename_unionall`.
2495
2517
t = jl_new_struct (jl_uniontype_type , a , b );
2496
2518
}
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 ;
2502
2522
}
2503
2523
else {
2504
2524
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
2516
2536
JL_GC_PUSH2 (& T , & N );
2517
2537
if (v -> T ) {
2518
2538
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
+ }
2523
2551
}
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 ))
2526
2553
t = (jl_value_t * )jl_wrap_vararg (T , N , check , nothrow );
2527
- }
2528
2554
JL_GC_POP ();
2529
2555
return t ;
2530
2556
}
@@ -2543,16 +2569,15 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t
2543
2569
int bound = 0 ;
2544
2570
for (i = 0 ; i < ntp ; i ++ ) {
2545
2571
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 );
2553
2576
t = NULL ;
2577
+ break ;
2554
2578
}
2555
- if (t == NULL ) break ;
2579
+ iparams [i ] = pi ;
2580
+ bound |= (pi != elt );
2556
2581
}
2557
2582
// if t's parameters are not bound in the environment, return it uncopied (#9378)
2558
2583
if (t != NULL && bound )
0 commit comments