@@ -204,7 +204,9 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
204
204
if seen ≠ napplicable
205
205
# there is unanalyzed candidate, widen type and effects to the top
206
206
rettype = Any
207
- all_effects = Effects ()
207
+ # there may be unanalyzed effects within unseen dispatch candidate,
208
+ # but we can still ignore nonoverlayed effect here since we already accounted for it
209
+ all_effects = merge_effects (all_effects, EFFECTS_UNKNOWN)
208
210
elseif isa (matches, MethodMatches) ? (! matches. fullmatch || any_ambig (matches)) :
209
211
(! all (matches. fullmatches) || any_ambig (matches))
210
212
# Account for the fact that we may encounter a MethodError with a non-covered or ambiguous signature.
@@ -1304,21 +1306,32 @@ function ssa_def_slot(@nospecialize(arg), sv::InferenceState)
1304
1306
return arg
1305
1307
end
1306
1308
1309
+ struct AbstractIterationResult
1310
+ cti:: Vector{Any}
1311
+ info:: MaybeAbstractIterationInfo
1312
+ ai_effects:: Effects
1313
+ end
1314
+ AbstractIterationResult (cti:: Vector{Any} , info:: MaybeAbstractIterationInfo ) =
1315
+ AbstractIterationResult (cti, info, EFFECTS_TOTAL)
1316
+
1307
1317
# `typ` is the inferred type for expression `arg`.
1308
1318
# if the expression constructs a container (e.g. `svec(x,y,z)`),
1309
1319
# refine its type to an array of element types.
1310
1320
# Union of Tuples of the same length is converted to Tuple of Unions.
1311
1321
# returns an array of types
1312
1322
function precise_container_type (interp:: AbstractInterpreter , @nospecialize (itft), @nospecialize (typ),
1313
1323
sv:: Union{InferenceState, IRCode} )
1314
- if isa (typ, PartialStruct) && typ. typ. name === Tuple. name
1315
- return typ. fields, nothing
1324
+ if isa (typ, PartialStruct)
1325
+ widet = typ. typ
1326
+ if isa (widet, DataType) && widet. name === Tuple. name
1327
+ return AbstractIterationResult (typ. fields, nothing )
1328
+ end
1316
1329
end
1317
1330
1318
1331
if isa (typ, Const)
1319
1332
val = typ. val
1320
1333
if isa (val, SimpleVector) || isa (val, Tuple)
1321
- return Any[ Const (val[i]) for i in 1 : length (val) ], nothing # avoid making a tuple Generator here!
1334
+ return AbstractIterationResult ( Any[ Const (val[i]) for i in 1 : length (val) ], nothing ) # avoid making a tuple Generator here!
1322
1335
end
1323
1336
end
1324
1337
@@ -1333,12 +1346,12 @@ function precise_container_type(interp::AbstractInterpreter, @nospecialize(itft)
1333
1346
if isa (tti, Union)
1334
1347
utis = uniontypes (tti)
1335
1348
if any (@nospecialize (t) -> ! isa (t, DataType) || ! (t <: Tuple ) || ! isknownlength (t), utis)
1336
- return Any[Vararg{Any}], nothing
1349
+ return AbstractIterationResult ( Any[Vararg{Any}], nothing , EFFECTS_UNKNOWN′)
1337
1350
end
1338
1351
ltp = length ((utis[1 ]:: DataType ). parameters)
1339
1352
for t in utis
1340
1353
if length ((t:: DataType ). parameters) != ltp
1341
- return Any[Vararg{Any}], nothing
1354
+ return AbstractIterationResult ( Any[Vararg{Any}], nothing )
1342
1355
end
1343
1356
end
1344
1357
result = Any[ Union{} for _ in 1 : ltp ]
@@ -1349,12 +1362,12 @@ function precise_container_type(interp::AbstractInterpreter, @nospecialize(itft)
1349
1362
result[j] = tmerge (result[j], rewrap_unionall (tps[j], tti0))
1350
1363
end
1351
1364
end
1352
- return result, nothing
1365
+ return AbstractIterationResult ( result, nothing )
1353
1366
elseif tti0 <: Tuple
1354
1367
if isa (tti0, DataType)
1355
- return Any[ p for p in tti0. parameters ], nothing
1368
+ return AbstractIterationResult ( Any[ p for p in tti0. parameters ], nothing )
1356
1369
elseif ! isa (tti, DataType)
1357
- return Any[Vararg{Any}], nothing
1370
+ return AbstractIterationResult ( Any[Vararg{Any}], nothing )
1358
1371
else
1359
1372
len = length (tti. parameters)
1360
1373
last = tti. parameters[len]
@@ -1363,12 +1376,14 @@ function precise_container_type(interp::AbstractInterpreter, @nospecialize(itft)
1363
1376
if va
1364
1377
elts[len] = Vararg{elts[len]}
1365
1378
end
1366
- return elts, nothing
1379
+ return AbstractIterationResult ( elts, nothing )
1367
1380
end
1368
- elseif tti0 === SimpleVector || tti0 === Any
1369
- return Any[Vararg{Any}], nothing
1381
+ elseif tti0 === SimpleVector
1382
+ return AbstractIterationResult (Any[Vararg{Any}], nothing )
1383
+ elseif tti0 === Any
1384
+ return AbstractIterationResult (Any[Vararg{Any}], nothing , EFFECTS_UNKNOWN′)
1370
1385
elseif tti0 <: Array
1371
- return Any[Vararg{eltype (tti0)}], nothing
1386
+ return AbstractIterationResult ( Any[Vararg{eltype (tti0)}], nothing )
1372
1387
else
1373
1388
return abstract_iteration (interp, itft, typ, sv)
1374
1389
end
@@ -1379,7 +1394,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
1379
1394
if isa (itft, Const)
1380
1395
iteratef = itft. val
1381
1396
else
1382
- return Any[Vararg{Any}], nothing
1397
+ return AbstractIterationResult ( Any[Vararg{Any}], nothing , EFFECTS_UNKNOWN′)
1383
1398
end
1384
1399
@assert ! isvarargtype (itertype)
1385
1400
call = abstract_call_known (interp, iteratef, ArgInfo (nothing , Any[itft, itertype]), StmtInfo (true ), sv)
@@ -1389,7 +1404,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
1389
1404
# WARNING: Changes to the iteration protocol must be reflected here,
1390
1405
# this is not just an optimization.
1391
1406
# TODO : this doesn't realize that Array, SimpleVector, Tuple, and NamedTuple do not use the iterate protocol
1392
- stateordonet === Bottom && return Any[Bottom], AbstractIterationInfo (CallMeta[CallMeta (Bottom, call. effects, info)])
1407
+ stateordonet === Bottom && return AbstractIterationResult ( Any[Bottom], AbstractIterationInfo (CallMeta[CallMeta (Bottom, call. effects, info)], true ) )
1393
1408
valtype = statetype = Bottom
1394
1409
ret = Any[]
1395
1410
calls = CallMeta[call]
@@ -1399,7 +1414,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
1399
1414
# length iterators, or interesting prefix
1400
1415
while true
1401
1416
if stateordonet_widened === Nothing
1402
- return ret, AbstractIterationInfo (calls)
1417
+ return AbstractIterationResult ( ret, AbstractIterationInfo (calls, true ) )
1403
1418
end
1404
1419
if Nothing <: stateordonet_widened || length (ret) >= InferenceParams (interp). MAX_TUPLE_SPLAT
1405
1420
break
@@ -1411,7 +1426,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
1411
1426
# If there's no new information in this statetype, don't bother continuing,
1412
1427
# the iterator won't be finite.
1413
1428
if ⊑ (typeinf_lattice (interp), nstatetype, statetype)
1414
- return Any[Bottom], nothing
1429
+ return AbstractIterationResult ( Any[Bottom], AbstractIterationInfo (calls, false ), EFFECTS_THROWS)
1415
1430
end
1416
1431
valtype = getfield_tfunc (typeinf_lattice (interp), stateordonet, Const (1 ))
1417
1432
push! (ret, valtype)
@@ -1441,7 +1456,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
1441
1456
# ... but cannot terminate
1442
1457
if ! may_have_terminated
1443
1458
# ... and cannot have terminated prior to this loop
1444
- return Any[Bottom], nothing
1459
+ return AbstractIterationResult ( Any[Bottom], AbstractIterationInfo (calls, false ), EFFECTS_UNKNOWN′)
1445
1460
else
1446
1461
# iterator may have terminated prior to this loop, but not during it
1447
1462
valtype = Bottom
@@ -1451,13 +1466,15 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
1451
1466
end
1452
1467
valtype = tmerge (valtype, nounion. parameters[1 ])
1453
1468
statetype = tmerge (statetype, nounion. parameters[2 ])
1454
- stateordonet = abstract_call_known (interp, iteratef, ArgInfo (nothing , Any[Const (iteratef), itertype, statetype]), StmtInfo (true ), sv). rt
1469
+ call = abstract_call_known (interp, iteratef, ArgInfo (nothing , Any[Const (iteratef), itertype, statetype]), StmtInfo (true ), sv)
1470
+ push! (calls, call)
1471
+ stateordonet = call. rt
1455
1472
stateordonet_widened = widenconst (stateordonet)
1456
1473
end
1457
1474
if valtype != = Union{}
1458
1475
push! (ret, Vararg{valtype})
1459
1476
end
1460
- return ret, nothing
1477
+ return AbstractIterationResult ( ret, AbstractIterationInfo (calls, false ))
1461
1478
end
1462
1479
1463
1480
# do apply(af, fargs...), where af is a function value
@@ -1488,13 +1505,9 @@ function abstract_apply(interp::AbstractInterpreter, argtypes::Vector{Any}, si::
1488
1505
infos′ = Vector{MaybeAbstractIterationInfo}[]
1489
1506
for ti in (splitunions ? uniontypes (aargtypes[i]) : Any[aargtypes[i]])
1490
1507
if ! isvarargtype (ti)
1491
- cti_info = precise_container_type (interp, itft, ti, sv)
1492
- cti = cti_info[1 ]:: Vector{Any}
1493
- info = cti_info[2 ]:: MaybeAbstractIterationInfo
1508
+ (;cti, info, ai_effects) = precise_container_type (interp, itft, ti, sv)
1494
1509
else
1495
- cti_info = precise_container_type (interp, itft, unwrapva (ti), sv)
1496
- cti = cti_info[1 ]:: Vector{Any}
1497
- info = cti_info[2 ]:: MaybeAbstractIterationInfo
1510
+ (;cti, info, ai_effects) = precise_container_type (interp, itft, unwrapva (ti), sv)
1498
1511
# We can't represent a repeating sequence of the same types,
1499
1512
# so tmerge everything together to get one type that represents
1500
1513
# everything.
@@ -1507,6 +1520,12 @@ function abstract_apply(interp::AbstractInterpreter, argtypes::Vector{Any}, si::
1507
1520
end
1508
1521
cti = Any[Vararg{argt}]
1509
1522
end
1523
+ effects = merge_effects (effects, ai_effects)
1524
+ if info != = nothing
1525
+ for call in info. each
1526
+ effects = merge_effects (effects, call. effects)
1527
+ end
1528
+ end
1510
1529
if any (@nospecialize (t) -> t === Bottom, cti)
1511
1530
continue
1512
1531
end
0 commit comments