Bug 404675 - [1.8][compiler] user friendly reporting of type inference errors
Summary: [1.8][compiler] user friendly reporting of type inference errors
Status: CLOSED WONTFIX
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 4.3   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Stephan Herrmann CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
: 433147 (view as bug list)
Depends on: 426657
Blocks:
  Show dependency tree
 
Reported: 2013-04-01 13:20 EDT by Stephan Herrmann CLA
Modified: 2020-04-03 06:11 EDT (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Stephan Herrmann CLA 2013-04-01 13:20:03 EDT
The new spec part G (0.6.2 edr for jsr 335) does not make any statements, how type errors should be reported to the user.

My current draft implementation surfaces some of the inference variables and synthetic type variables in error messages, which should probably be avoided.

This bug shall cover the work to hide the new type inference as good as possible during error reporting.

Several of the current regressions in GenericTypeTest can actually be attributed just to the phase of error reporting.
Comment 1 Stephan Herrmann CLA 2013-10-12 13:57:52 EDT
In addition, 0.6.3 also mentions situations where type inference directly triggers a compile error. I'm adding an InferenceFailedException (because at time of failing we have no sufficient context for error reporting).
Making these into user friendly messages is again a challenge.
Comment 2 Stephan Herrmann CLA 2014-01-02 11:59:56 EST
See bug 424591 comment 22 for a nonsense error message, that needs improving.
Comment 3 Srikanth Sankaran CLA 2014-01-31 18:34:27 EST
Do we reasonably expect to get to this by March ? If not, let us retarget to
4.4.
Comment 4 Stephan Herrmann CLA 2014-01-31 18:44:13 EST
(In reply to Srikanth Sankaran from comment #3)
> Do we reasonably expect to get to this by March ? If not, let us retarget to
> 4.4.

There are several parts to this:
1. where to dump the verbose message?
2. is information available? 
3. how to explain to the user?

I don't know about (1) (see bug 426657: is this difficult? ideas? plan?)
(2) could be close to trivial, InferenceContext18 already holds all you'd want to know (and more :) ).
Regarding (3) we could start a 3-year project in AI research :)

Filtering the contents of IC18 and formatting this would be feasible by March, IFF we target some "additional info" feature for gurus (and bug reports).

As soon as we engage in any attempt to really *explain*, we're beyond March for sure.
Comment 5 Stephan Herrmann CLA 2014-01-31 18:50:06 EST
Independent from any "big" solution, I will fine tune some of the errors, like: we report many failures as type mismatch or "m is not applicable to args xyz" where we should at least *mention* that this report originates from a failed attempt to infer types :)
Comment 6 Srikanth Sankaran CLA 2014-02-14 04:56:01 EST
3 years worth of AI ? OK :)

Given the risks in having to change a potentially change a large number of
test messages and the attendant load in verifying them, I'll retarget it to
4.4 for now.
Comment 7 Timo Kinnunen CLA 2014-03-04 10:17:48 EST
About explaining to users, I've thought about that some and for me personally, I don't find even more explanations about things that I won't understand that enticing to look forward to :)

Instead for me something much more usable - and simpler to specify an implementation, too! - would be if intermediate types were rendered in valid Java code snippets that could be copy-pasted into the editor for a closer look., syntax highlighting, formatting, etc. While some types might not be expressible at all, producing some commented out block like /*Consumer<? super ? super String> type = null;*/ wouldn't be too bad.

I don't know how feasible this would actually be. On its face producing valid Java to display mid-flight Java types doesn't sound too unreasonable. After all, producing valid Java code is what it's all about  :)
Comment 8 Srikanth Sankaran CLA 2014-03-04 12:02:44 EST
(In reply to Timo Kinnunen from comment #7)

Thanks for weighing in.

> I don't know how feasible this would actually be.

Did you see Stephan's reference to 3 year research project in AI in comment#4 ?

:)
Comment 9 Stephan Herrmann CLA 2014-03-04 19:29:07 EST
(In reply to Timo Kinnunen from comment #7)
> About explaining to users, I've thought about that some and for me
> personally, I don't find even more explanations about things that I won't
> understand that enticing to look forward to :)
> 
> Instead for me something much more usable - and simpler to specify an
> implementation, too! - would be if intermediate types were rendered in valid
> Java code snippets that could be copy-pasted into the editor for a closer
> look., syntax highlighting, formatting, etc. While some types might not be
> expressible at all, producing some commented out block like /*Consumer<?
> super ? super String> type = null;*/ wouldn't be too bad.
> 
> I don't know how feasible this would actually be. On its face producing
> valid Java to display mid-flight Java types doesn't sound too unreasonable.
> After all, producing valid Java code is what it's all about  :)

If you suggest to just display the solution how the typing should be, to result in legal Java code: go, grab $1,000,000, and we're partners in research :)

If you remember the early days of p2 and the unspeakable error messages when you tried to install something that p2 couldn't figure out: it's the same game also here. When we find an error, what we have in hands is a big bag of atomic constraints. Tracing the one failing constraint back to its many sources and reporting the one source that matters to the user is one of the hard problems in software. Changing the input so that inference can succeed is another hard problem. If your system contains < 10 types, that latter problem could actually be solvable. It probably won't fly if the option space gets large.

