Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make java compiler output type inference information

Is it possible to get javac to output information about the types it's inferring for method invocations?

For example, I want to know what is inferred for the formal type T in the invocation of bar.

private static <T> void bar() { ... }
public void foo() {
  bar();
}

I was exploring javac -Xprint and friends, but can't find anything that exposes this level of detail.


EDIT Example. I didn't want to put this up originally because it'll complicate answers. I'm primarily interested in getting debug info out of javac. Anyway, this was the motivating example:

public class Scratch {
  private static <T extends Throwable> void sneakyThrow(Throwable t) throws T {
    throw (T) t; // Warning: Type safety: Unchecked cast from Throwable to T
  }
  public void foo() {
    sneakyThrow(new Exception());
  }
}

This compiles, but any reasonable decision as to the actual type of T should yield Throwable, and require that foo() throws Throwable. Eclipse seems to think it's RuntimeException. I want to know what javac thinks is happening. If it's a bug in javac's processing of type parameters in the throws clause, the answer to this question would allow me to prove it.

like image 434
Joe Kearney Avatar asked Jun 18 '14 11:06

Joe Kearney


People also ask

What is Java type inference?

Type inference is a Java compiler's ability to look at each method invocation and corresponding declaration to determine the type argument (or arguments) that make the invocation applicable.

What is type inference in compiler?

Type inference is the ability to automatically deduce, either partially or fully, the type of an expression at compile time. The compiler is often able to infer the type of a variable or the type signature of a function, without explicit type annotations having been given.

Why does Java not have type inference?

So, I can imagine that type inference was probably not supported because Java was aimed at programmers coming from C++, Pascal, or other mainstream languages that did not have it (principle of least surprise).


1 Answers

It's possible to see with a lot of detail what javac has inferred / resolved etc. To do that you need to use the hidden / unsupported / undocumented option: -XDverboseResolution. If one want to see all the information then the value to pass is 'all' as in: -XDverboseResolution=all. If one only want to see the instantiation of the generic methods then the option is: -XDverboseResolution=deferred-inference. For the code in the original question I get the following output:

command: javac -XDverboseResolution=deferred-inference Scratch.java

output:

Scratch.java:6: Note: Deferred instantiation of method <T>sneakyThrow(Throwable)
    sneakyThrow(new Exception());
               ^
  instantiated signature: (Throwable)void
  target-type: <none>
  where T is a type-variable:
    T extends Throwable declared in method <T>sneakyThrow(Throwable)
Note: Scratch.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

From this output you can infer that T has been instantiated to Throwable.

I hope this is what you were looking for.

like image 171
Vicente Romero Avatar answered Nov 02 '22 22:11

Vicente Romero