@@ -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,7 +506,7 @@ 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
484512 exists ( Path p , TypeMention tm |
@@ -576,7 +604,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
576604 }
577605 }
578606
579- abstract private class TupleDeclaration extends Declaration {
607+ abstract additional class TupleDeclaration extends Declaration {
580608 override Type getDeclaredType ( DeclarationPosition dpos , TypePath path ) {
581609 result = super .getDeclaredType ( dpos , path )
582610 or
@@ -1032,9 +1060,18 @@ private Type inferFieldExprType(AstNode n, TypePath path) {
10321060 )
10331061}
10341062
1035- /** Gets the root type of the reference expression `re `. */
1063+ /** Gets the root type of the reference node `ref `. */
10361064pragma [ 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+ }
10381075
10391076pragma [ nomagic]
10401077private Type inferTryExprType ( TryExpr te , TypePath path ) {
@@ -1178,6 +1215,120 @@ private Type inferIndexExprType(IndexExpr ie, TypePath path) {
11781215 )
11791216}
11801217
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+
11811332final private class ForIterableExpr extends Expr {
11821333 ForIterableExpr ( ) { this = any ( ForExpr fe ) .getIterable ( ) }
11831334
@@ -1813,7 +1964,7 @@ private module Cached {
18131964 or
18141965 result = inferFieldExprType ( n , path )
18151966 or
1816- result = inferRefExprType ( n ) and
1967+ result = inferRefNodeType ( n ) and
18171968 path .isEmpty ( )
18181969 or
18191970 result = inferTryExprType ( n , path )
@@ -1836,6 +1987,10 @@ private module Cached {
18361987 result = inferForLoopExprType ( n , path )
18371988 or
18381989 result = inferCastExprType ( n , path )
1990+ or
1991+ result = inferStructPatType ( n , path )
1992+ or
1993+ result = inferTupleStructPatType ( n , path )
18391994 }
18401995}
18411996
0 commit comments