private static boolean canChangeTo(@NotNull Project project, @NotNull VarianceCandidate candidate, boolean isExtends) {
    @NotNull PsiMethod method = candidate.method;
    PsiCodeBlock methodBody = method.getBody();
    if (methodBody == null) return false;

    PsiClassType newParameterType = suggestMethodParameterType(candidate, isExtends);

    PsiMethod methodCopy = DebugUtil
      .performPsiModification("Creating method copy", () -> createMethodCopy(project, candidate.method, candidate.methodParameterIndex, newParameterType));
    PsiClass containingClass = candidate.method.getContainingClass();
    PsiField field = findFieldAssignedFromMethodParameter(candidate.methodParameter, method);
    List<PsiElement> superMethodsCalls = new ArrayList<>(); // shouldn't error-check these because they're not generalized yet
    findSuperMethodCallsInside(methodCopy, candidate.superMethods, superMethodsCalls);
    // for same-named methods we have to copy the class because the specific method would not be resolved otherwise
    if (field == null && containingClass.findMethodsByName(candidate.method.getName()).length == 1) {
      // check body only to avoid messing with @Override annotations errors
      return errorChecks(methodCopy.getBody(), superMethodsCalls);
    }
    // not anonymous nor local
    if (containingClass.getQualifiedName() != null) {
      // field can be referenced from anywhere in the file
      PsiMethod methodCopyInClass = DebugUtil.performPsiModification("Creating class copy",
                                    () -> createClassCopy(project, field, containingClass, candidate.method, methodCopy, newParameterType));
      Collection<PsiMethod> methodsToErrorCheck;

      // check all field usages in the file
      if (field != null) {
        PsiClass classCopy = methodCopyInClass.getContainingClass();
        int fieldIndex = ArrayUtil.indexOf(containingClass.getFields(), field);
        if (fieldIndex == -1) return false;
        PsiField fieldCopy = classCopy.getFields()[fieldIndex];
        Collection<PsiReference> refs = ReferencesSearch.search(fieldCopy, new LocalSearchScope(classCopy)).findAll();
        Map<PsiMethod, List<PsiReference>> collect =
          refs.stream()
            // map null to "method" to filter it out later
            .collect(Collectors.groupingBy(ref -> ObjectUtils.notNull(PsiTreeUtil.getParentOfType(ref.getElement(), PsiMethod.class), method)));
        methodsToErrorCheck = ContainerUtil.filter(collect.keySet(), k->k != method);
      }
      else {
        methodsToErrorCheck = Collections.singletonList(methodCopyInClass);
      }

      for (PsiMethod psiMethodCopy : methodsToErrorCheck) {
        PsiCodeBlock body = psiMethodCopy.getBody();
        if (body != null && !errorChecks(body, superMethodsCalls)) return false;
      }

      return true;
    }
    // for anon/local have to copy containing method
    PsiMethod containingMethod = PsiTreeUtil.getParentOfType(containingClass, PsiMethod.class);
    if (containingMethod != null) {
      PsiMethod containingMethodCopy = DebugUtil
        .performPsiModification("Creating method copy", () -> createMethodCopy(project, containingMethod, -1, newParameterType));

      // find anon class in the copy
      int anonClassOffsetInContainingMethod = containingClass.getTextRange().getStartOffset() - containingMethod.getTextRange().getStartOffset();
      PsiElement element = containingMethodCopy.findElementAt(anonClassOffsetInContainingMethod);
      PsiClass containingClassCopy = PsiTreeUtil.getParentOfType(element, containingClass.getClass(), false);
      PsiMethod newMethodCopy = containingClassCopy.getMethods()[ArrayUtil.indexOf(containingClass.getMethods(), candidate.method)];
      PsiTypeElement paramTE = Objects.requireNonNull(newMethodCopy.getParameterList().getParameter(candidate.methodParameterIndex)).getTypeElement();
      ReplaceWithQuestionTFix.replaceType(project, paramTE, newParameterType);

      findSuperMethodCallsInside(newMethodCopy, candidate.superMethods, superMethodsCalls);
      return errorChecks(newMethodCopy.getBody(), superMethodsCalls);
    }

    return false;
  }
private static boolean canChangeTo(@NotNull Project project, @NotNull VarianceCandidate candidate, boolean isExtends)