code: public static void walk(final Type one, final Type two, final TypesVisitor visitor) {
          // Use possibly more specific generics (otherwise root class generics would be used as Object and this
          // way it could be used as upper bound)
          // Also, types could contain outer class generics declarations, which must be preserved
          // e.g. (Outer<String>.Inner field).getGenericType() == ParameterizedType with parametrized owner
          // Wrapped into ignore map for very specific case, when type is TypeVariable
          final Map<String, Type> oneKnownGenerics =
                  new IgnoreGenericsMap(GenericsResolutionUtils.resolveGenerics(one, IGNORE_VARS));
          final Map<String, Type> twoKnownGenerics =
                  new IgnoreGenericsMap(GenericsResolutionUtils.resolveGenerics(two, IGNORE_VARS));
          // Resolve variables mainly to simplify empty wildcards (? extends Object and ? super Object) to Object
          // Still have to pass map because of possibly declared outer class generics. Note that for all
          // types operations ignoring map could be used as we already replaced all variables. These generics
          // are required only for type context building (on some level to resolve comparable type)
          doWalk(GenericsUtils.resolveTypeVariables(one, oneKnownGenerics), oneKnownGenerics,
                  GenericsUtils.resolveTypeVariables(two, twoKnownGenerics), twoKnownGenerics, visitor);
      }
docs: Walk will stop if visitor tells it's enough or when hierarchy incompatibility will be found.
  
  @param one     first type
  @param two     second type
  @param visitor visitor