@@ -103,6 +103,13 @@ private module Input1 implements InputSig1<Location> {
103103 node = tp0 .( SelfTypeParameter ) .getTrait ( ) or
104104 node = tp0 .( ImplTraitTypeTypeParameter ) .getImplTraitTypeRepr ( )
105105 )
106+ or
107+ exists ( TupleTypeParameter ttp , int maxArity |
108+ maxArity = max ( int i | i = any ( TupleType tt ) .getArity ( ) ) and
109+ tp0 = ttp and
110+ kind = 2 and
111+ id = ttp .getTupleType ( ) .getArity ( ) * maxArity + ttp .getIndex ( )
112+ )
106113 |
107114 tp0 order by kind , id
108115 )
@@ -229,7 +236,7 @@ private Type inferLogicalOperationType(AstNode n, TypePath path) {
229236private Type inferAssignmentOperationType ( AstNode n , TypePath path ) {
230237 n instanceof AssignmentOperation and
231238 path .isEmpty ( ) and
232- result = TUnit ( )
239+ result instanceof UnitType
233240}
234241
235242pragma [ nomagic]
@@ -321,6 +328,17 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
321328 prefix1 .isEmpty ( ) and
322329 prefix2 = TypePath:: singleton ( TRefTypeParameter ( ) )
323330 or
331+ exists ( int i , int arity |
332+ prefix1 .isEmpty ( ) and
333+ prefix2 = TypePath:: singleton ( TTupleTypeParameter ( arity , i ) )
334+ |
335+ arity = n2 .( TupleExpr ) .getNumberOfFields ( ) and
336+ n1 = n2 .( TupleExpr ) .getField ( i )
337+ or
338+ arity = n2 .( TuplePat ) .getTupleArity ( ) and
339+ n1 = n2 .( TuplePat ) .getField ( i )
340+ )
341+ or
324342 exists ( BlockExpr be |
325343 n1 = be and
326344 n2 = be .getStmtList ( ) .getTailExpr ( ) and
@@ -534,6 +552,12 @@ private Type inferStructExprType(AstNode n, TypePath path) {
534552 )
535553}
536554
555+ pragma [ nomagic]
556+ private Type inferTupleRootType ( AstNode n ) {
557+ // `typeEquality` handles the non-root cases
558+ result = TTuple ( [ n .( TupleExpr ) .getNumberOfFields ( ) , n .( TuplePat ) .getTupleArity ( ) ] )
559+ }
560+
537561pragma [ nomagic]
538562private Type inferPathExprType ( PathExpr pe , TypePath path ) {
539563 // nullary struct/variant constructors
@@ -1055,6 +1079,42 @@ private Type inferFieldExprType(AstNode n, TypePath path) {
10551079 )
10561080}
10571081
1082+ pragma [ nomagic]
1083+ private Type inferTupleIndexExprType ( FieldExpr fe , TypePath path ) {
1084+ exists ( int i , TypePath path0 |
1085+ fe .getIdentifier ( ) .getText ( ) = i .toString ( ) and
1086+ result = inferType ( fe .getContainer ( ) , path0 ) and
1087+ path0 .isCons ( TTupleTypeParameter ( _, i ) , path ) and
1088+ fe .getIdentifier ( ) .getText ( ) = i .toString ( )
1089+ )
1090+ }
1091+
1092+ /** Infers the type of `t` in `t.n` when `t` is a tuple. */
1093+ private Type inferTupleContainerExprType ( Expr e , TypePath path ) {
1094+ // NOTE: For a field expression `t.n` where `n` is a number `t` might be a
1095+ // tuple as in:
1096+ // ```rust
1097+ // let t = (Default::default(), 2);
1098+ // let s: String = t.0;
1099+ // ```
1100+ // But it could also be a tuple struct as in:
1101+ // ```rust
1102+ // struct T(String, u32);
1103+ // let t = T(Default::default(), 2);
1104+ // let s: String = t.0;
1105+ // ```
1106+ // We need type information to flow from `t.n` to tuple type parameters of `t`
1107+ // in the former case but not the latter case. Hence we include the condition
1108+ // that the root type of `t` must be a tuple type.
1109+ exists ( int i , TypePath path0 , FieldExpr fe , int arity |
1110+ e = fe .getContainer ( ) and
1111+ fe .getIdentifier ( ) .getText ( ) = i .toString ( ) and
1112+ arity = inferType ( fe .getContainer ( ) ) .( TupleType ) .getArity ( ) and
1113+ result = inferType ( fe , path0 ) and
1114+ path = TypePath:: cons ( TTupleTypeParameter ( arity , i ) , path0 )
1115+ )
1116+ }
1117+
10581118/** Gets the root type of the reference node `ref`. */
10591119pragma [ nomagic]
10601120private Type inferRefNodeType ( AstNode ref ) {
@@ -1943,12 +2003,19 @@ private module Cached {
19432003 or
19442004 result = inferStructExprType ( n , path )
19452005 or
2006+ result = inferTupleRootType ( n ) and
2007+ path .isEmpty ( )
2008+ or
19462009 result = inferPathExprType ( n , path )
19472010 or
19482011 result = inferCallExprBaseType ( n , path )
19492012 or
19502013 result = inferFieldExprType ( n , path )
19512014 or
2015+ result = inferTupleIndexExprType ( n , path )
2016+ or
2017+ result = inferTupleContainerExprType ( n , path )
2018+ or
19522019 result = inferRefNodeType ( n ) and
19532020 path .isEmpty ( )
19542021 or
0 commit comments