private static Type projectionTypeInternal(Projection<?> projection) throws ClassNotFoundException, NoSuchFieldException {
    Objects.requireNonNull(projection, "projection");
    final Path path = (Path) Matchers.toExpression(projection);
    AnnotatedElement element = path.element();
    final Class<?> declaringClass;
    if (element instanceof Field) {
      declaringClass = ((Field) element).getDeclaringClass();
    } else if (element instanceof Method) {
      declaringClass = ((Method) element).getDeclaringClass();
    } else {
      throw new IllegalArgumentException(String.format("Expected %s to be either field or method but was %s", path, element.getClass().getName()));
    }

    // manually get criteria class
    Class<?> criteriaClass = Class.forName(declaringClass.getPackage().getName() + "." + declaringClass.getSimpleName() + "Criteria");

    Field field = criteriaClass.getField(path.toStringPath());
    for (Type type: field.getType().getGenericInterfaces()) {
      if (type instanceof ParameterizedType && ((ParameterizedType) type).getRawType() == Projection.class) {
        // resolve Projection<P>
        Type resolved = TypeToken.of(field.getGenericType()).resolveType(type).getType();
        return ((ParameterizedType) resolved).getActualTypeArguments()[0];
      }
    }

    throw new IllegalArgumentException(String.format("Couldn't resolve type variable (%s) for %s %s", Projection.class.getSimpleName(), path, element));
  }
Get compile-time version of projection. P parameter for {@code Projection<P>}
criteria/common/test/org/immutables/criteria/matcher/ReturnTypeTest.java