@@ -260,7 +260,7 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
260
260
prefix2 .isEmpty ( ) and
261
261
(
262
262
exists ( Variable v | n1 = v .getAnAccess ( ) |
263
- n2 = v .getPat ( )
263
+ n2 = v .getPat ( ) . getName ( )
264
264
or
265
265
n2 = v .getParameter ( ) .( SelfParam )
266
266
)
@@ -276,6 +276,22 @@ 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
293
+ n1 = n2 .( LiteralPat ) .getLiteral ( )
294
+ or
279
295
exists ( BreakExpr break |
280
296
break .getExpr ( ) = n1 and
281
297
break .getTarget ( ) = n2 .( LoopExpr )
@@ -287,9 +303,21 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
287
303
)
288
304
or
289
305
n1 = n2 .( MacroExpr ) .getMacroCall ( ) .getMacroCallExpansion ( )
306
+ or
307
+ n1 = n2 .( MacroPat ) .getMacroCall ( ) .getMacroCallExpansion ( )
290
308
)
291
309
or
292
- n1 = n2 .( RefExpr ) .getExpr ( ) and
310
+ n1 =
311
+ any ( IdentPat ip |
312
+ n2 = ip .getName ( ) and
313
+ prefix1 .isEmpty ( ) and
314
+ if ip .isRef ( ) then prefix2 = TypePath:: singleton ( TRefTypeParameter ( ) ) else prefix2 .isEmpty ( )
315
+ )
316
+ or
317
+ (
318
+ n1 = n2 .( RefExpr ) .getExpr ( ) or
319
+ n1 = n2 .( RefPat ) .getPat ( )
320
+ ) and
293
321
prefix1 .isEmpty ( ) and
294
322
prefix2 = TypePath:: singleton ( TRefTypeParameter ( ) )
295
323
or
@@ -478,7 +506,7 @@ private module StructExprMatchingInput implements MatchingInputSig {
478
506
Type getInferredType ( AccessPosition apos , TypePath path ) {
479
507
result = inferType ( this .getNodeAt ( apos ) , path )
480
508
or
481
- // The struct type is supplied explicitly as a type qualifier, e.g.
509
+ // The struct/enum type is supplied explicitly as a type qualifier, e.g.
482
510
// `Foo<Bar>::Variant { ... }`.
483
511
apos .isStructPos ( ) and
484
512
exists ( Path p , TypeMention tm |
@@ -576,7 +604,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
576
604
}
577
605
}
578
606
579
- abstract private class TupleDeclaration extends Declaration {
607
+ abstract additional class TupleDeclaration extends Declaration {
580
608
override Type getDeclaredType ( DeclarationPosition dpos , TypePath path ) {
581
609
result = super .getDeclaredType ( dpos , path )
582
610
or
@@ -1032,9 +1060,18 @@ private Type inferFieldExprType(AstNode n, TypePath path) {
1032
1060
)
1033
1061
}
1034
1062
1035
- /** Gets the root type of the reference expression `re `. */
1063
+ /** Gets the root type of the reference node `ref `. */
1036
1064
pragma [ nomagic]
1037
- private Type inferRefExprType ( RefExpr re ) { exists ( re ) and result = TRefType ( ) }
1065
+ private Type inferRefNodeType ( AstNode ref ) {
1066
+ (
1067
+ ref = any ( IdentPat ip | ip .isRef ( ) ) .getName ( )
1068
+ or
1069
+ ref instanceof RefExpr
1070
+ or
1071
+ ref instanceof RefPat
1072
+ ) and
1073
+ result = TRefType ( )
1074
+ }
1038
1075
1039
1076
pragma [ nomagic]
1040
1077
private Type inferTryExprType ( TryExpr te , TypePath path ) {
@@ -1178,6 +1215,120 @@ private Type inferIndexExprType(IndexExpr ie, TypePath path) {
1178
1215
)
1179
1216
}
1180
1217
1218
+ /**
1219
+ * A matching configuration for resolving types of struct patterns
1220
+ * like `let Foo { bar } = ...`.
1221
+ */
1222
+ private module StructPatMatchingInput implements MatchingInputSig {
1223
+ class DeclarationPosition = StructExprMatchingInput:: DeclarationPosition ;
1224
+
1225
+ class Declaration = StructExprMatchingInput:: Declaration ;
1226
+
1227
+ class AccessPosition = DeclarationPosition ;
1228
+
1229
+ class Access extends StructPat {
1230
+ Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) { none ( ) }
1231
+
1232
+ AstNode getNodeAt ( AccessPosition apos ) {
1233
+ result = this .getPatField ( apos .asFieldPos ( ) ) .getPat ( )
1234
+ or
1235
+ result = this and
1236
+ apos .isStructPos ( )
1237
+ }
1238
+
1239
+ Type getInferredType ( AccessPosition apos , TypePath path ) {
1240
+ result = inferType ( this .getNodeAt ( apos ) , path )
1241
+ or
1242
+ // The struct/enum type is supplied explicitly as a type qualifier, e.g.
1243
+ // `let Foo<Bar>::Variant { ... } = ...`.
1244
+ apos .isStructPos ( ) and
1245
+ exists ( Path p , TypeMention tm |
1246
+ p = this .getPath ( ) and
1247
+ if resolvePath ( p ) instanceof Variant then tm = p .getQualifier ( ) else tm = p
1248
+ |
1249
+ result = tm .resolveTypeAt ( path )
1250
+ )
1251
+ }
1252
+
1253
+ Declaration getTarget ( ) { result = resolvePath ( this .getPath ( ) ) }
1254
+ }
1255
+
1256
+ predicate accessDeclarationPositionMatch ( AccessPosition apos , DeclarationPosition dpos ) {
1257
+ apos = dpos
1258
+ }
1259
+ }
1260
+
1261
+ private module StructPatMatching = Matching< StructPatMatchingInput > ;
1262
+
1263
+ /**
1264
+ * Gets the type of `n` at `path`, where `n` is either a struct pattern or
1265
+ * a field pattern of a struct pattern.
1266
+ */
1267
+ pragma [ nomagic]
1268
+ private Type inferStructPatType ( AstNode n , TypePath path ) {
1269
+ exists ( StructPatMatchingInput:: Access a , StructPatMatchingInput:: AccessPosition apos |
1270
+ n = a .getNodeAt ( apos ) and
1271
+ result = StructPatMatching:: inferAccessType ( a , apos , path )
1272
+ )
1273
+ }
1274
+
1275
+ /**
1276
+ * A matching configuration for resolving types of tuple struct patterns
1277
+ * like `let Some(x) = ...`.
1278
+ */
1279
+ private module TupleStructPatMatchingInput implements MatchingInputSig {
1280
+ class DeclarationPosition = CallExprBaseMatchingInput:: DeclarationPosition ;
1281
+
1282
+ class Declaration = CallExprBaseMatchingInput:: TupleDeclaration ;
1283
+
1284
+ class AccessPosition = DeclarationPosition ;
1285
+
1286
+ class Access extends TupleStructPat {
1287
+ Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) { none ( ) }
1288
+
1289
+ AstNode getNodeAt ( AccessPosition apos ) {
1290
+ result = this .getField ( apos .asPosition ( ) )
1291
+ or
1292
+ result = this and
1293
+ apos .isSelf ( )
1294
+ }
1295
+
1296
+ Type getInferredType ( AccessPosition apos , TypePath path ) {
1297
+ result = inferType ( this .getNodeAt ( apos ) , path )
1298
+ or
1299
+ // The struct/enum type is supplied explicitly as a type qualifier, e.g.
1300
+ // `let Option::<Foo>(x) = ...`.
1301
+ apos .isSelf ( ) and
1302
+ exists ( Path p , TypeMention tm |
1303
+ p = this .getPath ( ) and
1304
+ if resolvePath ( p ) instanceof Variant then tm = p .getQualifier ( ) else tm = p
1305
+ |
1306
+ result = tm .resolveTypeAt ( path )
1307
+ )
1308
+ }
1309
+
1310
+ Declaration getTarget ( ) { result = resolvePath ( this .getPath ( ) ) }
1311
+ }
1312
+
1313
+ predicate accessDeclarationPositionMatch ( AccessPosition apos , DeclarationPosition dpos ) {
1314
+ apos = dpos
1315
+ }
1316
+ }
1317
+
1318
+ private module TupleStructPatMatching = Matching< TupleStructPatMatchingInput > ;
1319
+
1320
+ /**
1321
+ * Gets the type of `n` at `path`, where `n` is either a tuple struct pattern or
1322
+ * a positional pattern of a tuple struct pattern.
1323
+ */
1324
+ pragma [ nomagic]
1325
+ private Type inferTupleStructPatType ( AstNode n , TypePath path ) {
1326
+ exists ( TupleStructPatMatchingInput:: Access a , TupleStructPatMatchingInput:: AccessPosition apos |
1327
+ n = a .getNodeAt ( apos ) and
1328
+ result = TupleStructPatMatching:: inferAccessType ( a , apos , path )
1329
+ )
1330
+ }
1331
+
1181
1332
final private class ForIterableExpr extends Expr {
1182
1333
ForIterableExpr ( ) { this = any ( ForExpr fe ) .getIterable ( ) }
1183
1334
@@ -1813,7 +1964,7 @@ private module Cached {
1813
1964
or
1814
1965
result = inferFieldExprType ( n , path )
1815
1966
or
1816
- result = inferRefExprType ( n ) and
1967
+ result = inferRefNodeType ( n ) and
1817
1968
path .isEmpty ( )
1818
1969
or
1819
1970
result = inferTryExprType ( n , path )
@@ -1836,6 +1987,10 @@ private module Cached {
1836
1987
result = inferForLoopExprType ( n , path )
1837
1988
or
1838
1989
result = inferCastExprType ( n , path )
1990
+ or
1991
+ result = inferStructPatType ( n , path )
1992
+ or
1993
+ result = inferTupleStructPatType ( n , path )
1839
1994
}
1840
1995
}
1841
1996
0 commit comments