@@ -276,6 +276,20 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
276
276
or
277
277
n1 = n2 .( MatchExpr ) .getAnArm ( ) .getExpr ( )
278
278
or
279
+ exists ( LetExpr let |
280
+ n1 = let .getScrutinee ( ) and
281
+ n2 = let .getPat ( )
282
+ )
283
+ or
284
+ exists ( MatchExpr me |
285
+ n1 = me .getScrutinee ( ) and
286
+ n2 = me .getAnArm ( ) .getPat ( )
287
+ )
288
+ or
289
+ n1 = n2 .( OrPat ) .getAPat ( )
290
+ or
291
+ n1 = n2 .( ParenPat ) .getPat ( )
292
+ or
279
293
exists ( BreakExpr break |
280
294
break .getExpr ( ) = n1 and
281
295
break .getTarget ( ) = n2 .( LoopExpr )
@@ -287,12 +301,18 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
287
301
)
288
302
or
289
303
n1 = n2 .( MacroExpr ) .getMacroCall ( ) .getMacroCallExpansion ( )
304
+ or
305
+ n1 = n2 .( MacroPat ) .getMacroCall ( ) .getMacroCallExpansion ( )
290
306
)
291
307
or
292
308
n1 = n2 .( RefExpr ) .getExpr ( ) and
293
309
prefix1 .isEmpty ( ) and
294
310
prefix2 = TypePath:: singleton ( TRefTypeParameter ( ) )
295
311
or
312
+ n1 = n2 .( RefPat ) .getPat ( ) and
313
+ prefix1 .isEmpty ( ) and
314
+ prefix2 = TypePath:: singleton ( TRefTypeParameter ( ) )
315
+ or
296
316
exists ( BlockExpr be |
297
317
n1 = be and
298
318
n2 = be .getStmtList ( ) .getTailExpr ( ) and
@@ -478,7 +498,7 @@ private module StructExprMatchingInput implements MatchingInputSig {
478
498
Type getInferredType ( AccessPosition apos , TypePath path ) {
479
499
result = inferType ( this .getNodeAt ( apos ) , path )
480
500
or
481
- // The struct type is supplied explicitly as a type qualifier, e.g.
501
+ // The struct/enum type is supplied explicitly as a type qualifier, e.g.
482
502
// `Foo<Bar>::Variant { ... }`.
483
503
apos .isStructPos ( ) and
484
504
exists ( Path p , TypeMention tm |
@@ -576,7 +596,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
576
596
}
577
597
}
578
598
579
- abstract private class TupleDeclaration extends Declaration {
599
+ abstract additional class TupleDeclaration extends Declaration {
580
600
override Type getDeclaredType ( DeclarationPosition dpos , TypePath path ) {
581
601
result = super .getDeclaredType ( dpos , path )
582
602
or
@@ -1178,6 +1198,120 @@ private Type inferIndexExprType(IndexExpr ie, TypePath path) {
1178
1198
)
1179
1199
}
1180
1200
1201
+ /**
1202
+ * A matching configuration for resolving types of struct patterns
1203
+ * like `let Foo { bar } = ...`.
1204
+ */
1205
+ private module StructPatMatchingInput implements MatchingInputSig {
1206
+ class DeclarationPosition = StructExprMatchingInput:: DeclarationPosition ;
1207
+
1208
+ class Declaration = StructExprMatchingInput:: Declaration ;
1209
+
1210
+ class AccessPosition = DeclarationPosition ;
1211
+
1212
+ class Access extends StructPat {
1213
+ Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) { none ( ) }
1214
+
1215
+ AstNode getNodeAt ( AccessPosition apos ) {
1216
+ result = this .getPatField ( apos .asFieldPos ( ) ) .getPat ( )
1217
+ or
1218
+ result = this and
1219
+ apos .isStructPos ( )
1220
+ }
1221
+
1222
+ Type getInferredType ( AccessPosition apos , TypePath path ) {
1223
+ result = inferType ( this .getNodeAt ( apos ) , path )
1224
+ or
1225
+ // The struct/enum type is supplied explicitly as a type qualifier, e.g.
1226
+ // `let Foo<Bar>::Variant { ... } = ...`.
1227
+ apos .isStructPos ( ) and
1228
+ exists ( Path p , TypeMention tm |
1229
+ p = this .getPath ( ) and
1230
+ if resolvePath ( p ) instanceof Variant then tm = p .getQualifier ( ) else tm = p
1231
+ |
1232
+ result = tm .resolveTypeAt ( path )
1233
+ )
1234
+ }
1235
+
1236
+ Declaration getTarget ( ) { result = resolvePath ( this .getPath ( ) ) }
1237
+ }
1238
+
1239
+ predicate accessDeclarationPositionMatch ( AccessPosition apos , DeclarationPosition dpos ) {
1240
+ apos = dpos
1241
+ }
1242
+ }
1243
+
1244
+ private module StructPatMatching = Matching< StructPatMatchingInput > ;
1245
+
1246
+ /**
1247
+ * Gets the type of `n` at `path`, where `n` is either a struct pattern or
1248
+ * a field pattern of a struct pattern.
1249
+ */
1250
+ pragma [ nomagic]
1251
+ private Type inferStructPatType ( AstNode n , TypePath path ) {
1252
+ exists ( StructPatMatchingInput:: Access a , StructPatMatchingInput:: AccessPosition apos |
1253
+ n = a .getNodeAt ( apos ) and
1254
+ result = StructPatMatching:: inferAccessType ( a , apos , path )
1255
+ )
1256
+ }
1257
+
1258
+ /**
1259
+ * A matching configuration for resolving types of tuple struct patterns
1260
+ * like `let Some(x) = ...`.
1261
+ */
1262
+ private module TupleStructPatMatchingInput implements MatchingInputSig {
1263
+ class DeclarationPosition = CallExprBaseMatchingInput:: DeclarationPosition ;
1264
+
1265
+ class Declaration = CallExprBaseMatchingInput:: TupleDeclaration ;
1266
+
1267
+ class AccessPosition = DeclarationPosition ;
1268
+
1269
+ class Access extends TupleStructPat {
1270
+ Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) { none ( ) }
1271
+
1272
+ AstNode getNodeAt ( AccessPosition apos ) {
1273
+ result = this .getField ( apos .asPosition ( ) )
1274
+ or
1275
+ result = this and
1276
+ apos .isSelf ( )
1277
+ }
1278
+
1279
+ Type getInferredType ( AccessPosition apos , TypePath path ) {
1280
+ result = inferType ( this .getNodeAt ( apos ) , path )
1281
+ or
1282
+ // The struct/enum type is supplied explicitly as a type qualifier, e.g.
1283
+ // `let Option::<Foo>(x) = ...`.
1284
+ apos .isSelf ( ) and
1285
+ exists ( Path p , TypeMention tm |
1286
+ p = this .getPath ( ) and
1287
+ if resolvePath ( p ) instanceof Variant then tm = p .getQualifier ( ) else tm = p
1288
+ |
1289
+ result = tm .resolveTypeAt ( path )
1290
+ )
1291
+ }
1292
+
1293
+ Declaration getTarget ( ) { result = resolvePath ( this .getPath ( ) ) }
1294
+ }
1295
+
1296
+ predicate accessDeclarationPositionMatch ( AccessPosition apos , DeclarationPosition dpos ) {
1297
+ apos = dpos
1298
+ }
1299
+ }
1300
+
1301
+ private module TupleStructPatMatching = Matching< TupleStructPatMatchingInput > ;
1302
+
1303
+ /**
1304
+ * Gets the type of `n` at `path`, where `n` is either a tuple struct pattern or
1305
+ * a positional pattern of a tuple struct pattern.
1306
+ */
1307
+ pragma [ nomagic]
1308
+ private Type inferTupleStructPatType ( AstNode n , TypePath path ) {
1309
+ exists ( TupleStructPatMatchingInput:: Access a , TupleStructPatMatchingInput:: AccessPosition apos |
1310
+ n = a .getNodeAt ( apos ) and
1311
+ result = TupleStructPatMatching:: inferAccessType ( a , apos , path )
1312
+ )
1313
+ }
1314
+
1181
1315
final private class ForIterableExpr extends Expr {
1182
1316
ForIterableExpr ( ) { this = any ( ForExpr fe ) .getIterable ( ) }
1183
1317
@@ -1836,6 +1970,10 @@ private module Cached {
1836
1970
result = inferForLoopExprType ( n , path )
1837
1971
or
1838
1972
result = inferCastExprType ( n , path )
1973
+ or
1974
+ result = inferStructPatType ( n , path )
1975
+ or
1976
+ result = inferTupleStructPatType ( n , path )
1839
1977
}
1840
1978
}
1841
1979
0 commit comments