JDK-8067848 : javax.lang.model.util.Types.capture changes order of type variable bounds
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8u25
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2014-12-14
  • Updated: 2015-12-11
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbd_majorUnresolved
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b18)
Java HotSpot(TM) Client VM (build 25.25-b02, mixed mode, sharing)

javac 1.8.0_25

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
Perhaps I'm reading something into the JLS but it seems pretty clear in the second bullet point of 5.1.10 that the bound of the fresh type variable is an intersection type where the first bound is the wildcard's bound followed by the type variable's bounds in declaration order:

If Ti is a wildcard type argument of the form ? extends Bi, then Si is a fresh type variable whose upper bound is glb(Bi, Ui[A1:=S1,...,An:=Sn]) and whose lower bound is the null type.
glb(V1,...,Vm) is defined as V1 & ... & Vm. 

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The sample source is an annotation processor. First compile it. Then compile it again with itself as the annotation processor:

javac CaptureOrder.java
javac -processor CaptureOrder CaptureOrder.java

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
capture#856 of ? extends I3
java.lang.Object&I3&I2&I1
ACTUAL -
capture#856 of ? extends I3
java.lang.Object&I1&I2&I3

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.Set;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
import javax.lang.model.util.*;

interface I1 {}
interface I2 {}
interface I3 {}
interface IA<A extends I2 & I1> {}

@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("*")
public class CaptureOrder extends AbstractProcessor {

	@Override
	public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
		if (roundEnv.processingOver()) test();
		return false;
	}

	IA<? extends I3> field;

	private static Element find(Element containing, String name) {
		for (Element el : containing.getEnclosedElements()) {
			if (el.getSimpleName().toString().equals(name)) return el;
		}
		return null;
	}

	void test() {
		Elements eu = processingEnv.getElementUtils();
		Types tu = processingEnv.getTypeUtils();

		TypeElement captureTestEl = eu.getTypeElement(CaptureOrder.class.getName());
		VariableElement fieldEl = (VariableElement) find(captureTestEl, "field");
		DeclaredType iaOfWildcardExtendsI3 = (DeclaredType) fieldEl.asType();
		DeclaredType capture = (DeclaredType) tu.capture(iaOfWildcardExtendsI3);
		TypeVariable captureTypeArg = (TypeVariable) capture.getTypeArguments().get(0);
		System.out.println(captureTypeArg);
		System.out.println(captureTypeArg.getUpperBound());
	}
}

---------- END SOURCE ----------


Comments
It's not entirely clear that the order of elements in an intersection type is meaningful, but there's also nothing in the spec to suggest otherwise. Probably best to avoid doing anything with this bug until the fundamental spec issues with intersection types (such as JDK-8024484) are sorted out.
11-12-2015

Checked this for JDK 8u25, 8u40 and 9ea and could reproduce this issue.
18-12-2014