@Override
    public PsiType apply(final PsiType type) {
      if (type instanceof PsiTypeVariable) {
        final PsiType t = myBindings.get(((PsiTypeVariable) type).getIndex());
        return t == null ? type : t;
      }
      else if (type instanceof PsiArrayType) {
        return apply(((PsiArrayType)type).getComponentType()).createArrayType();
      }
      else if (type instanceof PsiClassType) {
        final PsiClassType.ClassResolveResult result = Util.resolveType(type);
        final PsiClass theClass = result.getElement();
        final PsiSubstitutor aSubst = result.getSubstitutor();

        PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;

        if (theClass != null) {
          for (final PsiTypeParameter aParm : aSubst.getSubstitutionMap().keySet()) {
            final PsiType aType = aSubst.substitute(aParm);

            theSubst = theSubst.put(aParm, apply(aType));
          }

          return JavaPsiFacade.getElementFactory(theClass.getProject()).createType(theClass, theSubst);
        }
        else {
          return type;
        }
      }
      else if (type instanceof PsiWildcardType wcType) {
        final PsiType bound = wcType.getBound();

        if (bound != null) {
          final PsiType abound = apply(bound);

          if (abound instanceof PsiWildcardType) {
            return null;
          }

          return
            wcType.isExtends()
            ? PsiWildcardType.createExtends(PsiManager.getInstance(myProject), abound)
            : PsiWildcardType.createSuper(PsiManager.getInstance(myProject), abound);
        }

        return type;
      }
      else {
        return type;
      }
    }
@Override
    public PsiType apply(final PsiType type)