Bug 158531 - [1.5][compiler] javac reports errors, Eclipse not -- incompatible types
Summary: [1.5][compiler] javac reports errors, Eclipse not -- incompatible types
Status: RESOLVED DUPLICATE of bug 121369
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-09-25 06:03 EDT by Hendrik Maryns CLA
Modified: 2006-09-25 11:52 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Hendrik Maryns CLA 2006-09-25 06:03:14 EDT
Once again, a problem with generics where javac reports errors, but Eclipse doesn’t.  I do not know who is right.

javac -version
javac 1.5.0_07

=== ComparableComparator.java ===
package comparator;

import java.util.Comparator;

public class ComparableComparator<T extends Comparable<? super T>> implements Comparator<T> {

    @SuppressWarnings("unchecked")
    private static final ComparableComparator instance = new ComparableComparator();

    @SuppressWarnings("unchecked")
    public static <T extends Comparable<? super T>> ComparableComparator<T> getInstance() {
        return instance;
    }

    public int compare(T obj1, T obj2) {
        return obj1.compareTo(obj2);
    }

}
=== ComparableComparator.java ===

=== ComparatorUtils.java ===
package comparator;

import java.util.Comparator;

public class ComparatorUtils {

    @SuppressWarnings("unchecked")
    public static final Comparator NATURAL_COMPARATOR = ComparableComparator.getInstance();

    @SuppressWarnings("unchecked")
    public static <T extends Comparable<? super T>> Comparator<T> naturalComparator() {
        return NATURAL_COMPARATOR;
    }

    @SuppressWarnings("unchecked")
    public static <T> Comparator<T> nullLowComparator(Comparator<T> comparator) {
        if (comparator == null) {
            comparator = (Comparator<T>) naturalComparator();
        }
        return new NullComparator<T>(comparator, false);
    }
    
}
=== ComparatorUtils.java ===

=== NullComparator.java ===
package comparator;

import java.util.Comparator;

public class NullComparator<T> implements Comparator<T> {

    private Comparator<T> nonNullComparator;

    private boolean nullsAreHigh;

    @SuppressWarnings("unchecked")
    public NullComparator() {
        this((Comparator<T>) ComparableComparator.getInstance(), true);
    }

    public NullComparator(Comparator<T> nonNullComparator) {
        this(nonNullComparator, true);
    }

    @SuppressWarnings("unchecked")
    public NullComparator(boolean nullsAreHigh) {
        this((Comparator<T>) ComparableComparator.getInstance(), nullsAreHigh);
    }

    public NullComparator(Comparator<T> nonNullComparator, boolean nullsAreHigh) {
        this.nonNullComparator = nonNullComparator;
        this.nullsAreHigh = nullsAreHigh;
        
        if(nonNullComparator == null) {
            throw new NullPointerException("null nonNullComparator");
        }
    }

    public int compare(T o1, T o2) {
        if(o1 == o2) { return 0; }
        if(o1 == null) { return this.nullsAreHigh ? 1 : -1; }
        if(o2 == null) { return this.nullsAreHigh ? -1 : 1; }
        return this.nonNullComparator.compare(o1, o2);
    }

}
=== NullComparator.java ===

javac -classpath . comparator/ComparatorUtils.java
comparator/ComparatorUtils.java:8: incompatible types; inferred type argument(s) java.lang.Comparable<? super T> do not conform to bounds of type variable(s) T
found   : <T>comparator.ComparableComparator<T>
required: java.util.Comparator
    public static final Comparator NATURAL_COMPARATOR = ComparableComparator.getInstance();
                                                                                        ^
comparator/ComparatorUtils.java:18: incompatible types; inferred type argument(s) java.lang.Comparable<? super T> do not conform to bounds of type variable(s) T
found   : <T>java.util.Comparator<T>
required: java.lang.Object
            comparator = (Comparator<T>) naturalComparator();
                                                          ^
2 errors
Comment 1 Philipe Mulet CLA 2006-09-25 11:19:06 EDT
Let's make the example a bit more concise, and with numbered testcases:

import java.util.Comparator;

@SuppressWarnings("unchecked")
class ComparableComparator<T extends Comparable<? super T>> implements Comparator<T> {

	static ComparableComparator instance = new ComparableComparator();

public static <W extends Comparable<? super W>> ComparableComparator<W> getInstance() {
	return instance;
}
static <M extends Comparable<M>> Comparator<M> bar() {
	return null;
}
public int compare(T obj1, T obj2) {
	return obj1.compareTo(obj2);
}
}

