@@ -252,42 +252,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
252252 result = app .resolveTypeAt ( TypePath:: cons ( tp , suffix ) )
253253 )
254254 }
255-
256- /**
257- * Holds if `term1` is a possible instantiation of `term2`. That is, by
258- * substituting the type parameters in `term2` it is possible to obtain
259- * `term1`.
260- *
261- * For instance, if `A` and `B` are type parameters we have:
262- * - `Pair<int, string>` is an instantiation of `A`
263- * - `Pair<int, string>` is an instantiation of `Pair<A, B>`
264- * - `Pair<int, int>` is an instantiation of `Pair<A, A>`
265- * - `Pair<int, bool>` is _not_ an instantiation of `Pair<A, A>`
266- * - `Pair<int, string>` is _not_ an instantiation of `Pair<string, string>`
267- */
268- bindingset [ abs, term1, term2]
269- predicate isInstantiationOf ( TypeAbstraction abs , App term1 , Term term2 ) {
270- // Check the root type
271- exists ( Type root |
272- root = term2 .resolveTypeAt ( TypePath:: nil ( ) ) and
273- (
274- root = abs .getATypeParameter ( )
275- or
276- root = term1 .resolveTypeAt ( TypePath:: nil ( ) ) and
277- forall ( TypePath path , Type t | term2 .resolveTypeAt ( path ) = t |
278- if t = abs .getATypeParameter ( ) then any ( ) else term1 .resolveTypeAt ( path ) = t
279- ) and
280- forall ( TypeParameter tp , TypePath path1 , TypePath path2 |
281- tp = abs .getATypeParameter ( ) and
282- tp = term2 .resolveTypeAt ( path1 ) and
283- tp = term2 .resolveTypeAt ( path2 ) and
284- path1 != path2
285- |
286- term1 .resolveTypeAt ( path1 ) = term1 .resolveTypeAt ( path2 )
287- )
288- )
289- )
290- }
291255 }
292256
293257 /** Provides the input to `Make2`. */
@@ -332,8 +296,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
332296 */
333297 TypeMention getABaseTypeMention ( Type t ) ;
334298
335- predicate typeSatisfiesConstraint ( TypeAbstraction abs , TypeMention sub , TypeMention sup ) ;
336-
337299 /**
338300 * Gets a type constraint on the type parameter `tp`, if any. All
339301 * instantiations of the type parameter must satisfy the constraint.
@@ -348,6 +310,16 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
348310 * the type parameter `T` has the constraint `IComparable<T>`.
349311 */
350312 TypeMention getTypeParameterConstraint ( TypeParameter tp ) ;
313+
314+ /**
315+ * Holds if
316+ * - `abs` is a type abstraction of the free type variables in `typeMention`
317+ * and `constraint`, - and every instantiation of `typeMention` satisfies
318+ * `constraint`.
319+ */
320+ predicate typeMentionSatisfiesConstraint (
321+ TypeAbstraction abs , TypeMention typeMention , TypeMention constraint
322+ ) ;
351323 }
352324
353325 module Make2< InputSig2 Input2> {
@@ -461,7 +433,18 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
461433 )
462434 }
463435
464- // bindingset[abs, app, term]
436+ /**
437+ * Holds if `term1` is a possible instantiation of `term2`. That is, by
438+ * making appropriate substitutions for the free type parameters in
439+ * `term2`, given by `aps`, it is possible to obtain `term1`.
440+ *
441+ * For instance, if `A` and `B` are free type parameters we have:
442+ * - `Pair<int, string>` is an instantiation of `A`
443+ * - `Pair<int, string>` is an instantiation of `Pair<A, B>`
444+ * - `Pair<int, int>` is an instantiation of `Pair<A, A>`
445+ * - `Pair<int, bool>` is _not_ an instantiation of `Pair<A, A>`
446+ * - `Pair<int, string>` is _not_ an instantiation of `Pair<string, string>`
447+ */
465448 predicate isInstantiationOf ( App app , TypeAbstraction abs , TypeMention term ) {
466449 potentialInstantiationOf ( abs , app , term ) and
467450 // All the concrete types in `term` are satisfied
@@ -494,18 +477,37 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
494477 not exists ( TypePath path , Type t | ment .resolveTypeAt ( path ) = t )
495478 }
496479
480+ module IsInstantiationOfInput implements IsInstantiationOfSig< TypeMention > {
481+ pragma [ nomagic]
482+ private predicate getConstraintLhs ( Type type , TypeAbstraction abs , TypeMention lhs ) {
483+ typeMentionSatisfiesConstraint ( abs , lhs , _) and type = resolveTypeMentionRoot ( lhs )
484+ }
485+
486+ pragma [ nomagic]
487+ private predicate getConstraintRhs ( Type type , TypeMention rhs ) {
488+ typeMentionSatisfiesConstraint ( _, _, rhs ) and type = resolveTypeMentionRoot ( rhs )
489+ }
490+
491+ predicate potentialInstantiationOf ( TypeAbstraction abs , TypeMention sub , TypeMention sup ) {
492+ exists ( Type type | getConstraintRhs ( type , sub ) and getConstraintLhs ( type , abs , sup ) )
493+ }
494+ }
495+
497496 // The type mention `sub` satisfies `sup` with the type `t` at the path `path`.
498497 predicate typeSatisfiesConstraintTrans (
499498 TypeAbstraction abs , TypeMention sub , TypeMention sup , TypePath path , Type t
500499 ) {
501500 // base case
502- typeSatisfiesConstraint ( abs , sub , sup ) and
501+ typeMentionSatisfiesConstraint ( abs , sub , sup ) and
503502 sup .resolveTypeAt ( path ) = t
504503 or
505504 // recursive case
506505 exists ( TypeAbstraction midAbs , TypeMention midSup , TypeMention midSub |
507- typeSatisfiesConstraint ( abs , sub , midSup ) and
508- TypeTreeUtils< TypeMention , TypeMention > :: isInstantiationOf ( abs , midSup , midSub ) and
506+ typeMentionSatisfiesConstraint ( abs , sub , midSup ) and
507+ // NOTE: `midAbs` describe the free type variables in `midSub`, hence
508+ // we use that for instantiation check.
509+ IsInstantiationOf< TypeMention , IsInstantiationOfInput > :: isInstantiationOf ( midSup , midAbs ,
510+ midSub ) and
509511 (
510512 typeSatisfiesConstraintTrans ( midAbs , midSub , sup , path , t ) and
511513 not t = abs .getATypeParameter ( )
0 commit comments