@@ -17,7 +17,7 @@ module Gvn {
17
17
string getNameNested ( Type t ) {
18
18
if not t instanceof NestedType or t .( NestedType ) .getDeclaringType ( ) instanceof GenericType
19
19
then result = t .getName ( )
20
- else result = getNameNested ( t .( NestedType ) .getDeclaringType ( ) ) + ". " + t .getName ( )
20
+ else result = getNameNested ( t .( NestedType ) .getDeclaringType ( ) ) + "+ " + t .getName ( )
21
21
}
22
22
23
23
/**
@@ -326,123 +326,78 @@ module Gvn {
326
326
getTypeArgument ( k , t , i ) = TTypeParameterGvnType ( )
327
327
}
328
328
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
-
349
329
/**
350
330
* Hold if `arg1` and `arg2` are unifiable, and both are the `i`th type argument
351
331
* of a compound type of kind `k`.
332
+ *
333
+ * `subsumes` indicates whether `arg1` in fact subsumes `arg2`.
352
334
*/
353
335
pragma [ nomagic]
354
336
private predicate unifiableTypeArguments (
355
- CompoundTypeKind k , GvnTypeArgument arg1 , GvnTypeArgument arg2 , int i
337
+ CompoundTypeKind k , GvnTypeArgument arg1 , GvnTypeArgument arg2 , int i , boolean subsumes
356
338
) {
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 )
365
346
)
366
347
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
374
357
}
375
358
376
359
pragma [ nomagic]
377
360
private predicate unifiableSingle0 (
378
- CompoundTypeKind k , ConstructedGvnType t2 , GvnTypeArgument arg1 , GvnTypeArgument arg2
361
+ CompoundTypeKind k , ConstructedGvnType t2 , GvnTypeArgument arg1 , GvnTypeArgument arg2 ,
362
+ boolean subsumes
379
363
) {
380
- unifiableTypeArguments ( k , arg1 , arg2 , 0 ) and
364
+ unifiableTypeArguments ( k , arg1 , arg2 , 0 , subsumes ) and
381
365
arg2 = getTypeArgument ( k , t2 , 0 ) and
382
366
k .getNumberOfTypeParameters ( ) = 1
383
367
}
384
368
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
-
396
369
pragma [ nomagic]
397
370
private predicate unifiableMultiple01Aux0 (
398
- CompoundTypeKind k , ConstructedGvnType t2 , GvnTypeArgument arg10 , GvnTypeArgument arg21
371
+ CompoundTypeKind k , ConstructedGvnType t2 , GvnTypeArgument arg10 , GvnTypeArgument arg21 ,
372
+ boolean subsumes
399
373
) {
400
374
exists ( GvnTypeArgument arg20 |
401
- unifiableTypeArguments ( k , arg10 , arg20 , 0 ) and
375
+ unifiableTypeArguments ( k , arg10 , arg20 , 0 , subsumes ) and
402
376
arg20 = getTypeArgument ( k , t2 , 0 ) and
403
377
arg21 = getTypeArgument ( k , t2 , 1 )
404
378
)
405
379
}
406
380
407
381
pragma [ nomagic]
408
382
private predicate unifiableMultiple01Aux1 (
409
- CompoundTypeKind k , ConstructedGvnType t1 , GvnTypeArgument arg10 , GvnTypeArgument arg21
383
+ CompoundTypeKind k , ConstructedGvnType t1 , GvnTypeArgument arg10 , GvnTypeArgument arg21 ,
384
+ boolean subsumes
410
385
) {
411
386
exists ( GvnTypeArgument arg11 |
412
- unifiableTypeArguments ( k , arg11 , arg21 , 1 ) and
387
+ unifiableTypeArguments ( k , arg11 , arg21 , 1 , subsumes ) and
413
388
arg10 = getTypeArgument ( k , t1 , 0 ) and
414
389
arg11 = getTypeArgument ( k , t1 , 1 )
415
390
)
416
391
}
417
392
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
-
431
393
pragma [ nomagic]
432
394
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
442
396
) {
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
446
401
)
447
402
}
448
403
@@ -452,45 +407,35 @@ module Gvn {
452
407
*/
453
408
pragma [ nomagic]
454
409
private predicate unifiableMultiple (
455
- CompoundTypeKind k , ConstructedGvnType t1 , ConstructedGvnType t2 , int i
410
+ CompoundTypeKind k , ConstructedGvnType t1 , ConstructedGvnType t2 , int i , boolean subsumes
456
411
) {
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
458
418
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
+ )
461
425
}
462
426
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
+ )
473
433
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 )
478
436
)
479
437
}
480
438
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
-
494
439
cached
495
440
private module Cached {
496
441
cached
@@ -540,33 +485,20 @@ module Gvn {
540
485
}
541
486
542
487
/**
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
544
489
* replace all type parameters in `t1` and `t2` with some GVNs (possibly
545
490
* type parameters themselves) to make the two substituted terms equal.
546
491
*/
547
492
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 , _) }
553
494
554
495
/**
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
556
497
* type parameters in `t1` with some GVNs (possibly type parameters themselves)
557
498
* to make the two substituted terms equal.
558
499
*/
559
500
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 ) }
570
502
}
571
503
572
504
import Cached
0 commit comments