boolean (@NotNull PsiClass recordClass, @NotNull PsiType type, PsiElementFactory factory, InferenceSession session) { if (type instanceof PsiClassType) { PsiClassType classType = (PsiClassType)type; PsiClassType.ClassResolveResult result = classType.resolveGenerics(); PsiClass gClass = result.getElement(); if (gClass == null) return false; List<PsiTypeParameter> wildcardTypeParams = new ArrayList<>(); List<PsiWildcardType> wildcardTypes = new ArrayList<>(); PsiType[] arguments = classType.getParameters(); PsiTypeParameter[] parameters = gClass.getTypeParameters(); for (int i = 0; i < arguments.length; i++) { PsiType argument = arguments[i]; if (argument instanceof PsiWildcardType && i < parameters.length) { wildcardTypeParams.add(parameters[i]); wildcardTypes.add((PsiWildcardType)argument); } } if (!wildcardTypeParams.isEmpty()) { InferenceVariable[] variables = session.initOrReuseVariables(session.getContext(), wildcardTypeParams.toArray(PsiTypeParameter.EMPTY_ARRAY)); PsiSubstitutor newSubstitutor = result.getSubstitutor(); for (int i = 0; i < variables.length; i++) { PsiWildcardType wildcardType = wildcardTypes.get(i); if (wildcardType.isExtends()) { variables[i].addBound(wildcardType.getExtendsBound(), InferenceBound.UPPER, null); } else if (wildcardType.isSuper()) { variables[i].addBound(wildcardType.getExtendsBound(), InferenceBound.LOWER, null); } newSubstitutor = newSubstitutor.put(wildcardTypeParams.get(i), factory.createType(variables[i])); } type = factory.createType(gClass, newSubstitutor); } if (gClass instanceof PsiTypeParameter) { for (PsiClassType upperBound : gClass.getExtendsListTypes()) { if (!addConstraints(recordClass, upperBound, factory, session)) return false; } } else if (InheritanceUtil.isInheritorOrSelf(recordClass, gClass, true)) { PsiClassType rAType = factory.createType(recordClass, session.getInferenceSubstitution()); PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(gClass, rAType); PsiType recordPrimeType = factory.createType(gClass, superClassSubstitutor); session.addConstraint(new TypeEqualityConstraint(type, recordPrimeType)); } } if (type instanceof PsiIntersectionType) { for (PsiType conjunct : ((PsiIntersectionType)type).getConjuncts()) { if (!addConstraints(recordClass, conjunct, factory, session)) return false; } } return true; }