1625 } |
1625 } |
1626 |
1626 |
1627 // Attribute clazz expression and store |
1627 // Attribute clazz expression and store |
1628 // symbol + type back into the attributed tree. |
1628 // symbol + type back into the attributed tree. |
1629 Type clazztype = attribType(clazz, env); |
1629 Type clazztype = attribType(clazz, env); |
1630 Pair<Scope,Scope> mapping = getSyntheticScopeMapping(clazztype); |
|
1631 clazztype = chk.checkDiamond(tree, clazztype); |
1630 clazztype = chk.checkDiamond(tree, clazztype); |
1632 chk.validate(clazz, localEnv); |
1631 chk.validate(clazz, localEnv); |
1633 if (tree.encl != null) { |
1632 if (tree.encl != null) { |
1634 // We have to work in this case to store |
1633 // We have to work in this case to store |
1635 // symbol + type back into the attributed tree. |
1634 // symbol + type back into the attributed tree. |
1652 // Attribute constructor arguments. |
1651 // Attribute constructor arguments. |
1653 List<Type> argtypes = attribArgs(tree.args, localEnv); |
1652 List<Type> argtypes = attribArgs(tree.args, localEnv); |
1654 List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv); |
1653 List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv); |
1655 |
1654 |
1656 if (TreeInfo.isDiamond(tree) && !clazztype.isErroneous()) { |
1655 if (TreeInfo.isDiamond(tree) && !clazztype.isErroneous()) { |
1657 clazztype = attribDiamond(localEnv, tree, clazztype, mapping, argtypes, typeargtypes); |
1656 clazztype = attribDiamond(localEnv, tree, clazztype, argtypes, typeargtypes); |
1658 clazz.type = clazztype; |
1657 clazz.type = clazztype; |
1659 } else if (allowDiamondFinder && |
1658 } else if (allowDiamondFinder && |
1660 tree.def == null && |
1659 tree.def == null && |
1661 !clazztype.isErroneous() && |
1660 !clazztype.isErroneous() && |
1662 clazztype.getTypeArguments().nonEmpty() && |
1661 clazztype.getTypeArguments().nonEmpty() && |
1825 } |
1823 } |
1826 |
1824 |
1827 Type attribDiamond(Env<AttrContext> env, |
1825 Type attribDiamond(Env<AttrContext> env, |
1828 JCNewClass tree, |
1826 JCNewClass tree, |
1829 Type clazztype, |
1827 Type clazztype, |
1830 Pair<Scope, Scope> mapping, |
|
1831 List<Type> argtypes, |
1828 List<Type> argtypes, |
1832 List<Type> typeargtypes) { |
1829 List<Type> typeargtypes) { |
1833 if (clazztype.isErroneous() || |
1830 if (clazztype.isErroneous() || |
1834 clazztype.isInterface() || |
1831 clazztype.isInterface()) { |
1835 mapping == erroneousMapping) { |
|
1836 //if the type of the instance creation expression is erroneous, |
1832 //if the type of the instance creation expression is erroneous, |
1837 //or if it's an interface, or if something prevented us to form a valid |
1833 //or if it's an interface, or if something prevented us to form a valid |
1838 //mapping, return the (possibly erroneous) type unchanged |
1834 //mapping, return the (possibly erroneous) type unchanged |
1839 return clazztype; |
1835 return clazztype; |
1840 } |
1836 } |
1841 |
1837 |
1842 //dup attribution environment and augment the set of inference variables |
1838 //dup attribution environment and augment the set of inference variables |
1843 Env<AttrContext> localEnv = env.dup(tree); |
1839 Env<AttrContext> localEnv = env.dup(tree); |
1844 localEnv.info.tvars = clazztype.tsym.type.getTypeArguments(); |
1840 |
|
1841 ClassType site = new ClassType(clazztype.getEnclosingType(), |
|
1842 clazztype.tsym.type.getTypeArguments(), |
|
1843 clazztype.tsym); |
1845 |
1844 |
1846 //if the type of the instance creation expression is a class type |
1845 //if the type of the instance creation expression is a class type |
1847 //apply method resolution inference (JLS 15.12.2.7). The return type |
1846 //apply method resolution inference (JLS 15.12.2.7). The return type |
1848 //of the resolved constructor will be a partially instantiated type |
1847 //of the resolved constructor will be a partially instantiated type |
1849 ((ClassSymbol) clazztype.tsym).members_field = mapping.snd; |
1848 Symbol constructor = rs.resolveDiamond(tree.pos(), |
1850 Symbol constructor; |
|
1851 try { |
|
1852 constructor = rs.resolveDiamond(tree.pos(), |
|
1853 localEnv, |
1849 localEnv, |
1854 clazztype, |
1850 site, |
1855 argtypes, |
1851 argtypes, |
1856 typeargtypes); |
1852 typeargtypes); |
1857 } finally { |
1853 |
1858 ((ClassSymbol) clazztype.tsym).members_field = mapping.fst; |
|
1859 } |
|
1860 if (constructor.kind == MTH) { |
1854 if (constructor.kind == MTH) { |
1861 ClassType ct = new ClassType(clazztype.getEnclosingType(), |
1855 clazztype = checkMethod(site, |
1862 clazztype.tsym.type.getTypeArguments(), |
|
1863 clazztype.tsym); |
|
1864 clazztype = checkMethod(ct, |
|
1865 constructor, |
1856 constructor, |
1866 localEnv, |
1857 localEnv, |
1867 tree.args, |
1858 tree.args, |
1868 argtypes, |
1859 argtypes, |
1869 typeargtypes, |
1860 typeargtypes, |
1890 } |
1881 } |
1891 return chk.checkClassType(tree.clazz.pos(), |
1882 return chk.checkClassType(tree.clazz.pos(), |
1892 clazztype, |
1883 clazztype, |
1893 true); |
1884 true); |
1894 } |
1885 } |
1895 |
|
1896 /** Creates a synthetic scope containing fake generic constructors. |
|
1897 * Assuming that the original scope contains a constructor of the kind: |
|
1898 * Foo(X x, Y y), where X,Y are class type-variables declared in Foo, |
|
1899 * the synthetic scope is added a generic constructor of the kind: |
|
1900 * <X,Y>Foo<X,Y>(X x, Y y). This is crucial in order to enable diamond |
|
1901 * inference. The inferred return type of the synthetic constructor IS |
|
1902 * the inferred type for the diamond operator. |
|
1903 */ |
|
1904 private Pair<Scope, Scope> getSyntheticScopeMapping(Type ctype) { |
|
1905 if (ctype.tag != CLASS) { |
|
1906 return erroneousMapping; |
|
1907 } |
|
1908 |
|
1909 Pair<Scope, Scope> mapping = |
|
1910 new Pair<Scope, Scope>(ctype.tsym.members(), new Scope(ctype.tsym)); |
|
1911 |
|
1912 //for each constructor in the original scope, create a synthetic constructor |
|
1913 //whose return type is the type of the class in which the constructor is |
|
1914 //declared, and insert it into the new scope. |
|
1915 for (Scope.Entry e = mapping.fst.lookup(names.init); |
|
1916 e.scope != null; |
|
1917 e = e.next()) { |
|
1918 Type synthRestype = new ClassType(ctype.getEnclosingType(), |
|
1919 ctype.tsym.type.getTypeArguments(), |
|
1920 ctype.tsym); |
|
1921 MethodSymbol synhConstr = new MethodSymbol(e.sym.flags(), |
|
1922 names.init, |
|
1923 types.createMethodTypeWithReturn(e.sym.type, synthRestype), |
|
1924 e.sym.owner); |
|
1925 mapping.snd.enter(synhConstr); |
|
1926 } |
|
1927 return mapping; |
|
1928 } |
|
1929 |
|
1930 private final Pair<Scope,Scope> erroneousMapping = new Pair<Scope,Scope>(null, null); |
|
1931 |
1886 |
1932 /** Make an attributed null check tree. |
1887 /** Make an attributed null check tree. |
1933 */ |
1888 */ |
1934 public JCExpression makeNullCheck(JCExpression arg) { |
1889 public JCExpression makeNullCheck(JCExpression arg) { |
1935 // optimization: X.this is never null; skip null check |
1890 // optimization: X.this is never null; skip null check |