docs: static ImmutableMap<ExecutableElement, TypeMirror> rewriteReturnTypes(
        Elements elementUtils,
        Types typeUtils,
        Collection<ExecutableElement> methods,
        TypeElement sourceType,
        TypeElement targetType) {
      List<? extends TypeParameterElement> sourceTypeParameters = sourceType.getTypeParameters();
      List<? extends TypeParameterElement> targetTypeParameters = targetType.getTypeParameters();
      Preconditions.checkArgument(
          sourceTypeParameters.toString().equals(targetTypeParameters.toString()),
          "%s != %s",
          sourceTypeParameters,
          targetTypeParameters);
      // What we're doing is only valid if the type parameters are "the same". The check here even
      // requires the names to be the same. The logic would still work without that, but we impose
      // that requirement elsewhere and it means we can check in this simple way.
      EclipseHack eclipseHack = new EclipseHack(elementUtils, typeUtils);
      TypeMirror[] targetTypeParameterMirrors = new TypeMirror[targetTypeParameters.size()];
      for (int i = 0; i < targetTypeParameters.size(); i++) {
        targetTypeParameterMirrors[i] = targetTypeParameters.get(i).asType();
      }
      DeclaredType parallelSource = typeUtils.getDeclaredType(sourceType, targetTypeParameterMirrors);
      return methods.stream()
          .collect(
              ImmutableMap.toImmutableMap(
                  m -> m, m -> eclipseHack.methodReturnType(m, parallelSource)));
    }