@@ -8,6 +8,7 @@ private import TypeMention
8
8
private import codeql.typeinference.internal.TypeInference
9
9
private import codeql.rust.frameworks.stdlib.Stdlib
10
10
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
11
+ private import codeql.rust.elements.Call
11
12
12
13
class Type = T:: Type ;
13
14
@@ -496,28 +497,25 @@ private Type inferPathExprType(PathExpr pe, TypePath path) {
496
497
* like `foo::bar(baz)` and `foo.bar(baz)`.
497
498
*/
498
499
private module CallExprBaseMatchingInput implements MatchingInputSig {
499
- private predicate paramPos ( ParamList pl , Param p , int pos , boolean inMethod ) {
500
- p = pl .getParam ( pos ) and
501
- if pl .hasSelfParam ( ) then inMethod = true else inMethod = false
502
- }
500
+ private predicate paramPos ( ParamList pl , Param p , int pos ) { p = pl .getParam ( pos ) }
503
501
504
502
private newtype TDeclarationPosition =
505
503
TSelfDeclarationPosition ( ) or
506
- TPositionalDeclarationPosition ( int pos , boolean inMethod ) { paramPos ( _, _, pos , inMethod ) } or
504
+ TPositionalDeclarationPosition ( int pos ) { paramPos ( _, _, pos ) } or
507
505
TReturnDeclarationPosition ( )
508
506
509
507
class DeclarationPosition extends TDeclarationPosition {
510
508
predicate isSelf ( ) { this = TSelfDeclarationPosition ( ) }
511
509
512
- int asPosition ( boolean inMethod ) { this = TPositionalDeclarationPosition ( result , inMethod ) }
510
+ int asPosition ( ) { this = TPositionalDeclarationPosition ( result ) }
513
511
514
512
predicate isReturn ( ) { this = TReturnDeclarationPosition ( ) }
515
513
516
514
string toString ( ) {
517
515
this .isSelf ( ) and
518
516
result = "self"
519
517
or
520
- result = this .asPosition ( _ ) .toString ( )
518
+ result = this .asPosition ( ) .toString ( )
521
519
or
522
520
this .isReturn ( ) and
523
521
result = "(return)"
@@ -550,7 +548,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
550
548
override Type getParameterType ( DeclarationPosition dpos , TypePath path ) {
551
549
exists ( int pos |
552
550
result = this .getTupleField ( pos ) .getTypeRepr ( ) .( TypeMention ) .resolveTypeAt ( path ) and
553
- dpos = TPositionalDeclarationPosition ( pos , false )
551
+ dpos = TPositionalDeclarationPosition ( pos )
554
552
)
555
553
}
556
554
@@ -573,7 +571,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
573
571
override Type getParameterType ( DeclarationPosition dpos , TypePath path ) {
574
572
exists ( int p |
575
573
result = this .getTupleField ( p ) .getTypeRepr ( ) .( TypeMention ) .resolveTypeAt ( path ) and
576
- dpos = TPositionalDeclarationPosition ( p , false )
574
+ dpos = TPositionalDeclarationPosition ( p )
577
575
)
578
576
}
579
577
@@ -606,9 +604,9 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
606
604
}
607
605
608
606
override Type getParameterType ( DeclarationPosition dpos , TypePath path ) {
609
- exists ( Param p , int i , boolean inMethod |
610
- paramPos ( this .getParamList ( ) , p , i , inMethod ) and
611
- dpos = TPositionalDeclarationPosition ( i , inMethod ) and
607
+ exists ( Param p , int i |
608
+ paramPos ( this .getParamList ( ) , p , i ) and
609
+ dpos = TPositionalDeclarationPosition ( i ) and
612
610
result = inferAnnotatedType ( p .getPat ( ) , path )
613
611
)
614
612
or
@@ -640,125 +638,44 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
640
638
}
641
639
}
642
640
643
- private predicate argPos ( CallExprBase call , Expr e , int pos , boolean isMethodCall ) {
644
- exists ( ArgList al |
645
- e = al .getArg ( pos ) and
646
- call .getArgList ( ) = al and
647
- if call instanceof MethodCallExpr then isMethodCall = true else isMethodCall = false
648
- )
649
- }
650
-
651
- private newtype TAccessPosition =
652
- TSelfAccessPosition ( ) or
653
- TPositionalAccessPosition ( int pos , boolean isMethodCall ) { argPos ( _, _, pos , isMethodCall ) } or
654
- TReturnAccessPosition ( )
655
-
656
- class AccessPosition extends TAccessPosition {
657
- predicate isSelf ( ) { this = TSelfAccessPosition ( ) }
658
-
659
- int asPosition ( boolean isMethodCall ) { this = TPositionalAccessPosition ( result , isMethodCall ) }
660
-
661
- predicate isReturn ( ) { this = TReturnAccessPosition ( ) }
662
-
663
- string toString ( ) {
664
- this .isSelf ( ) and
665
- result = "self"
666
- or
667
- result = this .asPosition ( _) .toString ( )
668
- or
669
- this .isReturn ( ) and
670
- result = "(return)"
671
- }
672
- }
641
+ class AccessPosition = DeclarationPosition ;
673
642
674
643
private import codeql.rust.elements.internal.CallExprImpl:: Impl as CallExprImpl
675
644
676
- abstract class Access extends Expr {
677
- abstract Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) ;
678
-
679
- abstract AstNode getNodeAt ( AccessPosition apos ) ;
680
-
681
- abstract Type getInferredType ( AccessPosition apos , TypePath path ) ;
682
-
683
- abstract Declaration getTarget ( ) ;
684
- }
685
-
686
- private class CallExprBaseAccess extends Access instanceof CallExprBase {
687
- private TypeMention getMethodTypeArg ( int i ) {
688
- result = this .( MethodCallExpr ) .getGenericArgList ( ) .getTypeArg ( i )
689
- }
690
-
691
- override Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) {
645
+ final class Access extends Call {
646
+ Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) {
692
647
exists ( TypeMention arg | result = arg .resolveTypeAt ( path ) |
693
648
arg = getExplicitTypeArgMention ( CallExprImpl:: getFunctionPath ( this ) , apos .asTypeParam ( ) )
694
649
or
695
- arg = this .getMethodTypeArg ( apos .asMethodTypeArgumentPosition ( ) )
650
+ arg =
651
+ this .( MethodCallExpr ) .getGenericArgList ( ) .getTypeArg ( apos .asMethodTypeArgumentPosition ( ) )
696
652
)
697
653
}
698
654
699
- override AstNode getNodeAt ( AccessPosition apos ) {
700
- exists ( int p , boolean isMethodCall |
701
- argPos ( this , result , p , isMethodCall ) and
702
- apos = TPositionalAccessPosition ( p , isMethodCall )
703
- )
655
+ AstNode getNodeAt ( AccessPosition apos ) {
656
+ result = this .getArgument ( apos .asPosition ( ) )
704
657
or
705
- result = this .( MethodCallExpr ) .getReceiver ( ) and
706
- apos = TSelfAccessPosition ( )
658
+ result = this .getReceiver ( ) and apos .isSelf ( )
707
659
or
708
- result = this and
709
- apos = TReturnAccessPosition ( )
660
+ result = this and apos .isReturn ( )
710
661
}
711
662
712
- override Type getInferredType ( AccessPosition apos , TypePath path ) {
663
+ Type getInferredType ( AccessPosition apos , TypePath path ) {
713
664
result = inferType ( this .getNodeAt ( apos ) , path )
714
665
}
715
666
716
- override Declaration getTarget ( ) {
717
- result = CallExprImpl:: getResolvedFunction ( this )
718
- or
667
+ Declaration getTarget ( ) {
719
668
result = inferMethodCallTarget ( this ) // mutual recursion; resolving method calls requires resolving types and vice versa
720
- }
721
- }
722
-
723
- private class OperationAccess extends Access instanceof Operation {
724
- OperationAccess ( ) { super .isOverloaded ( _, _) }
725
-
726
- override Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) {
727
- // The syntax for operators does not allow type arguments.
728
- none ( )
729
- }
730
-
731
- override AstNode getNodeAt ( AccessPosition apos ) {
732
- result = super .getOperand ( 0 ) and apos = TSelfAccessPosition ( )
733
- or
734
- result = super .getOperand ( 1 ) and apos = TPositionalAccessPosition ( 0 , true )
735
669
or
736
- result = this and apos = TReturnAccessPosition ( )
737
- }
738
-
739
- override Type getInferredType ( AccessPosition apos , TypePath path ) {
740
- result = inferType ( this .getNodeAt ( apos ) , path )
741
- }
742
-
743
- override Declaration getTarget ( ) {
744
- result = inferMethodCallTarget ( this ) // mutual recursion; resolving method calls requires resolving types and vice versa
670
+ result = CallExprImpl:: getResolvedFunction ( this )
745
671
}
746
672
}
747
673
748
674
predicate accessDeclarationPositionMatch ( AccessPosition apos , DeclarationPosition dpos ) {
749
675
apos .isSelf ( ) and
750
676
dpos .isSelf ( )
751
677
or
752
- exists ( int pos , boolean isMethodCall | pos = apos .asPosition ( isMethodCall ) |
753
- pos = 0 and
754
- isMethodCall = false and
755
- dpos .isSelf ( )
756
- or
757
- isMethodCall = false and
758
- pos = dpos .asPosition ( true ) + 1
759
- or
760
- pos = dpos .asPosition ( isMethodCall )
761
- )
678
+ apos .asPosition ( ) = dpos .asPosition ( )
762
679
or
763
680
apos .isReturn ( ) and
764
681
dpos .isReturn ( )
@@ -1180,91 +1097,29 @@ private Type inferIndexExprType(IndexExpr ie, TypePath path) {
1180
1097
)
1181
1098
}
1182
1099
1183
- private module MethodCall {
1184
- /** An expression that calls a method. */
1185
- abstract private class MethodCallImpl extends Expr {
1186
- /** Gets the name of the method targeted. */
1187
- abstract string getMethodName ( ) ;
1188
-
1189
- /** Gets the number of arguments _excluding_ the `self` argument. */
1190
- abstract int getArity ( ) ;
1191
-
1192
- /** Gets the trait targeted by this method call, if any. */
1193
- Trait getTrait ( ) { none ( ) }
1194
-
1195
- /** Gets the type of the receiver of the method call at `path`. */
1196
- abstract Type getTypeAt ( TypePath path ) ;
1100
+ final class MethodCall extends Call {
1101
+ MethodCall ( ) {
1102
+ exists ( this .getReceiver ( ) ) and
1103
+ // We want the method calls that don't have a path to a concrete method in
1104
+ // an impl block. We need to exclude calls like `MyType::my_method(..)`.
1105
+ ( this instanceof CallExpr implies exists ( this .getTrait ( ) ) )
1197
1106
}
1198
1107
1199
- final class MethodCall = MethodCallImpl ;
1200
-
1201
- private class MethodCallExprMethodCall extends MethodCallImpl instanceof MethodCallExpr {
1202
- override string getMethodName ( ) { result = super .getIdentifier ( ) .getText ( ) }
1203
-
1204
- override int getArity ( ) { result = super .getArgList ( ) .getNumberOfArgs ( ) }
1205
-
1206
- pragma [ nomagic]
1207
- override Type getTypeAt ( TypePath path ) {
1108
+ /** Gets the type of the receiver of the method call at `path`. */
1109
+ Type getTypeAt ( TypePath path ) {
1110
+ if this .receiverImplicitlyBorrowed ( )
1111
+ then
1208
1112
exists ( TypePath path0 | result = inferType ( super .getReceiver ( ) , path0 ) |
1209
1113
path0 .isCons ( TRefTypeParameter ( ) , path )
1210
1114
or
1211
1115
not path0 .isCons ( TRefTypeParameter ( ) , _) and
1212
1116
not ( path0 .isEmpty ( ) and result = TRefType ( ) ) and
1213
1117
path = path0
1214
1118
)
1215
- }
1216
- }
1217
-
1218
- private class CallExprMethodCall extends MethodCallImpl instanceof CallExpr {
1219
- TraitItemNode trait ;
1220
- string methodName ;
1221
- Expr receiver ;
1222
-
1223
- CallExprMethodCall ( ) {
1224
- receiver = this .getArg ( 0 ) and
1225
- exists ( Path path , Function f |
1226
- path = this .getFunction ( ) .( PathExpr ) .getPath ( ) and
1227
- f = resolvePath ( path ) and
1228
- f .getParamList ( ) .hasSelfParam ( ) and
1229
- trait = resolvePath ( path .getQualifier ( ) ) and
1230
- trait .getAnAssocItem ( ) = f and
1231
- path .getSegment ( ) .getIdentifier ( ) .getText ( ) = methodName
1232
- )
1233
- }
1234
-
1235
- override string getMethodName ( ) { result = methodName }
1236
-
1237
- override int getArity ( ) { result = super .getArgList ( ) .getNumberOfArgs ( ) - 1 }
1238
-
1239
- override Trait getTrait ( ) { result = trait }
1240
-
1241
- pragma [ nomagic]
1242
- override Type getTypeAt ( TypePath path ) { result = inferType ( receiver , path ) }
1243
- }
1244
-
1245
- private class OperationMethodCall extends MethodCallImpl instanceof Operation {
1246
- TraitItemNode trait ;
1247
- string methodName ;
1248
-
1249
- OperationMethodCall ( ) { super .isOverloaded ( trait , methodName ) }
1250
-
1251
- override string getMethodName ( ) { result = methodName }
1252
-
1253
- override int getArity ( ) { result = this .( Operation ) .getNumberOfOperands ( ) - 1 }
1254
-
1255
- override Trait getTrait ( ) { result = trait }
1256
-
1257
- pragma [ nomagic]
1258
- override Type getTypeAt ( TypePath path ) {
1259
- result = inferType ( this .( BinaryExpr ) .getLhs ( ) , path )
1260
- or
1261
- result = inferType ( this .( PrefixExpr ) .getExpr ( ) , path )
1262
- }
1119
+ else result = inferType ( super .getReceiver ( ) , path )
1263
1120
}
1264
1121
}
1265
1122
1266
- import MethodCall
1267
-
1268
1123
/**
1269
1124
* Holds if a method for `type` with the name `name` and the arity `arity`
1270
1125
* exists in `impl`.
@@ -1293,7 +1148,7 @@ private module IsInstantiationOfInput implements IsInstantiationOfInputSig<Metho
1293
1148
private predicate isMethodCall ( MethodCall mc , Type rootType , string name , int arity ) {
1294
1149
rootType = mc .getTypeAt ( TypePath:: nil ( ) ) and
1295
1150
name = mc .getMethodName ( ) and
1296
- arity = mc .getArity ( )
1151
+ arity = mc .getNumberOfArguments ( )
1297
1152
}
1298
1153
1299
1154
pragma [ nomagic]
0 commit comments