@@ -17,7 +17,7 @@ module Gvn {
1717 string getNameNested ( Type t ) {
1818 if not t instanceof NestedType or t .( NestedType ) .getDeclaringType ( ) instanceof GenericType
1919 then result = t .getName ( )
20- else result = getNameNested ( t .( NestedType ) .getDeclaringType ( ) ) + ". " + t .getName ( )
20+ else result = getNameNested ( t .( NestedType ) .getDeclaringType ( ) ) + "+ " + t .getName ( )
2121 }
2222
2323 /**
@@ -326,123 +326,78 @@ module Gvn {
326326 getTypeArgument ( k , t , i ) = TTypeParameterGvnType ( )
327327 }
328328
329- /**
330- * Hold if (non-type-parameters) `arg1` and `arg2` are unifiable, and both are
331- * the `i`th type argument of a compound type of kind `k`.
332- */
333- pragma [ nomagic]
334- private predicate unifiableNonTypeParameterTypeArguments (
335- CompoundTypeKind k , GvnTypeArgument arg1 , GvnTypeArgument arg2 , int i
336- ) {
337- exists ( int j |
338- arg1 = getNonTypeParameterTypeArgument ( k , _, i ) and
339- arg2 = getNonTypeParameterTypeArgument ( k , _, j ) and
340- i <= j and
341- j <= i
342- |
343- arg1 = arg2
344- or
345- unifiable ( arg1 , arg2 )
346- )
347- }
348-
349329 /**
350330 * Hold if `arg1` and `arg2` are unifiable, and both are the `i`th type argument
351331 * of a compound type of kind `k`.
332+ *
333+ * `subsumes` indicates whether `arg1` in fact subsumes `arg2`.
352334 */
353335 pragma [ nomagic]
354336 private predicate unifiableTypeArguments (
355- CompoundTypeKind k , GvnTypeArgument arg1 , GvnTypeArgument arg2 , int i
337+ CompoundTypeKind k , GvnTypeArgument arg1 , GvnTypeArgument arg2 , int i , boolean subsumes
356338 ) {
357- unifiableNonTypeParameterTypeArguments ( k , arg1 , arg2 , i )
358- or
359- exists ( int j |
360- arg1 = TTypeParameterGvnType ( ) and
361- typeArgumentIsTypeParameter ( k , _, i ) and
362- arg2 = getTypeArgument ( k , _, j ) and
363- i <= j and
364- j <= i
339+ arg1 = getNonTypeParameterTypeArgument ( k , _, pragma [ only_bind_into ] ( i ) ) and
340+ arg2 = getNonTypeParameterTypeArgument ( k , _, pragma [ only_bind_into ] ( i ) ) and
341+ (
342+ arg1 = arg2 and
343+ subsumes = true
344+ or
345+ unifiable ( arg1 , arg2 , subsumes )
365346 )
366347 or
367- exists ( int j |
368- arg1 = getTypeArgument ( k , _, i ) and
369- typeArgumentIsTypeParameter ( k , _, j ) and
370- arg2 = TTypeParameterGvnType ( ) and
371- i <= j and
372- j <= i
373- )
348+ arg1 = TTypeParameterGvnType ( ) and
349+ typeArgumentIsTypeParameter ( k , _, pragma [ only_bind_into ] ( i ) ) and
350+ arg2 = getTypeArgument ( k , _, pragma [ only_bind_into ] ( i ) ) and
351+ subsumes = true
352+ or
353+ arg1 = getNonTypeParameterTypeArgument ( k , _, pragma [ only_bind_into ] ( i ) ) and
354+ typeArgumentIsTypeParameter ( k , _, pragma [ only_bind_into ] ( i ) ) and
355+ arg2 = TTypeParameterGvnType ( ) and
356+ subsumes = false
374357 }
375358
376359 pragma [ nomagic]
377360 private predicate unifiableSingle0 (
378- CompoundTypeKind k , ConstructedGvnType t2 , GvnTypeArgument arg1 , GvnTypeArgument arg2
361+ CompoundTypeKind k , ConstructedGvnType t2 , GvnTypeArgument arg1 , GvnTypeArgument arg2 ,
362+ boolean subsumes
379363 ) {
380- unifiableTypeArguments ( k , arg1 , arg2 , 0 ) and
364+ unifiableTypeArguments ( k , arg1 , arg2 , 0 , subsumes ) and
381365 arg2 = getTypeArgument ( k , t2 , 0 ) and
382366 k .getNumberOfTypeParameters ( ) = 1
383367 }
384368
385- /**
386- * Holds if the type arguments of types `t1` and `t2` are unifiable, `t1`
387- * and `t2` are of the same kind, and the number of type arguments is 1.
388- */
389- private predicate unifiableSingle ( ConstructedGvnType t1 , ConstructedGvnType t2 ) {
390- exists ( CompoundTypeKind k , GvnTypeArgument arg1 , GvnTypeArgument arg2 |
391- unifiableSingle0 ( k , t2 , arg1 , arg2 ) and
392- arg1 = getTypeArgument ( k , t1 , 0 )
393- )
394- }
395-
396369 pragma [ nomagic]
397370 private predicate unifiableMultiple01Aux0 (
398- CompoundTypeKind k , ConstructedGvnType t2 , GvnTypeArgument arg10 , GvnTypeArgument arg21
371+ CompoundTypeKind k , ConstructedGvnType t2 , GvnTypeArgument arg10 , GvnTypeArgument arg21 ,
372+ boolean subsumes
399373 ) {
400374 exists ( GvnTypeArgument arg20 |
401- unifiableTypeArguments ( k , arg10 , arg20 , 0 ) and
375+ unifiableTypeArguments ( k , arg10 , arg20 , 0 , subsumes ) and
402376 arg20 = getTypeArgument ( k , t2 , 0 ) and
403377 arg21 = getTypeArgument ( k , t2 , 1 )
404378 )
405379 }
406380
407381 pragma [ nomagic]
408382 private predicate unifiableMultiple01Aux1 (
409- CompoundTypeKind k , ConstructedGvnType t1 , GvnTypeArgument arg10 , GvnTypeArgument arg21
383+ CompoundTypeKind k , ConstructedGvnType t1 , GvnTypeArgument arg10 , GvnTypeArgument arg21 ,
384+ boolean subsumes
410385 ) {
411386 exists ( GvnTypeArgument arg11 |
412- unifiableTypeArguments ( k , arg11 , arg21 , 1 ) and
387+ unifiableTypeArguments ( k , arg11 , arg21 , 1 , subsumes ) and
413388 arg10 = getTypeArgument ( k , t1 , 0 ) and
414389 arg11 = getTypeArgument ( k , t1 , 1 )
415390 )
416391 }
417392
418- /**
419- * Holds if the first two type arguments of types `t1` and `t2` are unifiable,
420- * and both `t1` and `t2` are of kind `k`.
421- */
422- private predicate unifiableMultiple01 (
423- CompoundTypeKind k , ConstructedGvnType t1 , ConstructedGvnType t2
424- ) {
425- exists ( GvnTypeArgument arg10 , GvnTypeArgument arg21 |
426- unifiableMultiple01Aux0 ( k , t2 , arg10 , arg21 ) and
427- unifiableMultiple01Aux1 ( k , t1 , arg10 , arg21 )
428- )
429- }
430-
431393 pragma [ nomagic]
432394 private predicate unifiableMultiple2Aux (
433- CompoundTypeKind k , ConstructedGvnType t2 , int i , GvnTypeArgument arg1 , GvnTypeArgument arg2
434- ) {
435- unifiableTypeArguments ( k , arg1 , arg2 , i ) and
436- arg2 = getTypeArgument ( k , t2 , i ) and
437- i >= 2
438- }
439-
440- private predicate unifiableMultiple2 (
441- CompoundTypeKind k , ConstructedGvnType t1 , ConstructedGvnType t2 , int i
395+ CompoundTypeKind k , ConstructedGvnType t2 , int i , GvnTypeArgument arg1 , boolean subsumes
442396 ) {
443- exists ( GvnTypeArgument arg1 , GvnTypeArgument arg2 |
444- unifiableMultiple2Aux ( k , t2 , i , arg1 , arg2 ) and
445- arg1 = getTypeArgument ( k , t1 , i )
397+ exists ( GvnTypeArgument arg2 |
398+ unifiableTypeArguments ( k , arg1 , arg2 , i , subsumes ) and
399+ arg2 = getTypeArgument ( k , t2 , i ) and
400+ i >= 2
446401 )
447402 }
448403
@@ -452,45 +407,35 @@ module Gvn {
452407 */
453408 pragma [ nomagic]
454409 private predicate unifiableMultiple (
455- CompoundTypeKind k , ConstructedGvnType t1 , ConstructedGvnType t2 , int i
410+ CompoundTypeKind k , ConstructedGvnType t1 , ConstructedGvnType t2 , int i , boolean subsumes
456411 ) {
457- unifiableMultiple01 ( k , t1 , t2 ) and i = 1
412+ exists ( GvnTypeArgument arg10 , GvnTypeArgument arg21 , boolean subsumes1 , boolean subsumes2 |
413+ unifiableMultiple01Aux0 ( k , t2 , arg10 , arg21 , subsumes1 ) and
414+ unifiableMultiple01Aux1 ( k , t1 , arg10 , arg21 , subsumes2 ) and
415+ subsumes = subsumes1 .booleanAnd ( subsumes2 )
416+ ) and
417+ i = 1
458418 or
459- unifiableMultiple ( k , t1 , t2 , i - 1 ) and
460- unifiableMultiple2 ( k , t1 , t2 , i )
419+ exists ( GvnTypeArgument arg1 , boolean subsumes1 , boolean subsumes2 |
420+ unifiableMultiple ( k , t1 , t2 , i - 1 , subsumes1 ) and
421+ unifiableMultiple2Aux ( k , t2 , i , arg1 , subsumes2 ) and
422+ arg1 = getTypeArgument ( k , t1 , i ) and
423+ subsumes = subsumes1 .booleanAnd ( subsumes2 )
424+ )
461425 }
462426
463- private newtype TTypePath =
464- TTypePathNil ( ) or
465- TTypePathCons ( int head , TTypePath tail ) { exists ( getTypeAtCons ( _, head , tail ) ) }
466-
467- /**
468- * Gets the GVN inside GVN `t`, by following the path `path`, if any.
469- */
470- private GvnType getTypeAt ( GvnType t , TTypePath path ) {
471- path = TTypePathNil ( ) and
472- result = t
427+ pragma [ nomagic]
428+ private predicate unifiable ( ConstructedGvnType t1 , ConstructedGvnType t2 , boolean subsumes ) {
429+ exists ( CompoundTypeKind k , GvnTypeArgument arg1 , GvnTypeArgument arg2 |
430+ unifiableSingle0 ( k , t2 , arg1 , arg2 , subsumes ) and
431+ arg1 = getTypeArgument ( k , t1 , 0 )
432+ )
473433 or
474- exists ( ConstructedGvnTypeList l , int head , TTypePath tail |
475- t = TConstructedGvnType ( l ) and
476- path = TTypePathCons ( head , tail ) and
477- result = getTypeAtCons ( l , head , tail )
434+ exists ( CompoundTypeKind k |
435+ unifiableMultiple ( k , t1 , t2 , k .getNumberOfTypeParameters ( ) - 1 , subsumes )
478436 )
479437 }
480438
481- private GvnType getTypeAtCons ( ConstructedGvnTypeList l , int head , TTypePath tail ) {
482- result = getTypeAt ( l .getArg ( head ) , tail )
483- }
484-
485- /**
486- * Gets the leaf GVN inside GVN `t`, by following the path `path`, if any.
487- */
488- pragma [ noinline]
489- private GvnType getLeafTypeAt ( GvnType t , TTypePath path ) {
490- result = getTypeAt ( t , path ) and
491- not result instanceof ConstructedGvnType
492- }
493-
494439 cached
495440 private module Cached {
496441 cached
@@ -540,33 +485,20 @@ module Gvn {
540485 }
541486
542487 /**
543- * Holds if GVNs `t1` and `t2` can be unified. That is, is it possible to
488+ * Holds if GVNs `t1` and `t2` can be unified. That is, it is possible to
544489 * replace all type parameters in `t1` and `t2` with some GVNs (possibly
545490 * type parameters themselves) to make the two substituted terms equal.
546491 */
547492 cached
548- predicate unifiable ( ConstructedGvnType t1 , ConstructedGvnType t2 ) {
549- unifiableSingle ( t1 , t2 )
550- or
551- exists ( CompoundTypeKind k | unifiableMultiple ( k , t1 , t2 , k .getNumberOfTypeParameters ( ) - 1 ) )
552- }
493+ predicate unifiable ( ConstructedGvnType t1 , ConstructedGvnType t2 ) { unifiable ( t1 , t2 , _) }
553494
554495 /**
555- * Holds if GVN `t1` subsumes GVN `t2`. That is, is it possible to replace all
496+ * Holds if GVN `t1` subsumes GVN `t2`. That is, it is possible to replace all
556497 * type parameters in `t1` with some GVNs (possibly type parameters themselves)
557498 * to make the two substituted terms equal.
558499 */
559500 cached
560- predicate subsumes ( ConstructedGvnType t1 , ConstructedGvnType t2 ) {
561- unifiable ( t1 , t2 ) and // subsumption implies unification
562- forall ( TTypePath path , GvnType leaf1 | leaf1 = getLeafTypeAt ( t1 , path ) |
563- exists ( GvnType child2 | child2 = getTypeAt ( t2 , path ) |
564- leaf1 = TTypeParameterGvnType ( )
565- or
566- leaf1 = child2
567- )
568- )
569- }
501+ predicate subsumes ( ConstructedGvnType t1 , ConstructedGvnType t2 ) { unifiable ( t1 , t2 , true ) }
570502 }
571503
572504 import Cached
0 commit comments