changeset 50625:528fce34226e condy-folding

removing regular expressions from the constants api
author vromero
date Fri, 11 May 2018 14:46:38 -0700
parents 10d2bee4357d
children 89750f4b2b25
files src/java.base/share/classes/java/lang/invoke/constant/ConstantClassDesc.java src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodTypeDesc.java src/java.base/share/classes/java/lang/invoke/constant/ConstantUtils.java test/jdk/java/lang/invoke/constant/ClassRefTest.java test/jdk/java/lang/invoke/constant/CondyRefTest.java test/jdk/java/lang/invoke/constant/IntrinsifiedRefTest.java test/jdk/java/lang/invoke/constant/MethodHandleRefTest.java test/jdk/java/lang/invoke/constant/MethodTypeRefTest.java test/jdk/java/lang/invoke/constant/SymbolicRefTest.java
diffstat 9 files changed, 115 insertions(+), 82 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/invoke/constant/ConstantClassDesc.java	Fri May 11 10:19:27 2018 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantClassDesc.java	Fri May 11 14:46:38 2018 -0700
@@ -28,9 +28,6 @@
 import java.lang.reflect.Array;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.regex.Pattern;
-
-import jdk.internal.lang.annotation.Foldable;
 
 import static java.lang.invoke.constant.ConstantDescs.BSM_CLASSDESC;
 import static java.lang.invoke.constant.ConstantDescs.CR_ClassDesc;
