@@ -5,33 +5,55 @@ private import CaptureModelsSpecific as Specific
55private import CaptureModels
66
77/**
8- * A type representing classes that has a method which returns an iterator.
8+ * A type representing class types of instantiations of class types
9+ * that has a method which returns an iterator.
910 */
1011private class IterableType extends Class {
1112 private Type elementType ;
1213
1314 IterableType ( ) {
14- exists ( Method m , Type return | m .getDeclaringType ( ) = this |
15+ exists ( Method m , Type return , Type t | m .getDeclaringType ( ) = t |
1516 return = m .getReturnType ( ) and
1617 return .getName ( ) .matches ( "Iterator%" ) and
17- elementType = return .( ParameterizedType ) .getTypeArgument ( 0 )
18+ elementType = return .( ParameterizedType ) .getTypeArgument ( 0 ) and
19+ ( this = t or instantiates ( this , t , _, _) )
1820 )
1921 }
2022
2123 /**
2224 * Returns the iterator element type of `this`.
25+ * TODO: Improve this as it doesn't return the correct type instantiations.
2326 */
2427 Type getElementType ( ) { result = elementType }
2528}
2629
30+ /**
31+ * Holds if type `bound` is an upper bound for type `t` or equal to `t`.
32+ */
33+ private predicate isEffectivelyUpperBound ( Type t , Type bound ) {
34+ t = bound or
35+ t .( Wildcard ) .getUpperBound ( ) .getType ( ) = bound
36+ }
37+
38+ /**
39+ * Holds if type `bound` is a lower bound for type `t` or equal to `t`.
40+ */
41+ private predicate isEffectivelyLowerBound ( Type t , Type bound ) {
42+ t = bound or
43+ t .( Wildcard ) .getLowerBound ( ) .getType ( ) = bound
44+ }
45+
2746/**
2847 * Holds if `t` is a container like type of `tv` (eg. `List<T>`).
48+ * Note that collections are covariant in their element type.
2949 */
3050private predicate genericContainerType ( RefType t , TypeVariable tv ) {
31- (
32- t .( ContainerType ) .getElementType ( ) = tv
51+ exists ( Type et |
52+ et = t .( ContainerType ) .getElementType ( )
3353 or
34- t .( IterableType ) .getElementType ( ) = tv
54+ et = t .( IterableType ) .getElementType ( )
55+ |
56+ isEffectivelyUpperBound ( et , tv )
3557 )
3658}
3759
@@ -50,19 +72,33 @@ private predicate localTypeParameter(Callable callable, TypeVariable tv) {
5072 callable .( GenericCallable ) .getATypeParameter ( ) = tv
5173}
5274
75+ private string parameterAccess ( Parameter p ) {
76+ exists ( Type t | t = p .getType ( ) |
77+ if
78+ t instanceof Array and
79+ not Specific:: isPrimitiveTypeUsedForBulkData ( p .getType ( ) .( Array ) .getElementType ( ) )
80+ then result = "Argument[" + p .getPosition ( ) + "].ArrayElement"
81+ else
82+ if t instanceof ContainerType or t instanceof IterableType
83+ then result = "Argument[" + p .getPosition ( ) + "].Element"
84+ else result = "Argument[" + p .getPosition ( ) + "]"
85+ )
86+ }
87+
5388/**
5489 * Holds if `callable` has a type parameter `tv` or container parameterized over type `tv`.
5590 */
5691private predicate parameter ( Callable callable , string input , TypeVariable tv ) {
57- exists ( Parameter p |
58- input = Specific :: parameterAccess ( p ) and
92+ exists ( Parameter p , Type pt |
93+ input = parameterAccess ( p ) and
5994 p = callable .getAParameter ( ) and
95+ pt = p .getType ( ) and
6096 (
6197 // Parameter of type tv
62- p . getType ( ) = tv
98+ isEffectivelyUpperBound ( pt , tv )
6399 or
64100 // Parameter is a container of type tv
65- genericContainerType ( p . getType ( ) , tv )
101+ genericContainerType ( pt , tv )
66102 )
67103 )
68104}
@@ -80,6 +116,7 @@ private string getSyntheticField(TypeVariable tv) {
80116 */
81117private string implicit ( Callable callable , TypeVariable tv ) {
82118 classTypeParameter ( callable , tv ) and
119+ not callable .isStatic ( ) and
83120 exists ( string access |
84121 if genericContainerType ( callable .getDeclaringType ( ) , tv )
85122 then access = ".Element"
@@ -113,11 +150,9 @@ private class Function extends ParameterizedType {
113150 * Note that functions are contravariant in their parameter types.
114151 */
115152 Type getParameterType ( int position ) {
116- exists ( Type t | fi .getRunMethod ( ) .getParameterType ( position ) = getTypeReplacement ( t ) |
117- (
118- result = t or
119- result = t .( Wildcard ) .getLowerBound ( ) .getType ( )
120- )
153+ exists ( Type t |
154+ fi .getRunMethod ( ) .getParameterType ( position ) = getTypeReplacement ( t ) and
155+ isEffectivelyLowerBound ( t , result )
121156 )
122157 }
123158
@@ -126,11 +161,9 @@ private class Function extends ParameterizedType {
126161 * Note that functions are covariant in their return type.
127162 */
128163 Type getReturnType ( ) {
129- exists ( Type t | fi .getRunMethod ( ) .getReturnType ( ) = getTypeReplacement ( t ) |
130- (
131- result = t or
132- result = t .( Wildcard ) .getUpperBound ( ) .getType ( )
133- )
164+ exists ( Type t |
165+ fi .getRunMethod ( ) .getReturnType ( ) = getTypeReplacement ( t ) and
166+ isEffectivelyUpperBound ( t , result )
134167 )
135168 }
136169}
0 commit comments