8237067: Implementation of <anyType>.default - (lworld branch)

Jesper Steen Møller jesper at selskabet.org
Mon Feb 3 08:40:06 UTC 2020


Hi list and Srikanth

Here’s a second version of the patch.

> (1) The change in LocaleProvidersRun.java seems unconnected to the fix. I am able to back it out and the test still passes.

Removed.

> (2) CheckBadSelector.java: it is customary to include the bug number with a @bug xxxxxxxx tag

Fixed.

> (3) CheckMakeDefault.java: I apologize for having left stale identifiers in this file. But now that we are changing it,
> could you (a) remove the comments "// NO: Sinner is not a value class." in line 13, (b) drop the "// OK" from line 19 (c) Drop the comment "// Allowed in the new 'State of Valhalla'" in line 41 (it was allowed already, the name badFactory was stale)

Fixed, I removed the badFactory as it wasn’t testing anything by itself.

> (4) DefaultNonInlines.java: (a) Copyright mentions 2018. (b) I am curious - why are the statements using while instead if ?? (c) The SOP is to throw new AssertionError rather than just Exception. (d) The second "// Array type - differnt syntactically" is inappropriate. (d) '\0' shows up highlit in red in Vim - (why ?) It accepts '\u0000' without gripes.
> 

a) Fixed
b) By using while, we (implicitly) test that the .default is not a Constant Expression as per the spec. The reachability-analysis will detect that a “while (<constant-expression>) { <body> }” does not terminate if <constant-expression> evaluates to true and <body> doesn’t contain a break or return. So implicitly, this way, we test that the <type>.default does not produce a constant expression. I’ve added a comment mentioning this.
c) Fixed.
d) Vim must somehow not understand octal escapes in character. In my reading of JLS §3.10.4 (Character Literals) and §3.10.6 (Escape Sequences for Character and String Literals), single octal digits are just fine as EscapeSequences. In this case, the code unit lies within the supported range for octals (\u0000 through \u00FF), so all is legal Java.

> (5) Gen.java: Can we factor out the common code result = items.makeStackItem(tree.type); from the 3 paths ??
> 

Fixed

> (6) JavacParser.java: 1345 - Just curious - what necessitates this change ??
> 

The token’s end position must be recorded for the produced node, otherwise the postion information will be incomplete. This is tested in tools/javac/tree/TreePosTest.java which will fail without this change.

> 
> (7) I think the changes to allow Type.default should be keyed off of Feature.INLINE_TYPES (see com.sun.tools.javac.code.Source.Feature#allowedInSource). Earlier code changes done by me may have missed checking for this. Sorry about that! We can take the present opportunity to fix that. It may be cleaner to always allow this in the parser and report an error in Attr.
> 
> As of now
> 
> class X {
>     X x = X.default;
> }
> 
> compiles fine with valhalla tip when javac is invoked as: valhalla/build/linux-x86_64-server-release/images/jdk/bin/javac --release 13 X.java


Fixed in the parser in the three places, and a test (CheckFeatureGate) has been added to test all feature gating of inlines.

-Jesper

diff -r e2f1c4d5f39e 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	Tue Jan 28 17:12:01 2020 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Feb 03 09:38:20 2020 +0100
@@ -4042,10 +4042,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;
+                }
             }
         }
 
@@ -4203,12 +4208,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);
@@ -4218,6 +4218,10 @@
             case WILDCARD:
                 throw new AssertionError(tree);
             case TYPEVAR:
+                if (name == names._default) {
+                    // Be sure to return the default value before examining bounds
+                    return new VarSymbol(STATIC, names._default, site, site.tsym);
+                }
                 // Normally, site.getUpperBound() shouldn't be null.
                 // It should only happen during memberEnter/attribBase
                 // when determining the super type which *must* beac
