@@ -2178,9 +2178,17 @@ private module BlanketImplementation {
21782178 arity = result .( ImplItemNode ) .resolveTraitTy ( ) .( Trait ) .getNumberOfGenericParams ( )
21792179 }
21802180
2181+ private predicate duplicatedImpl ( Impl impl1 , Impl impl2 ) {
2182+ exists ( string fileName , string traitName , int arity , string tpName |
2183+ impl1 = getPotentialDuplicated ( fileName , traitName , arity , tpName ) and
2184+ impl2 = getPotentialDuplicated ( fileName , traitName , arity , tpName ) and
2185+ impl1 .getLocation ( ) .getFile ( ) .getAbsolutePath ( ) <
2186+ impl2 .getLocation ( ) .getFile ( ) .getAbsolutePath ( )
2187+ )
2188+ }
2189+
21812190 /**
2182- * Holds if `impl1` and `impl2` are duplicates and `impl2` is strictly more
2183- * "canonical" than `impl1`.
2191+ * Holds if `impl` is a canonical blanket implementation.
21842192 *
21852193 * Libraries can often occur several times in the database for different
21862194 * library versions. This causes the same blanket implementations to exist
@@ -2189,40 +2197,18 @@ private module BlanketImplementation {
21892197 * We detect these duplicates based on some simple heuristics (same trait
21902198 * name, file name, etc.). For these duplicates we select the one with the
21912199 * greatest file name (which usually is also the one with the greatest library
2192- * version in the path)
2200+ * version in the path) as the "canonical" implementation.
21932201 */
2194- predicate duplicatedImpl ( Impl impl1 , Impl impl2 ) {
2195- exists ( string fileName , string traitName , int arity , string tpName |
2196- impl1 = getPotentialDuplicated ( fileName , traitName , arity , tpName ) and
2197- impl2 = getPotentialDuplicated ( fileName , traitName , arity , tpName ) and
2198- impl1 .getLocation ( ) .getFile ( ) .getAbsolutePath ( ) <
2199- impl2 .getLocation ( ) .getFile ( ) .getAbsolutePath ( )
2200- )
2202+ private predicate isCanonicalImpl ( Impl impl ) {
2203+ not duplicatedImpl ( impl , _) and impl .( ImplItemNode ) .isBlanketImplementation ( )
22012204 }
22022205
2203- predicate isCanonicalImpl ( Impl impl ) {
2204- not duplicatedImpl ( impl , _) and isBlanketImplementation ( impl )
2205- }
2206-
2207- Impl getCanonicalImpl ( Impl impl ) {
2208- result =
2209- max ( Impl impl0 , Location l |
2210- duplicatedImpl ( impl , impl0 ) and l = impl0 .getLocation ( )
2211- |
2212- impl0 order by l .getFile ( ) .getAbsolutePath ( ) , l .getStartLine ( )
2213- )
2214- or
2215- isCanonicalImpl ( impl ) and result = impl
2216- }
2217-
2218- predicate isCanonicalBlanketImplementation ( Impl impl ) { impl = getCanonicalImpl ( impl ) }
2219-
22202206 /**
2221- * Holds if `impl` is a blanket implementation for a type parameter and the type
2222- * parameter must implement `trait `.
2207+ * Holds if `impl` is a blanket implementation for a type parameter with trait
2208+ * bound `traitBound `.
22232209 */
2224- private predicate blanketImplementationTraitBound ( Impl impl , Trait t ) {
2225- t =
2210+ private predicate blanketImplementationTraitBound ( Impl impl , Trait traitBound ) {
2211+ traitBound =
22262212 min ( Trait trait , int i |
22272213 trait = getBlanketImplementationTypeParam ( impl ) .resolveBound ( i ) and
22282214 // Exclude traits that are known to not narrow things down very much.
@@ -2243,10 +2229,10 @@ private module BlanketImplementation {
22432229 * `arity`.
22442230 */
22452231 private predicate blanketImplementationMethod (
2246- ImplItemNode impl , Trait trait , string name , int arity , Function f
2232+ ImplItemNode impl , Trait traitBound , string name , int arity , Function f
22472233 ) {
2248- isCanonicalBlanketImplementation ( impl ) and
2249- blanketImplementationTraitBound ( impl , trait ) and
2234+ isCanonicalImpl ( impl ) and
2235+ blanketImplementationTraitBound ( impl , traitBound ) and
22502236 f .getParamList ( ) .hasSelfParam ( ) and
22512237 arity = f .getParamList ( ) .getNumberOfParams ( ) and
22522238 (
@@ -2258,48 +2244,48 @@ private module BlanketImplementation {
22582244 f = impl .resolveTraitTy ( ) .getAssocItem ( name )
22592245 ) and
22602246 // If the method is already available through one of the trait bounds on the
2261- // type parameter (because they share a common ancestor trait) then ignore
2247+ // type parameter (because they share a common super trait) then ignore
22622248 // it.
22632249 not getBlanketImplementationTypeParam ( impl ) .resolveABound ( ) .( TraitItemNode ) .getASuccessor ( name ) =
22642250 f
22652251 }
22662252
2267- predicate methodCallMatchesBlanketImpl ( MethodCall mc , Type t , Impl impl , Trait trait , Function f ) {
2253+ pragma [ nomagic]
2254+ predicate methodCallMatchesBlanketImpl (
2255+ MethodCall mc , Type t , ImplItemNode impl , Trait traitBound , Trait traitImpl , Function f
2256+ ) {
22682257 // Only check method calls where we have ruled out inherent method targets.
22692258 // Ideally we would also check if non-blanket method targets have been ruled
22702259 // out.
22712260 methodCallHasNoInherentTarget ( mc ) and
22722261 exists ( string name , int arity |
22732262 isMethodCall ( mc , t , name , arity ) and
2274- blanketImplementationMethod ( impl , trait , name , arity , f )
2275- )
2263+ blanketImplementationMethod ( impl , traitBound , name , arity , f )
2264+ ) and
2265+ traitImpl = impl .resolveTraitTy ( )
22762266 }
22772267
22782268 private predicate relevantTraitVisible ( Element mc , Trait trait ) {
2279- exists ( ImplItemNode impl |
2280- methodCallMatchesBlanketImpl ( mc , _, impl , _, _) and
2281- trait = impl .resolveTraitTy ( )
2282- )
2269+ methodCallMatchesBlanketImpl ( mc , _, _, _, trait , _)
22832270 }
22842271
22852272 module SatisfiesConstraintInput implements SatisfiesConstraintInputSig< MethodCall > {
22862273 pragma [ nomagic]
22872274 predicate relevantConstraint ( MethodCall mc , Type constraint ) {
2288- exists ( Trait trait , Trait trait2 , ImplItemNode impl |
2289- methodCallMatchesBlanketImpl ( mc , _, impl , trait , _) and
2290- TraitIsVisible< relevantTraitVisible / 2 > :: traitIsVisible ( mc , pragma [ only_bind_into ] ( trait2 ) ) and
2291- trait2 = pragma [ only_bind_into ] ( impl .resolveTraitTy ( ) ) and
2292- trait = constraint .( TraitType ) .getTrait ( )
2275+ exists ( Trait traitBound , Trait traitImpl , ImplItemNode impl |
2276+ methodCallMatchesBlanketImpl ( mc , _, impl , traitBound , traitImpl , _) and
2277+ TraitIsVisible< relevantTraitVisible / 2 > :: traitIsVisible ( mc , traitImpl ) and
2278+ traitBound = constraint .( TraitType ) .getTrait ( )
22932279 )
22942280 }
22952281
22962282 predicate useUniversalConditions ( ) { none ( ) }
22972283 }
22982284
2299- predicate hasBlanketImpl ( MethodCall mc , Type t , Impl impl , Trait trait , Function f ) {
2285+ predicate hasBlanketImpl ( MethodCall mc , Type t , Impl impl , Trait traitBound , Function f ) {
23002286 SatisfiesConstraint< MethodCall , SatisfiesConstraintInput > :: satisfiesConstraintType ( mc ,
2301- TTrait ( trait ) , _, _) and
2302- methodCallMatchesBlanketImpl ( mc , t , impl , trait , f )
2287+ TTrait ( traitBound ) , _, _) and
2288+ methodCallMatchesBlanketImpl ( mc , t , impl , traitBound , _ , f )
23032289 }
23042290
23052291 pragma [ nomagic]
0 commit comments