code: public static Type build(final Type type, final Type source) {
          if (!TypeUtils.isAssignable(type, source)) {
              throw new IllegalArgumentException(String.format(
                      "Can't track type %s generics because it's not assignable to %s",
                      TypeToStringUtils.toStringType(type),
                      TypeToStringUtils.toStringTypeIgnoringVariables(source)));
          }
  
          Type res = type;
  
          if (ArrayTypeUtils.isArray(type) && ArrayTypeUtils.isArray(source)) {
              // for arrays track actual component types
              res = ArrayTypeUtils.toArrayType(
                      build(ArrayTypeUtils.getArrayComponentType(type), ArrayTypeUtils.getArrayComponentType(source)));
          } else {
              final Class<?> target = GenericsUtils.resolveClass(type);
              // it make sense to track from direct parameterized type or parameterized types inside wildcard
              if (target.getTypeParameters().length > 0
                      && (source instanceof ParameterizedType || source instanceof WildcardType)) {
  
                  // select the most specific generics
                  final Map<String, Type> generics = resolveGenerics(type, target, source);
                  // empty generics may appear from wildcard without parameterized types (no source)
                  if (!generics.isEmpty()) {
                      res = new ParameterizedTypeImpl(target,
                              generics.values().toArray(new Type[0]),
                              // intentionally not tracking owner type as redundant complication
                              TypeUtils.getOuter(type));
                  }
              }
          }
  
          return res;
      }
docs: Sub type must be either {@link ParameterizedType} or {@link WildcardType} containing parameterized types,
  because otherwise tracking is impossible (no source to track from) and so orignial type is simply returned as is.
  <p>
  In case of arrays, internal components are directly compared.
  
  @param type   type to track generics for
  @param source type to track generics from (middle type)
  @return improved type or original type itself if nothing to track
  @throws IllegalArgumentException if type is not assignable for provided sub type