@@ -44,9 +41,6 @@
  * {@code Constant_Class_info} entry in the constant pool of a classfile.
  */
 public class ConstantClassDesc implements ClassDesc {
-    @Foldable
-    private static final Pattern TYPE_DESC = Pattern.compile("(\\[*)(V|I|J|S|B|C|F|D|Z|L[^/.\\[;][^.\\[;]*;)");
-
     private final String descriptor;
 
     /**
@@ -59,14 +53,11 @@
      * field descriptor string, or does not describe a class or interface type
      */
     ConstantClassDesc(String descriptor) {
-        // @@@ Replace validation with a lower-overhead mechanism than regex
-        // Follow the trail from MethodType.fromMethodDescriptorString to
-        // parsing code in sun/invoke/util/BytecodeDescriptor.java which could
-        // be extracted and/or shared
-        // @@@ regex actually permits primitive types
         requireNonNull(descriptor);
-        if (!TYPE_DESC.matcher(descriptor).matches())
-            throw new IllegalArgumentException(String.format("not a valid type descriptor: %s", descriptor));
+        int len = ConstantUtils.matchSig(descriptor, 0, descriptor.length());
+        if (len == 0 || len == 1
+            || len != descriptor.length())
+            throw new IllegalArgumentException(String.format("not a valid reference type descriptor: %s", descriptor));
         this.descriptor = descriptor;
     }
 
--- a/src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodTypeDesc.java	Fri May 11 10:19:27 2018 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodTypeDesc.java	Fri May 11 14:46:38 2018 -0700
@@ -24,16 +24,13 @@
  */
 package java.lang.invoke.constant;
 
-import jdk.internal.lang.annotation.Foldable;
-
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+
+import jdk.internal.lang.annotation.Foldable;
 
 import static java.lang.invoke.constant.ConstantDescs.BSM_METHODTYPEDESC;
 import static java.lang.invoke.constant.ConstantDescs.CR_ConstantMethodTypeDesc;
@@ -45,10 +42,6 @@
  * {@code Constant_MethodType_info} entry in the constant pool of a classfile.
  */
 public final class ConstantMethodTypeDesc implements MethodTypeDesc {
-
-    private static final Pattern TYPE_DESC = Pattern.compile("(\\[*)(V|I|J|S|B|C|F|D|Z|L[^/.\\[;][^.\\[;]*;)");
-    private static final Pattern pattern = Pattern.compile("\\((.*)\\)(.*)");
-
     private final ClassDesc returnType;
     private final ClassDesc[] argTypes;
 
@@ -78,30 +71,10 @@
      */
     @Foldable
     static ConstantMethodTypeDesc ofDescriptor(String descriptor) {
-        // @@@ Replace validation with a lower-overhead mechanism than regex
-        // Follow the trail from MethodType.fromMethodDescriptorString to
-        // parsing code in sun/invoke/util/BytecodeDescriptor.java which could
-        // be extracted and/or shared
-        Matcher matcher = pattern.matcher(descriptor);
-        if (!matcher.matches())
-            throw new IllegalArgumentException(String.format("%s is not a valid method descriptor", descriptor));
-        String paramTypesStr = matcher.group(1);
-        String returnTypeStr = matcher.group(2);
-        if (!TYPE_DESC.matcher(returnTypeStr).matches())
-            throw new IllegalArgumentException(String.format("Invalid return type %s", returnTypeStr));
-        List<String> params = new ArrayList<>();
-        matcher = TYPE_DESC.matcher(paramTypesStr);
-        while (matcher.regionStart() < paramTypesStr.length()) {
-            if (matcher.lookingAt()) {
-                params.add(matcher.group());
-                matcher.region(matcher.end(), matcher.regionEnd());
-            }
-            else
-                throw new IllegalArgumentException(String.format("Invalid parameter type: %s",
-                                                                 paramTypesStr.substring(matcher.regionStart(), matcher.regionEnd())));
-        }
-        ClassDesc[] paramTypes = params.stream().map(ClassDesc::ofDescriptor).toArray(ClassDesc[]::new);
-        return new ConstantMethodTypeDesc(ClassDesc.ofDescriptor(returnTypeStr), paramTypes);
+        requireNonNull(descriptor);
+        List<String> types = ConstantUtils.parseMethodDescriptor(descriptor);
+        ClassDesc[] paramTypes = types.stream().skip(1).map(ClassDesc::ofDescriptor).toArray(ClassDesc[]::new);
+        return new ConstantMethodTypeDesc(ClassDesc.ofDescriptor(types.get(0)), paramTypes);
     }
 
     @Foldable
--- a/src/java.base/share/classes/java/lang/invoke/constant/ConstantUtils.java	Fri May 11 10:19:27 2018 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantUtils.java	Fri May 11 14:46:38 2018 -0700
@@ -24,10 +24,14 @@
  */
 package java.lang.invoke.constant;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Optional;
 import java.util.Set;
 
+import sun.invoke.util.Wrapper;
+
 /**
  * ConstantUtils
  *
@@ -118,4 +122,69 @@
             return Optional.empty();
         }
     }
+
+    /**
+     * Parse a method descriptor string, and return a list of field descriptor
+     * strings, return type first, then parameter types
+     *
+     * @param descriptor the descriptor string
+     * @return the list of types
+     * @throws IllegalArgumentException if the descriptor string is not valid
+     */
+    static List<String> parseMethodDescriptor(String descriptor) {
+        int cur = 0, end = descriptor.length();
+        ArrayList<String> ptypes = new ArrayList<>();
+
+        if (cur >= end || descriptor.charAt(cur) != '(')
+            throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
+
+        ++cur;  // skip '('
+        while (cur < end && descriptor.charAt(cur) != ')') {
+            int len = matchSig(descriptor, cur, end);
+            if (len == 0 || descriptor.charAt(cur) == 'V')
+                throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
+            ptypes.add(descriptor.substring(cur, cur + len));
+            cur += len;
+        }
+        if (cur >= end)
+            throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
+        ++cur;  // skip ')'
+
+        int rLen = matchSig(descriptor, cur, end);
+        if (rLen == 0 || cur + rLen != end)
+            throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
+        ptypes.add(0, descriptor.substring(cur, cur + rLen));
+        return ptypes;
+    }
+
+    /**
+     * Validate that the characters at [start, end) within the provided string
+     * describe a valid field type descriptor.
+     *
+     * @param str the descriptor string
+     * @param start the starting index into the string
+     * @param end the ending index within the string
+     * @return the length of the descriptor, or 0 if it is not a descriptor
+     * @throws IllegalArgumentException if the descriptor string is not valid
+     */
+    static int matchSig(String str, int start, int end) {
+        if (start >= end || start >= str.length() || end > str.length())
+            return 0;
+        char c = str.charAt(start);
+        if (c == 'L') {
+            int endc = str.indexOf(';', start);
+            int badc = str.indexOf('.', start);
+            if (badc >= 0 && badc < endc)
+                return 0;
+            badc = str.indexOf('[', start);
+            if (badc >= 0 && badc < endc)
+                return 0;
+            return (endc < 0) ? 0 : endc - start + 1;
+        } else if (c == '[') {
+            int t = matchSig(str, start+1, end);
+            return (t > 0) ? t + 1 : 0;
+        } else {
+            return ("IJCSBFDZV".indexOf(c) >= 0) ? 1 : 0;
+        }
+    }
 }
--- a/test/jdk/java/lang/invoke/constant/ClassRefTest.java	Fri May 11 10:19:27 2018 -0700
+++ b/test/jdk/java/lang/invoke/constant/ClassRefTest.java	Fri May 11 14:46:38 2018 -0700
@@ -57,17 +57,17 @@
         assertEquals(r, ClassDesc.ofDescriptor(r.descriptorString()));
 
         if (!r.descriptorString().equals("V")) {
-            assertEquals(r, r.array().componentType());
+            assertEquals(r, r.arrayType().componentType());
             // Commutativity: array -> resolve -> componentType -> toSymbolic
-            assertEquals(r, r.array().resolveConstantDesc(LOOKUP).getComponentType().describeConstable(LOOKUP).orElseThrow());
+            assertEquals(r, r.arrayType().resolveConstantDesc(LOOKUP).getComponentType().describeConstable().orElseThrow());
             // Commutativity: resolve -> array -> toSymbolic -> component type
-            assertEquals(r, Array.newInstance(r.resolveConstantDesc(LOOKUP), 0).getClass().describeConstable(LOOKUP).orElseThrow().componentType());
+            assertEquals(r, Array.newInstance(r.resolveConstantDesc(LOOKUP), 0).getClass().describeConstable().orElseThrow().componentType());
         }
 
         if (r.isArray()) {
-            assertEquals(r, r.componentType().array());
-            assertEquals(r, r.resolveConstantDesc(LOOKUP).getComponentType().describeConstable(LOOKUP).orElseThrow().array());
-            assertEquals(r, Array.newInstance(r.componentType().resolveConstantDesc(LOOKUP), 0).getClass().describeConstable(LOOKUP).orElseThrow());
+            assertEquals(r, r.componentType().arrayType());
+            assertEquals(r, r.resolveConstantDesc(LOOKUP).getComponentType().describeConstable().orElseThrow().arrayType());
+            assertEquals(r, Array.newInstance(r.componentType().resolveConstantDesc(LOOKUP), 0).getClass().describeConstable().orElseThrow());
         }
     }
 