As a middle ground, we may want to say which types in the signature we could figure out, and which ones remain unresolved when inference fails. Not sure in how many cases this will really help, sometimes we'd simply say: we couldn't find a solution for any of the types in the signature, because types tend to depend on each other, and when the big equation fails, we may still have a blank board.
Comment 10 Timo Kinnunen CLA 2014-03-05 08:35:50 EST
(In reply to comment #9)
> As a middle ground, we may want to say which types in the signature we could
> figure out, and which ones remain unresolved when inference fails.

Yes, this is what I'm looking for, just using Java's syntax so that parts could be copy-pasted back into my code to be used as building blocks towards the eventual solution. To give a concrete example, let's start with this method while ignoring for the moment why or if it should compile or not:

  @SafeVarargs static <T, C extends Consumer<? super T>> Consumer<? super T> asSingleConsumer_notOK(C... actions) {
    return Stream.of(actions).reduce(Consumer::andThen).orElse((c) -> {});
  }

To fix that, I manually made an exploded version of it to see each component part separately. That revealed two parts that weren't getting connected automatically, so I added the missing pieces to where they needed to go, giving this version that compiles:

  @SafeVarargs static <T, C extends Consumer<? super T>> Consumer<? super T> asSingleConsumer_OK(C... actions) {
    Stream<Consumer<? super T>> of = Stream.<Consumer<? super T>> of(actions);
    Function<Consumer<? super T>, Consumer<T>> function = (Consumer<? super T> t) -> t::accept; // the missing link
    Stream<Consumer<T>> map = of.map(function);
    BinaryOperator<Consumer<T>> accumulator = Consumer<T>::andThen;
    Optional<Consumer<T>> reduce = map.reduce(accumulator);
    Consumer<T> orElse = reduce.orElse((c) -> {});
    Consumer<? super T> returned = orElse;
    return returned;
  }

I would imagine a verbose mode of inference could display the types of all of these variables above: returned, orElse, reduce, accumulator, map and of. This would leave me with the task of coming up with the assignment map = of.map(function) and of course the variable function. 

After that, putting all the pieces back together and simplifying a bit gives this final version:

  @SafeVarargs static <T, C extends Consumer<? super T>> Consumer<? super T> asSingleConsumer_done(C... actions) {
    return Stream
      .<Consumer<? super T>> of(actions)
      .<Consumer<T>> map((Consumer<? super T> t) -> t::accept)
      .reduce(Consumer<T>::andThen).orElse((c) -> {});
  }

> Not sure in
> how many cases this will really help, sometimes we'd simply say: we couldn't
> find a solution for any of the types in the signature, because types tend to
> depend on each other, and when the big equation fails, we may still have a blank
> board.

I see. What might be needed here could be provided by running inference again, but this time with additional rules available that would detect typical type/constraint patterns arising from common errors in user code. These rules could steer the verbose mode inference around obstacles or provide suggestions for fixing the errors. In addition but separately from that, they could also act as a test-bed for future additions or refinements to the type inference specification driven by common real-world problems.
Comment 11 Stephan Herrmann CLA 2014-03-05 09:28:05 EST
Note that much of the explosion you can already inspect using hover.

I just sometimes wonder, how to get the regular hover, when an error hover cuts the line. If such a feature doesn't exist, that'd be worth a RFE against JDT/Text, I'd say.
Comment 12 Srikanth Sankaran CLA 2014-03-05 10:38:11 EST
(In reply to Stephan Herrmann from comment #11)
> Note that much of the explosion you can already inspect using hover.
> 
> I just sometimes wonder, how to get the regular hover, when an error hover
> cuts the line. If such a feature doesn't exist, that'd be worth a RFE
> against JDT/Text, I'd say.

Something that keeps bugging and for which I have been meaning to file a defect 
report in the last five years (!) is: while debugging the javadoc hover comes
up when I point the mouse at field. 

    outer.middle.inner.field

This causes untold amount of  wasted debugging cycles in my case, trying to
get at the value of field
Comment 13 Markus Keller CLA 2014-03-27 17:10:49 EDT
(In reply to Stephan Herrmann from comment #11)
> Note that much of the explosion you can already inspect using hover.
> 
> I just sometimes wonder, how to get the regular hover, when an error hover
> cuts the line. If such a feature doesn't exist, that'd be worth a RFE
> against JDT/Text, I'd say.

See the "Java > Editor > Hovers" preference page: Javadoc hover is Ctrl+Shift.


(In reply to Srikanth Sankaran from comment #12)
> while debugging the javadoc hover comes up when I point the mouse at field. 
> 
>     outer.middle.inner.field

Bug 221886. Workaround: Click, Alt+Shift+Up, Alt+Shift+Up, Ctrl+Shift+I.
Comment 14 Stephan Herrmann CLA 2014-04-21 16:34:20 EDT
*** Bug 433147 has been marked as a duplicate of this bug. ***
Comment 15 Eclipse Genie CLA 2020-04-03 06:11:59 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug.

If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.