7148164: attribution code for diamond should not rely on mutable state
authormcimadamore
Fri, 02 Mar 2012 12:58:35 +0000
changeset 12078 7470e05d486b
parent 12077 2038f4fe956e
child 12079 e1739a771470
7148164: attribution code for diamond should not rely on mutable state Summary: Update attribution code for diamond operator not to rely on mutable state Reviewed-by: jjg
langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Mar 02 12:57:47 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Mar 02 12:58:35 2012 +0000
@@ -1627,7 +1627,6 @@
         // Attribute clazz expression and store
         // symbol + type back into the attributed tree.
         Type clazztype = attribType(clazz, env);
-        Pair<Scope,Scope> mapping = getSyntheticScopeMapping(clazztype);
         clazztype = chk.checkDiamond(tree, clazztype);
         chk.validate(clazz, localEnv);
         if (tree.encl != null) {
@@ -1654,7 +1653,7 @@
         List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv);
 
         if (TreeInfo.isDiamond(tree) && !clazztype.isErroneous()) {
-            clazztype = attribDiamond(localEnv, tree, clazztype, mapping, argtypes, typeargtypes);
+            clazztype = attribDiamond(localEnv, tree, clazztype, argtypes, typeargtypes);
             clazz.type = clazztype;
         } else if (allowDiamondFinder &&
                 tree.def == null &&
@@ -1671,7 +1670,6 @@
                 inferred = attribDiamond(localEnv,
                         tree,
                         clazztype,
-                        mapping,
                         argtypes,
                         typeargtypes);
             }
