@@ -260,7 +260,7 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
260260 prefix2 .isEmpty ( ) and
261261 (
262262 exists ( Variable v | n1 = v .getAnAccess ( ) |
263- n2 = v .getPat ( )
263+ n2 = v .getPat ( ) . getName ( )
264264 or
265265 n2 = v .getParameter ( ) .( SelfParam )
266266 )
@@ -276,6 +276,22 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
276276 or
277277 n1 = n2 .( MatchExpr ) .getAnArm ( ) .getExpr ( )
278278 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
279295 exists ( BreakExpr break |
280296 break .getExpr ( ) = n1 and
281297 break .getTarget ( ) = n2 .( LoopExpr )
@@ -287,9 +303,21 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
287303 )
288304 or
289305 n1 = n2 .( MacroExpr ) .getMacroCall ( ) .getMacroCallExpansion ( )
306+ or
307+ n1 = n2 .( MacroPat ) .getMacroCall ( ) .getMacroCallExpansion ( )
290308 )
291309 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
293321 prefix1 .isEmpty ( ) and
294322 prefix2 = TypePath:: singleton ( TRefTypeParameter ( ) )
295323 or
@@ -478,15 +506,10 @@ private module StructExprMatchingInput implements MatchingInputSig {
478506 Type getInferredType ( AccessPosition apos , TypePath path ) {
479507 result = inferType ( this .getNodeAt ( apos ) , path )
480508 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.
482510 // `Foo<Bar>::Variant { ... }`.
483511 apos .isStructPos ( ) and
484- exists ( Path p , TypeMention tm |
485- p = this .getPath ( ) and
486- if resolvePath ( p ) instanceof Variant then tm = p .getQualifier ( ) else tm = p
487- |
488- result = tm .resolveTypeAt ( path )
489- )
512+ result = this .getPath ( ) .( TypeMention ) .resolveTypeAt ( path )
490513 }
491514
492515 Declaration getTarget ( ) { result = resolvePath ( this .getPath ( ) ) }
@@ -576,7 +599,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
576599 }
577600 }
578601
579- abstract private class TupleDeclaration extends Declaration {
602+ abstract additional class TupleDeclaration extends Declaration {
580603 override Type getDeclaredType ( DeclarationPosition dpos , TypePath path ) {
581604 result = super .getDeclaredType ( dpos , path )
582605 or
@@ -1032,9 +1055,18 @@ private Type inferFieldExprType(AstNode n, TypePath path) {
10321055 )
10331056}
10341057
1035- /** Gets the root type of the reference expression `re `. */
1058+ /** Gets the root type of the reference node `ref `. */
10361059pragma [ nomagic]
1037- private Type inferRefExprType ( RefExpr re ) { exists ( re ) and result = TRefType ( ) }
1060+ private Type inferRefNodeType ( AstNode ref ) {
1061+ (
1062+ ref = any ( IdentPat ip | ip .isRef ( ) ) .getName ( )
1063+ or
1064+ ref instanceof RefExpr
1065+ or
1066+ ref instanceof RefPat
1067+ ) and
1068+ result = TRefType ( )
1069+ }
10381070
10391071pragma [ nomagic]
10401072private Type inferTryExprType ( TryExpr te , TypePath path ) {
@@ -1178,6 +1210,110 @@ private Type inferIndexExprType(IndexExpr ie, TypePath path) {
11781210 )
11791211}
11801212
1213+ /**
1214+ * A matching configuration for resolving types of struct patterns
1215+ * like `let Foo { bar } = ...`.
1216+ */
1217+ private module StructPatMatchingInput implements MatchingInputSig {
1218+ class DeclarationPosition = StructExprMatchingInput:: DeclarationPosition ;
1219+
1220+ class Declaration = StructExprMatchingInput:: Declaration ;
1221+
1222+ class AccessPosition = DeclarationPosition ;
1223+
1224+ class Access extends StructPat {
1225+ Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) { none ( ) }
1226+
1227+ AstNode getNodeAt ( AccessPosition apos ) {
1228+ result = this .getPatField ( apos .asFieldPos ( ) ) .getPat ( )
1229+ or
1230+ result = this and
1231+ apos .isStructPos ( )
1232+ }
1233+
1234+ Type getInferredType ( AccessPosition apos , TypePath path ) {
1235+ result = inferType ( this .getNodeAt ( apos ) , path )
1236+ or
1237+ // The struct/enum type is supplied explicitly as a type qualifier, e.g.
1238+ // `let Foo<Bar>::Variant { ... } = ...`.
1239+ apos .isStructPos ( ) and
1240+ result = this .getPath ( ) .( TypeMention ) .resolveTypeAt ( path )
1241+ }
1242+
1243+ Declaration getTarget ( ) { result = resolvePath ( this .getPath ( ) ) }
1244+ }
1245+
1246+ predicate accessDeclarationPositionMatch ( AccessPosition apos , DeclarationPosition dpos ) {
1247+ apos = dpos
1248+ }
1249+ }
1250+
1251+ private module StructPatMatching = Matching< StructPatMatchingInput > ;
1252+
1253+ /**
1254+ * Gets the type of `n` at `path`, where `n` is either a struct pattern or
1255+ * a field pattern of a struct pattern.
1256+ */
1257+ pragma [ nomagic]
1258+ private Type inferStructPatType ( AstNode n , TypePath path ) {
1259+ exists ( StructPatMatchingInput:: Access a , StructPatMatchingInput:: AccessPosition apos |
1260+ n = a .getNodeAt ( apos ) and
1261+ result = StructPatMatching:: inferAccessType ( a , apos , path )
1262+ )
1263+ }
1264+
1265+ /**
1266+ * A matching configuration for resolving types of tuple struct patterns
1267+ * like `let Some(x) = ...`.
1268+ */
1269+ private module TupleStructPatMatchingInput implements MatchingInputSig {
1270+ class DeclarationPosition = CallExprBaseMatchingInput:: DeclarationPosition ;
1271+
1272+ class Declaration = CallExprBaseMatchingInput:: TupleDeclaration ;
1273+
1274+ class AccessPosition = DeclarationPosition ;
1275+
1276+ class Access extends TupleStructPat {
1277+ Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) { none ( ) }
1278+
1279+ AstNode getNodeAt ( AccessPosition apos ) {
1280+ result = this .getField ( apos .asPosition ( ) )
1281+ or
1282+ result = this and
1283+ apos .isSelf ( )
1284+ }
1285+
1286+ Type getInferredType ( AccessPosition apos , TypePath path ) {
1287+ result = inferType ( this .getNodeAt ( apos ) , path )
1288+ or
1289+ // The struct/enum type is supplied explicitly as a type qualifier, e.g.
1290+ // `let Option::<Foo>::Some(x) = ...`.
1291+ apos .isSelf ( ) and
1292+ result = this .getPath ( ) .( TypeMention ) .resolveTypeAt ( path )
1293+ }
1294+
1295+ Declaration getTarget ( ) { result = resolvePath ( this .getPath ( ) ) }
1296+ }
1297+
1298+ predicate accessDeclarationPositionMatch ( AccessPosition apos , DeclarationPosition dpos ) {
1299+ apos = dpos
1300+ }
1301+ }
1302+
1303+ private module TupleStructPatMatching = Matching< TupleStructPatMatchingInput > ;
1304+
1305+ /**
1306+ * Gets the type of `n` at `path`, where `n` is either a tuple struct pattern or
1307+ * a positional pattern of a tuple struct pattern.
1308+ */
1309+ pragma [ nomagic]
1310+ private Type inferTupleStructPatType ( AstNode n , TypePath path ) {
1311+ exists ( TupleStructPatMatchingInput:: Access a , TupleStructPatMatchingInput:: AccessPosition apos |
1312+ n = a .getNodeAt ( apos ) and
1313+ result = TupleStructPatMatching:: inferAccessType ( a , apos , path )
1314+ )
1315+ }
1316+
11811317final private class ForIterableExpr extends Expr {
11821318 ForIterableExpr ( ) { this = any ( ForExpr fe ) .getIterable ( ) }
11831319
@@ -1813,7 +1949,7 @@ private module Cached {
18131949 or
18141950 result = inferFieldExprType ( n , path )
18151951 or
1816- result = inferRefExprType ( n ) and
1952+ result = inferRefNodeType ( n ) and
18171953 path .isEmpty ( )
18181954 or
18191955 result = inferTryExprType ( n , path )
@@ -1836,6 +1972,10 @@ private module Cached {
18361972 result = inferForLoopExprType ( n , path )
18371973 or
18381974 result = inferCastExprType ( n , path )
1975+ or
1976+ result = inferStructPatType ( n , path )
1977+ or
1978+ result = inferTupleStructPatType ( n , path )
18391979 }
18401980}
18411981
0 commit comments