public static boolean isUncheckedCast(@NotNull PsiType castType, @NotNull PsiType operandType) {
    if (TypeConversionUtil.isAssignable(castType, operandType, false)) return false;

    castType = castType.getDeepComponentType();
    if (castType instanceof PsiClassType) {
      final PsiClassType castClassType = (PsiClassType)castType;
      operandType = operandType.getDeepComponentType();
      if (operandType instanceof PsiCapturedWildcardType) {
        operandType = ((PsiCapturedWildcardType)operandType).getUpperBound();
      }

      if (!(operandType instanceof PsiClassType)) return false;
      final PsiClassType operandClassType = (PsiClassType)operandType;
      final PsiClassType.ClassResolveResult castResult = castClassType.resolveGenerics();
      final PsiClassType.ClassResolveResult operandResult = operandClassType.resolveGenerics();
      final PsiClass operandClass = operandResult.getElement();
      final PsiClass castClass = castResult.getElement();

      if (operandClass == null || castClass == null) return false;
      if (castClass instanceof PsiTypeParameter) return true;

      if (castClassType.hasNonTrivialParameters()) {
        if (operandClassType.isRaw()) return true;
        if (castClass.isInheritor(operandClass, true)) {
          PsiSubstitutor castSubstitutor = castResult.getSubstitutor();
          PsiElementFactory factory = JavaPsiFacade.getElementFactory(castClass.getProject());
          for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(castClass)) {
            //only parameters declared in containing classes
            if (typeParameter.getOwner() instanceof PsiMethod) {
              continue;
            }
            PsiSubstitutor modifiedSubstitutor = castSubstitutor.put(typeParameter, null);
            PsiClassType otherType = factory.createType(castClass, modifiedSubstitutor);
            if (TypeConversionUtil.isAssignable(operandType, otherType, false)) return true;
          }
          //from Java7. Java 6 now is unsupported
          //according to `Checked and Unchecked Narrowing Reference Conversions`
          PsiSubstitutor superSubstitutor =
            TypeConversionUtil.getSuperClassSubstitutor(operandClass, castClass, castResult.getSubstitutor());
          PsiSubstitutor operandSubstitutor = operandResult.getSubstitutor();
          PsiClass superClass = operandResult.getElement();
          if (superClass == null) {
            return true;
          }
          Set<PsiTypeParameter> capturedWildcardType = new HashSet<>();
          for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(operandClass)) {
            //only parameters declared in containing classes
            if (parameter.getOwner() instanceof PsiMethod) {
              continue;
            }
            PsiType operandParameterType = operandSubstitutor.substitute(parameter);
            if (operandParameterType instanceof PsiCapturedWildcardType) {
              capturedWildcardType.add(parameter);
            }
            PsiType superParameterType = superSubstitutor.substitute(parameter);
            if (operandParameterType != null &&
                superParameterType != null &&
                !TypeConversionUtil.typesAgree(superParameterType, operandParameterType, false)) {
              return true;
            }
          }
          return !capturedWildcardTypesAreNotMerged(capturedWildcardType, operandClass, castClass);
        }
        return true;
      }
    }

    return false;
  }
public static boolean isUncheckedCast(@NotNull PsiType castType, @NotNull PsiType operandType)