@@ -231,6 +231,24 @@ private Type inferAssignmentOperationType(AstNode n, TypePath path) {
231231 result = TUnit ( )
232232}
233233
234+ pragma [ nomagic]
235+ private Struct getRangeType ( RangeExpr re ) {
236+ re instanceof RangeFromExpr and
237+ result instanceof RangeFromStruct
238+ or
239+ re instanceof RangeToExpr and
240+ result instanceof RangeToStruct
241+ or
242+ re instanceof RangeFromToExpr and
243+ result instanceof RangeStruct
244+ or
245+ re instanceof RangeInclusiveExpr and
246+ result instanceof RangeInclusiveStruct
247+ or
248+ re instanceof RangeToInclusiveExpr and
249+ result instanceof RangeToInclusiveStruct
250+ }
251+
234252/**
235253 * Holds if the type tree of `n1` at `prefix1` should be equal to the type tree
236254 * of `n2` at `prefix2` and type information should propagate in both directions
@@ -296,6 +314,13 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
296314 n1 .( ArrayRepeatExpr ) .getRepeatOperand ( ) = n2 and
297315 prefix1 = TypePath:: singleton ( TArrayTypeParameter ( ) ) and
298316 prefix2 .isEmpty ( )
317+ or
318+ exists ( Struct s |
319+ n2 = [ n1 .( RangeExpr ) .getStart ( ) , n1 .( RangeExpr ) .getEnd ( ) ] and
320+ prefix1 = TypePath:: singleton ( TTypeParamTypeParameter ( s .getGenericParamList ( ) .getATypeParam ( ) ) ) and
321+ prefix2 .isEmpty ( ) and
322+ s = getRangeType ( n1 )
323+ )
299324}
300325
301326pragma [ nomagic]
@@ -1062,7 +1087,7 @@ private TraitType inferAsyncBlockExprRootType(AsyncBlockExpr abe) {
10621087 result = getFutureTraitType ( )
10631088}
10641089
1065- final class AwaitTarget extends Expr {
1090+ final private class AwaitTarget extends Expr {
10661091 AwaitTarget ( ) { this = any ( AwaitExpr ae ) .getExpr ( ) }
10671092
10681093 Type getTypeAt ( TypePath path ) { result = inferType ( this , path ) }
@@ -1098,6 +1123,12 @@ private class Vec extends Struct {
10981123pragma [ nomagic]
10991124private Type inferArrayExprType ( ArrayExpr ae ) { exists ( ae ) and result = TArrayType ( ) }
11001125
1126+ /**
1127+ * Gets the root type of the range expression `re`.
1128+ */
1129+ pragma [ nomagic]
1130+ private Type inferRangeExprType ( RangeExpr re ) { result = TStruct ( getRangeType ( re ) ) }
1131+
11011132/**
11021133 * According to [the Rust reference][1]: _"array and slice-typed expressions
11031134 * can be indexed with a `usize` index ... For other types an index expression
@@ -1134,23 +1165,49 @@ private Type inferIndexExprType(IndexExpr ie, TypePath path) {
11341165 )
11351166}
11361167
1168+ final private class ForIterableExpr extends Expr {
1169+ ForIterableExpr ( ) { this = any ( ForExpr fe ) .getIterable ( ) }
1170+
1171+ Type getTypeAt ( TypePath path ) { result = inferType ( this , path ) }
1172+ }
1173+
1174+ private module ForIterableSatisfiesConstraintInput implements
1175+ SatisfiesConstraintInputSig< ForIterableExpr >
1176+ {
1177+ predicate relevantConstraint ( ForIterableExpr term , Type constraint ) {
1178+ exists ( term ) and
1179+ exists ( Trait t | t = constraint .( TraitType ) .getTrait ( ) |
1180+ // TODO: Remove the line below once we can handle the `impl<I: Iterator> IntoIterator for I` implementation
1181+ t instanceof IteratorTrait or
1182+ t instanceof IntoIteratorTrait
1183+ )
1184+ }
1185+ }
1186+
1187+ pragma [ nomagic]
1188+ private AssociatedTypeTypeParameter getIteratorItemTypeParameter ( ) {
1189+ result .getTypeAlias ( ) = any ( IteratorTrait t ) .getItemType ( )
1190+ }
1191+
1192+ pragma [ nomagic]
1193+ private AssociatedTypeTypeParameter getIntoIteratorItemTypeParameter ( ) {
1194+ result .getTypeAlias ( ) = any ( IntoIteratorTrait t ) .getItemType ( )
1195+ }
1196+
11371197pragma [ nomagic]
11381198private Type inferForLoopExprType ( AstNode n , TypePath path ) {
11391199 // type of iterable -> type of pattern (loop variable)
1140- exists ( ForExpr fe , Type iterableType , TypePath iterablePath |
1200+ exists ( ForExpr fe , TypePath exprPath , AssociatedTypeTypeParameter tp |
11411201 n = fe .getPat ( ) and
1142- iterableType = inferType ( fe .getIterable ( ) , iterablePath ) and
1143- result = iterableType and
1144- (
1145- iterablePath .isCons ( any ( Vec v ) .getElementTypeParameter ( ) , path )
1146- or
1147- iterablePath .isCons ( any ( ArrayTypeParameter tp ) , path )
1148- or
1149- iterablePath
1150- .stripPrefix ( TypePath:: cons ( TRefTypeParameter ( ) ,
1151- TypePath:: singleton ( any ( SliceTypeParameter tp ) ) ) ) = path
1152- // TODO: iterables (general case for containers, ranges etc)
1153- )
1202+ SatisfiesConstraint< ForIterableExpr , ForIterableSatisfiesConstraintInput > :: satisfiesConstraintType ( fe .getIterable ( ) ,
1203+ _, exprPath , result ) and
1204+ exprPath .isCons ( tp , path )
1205+ |
1206+ tp = getIntoIteratorItemTypeParameter ( )
1207+ or
1208+ // TODO: Remove once we can handle the `impl<I: Iterator> IntoIterator for I` implementation
1209+ tp = getIteratorItemTypeParameter ( ) and
1210+ inferType ( fe .getIterable ( ) ) != TArrayType ( )
11541211 )
11551212}
11561213
@@ -1589,6 +1646,9 @@ private module Cached {
15891646 result = inferArrayExprType ( n ) and
15901647 path .isEmpty ( )
15911648 or
1649+ result = inferRangeExprType ( n ) and
1650+ path .isEmpty ( )
1651+ or
15921652 result = inferIndexExprType ( n , path )
15931653 or
15941654 result = inferForLoopExprType ( n , path )
0 commit comments