@@ -1512,6 +1512,10 @@ private predicate methodCandidateTrait(Type type, Trait trait, string name, int
15121512 methodCandidate ( type , name , arity , impl )
15131513}
15141514
1515+ /**
1516+ * Holds if `mc` has `rootType` as the root type of the reciever and the target
1517+ * method is named `name` and has arity `arity`
1518+ */
15151519pragma [ nomagic]
15161520private predicate isMethodCall ( MethodCall mc , Type rootType , string name , int arity ) {
15171521 rootType = mc .getTypeAt ( TypePath:: nil ( ) ) and
@@ -1710,6 +1714,91 @@ private predicate methodCallHasImplCandidate(MethodCall mc, Impl impl) {
17101714 else any ( )
17111715}
17121716
1717+ private module BlanketImplementation {
1718+ /**
1719+ * Holds if `impl` is a blanket implementation, that is, an implementation of a
1720+ * trait for a type parameter.
1721+ */
1722+ private TypeParamItemNode getBlanketImplementationTypeParam ( Impl impl ) {
1723+ result = impl .( ImplItemNode ) .resolveSelfTy ( ) and
1724+ result = impl .getGenericParamList ( ) .getAGenericParam ( ) and
1725+ not exists ( impl .getAttributeMacroExpansion ( ) )
1726+ }
1727+
1728+ /**
1729+ * Holds if `impl` is a blanket implementation for a type parameter and the type
1730+ * parameter must implement `trait`.
1731+ */
1732+ private predicate blanketImplementationTraitBound ( Impl impl , Trait t ) {
1733+ t =
1734+ rank [ 1 ] ( Trait trait , int i |
1735+ trait = getBlanketImplementationTypeParam ( impl ) .resolveBound ( i ) and
1736+ not trait .getName ( ) .getText ( ) = [ "Sized" , "Fn" , "FnOnce" , "FnMut" ]
1737+ |
1738+ trait order by i
1739+ )
1740+ }
1741+
1742+ private predicate blanketImplementationWithoutBound ( Impl impl ) {
1743+ not exists ( impl .getAttributeMacroExpansion ( ) ) and
1744+ exists ( TypeParam gp |
1745+ gp = impl .getGenericParamList ( ) .getAGenericParam ( ) and
1746+ gp = impl .( ImplItemNode ) .resolveSelfTy ( ) and
1747+ not exists ( gp .( TypeParamItemNode ) .getABoundPath ( ) )
1748+ )
1749+ }
1750+
1751+ private predicate test ( Impl impl , ItemNode resolved ) {
1752+ exists ( TypeParamItemNode tp |
1753+ tp = getBlanketImplementationTypeParam ( impl ) and
1754+ not blanketImplementationTraitBound ( impl , _) and
1755+ not blanketImplementationWithoutBound ( impl ) and
1756+ resolved = resolvePath ( tp .getBoundPath ( 0 ) )
1757+ )
1758+ }
1759+
1760+ private predicate blanketImplementationMethod (
1761+ Impl impl , Trait trait , string name , int arity , Function f
1762+ ) {
1763+ f = impl .( ImplItemNode ) .getASuccessor ( name ) and
1764+ blanketImplementationTraitBound ( impl , trait ) and
1765+ f .getParamList ( ) .hasSelfParam ( ) and
1766+ arity = f .getParamList ( ) .getNumberOfParams ( ) and
1767+ // Make this stronger and document
1768+ not trait .( TraitItemNode ) .getASuccessor ( name ) = f
1769+ }
1770+
1771+ predicate methodCallMatchesBlanketImpl ( MethodCall mc , Type t , Impl impl , Trait trait , Function f ) {
1772+ exists ( string name , int arity |
1773+ isMethodCall ( mc , t , name , arity ) and
1774+ blanketImplementationMethod ( impl , trait , name , arity , f )
1775+ )
1776+ }
1777+
1778+ module SatisfiesConstraintInput implements SatisfiesConstraintInputSig< MethodCall > {
1779+ pragma [ nomagic]
1780+ predicate relevantConstraint ( MethodCall mc , Type constraint ) {
1781+ methodCallMatchesBlanketImpl ( mc , _, _, constraint .( TraitType ) .getTrait ( ) , _)
1782+ }
1783+ }
1784+
1785+ predicate debugSatisfiesConstraintType ( MethodCall mc , Trait trait , TypePath path , Type ty ) {
1786+ SatisfiesConstraint< MethodCall , SatisfiesConstraintInput > :: satisfiesConstraintType ( mc ,
1787+ TTrait ( trait ) , path , ty )
1788+ }
1789+
1790+ predicate getBlanketImpl ( MethodCall mc , Type t , Impl impl , Trait trait , Function f ) {
1791+ SatisfiesConstraint< MethodCall , SatisfiesConstraintInput > :: satisfiesConstraintType ( mc ,
1792+ TTrait ( trait ) , _, _) and
1793+ methodCallMatchesBlanketImpl ( mc , t , impl , trait , f )
1794+ }
1795+
1796+ pragma [ nomagic]
1797+ Function getMethodFromBlanketImpl ( MethodCall mc ) {
1798+ BlanketImplementation:: getBlanketImpl ( mc , _, _, _, result )
1799+ }
1800+ }
1801+
17131802/** Gets a method from an `impl` block that matches the method call `mc`. */
17141803pragma [ nomagic]
17151804private Function getMethodFromImpl ( MethodCall mc ) {
@@ -1745,6 +1834,8 @@ private Function resolveMethodCallTarget(MethodCall mc) {
17451834 // The method comes from an `impl` block targeting the type of the receiver.
17461835 result = getMethodFromImpl ( mc )
17471836 or
1837+ result = BlanketImplementation:: getMethodFromBlanketImpl ( mc )
1838+ or
17481839 // The type of the receiver is a type parameter and the method comes from a
17491840 // trait bound on the type parameter.
17501841 result = getTypeParameterMethod ( mc .getTypeAt ( TypePath:: nil ( ) ) , mc .getMethodName ( ) )
0 commit comments