@@ -1827,12 +1825,10 @@
     Type attribDiamond(Env<AttrContext> env,
                         JCNewClass tree,
                         Type clazztype,
-                        Pair<Scope, Scope> mapping,
                         List<Type> argtypes,
                         List<Type> typeargtypes) {
         if (clazztype.isErroneous() ||
-                clazztype.isInterface() ||
-                mapping == erroneousMapping) {
+                clazztype.isInterface()) {
             //if the type of the instance creation expression is erroneous,
             //or if it's an interface, or if something prevented us to form a valid
             //mapping, return the (possibly erroneous) type unchanged
@@ -1841,27 +1837,22 @@
 
         //dup attribution environment and augment the set of inference variables
         Env<AttrContext> localEnv = env.dup(tree);
-        localEnv.info.tvars = clazztype.tsym.type.getTypeArguments();
+
+        ClassType site = new ClassType(clazztype.getEnclosingType(),
+                    clazztype.tsym.type.getTypeArguments(),
+                    clazztype.tsym);
 
         //if the type of the instance creation expression is a class type
         //apply method resolution inference (JLS 15.12.2.7). The return type
         //of the resolved constructor will be a partially instantiated type
-        ((ClassSymbol) clazztype.tsym).members_field = mapping.snd;
-        Symbol constructor;
-        try {
-            constructor = rs.resolveDiamond(tree.pos(),
+        Symbol constructor = rs.resolveDiamond(tree.pos(),
                     localEnv,
-                    clazztype,
+                    site,
                     argtypes,
                     typeargtypes);
-        } finally {
-            ((ClassSymbol) clazztype.tsym).members_field = mapping.fst;
-        }
+
         if (constructor.kind == MTH) {
-            ClassType ct = new ClassType(clazztype.getEnclosingType(),
-                    clazztype.tsym.type.getTypeArguments(),
-                    clazztype.tsym);
-            clazztype = checkMethod(ct,
+            clazztype = checkMethod(site,
                     constructor,
                     localEnv,
                     tree.args,
@@ -1893,42 +1884,6 @@
                 true);
     }
 
-    /** Creates a synthetic scope containing fake generic constructors.
-     *  Assuming that the original scope contains a constructor of the kind:
-     *  Foo(X x, Y y), where X,Y are class type-variables declared in Foo,
-     *  the synthetic scope is added a generic constructor of the kind:
-     *  <X,Y>Foo<X,Y>(X x, Y y). This is crucial in order to enable diamond
-     *  inference. The inferred return type of the synthetic constructor IS
-     *  the inferred type for the diamond operator.
-     */
-    private Pair<Scope, Scope> getSyntheticScopeMapping(Type ctype) {
-        if (ctype.tag != CLASS) {
-            return erroneousMapping;
-        }
-
-        Pair<Scope, Scope> mapping =
-                new Pair<Scope, Scope>(ctype.tsym.members(), new Scope(ctype.tsym));
-
-        //for each constructor in the original scope, create a synthetic constructor
-        //whose return type is the type of the class in which the constructor is
-        //declared, and insert it into the new scope.
-        for (Scope.Entry e = mapping.fst.lookup(names.init);
-                e.scope != null;
-                e = e.next()) {
-            Type synthRestype = new ClassType(ctype.getEnclosingType(),
-                        ctype.tsym.type.getTypeArguments(),
-                        ctype.tsym);
-            MethodSymbol synhConstr = new MethodSymbol(e.sym.flags(),
-                    names.init,
-                    types.createMethodTypeWithReturn(e.sym.type, synthRestype),
-                    e.sym.owner);
-            mapping.snd.enter(synhConstr);
-        }
-        return mapping;
-    }
-
-    private final Pair<Scope,Scope> erroneousMapping = new Pair<Scope,Scope>(null, null);
-
     /** Make an attributed null check tree.
      */
     public JCExpression makeNullCheck(JCExpression arg) {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Mar 02 12:57:47 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Mar 02 12:58:35 2012 +0000
@@ -1835,7 +1835,7 @@
                    steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
                    sym.kind >= ERRONEOUS) {
                 currentResolutionContext.step = steps.head;
-                sym = findConstructor(pos, env, site, argtypes, typeargtypes,
+                sym = findDiamond(env, site, argtypes, typeargtypes,
                         steps.head.isBoxingRequired(),
                         env.info.varArgs = steps.head.isVarargsRequired());
                 currentResolutionContext.resolutionCache.put(steps.head, sym);
@@ -1867,6 +1867,43 @@
         }
     }
 
+    /** This method scans all the constructor symbol in a given class scope -
+     *  assuming that the original scope contains a constructor of the kind:
+     *  Foo(X x, Y y), where X,Y are class type-variables declared in Foo,
+     *  a method check is executed against the modified constructor type:
+     *  <X,Y>Foo<X,Y>(X x, Y y). This is crucial in order to enable diamond
+     *  inference. The inferred return type of the synthetic constructor IS
+     *  the inferred type for the diamond operator.
+     */
+    private Symbol findDiamond(Env<AttrContext> env,
+                              Type site,
+                              List<Type> argtypes,
+                              List<Type> typeargtypes,
+                              boolean allowBoxing,
+                              boolean useVarargs) {
+        Symbol bestSoFar = methodNotFound;
+        for (Scope.Entry e = site.tsym.members().lookup(names.init);
+             e.scope != null;
+             e = e.next()) {
+            //- System.out.println(" e " + e.sym);
+            if (e.sym.kind == MTH &&
+                (e.sym.flags_field & SYNTHETIC) == 0) {
+                    List<Type> oldParams = e.sym.type.tag == FORALL ?
+                            ((ForAll)e.sym.type).tvars :
+                            List.<Type>nil();
+                    Type constrType = new ForAll(site.tsym.type.getTypeArguments().appendList(oldParams),
+                            types.createMethodTypeWithReturn(e.sym.type.asMethodType(), site));
+                    bestSoFar = selectBest(env, site, argtypes, typeargtypes,
+                            new MethodSymbol(e.sym.flags(), names.init, constrType, site.tsym),
+                            bestSoFar,
+                            allowBoxing,
+                            useVarargs,
+                            false);
+            }
+        }
+        return bestSoFar;
+    }
+
     /** Resolve constructor.
      *  @param pos       The position to use for error reporting.
      *  @param env       The environment current at the constructor invocation.