boolean (@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)) { 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)) { 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; }