@@ -1471,20 +1471,18 @@ private module MethodResolution {
14711471 }
14721472
14731473 /**
1474- * Same as `getACandidateReceiverTypeAt`, but with traits substituted in for types
1475- * with trait bounds.
1474+ * Same as `getACandidateReceiverTypeAt`, but excludes pseudo types `!` and `unknown`.
14761475 */
14771476 pragma[nomagic]
1478- Type getACandidateReceiverTypeAtSubstituteLookupTraits(
1479- string derefChain, boolean borrow, TypePath path
1480- ) {
1481- result = substituteLookupTraits(this.getACandidateReceiverTypeAt(derefChain, borrow, path) )
1477+ Type getANonPseudoCandidateReceiverTypeAt(string derefChain, boolean borrow, TypePath path) {
1478+ result = this.getACandidateReceiverTypeAt( derefChain, borrow, path) and
1479+ result != TNeverType() and
1480+ result != TUnknownType( )
14821481 }
14831482
14841483 pragma[nomagic]
14851484 private Type getComplexStrippedType(string derefChain, boolean borrow, TypePath strippedTypePath) {
1486- result =
1487- this.getACandidateReceiverTypeAtSubstituteLookupTraits(derefChain, borrow, strippedTypePath) and
1485+ result = this.getANonPseudoCandidateReceiverTypeAt(derefChain, borrow, strippedTypePath) and
14881486 isComplexRootStripped(strippedTypePath, result)
14891487 }
14901488
@@ -1523,23 +1521,58 @@ private module MethodResolution {
15231521 )
15241522 }
15251523
1524+ // forex using recursion
1525+ pragma[nomagic]
1526+ private predicate hasNoCompatibleTargetNoBorrowToIndex(
1527+ string derefChain, TypePath strippedTypePath, Type strippedType, int n
1528+ ) {
1529+ (
1530+ this.supportsAutoDerefAndBorrow()
1531+ or
1532+ // needed for the `hasNoCompatibleTarget` check in
1533+ // `ReceiverSatisfiesBlanketLikeConstraintInput::hasBlanketCandidate`
1534+ derefChain = ""
1535+ ) and
1536+ strippedType = this.getComplexStrippedType(derefChain, false, strippedTypePath) and
1537+ n = -1
1538+ or
1539+ this.hasNoCompatibleTargetNoBorrowToIndex(derefChain, strippedTypePath, strippedType, n - 1) and
1540+ exists(Type t | t = getNthLookupType(strippedType, n) |
1541+ this.hasNoCompatibleTargetCheck(derefChain, false, strippedTypePath, t)
1542+ )
1543+ }
1544+
15261545 /**
15271546 * Holds if the candidate receiver type represented by `derefChain` does not
15281547 * have a matching method target.
15291548 */
15301549 pragma[nomagic]
15311550 predicate hasNoCompatibleTargetNoBorrow(string derefChain) {
1551+ exists(Type strippedType |
1552+ this.hasNoCompatibleTargetNoBorrowToIndex(derefChain, _, strippedType,
1553+ getLastLookupTypeIndex(strippedType))
1554+ )
1555+ }
1556+
1557+ // forex using recursion
1558+ pragma[nomagic]
1559+ private predicate hasNoCompatibleNonBlanketTargetNoBorrowToIndex(
1560+ string derefChain, TypePath strippedTypePath, Type strippedType, int n
1561+ ) {
15321562 (
15331563 this.supportsAutoDerefAndBorrow()
15341564 or
15351565 // needed for the `hasNoCompatibleTarget` check in
15361566 // `ReceiverSatisfiesBlanketLikeConstraintInput::hasBlanketCandidate`
15371567 derefChain = ""
15381568 ) and
1539- exists(TypePath strippedTypePath, Type strippedType |
1540- not derefChain.matches("%.ref") and // no need to try a borrow if the last thing we did was a deref
1541- strippedType = this.getComplexStrippedType(derefChain, false, strippedTypePath) and
1542- this.hasNoCompatibleTargetCheck(derefChain, false, strippedTypePath, strippedType)
1569+ strippedType = this.getComplexStrippedType(derefChain, false, strippedTypePath) and
1570+ n = -1
1571+ or
1572+ this.hasNoCompatibleNonBlanketTargetNoBorrowToIndex(derefChain, strippedTypePath,
1573+ strippedType, n - 1) and
1574+ exists(Type t | t = getNthLookupType(strippedType, n) |
1575+ this.hasNoCompatibleNonBlanketTargetCheck(derefChain, false, strippedTypePath, t)
15431576 )
15441577 }
15451578
@@ -1549,17 +1582,24 @@ private module MethodResolution {
15491582 */
15501583 pragma[nomagic]
15511584 predicate hasNoCompatibleNonBlanketTargetNoBorrow(string derefChain) {
1552- (
1553- this.supportsAutoDerefAndBorrow()
1554- or
1555- // needed for the `hasNoCompatibleTarget` check in
1556- // `ReceiverSatisfiesBlanketLikeConstraintInput::hasBlanketCandidate`
1557- derefChain = ""
1558- ) and
1559- exists(TypePath strippedTypePath, Type strippedType |
1560- not derefChain.matches("%.ref") and // no need to try a borrow if the last thing we did was a deref
1561- strippedType = this.getComplexStrippedType(derefChain, false, strippedTypePath) and
1562- this.hasNoCompatibleNonBlanketTargetCheck(derefChain, false, strippedTypePath, strippedType)
1585+ exists(Type strippedType |
1586+ this.hasNoCompatibleNonBlanketTargetNoBorrowToIndex(derefChain, _, strippedType,
1587+ getLastLookupTypeIndex(strippedType))
1588+ )
1589+ }
1590+
1591+ // forex using recursion
1592+ pragma[nomagic]
1593+ private predicate hasNoCompatibleTargetBorrowToIndex(
1594+ string derefChain, TypePath strippedTypePath, Type strippedType, int n
1595+ ) {
1596+ this.hasNoCompatibleTargetNoBorrow(derefChain) and
1597+ strippedType = this.getComplexStrippedType(derefChain, true, strippedTypePath) and
1598+ n = -1
1599+ or
1600+ this.hasNoCompatibleTargetBorrowToIndex(derefChain, strippedTypePath, strippedType, n - 1) and
1601+ exists(Type t | t = getNthLookupType(strippedType, n) |
1602+ this.hasNoCompatibleNonBlanketLikeTargetCheck(derefChain, true, strippedTypePath, t)
15631603 )
15641604 }
15651605
@@ -1569,11 +1609,25 @@ private module MethodResolution {
15691609 */
15701610 pragma[nomagic]
15711611 predicate hasNoCompatibleTargetBorrow(string derefChain) {
1572- exists(TypePath strippedTypePath, Type strippedType |
1573- this.hasNoCompatibleTargetNoBorrow(derefChain) and
1574- strippedType = this.getComplexStrippedType(derefChain, true, strippedTypePath) and
1575- this.hasNoCompatibleNonBlanketLikeTargetCheck(derefChain, true, strippedTypePath,
1576- strippedType)
1612+ exists(Type strippedType |
1613+ this.hasNoCompatibleTargetBorrowToIndex(derefChain, _, strippedType,
1614+ getLastLookupTypeIndex(strippedType))
1615+ )
1616+ }
1617+
1618+ // forex using recursion
1619+ pragma[nomagic]
1620+ private predicate hasNoCompatibleNonBlanketTargetBorrowToIndex(
1621+ string derefChain, TypePath strippedTypePath, Type strippedType, int n
1622+ ) {
1623+ this.hasNoCompatibleTargetNoBorrow(derefChain) and
1624+ strippedType = this.getComplexStrippedType(derefChain, true, strippedTypePath) and
1625+ n = -1
1626+ or
1627+ this.hasNoCompatibleNonBlanketTargetBorrowToIndex(derefChain, strippedTypePath, strippedType,
1628+ n - 1) and
1629+ exists(Type t | t = getNthLookupType(strippedType, n) |
1630+ this.hasNoCompatibleNonBlanketTargetCheck(derefChain, true, strippedTypePath, t)
15771631 )
15781632 }
15791633
@@ -1583,10 +1637,9 @@ private module MethodResolution {
15831637 */
15841638 pragma[nomagic]
15851639 predicate hasNoCompatibleNonBlanketTargetBorrow(string derefChain) {
1586- exists(TypePath strippedTypePath, Type strippedType |
1587- this.hasNoCompatibleTargetNoBorrow(derefChain) and
1588- strippedType = this.getComplexStrippedType(derefChain, true, strippedTypePath) and
1589- this.hasNoCompatibleNonBlanketTargetCheck(derefChain, true, strippedTypePath, strippedType)
1640+ exists(Type strippedType |
1641+ this.hasNoCompatibleNonBlanketTargetBorrowToIndex(derefChain, _, strippedType,
1642+ getLastLookupTypeIndex(strippedType))
15901643 )
15911644 }
15921645
@@ -1804,9 +1857,8 @@ private module MethodResolution {
18041857 MethodCall getMethodCall() { result = mc_ }
18051858
18061859 Type getTypeAt(TypePath path) {
1807- result = mc_.getACandidateReceiverTypeAtSubstituteLookupTraits(derefChain, borrow, path) and
1808- not result = TNeverType() and
1809- not result = TUnknownType()
1860+ result =
1861+ substituteLookupTraits(mc_.getANonPseudoCandidateReceiverTypeAt(derefChain, borrow, path))
18101862 }
18111863
18121864 pragma[nomagic]
0 commit comments