@@ -75,8 +75,8 @@
         testClassRef(r);
 
         assertEquals(r.resolveConstantDesc(LOOKUP), c);
-        assertEquals(c.describeConstable(LOOKUP).orElseThrow(), r);
-        assertEquals(ClassDesc.ofDescriptor(c.toDescriptorString()), r);
+        assertEquals(c.describeConstable().orElseThrow(), r);
+        assertEquals(ClassDesc.ofDescriptor(c.descriptorString()), r);
     }
 
     public void testSymbolicRefsConstants() throws ReflectiveOperationException {
@@ -113,9 +113,9 @@
                 assertEquals(p.name, c.displayName());
                 refs.forEach(cc -> assertEquals(c, cc));
                 if (p != Primitives.VOID) {
-                    testClassRef(c.array(), p.arrayClass);
+                    testClassRef(c.arrayType(), p.arrayClass);
                     assertEquals(c, ((ClassDesc) p.arrayClass.describeConstable().orElseThrow()).componentType());
-                    assertEquals(c, p.classRef.array().componentType());
+                    assertEquals(c, p.classRef.arrayType().componentType());
                 }
             }
 
@@ -134,18 +134,18 @@
         List<ClassDesc> stringClassRefs = Arrays.asList(ClassDesc.ofDescriptor("Ljava/lang/String;"),
                                                         ClassDesc.of("java.lang", "String"),
                                                         ClassDesc.of("java.lang.String"),
-                                                        ClassDesc.of("java.lang.String").array().componentType(),
-                                                        String.class.describeConstable(LOOKUP).orElseThrow());
+                                                        ClassDesc.of("java.lang.String").arrayType().componentType(),
+                                                        String.class.describeConstable().orElseThrow());
         for (ClassDesc r : stringClassRefs) {
             testClassRef(r, String.class);
             assertFalse(r.isPrimitive());
             assertEquals("Ljava/lang/String;", r.descriptorString());
             assertEquals("String", r.displayName());
-            assertEquals(r.array().resolveConstantDesc(LOOKUP), String[].class);
+            assertEquals(r.arrayType().resolveConstantDesc(LOOKUP), String[].class);
             stringClassRefs.forEach(rr -> assertEquals(r, rr));
         }
 
