@Override
            public Boolean visitClassType(ClassType t, Type s) {
                if (t == s)
                    return true;

                if (s.tag >= firstPartialTag)
                    return visit(s, t);

                if (s.isSuperBound() && !s.isExtendsBound())
                    return visit(t, upperBound(s)) && visit(t, lowerBound(s));

                if (t.isCompound() && s.isCompound()) {
                    if (!visit(supertype(t), supertype(s)))
                        return false;

                    HashSet<SingletonType> set = new HashSet<SingletonType>();
                    for (Type x : interfaces(t))
                        set.add(new SingletonType(x));
                    for (Type x : interfaces(s)) {
                        if (!set.remove(new SingletonType(x)))
                            return false;
                    }
                    return (set.isEmpty());
                }
                return t.tsym == s.tsym
                    && visit(t.getEnclosingType(), s.getEnclosingType())
                    && containsTypeEquivalent(t.getTypeArguments(), s.getTypeArguments());
            }