@@ -193,9 +193,7 @@ module LocalFlow {
193193 }
194194
195195 pragma [ nomagic]
196- predicate localFlowStepCommon ( Node nodeFrom , Node nodeTo ) {
197- nodeFrom .asExpr ( ) = getALastEvalNode ( nodeTo .asExpr ( ) )
198- or
196+ predicate localMustFlowStep ( Node nodeFrom , Node nodeTo ) {
199197 // An edge from the right-hand side of a let statement to the left-hand side.
200198 exists ( LetStmt s |
201199 nodeFrom .asExpr ( ) = s .getInitializer ( ) and
@@ -238,6 +236,15 @@ module LocalFlow {
238236 nodeTo .asPat ( ) = match .getAnArm ( ) .getPat ( )
239237 )
240238 or
239+ nodeFrom .asExpr ( ) = nodeTo .asExpr ( ) .( ParenExpr ) .getExpr ( )
240+ }
241+
242+ pragma [ nomagic]
243+ predicate localFlowStepCommon ( Node nodeFrom , Node nodeTo ) {
244+ localMustFlowStep ( nodeFrom , nodeTo )
245+ or
246+ nodeFrom .asExpr ( ) = getALastEvalNode ( nodeTo .asExpr ( ) )
247+ or
241248 nodeFrom .asPat ( ) .( OrPat ) .getAPat ( ) = nodeTo .asPat ( )
242249 or
243250 nodeTo .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) =
@@ -263,10 +270,84 @@ predicate lambdaCallExpr(CallExprImpl::DynamicCallExpr call, LambdaCallKind kind
263270 exists ( kind )
264271}
265272
273+ // NOTE: We do not yet track type information, except for closures where
274+ // we use the closure itself to represent the unique type.
275+ final class DataFlowType extends TDataFlowType {
276+ Expr asClosureExpr ( ) { this = TClosureExprType ( result ) }
277+
278+ predicate isUnknownType ( ) { this = TUnknownType ( ) }
279+
280+ predicate isSourceContextParameterType ( ) { this = TSourceContextParameterType ( ) }
281+
282+ string toString ( ) {
283+ exists ( this .asClosureExpr ( ) ) and
284+ result = "... => .."
285+ or
286+ this .isUnknownType ( ) and
287+ result = ""
288+ or
289+ this .isSourceContextParameterType ( ) and
290+ result = "<source context parameter type>"
291+ }
292+ }
293+
294+ pragma [ nomagic]
295+ private predicate compatibleTypesSourceContextParameterTypeLeft ( DataFlowType t1 , DataFlowType t2 ) {
296+ t1 .isSourceContextParameterType ( ) and not exists ( t2 .asClosureExpr ( ) )
297+ }
298+
299+ pragma [ nomagic]
300+ private predicate compatibleTypesLeft ( DataFlowType t1 , DataFlowType t2 ) {
301+ t1 .isUnknownType ( )
302+ or
303+ t1 .asClosureExpr ( ) = t2 .asClosureExpr ( )
304+ or
305+ compatibleTypesSourceContextParameterTypeLeft ( t1 , t2 )
306+ }
307+
308+ predicate compatibleTypes ( DataFlowType t1 , DataFlowType t2 ) {
309+ compatibleTypesLeft ( t1 , t2 )
310+ or
311+ compatibleTypesLeft ( t2 , t1 )
312+ }
313+
314+ pragma [ nomagic]
315+ predicate typeStrongerThan ( DataFlowType t1 , DataFlowType t2 ) {
316+ exists ( t1 ) and t2 .isUnknownType ( )
317+ or
318+ compatibleTypesSourceContextParameterTypeLeft ( t1 , t2 )
319+ }
320+
321+ DataFlowType getNodeType ( NodePublic node ) {
322+ result .asClosureExpr ( ) = node .asExpr ( )
323+ or
324+ result .asClosureExpr ( ) = node .( ClosureParameterNode ) .getCfgScope ( )
325+ or
326+ exists ( VariableCapture:: Flow:: SynthesizedCaptureNode scn |
327+ scn = node .( CaptureNode ) .getSynthesizedCaptureNode ( ) and
328+ if scn .isInstanceAccess ( )
329+ then result .asClosureExpr ( ) = scn .getEnclosingCallable ( )
330+ else result .isUnknownType ( )
331+ )
332+ or
333+ not lambdaCreationExpr ( node .asExpr ( ) ) and
334+ not node instanceof ClosureParameterNode and
335+ not node instanceof CaptureNode and
336+ result .isUnknownType ( )
337+ }
338+
266339// Defines a set of aliases needed for the `RustDataFlow` module
267340private module Aliases {
268341 class DataFlowCallableAlias = DataFlowCallable ;
269342
343+ class DataFlowTypeAlias = DataFlowType ;
344+
345+ predicate compatibleTypesAlias = compatibleTypes / 2 ;
346+
347+ predicate typeStrongerThanAlias = typeStrongerThan / 2 ;
348+
349+ predicate getNodeTypeAlias = getNodeType / 1 ;
350+
270351 class ReturnKindAlias = ReturnKind ;
271352
272353 class DataFlowCallAlias = DataFlowCall ;
@@ -398,8 +479,6 @@ module RustDataFlowGen<RustDataFlowInputSig Input> implements InputSig<Location>
398479 result = node .( Node:: Node ) .getEnclosingCallable ( )
399480 }
400481
401- DataFlowType getNodeType ( Node node ) { any ( ) }
402-
403482 predicate nodeIsHidden ( Node node ) {
404483 node instanceof SsaNode or
405484 node .( FlowSummaryNode ) .getSummaryNode ( ) .isHidden ( ) or
@@ -486,15 +565,17 @@ module RustDataFlowGen<RustDataFlowInputSig Input> implements InputSig<Location>
486565 */
487566 OutNode getAnOutNode ( DataFlowCall call , ReturnKind kind ) { call = result .getCall ( kind ) }
488567
489- // NOTE: For now we use the type `Unit` and do not benefit from type
490- // information in the data flow analysis.
491- final class DataFlowType extends Unit {
492- string toString ( ) { result = "" }
493- }
568+ class DataFlowType = DataFlowTypeAlias ;
494569
495- predicate compatibleTypes ( DataFlowType t1 , DataFlowType t2 ) { any ( ) }
570+ predicate compatibleTypes = compatibleTypesAlias / 2 ;
496571
497- predicate typeStrongerThan ( DataFlowType t1 , DataFlowType t2 ) { none ( ) }
572+ predicate typeStrongerThan = typeStrongerThanAlias / 2 ;
573+
574+ DataFlowType getSourceContextParameterNodeType ( Node p ) {
575+ exists ( p ) and result .isSourceContextParameterType ( )
576+ }
577+
578+ predicate getNodeType = getNodeTypeAlias / 1 ;
498579
499580 class Content = ContentAlias ;
500581
@@ -897,6 +978,8 @@ module RustDataFlowGen<RustDataFlowInputSig Input> implements InputSig<Location>
897978 predicate localMustFlowStep ( Node node1 , Node node2 ) {
898979 SsaFlow:: localMustFlowStep ( node1 , node2 )
899980 or
981+ LocalFlow:: localMustFlowStep ( node1 , node2 )
982+ or
900983 FlowSummaryImpl:: Private:: Steps:: summaryLocalMustFlowStep ( node1
901984 .( FlowSummaryNode )
902985 .getSummaryNode ( ) , node2 .( FlowSummaryNode ) .getSummaryNode ( ) )
@@ -1110,6 +1193,12 @@ private module Cached {
11101193 TCfgScope ( CfgScope scope ) or
11111194 TSummarizedCallable ( SummarizedCallable c )
11121195
1196+ cached
1197+ newtype TDataFlowType =
1198+ TClosureExprType ( Expr e ) { lambdaCreationExpr ( e ) } or
1199+ TUnknownType ( ) or
1200+ TSourceContextParameterType ( )
1201+
11131202 /** This is the local flow predicate that is exposed. */
11141203 cached
11151204 predicate localFlowStepImpl ( Node nodeFrom , Node nodeTo ) {
0 commit comments