@@ -26,7 +26,7 @@ abstract class NodeImpl extends Node {
2626
2727 /** Gets the type of this node used for type pruning. */
2828 cached
29- DataFlowType getDataFlowType ( ) {
29+ Gvn :: GvnType getDataFlowType ( ) {
3030 Stages:: DataFlowStage:: forceCachingInSameStage ( ) and
3131 exists ( Type t0 | result = Gvn:: getGlobalValueNumber ( t0 ) |
3232 t0 = getCSharpType ( this .getType ( ) )
@@ -490,14 +490,23 @@ private Type getCSharpType(DotNet::Type t) {
490490 result .matchesHandle ( t )
491491}
492492
493+ /** A GVN type that is either a `DataFlowType` or unifiable with a `DataFlowType`. */
494+ private class DataFlowTypeOrUnifiable extends Gvn:: GvnType {
495+ pragma [ nomagic]
496+ DataFlowTypeOrUnifiable ( ) {
497+ this instanceof DataFlowType or
498+ Gvn:: unifiable ( any ( DataFlowType t ) , this )
499+ }
500+ }
501+
493502pragma [ noinline]
494- private TypeParameter getATypeParameterSubType ( DataFlowType t ) {
503+ private TypeParameter getATypeParameterSubType ( DataFlowTypeOrUnifiable t ) {
495504 not t instanceof Gvn:: TypeParameterGvnType and
496505 exists ( Type t0 | t = Gvn:: getGlobalValueNumber ( t0 ) | implicitConversionRestricted ( result , t0 ) )
497506}
498507
499508pragma [ noinline]
500- private DataFlowType getANonTypeParameterSubType ( DataFlowType t ) {
509+ private Gvn :: GvnType getANonTypeParameterSubType ( DataFlowTypeOrUnifiable t ) {
501510 not t instanceof Gvn:: TypeParameterGvnType and
502511 not result instanceof Gvn:: TypeParameterGvnType and
503512 exists ( Type t1 , Type t2 |
@@ -728,12 +737,8 @@ private module Cached {
728737 )
729738 }
730739
731- /**
732- * Holds if GVNs `t1` and `t2` may have a common sub type. Neither `t1` nor
733- * `t2` are allowed to be type parameters.
734- */
735- cached
736- predicate commonSubType ( DataFlowType t1 , DataFlowType t2 ) {
740+ pragma [ nomagic]
741+ private predicate commonSubTypeGeneral ( DataFlowTypeOrUnifiable t1 , DataFlowType t2 ) {
737742 not t1 instanceof Gvn:: TypeParameterGvnType and
738743 t1 = t2
739744 or
@@ -742,11 +747,18 @@ private module Cached {
742747 getANonTypeParameterSubType ( t1 ) = getANonTypeParameterSubType ( t2 )
743748 }
744749
750+ /**
751+ * Holds if GVNs `t1` and `t2` may have a common sub type. Neither `t1` nor
752+ * `t2` are allowed to be type parameters.
753+ */
754+ cached
755+ predicate commonSubType ( DataFlowType t1 , DataFlowType t2 ) { commonSubTypeGeneral ( t1 , t2 ) }
756+
745757 cached
746758 predicate commonSubTypeUnifiableLeft ( DataFlowType t1 , DataFlowType t2 ) {
747- exists ( DataFlowType t |
759+ exists ( Gvn :: GvnType t |
748760 Gvn:: unifiable ( t1 , t ) and
749- commonSubType ( t , t2 )
761+ commonSubTypeGeneral ( t , t2 )
750762 )
751763 }
752764
@@ -2004,7 +2016,7 @@ module LibraryFlow {
20042016
20052017/** Gets the type of content `c`. */
20062018pragma [ noinline]
2007- private DataFlowType getContentType ( Content c ) {
2019+ private Gvn :: GvnType getContentType ( Content c ) {
20082020 exists ( Type t | result = Gvn:: getGlobalValueNumber ( t ) |
20092021 t = c .( FieldContent ) .getField ( ) .getType ( )
20102022 or
@@ -2031,7 +2043,7 @@ class LibraryCodeNode extends NodeImpl, TLibraryCodeNode {
20312043
20322044 override Callable getEnclosingCallableImpl ( ) { result = callCfn .getEnclosingCallable ( ) }
20332045
2034- override DataFlowType getDataFlowType ( ) {
2046+ override Gvn :: GvnType getDataFlowType ( ) {
20352047 exists ( LibraryFlow:: AdjustedAccessPath ap |
20362048 state = LibraryFlow:: TLibraryCodeNodeAfterReadState ( ap ) and
20372049 if sinkAp .length ( ) = 0 and state .isLastReadState ( ) and preservesValue = true
@@ -2194,6 +2206,20 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
21942206
21952207predicate readStep = readStepImpl / 3 ;
21962208
2209+ /**
2210+ * An entity used to represent the type of data-flow node. Two nodes will have
2211+ * the same `DataFlowType` when the underlying `Type`s are structurally equal
2212+ * modulo type parameters and identity conversions.
2213+ *
2214+ * For example, `Func<T, int>` and `Func<S, int>` are mapped to the same
2215+ * `DataFlowType`, while `Func<T, int>` and `Func<string, int>` are not, because
2216+ * `string` is not a type parameter.
2217+ */
2218+ class DataFlowType extends Gvn:: GvnType {
2219+ pragma [ nomagic]
2220+ DataFlowType ( ) { this = any ( NodeImpl n ) .getDataFlowType ( ) }
2221+ }
2222+
21972223/** Gets the type of `n` used for type pruning. */
21982224DataFlowType getNodeType ( NodeImpl n ) { result = n .getDataFlowType ( ) }
21992225
@@ -2323,8 +2349,6 @@ class CastNode extends Node {
23232349
23242350class DataFlowExpr = DotNet:: Expr ;
23252351
2326- class DataFlowType = Gvn:: GvnType ;
2327-
23282352/** Holds if `e` is an expression that always has the same Boolean value `val`. */
23292353private predicate constantBooleanExpr ( Expr e , boolean val ) {
23302354 e = any ( AbstractValues:: BooleanValue bv | val = bv .getValue ( ) ) .getAnExpr ( )
0 commit comments