@@ -740,10 +740,6 @@ abstract class Content extends TContent {
740
740
*/
741
741
abstract class VariantContent extends Content { }
742
742
743
- private TupleField getVariantTupleField ( Variant v , int i ) {
744
- result = v .getFieldList ( ) .( TupleFieldList ) .getField ( i )
745
- }
746
-
747
743
/** A tuple variant. */
748
744
private class VariantTupleFieldContent extends VariantContent , TVariantTupleFieldContent {
749
745
private Variant v ;
@@ -757,16 +753,11 @@ private class VariantTupleFieldContent extends VariantContent, TVariantTupleFiel
757
753
exists ( string name |
758
754
name = v .getName ( ) .getText ( ) and
759
755
// only print indices when the arity is > 1
760
- if exists ( getVariantTupleField ( v , 1 ) ) then result = name + "(" + pos_ + ")" else result = name
756
+ if exists ( v . getTupleField ( 1 ) ) then result = name + "(" + pos_ + ")" else result = name
761
757
)
762
758
}
763
759
764
- final override Location getLocation ( ) { result = getVariantTupleField ( v , pos_ ) .getLocation ( ) }
765
- }
766
-
767
- private RecordField getVariantRecordField ( Variant v , string field ) {
768
- result = v .getFieldList ( ) .( RecordFieldList ) .getAField ( ) and
769
- field = result .getName ( ) .getText ( )
760
+ final override Location getLocation ( ) { result = v .getTupleField ( pos_ ) .getLocation ( ) }
770
761
}
771
762
772
763
/** A record variant. */
@@ -782,34 +773,56 @@ private class VariantRecordFieldContent extends VariantContent, TVariantRecordFi
782
773
exists ( string name |
783
774
name = v .getName ( ) .getText ( ) and
784
775
// only print field when the arity is > 1
785
- if strictcount ( string f | exists ( getVariantRecordField ( v , f ) ) ) > 1
776
+ if strictcount ( v . getRecordField ( _ ) ) > 1
786
777
then result = name + "{" + field_ + "}"
787
778
else result = name
788
779
)
789
780
}
790
781
791
782
final override Location getLocation ( ) {
792
- result = getVariantRecordField ( v , field_ ) .getName ( ) .getLocation ( )
783
+ result = v . getRecordField ( field_ ) .getName ( ) .getLocation ( )
793
784
}
794
785
}
795
786
796
- /** Content stored in a field on a struct. */
797
- private class StructFieldContent extends Content , TStructFieldContent {
787
+ abstract private class FieldContent extends Content {
788
+ pragma [ nomagic]
789
+ abstract FieldExprCfgNode getAnAccess ( ) ;
790
+ }
791
+
792
+ /** Content stored in a tuple field on a struct. */
793
+ private class StructTupleFieldContent extends FieldContent , TStructTupleFieldContent {
794
+ private Struct s ;
795
+ private int pos_ ;
796
+
797
+ StructTupleFieldContent ( ) { this = TStructTupleFieldContent ( s , pos_ ) }
798
+
799
+ Struct getStruct ( int pos ) { result = s and pos = pos_ }
800
+
801
+ override FieldExprCfgNode getAnAccess ( ) {
802
+ s .getTupleField ( pos_ ) = result .getFieldExpr ( ) .getTupleField ( )
803
+ }
804
+
805
+ override string toString ( ) { result = s .getName ( ) .getText ( ) + "." + pos_ .toString ( ) }
806
+
807
+ override Location getLocation ( ) { result = s .getTupleField ( pos_ ) .getLocation ( ) }
808
+ }
809
+
810
+ /** Content stored in a record field on a struct. */
811
+ private class StructRecordFieldContent extends FieldContent , TStructRecordFieldContent {
798
812
private Struct s ;
799
813
private string field_ ;
800
814
801
- StructFieldContent ( ) { this = TStructFieldContent ( s , field_ ) }
815
+ StructRecordFieldContent ( ) { this = TStructRecordFieldContent ( s , field_ ) }
802
816
803
817
Struct getStruct ( string field ) { result = s and field = field_ }
804
818
819
+ override FieldExprCfgNode getAnAccess ( ) {
820
+ s .getRecordField ( field_ ) = result .getFieldExpr ( ) .getRecordField ( )
821
+ }
822
+
805
823
override string toString ( ) { result = s .getName ( ) .getText ( ) + "." + field_ .toString ( ) }
806
824
807
- override Location getLocation ( ) {
808
- exists ( Name f | f = s .getFieldList ( ) .( RecordFieldList ) .getAField ( ) .getName ( ) |
809
- f .getText ( ) = field_ and
810
- result = f .getLocation ( )
811
- )
812
- }
825
+ override Location getLocation ( ) { result = s .getRecordField ( field_ ) .getName ( ) .getLocation ( ) }
813
826
}
814
827
815
828
/** A captured variable. */
@@ -853,23 +866,23 @@ final class ElementContent extends Content, TElementContent {
853
866
* NOTE: Unlike `struct`s and `enum`s tuples are structural and not nominal,
854
867
* hence we don't store a canonical path for them.
855
868
*/
856
- final class TuplePositionContent extends Content , TTuplePositionContent {
869
+ final class TuplePositionContent extends FieldContent , TTuplePositionContent {
857
870
private int pos ;
858
871
859
872
TuplePositionContent ( ) { this = TTuplePositionContent ( pos ) }
860
873
861
874
int getPosition ( ) { result = pos }
862
875
876
+ override FieldExprCfgNode getAnAccess ( ) {
877
+ // todo: limit to tuple types
878
+ result .getNameRef ( ) .getText ( ) .toInt ( ) = pos
879
+ }
880
+
863
881
override string toString ( ) { result = "tuple." + pos .toString ( ) }
864
882
865
883
override Location getLocation ( ) { result instanceof EmptyLocation }
866
884
}
867
885
868
- /** Holds if `access` indexes a tuple at an index corresponding to `c`. */
869
- private predicate fieldTuplePositionContent ( FieldExprCfgNode access , TuplePositionContent c ) {
870
- access .getNameRef ( ) .getText ( ) .toInt ( ) = c .getPosition ( )
871
- }
872
-
873
886
/** A value that represents a set of `Content`s. */
874
887
abstract class ContentSet extends TContentSet {
875
888
/** Gets a textual representation of this element. */
@@ -1101,6 +1114,10 @@ module RustDataFlow implements InputSig<Location> {
1101
1114
pragma [ nomagic]
1102
1115
private predicate tupleVariantDestruction ( TupleStructPat p , Variant v ) { v = resolvePath ( p ) }
1103
1116
1117
+ /** Holds if `p` destructs an struct `s`. */
1118
+ pragma [ nomagic]
1119
+ private predicate tupleStructDestruction ( TupleStructPat p , Struct s ) { s = resolvePath ( p ) }
1120
+
1104
1121
/** Holds if `p` destructs an enum variant `v`. */
1105
1122
pragma [ nomagic]
1106
1123
private predicate recordVariantDestruction ( RecordPat p , Variant v ) { v = resolvePath ( p ) }
@@ -1122,6 +1139,10 @@ module RustDataFlow implements InputSig<Location> {
1122
1139
|
1123
1140
tupleVariantDestruction ( pat .getPat ( ) , c .( VariantTupleFieldContent ) .getVariant ( pos ) )
1124
1141
or
1142
+ tupleStructDestruction ( pat .getPat ( ) , c .( StructTupleFieldContent ) .getStruct ( pos ) )
1143
+ or
1144
+ tupleStructDestruction ( pat .getPat ( ) , c .( StructTupleFieldContent ) .getStruct ( pos ) )
1145
+ or
1125
1146
VariantInLib:: tupleVariantCanonicalDestruction ( pat .getPat ( ) , c , pos )
1126
1147
)
1127
1148
or
@@ -1138,7 +1159,7 @@ module RustDataFlow implements InputSig<Location> {
1138
1159
recordVariantDestruction ( pat .getPat ( ) , c .( VariantRecordFieldContent ) .getVariant ( field ) )
1139
1160
or
1140
1161
// Pattern destructs a struct.
1141
- structDestruction ( pat .getPat ( ) , c .( StructFieldContent ) .getStruct ( field ) )
1162
+ structDestruction ( pat .getPat ( ) , c .( StructRecordFieldContent ) .getStruct ( field ) )
1142
1163
) and
1143
1164
node2 .asPat ( ) = pat .getFieldPat ( field )
1144
1165
)
@@ -1147,11 +1168,9 @@ module RustDataFlow implements InputSig<Location> {
1147
1168
node1 .asPat ( ) .( RefPatCfgNode ) .getPat ( ) = node2 .asPat ( )
1148
1169
or
1149
1170
exists ( FieldExprCfgNode access |
1150
- // Read of a tuple entry
1151
- fieldTuplePositionContent ( access , c ) and
1152
- // TODO: Handle read of a struct field.
1153
1171
node1 .asExpr ( ) = access .getExpr ( ) and
1154
- node2 .asExpr ( ) = access
1172
+ node2 .asExpr ( ) = access and
1173
+ access = c .( FieldContent ) .getAnAccess ( )
1155
1174
)
1156
1175
or
1157
1176
exists ( IndexExprCfgNode arr |
@@ -1207,12 +1226,13 @@ module RustDataFlow implements InputSig<Location> {
1207
1226
pragma [ nomagic]
1208
1227
private predicate structConstruction ( RecordExpr re , Struct s ) { s = resolvePath ( re ) }
1209
1228
1210
- private predicate tupleAssignment ( Node node1 , Node node2 , TuplePositionContent c ) {
1229
+ pragma [ nomagic]
1230
+ private predicate fieldAssignment ( Node node1 , Node node2 , FieldContent c ) {
1211
1231
exists ( AssignmentExprCfgNode assignment , FieldExprCfgNode access |
1212
1232
assignment .getLhs ( ) = access and
1213
- fieldTuplePositionContent ( access , c ) and
1214
1233
node1 .asExpr ( ) = assignment .getRhs ( ) and
1215
- node2 .asExpr ( ) = access .getExpr ( )
1234
+ node2 .asExpr ( ) = access .getExpr ( ) and
1235
+ access = c .getAnAccess ( )
1216
1236
)
1217
1237
}
1218
1238
@@ -1234,7 +1254,7 @@ module RustDataFlow implements InputSig<Location> {
1234
1254
c .( VariantRecordFieldContent ) .getVariant ( field ) )
1235
1255
or
1236
1256
// Expression is for a struct.
1237
- structConstruction ( re .getRecordExpr ( ) , c .( StructFieldContent ) .getStruct ( field ) )
1257
+ structConstruction ( re .getRecordExpr ( ) , c .( StructRecordFieldContent ) .getStruct ( field ) )
1238
1258
) and
1239
1259
node1 .asExpr ( ) = re .getFieldExpr ( field ) and
1240
1260
node2 .asExpr ( ) = re
@@ -1252,7 +1272,7 @@ module RustDataFlow implements InputSig<Location> {
1252
1272
node2 .asExpr ( ) .( ArrayListExprCfgNode ) .getAnExpr ( )
1253
1273
]
1254
1274
or
1255
- tupleAssignment ( node1 , node2 .( PostUpdateNode ) .getPreUpdateNode ( ) , c )
1275
+ fieldAssignment ( node1 , node2 .( PostUpdateNode ) .getPreUpdateNode ( ) , c )
1256
1276
or
1257
1277
exists ( AssignmentExprCfgNode assignment , IndexExprCfgNode index |
1258
1278
c instanceof ElementContent and
@@ -1288,7 +1308,7 @@ module RustDataFlow implements InputSig<Location> {
1288
1308
* in `x.f = newValue`.
1289
1309
*/
1290
1310
predicate clearsContent ( Node n , ContentSet cs ) {
1291
- tupleAssignment ( _, n , cs .( SingletonContentSet ) .getContent ( ) )
1311
+ fieldAssignment ( _, n , cs .( SingletonContentSet ) .getContent ( ) )
1292
1312
or
1293
1313
FlowSummaryImpl:: Private:: Steps:: summaryClearsContent ( n .( Node:: FlowSummaryNode ) .getSummaryNode ( ) ,
1294
1314
cs )
@@ -1594,10 +1614,10 @@ private module Cached {
1594
1614
1595
1615
cached
1596
1616
newtype TContent =
1597
- TVariantTupleFieldContent ( Variant v , int pos ) { exists ( getVariantTupleField ( v , pos ) ) } or
1617
+ TVariantTupleFieldContent ( Variant v , int pos ) { exists ( v . getTupleField ( pos ) ) } or
1598
1618
// TODO: Remove once library types are extracted
1599
1619
TVariantInLibTupleFieldContent ( VariantInLib:: VariantInLib v , int pos ) { pos = v .getAPosition ( ) } or
1600
- TVariantRecordFieldContent ( Variant v , string field ) { exists ( getVariantRecordField ( v , field ) ) } or
1620
+ TVariantRecordFieldContent ( Variant v , string field ) { exists ( v . getRecordField ( field ) ) } or
1601
1621
TElementContent ( ) or
1602
1622
TTuplePositionContent ( int pos ) {
1603
1623
pos in [ 0 .. max ( [
@@ -1606,9 +1626,8 @@ private module Cached {
1606
1626
]
1607
1627
) ]
1608
1628
} or
1609
- TStructFieldContent ( Struct s , string field ) {
1610
- field = s .getFieldList ( ) .( RecordFieldList ) .getAField ( ) .getName ( ) .getText ( )
1611
- } or
1629
+ TStructTupleFieldContent ( Struct s , int pos ) { exists ( s .getTupleField ( pos ) ) } or
1630
+ TStructRecordFieldContent ( Struct s , string field ) { exists ( s .getRecordField ( field ) ) } or
1612
1631
TCapturedVariableContent ( VariableCapture:: CapturedVariable v ) or
1613
1632
TReferenceContent ( )
1614
1633
0 commit comments