@@ -4242,11 +4246,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 is 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 e2f1c4d5f39e 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	Tue Jan 28 17:12:01 2020 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Mon Feb 03 09:38:20 2020 +0100
@@ -2405,7 +2405,13 @@
             result = items.makeStackItem(pt);
             return;
         } else if (tree.name == names._default) {
-            code.emitop2(defaultvalue, checkDimension(tree.pos(), tree.type), PoolWriter::putClass);
+            if (tree.type.asElement().isValue()) {
+                code.emitop2(defaultvalue, checkDimension(tree.pos(), tree.type), PoolWriter::putClass);
+            } else if (tree.type.isReference()) {
+                code.emitop0(aconst_null);
+            } else {
+                code.emitop0(zero(Code.typecode(tree.type)));
+            }
             result = items.makeStackItem(tree.type);
             return;
         }
diff -r e2f1c4d5f39e 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	Tue Jan 28 17:12:01 2020 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Feb 03 09:38:20 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) {
@@ -1324,11 +1340,14 @@
                         if ((mode & EXPR) != 0) {
                             switch (token.kind) {
                             case DEFAULT:
-                                if (typeArgs != null) return illegal();
-                                selectExprMode();
-                                t = F.at(pos).Select(t, names._default);
-                                nextToken();
-                                break loop;
+                                if (Feature.INLINE_TYPES.allowedInSource(source)) {
+                                    if (typeArgs != null) return illegal();
+                                    selectExprMode();
+                                    t = to(F.at(pos).Select(t, names._default));
+                                    nextToken();
+                                    break loop;
+                                }
+                                break;
                             case CLASS:
                                 if (typeArgs != null) return illegal();
                                 selectExprMode();
@@ -1395,7 +1414,7 @@
                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
                             while (token.kind == DOT) {
                                 nextToken();
-                                if (token.kind == DEFAULT) {
+                                if (token.kind == DEFAULT && Feature.INLINE_TYPES.allowedInSource(source)) {
                                     t =  toP(F.at(token.pos).Select(t, names._default));
                                     nextToken();
                                     selectExprMode();
@@ -2228,7 +2247,13 @@
             selectExprMode();
             int pos = token.pos;
             nextToken();
-            accept(CLASS);
+            TokenKind selector;
+            if (Feature.INLINE_TYPES.allowedInSource(source)) {
+                selector = accept2(CLASS, DEFAULT);
+            } else {
+                accept(CLASS);
+                selector = CLASS;
+            }
             if (token.pos == endPosTable.errorEndPos) {
                 // error recovery
                 Name name;
@@ -2246,7 +2271,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 e2f1c4d5f39e 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	Mon Feb 03 09:38:20 2020 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020, 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
+ * @bug 8237067
+ * @summary [lworld] Check good and bad selectors on a type name
+ * @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 e2f1c4d5f39e 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	Mon Feb 03 09:38:20 2020 +0100
@@ -0,0 +1,2 @@
+CheckBadSelector.java:37:21: compiler.err.expected2: class, default
+1 error
diff -r e2f1c4d5f39e test/langtools/tools/javac/valhalla/lworld-values/CheckFeatureGate.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/valhalla/lworld-values/CheckFeatureGate.java	Mon Feb 03 09:38:20 2020 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2020, 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 eve
+ *
+ * n 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
+ * @bug 8237067
+ * @summary Check that feature gated constructs are not allowed in previous versions.
+ * @compile/fail/ref=CheckFeatureGate.out --release=13 -XDrawDiagnostics CheckFeatureGate.java
+ */
+
+public class CheckFeatureGate {
+
+    static inline class Val {
+        public int v = 42;
+    }
+
+    static <T> void checkDefaultT(Class<T> clazz) throws Exception {
+        while (T.default != null)
+            throw new AssertionError("Generic object should default to null");
+    }
+
+    public static void main(String[] args) throws Exception {
+        int a = int.default;
+        String s = String.default;
+        int[] ia = int[].default;
+        checkDefaultT(Object.class);
+    }
+}
diff -r e2f1c4d5f39e test/langtools/tools/javac/valhalla/lworld-values/CheckFeatureGate.out
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/valhalla/lworld-values/CheckFeatureGate.out	Mon Feb 03 09:38:20 2020 +0100
@@ -0,0 +1,12 @@
+CheckFeatureGate.java:37:12: compiler.err.feature.not.supported.in.source: (compiler.misc.feature.inline.type), 13, 14
+CheckFeatureGate.java:42:18: compiler.err.expected: token.identifier
+CheckFeatureGate.java:42:25: compiler.err.expected2: :, ->
+CheckFeatureGate.java:42:26: compiler.err.illegal.start.of.expr
+CheckFeatureGate.java:42:33: compiler.err.expected: ';'
+CheckFeatureGate.java:47:21: compiler.err.expected: class
+CheckFeatureGate.java:47:28: compiler.err.expected2: :, ->
+CheckFeatureGate.java:48:27: compiler.err.expected: token.identifier
+CheckFeatureGate.java:48:34: compiler.err.expected2: :, ->
+CheckFeatureGate.java:49:26: compiler.err.expected: class
+CheckFeatureGate.java:49:33: compiler.err.expected2: :, ->
+11 errors
\ No newline at end of file
diff -r e2f1c4d5f39e test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.java
--- a/test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.java	Tue Jan 28 17:12:01 2020 +0530
+++ b/test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.java	Mon Feb 03 09:38:20 2020 +0100
@@ -10,26 +10,33 @@
     inline abstract class A { int x = 10; } // Error
     static final class Sinner {
         static Sinner make() {
-            return Sinner.default; // NO: Sinner is not a value class.
+            return Sinner.default;
         }
     }
 
     inline static final class SinnerValue {
         static SinnerValue make() {
-            return SinnerValue.default; // OK.
+            return SinnerValue.default;
         } int x = 10;
     }
 
     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;
-    }
-
     static Point make(int x, int y) {
        Point p = Point.default;
        String s = String.default;
diff -r e2f1c4d5f39e test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.out
--- a/test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.out	Tue Jan 28 17:12:01 2020 +0530
+++ b/test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.out	Mon Feb 03 09:38:20 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 e2f1c4d5f39e test/langtools/tools/javac/valhalla/lworld-values/CheckValueFactoryWithReference.java
--- a/test/langtools/tools/javac/valhalla/lworld-values/CheckValueFactoryWithReference.java	Tue Jan 28 17:12:01 2020 +0530
+++ /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 e2f1c4d5f39e test/langtools/tools/javac/valhalla/lworld-values/CheckValueFactoryWithReference.out
--- a/test/langtools/tools/javac/valhalla/lworld-values/CheckValueFactoryWithReference.out	Tue Jan 28 17:12:01 2020 +0530
+++ /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 e2f1c4d5f39e 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	Mon Feb 03 09:38:20 2020 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2020, 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 eve
+ *
+ * n 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 -Dtest.compiler.opts=-release=13 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 AssertionError("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 AssertionError("inline object fields should default to defaults");
+
+        while ((new Val()).v != 42)
+            throw new AssertionError("inline object fields should default to whatever constructor says");
+
+        // Simple reference default is just null
+        while (String.default != null)
+            throw new AssertionError("reference object should default to null");
+
+        // Reference default checked in method above
+        checkDefaultT(String.class);
+
+        // Array type - different syntactically
+        while (int[].default != null)
+            throw new AssertionError("arrays should default to null");
+
+        while (boolean.default != false)
+            throw new AssertionError("boolean should default to false");
+
+        while (char.default != '\0')
+            throw new AssertionError("char should default to '\0'");
+
+        while (int.default != 0)
+            throw new AssertionError("int should default to 0");
+
+        while (byte.default != 0)
+            throw new AssertionError("byte should default to 0");
+
+        while (short.default != 0)
+            throw new AssertionError("short should default to 0");
+
+        while (long.default != 0L)
+            throw new AssertionError("long should default to 0L");
+
+        while (float.default != 0.0F)
+            throw new AssertionError("float should default to 0.0F");
+
+        while (double.default != 0.0D)
+            throw new AssertionError("double should default to 0.0D");
+
+        // Note: The while loops above implicitly test that the SomeType.default does not
+        // return a constant expression.
+    }
+}




More information about the valhalla-dev mailing list