@SuppressWarnings("unchecked")
class ComparatorUtils {

	static Comparator BAR = ComparableComparator.bar();//0
	static Comparator NATURAL_COMPARATOR = ComparableComparator.getInstance();//1

public static <T extends Comparable<? super T>> Comparator<T> naturalComparator() {
	return NATURAL_COMPARATOR;
}

public static <U> Comparator<U> nullLowComparator(Comparator<U> comparator) {
	if (comparator == null)
		comparator = (Comparator<U>) naturalComparator();//2
	return new NullComparator<U>(comparator, false);
}
}

@SuppressWarnings("unchecked")
class NullComparator<V> implements Comparator<V> {

	Comparator<V> nonNullComparator;
	boolean nullsAreHigh;

public NullComparator() {
	this((Comparator<V>) ComparableComparator.getInstance(), true);//3
}

public NullComparator(Comparator<V> nonNullComparator) {
	this(nonNullComparator, true);
}

public NullComparator(boolean nullsAreHigh) {
	this((Comparator<V>) ComparableComparator.getInstance(), nullsAreHigh);//4
}

public NullComparator(Comparator<V> nonNullComparator, boolean nullsAreHigh) {
	this.nonNullComparator = nonNullComparator;
	this.nullsAreHigh = nullsAreHigh;
	if (nonNullComparator == null) {
		throw new NullPointerException("null nonNullComparator");
	}
}

public int compare(V obj1, V obj2) {
	return 0;
}
}
Comment 2 Philipe Mulet CLA 2006-09-25 11:19:46 EDT
javac says:
X.java:22: incompatible types; inferred type argument(s) java.lang.Object do not conform to bounds of type variable(s) M
found   : <M>java.util.Comparator<M>
required: java.util.Comparator
        static Comparator BAR = ComparableComparator.bar();//0
                                                        ^
X.java:23: incompatible types; inferred type argument(s) java.lang.Comparable<? super W> do not conform to bounds of type variable(s) W
found   : <W>ComparableComparator<W>
required: java.util.Comparator
        static Comparator NATURAL_COMPARATOR = ComparableComparator.getInstance();//1
                                                                               ^
X.java:31: incompatible types; inferred type argument(s) java.lang.Comparable<? super T> do not conform to bounds of type variable(s) T
found   : <T>java.util.Comparator<T>
required: java.lang.Object
                comparator = (Comparator<U>) naturalComparator();//2
                                                              ^
X.java:43: incompatible types; inferred type argument(s) java.lang.Comparable<? super W> do not conform to bounds of type variable(s) W
found   : <W>ComparableComparator<W>
required: java.lang.Object
        this((Comparator<V>) ComparableComparator.getInstance(), true);//3
                                                             ^
X.java:51: incompatible types; inferred type argument(s) java.lang.Comparable<? super W> do not conform to bounds of type variable(s) W
found   : <W>ComparableComparator<W>
required: java.lang.Object
        this((Comparator<V>) ComparableComparator.getInstance(), nullsAreHigh);//4
                                                             ^
5 errors
Comment 3 Philipe Mulet CLA 2006-09-25 11:21:56 EDT
Problem (0) seems to be a duplicate of bug 121369, which traces back to a bug in javac & spec, which haven't been resolved so far (spec has a hole, and javac doesn't provide a definite answer. We provide a slightly better answer (one more substitution) but we need the JLS to be fixed to agree on the final result. We believe that Eclipse support is closer to where the JLS should end up at.
Comment 4 Philipe Mulet CLA 2006-09-25 11:22:41 EDT
(Note that problem 0 did not exist in your original testcase)
Comment 5 Philipe Mulet CLA 2006-09-25 11:48:55 EDT
Problem (1) is another instance of the same issue in javac. Mishandling of inferred parameter type, where bound is mutually recursive.

If eliminating the self-reference in type parameter bound, examples are working again, e.g.

class ComparableComparator {
  static <M extends String> Comparator<M> baz() {
	return null;
  }
}

class ComparatorUtils {
  static Comparator BAR3 = ComparableComparator.baz();//1b
}
Comment 6 Philipe Mulet CLA 2006-09-25 11:52:18 EDT
Problems are again the same.

Added GenericTypeTest#test1035.
Closing as dup of bug 121369

*** This bug has been marked as a duplicate of 121369 ***