8237067: Implementation of <anyType>.default - (lworld branch)
Jesper Steen Møller
jesper at selskabet.org
Tue Jan 21 17:14:17 UTC 2020
Hi again
Patch appended in plain text.
> On 21 Jan 2020, at 18.01, Srikanth <srikanth.adayapalam at oracle.com> wrote:
>
> Hi Jesper,
>
> It looks like the patch attachment got stripped. Don't know why. Could you inline the fix and send it ?
>
> TIA
> Srikanth (Mere mortal, neither Norse, nor God :) )
>
> On 21/01/20 10:28 pm, Jesper Steen Møller wrote:
>> Hi people (or Norse gods ?)
>>
>> Here's an attempted patch for JDK-8237067. It works with tier1 and 2 tests against the lworld tip, so I think it’s ready for review.
>>
>> The purpose of the change is described in the ticket. As per the discussion in the week-end [1], default values are NOT introduced as constant expressions.
>>
>> -Jesper
>>
>> [1]: https://mail.openjdk.java.net/pipermail/valhalla-dev/2020-January/006713.html
>>
>>
>>
>>
>
diff -r 7fca6c5e0d99 src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Fri Nov 22 15:19:11 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Sun Jan 19 13:49:09 2020 +0100
@@ -3832,10 +3832,15 @@
while (elt.hasTag(ARRAY))
elt = ((ArrayType)elt).elemtype;
if (elt.hasTag(TYPEVAR)) {
- log.error(tree.pos(), Errors.TypeVarCantBeDeref);
- result = tree.type = types.createErrorType(tree.name, site.tsym, site);
- tree.sym = tree.type.tsym;
- return ;
+ if (tree.name == names._default) {
+ result = check(tree, litType(BOT).constType(null),
+ KindSelector.VAL, resultInfo);
+ } else {
+ log.error(tree.pos(), Errors.TypeVarCantBeDeref);
+ result = tree.type = types.createErrorType(tree.name, site.tsym, site);
+ tree.sym = tree.type.tsym;
+ return;
+ }
}
}
@@ -3993,12 +3998,7 @@
// visitSelect that qualifier expression is a type.
return syms.getClassField(site, types);
} else if (name == names._default) {
- if (!types.isValue(site)) {
- log.error(pos, Errors.MakeDefaultWithNonvalue);
- return syms.errSymbol;
- } else {
- return new VarSymbol(STATIC, names._default, site, site.tsym);
- }
+ return new VarSymbol(STATIC, names._default, site, site.tsym);
} else {
// We are seeing a plain identifier as selector.
Symbol sym = rs.findIdentInType(pos, env, site, name, resultInfo.pkind);
@@ -4014,6 +4014,11 @@
// done before attributing the type variables. In
// other words, we are seeing this illegal program:
// class B<T> extends A<T.foo> {}
+
+ if (name == names._default) {
+ // Be sure to return the default value before examining bounds
+ return new VarSymbol(STATIC, names._default, site, site.tsym);
+ }
Symbol sym = (site.getUpperBound() != null)
? selectSym(tree, location, capture(site.getUpperBound()), env, resultInfo)
: null;
@@ -4032,11 +4037,13 @@
return types.createErrorType(name, site.tsym, site).tsym;
default:
// The qualifier expression is of a primitive type -- only
- // .class is allowed for these.
+ // .class and .default are allowed for these.
if (name == names._class) {
// In this case, we have already made sure in Select that
// qualifier expression is a type.
return syms.getClassField(site, types);
+ } else if (name == names._default) {
+ return new VarSymbol(STATIC, names._default, site, site.tsym);
} else {
log.error(pos, Errors.CantDeref(site));
return syms.errSymbol;
diff -r 7fca6c5e0d99 src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Fri Nov 22 15:19:11 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Sun Jan 19 13:49:09 2020 +0100
@@ -2401,8 +2401,16 @@
result = items.makeStackItem(pt);
return;
} else if (tree.name == names._default) {
- code.emitop2(defaultvalue, checkDimension(tree.pos(), tree.type), PoolWriter::putClass);
- result = items.makeStackItem(tree.type);
+ if (tree.type.asElement().isValue()) {
+ code.emitop2(defaultvalue, checkDimension(tree.pos(), tree.type), PoolWriter::putClass);
+ result = items.makeStackItem(tree.type);
+ } else if (tree.type.isReference()) {
+ code.emitop0(aconst_null);
+ result = items.makeStackItem(tree.type);
+ } else {
+ code.emitop0(zero(Code.typecode(tree.type)));
+ result = items.makeStackItem(tree.type);
+ }
return;
}
diff -r 7fca6c5e0d99 src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Nov 22 15:19:11 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Sun Jan 19 13:49:09 2020 +0100
@@ -477,6 +477,22 @@
}
}
+ /** If next input token matches one of the two given tokens, skip it, otherwise report
+ * an error.
+ *
+ * @return The actual token kind.
+ */
+ public TokenKind accept2(TokenKind tk1, TokenKind tk2) {
+ TokenKind returnValue = token.kind;
+ if (token.kind == tk1 || token.kind == tk2) {
+ nextToken();
+ } else {
+ setErrorEndPos(token.pos);
+ reportSyntaxError(S.prevToken().endPos, Errors.Expected2(tk1, tk2));
+ }
+ return returnValue;
+ }
+
/** Report an illegal start of expression/type error at given position.
*/
JCExpression illegal(int pos) {
@@ -1327,7 +1343,7 @@
case DEFAULT:
if (typeArgs != null) return illegal();
selectExprMode();
- t = F.at(pos).Select(t, names._default);
+ t = to(F.at(pos).Select(t, names._default));
nextToken();
break loop;
case CLASS:
@@ -2221,7 +2237,7 @@
return t;
}
- /** BracketsSuffixExpr = "." CLASS
+ /** BracketsSuffixExpr = "." (CLASS | DEFAULT)
* BracketsSuffixType =
*/
JCExpression bracketsSuffix(JCExpression t) {
@@ -2229,7 +2245,7 @@
selectExprMode();
int pos = token.pos;
nextToken();
- accept(CLASS);
+ TokenKind selector = accept2(CLASS, DEFAULT);
if (token.pos == endPosTable.errorEndPos) {
// error recovery
Name name;
@@ -2247,7 +2263,7 @@
// taking care to handle some interior dimension(s) being annotated.
if ((tag == TYPEARRAY && TreeInfo.containsTypeAnnotation(t)) || tag == ANNOTATED_TYPE)
syntaxError(token.pos, Errors.NoAnnotationsOnDotClass);
- t = toP(F.at(pos).Select(t, names._class));
+ t = toP(F.at(pos).Select(t, selector == CLASS ? names._class : names._default));
}
} else if ((mode & TYPE) != 0) {
if (token.kind != COLCOL) {
diff -r 7fca6c5e0d99 src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Nov 22 15:19:11 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Sun Jan 19 13:49:09 2020 +0100
@@ -3545,9 +3545,6 @@
compiler.err.value.does.not.support=\
Inline types do not support {0}
-compiler.err.make.default.with.nonvalue=\
- Default value creation requires an inline type
-
compiler.err.value.may.not.extend=\
Inline type may not extend another inline type or class
diff -r 7fca6c5e0d99 test/jdk/java/util/Locale/LocaleProvidersRun.java
--- a/test/jdk/java/util/Locale/LocaleProvidersRun.java Fri Nov 22 15:19:11 2019 +0100
+++ b/test/jdk/java/util/Locale/LocaleProvidersRun.java Sun Jan 19 13:49:09 2020 +0100
@@ -172,6 +172,8 @@
.addToolArg("-cp")
.addToolArg(Utils.TEST_CLASS_PATH)
.addToolArg("-Djava.locale.providers=" + prefList)
+ .addToolArg("-Duser.language=en")
+ .addToolArg("-Duser.country=US")
.addToolArg("--add-exports=java.base/sun.util.locale.provider=ALL-UNNAMED")
.addToolArg("LocaleProviders")
.addToolArg(methodName)
diff -r 7fca6c5e0d99 test/langtools/tools/javac/diags/examples.not-yet.txt
--- a/test/langtools/tools/javac/diags/examples.not-yet.txt Fri Nov 22 15:19:11 2019 +0100
+++ b/test/langtools/tools/javac/diags/examples.not-yet.txt Sun Jan 19 13:49:09 2020 +0100
@@ -203,7 +203,6 @@
# Value types
compiler.err.cyclic.value.type.membership
compiler.err.value.does.not.support
-compiler.err.make.default.with.nonvalue
compiler.err.value.may.not.extend
compiler.warn.potential.null.pollution
compiler.err.empty.value.not.yet
diff -r 7fca6c5e0d99 test/langtools/tools/javac/valhalla/lworld-values/CheckBadSelector.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/valhalla/lworld-values/CheckBadSelector.java Sun Jan 19 13:49:09 2020 +0100
@@ -0,0 +1,14 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary Check that syntax constraints still exist
+ *
+ * @compile/fail/ref=CheckBadSelector.out -XDrawDiagnostics CheckBadSelector.java
+ */
+inline final class Point {
+
+ void badSelector() {
+ Class<?> c = int.class;
+ int i = int.default;
+ int x = int.whatever;
+ }
+}
diff -r 7fca6c5e0d99 test/langtools/tools/javac/valhalla/lworld-values/CheckBadSelector.out
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/valhalla/lworld-values/CheckBadSelector.out Sun Jan 19 13:49:09 2020 +0100
@@ -0,0 +1,2 @@
+CheckBadSelector.java:12:21: compiler.err.expected2: class, default
+1 error
diff -r 7fca6c5e0d99 test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.java
--- a/test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.java Fri Nov 22 15:19:11 2019 +0100
+++ b/test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.java Sun Jan 19 13:49:09 2020 +0100
@@ -23,11 +23,22 @@
final int x;
final int y;
+ final int nonbool = boolean.default;
+ final boolean nonbyte = byte.default;
+ final boolean nonchar = char.default;
+ final boolean nonint = int.default;
+ final boolean nonshort = short.default;
+ final boolean nonlong = long.default;
+ final boolean nonfloat = float.default;
+ final boolean nondouble = double.default;
+ final int nonString = String.default;
+ final int nonbyteArray = byte[].default;
+
Point() {}
Point (int x, int y) {}
- Point badFactory(int x, int y) {
- return Point.default;
+ Point goodFactory(int x, int y) {
+ return Point.default; // Allowed in the new 'State of Valhalla'
}
static Point make(int x, int y) {
diff -r 7fca6c5e0d99 test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.out
--- a/test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.out Fri Nov 22 15:19:11 2019 +0100
+++ b/test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.out Sun Jan 19 13:49:09 2020 +0100
@@ -1,5 +1,13 @@
CheckMakeDefault.java:9:12: compiler.err.illegal.combination.of.modifiers: interface, inline
CheckMakeDefault.java:10:21: compiler.err.illegal.combination.of.modifiers: abstract, inline
-CheckMakeDefault.java:13:26: compiler.err.make.default.with.nonvalue
-CheckMakeDefault.java:35:25: compiler.err.make.default.with.nonvalue
-4 errors
+CheckMakeDefault.java:26:32: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: boolean, int)
+CheckMakeDefault.java:27:33: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: byte, boolean)
+CheckMakeDefault.java:28:33: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: char, boolean)
+CheckMakeDefault.java:29:31: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: int, boolean)
+CheckMakeDefault.java:30:35: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: short, boolean)
+CheckMakeDefault.java:31:33: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: long, boolean)
+CheckMakeDefault.java:32:35: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: float, boolean)
+CheckMakeDefault.java:33:37: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: double, boolean)
+CheckMakeDefault.java:34:33: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, int)
+CheckMakeDefault.java:35:36: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: byte[], int)
+12 errors
\ No newline at end of file
diff -r 7fca6c5e0d99 test/langtools/tools/javac/valhalla/lworld-values/CheckValueFactoryWithReference.java
--- a/test/langtools/tools/javac/valhalla/lworld-values/CheckValueFactoryWithReference.java Fri Nov 22 15:19:11 2019 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @summary Do not allow mismatched instantiation syntax between value & reference types.
- *
- * @compile/fail/ref=CheckValueFactoryWithReference.out -XDrawDiagnostics CheckValueFactoryWithReference.java
- */
-
-final class CheckValueFactoryWithReference {
- final Object o = Object.default;
- inline final class Point { int x = 10; }
- Point p = new Point();
-}
diff -r 7fca6c5e0d99 test/langtools/tools/javac/valhalla/lworld-values/CheckValueFactoryWithReference.out
--- a/test/langtools/tools/javac/valhalla/lworld-values/CheckValueFactoryWithReference.out Fri Nov 22 15:19:11 2019 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-CheckValueFactoryWithReference.java:9:28: compiler.err.make.default.with.nonvalue
-1 error
diff -r 7fca6c5e0d99 test/langtools/tools/javac/valhalla/lworld-values/DefaultNonInlines.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/valhalla/lworld-values/DefaultNonInlines.java Sun Jan 19 13:49:09 2020 +0100
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test Check default values for non-inline types
+ * @bug 8237067
+ * @summary [lworld] Provide linguistic support to denote default values.
+ * @run main/othervm DefaultNonInlines
+ */
+
+public class DefaultNonInlines {
+
+ static inline class Val {
+ public int v = 42;
+ }
+
+ static <T> void checkDefaultT(Class<T> clazz) throws Exception {
+ while (T.default != null)
+ throw new Exception("Generic object should default to null");
+ }
+
+ public static void main(String[] args) throws Exception {
+ // Default value is set by inline class constructor
+ while (Val.default.v != int.default)
+ throw new Exception("inline object fields should default to defaults");
+
+ while ((new Val()).v != 42)
+ throw new Exception("inline object fields should default to whatever constructor says");
+
+ // Simple reference default is just null
+ while (String.default != null)
+ throw new Exception("reference object should default to null");
+
+ // Reference default checked in method above
+ checkDefaultT(String.class);
+
+ // Array type - differnt syntactically
+ while (int[].default != null)
+ throw new Exception("arrays should default to null");
+
+ // Array type - differnt syntactically
+ while (boolean.default != false)
+ throw new Exception("boolean should default to false");
+
+ while (char.default != '\0')
+ throw new Exception("char should default to '\0'");
+
+ while (int.default != 0)
+ throw new Exception("int should default to 0");
+
+ while (byte.default != 0)
+ throw new Exception("byte should default to 0");
+
+ while (short.default != 0)
+ throw new Exception("short should default to 0");
+
+ while (long.default != 0L)
+ throw new Exception("long should default to 0L");
+
+ while (float.default != 0.0F)
+ throw new Exception("float should default to 0.0F");
+
+ while (double.default != 0.0D)
+ throw new Exception("double should default to 0.0D");
+ }
+}
More information about the valhalla-dev
mailing list