Types.isSameType() unification

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Mon Jan 22 09:34:47 UTC 2018


Hi B.

interesting approach, thanks for the patch; digging a bit into the 
history the loose vs. strict dichotomy started here:

http://hg.openjdk.java.net/lambda/lambda/langtools/rev/1df20330f6bd#l1.63

As you can see, javac started out with a loose behavior, but then a 
stricter semantics (closer to JLS) was required during incorporation: 
e.g. a new bound should be added to an inference var only if this bound 
is different from the existing ones; the loose same-ness check would 
consider cloned inference-vars equivalent and, as such, was missing out 
on some extra constraints - hence the strict version.

At the time it did not occur to me that, maybe, the loose version was 
just wrong and the compiler could be better off with the stricter 
version; also, since we were in the middle of replacing an inference 
engine with a new one, we were trying to limit the impact of new changes 
as much as possible.

Since your patch makes strict behavior the only choice, the problem with 
inference variable bounds is naturally addressed - but of course all 
code calling isSameTypes normally would now see a change in behavior, so 
we need to make sure that the new behavior is acceptable in all cases. 
But your analysis seems to suggest that most of the stuff just works and 
that was just me being overly conservative at the time - in which case 
we can happily change the code, and eliminate this source of complexity.

I'll do some more tests on your patch and see how it goes.

Maurizio


On 20/01/18 22:17, B. Blaser wrote:
> Hi,
>
> As noted previously in [1], 'isSameTypeLoose' doesn't work properly
> with '==' instances of a same type variable with recursive bounds
> which is indeed wrong.
>
> Moreover, 'isSameType' should be the unique 'isSameTypeStrict'
> relation as explained in [2].
>
> So, I simply tried to remove 'isSameTypeLoose' but I got, of course,
> some failing tests like [3] & [4].
>
> As it seems that 'isSameTypeStrict' is too strict for wildcards I kept
> the default behavior in such cases, as here under.
>
> I did this experiment on a quite old JDK10 revision (sorry) with
> encouraging test results (nothing seems to be broken).
>
> What do you think?
>
> Thanks,
> Bernard
>
> [1] http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011291.html
> [2] http://mail.openjdk.java.net/pipermail/compiler-dev/2017-November/011296.html
> [3] tools/javac/generics/wildcards/neg/CastTest.java
> [4] tools/javac/generics/wildcards/pos/CastTest.java
>
> diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
> b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
> @@ -1031,9 +1031,7 @@
>           return isSameType(t, s, false);
>       }
>       public boolean isSameType(Type t, Type s, boolean strict) {
> -        return strict ?
> -                isSameTypeStrict.visit(t, s) :
> -                isSameTypeLoose.visit(t, s);
> +        return isSameTypeStrict.visit(t, s);
>       }
>       // where
>           abstract class SameTypeVisitor extends TypeRelation {
> @@ -1177,44 +1175,6 @@
>           }
>
>           /**
> -         * Standard type-equality relation - type variables are considered
> -         * equals if they share the same type symbol.
> -         */
> -        TypeRelation isSameTypeLoose = new LooseSameTypeVisitor();
> -
> -        private class LooseSameTypeVisitor extends SameTypeVisitor {
> -
> -            /** cache of the type-variable pairs being (recursively) tested. */
> -            private Set<TypePair> cache = new HashSet<>();
> -
> -            @Override
> -            boolean sameTypeVars(TypeVar tv1, TypeVar tv2) {
> -                return tv1.tsym == tv2.tsym && checkSameBounds(tv1, tv2);
> -            }
> -            @Override
> -            protected boolean containsTypes(List<Type> ts1, List<Type> ts2) {
> -                return containsTypeEquivalent(ts1, ts2);
> -            }
> -
> -            /**
> -             * Since type-variable bounds can be recursive, we need
> to protect against
> -             * infinite loops - where the same bounds are checked
> over and over recursively.
> -             */
> -            private boolean checkSameBounds(TypeVar tv1, TypeVar tv2) {
> -                TypePair p = new TypePair(tv1, tv2, true);
> -                if (cache.add(p)) {
> -                    try {
> -                        return visit(tv1.getUpperBound(), tv2.getUpperBound());
> -                    } finally {
> -                        cache.remove(p);
> -                    }
> -                } else {
> -                    return false;
> -                }
> -            }
> -        };
> -
> -        /**
>            * Strict type-equality relation - type variables are considered
>            * equals if they share the same object identity.
>            */
> @@ -1227,17 +1187,6 @@
>               protected boolean containsTypes(List<Type> ts1, List<Type> ts2) {
>                   return isSameTypes(ts1, ts2, true);
>               }
> -
> -            @Override
> -            public Boolean visitWildcardType(WildcardType t, Type s) {
> -                if (!s.hasTag(WILDCARD)) {
> -                    return false;
> -                } else {
> -                    WildcardType t2 = (WildcardType)s;
> -                    return t.kind == t2.kind &&
> -                            isSameType(t.type, t2.type, true);
> -                }
> -            }
>           };
>
>       // </editor-fold>



More information about the compiler-dev mailing list