Summary
Javac should be sync with a section of JLS 11 §8.4.5
Problem
Javac is not in sync with JLS 11 §8.4.5. See details below in the specification section.
Solution
Synchronize javac with the spec. But in order to reduce possible compatibility issues, the new approach will only be executable for source >= 13
Specification
Per JLS 11 §8.4.8.3, when analyzing if a method can override another one, the first method must be return-type-substitutable for the second. And according to JLS 8.4.5:
A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return type R2 iff any of the following is true, the following apply to the case in which R1 is a reference type:
R1 , adapted to the type parameters of d2 (§8.4.4), is a subtype of R2.
R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9)
d1 does not have the same signature as d2 (§8.4.2), and R1 = | R2 |
Javac is implementing the last assertion incorrectly as it is testing for subtyping (R1 <: | R2 | ) instead of type equality which is what the spec is enforcing.
The actual fix to the compiler is rather simple:
--- old/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java 2018-12-03 18:26:38.765597146 -0500
+++ new/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java 2018-12-03 18:26:38.469597132 -0500
@@ -185,7 +185,8 @@
SWITCH_MULTIPLE_CASE_LABELS(JDK12, Fragments.FeatureMultipleCaseLabels, DiagKind.PLURAL),
SWITCH_RULE(JDK12, Fragments.FeatureSwitchRules, DiagKind.PLURAL),
SWITCH_EXPRESSION(JDK12, Fragments.FeatureSwitchExpressions, DiagKind.PLURAL),
- RAW_STRING_LITERALS(JDK12, Fragments.FeatureRawStringLiterals, DiagKind.PLURAL);
+ RAW_STRING_LITERALS(JDK12, Fragments.FeatureRawStringLiterals, DiagKind.PLURAL),
+ RETURN_TYPE_SUBSTITUTABLE_SAME_TYPE(JDK12);
enum DiagKind {
NORMAL,
--- old/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java 2018-12-03 18:26:39.689597191 -0500
+++ new/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java 2018-12-03 18:26:39.393597177 -0500
@@ -91,6 +91,7 @@
final Names names;
final boolean allowDefaultMethods;
final boolean mapCapturesToBounds;
+ final boolean returnTypeSustitutableSameType;
final Check chk;
final Enter enter;
JCDiagnostic.Factory diags;
@@ -114,6 +115,7 @@
Source source = Source.instance(context);
allowDefaultMethods = Feature.DEFAULT_METHODS.allowedInSource(source);
mapCapturesToBounds = Feature.MAP_CAPTURES_TO_BOUNDS.allowedInSource(source);
+ returnTypeSustitutableSameType = Feature.RETURN_TYPE_SUBSTITUTABLE_SAME_TYPE.allowedInSource(source);
chk = Check.instance(context);
enter = Enter.instance(context);
capturedName = names.fromString("<captured wildcard>");
@@ -4235,8 +4237,13 @@
return covariantReturnType(r1.getReturnType(), r2res, warner);
if (isSubtypeUnchecked(r1.getReturnType(), r2res, warner))
return true;
- if (!isSubtype(r1.getReturnType(), erasure(r2res)))
- return false;
+ if (returnTypeSustitutableSameType) {
+ if (!isSameType(r1.getReturnType(), erasure(r2res)))
+ return false;
+ } else {
+ if (!isSubtype(r1.getReturnType(), erasure(r2res)))
+ return false;
+ }
warner.warn(LintCategory.UNCHECKED);
return true;
}
References
- csr of
-
JDK-8207224 Javac compiles source code despite illegal use of unchecked conversions
-
- Resolved
-