@@ -204,38 +204,42 @@ private predicate exactType(TypeFlowNode n, RefType t) {
204204
205205/**
206206 * Holds if `n` occurs in a position where type information might be discarded;
207- * `t ` is the potentially boxed type of `n`, `t1 ` is the erasure of `t `, and
208- * `t2` is the erased type of the implicit or explicit cast .
207+ * `t1 ` is the type of `n`, `t1e ` is the erasure of `t1 `, `t2` is the type of
208+ * the implicit or explicit cast, and `t2e` is the erasure of `t2` .
209209 */
210- pragma [ noinline]
211- private predicate upcastCand ( TypeFlowNode n , RefType t , RefType t1 , RefType t2 ) {
212- t = boxIfNeeded ( n .getType ( ) ) and
213- t .getErasure ( ) = t1 and
214- (
215- exists ( Variable v | v .getAnAssignedValue ( ) = n .asExpr ( ) and t2 = v .getType ( ) .getErasure ( ) )
216- or
217- exists ( CastingExpr c | c .getExpr ( ) = n .asExpr ( ) and t2 = c .getType ( ) .getErasure ( ) )
218- or
219- exists ( ReturnStmt ret |
220- ret .getResult ( ) = n .asExpr ( ) and t2 = ret .getEnclosingCallable ( ) .getReturnType ( ) .getErasure ( )
221- )
222- or
223- exists ( MethodAccess ma | viableImpl_v1 ( ma ) = n .asMethod ( ) and t2 = ma .getType ( ) .getErasure ( ) )
224- or
225- exists ( Parameter p | privateParamArg ( p , n .asExpr ( ) ) and t2 = p .getType ( ) .getErasure ( ) )
226- or
227- exists ( ChooseExpr cond |
228- cond .getAResultExpr ( ) = n .asExpr ( ) and
229- t2 = cond .getType ( ) .getErasure ( )
210+ pragma [ nomagic]
211+ private predicate upcastCand ( TypeFlowNode n , RefType t1 , RefType t1e , RefType t2 , RefType t2e ) {
212+ exists ( TypeFlowNode next | step ( n , next ) or joinStep ( n , next ) |
213+ n .getType ( ) = t1 and
214+ next .getType ( ) = t2 and
215+ t1 .getErasure ( ) = t1e and
216+ t2 .getErasure ( ) = t2e and
217+ t1 != t2
218+ )
219+ }
220+
221+ /** Holds if `t` is a raw type or parameterised type with unrestricted type arguments. */
222+ private predicate unbound ( RefType t ) {
223+ t instanceof RawType
224+ or
225+ exists ( ParameterizedType pt | pt = t |
226+ forex ( RefType arg | arg = pt .getATypeArgument ( ) |
227+ arg .( Wildcard ) .isUnconstrained ( )
228+ or
229+ arg .( BoundedType ) .getUpperBoundType ( ) instanceof TypeObject and
230+ not arg .( Wildcard ) .hasLowerBound ( )
230231 )
231232 )
232233}
233234
234235/** Holds if `n` occurs in a position where type information is discarded. */
235- private predicate upcast ( TypeFlowNode n , RefType t ) {
236- exists ( RefType t1 , RefType t2 |
237- upcastCand ( n , t , t1 , t2 ) and
238- t1 .getASourceSupertype + ( ) = t2
236+ private predicate upcast ( TypeFlowNode n , RefType t1 ) {
237+ exists ( RefType t1e , RefType t2 , RefType t2e | upcastCand ( n , t1 , t1e , t2 , t2e ) |
238+ t1e .getASourceSupertype + ( ) = t2e
239+ or
240+ t1e = t2e and
241+ unbound ( t2 ) and
242+ not unbound ( t1 )
239243 )
240244}
241245
0 commit comments