@@ -1176,6 +1176,114 @@ private Type substituteLookupTraits(Type t) {
11761176 * [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers
11771177 */
11781178private module MethodCallResolution {
1179+ /**
1180+ * Provides logic for checking receiver types against constraints of
1181+ * [blanket implementations][1].
1182+ *
1183+ * [1]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods
1184+ */
1185+ module BlanketImplementation {
1186+ /**
1187+ * Holds if `tp` is the type parameter of a blanket implementation and
1188+ * `traitBound` is the first non-trivial trait bound of `tp`.
1189+ */
1190+ pragma [ nomagic]
1191+ private predicate blanketImplementationTraitBound ( TypeParamItemNode tp , Trait traitBound ) {
1192+ tp = any ( ImplItemNode impl ) .getBlanketImplementationTypeParam ( ) and
1193+ traitBound =
1194+ min ( Trait trait , int i |
1195+ trait = tp .resolveBound ( i ) and
1196+ // Exclude traits that are known to not narrow things down very much.
1197+ not trait .getName ( ) .getText ( ) =
1198+ [
1199+ "Sized" , "Clone" ,
1200+ // The auto traits
1201+ "Send" , "Sync" , "Unpin" , "UnwindSafe" , "RefUnwindSafe"
1202+ ]
1203+ |
1204+ trait order by i
1205+ )
1206+ }
1207+
1208+ signature module SatisfiesBlanketConstraintInputSig< HasTypeTreeSig ReceiverType> {
1209+ /**
1210+ * Holds if a method call with receiver type `rt` may potentially target
1211+ * `m`, which is defined in a blanket implementation with type parameter
1212+ * `blanketTypeParam`.
1213+ *
1214+ * `blanketPath` points to the type `blanketTypeParam` inside the type of
1215+ * `m`'s `self` parameter.
1216+ */
1217+ predicate hasBlanketCandidate (
1218+ ReceiverType rt , Function m , TypePath blanketPath , TypeParam blanketTypeParam
1219+ ) ;
1220+ }
1221+
1222+ module SatisfiesBlanketConstraint<
1223+ HasTypeTreeSig ReceiverType, SatisfiesBlanketConstraintInputSig< ReceiverType > Input>
1224+ {
1225+ private newtype TReceiverTypeAndBlanketOffset =
1226+ MkReceiverTypeAndBlanketOffset ( ReceiverType rt , TypePath blanketPath ) {
1227+ Input:: hasBlanketCandidate ( rt , _, blanketPath , _)
1228+ }
1229+
1230+ private class ReceiverTypeAndBlanketOffset extends MkReceiverTypeAndBlanketOffset {
1231+ ReceiverType rt ;
1232+ TypePath blanketPath ;
1233+
1234+ ReceiverTypeAndBlanketOffset ( ) { this = MkReceiverTypeAndBlanketOffset ( rt , blanketPath ) }
1235+
1236+ ReceiverType getReceiverType ( ) { result = rt }
1237+
1238+ TypePath getBlanketPath ( ) { result = blanketPath }
1239+
1240+ Location getLocation ( ) { result = rt .getLocation ( ) }
1241+
1242+ Type getTypeAt ( TypePath path ) { result = rt .getTypeAt ( blanketPath .appendInverse ( path ) ) }
1243+
1244+ string toString ( ) {
1245+ result = rt .toString ( ) + " [blanket at " + blanketPath .toString ( ) + "]"
1246+ }
1247+ }
1248+
1249+ private module SatisfiesBlanketConstraintInput implements
1250+ SatisfiesConstraintInputSig< ReceiverTypeAndBlanketOffset >
1251+ {
1252+ pragma [ nomagic]
1253+ additional predicate relevantConstraint (
1254+ ReceiverTypeAndBlanketOffset rto , Function m , Trait traitBound
1255+ ) {
1256+ exists ( ReceiverType rt , TypePath blanketPath , TypeParam blanketTypeParam |
1257+ rto = MkReceiverTypeAndBlanketOffset ( rt , blanketPath ) and
1258+ Input:: hasBlanketCandidate ( rt , m , blanketPath , blanketTypeParam ) and
1259+ blanketImplementationTraitBound ( blanketTypeParam , traitBound )
1260+ )
1261+ }
1262+
1263+ pragma [ nomagic]
1264+ predicate relevantConstraint ( ReceiverTypeAndBlanketOffset rto , Type constraint ) {
1265+ relevantConstraint ( rto , _, constraint .( TraitType ) .getTrait ( ) )
1266+ }
1267+
1268+ predicate useUniversalConditions ( ) { none ( ) }
1269+ }
1270+
1271+ /**
1272+ * Holds if the receiver type `rt` satisfies the first non-trivial blanket
1273+ * constraint of the method `m`.
1274+ */
1275+ pragma [ nomagic]
1276+ predicate satisfiesBlanketConstraint ( ReceiverType rt , Function m ) {
1277+ exists ( ReceiverTypeAndBlanketOffset rto , Trait traitBound |
1278+ rto = MkReceiverTypeAndBlanketOffset ( rt , _) and
1279+ SatisfiesBlanketConstraintInput:: relevantConstraint ( rto , m , traitBound ) and
1280+ SatisfiesConstraint< ReceiverTypeAndBlanketOffset , SatisfiesBlanketConstraintInput > :: satisfiesConstraintType ( rto ,
1281+ TTrait ( traitBound ) , _, _)
1282+ )
1283+ }
1284+ }
1285+ }
1286+
11791287 /**
11801288 * Holds if `root` is a valid complex [`self` root type][1], with type
11811289 * parameter `tp`.
@@ -1684,86 +1792,18 @@ private module MethodCallResolution {
16841792 Location getLocation ( ) { result = mc_ .getLocation ( ) }
16851793 }
16861794
1687- private newtype TMethodCallCandAndBlanketOffset =
1688- MkMethodCallCandAndBlanketOffset ( MethodCallCand mcc , TypePath blanketPath ) {
1689- exists ( MethodCall mc , string name , int arity , TypeParam blanketTypeParam |
1690- mcc .hasInfo ( mc , _, _, name , arity ) and
1691- methodCallBlanketCandidate ( mc , _, _, _, blanketPath , blanketTypeParam )
1692- )
1693- }
1694-
1695- private class MethodCallCandAndBlanketOffset extends MkMethodCallCandAndBlanketOffset {
1696- MethodCallCand mcc_ ;
1697- TypePath blanketPath ;
1698-
1699- MethodCallCandAndBlanketOffset ( ) { this = MkMethodCallCandAndBlanketOffset ( mcc_ , blanketPath ) }
1700-
1701- MethodCallCand getMethodCallCand ( ) { result = mcc_ }
1702-
1703- TypePath getBlanketPath ( ) { result = blanketPath }
1704-
1705- Location getLocation ( ) { result = mcc_ .getLocation ( ) }
1706-
1707- Type getTypeAt ( TypePath path ) { result = mcc_ .getTypeAt ( blanketPath .appendInverse ( path ) ) }
1708-
1709- string toString ( ) { result = mcc_ .toString ( ) + " (blanket at " + blanketPath .toString ( ) + ")" }
1710- }
1711-
17121795 private module SatisfiesBlanketConstraintInput implements
1713- SatisfiesConstraintInputSig < MethodCallCandAndBlanketOffset >
1796+ BlanketImplementation :: SatisfiesBlanketConstraintInputSig < MethodCallCand >
17141797 {
1715- /**
1716- * Holds if `impl` is a blanket implementation for a type parameter and
1717- * `traitBound` is the first non-trivial trait bound of that type parameter.
1718- */
17191798 pragma [ nomagic]
1720- private predicate blanketImplementationTraitBound ( TypeParamItemNode tp , Trait traitBound ) {
1721- tp = any ( ImplItemNode impl ) .getBlanketImplementationTypeParam ( ) and
1722- traitBound =
1723- min ( Trait trait , int i |
1724- trait = tp .resolveBound ( i ) and
1725- // Exclude traits that are known to not narrow things down very much.
1726- not trait .getName ( ) .getText ( ) =
1727- [
1728- "Sized" , "Clone" ,
1729- // The auto traits
1730- "Send" , "Sync" , "Unpin" , "UnwindSafe" , "RefUnwindSafe"
1731- ]
1732- |
1733- trait order by i
1734- )
1735- }
1736-
1737- pragma [ nomagic]
1738- additional predicate relevantConstraint (
1739- MethodCallCandAndBlanketOffset mcco , Function m , Trait traitBound
1799+ predicate hasBlanketCandidate (
1800+ MethodCallCand mcc , Function m , TypePath blanketPath , TypeParam blanketTypeParam
17401801 ) {
1741- exists (
1742- MethodCallCand mcc , MethodCall mc , string name , int arity , TypePath blanketPath ,
1743- TypeParam blanketTypeParam
1744- |
1745- mcco = MkMethodCallCandAndBlanketOffset ( mcc , blanketPath ) and
1802+ exists ( MethodCall mc , string name , int arity |
17461803 mcc .hasInfo ( mc , _, _, name , arity ) and
1747- methodCallBlanketCandidate ( mc , m , _, _, blanketPath , blanketTypeParam ) and
1748- blanketImplementationTraitBound ( blanketTypeParam , traitBound )
1804+ methodCallBlanketCandidate ( mc , m , _, _, blanketPath , blanketTypeParam )
17491805 )
17501806 }
1751-
1752- pragma [ nomagic]
1753- predicate relevantConstraint ( MethodCallCandAndBlanketOffset mcco , Type constraint ) {
1754- relevantConstraint ( mcco , _, constraint .( TraitType ) .getTrait ( ) )
1755- }
1756-
1757- predicate useUniversalConditions ( ) { none ( ) }
1758- }
1759-
1760- private predicate hasBlanketImpl ( MethodCallCand mcc , Function f ) {
1761- exists ( MethodCallCandAndBlanketOffset mcco , Trait traitBound |
1762- mcco = MkMethodCallCandAndBlanketOffset ( mcc , _) and
1763- SatisfiesBlanketConstraintInput:: relevantConstraint ( mcco , f , traitBound ) and
1764- SatisfiesConstraint< MethodCallCandAndBlanketOffset , SatisfiesBlanketConstraintInput > :: satisfiesConstraintType ( mcco ,
1765- TTrait ( traitBound ) , _, _)
1766- )
17671807 }
17681808
17691809 /**
@@ -1786,7 +1826,8 @@ private module MethodCallResolution {
17861826 methodCallNonBlanketCandidate ( mc , m , abs , constraint , strippedTypePath , strippedType )
17871827 or
17881828 methodCallBlanketCandidate ( mc , m , abs , constraint , _, _) and
1789- hasBlanketImpl ( mcc , m )
1829+ BlanketImplementation:: SatisfiesBlanketConstraint< MethodCallCand , SatisfiesBlanketConstraintInput > :: satisfiesBlanketConstraint ( mcc ,
1830+ m )
17901831 )
17911832 }
17921833
0 commit comments