-        testClassRef(ClassDesc.of("java.lang.String").array(), String[].class);
+        testClassRef(ClassDesc.of("java.lang.String").arrayType(), String[].class);
         testClassRef(ClassDesc.of("java.util.Map").inner("Entry"), Map.Entry.class);
 
         ClassDesc thisClassRef = ClassDesc.ofDescriptor("LClassRefTest;");
@@ -172,16 +172,16 @@
         assertEquals("", ClassDesc.of("Bar").inner("Baz").packageName());
 
         testBadPackageName(ConstantDescs.CR_int);
-        testBadPackageName(ConstantDescs.CR_int.array());
-        testBadPackageName(ConstantDescs.CR_String.array());
-        testBadPackageName(ClassDesc.of("Bar").array());
+        testBadPackageName(ConstantDescs.CR_int.arrayType());
+        testBadPackageName(ConstantDescs.CR_String.arrayType());
+        testBadPackageName(ClassDesc.of("Bar").arrayType());
     }
 
     public void testArrayClassRef() throws ReflectiveOperationException {
         for (String d : basicDescs) {
             ClassDesc a0 = ClassDesc.ofDescriptor(d);
-            ClassDesc a1 = a0.array();
-            ClassDesc a2 = a1.array();
+            ClassDesc a1 = a0.arrayType();
+            ClassDesc a2 = a1.arrayType();
 
             testClassRef(a0);
             testClassRef(a1);
--- a/test/jdk/java/lang/invoke/constant/CondyRefTest.java	Fri May 11 10:19:27 2018 -0700
+++ b/test/jdk/java/lang/invoke/constant/CondyRefTest.java	Fri May 11 14:46:38 2018 -0700
@@ -66,7 +66,7 @@
     private void testVarHandleRef(DynamicConstantDesc<VarHandle> r, VarHandle vh) throws ReflectiveOperationException  {
         testSymbolicRef(r);
         assertEquals(r.resolveConstantDesc(LOOKUP), vh);
-        assertEquals(vh.describeConstable(LOOKUP).orElseThrow(), r);
+        assertEquals(vh.describeConstable().orElseThrow(), r);
     }
 
     private static<E extends Enum<E>> void testEnumRef(EnumDesc<E> r, E e) throws ReflectiveOperationException {
@@ -94,8 +94,8 @@
     }
 
     public void testNested() throws Throwable {
-        ConstantMethodHandleDesc invoker = ConstantDescs.ofConstantBootstrap(CR_ConstantBootstraps, "invoke", CR_Object, CR_MethodHandle, CR_Object.array());
-        ConstantMethodHandleDesc format = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_String, "format", CR_String, CR_String, CR_Object.array());
+        ConstantMethodHandleDesc invoker = ConstantDescs.ofConstantBootstrap(CR_ConstantBootstraps, "invoke", CR_Object, CR_MethodHandle, CR_Object.arrayType());
+        ConstantMethodHandleDesc format = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_String, "format", CR_String, CR_String, CR_Object.arrayType());
 
         String s = (String) invoker.resolveConstantDesc(LOOKUP)
                                    .invoke(LOOKUP, "", String.class,
@@ -148,7 +148,7 @@
         assertEquals(9, (int) varHandle.get(instance));
         assertEquals(instance.f, 9);
 
-        vhc = VarHandleDesc.ofArray(CR_int.array());
+        vhc = VarHandleDesc.ofArray(CR_int.arrayType());
         varHandle = MethodHandles.arrayElementVarHandle(int[].class);
         testVarHandleRef(vhc, varHandle);
 
@@ -207,9 +207,9 @@
         assertLifted(VarHandleDesc.ofField(testClass, "f", CR_int),
                      DynamicConstantDesc.of(ConstantDescs.BSM_VARHANDLE_FIELD, "f", CR_VarHandle, new ConstantDesc<?>[] {testClass, "f", CR_int }),
                      DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_VARHANDLE_FIELD, "f", CR_VarHandle, new ConstantDesc<?>[] {testClass, "f", CR_int }));
-        assertLifted(VarHandleDesc.ofArray(CR_int.array()),
-                     DynamicConstantDesc.of(ConstantDescs.BSM_VARHANDLE_ARRAY, "_", CR_VarHandle, new ConstantDesc<?>[] {CR_int.array() }),
-                     DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_VARHANDLE_ARRAY, "_", CR_VarHandle, new ConstantDesc<?>[] {CR_int.array() }));
+        assertLifted(VarHandleDesc.ofArray(CR_int.arrayType()),
+                     DynamicConstantDesc.of(ConstantDescs.BSM_VARHANDLE_ARRAY, "_", CR_VarHandle, new ConstantDesc<?>[] {CR_int.arrayType() }),
+                     DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_VARHANDLE_ARRAY, "_", CR_VarHandle, new ConstantDesc<?>[] {CR_int.arrayType() }));
     }
 
 }
