@@ -1363,6 +1363,8 @@ Determine whether two methods `m1` and `m2` may be ambiguous for some call
1363
1363
signature. This test is performed in the context of other methods of the same
1364
1364
function; in isolation, `m1` and `m2` might be ambiguous, but if a third method
1365
1365
resolving the ambiguity has been defined, this returns `false`.
1366
+ Alternatively, in isolation `m1` and `m2` might be ordered, but if a third
1367
+ method cannot be sorted with them, they may cause an ambiguity together.
1366
1368
1367
1369
For parametric types, the `ambiguous_bottom` keyword argument controls whether
1368
1370
`Union{}` counts as an ambiguous intersection of type parameters – when `true`,
@@ -1389,27 +1391,87 @@ false
1389
1391
```
1390
1392
"""
1391
1393
function isambiguous (m1:: Method , m2:: Method ; ambiguous_bottom:: Bool = false )
1392
- # TODO : eagerly returning `morespecific` is wrong, and fails to consider
1393
- # the possibility of an ambiguity caused by a third method:
1394
- # see the precise algorithm in ml_matches for a more correct computation
1395
- if m1 === m2 || morespecific (m1. sig, m2. sig) || morespecific (m2. sig, m1. sig)
1396
- return false
1397
- end
1394
+ m1 === m2 && return false
1398
1395
ti = typeintersect (m1. sig, m2. sig)
1399
- (ti <: m1.sig && ti <: m2.sig ) || return false # XXX : completely wrong, obviously
1400
1396
ti === Bottom && return false
1401
- if ! ambiguous_bottom
1402
- has_bottom_parameter (ti) && return false
1403
- end
1404
- matches = _methods_by_ftype (ti, - 1 , typemax (UInt))
1405
- for match in matches
1406
- m = match. method
1407
- m === m1 && continue
1408
- m === m2 && continue
1409
- if ti <: m.sig && morespecific (m. sig, m1. sig) && morespecific (m. sig, m2. sig)
1397
+ function inner (ti)
1398
+ ti === Bottom && return false
1399
+ if ! ambiguous_bottom
1400
+ has_bottom_parameter (ti) && return false
1401
+ end
1402
+ min = UInt[typemin (UInt)]
1403
+ max = UInt[typemax (UInt)]
1404
+ has_ambig = Int32[0 ]
1405
+ ms = _methods_by_ftype (ti, - 1 , typemax (UInt), true , min, max, has_ambig)
1406
+ has_ambig[] == 0 && return false
1407
+ if ! ambiguous_bottom
1408
+ filter! (ms) do m
1409
+ return ! has_bottom_parameter (m. spec_types)
1410
+ end
1411
+ end
1412
+ # if ml-matches reported the existence of an ambiguity over their
1413
+ # intersection, see if both m1 and m2 may be involved in it
1414
+ have_m1 = have_m2 = false
1415
+ for match in ms
1416
+ m = match. method
1417
+ m === m1 && (have_m1 = true )
1418
+ m === m2 && (have_m2 = true )
1419
+ end
1420
+ if ! have_m1 || ! have_m2
1421
+ # ml-matches did not need both methods to expose the reported ambiguity
1422
+ return false
1423
+ end
1424
+ if ! ambiguous_bottom
1425
+ # since we're intentionally ignoring certain ambiguities (via the
1426
+ # filter call above), see if we can now declare the intersection fully
1427
+ # covered even though it is partially ambiguous over Union{} as a type
1428
+ # parameter somewhere
1429
+ minmax = nothing
1430
+ for match in ms
1431
+ m = match. method
1432
+ match. fully_covers || continue
1433
+ if minmax === nothing || morespecific (m. sig, minmax. sig)
1434
+ minmax = m
1435
+ end
1436
+ end
1437
+ if minmax === nothing
1438
+ return true
1439
+ end
1440
+ for match in ms
1441
+ m = match. method
1442
+ m === minmax && continue
1443
+ if match. fully_covers
1444
+ if ! morespecific (minmax. sig, m. sig)
1445
+ return true
1446
+ end
1447
+ else
1448
+ if morespecific (m. sig, minmax. sig)
1449
+ return true
1450
+ end
1451
+ end
1452
+ end
1410
1453
return false
1411
1454
end
1455
+ return true
1456
+ end
1457
+ if ! (ti <: m1.sig && ti <: m2.sig )
1458
+ # When type-intersection fails, it's often also not commutative. Thus
1459
+ # checking the reverse may allow detecting ambiguity solutions
1460
+ # correctly in more cases (and faster).
1461
+ ti2 = typeintersect (m2. sig, m1. sig)
1462
+ if ti2 <: m1.sig && ti2 <: m2.sig
1463
+ ti = ti2
1464
+ elseif ti != ti2
1465
+ # TODO : this would be the correct way to handle this case, but
1466
+ # people complained so we don't do it
1467
+ # inner(ti2) || return false
1468
+ return false # report that the type system failed to decide if it was ambiguous by saying they definitely aren't
1469
+ else
1470
+ return false # report that the type system failed to decide if it was ambiguous by saying they definitely aren't
1471
+ end
1412
1472
end
1473
+ inner (ti) || return false
1474
+ # otherwise type-intersection reported an ambiguity we couldn't solve
1413
1475
return true
1414
1476
end
1415
1477
0 commit comments