From daniel.smith at oracle.com Mon Jan 6 16:44:22 2014 From: daniel.smith at oracle.com (Dan Smith) Date: Mon, 6 Jan 2014 17:44:22 -0700 Subject: JSR 335 Lambda Specification, 0.9.1 Message-ID: <5197E315-E88E-4B04-83A1-98CC28D81B1A@oracle.com> An updated specification can be found here: http://cr.openjdk.java.net/~dlsmith/jsr335-0.9.1/ This contains some small tweaks that I'd like to include with the Proposed Final Draft; I'll simply update the language spec portion of the preview bundle I shared previously. Other links Diff: http://cr.openjdk.java.net/~dlsmith/jsr335-0.9.1-diff.html One-page HTML: http://cr.openjdk.java.net/~dlsmith/jsr335-0.9.1.html Downloadable zip: http://cr.openjdk.java.net/~dlsmith/jsr335-0.9.1.zip Full change log, from the document: > Introduction: Added brief discussions about exception transparency and speculative checking during overload resolution. > > Method References: Removed the TypeName::m form of unbound method reference, which turned out to be unnecessary and introduced many complications. > > Poly Expressions: Added a note clarifying that poly conditionals do not have to contain poly expressions. > > Typing and Evaluation: Removed mentions of the TypeName::m method reference form. Allowed raw inner class types to be used in exact constructor references (because diamond inference cannot occur). > > Overload Resolution: Eliminated unnecessary uses of the qualifier "poly" in discussions of conditional expressions. > > Type Inference: Modified exception checking constraints so that they only exist for LambdaExpressions and MethodReferences (these constraints were previously generated for all other forms of expressions, and then trivially reduced to true). > > Default Methods: Tweaked inheritance rule for interfaces so that a static/non-static clash would be properly detected. > > Java Virtual Machine: Clarified that only 52.0 class files can allow InterfaceMethodrefs in method references of the kind invokeStatic andinvokeSpecial. The EG may be particularly interested in the additional "Potential Future Enhancements" discussions, so let me reproduce them here: > Special Exception Checking for Lambda Body Invocations > > A checked exception thrown by a lambda body should be identified by the type system wherever the corresponding method is invoked. This is supported in a limited way by allowing functional interface methods to have throws clauses?then, naturally, the method invocation knows what exceptions may be thrown. It is also possible to use a type parameter of a functional interface in the throws clause, thus allowing a thrown exception type to be inferred (by, say, the invocation of a library method that accepts a lambda argument). > > However, generics are not well-suited to the problem of representing the exceptions thrown by a block of code. In the common case (zero checked exceptions), an extra type parameter is a painful clerical burden (for example, Function becomes Function). And in cases in which multiple exceptions are thrown, there is no way to provide a list of types as a type argument. Even with workarounds for these problems, it is difficult to write lambda-friendly library code that properly accounts for all the exception types thrown by the provided lambda bodies. > > A more ambitious solution would be to special-case the treatment of lambdas in the compiler's exception checking logic, detecting the locations in which the checked exceptions of a lambda body may manifest themselves without relying on the throws clause of the functional interface. This would eliminate any clerical burden on programmers, while still providing strong exception checking; but it would require the compiler to perform advanced analysis techniques. > > Speculative Type Checking During Overload Resolution > > Implicitly-typed lambda expressions (that is, lambdas with parameters that do not declare their types) and inexact method references (that is, references to overloaded or generic methods) cannot be type-checked before their parameter types are known. These types are derived from the targeted functional interface type. In the case of a method invocation argument (e.g., m(x -> x.foo())), if the method being invoked is overloaded, there may be multiple possible target types, one for each overloaded method declaration. > > The approach developed here is to ignore the lambda expression or method reference until after overload resolution decides on the method to be invoked?the lambda argument is not pertinent to applicability. Once overload resolution completes, the lambda body can be type-checked. > > Another possible approach is to type-check the lambda body or method reference speculatively, once for each possible target type. This provides a more powerful disambiguation mechanism for overload resolution?the use of lambda parameters in the lambda body may clarify which parameter type was expected. However, there are a number of challenges: users must consider multiple possible typings when reading a block of code; program behavior depends on subtle type errors; worst-case computational complexity is exponential. And in some cases, it is still necessary to ignore lambda expressions during overload resolution, because the parameter types are inferred from the method invocation's own target type. I know there are a variety of other features that didn't make the cut (we assembled a list back in July, which I'll reproduce for posterity here on the list sometime soon), but among topics that didn't yet have a discussion block, these seemed to me to be the areas that were the most fully pursued, and so deserving of special mention. ?Dan From stephan.herrmann at berlin.de Tue Jan 7 14:22:27 2014 From: stephan.herrmann at berlin.de (Stephan Herrmann) Date: Tue, 07 Jan 2014 23:22:27 +0100 Subject: JSR 335 Lambda Specification, 0.9.0 In-Reply-To: <769DA1D4-ACEB-485B-AA70-8C752D4BCF61@oracle.com> References: <769DA1D4-ACEB-485B-AA70-8C752D4BCF61@oracle.com> Message-ID: <52CC7E23.2090906@berlin.de> (all this is about 18.5.2:) From the Changelog of 0.9.0: > Added rules to invocation type inference to special-case when the return type is an inference variable, and may end up either being wildcard-parameterized or requiring unchecked conversion. These changes are causing regressions in our implementation. I might have some other bugs lurking around, but could you please double check: Could some occurrences of R ? be intended to say R instead? Specifically these: - bullet 3.2: "Otherwise, if R ? is a parameterized type ..." - bullet 3.3: "Otherwise, if R ? is an inference variable ? ..." Additionally the use of erasure in bullet 3.1 causes grief. In experiments I do get better results using a raw type instead. Finally: it would be extremely helpful if you could give examples for the new bullets 3.3.1 and 3.3.2. So far I haven't a clue :) thanks, Stephan From daniel.smith at oracle.com Mon Jan 13 15:12:34 2014 From: daniel.smith at oracle.com (Dan Smith) Date: Mon, 13 Jan 2014 16:12:34 -0700 Subject: JSR 335 Lambda Specification, 0.9.0 In-Reply-To: <52CC7E23.2090906@berlin.de> References: <769DA1D4-ACEB-485B-AA70-8C752D4BCF61@oracle.com> <52CC7E23.2090906@berlin.de> Message-ID: <45C5A93A-B917-4A8D-8195-5D7B12546DE5@oracle.com> On Jan 7, 2014, at 3:22 PM, Stephan Herrmann wrote: > (all this is about 18.5.2:) > > From the Changelog of 0.9.0: >> Added rules to invocation type inference to special-case when the return type is an inference variable, and may end up either being wildcard-parameterized or requiring unchecked conversion. > > These changes are causing regressions in our implementation. > I might have some other bugs lurking around, but could you please double check: > Could some occurrences of R ? be intended to say R instead? Specifically these: > - bullet 3.2: "Otherwise, if R ? is a parameterized type ..." > - bullet 3.3: "Otherwise, if R ? is an inference variable ? ..." Yes. All this means is that the type has inference variables in it. (R, before substitution, is the declared return type of the method.) > Additionally the use of erasure in bullet 3.1 causes grief. > In experiments I do get better results using a raw type instead. ? Which raw type? This isn't really new, but simply clarifying/preserving the rule from 15.12.2.6 that, if unchecked conversion occurred, the return type is the erasure. (See JLS 7.) > Finally: it would be extremely helpful if you could give examples for > the new bullets 3.3.1 and 3.3.2. So far I haven't a clue :) R m(R... args); void forEach(List arg); Bullet 3.3.1: I noticed there's an error: bullet 3.3 should say that U is the _capture of_ the instantiation of alpha. Here are two examples: forEach(m((List) null)); Let 'r' and 't' be inference variables. Bounds B2 for m are { List <: r, r <: Object }. It would be incorrect to assert that r -> List -- in reality, the constraint is that the _capture of_ 'r' is a subtype of List. So in this situation we eagerly resolve r = List, perform capture, and then proceed with List<#CAP> -> List. forEach(m((ArrayList) null, (LinkedList) null)); Bounds B2 for m are { List <: r, List <: r, r <: Object }. Again, an error would occur if we required r -> List, but there's no problem if we use lub to resolve r = List and perform capture. Bullet 3.3.2: forEach(m((ArrayList) null)); Bounds B2 for m are { List <: r, r <: Object }. There would be an error if we asserted r <: List. But if we eagerly resolve r = List, then we can do ArrayList -> List and 18.2.2 can do its job by recognizing an unchecked conversion. ?Dan From daniel.smith at oracle.com Mon Jan 13 16:00:42 2014 From: daniel.smith at oracle.com (Dan Smith) Date: Mon, 13 Jan 2014 17:00:42 -0700 Subject: JSR 335 Lambda Specification, 0.9.0 In-Reply-To: <52C157FB.18337.FD4126A@v.a.ammodytes.googlemail.com> References: <769DA1D4-ACEB-485B-AA70-8C752D4BCF61@oracle.com> <52C157FB.18337.FD4126A@v.a.ammodytes.googlemail.com> Message-ID: <6FA2B751-0147-48FA-B439-CFC506FC0351@oracle.com> Responses to some comments received at lambda-spec-comments: On Dec 30, 2013, at 4:24 AM, v.a.ammodytes at googlemail.com wrote: > In Part B, 14.18 (The throw Statement), the appearance of 'in a method declaration' was extended to 'in a method declaration or a lambda expression'. The whole sentence now reads: > >> > If a throw statement is contained in a method declaration or a lambda expression, but its value is not caught by some try statement that contains it, then the invocation of the method completes abruptly because of the throw. > << > > Maybe this is nit-picking, but I'm missing a similar extension of the second half of this rule, because the invocation of a lambda is not the same as the invocation of a method. On the contrary, invocation of a lambda is _only_ via invocation of a method -- there is no other invocation mechanism. (I recognize that the wording in this sentence is subtle, but I didn't want to make a big deal about lambda expressions here by adding a lot of clarifying text.) > In Part G, 18.2.3 (Subtyping Constraints), the algorithm to reduce ?S <: T? where none of the first four cases applies starts with: > >> > If T is a parameterized class or interface type, or an inner class type of a parameterized class or interface type (directly or indirectly), let A1, ..., An be the type arguments appearing in T; among the supertypes (4.10) of S, a corresponding class or interface type is identified, with type arguments B1, ..., Bn. If no such type exists, the constraint reduces to false. Otherwise, the constraint reduces to the following new constraints: for all i, 1 ? i ? n, ?Bi <= Ai?. > << > > This leaves open the question, what shall happen if there exists more than one suitable candidate among the supertypes and the arbitrarily chosen candidate happens to reduce to false later on. > > After digging into some more of part G and following the link to the work of of Kennedy and Pierce in the comments to 18.3, my best guess would be that the intended algorithm in 18.2.3 is meant to backtrack and try out all candidates one at a time. Am I guessing correctly? If so, I propose to be more specific about this, either in the spec or in a comment. The definition of "supertypes" in Chapter 4 is somewhat vague -- that's something I'd like to clean up in the future -- but the idea is that it is a finite set and never includes two parameterizations of the same class. The well-formedness rules for class declarations (8.1.5) and type parameter bounds (4.4) help to guarantee this property. So, no, there's no need (or support) for backtracking -- we pursue the only possible path. > In Part C, 15.28 (Method Reference Expressions), one of the provided examples may require updating: > >> > (test ? list.map(String::length) : Collections.emptyList())::iterator > << > > In an earlier version of the API, the List interface probably contained a map method returning a new List. Readers unaware of this history may be puzzled by this example.. An updated version may look like this: > > (test ? list.stream().map(String::length).collect(Collectors.toList()) : Collections.emptyList())::iterator Agreed this should be fixed. No need for semantic equivalence, though -- it's just an illustration of syntax. Here's my fix: (test ? stream.map(String::trim) : stream)::toArray > BTW: The type parameter on Collections.emptyList is annoying, but without it b120 fails to compile this code fragment. Correct. Addressed by just getting rid of it entirely. ?Dan From daniel.smith at oracle.com Wed Jan 15 17:03:24 2014 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 15 Jan 2014 18:03:24 -0700 Subject: JSR 335 Lambda Specification, 0.9.2 Message-ID: <4BCA3466-65B4-41AE-87EB-901DE85EB4C0@oracle.com> The 0.9.1 spec has now been posted with the Proposed Final Draft: https://jcp.org/aboutJava/communityprocess/pfd/jsr335/index.html I've made a couple of small clarifications since, producing 0.9.2: http://cr.openjdk.java.net/~dlsmith/jsr335-0.9.2/ The Final Release is expected to consist of this document (relabeled as 1.0), along with the other contents of the Proposed Final Draft. Other links Diff: http://cr.openjdk.java.net/~dlsmith/jsr335-0.9.2-diff.html One-page HTML: http://cr.openjdk.java.net/~dlsmith/jsr335-0.9.2.html Downloadable zip: http://cr.openjdk.java.net/~dlsmith/jsr335-0.9.2.zip Full change log, from the document: > Overload Resolution: Used a simpler, equivalent definition of "reference expression" for the purpose of more-specific method testing. > > Type Inference: Cleaned up handling of intersection types in 18.2.4 and 18.5.4. Simplified discussion in 18.2.1.1. ?Dan From forax at univ-mlv.fr Tue Jan 21 14:23:18 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 21 Jan 2014 23:23:18 +0100 Subject: Bug in javac and eclipse ?? Message-ID: <52DEF356.5090600@univ-mlv.fr> (CC lambda-dev) This code do not compile neither with Eclipse nor with javac, but I think that both are wrong. public class ReferenceProblem { static class A { public A(Runnable r) { } } static final A constant = new A(() -> { System.out.println(constant); }); } javac talks about 'self reference' but there is no self reference here, a lambda is a delayed computation. 15.27.2 only concern local variables, so I don't think this code should be rejected. cheers, R?mi From spullara at gmail.com Tue Jan 21 14:33:14 2014 From: spullara at gmail.com (Sam Pullara) Date: Tue, 21 Jan 2014 14:33:14 -0800 Subject: Bug in javac and eclipse ?? In-Reply-To: <52DEF356.5090600@univ-mlv.fr> References: <52DEF356.5090600@univ-mlv.fr> Message-ID: <945ED26D-DF57-404D-BC5D-75537C5F77FE@gmail.com> I think this is similar to the same issue with instance fields, you have to fully specify them. If you use ReferenceProblem.constant (or in the case of instance fields, this.constant) it works. Not sure why the behavior is different. Sam On Jan 21, 2014, at 2:23 PM, Remi Forax wrote: > (CC lambda-dev) > This code do not compile neither with Eclipse nor with javac, but I think that both are wrong. > > public class ReferenceProblem { > static class A { > public A(Runnable r) { } > } > > static final A constant = new A(() -> { > System.out.println(constant); > }); > } > > javac talks about 'self reference' but there is no self reference here, a lambda is a delayed computation. > 15.27.2 only concern local variables, so I don't think this code should be rejected. > > cheers, > R?mi > From daniel.smith at oracle.com Tue Jan 21 15:14:39 2014 From: daniel.smith at oracle.com (Dan Smith) Date: Tue, 21 Jan 2014 16:14:39 -0700 Subject: Bug in javac and eclipse ?? In-Reply-To: <52DEF356.5090600@univ-mlv.fr> References: <52DEF356.5090600@univ-mlv.fr> Message-ID: The relevant spec (unchanged by Lambda) is 8.3.3. The error is as specified. This has been on the radar for a few months, with emails about it popping up periodically. See, e.g, the "Reader mail bag, 2nd edition" email: > 3 Dec 2013, Markus Keller , "Self-reference to field from lambda expression in initializer" > I've had quite a few discussions about this, and concluded that it is best not to do anything until we flesh out a potential "recursive lambda expression" feature in the future. (In 8, local variables initialized with lambdas have a similar inability to directly refer to themselves.) Adding to that conclusion a bit: - It is sometimes safe to refer to field inside a lambda in its initializer body, but not always (e.g., what if you immediately invoke a lambda in the initializer?) - Were we to come up with a perfect rule, the rules for when it's safe to refer to a field would be the same as the rules for when it's safe to refer to a local variable. (Noting, however, that the requirements of the language are different: it is never tolerable to refer to a local variable before initialization, while early access to fields is sometimes permitted.) - The approach we took in JSR 335 in general was to claim that recursive lambdas were probably not all that useful, and wait for evidence to the contrary. An argument for more convenient recursive access in field initializers is probably also an argument for support for recursive access from local variable initializers. - In any case, you can always use qualified access ('System.out.println(ReferenceProblem.constant)'), for which 8.3.3 does not apply. ?Dan On Jan 21, 2014, at 3:23 PM, Remi Forax wrote: > (CC lambda-dev) > This code do not compile neither with Eclipse nor with javac, but I think that both are wrong. > > public class ReferenceProblem { > static class A { > public A(Runnable r) { } > } > > static final A constant = new A(() -> { > System.out.println(constant); > }); > } > > javac talks about 'self reference' but there is no self reference here, a lambda is a delayed computation. > 15.27.2 only concern local variables, so I don't think this code should be rejected. > > cheers, > R?mi > From forax at univ-mlv.fr Tue Jan 21 15:46:43 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 22 Jan 2014 00:46:43 +0100 Subject: Bug in javac and eclipse ?? In-Reply-To: References: <52DEF356.5090600@univ-mlv.fr> Message-ID: <52DF06E3.9020606@univ-mlv.fr> On 01/22/2014 12:14 AM, Dan Smith wrote: > The relevant spec (unchanged by Lambda) is 8.3.3. The error is as specified. > > This has been on the radar for a few months, with emails about it popping up periodically. See, e.g, the "Reader mail bag, 2nd edition" email: > >> 3 Dec 2013, Markus Keller , "Self-reference to field from lambda expression in initializer" >> I've had quite a few discussions about this, and concluded that it is best not to do anything until we flesh out a potential "recursive lambda expression" feature in the future. (In 8, local variables initialized with lambdas have a similar inability to directly refer to themselves.) > Adding to that conclusion a bit: > > - It is sometimes safe to refer to field inside a lambda in its initializer body, but not always (e.g., what if you immediately invoke a lambda in the initializer?) You may see the wrong value (at least not the one you expect) but it's clearly not unsafe or we have not the same definition of unsafe. The issue you describe may appear with an anonymous class too (so since Java 1.1), but this code is legal: class Foo { A field = new A(new Runnable() { @Override public void run() { System.out.println(field); } }); } To sumarrize, I don't understand: 1) why the code is valid for an anonymous class but not a lambda ? 2) why the type checker rejects a perfectly valid code. ? 3) why qualified access works but not unqualified access doesn't ? > > - Were we to come up with a perfect rule, the rules for when it's safe to refer to a field would be the same as the rules for when it's safe to refer to a local variable. (Noting, however, that the requirements of the language are different: it is never tolerable to refer to a local variable before initialization, while early access to fields is sometimes permitted.) yes, it's permitted when the code may work. > > - The approach we took in JSR 335 in general was to claim that recursive lambdas were probably not all that useful, and wait for evidence to the contrary. An argument for more convenient recursive access in field initializers is probably also an argument for support for recursive access from local variable initializers. no, as you said in the sentence just above, before 8, reference to fields were accepted by the JLS when it can be meaningful, reference to local variable are never accepted. > > - In any case, you can always use qualified access ('System.out.println(ReferenceProblem.constant)'), for which 8.3.3 does not apply. see the question of Sam, it's confusing when unqualified access doesn't work but qualified access work. It's like created an artificial corner case without > > ?Dan regards, R?mi > > On Jan 21, 2014, at 3:23 PM, Remi Forax wrote: > >> (CC lambda-dev) >> This code do not compile neither with Eclipse nor with javac, but I think that both are wrong. >> >> public class ReferenceProblem { >> static class A { >> public A(Runnable r) { } >> } >> >> static final A constant = new A(() -> { >> System.out.println(constant); >> }); >> } >> >> javac talks about 'self reference' but there is no self reference here, a lambda is a delayed computation. >> 15.27.2 only concern local variables, so I don't think this code should be rejected. >> >> cheers, >> R?mi >> From forax at univ-mlv.fr Wed Jan 22 00:28:10 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 22 Jan 2014 09:28:10 +0100 Subject: Bug in javac and eclipse ?? In-Reply-To: References: <52DEF356.5090600@univ-mlv.fr> Message-ID: <52DF811A.4020705@univ-mlv.fr> On 01/22/2014 04:36 AM, Zhong Yu wrote: > On Tue, Jan 21, 2014 at 5:14 PM, Dan Smith wrote: >> The relevant spec (unchanged by Lambda) is 8.3.3. The error is as specified. >> >> This has been on the radar for a few months, with emails about it popping up periodically. See, e.g, the "Reader mail bag, 2nd edition" email: >> >>> 3 Dec 2013, Markus Keller , "Self-reference to field from lambda expression in initializer" >>> I've had quite a few discussions about this, and concluded that it is best not to do anything until we flesh out a potential "recursive lambda expression" feature in the future. (In 8, local variables initialized with lambdas have a similar inability to directly refer to themselves.) >> Adding to that conclusion a bit: >> >> - It is sometimes safe to refer to field inside a lambda in its initializer body, but not always (e.g., what if you immediately invoke a lambda in the initializer?) > Prior to lambda, if a field initializer references the field itself, > it's highly likely that it is a programming mistake, for example, `int > y = y+1;`. It makes sense to forbid it because in all likelihood > that'll help the programmer. > > But it is not true if the field is referenced inside a lambda body. It > is very un-likely that it is a programming mistake. It's most likely > what the programmer intends it to be. yes, BTW, what I wanted to write is a destructured(*) visitor which is as you said is a legit code. public static final Visitor EVAL_VISITOR = new Visitor() .when(Value.class, Value::getValue) .when(BinOp.class, expr -> expr.getOp().applyAsInt( EVAL_VISITOR.visit(expr.getLeft()), EVAL_VISITOR.visit(expr.getRight()))); but with the current rule, either you have to qualify the reference to the visitor or you can call a mustache to the rescue :) public static final Visitor EVAL_VISITOR = new Visitor() {{ // <- mustache this.when(Value.class, Value::getValue) .when(BinOp.class, expr -> expr.getOp().applyAsInt( visit(expr.getLeft()), visit(expr.getRight()))); }}; sadly mustache solution generates an anonymous class. R?mi * I call it a destructured visitor just for the sake of give it a name. it's a practical answer to the expression problem described by Philip Wadler [1] (it doesn't solve it because there is a hidden cast), the code of the Visitor is left as an exercise for the reader. [1] http://homepages.inf.ed.ac.uk/wadler/papers/expression/expression.txt > >> - Were we to come up with a perfect rule, the rules for when it's safe to refer to a field would be the same as the rules for when it's safe to refer to a local variable. (Noting, however, that the requirements of the language are different: it is never tolerable to refer to a local variable before initialization, while early access to fields is sometimes permitted.) >> >> - The approach we took in JSR 335 in general was to claim that recursive lambdas were probably not all that useful, and wait for evidence to the contrary. > I've encountered it in my real-world code. Basically the lambda is > registered as an one-off listener to some event; when the event > occurs, the lambda may need to register itself again. This example is > by no means contrived, and I'll bet $20 that we'll hear a lot of > complains why this cannot be done. And the workaround (prefixing with > "this." or "TheClass.") will only seem to be mysterious. > > Zhong Yu > >> An argument for more convenient recursive access in field initializers is probably also an argument for support for recursive access from local variable initializers. >> >> - In any case, you can always use qualified access ('System.out.println(ReferenceProblem.constant)'), for which 8.3.3 does not apply. >> >> ?Dan >> >> On Jan 21, 2014, at 3:23 PM, Remi Forax wrote: >> >>> (CC lambda-dev) >>> This code do not compile neither with Eclipse nor with javac, but I think that both are wrong. >>> >>> public class ReferenceProblem { >>> static class A { >>> public A(Runnable r) { } >>> } >>> >>> static final A constant = new A(() -> { >>> System.out.println(constant); >>> }); >>> } >>> >>> javac talks about 'self reference' but there is no self reference here, a lambda is a delayed computation. >>> 15.27.2 only concern local variables, so I don't think this code should be rejected. >>> >>> cheers, >>> R?mi >>> From daniel.smith at oracle.com Wed Jan 22 09:39:21 2014 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 22 Jan 2014 10:39:21 -0700 Subject: Bug in javac and eclipse ?? In-Reply-To: References: <52DEF356.5090600@univ-mlv.fr> <52DF06E3.9020606@univ-mlv.fr> Message-ID: <3B39A770-C09B-4E4E-BC33-FB74BBF9D583@oracle.com> On Jan 22, 2014, at 4:09 AM, Markus Keller wrote: > Remi, you are totally correct, this is a spec bug (oversight, since 8.3.3 > was not updated when lambdas were added). > The Eclipse compiler had this right, until we bowed down to the bad spec: > https://bugs.eclipse.org/421926 > > Unfortunately, my first mail on this subject was not perfect, since I > first also thought this was about "Self-reference to field from lambda > expression in initializer". Dan's answer also referred to a "recursive > lambda expression" feature, which shows that Oracle's internal discussion > was also based on wrong assumptions. Can you clarify what incorrect assumptions you think were made? I'm not seeing any new information in this thread. I've tried to be very clear about where were at: sure, it would be convenient to do something here, but it's a complicated space and it deserves a lot more analysis before we commit to something. It's at the top of our "potential future enhancements" list. ?Dan From forax at univ-mlv.fr Wed Jan 22 10:16:17 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 22 Jan 2014 19:16:17 +0100 Subject: Bug in javac and eclipse ?? In-Reply-To: <3B39A770-C09B-4E4E-BC33-FB74BBF9D583@oracle.com> References: <52DEF356.5090600@univ-mlv.fr> <52DF06E3.9020606@univ-mlv.fr> <3B39A770-C09B-4E4E-BC33-FB74BBF9D583@oracle.com> Message-ID: <52E00AF1.4010502@univ-mlv.fr> On 01/22/2014 06:39 PM, Dan Smith wrote: > On Jan 22, 2014, at 4:09 AM, Markus Keller wrote: > >> Remi, you are totally correct, this is a spec bug (oversight, since 8.3.3 >> was not updated when lambdas were added). >> The Eclipse compiler had this right, until we bowed down to the bad spec: >> https://bugs.eclipse.org/421926 >> >> Unfortunately, my first mail on this subject was not perfect, since I >> first also thought this was about "Self-reference to field from lambda >> expression in initializer". Dan's answer also referred to a "recursive >> lambda expression" feature, which shows that Oracle's internal discussion >> was also based on wrong assumptions. > Can you clarify what incorrect assumptions you think were made? I'm not seeing any new information in this thread. > > I've tried to be very clear about where were at: sure, it would be convenient to do something here, but it's a complicated space and it deserves a lot more analysis before we commit to something. While I agree that this is a complicated space, it was also already explored by the guys that design the previous versions of Java. And as far as I know, nobody ever complain, famous stupid words, maybe ... As far as remember, the EG just decide to not support self reference in case of local variable (mostly because in Java you cannot reference the address of a local variable from a scope that is not in the same method) In case of a field, the lambda doesn't reference itself but 'this'. That's why if instead of using a lambda, one uses an anonymous class, it compiles. Given that rules on self-reference already exist, I think it's better to not invent a new one. The only issue IMO is that it seems that the JLS 7 doesn't clearly explicit these previous rules. > It's at the top of our "potential future enhancements" list. there are so many items on that issue list that removing one is not an issue :) > > ?Dan R?mi From stephan.herrmann at berlin.de Fri Jan 24 16:38:47 2014 From: stephan.herrmann at berlin.de (Stephan Herrmann) Date: Sat, 25 Jan 2014 01:38:47 +0100 Subject: 18.2.3 fails to properly reduce =?UTF-8?B?4p+obnVsbCA8OiDOseKfqQ==?= Message-ID: <52E30797.4080301@berlin.de> Srikanth brought up a test case[1] that seems to reveal a bug in 18.2.3. Indirectly the example shows that inference can produce a solution that instantiates a type variable to the null type. Since it occurred in a varargs context we are trying to generate new null[] The problem seems to be in the order of rules in 18.2.3. The constraint ?null <: ?? reduces to the bound null <: ? where it actually should reduce to true, right? best, Stephan [1] https://bugs.eclipse.org/bugs/show_bug.cgi?id=426534 From stephan.herrmann at berlin.de Tue Jan 28 03:33:29 2014 From: stephan.herrmann at berlin.de (Stephan Herrmann) Date: Tue, 28 Jan 2014 12:33:29 +0100 Subject: necessary information is never considered by inference? Message-ID: <52E79589.9060306@berlin.de> Consider this example: import java.util.stream.Stream; import java.util.*; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toList; public class X { void test(Stream> stream) { stream.collect(collectingAndThen(toList(), Collections::unmodifiableList)) .remove(0); } } I fail to see anything in the spec that would let us determine the return type of the collect(..) invocation. Hence the remove() call would be unresolvable. Given that javac does accept the program, I'm wondering what's causing this discrepancy. We have two inference variables from the outer invocation, let's write it as: ,A#1,R#0>) plus four inference variables from the inner invocation: Collector collectingAndThen(Collector, Function) My question is: how do we get a constraint that would help inference to find the desired instantiation for R#0. From the dependencies / instantiations I see, these are relevant: RR#5 = R#0 R#4 = List> There's no dependency between R#0/RR#5 and any other type in sight. It seems we could only get this connection from inspecting the method reference Collections::unmodifiableList, from which we *might* deduce constraints in the following vein (ignoring exact relations): List ~ R#4 List ~ RR#5 which would probably allow us to correlate R#4 with RR#5. However, I don't see where the spec would allow me to introduce such constraints: we're reducing this constraint: ?collectingAndThen(toList(), Collections::unmodifiableList) ? Collector,A#1,R#0>? for this reduction 18.2.1 instructs me to apply 18.5.2 for computing B3. The problem is: computation of B3 only comprise those parts of 18.5.2 that never touch the argument expressions, those come into the picture only after. I made experiments to let 18.2.1 compute B4 instead of B3, this would nicely produce an "interesting" constraint ?Collections::unmodifiableList ? java.util.function.Function? but while the outer inference (collect) is still running we don't seem to be in a position for resolving any inference variables. OTOH, reducing the constraint with inference variables in these positions yields false (inexact method reference, whose function type has non-proper parameters). If I would ignore even that rule I *would* get at least this: ?List ? RR#5? So, what *does* create the connection between R#4 and RR#5?? thanks, Stephan PS: note that the problem does not occur when making the method reference exact by saying "Collections::>unmodifiableList". From brian.goetz at oracle.com Wed Jan 29 08:23:15 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 29 Jan 2014 11:23:15 -0500 Subject: Updated RI and TCK Message-ID: <52E92AF3.1040502@oracle.com> An updated draft Reference Implementation for JSR-337, Java SE 8, which is also the reference implementation for JSR 335, is available here: http://jdk8.java.net/java-se-8-ri/[1] This is based on JDK 8 build 126; the previous was build 121. The draft TCK has also been updated, to JCK 8 build 40. You can access it via the instructions you previously received; if you have not received these instructions, let me know. There are a small number of known TCK failures, as documented in the "known failures list" delivered with the TCK (jck8b40-jdk8b126.kfl). If you run the TCK, provide that file as an exclude list in order to skip the problematic tests. Those tests will be omitted from the final JCK 8 build, and other than documentation fixes that should be the only JCK change relative to JDK 8 build 40. We expect to post a minor update to the draft Specification shortly, and will allow at least an additional week for feedback on that, so if you wish to run the TCK against the RI in your local environment you should have plenty of time. From daniel.smith at oracle.com Fri Jan 31 13:52:02 2014 From: daniel.smith at oracle.com (Dan Smith) Date: Fri, 31 Jan 2014 14:52:02 -0700 Subject: =?utf-8?Q?Re=3A_18=2E2=2E3_fails_to_properly_reduce_=E2=9F=A8nul?= =?utf-8?Q?l_=3C=3A_=CE=B1=E2=9F=A9?= In-Reply-To: <52E30797.4080301@berlin.de> References: <52E30797.4080301@berlin.de> Message-ID: Yes, you're right. That's a bug. Thanks for reporting it. I've created this JBS bug: https://bugs.openjdk.java.net/browse/JDK-8033407 ?Dan On Jan 24, 2014, at 5:38 PM, Stephan Herrmann wrote: > Srikanth brought up a test case[1] that seems to reveal a bug in 18.2.3. > > Indirectly the example shows that inference can produce a solution > that instantiates a type variable to the null type. > Since it occurred in a varargs context we are trying to generate > > new null[] > > The problem seems to be in the order of rules in 18.2.3. > The constraint ?null <: ?? reduces to the bound null <: ? > where it actually should reduce to true, right? > > best, > Stephan > > > > [1] https://bugs.eclipse.org/bugs/show_bug.cgi?id=426534 From daniel.smith at oracle.com Fri Jan 31 16:39:47 2014 From: daniel.smith at oracle.com (Dan Smith) Date: Fri, 31 Jan 2014 17:39:47 -0700 Subject: necessary information is never considered by inference? In-Reply-To: <52E79589.9060306@berlin.de> References: <52E79589.9060306@berlin.de> Message-ID: <777D04F7-4BCB-4479-9B06-132F02F1051B@oracle.com> On Jan 28, 2014, at 4:33 AM, Stephan Herrmann wrote: > Consider this example: > > import java.util.stream.Stream; > import java.util.*; > import static java.util.stream.Collectors.collectingAndThen; > import static java.util.stream.Collectors.toList; > public class X { > void test(Stream> stream) { > stream.collect(collectingAndThen(toList(), Collections::unmodifiableList)) > .remove(0); > } > } > > I fail to see anything in the spec that would let us determine the > return type of the collect(..) invocation. Hence the remove() call > would be unresolvable. > > Given that javac does accept the program, I'm wondering what's causing > this discrepancy. > > We have two inference variables from the outer invocation, let's write it as: ... > However, I don't see where the spec would allow me to introduce > such constraints: we're reducing this constraint: > ?collectingAndThen(toList(), Collections::unmodifiableList) ? Collector,A#1,R#0>? > for this reduction 18.2.1 instructs me to apply 18.5.2 for computing B3. > The problem is: computation of B3 only comprise those parts of 18.5.2 that > never touch the argument expressions, those come into the picture only after. Yes, this is the crux of the problem. The nested invocation's method reference is irrelevant to invocation typing in the spec, but javac is using it. I believe javac captures the intended behavior; I'm now revisiting the design discussions about this to figure out what's supposed to happen. ?Dan From srikanth_sankaran at in.ibm.com Fri Jan 31 21:10:04 2014 From: srikanth_sankaran at in.ibm.com (Srikanth S Adayapalam) Date: Sat, 1 Feb 2014 10:40:04 +0530 Subject: Eclipse + Java 8 Early access release III In-Reply-To: References: Message-ID: A brief note here that Eclipse announced availability of early access builds with improved support for Java 8. Announcement can be seen here: http://dev.eclipse.org/mhonarc/lists/eclipse-dev/msg09738.html 1.75 line inline summary: Compiler and many other components of the Eclipse SDK are feature complete for Java 8 and 45 beta program starts. Any & all follow ups to eclipse newsgroups/bugzilla/mailing lists please. Thanks, Srikanth -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/lambda-spec-experts/attachments/20140201/8284590a/attachment.html