boolean (InferenceSession session, Set<? super InferenceVariable> dependencies, List<? super ConstraintFormula> constraints) { if (!session.collectDependencies(myS, dependencies) && !session.collectDependencies(myT, dependencies)) { if (myT == null) return myS == null || myS.equalsToText(CommonClassNames.JAVA_LANG_OBJECT); if (myS == null) return true; return TypeConversionUtil.isAssignable(myT, myS); } if (PsiTypes.nullType().equals(myT) || myT == null) return false; if (PsiTypes.nullType().equals(myS) || myS == null || myT.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return true; if (PsiTypes.voidType().equals(myS) ^ PsiTypes.voidType().equals(myT)) return false; InferenceVariable inferenceVariable = session.getInferenceVariable(myS); if (inferenceVariable != null) { InferenceVariable.addBound(myS, myT, InferenceBound.UPPER, session); return true; } inferenceVariable = session.getInferenceVariable(myT); if (inferenceVariable != null) { InferenceVariable.addBound(myT, myS, InferenceBound.LOWER, session); return true; } if (myT instanceof PsiArrayType) { PsiType sType = myS; if (myS instanceof PsiCapturedWildcardType) { final PsiType upperBound = ((PsiCapturedWildcardType)myS).getUpperBound(); if (upperBound instanceof PsiArrayType) { sType = upperBound; } } if (!(sType instanceof PsiArrayType)) return false; //todo most specific array supertype final PsiType tComponentType = ((PsiArrayType)myT).getComponentType(); final PsiType sComponentType = ((PsiArrayType)sType).getComponentType(); if (!(tComponentType instanceof PsiPrimitiveType) && !(sComponentType instanceof PsiPrimitiveType)) { constraints.add(new StrictSubtypingConstraint(tComponentType, sComponentType, myCapture)); return true; } return sComponentType instanceof PsiPrimitiveType && sComponentType.equals(tComponentType); } if (myT instanceof PsiClassType) { final PsiClassType.ClassResolveResult TResult = ((PsiClassType)myT).resolveGenerics(); final PsiClass CClass = TResult.getElement(); if (CClass != null) { if (CClass instanceof PsiTypeParameter) { if (myS instanceof PsiIntersectionType) { if (ArrayUtil.contains(myT, ((PsiIntersectionType)myS).getConjuncts())) { return true; } } final PsiType lowerBound = TypeConversionUtil.getInferredLowerBoundForSynthetic((PsiTypeParameter)CClass); if (lowerBound != null) { constraints.add(new StrictSubtypingConstraint(lowerBound, myS, myCapture)); return true; } return false; } if (myS instanceof PsiArrayType) { return myT.isAssignableFrom(myS); } PsiClassType sType = getSubclassType(CClass, myS, myCapture); if (sType == null) return false; final PsiClassType.ClassResolveResult SResult = sType.resolveGenerics(); PsiClass SClass = SResult.getElement(); if (SClass == null) return false; if (((PsiClassType)myT).isRaw() || myCapture && sType.isRaw()) { return InheritanceUtil.isInheritorOrSelf(SClass, CClass, true); } PsiSubstitutor substitutor = SResult.getSubstitutor(); Map<PsiTypeParameter, PsiType> map = new HashMap<>(); for (PsiTypeParameter typeParameter : SClass.getTypeParameters()) { map.put(typeParameter, substitutor.substituteWithBoundsPromotion(typeParameter)); } substitutor = substitutor.putAll(map); final PsiSubstitutor tSubstitutor = TResult.getSubstitutor(); final PsiSubstitutor sSubstitutor = TypeConversionUtil.getClassSubstitutor(CClass, SClass, substitutor); if (sSubstitutor != null) { for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(CClass)) { final PsiType tSubstituted = tSubstitutor.substitute(parameter); final PsiType sSubstituted = sSubstitutor.substitute(parameter); if (tSubstituted == null ^ sSubstituted == null) { return false; } constraints.add(new SubtypingConstraint(tSubstituted, sSubstituted)); } return true; } } return false; } if (myT instanceof PsiIntersectionType) { for (PsiType conjunct : ((PsiIntersectionType)myT).getConjuncts()) { constraints.add(new StrictSubtypingConstraint(conjunct, myS, myCapture)); } return true; } if (myT instanceof PsiCapturedWildcardType) { PsiType lowerBound = ((PsiCapturedWildcardType)myT).getLowerBound(); if (lowerBound != PsiTypes.nullType()) { constraints.add(new StrictSubtypingConstraint(lowerBound, myS, myCapture)); } } return true; }