@@ -746,10 +746,6 @@ abstract class Content extends TContent {
746
746
*/
747
747
abstract class VariantContent extends Content { }
748
748
749
- private TupleField getVariantTupleField ( Variant v , int i ) {
750
- result = v .getFieldList ( ) .( TupleFieldList ) .getField ( i )
751
- }
752
-
753
749
/** A tuple variant. */
754
750
private class VariantTupleFieldContent extends VariantContent , TVariantTupleFieldContent {
755
751
private Variant v ;
@@ -763,16 +759,11 @@ private class VariantTupleFieldContent extends VariantContent, TVariantTupleFiel
763
759
exists ( string name |
764
760
name = v .getName ( ) .getText ( ) and
765
761
// only print indices when the arity is > 1
766
- if exists ( getVariantTupleField ( v , 1 ) ) then result = name + "(" + pos_ + ")" else result = name
762
+ if exists ( v . getTupleField ( 1 ) ) then result = name + "(" + pos_ + ")" else result = name
767
763
)
768
764
}
769
765
770
- final override Location getLocation ( ) { result = getVariantTupleField ( v , pos_ ) .getLocation ( ) }
771
- }
772
-
773
- private RecordField getVariantRecordField ( Variant v , string field ) {
774
- result = v .getFieldList ( ) .( RecordFieldList ) .getAField ( ) and
775
- field = result .getName ( ) .getText ( )
766
+ final override Location getLocation ( ) { result = v .getTupleField ( pos_ ) .getLocation ( ) }
776
767
}
777
768
778
769
/** A record variant. */
@@ -788,34 +779,56 @@ private class VariantRecordFieldContent extends VariantContent, TVariantRecordFi
788
779
exists ( string name |
789
780
name = v .getName ( ) .getText ( ) and
790
781
// only print field when the arity is > 1
791
- if strictcount ( string f | exists ( getVariantRecordField ( v , f ) ) ) > 1
782
+ if strictcount ( v . getRecordField ( _ ) ) > 1
792
783
then result = name + "{" + field_ + "}"
793
784
else result = name
794
785
)
795
786
}
796
787
797
788
final override Location getLocation ( ) {
798
- result = getVariantRecordField ( v , field_ ) .getName ( ) .getLocation ( )
789
+ result = v . getRecordField ( field_ ) .getName ( ) .getLocation ( )
799
790
}
800
791
}
801
792
802
- /** Content stored in a field on a struct. */
803
- class StructFieldContent extends Content , TStructFieldContent {
793
+ abstract private class FieldContent extends Content {
794
+ pragma [ nomagic]
795
+ abstract FieldExprCfgNode getAnAccess ( ) ;
796
+ }
797
+
798
+ /** Content stored in a tuple field on a struct. */
799
+ private class StructTupleFieldContent extends FieldContent , TStructTupleFieldContent {
800
+ private Struct s ;
801
+ private int pos_ ;
802
+
803
+ StructTupleFieldContent ( ) { this = TStructTupleFieldContent ( s , pos_ ) }
804
+
805
+ Struct getStruct ( int pos ) { result = s and pos = pos_ }
806
+
807
+ override FieldExprCfgNode getAnAccess ( ) {
808
+ s .getTupleField ( pos_ ) = result .getFieldExpr ( ) .getTupleField ( )
809
+ }
810
+
811
+ override string toString ( ) { result = s .getName ( ) .getText ( ) + "." + pos_ .toString ( ) }
812
+
813
+ override Location getLocation ( ) { result = s .getTupleField ( pos_ ) .getLocation ( ) }
814
+ }
815
+
816
+ /** Content stored in a record field on a struct. */
817
+ class StructRecordFieldContent extends FieldContent , TStructRecordFieldContent {
804
818
private Struct s ;
805
819
private string field_ ;
806
820
807
- StructFieldContent ( ) { this = TStructFieldContent ( s , field_ ) }
821
+ StructRecordFieldContent ( ) { this = TStructRecordFieldContent ( s , field_ ) }
808
822
809
823
Struct getStruct ( string field ) { result = s and field = field_ }
810
824
825
+ override FieldExprCfgNode getAnAccess ( ) {
826
+ s .getRecordField ( field_ ) = result .getFieldExpr ( ) .getRecordField ( )
827
+ }
828
+
811
829
override string toString ( ) { result = s .getName ( ) .getText ( ) + "." + field_ .toString ( ) }
812
830
813
- override Location getLocation ( ) {
814
- exists ( Name f | f = s .getFieldList ( ) .( RecordFieldList ) .getAField ( ) .getName ( ) |
815
- f .getText ( ) = field_ and
816
- result = f .getLocation ( )
817
- )
818
- }
831
+ override Location getLocation ( ) { result = s .getRecordField ( field_ ) .getName ( ) .getLocation ( ) }
819
832
}
820
833
821
834
/** A captured variable. */
@@ -859,23 +872,23 @@ final class ElementContent extends Content, TElementContent {
859
872
* NOTE: Unlike `struct`s and `enum`s tuples are structural and not nominal,
860
873
* hence we don't store a canonical path for them.
861
874
*/
862
- final class TuplePositionContent extends Content , TTuplePositionContent {
875
+ final class TuplePositionContent extends FieldContent , TTuplePositionContent {
863
876
private int pos ;
864
877
865
878
TuplePositionContent ( ) { this = TTuplePositionContent ( pos ) }
866
879
867
880
int getPosition ( ) { result = pos }
868
881
882
+ override FieldExprCfgNode getAnAccess ( ) {
883
+ // todo: limit to tuple types
884
+ result .getNameRef ( ) .getText ( ) .toInt ( ) = pos
885
+ }
886
+
869
887
override string toString ( ) { result = "tuple." + pos .toString ( ) }
870
888
871
889
override Location getLocation ( ) { result instanceof EmptyLocation }
872
890
}
873
891
874
- /** Holds if `access` indexes a tuple at an index corresponding to `c`. */
875
- private predicate fieldTuplePositionContent ( FieldExprCfgNode access , TuplePositionContent c ) {
876
- access .getNameRef ( ) .getText ( ) .toInt ( ) = c .getPosition ( )
877
- }
878
-
879
892
/** A value that represents a set of `Content`s. */
880
893
abstract class ContentSet extends TContentSet {
881
894
/** Gets a textual representation of this element. */
@@ -1107,6 +1120,10 @@ module RustDataFlow implements InputSig<Location> {
1107
1120
pragma [ nomagic]
1108
1121
private predicate tupleVariantDestruction ( TupleStructPat p , Variant v ) { v = resolvePath ( p ) }
1109
1122
1123
+ /** Holds if `p` destructs an struct `s`. */
1124
+ pragma [ nomagic]
1125
+ private predicate tupleStructDestruction ( TupleStructPat p , Struct s ) { s = resolvePath ( p ) }
1126
+
1110
1127
/** Holds if `p` destructs an enum variant `v`. */
1111
1128
pragma [ nomagic]
1112
1129
private predicate recordVariantDestruction ( RecordPat p , Variant v ) { v = resolvePath ( p ) }
@@ -1128,6 +1145,10 @@ module RustDataFlow implements InputSig<Location> {
1128
1145
|
1129
1146
tupleVariantDestruction ( pat .getPat ( ) , c .( VariantTupleFieldContent ) .getVariant ( pos ) )
1130
1147
or
1148
+ tupleStructDestruction ( pat .getPat ( ) , c .( StructTupleFieldContent ) .getStruct ( pos ) )
1149
+ or
1150
+ tupleStructDestruction ( pat .getPat ( ) , c .( StructTupleFieldContent ) .getStruct ( pos ) )
1151
+ or
1131
1152
VariantInLib:: tupleVariantCanonicalDestruction ( pat .getPat ( ) , c , pos )
1132
1153
)
1133
1154
or
@@ -1144,7 +1165,7 @@ module RustDataFlow implements InputSig<Location> {
1144
1165
recordVariantDestruction ( pat .getPat ( ) , c .( VariantRecordFieldContent ) .getVariant ( field ) )
1145
1166
or
1146
1167
// Pattern destructs a struct.
1147
- structDestruction ( pat .getPat ( ) , c .( StructFieldContent ) .getStruct ( field ) )
1168
+ structDestruction ( pat .getPat ( ) , c .( StructRecordFieldContent ) .getStruct ( field ) )
1148
1169
) and
1149
1170
node2 .asPat ( ) = pat .getFieldPat ( field )
1150
1171
)
@@ -1153,11 +1174,9 @@ module RustDataFlow implements InputSig<Location> {
1153
1174
node1 .asPat ( ) .( RefPatCfgNode ) .getPat ( ) = node2 .asPat ( )
1154
1175
or
1155
1176
exists ( FieldExprCfgNode access |
1156
- // Read of a tuple entry
1157
- fieldTuplePositionContent ( access , c ) and
1158
- // TODO: Handle read of a struct field.
1159
1177
node1 .asExpr ( ) = access .getExpr ( ) and
1160
- node2 .asExpr ( ) = access
1178
+ node2 .asExpr ( ) = access and
1179
+ access = c .( FieldContent ) .getAnAccess ( )
1161
1180
)
1162
1181
or
1163
1182
exists ( IndexExprCfgNode arr |
@@ -1213,12 +1232,13 @@ module RustDataFlow implements InputSig<Location> {
1213
1232
pragma [ nomagic]
1214
1233
private predicate structConstruction ( RecordExpr re , Struct s ) { s = resolvePath ( re ) }
1215
1234
1216
- private predicate tupleAssignment ( Node node1 , Node node2 , TuplePositionContent c ) {
1235
+ pragma [ nomagic]
1236
+ private predicate fieldAssignment ( Node node1 , Node node2 , FieldContent c ) {
1217
1237
exists ( AssignmentExprCfgNode assignment , FieldExprCfgNode access |
1218
1238
assignment .getLhs ( ) = access and
1219
- fieldTuplePositionContent ( access , c ) and
1220
1239
node1 .asExpr ( ) = assignment .getRhs ( ) and
1221
- node2 .asExpr ( ) = access .getExpr ( )
1240
+ node2 .asExpr ( ) = access .getExpr ( ) and
1241
+ access = c .getAnAccess ( )
1222
1242
)
1223
1243
}
1224
1244
@@ -1240,7 +1260,7 @@ module RustDataFlow implements InputSig<Location> {
1240
1260
c .( VariantRecordFieldContent ) .getVariant ( field ) )
1241
1261
or
1242
1262
// Expression is for a struct.
1243
- structConstruction ( re .getRecordExpr ( ) , c .( StructFieldContent ) .getStruct ( field ) )
1263
+ structConstruction ( re .getRecordExpr ( ) , c .( StructRecordFieldContent ) .getStruct ( field ) )
1244
1264
) and
1245
1265
node1 .asExpr ( ) = re .getFieldExpr ( field ) and
1246
1266
node2 .asExpr ( ) = re
@@ -1258,7 +1278,7 @@ module RustDataFlow implements InputSig<Location> {
1258
1278
node2 .asExpr ( ) .( ArrayListExprCfgNode ) .getAnExpr ( )
1259
1279
]
1260
1280
or
1261
- tupleAssignment ( node1 , node2 .( PostUpdateNode ) .getPreUpdateNode ( ) , c )
1281
+ fieldAssignment ( node1 , node2 .( PostUpdateNode ) .getPreUpdateNode ( ) , c )
1262
1282
or
1263
1283
exists ( AssignmentExprCfgNode assignment , IndexExprCfgNode index |
1264
1284
c instanceof ElementContent and
@@ -1294,7 +1314,7 @@ module RustDataFlow implements InputSig<Location> {
1294
1314
* in `x.f = newValue`.
1295
1315
*/
1296
1316
predicate clearsContent ( Node n , ContentSet cs ) {
1297
- tupleAssignment ( _, n , cs .( SingletonContentSet ) .getContent ( ) )
1317
+ fieldAssignment ( _, n , cs .( SingletonContentSet ) .getContent ( ) )
1298
1318
or
1299
1319
FlowSummaryImpl:: Private:: Steps:: summaryClearsContent ( n .( Node:: FlowSummaryNode ) .getSummaryNode ( ) ,
1300
1320
cs )
@@ -1600,10 +1620,10 @@ private module Cached {
1600
1620
1601
1621
cached
1602
1622
newtype TContent =
1603
- TVariantTupleFieldContent ( Variant v , int pos ) { exists ( getVariantTupleField ( v , pos ) ) } or
1623
+ TVariantTupleFieldContent ( Variant v , int pos ) { exists ( v . getTupleField ( pos ) ) } or
1604
1624
// TODO: Remove once library types are extracted
1605
1625
TVariantInLibTupleFieldContent ( VariantInLib:: VariantInLib v , int pos ) { pos = v .getAPosition ( ) } or
1606
- TVariantRecordFieldContent ( Variant v , string field ) { exists ( getVariantRecordField ( v , field ) ) } or
1626
+ TVariantRecordFieldContent ( Variant v , string field ) { exists ( v . getRecordField ( field ) ) } or
1607
1627
TElementContent ( ) or
1608
1628
TTuplePositionContent ( int pos ) {
1609
1629
pos in [ 0 .. max ( [
@@ -1612,9 +1632,8 @@ private module Cached {
1612
1632
]
1613
1633
) ]
1614
1634
} or
1615
- TStructFieldContent ( Struct s , string field ) {
1616
- field = s .getFieldList ( ) .( RecordFieldList ) .getAField ( ) .getName ( ) .getText ( )
1617
- } or
1635
+ TStructTupleFieldContent ( Struct s , int pos ) { exists ( s .getTupleField ( pos ) ) } or
1636
+ TStructRecordFieldContent ( Struct s , string field ) { exists ( s .getRecordField ( field ) ) } or
1618
1637
TCapturedVariableContent ( VariableCapture:: CapturedVariable v ) or
1619
1638
TReferenceContent ( )
1620
1639
0 commit comments