--- a/test/jdk/java/lang/invoke/constant/IntrinsifiedRefTest.java	Fri May 11 10:19:27 2018 -0700
+++ b/test/jdk/java/lang/invoke/constant/IntrinsifiedRefTest.java	Fri May 11 14:46:38 2018 -0700
@@ -85,7 +85,7 @@
     private static <T extends Constable> void assertIntrinsic(ConstantDesc<T> ref, T intrinsified, T target) throws ReflectiveOperationException {
         assertEquals(target, intrinsified);
         assertEquals(ref.resolveConstantDesc(LOOKUP), intrinsified);
-        assertEquals(intrinsified.describeConstable(LOOKUP).orElseThrow(), ref);
+        assertEquals(intrinsified.describeConstable().orElseThrow(), ref);
     }
 
     private static<T extends Constable> void assertIntrinsicFail(ConstantDesc<T> ref, Supplier<T> supplier, Class<? extends Throwable> exception) {
@@ -114,7 +114,7 @@
         assertIntrinsic(cr3, ldc(cr3), String.class);
 
         ClassDesc cr4 = ClassDesc.ofDescriptor("[Ljava/lang/String;");
-        ClassDesc cr5 = cr2.array();
+        ClassDesc cr5 = cr2.arrayType();
         assertIntrinsic(cr4, ldc(cr4), String[].class);
         assertIntrinsic(cr5, ldc(cr5), String[].class);
 
@@ -123,7 +123,7 @@
         assertIntrinsic(ConstantDescs.CR_int, ldc(ConstantDescs.CR_int), int.class);
 
         ClassDesc cr7 = ClassDesc.ofDescriptor("[I");
-        ClassDesc cr8 = ConstantDescs.CR_int.array();
+        ClassDesc cr8 = ConstantDescs.CR_int.arrayType();
         assertIntrinsic(cr7, ldc(cr7), int[].class);
         assertIntrinsic(cr8, ldc(cr8), int[].class);
     }
--- a/test/jdk/java/lang/invoke/constant/MethodHandleRefTest.java	Fri May 11 10:19:27 2018 -0700
+++ b/test/jdk/java/lang/invoke/constant/MethodHandleRefTest.java	Fri May 11 14:46:38 2018 -0700
@@ -94,12 +94,12 @@
         testMethodHandleRef(r);
 
         assertMHEquals(r.resolveConstantDesc(LOOKUP), mh);
-        assertEquals(mh.describeConstable(LOOKUP).orElseThrow(), r);
+        assertEquals(mh.describeConstable().orElseThrow(), r);
 
         // compare extractable properties: refKind, owner, name, type
         MethodHandleInfo mhi = LOOKUP.revealDirect(mh);
         ConstantMethodHandleDesc rr = (ConstantMethodHandleDesc) r;
