0

I have some fairly complex code that uses Javaslang. If I compile it into a jar, it runs fine. However, when I try to step into it in Eclipse for debugging, Eclipse flags it as a compilation error and dies when it reaches that line. The particularly weird part is that this worked a week ago, and the code has not changed in the interim.

Things I have tried:

  • clean project (including unchecking 'build automatically')
  • delete project from Eclipse, delete .project and .settings, re-import from scratch
  • delete project from Eclipse, delete .project, .classpath, .settings, do mvn eclipse:eclipse, reimport

Maven builds this without errors [both within Eclipse and from the command line]. I can run the project this depends on and have it access this code from the JAR, so I know it works. I just cannot have Eclipse access the code from the project, either in 'run' or 'debug' mode.

    Seq<Tuple2<StateProbabilityVector, ScenData>> resultStateProbs =
        futures.
            flatMap(Future::get).
            toList();

    // Update the target counts.
    // THIS ENTIRE STATEMENT IS THE ERROR
    Seq<Tuple2<ScenState, Probability>> result =
        resultStateProbs.flatMap(tuple -> tuple.apply((spv, baTargetCount) ->
    {
        return spv.getStateProbList().
        peek(sp -> logger.debug("Checking if {} > {}: {}",
                               sp.getProbability(),
                               intermediateMinProb,
                               sp.getProbability().greaterThan(intermediateMinProb))).
        filter(sp -> sp.getProbability().greaterThan(intermediateMinProb)).
        map(sp -> updateScenarioData(sp, baTargetCount, dupStateInfo));
    }));

// signature for updateScenarioData
protected abstract Tuple2<ScenState, Probability> updateScenarioData(StateProbability stateProb,
                                                                         ScenData scenData,
                                                                     DSI dupStateInfo);
// truncated def of StateProbabilityVector
@Getter @ToString @Builder
public class StateProbabilityVector {
 @NonNull
    private final Seq<StateProbability> stateProbList;
}

So the types are all correct, but Eclipse claims:

> Type mismatch: cannot convert from Object to Iterable<? extends
> Object>    
> Type mismatch: cannot convert from Seq<Object> to
> Seq<Tuple2<ScenState,Probability>>
Mathias Dpunkt
  • 11,594
  • 4
  • 45
  • 70
betseyb
  • 1,302
  • 2
  • 18
  • 37
  • 1
    which is the line that eclipse shows as error? – Blip Jun 15 '17 at 14:46
  • eclipse has corrupted the code compilation cache, you need to reset it completely and it will probably work just fine. –  Jun 15 '17 at 15:02
  • clean the project in eclipse – Blip Jun 15 '17 at 15:11
  • Tried to clean the project; no effect. Cleaned all projects for good measure; no joy. – betseyb Jun 15 '17 at 15:16
  • I also tried exiting out of Eclipse and restarting, which had no effect. – betseyb Jun 15 '17 at 15:23
  • To the downvoters- please add a comment explaining why you downvoted, so I may improve my question. – betseyb Jun 15 '17 at 15:24
  • 1
    Not the answer you're looking for, but... Eclipse has *horrible* Maven support, and is a bug-ridden mess in general. I felt like I was born again when I finally dumped Eclipse and started using IDEA for all Java projects. – Kevin Krumwiede Jun 15 '17 at 16:40
  • delete the project and recreate it –  Jun 15 '17 at 17:34
  • @JarrodRoberson, as I stated above in my edits to the question, I tried that, and it had no effect. I deleted the project within Eclipse, deleted the .project, .classpath, and .settings, and re-created the project. Several times. – betseyb Jun 15 '17 at 18:09
  • 1
    This is a type inference problem faced by the Eclipse compiler. Eclipse uses it's own implementation of the java compiler (ECJ - Eclipse Compiler for Java) and it has different type inference capability than JDK's compiler (used by IntelliJ, Maven, and the `javac` command line tool). Try adding a type witness to the last line of the data transformation chain: `resultStateProbs.flatMap(tuple -> tuple.> apply((spv, baTargetCount) -> ...`, or other places in the call chain. Try to figure out which line confuses the type inference engine and add a type witness there. – Nándor Előd Fekete Jul 11 '17 at 10:18

1 Answers1

1

As Nándor comments, this is probably down to a difference between the Eclipse compiler and javac, and the problem can probably be solved with a type witness in the right place. To find the right place, I would start by breaking up the functional method chain and extracting some local variables:

Seq<Tuple2<ScenState, Probability>> result =
  resultStateProbs.flatMap(tuple -> {
    Seq<Tuple2<ScenState, Probability>> filteredAndUpdated =
      tuple.apply((spv, baTargetCount) -> {
        Seq<StateProbability> stateProbList = spv.getStateProbList();

        stateProbList.peek(sp -> {
          logger.debug("Checking if {} > {}: {}", sp.getProbability(), intermediateMinProb, sp.getProbability().greaterThan(intermediateMinProb));
        });

        Seq<StateProbability> filtered = stateProbList.filter(sp ->
          sp.getProbability().greaterThan(intermediateMinProb));

        Seq<Tuple2<ScenState, Probability>> updated = filtered.map(sp ->
          updateScenarioData(sp, baTargetCount, dupStateInfo));

        return updated;
      });
    return filteredAndUpdated;
  });

If you use Eclipse's extract variable refactoring, that by itself may tell you where it's inferring the wrong types, and explicitly declaring the correct types of the local variables might be enough to fix the problem all by itself.

If not, it should at least narrow the error down, and show you exactly where in the call chain Eclipse is having trouble. You can then probably fix it with type witnesses or, if all else fails, explicit casts, and then (with that type information added) perhaps inline the variables again, although this code is dense enough that I might leave them in.


Side notes:

  1. peek() will only only debug the first StateProbability -- is that your intent?
  2. consider adding a greaterThan() method to StateProbability so you don't have to repeatedly call getProbability().greaterThan(). (If the answer to #1 is "no", this method would also be a good place to put the debug statement.)
  3. consider adding a method on SceneState that would return a prefiltered list, like Seq<StateProbability> SceneState.allGreaterThan(Probability).
David Moles
  • 48,006
  • 27
  • 136
  • 235