| Summary: | org.eclipse.jdt.internal.compiler.ast.LambdaExpression$CopyFailureException | ||
|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Erdal Karaca <erdal.karaca.de> |
| Component: | Core | Assignee: | Sasikanth Bharadwaj <sasikanth.bharadwaj> |
| Status: | VERIFIED FIXED | QA Contact: | |
| Severity: | major | ||
| Priority: | P3 | CC: | jarthana, manoj.palat, markus.kell.r, mlippert, sasikanth.bharadwaj, stephan.herrmann |
| Version: | 3.1 | ||
| Target Milestone: | 4.7 M7 | ||
| Hardware: | PC | ||
| OS: | Windows 10 | ||
| See Also: |
https://git.eclipse.org/r/73460 https://bugs.eclipse.org/bugs/show_bug.cgi?id=460921 https://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=30b8634488c2a308787d6f4bc05e881c37e80405 |
||
| Whiteboard: | |||
|
Description
Erdal Karaca
Could you please provide a sample with the missing types? Thanks! I could not figure out what of my scenario/code causes this bug to extract a minimalistic example. So, I hope it is fine for you to grab the following plugins from my github repo [1] (sources are EPL): - de.metadocks.lambdaui - de.metadocks.lambdaui.snippets Once you have checked out the projects into your workspace, you can open, for example, the class de.metadocks.lambdaui.snippets.swt.HelloWorld and insert a dot at the end of line 77 (and wait for content assist to help, but fail here). [1] https://github.com/erdalkaraca/lambda-ui/tree/master/plugins Jay, Do you think this bug can still be fixed for Neon? (In reply to Erdal Karaca from comment #3) > Jay, > Do you think this bug can still be fixed for Neon? I am afraid not. We will take a look at this during 4.7 and if possible back port to 4.6.1. I gave it a first look, observations: (In reply to Erdal Karaca from comment #2) > ... > insert a dot at the end of line 77 (and wait for content assist to help, but > fail here). A dot at the very end didn't trigger the bug for me, but this: .text("Selection).|) At the point where we reparse the lambda, the scanner's toString() throws an exception, happens at: buffer.append("<source beginning>\n...\n"); //$NON-NLS-1$ int line = Util.getLineNumber(this.startPosition-1000, this.lineEnds, 0, this.linePtr); int lineStart = getLineStart(line); buffer.append(this.source, lineStart, this.startPosition-lineStart); Current values: line = 1 lineStart = -1 This is a problem with lineEnds, which at that point are an int[250] filled with '0' from top to toe. Perhaps a result of "recordLineSeparators = false", but this makes debugging painful without a working toString(). Rather than live inspection, this is what DEBUG=true prints during lambda reparse: -- ENTER INSIDE PARSE METHOD -- NestedLambda ::= PushLPAREN ::= LPAREN FormalParameterListopt ::= PushRPAREN ::= RPAREN ElidedLeftBraceAndReturn ::= Name ::= SimpleName QualifiedName ::= Name DOT SimpleName Name ::= SimpleName Dimsopt ::= NonWildTypeArgumentsopt ::= IdentifierOrNew ::= new ReferenceExpression ::= Name Dimsopt COLON_COLON... Expression ::= AssignmentExpression MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN Expression ::= AssignmentExpression MethodInvocation ::= Primary DOT Identifier LPAREN... -- EXIT FROM PARSE METHOD -- Doesn't look totally off the mark, but finally null is returned because of "this.lastAct == ERROR_ACTION". Q: Isn't a syntax error to be expected during complete? Experiment: set "this.haltOnSyntaxError = false" in parseLambdaExpression() Result: parsing seems to restart at the top of the file, which is not what we want. We hit ERROR_ACTION, when currentToken = TokenNameEOF, at a point with the following stack content: astStack (lenght 1): LambdaExpression "() -> {}" expressionStack (length 1): MessageSend SwtUI.create(Label::new).text("Selection") All looks good, except that we haven't folded the expression into the lambda. We can't yet do this, because the expression is not properly terminated (the final ')' is outside the range to parse). So much for my observations trying to understand the CopyFailureException. Next in this theatre: isn't CopyFailureException actually expected during assist parsing? OK, *normally* CopyFailureException during code assist is silently caught in LE.isCompatibleWith(). But in this example the exception is raised in a call chain from LE.sIsMoreSpecific()! That's a useful cue (which also explains difficulty to isolate the problem in a smaller example). New Gerrit change created: https://git.eclipse.org/r/73460 Thanks, Stephan! It seems that you have also isolated a minimalistic example/test to reproduce. (In reply to Erdal Karaca from comment #8) > Thanks, Stephan! > It seems that you have also isolated a minimalistic example/test to > reproduce. The key to this test case was to include these two methods from SwtUI: public SwtUI<T> child(ControlSupplier supplier) public SwtUI<T> child(ViewerSupplier supplier) <lecture> Aside from the completion issue, let me mention that this style of programming drives type inference to its limits (and perhaps beyond): overloading (the most convoluted concept in the Java language) combined with a difference in signatures of only two functional interfaces and then a lambda expression to make that choice with minimal type information contained, wow! One lesson I learned from implementing this inference: I cannot explain why and when overload resolution works and which result it will pick, at least not in terms that are amenable to a developer's understanding of their own code. For the sake of comprehensibility and predictability: use different names for those methods. It's so easy and avoids tremendous hassle. </lecture> Jay, Sassi, if hudons gives +1 I'm fine with putting this in RC3, but I won't push hard on it... That was a solution driven by unconscious programming :-) (In reply to Stephan Herrmann from comment #9) > (In reply to Erdal Karaca from comment #8) > > Thanks, Stephan! > > It seems that you have also isolated a minimalistic example/test to > > reproduce. > > The key to this test case was to include these two methods from SwtUI: > > public SwtUI<T> child(ControlSupplier supplier) > public SwtUI<T> child(ViewerSupplier supplier) > > <lecture> > Aside from the completion issue, let me mention that this style of > programming drives type inference to its limits (and perhaps beyond): > overloading (the most convoluted concept in the Java language) combined with > a difference in signatures of only two functional interfaces and then a > lambda expression to make that choice with minimal type information > contained, wow! > > One lesson I learned from implementing this inference: I cannot explain why > and when overload resolution works and which result it will pick, at least > not in terms that are amenable to a developer's understanding of their own > code. > For the sake of comprehensibility and predictability: use different names > for those methods. It's so easy and avoids tremendous hassle. > </lecture> > > Jay, Sassi, > > if hudons gives +1 I'm fine with putting this in RC3, but I won't push hard > on it... Any chance for this to make it into Neon.3 ? Would be great to get the fix in. Had this as well in an incomplete SWT snippet:
Image image= new Image(display, (int z) -> {
ImageData imageData= new ImageData(IMAGE_WIDTH, IMAGE_HEIGHT, 24, new PaletteData(0xff, 0xff00, 0xff0000));
imageData.setAlpha(, y1, 255);
return imageData;
});
Try to invoke Content Assist after "imageData.setAlpha(".
(In reply to Stephan Herrmann from comment #9)
> overloading (the most convoluted concept in the Java language) combined with
> a difference in signatures of only two functional interfaces and then a
> lambda expression to make that choice with minimal type information
> contained, wow!
Thanks for the reminder and your very insightful blogpost on this matter:
https://objectteams.wordpress.com/2017/04/02/several-languages-java-8/
Too bad Java's unnamed constructors sometimes make overloading hard to avoid.
(In reply to Markus Keller from comment #12) > Too bad Java's unnamed constructors sometimes make overloading hard to avoid. Let me add two quotes from Gilad's linked post "Systemic Overload": - "Constructors are a bad idea, as I’ve already explained, so let’s assume we don’t have them." - "Arity based overloading, as in e.g., Erlang, is pretty harmless." Considering the latter, I could even see some sense in adding a parameter just to move from type based overloading to arity based. Consider naming the additional parameter(s) "int overloadKludge1" ... :) @Sasi, we have a proposed patch. Bug is assigned to your name. Perhaps you just want to rebase & glance over the fix before pushing? (In reply to comment #14) > @Sasi, we have a proposed patch. Bug is assigned to your name. Perhaps you just > want to rebase & glance over the fix before pushing? Sure, on it right away Gerrit change https://git.eclipse.org/r/73460 was merged to [master]. Commit: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=30b8634488c2a308787d6f4bc05e881c37e80405 (In reply to comment #16) > Gerrit change https://git.eclipse.org/r/73460 was merged to [master]. > Commit: > http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=30b8634488c2a308787d6f4bc05e881c37e80405 Done, resolving. Thanks Stephan for the patch Verified for Eclipse Oxygen 4.7M7 Build id: I20170508-2000 |