PsiSubstitutor (PsiSubstitutor outer, PsiSubstitutor inner, PsiClass onClass) { PsiSubstitutor answer = PsiSubstitutor.EMPTY; Map<PsiTypeParameter, PsiType> outerMap = outer.getSubstitutionMap(); Map<PsiTypeParameter, PsiType> innerMap = inner.getSubstitutionMap(); for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(onClass)) { if (outerMap.containsKey(parameter) || innerMap.containsKey(parameter)) { PsiType innerType = inner.substitute(parameter); PsiClass paramCandidate = PsiCapturedWildcardType.isCapture() ? PsiUtil.resolveClassInClassTypeOnly(innerType) : null; PsiType targetType; if (paramCandidate instanceof PsiTypeParameter && paramCandidate != parameter) { targetType = outer.substituteWithBoundsPromotion((PsiTypeParameter)paramCandidate); if (targetType != null && innerType.getAnnotations().length > 0) { PsiAnnotation[] typeAnnotations = targetType.getAnnotations(); targetType = targetType.annotate(() -> ArrayUtil.mergeArrays(innerType.getAnnotations(), typeAnnotations)); } } else { targetType = outer.substitute(innerType); } answer = answer.put(parameter, targetType); } } return answer; }