@@ -1321,6 +1321,8 @@ Determine whether two methods `m1` and `m2` may be ambiguous for some call
1321
1321
signature. This test is performed in the context of other methods of the same
1322
1322
function; in isolation, `m1` and `m2` might be ambiguous, but if a third method
1323
1323
resolving the ambiguity has been defined, this returns `false`.
1324
+ Alternatively, in isolation `m1` and `m2` might be ordered, but if a third
1325
+ method cannot be sorted with them, they may cause an ambiguity together.
1324
1326
1325
1327
For parametric types, the `ambiguous_bottom` keyword argument controls whether
1326
1328
`Union{}` counts as an ambiguous intersection of type parameters – when `true`,
@@ -1347,27 +1349,82 @@ false
1347
1349
```
1348
1350
"""
1349
1351
function isambiguous (m1:: Method , m2:: Method ; ambiguous_bottom:: Bool = false )
1350
- # TODO : eagerly returning `morespecific` is wrong, and fails to consider
1351
- # the possibility of an ambiguity caused by a third method:
1352
- # see the precise algorithm in ml_matches for a more correct computation
1353
- if m1 === m2 || morespecific (m1. sig, m2. sig) || morespecific (m2. sig, m1. sig)
1354
- return false
1355
- end
1352
+ m1 === m2 && return false
1356
1353
ti = typeintersect (m1. sig, m2. sig)
1357
- (ti <: m1.sig && ti <: m2.sig ) || return false # XXX : completely wrong, obviously
1358
1354
ti === Bottom && return false
1359
- if ! ambiguous_bottom
1360
- has_bottom_parameter (ti) && return false
1361
- end
1362
- matches = _methods_by_ftype (ti, - 1 , typemax (UInt))
1363
- for match in matches
1364
- m = match. method
1365
- m === m1 && continue
1366
- m === m2 && continue
1367
- if ti <: m.sig && morespecific (m. sig, m1. sig) && morespecific (m. sig, m2. sig)
1355
+ function inner (ti)
1356
+ ti === Bottom && return false
1357
+ if ! ambiguous_bottom
1358
+ has_bottom_parameter (ti) && return false
1359
+ end
1360
+ min = UInt[typemin (UInt)]
1361
+ max = UInt[typemax (UInt)]
1362
+ has_ambig = Int32[0 ]
1363
+ ms = _methods_by_ftype (ti, - 1 , typemax (UInt), true , min, max, has_ambig)
1364
+ has_ambig[] == 0 && return false
1365
+ if ! ambiguous_bottom
1366
+ filter! (ms) do m
1367
+ return ! has_bottom_parameter (m. spec_types)
1368
+ end
1369
+ end
1370
+ # if ml-matches reported the existence of an ambiguity over their
1371
+ # intersection, see if both m1 and m2 may be involved in it
1372
+ have_m1 = have_m2 = false
1373
+ for match in ms
1374
+ m = match. method
1375
+ m === m1 && (have_m1 = true )
1376
+ m === m2 && (have_m2 = true )
1377
+ end
1378
+ if ! have_m1 || ! have_m2
1379
+ # ml-matches did not need both methods to expose the reported ambiguity
1368
1380
return false
1369
1381
end
1382
+ if ! ambiguous_bottom
1383
+ # since we're intentionally ignoring certain ambiguities (via the
1384
+ # filter call above), see if we can now declare the intersection fully
1385
+ # covered even though it is partially ambiguous over Union{} as a type
1386
+ # parameter somewhere
1387
+ minmax = nothing
1388
+ for match in ms
1389
+ m = match. method
1390
+ match. fully_covers || continue
1391
+ if minmax === nothing || morespecific (m. sig, minmax. sig)
1392
+ minmax = m
1393
+ end
1394
+ end
1395
+ if minmax === nothing
1396
+ return true
1397
+ end
1398
+ for match in ms
1399
+ m = match. method
1400
+ m === minmax && continue
1401
+ if match. fully_covers
1402
+ if ! morespecific (minmax. sig, m. sig)
1403
+ return true
1404
+ end
1405
+ else
1406
+ if morespecific (m. sig, minmax. sig)
1407
+ return true
1408
+ end
1409
+ end
1410
+ end
1411
+ return false
1412
+ end
1413
+ return true
1414
+ end
1415
+ if ! (ti <: m1.sig && ti <: m2.sig )
1416
+ # When type-intersection fails, it's often also not commutative. Thus
1417
+ # checking the reverse may allow detecting ambiguity solutions
1418
+ # correctly in more cases (and faster).
1419
+ ti2 = typeintersect (m2. sig, m1. sig)
1420
+ if ti2 <: m1.sig && ti2 <: m2.sig
1421
+ ti = ti2
1422
+ elseif ti != ti2
1423
+ inner (ti2) || return false
1424
+ end
1370
1425
end
1426
+ inner (ti) || return false
1427
+ # otherwise type-intersection reported an ambiguity we couldn't solve
1371
1428
return true
1372
1429
end
1373
1430
0 commit comments