@@ -699,7 +699,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
699699 }
700700
701701 Declaration getTarget ( ) {
702- result = inferMethodCallTarget ( this ) // mutual recursion; resolving method calls requires resolving types and vice versa
702+ result = resolveMethodCallTarget ( this ) // mutual recursion; resolving method calls requires resolving types and vice versa
703703 or
704704 result = CallExprImpl:: getResolvedFunction ( this )
705705 }
@@ -1178,14 +1178,14 @@ private predicate methodCandidateTrait(Type type, Trait trait, string name, int
11781178 methodCandidate ( type , name , arity , impl )
11791179}
11801180
1181- private module IsInstantiationOfInput implements IsInstantiationOfInputSig< MethodCall > {
1182- pragma [ nomagic]
1183- private predicate isMethodCall ( MethodCall mc , Type rootType , string name , int arity ) {
1184- rootType = mc .getTypeAt ( TypePath:: nil ( ) ) and
1185- name = mc .getMethodName ( ) and
1186- arity = mc .getNumberOfArguments ( )
1187- }
1181+ pragma [ nomagic]
1182+ private predicate isMethodCall ( MethodCall mc , Type rootType , string name , int arity ) {
1183+ rootType = mc .getTypeAt ( TypePath:: nil ( ) ) and
1184+ name = mc .getMethodName ( ) and
1185+ arity = mc .getNumberOfArguments ( )
1186+ }
11881187
1188+ private module IsInstantiationOfInput implements IsInstantiationOfInputSig< MethodCall > {
11891189 pragma [ nomagic]
11901190 predicate potentialInstantiationOf ( MethodCall mc , TypeAbstraction impl , TypeMention constraint ) {
11911191 exists ( Type rootType , string name , int arity |
@@ -1338,7 +1338,21 @@ private predicate methodResolutionDependsOnArgument(
13381338private Function getMethodFromImpl ( MethodCall mc ) {
13391339 exists ( Impl impl |
13401340 IsInstantiationOf< MethodCall , IsInstantiationOfInput > :: isInstantiationOf ( mc , impl , _) and
1341- result = getMethodSuccessor ( impl , mc .getMethodName ( ) )
1341+ result = getMethodSuccessor ( impl , mc .getMethodName ( ) ) and
1342+ if impl .hasTrait ( ) and not exists ( mc .getTrait ( ) )
1343+ then
1344+ // inherent methods take precedence over trait methods, so only allow
1345+ // trait methods when there are no matching inherent methods
1346+ exists ( Type rootType , string name , int arity |
1347+ isMethodCall ( mc , rootType , name , arity ) and
1348+ forall ( Impl other |
1349+ not other .hasTrait ( ) and
1350+ methodCandidate ( rootType , name , arity , other )
1351+ |
1352+ IsInstantiationOf< MethodCall , IsInstantiationOfInput > :: isNotInstantiationOf ( mc , other , _)
1353+ )
1354+ )
1355+ else any ( )
13421356 |
13431357 not methodResolutionDependsOnArgument ( impl , _, _, _, _, _) and
13441358 result = getMethodSuccessor ( impl , mc .getMethodName ( ) )
@@ -1356,22 +1370,6 @@ private Function getTraitMethod(ImplTraitReturnType trait, string name) {
13561370 result = getMethodSuccessor ( trait .getImplTraitTypeRepr ( ) , name )
13571371}
13581372
1359- /**
1360- * Gets a method that the method call `mc` resolves to based on type inference,
1361- * if any.
1362- */
1363- private Function inferMethodCallTarget ( MethodCall mc ) {
1364- // The method comes from an `impl` block targeting the type of the receiver.
1365- result = getMethodFromImpl ( mc )
1366- or
1367- // The type of the receiver is a type parameter and the method comes from a
1368- // trait bound on the type parameter.
1369- result = getTypeParameterMethod ( mc .getTypeAt ( TypePath:: nil ( ) ) , mc .getMethodName ( ) )
1370- or
1371- // The type of the receiver is an `impl Trait` type.
1372- result = getTraitMethod ( mc .getTypeAt ( TypePath:: nil ( ) ) , mc .getMethodName ( ) )
1373- }
1374-
13751373cached
13761374private module Cached {
13771375 private import codeql.rust.internal.CachedStages
@@ -1400,47 +1398,18 @@ private module Cached {
14001398 )
14011399 }
14021400
1403- private predicate isInherentImplFunction ( Function f ) {
1404- f = any ( Impl impl | not impl .hasTrait ( ) ) .( ImplItemNode ) .getAnAssocItem ( )
1405- }
1406-
1407- private predicate isTraitImplFunction ( Function f ) {
1408- f = any ( Impl impl | impl .hasTrait ( ) ) .( ImplItemNode ) .getAnAssocItem ( )
1409- }
1410-
1411- private Function resolveMethodCallTargetFrom ( MethodCall mc , boolean fromSource ) {
1412- result = inferMethodCallTarget ( mc ) and
1413- ( if result .fromSource ( ) then fromSource = true else fromSource = false ) and
1414- (
1415- // prioritize inherent implementation methods first
1416- isInherentImplFunction ( result )
1417- or
1418- not isInherentImplFunction ( inferMethodCallTarget ( mc ) ) and
1419- (
1420- // then trait implementation methods
1421- isTraitImplFunction ( result )
1422- or
1423- not isTraitImplFunction ( inferMethodCallTarget ( mc ) ) and
1424- (
1425- // then trait methods with default implementations
1426- result .hasBody ( )
1427- or
1428- // and finally trait methods without default implementations
1429- not inferMethodCallTarget ( mc ) .hasBody ( )
1430- )
1431- )
1432- )
1433- }
1434-
14351401 /** Gets a method that the method call `mc` resolves to, if any. */
14361402 cached
14371403 Function resolveMethodCallTarget ( MethodCall mc ) {
1438- // Functions in source code also gets extracted as library code, due to
1439- // this duplication we prioritize functions from source code.
1440- result = resolveMethodCallTargetFrom ( mc , true )
1404+ // The method comes from an `impl` block targeting the type of the receiver.
1405+ result = getMethodFromImpl ( mc )
1406+ or
1407+ // The type of the receiver is a type parameter and the method comes from a
1408+ // trait bound on the type parameter.
1409+ result = getTypeParameterMethod ( mc .getTypeAt ( TypePath:: nil ( ) ) , mc .getMethodName ( ) )
14411410 or
1442- not exists ( resolveMethodCallTargetFrom ( mc , true ) ) and
1443- result = resolveMethodCallTargetFrom ( mc , false )
1411+ // The type of the receiver is an `impl Trait` type.
1412+ result = getTraitMethod ( mc . getTypeAt ( TypePath :: nil ( ) ) , mc . getMethodName ( ) )
14441413 }
14451414
14461415 pragma [ inline]
0 commit comments