-        assertEquals(mhi.getDeclaringClass().toDescriptorString(), rr.owner().descriptorString());
+        assertEquals(mhi.getDeclaringClass().descriptorString(), rr.owner().descriptorString());
         assertEquals(mhi.getName(), rr.methodName());
         assertEquals(mhi.getReferenceKind(), rr.kind().refKind);
         assertEquals(mhi.getMethodType().toMethodDescriptorString(), r.methodType().descriptorString());
@@ -108,7 +108,7 @@
     public void testSimpleMHs() throws ReflectiveOperationException {
         testMethodHandleRef(MethodHandleDesc.of(MethodHandleDesc.Kind.VIRTUAL, CR_String, "isEmpty", "()Z"),
                             LOOKUP.findVirtual(String.class, "isEmpty", MethodType.fromMethodDescriptorString("()Z", null)));
-        testMethodHandleRef(MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_String, "format", CR_String, CR_String, CR_Object.array()),
+        testMethodHandleRef(MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_String, "format", CR_String, CR_String, CR_Object.arrayType()),
                             LOOKUP.findStatic(String.class, "format", MethodType.methodType(String.class, String.class, Object[].class)));
         testMethodHandleRef(MethodHandleDesc.of(MethodHandleDesc.Kind.INTERFACE_VIRTUAL, CR_List, "isEmpty", "()Z"),
                             LOOKUP.findVirtual(List.class, "isEmpty", MethodType.fromMethodDescriptorString("()Z", null)));
--- a/test/jdk/java/lang/invoke/constant/MethodTypeRefTest.java	Fri May 11 10:19:27 2018 -0700
+++ b/test/jdk/java/lang/invoke/constant/MethodTypeRefTest.java	Fri May 11 14:46:38 2018 -0700
@@ -65,7 +65,7 @@
         testMethodTypeRef(r);
 
         assertEquals(r.resolveConstantDesc(LOOKUP), mt);
-        assertEquals(mt.describeConstable(LOOKUP).get(), r);
+        assertEquals(mt.describeConstable().get(), r);
 
         assertEquals(r.descriptorString(), mt.toMethodDescriptorString());
         assertEquals(r.parameterCount(), mt.parameterCount());
--- a/test/jdk/java/lang/invoke/constant/SymbolicRefTest.java	Fri May 11 10:19:27 2018 -0700
+++ b/test/jdk/java/lang/invoke/constant/SymbolicRefTest.java	Fri May 11 14:46:38 2018 -0700
@@ -85,7 +85,7 @@
     }
 
     static ClassDesc classToRef(Class<?> c) {
-        return ClassDesc.ofDescriptor(c.toDescriptorString());
+        return ClassDesc.ofDescriptor(c.descriptorString());
     }
 
     static<T> void testSymbolicRef(ConstantDesc<T> ref) throws ReflectiveOperationException {
@@ -99,12 +99,12 @@
     private static<T> void testSymbolicRef(ConstantDesc<T> ref, boolean forwardOnly) throws ReflectiveOperationException {
         if (!forwardOnly) {
             // Round trip sym -> resolve -> toSymbolicRef
-            ConstantDesc<? super ConstantDesc<T>> s = ((Constable<ConstantDesc<T>>) ref.resolveConstantDesc(LOOKUP)).describeConstable(LOOKUP).orElseThrow();
+            ConstantDesc<? super ConstantDesc<T>> s = ((Constable<ConstantDesc<T>>) ref.resolveConstantDesc(LOOKUP)).describeConstable().orElseThrow();
             assertEquals(ref, s);
         }
 
         // Round trip sym -> quoted sym -> resolve
-        Optional<ConstantDesc<ConstantDesc<T>>> opt = (Optional<ConstantDesc<ConstantDesc<T>>>) ((Constable) ref).describeConstable(LOOKUP);
+        Optional<ConstantDesc<ConstantDesc<T>>> opt = (Optional<ConstantDesc<ConstantDesc<T>>>) ((Constable) ref).describeConstable();
         ConstantDesc<T> sr = opt.orElseThrow().resolveConstantDesc(LOOKUP);
         assertEquals(sr, ref);
     }