Push 23 August 1bb5b46bb326 fixes one bug, but introduces another

Peter Levart peter.levart at marand.si
Fri Aug 27 02:03:23 PDT 2010


On 08/24/10, Maurizio Cimadamore wrote:
> On 24/08/10 09:07, Howard Lovatt wrote:
> > Hi Maurizio,
> >
> >        il.forEach( #( i ) {
> >          if ( i<  3 ) { throw new Exception(); }
> >          return i * i;
> >        } ); // Need to catch the checked exception!
> >
> > Now needs a try block (as it should), but
> >
> >      il.forEach( #( i ) { return 2 * i; } ); // No exception, no try block
> >
> >   Also needs one and it shouldn't!
> >    
> Strictly speaking, this is not a bug - it is a limitation of the current 
> inference scheme that has been noticed elsewhere in this forum; 

Hi Maurizio,

Yes, I think that inference scheme has to be improved too.

 I haven't looked into the details yet. Maybe that is why I don't entirely understand this reasoning:

> unfortunately, when the body of the lambda expression has resolution 
> (e.g. operator/method) depending on the type of the parameter to be 
> inferred, javac cannot infer the thrown types from the lambda body; as 
> such, thrown types are inferred from the target type - in this case, the 
> target types throws E, whose bound is Exception - since no constraint is 
> found (from the lambda), E is simply instantiated to Exception.

Do you have to infer the thrown types of the lambda body even before the lambda body is "resolved" ? Can't this be done afterwards?

Maybe it's because you are considering lambda's thrown types in the resolution of the code surrounding the lambda expression (for example in the resolution of the invocation of the overloaded method where the lambda expression is one of it's parameters).

For example this program:


public class Closures
{
  public interface IoSam { void run(String s) throws java.io.IOException; }

  public interface TxtSam { void run(String s) throws java.text.ParseException; }

  public static void doIt(IoSam ioSam) throws java.io.IOException
  {
    ioSam.run("IoSam");
  }

  public static void doIt(TxtSam txtSam) throws java.text.ParseException
  {
    txtSam.run("TxtSam");
  }

  public static void main(String[] args) throws Exception
  {
    try
    {
      doIt(#(String s){ System.out.println("Ivoked via " + s); throw new java.io.IOException(); });
    }
    catch (java.io.IOException e) {}

    try
    {
      doIt(#(String s){ System.out.println("Ivoked via " + s); throw new java.text.ParseException(null, 0); });
    }
    catch (java.text.ParseException e) {}
  }
}


prints:


Ivoked via IoSam                                                                                                                                                                                                         
Ivoked via TxtSam                                                                                                                                                                                                        


Which shows that the resolution of overloaded method is taking the throws types of lambda expression into the consideration.

I don't think this is something that is desirable. Lambda return type and parameter types yes, but not throws types. They should just be checked and always inferred in direction "lambda expression" -> SAM method throws type parameter...

That is my simplified view of the matter. What do you think?

Regards, Peter

> 
> However I understand that this is something that needs to be improved - 
> it is showing up now because of  the bug I fixed in the compiler (the 
> compiler was assuming that no exception where thrown when inference gave 
> up - which is potentially unsafe).
> 
> Maurizio



More information about the lambda-dev mailing list