336 public void visitLambda(JCLambda tree) {
337 LambdaTranslationContext localContext = (LambdaTranslationContext)context;
338 MethodSymbol sym = localContext.translatedSym;
339 MethodType lambdaType = (MethodType) sym.type;
340
341 { /* Type annotation management: Based on where the lambda features, type annotations that
342 are interior to it, may at this point be attached to the enclosing method, or the first
343 constructor in the class, or in the enclosing class symbol or in the field whose
344 initializer is the lambda. In any event, gather up the annotations that belong to the
345 lambda and attach it to the implementation method.
346 */
347
348 Symbol owner = localContext.owner;
349 apportionTypeAnnotations(tree,
350 owner::getRawTypeAttributes,
351 owner::setTypeAttributes,
352 sym::setTypeAttributes);
353
354
355 boolean init;
356 if ((init = (owner.name == names.init)) || owner.name == names.clinit) {
357 owner = owner.owner;
358 apportionTypeAnnotations(tree,
359 init ? owner::getInitTypeAttributes : owner::getClassInitTypeAttributes,
360 init ? owner::setInitTypeAttributes : owner::setClassInitTypeAttributes,
361 sym::appendUniqueTypeAttributes);
362 }
363 if (localContext.self != null && localContext.self.getKind() == ElementKind.FIELD) {
364 owner = localContext.self;
365 apportionTypeAnnotations(tree,
366 owner::getRawTypeAttributes,
367 owner::setTypeAttributes,
368 sym::appendUniqueTypeAttributes);
369 }
370 }
371
372 //create the method declaration hoisting the lambda body
373 JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field),
374 sym.name,
375 make.QualIdent(lambdaType.getReturnType().tsym),
376 List.nil(),
377 localContext.syntheticParams,
378 lambdaType.getThrownTypes() == null ?
379 List.nil() :
380 make.Types(lambdaType.getThrownTypes()),
381 null,
382 null);
383 lambdaDecl.sym = sym;
384 lambdaDecl.type = lambdaType;
385
386 //translate lambda body
387 //As the lambda body is translated, all references to lambda locals,
388 //captured variables, enclosing members are adjusted accordingly
389 //to refer to the static method parameters (rather than i.e. accessing
390 //captured members directly).
391 lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl));
392
393 boolean dedupe = false;
394 if (deduplicateLambdas && !debugLinesOrVars && !localContext.isSerializable()) {
395 DedupedLambda dedupedLambda = new DedupedLambda(lambdaDecl.sym, lambdaDecl.body);
1651 clinits.put(csym, clinit);
1652 return clinit;
1653 }
1654
1655 /* if no clinit is found at Attr, then let's try at clinits.
1656 */
1657 clinit = (MethodSymbol)clinits.get(csym);
1658 if (clinit == null) {
1659 /* no luck, let's create a new one
1660 */
1661 clinit = makePrivateSyntheticMethod(STATIC,
1662 names.clinit,
1663 new MethodType(List.nil(), syms.voidType,
1664 List.nil(), syms.methodClass),
1665 csym);
1666 clinits.put(csym, clinit);
1667 }
1668 return clinit;
1669 } else {
1670 //get the first constructor and treat it as the instance init sym
1671 for (Symbol s : csym.members_field.getSymbolsByName(names.init)) {
1672 return s;
1673 }
1674 }
1675 Assert.error("init not found");
1676 return null;
1677 }
1678
1679 private JCTree directlyEnclosingLambda() {
1680 if (frameStack.isEmpty()) {
1681 return null;
1682 }
1683 List<Frame> frameStack2 = frameStack;
1684 while (frameStack2.nonEmpty()) {
1685 switch (frameStack2.head.tree.getTag()) {
1686 case CLASSDEF:
1687 case METHODDEF:
1688 return null;
1689 case LAMBDA:
1690 return frameStack2.head.tree;
1691 default:
1755 return null;
1756 }
1757
1758 private TranslationContext<?> context() {
1759 for (Frame frame : frameStack) {
1760 TranslationContext<?> context = contextMap.get(frame.tree);
1761 if (context != null) {
1762 return context;
1763 }
1764 }
1765 return null;
1766 }
1767
1768 /**
1769 * This is used to filter out those identifiers that needs to be adjusted
1770 * when translating away lambda expressions
1771 */
1772 private boolean lambdaIdentSymbolFilter(Symbol sym) {
1773 return (sym.kind == VAR || sym.kind == MTH)
1774 && !sym.isStatic()
1775 && sym.name != names.init;
1776 }
1777
1778 /**
1779 * This is used to filter out those select nodes that need to be adjusted
1780 * when translating away lambda expressions - at the moment, this is the
1781 * set of nodes that select `this' (qualified this)
1782 */
1783 private boolean lambdaFieldAccessFilter(JCFieldAccess fAccess) {
1784 return (context instanceof LambdaTranslationContext lambdaContext)
1785 && !fAccess.sym.isStatic()
1786 && fAccess.name == names._this
1787 && (fAccess.sym.owner.kind == TYP)
1788 && !lambdaContext.translatedSymbols.get(CAPTURED_OUTER_THIS).isEmpty();
1789 }
1790
1791 /**
1792 * This is used to filter out those new class expressions that need to
1793 * be qualified with an enclosing tree
1794 */
1795 private boolean lambdaNewClassFilter(TranslationContext<?> context, JCNewClass tree) {
1853 this.owner = owner(true);
1854 this.depth = frameStack.size() - 1;
1855 this.prev = context();
1856 ClassSymbol csym =
1857 types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.target, ABSTRACT | INTERFACE);
1858 this.bridges = types.functionalInterfaceBridges(csym);
1859 }
1860
1861 /** does this functional expression need to be created using alternate metafactory? */
1862 boolean needsAltMetafactory() {
1863 return tree.target.isIntersection() ||
1864 isSerializable() ||
1865 bridges.length() > 1;
1866 }
1867
1868 /** does this functional expression require serialization support? */
1869 boolean isSerializable() {
1870 if (forceSerializable) {
1871 return true;
1872 }
1873 return types.asSuper(tree.target, syms.serializableType.tsym) != null;
1874 }
1875
1876 /**
1877 * @return Name of the enclosing method to be folded into synthetic
1878 * method name
1879 */
1880 String enclosingMethodName() {
1881 return syntheticMethodNameComponent(owner.name);
1882 }
1883
1884 /**
1885 * @return Method name in a form that can be folded into a
1886 * component of a synthetic method name
1887 */
1888 String syntheticMethodNameComponent(Name name) {
1889 if (name == null) {
1890 return "null";
1891 }
1892 String methodName = name.toString();
1893 if (methodName.equals("<clinit>")) {
1894 methodName = "static";
1895 } else if (methodName.equals("<init>")) {
1896 methodName = "new";
1897 }
1898 return methodName;
1899 }
1900 }
1901
1902 /**
1903 * This class retains all the useful information about a lambda expression;
1904 * the contents of this class are filled by the LambdaAnalyzer visitor,
1905 * and the used by the main translation routines in order to adjust references
1906 * to captured locals/members, etc.
1907 */
1908 class LambdaTranslationContext extends TranslationContext<JCLambda> {
1909
1910 /** variable in the enclosing context to which this lambda is assigned */
1911 final Symbol self;
1912
1913 /** variable in the enclosing context to which this lambda is assigned */
1914 final Symbol assignedTo;
1915
1916 Map<LambdaSymbolKind, Map<Symbol, Symbol>> translatedSymbols;
2331 TypeVar tv = (TypeVar) t;
2332 return isIntersectionOrUnionType(tv.getUpperBound());
2333 }
2334 return false;
2335 }
2336
2337 /**
2338 * Does this reference need to be converted to a lambda
2339 * (i.e. var args need to be expanded or "super" is used)
2340 */
2341 final boolean needsConversionToLambda() {
2342 return interfaceParameterIsIntersectionOrUnionType() ||
2343 isSuper ||
2344 needsVarArgsConversion() ||
2345 isArrayOp() ||
2346 (!nestmateLambdas && isPrivateInOtherClass()) ||
2347 isProtectedInSuperClassOfEnclosingClassInOtherPackage(tree.sym, owner) ||
2348 !receiverAccessible() ||
2349 (tree.getMode() == ReferenceMode.NEW &&
2350 tree.kind != ReferenceKind.ARRAY_CTOR &&
2351 (tree.sym.owner.isDirectlyOrIndirectlyLocal() || tree.sym.owner.isInner()));
2352 }
2353
2354 Type generatedRefSig() {
2355 return types.erasure(tree.sym.type);
2356 }
2357
2358 Type bridgedRefSig() {
2359 return types.erasure(types.findDescriptorSymbol(tree.target.tsym).type);
2360 }
2361 }
2362 }
2363 // </editor-fold>
2364
2365 /*
2366 * These keys provide mappings for various translated lambda symbols
2367 * and the prevailing order must be maintained.
2368 */
2369 enum LambdaSymbolKind {
2370 PARAM, // original to translated lambda parameters
2371 LOCAL_VAR, // original to translated lambda locals
|
336 public void visitLambda(JCLambda tree) {
337 LambdaTranslationContext localContext = (LambdaTranslationContext)context;
338 MethodSymbol sym = localContext.translatedSym;
339 MethodType lambdaType = (MethodType) sym.type;
340
341 { /* Type annotation management: Based on where the lambda features, type annotations that
342 are interior to it, may at this point be attached to the enclosing method, or the first
343 constructor in the class, or in the enclosing class symbol or in the field whose
344 initializer is the lambda. In any event, gather up the annotations that belong to the
345 lambda and attach it to the implementation method.
346 */
347
348 Symbol owner = localContext.owner;
349 apportionTypeAnnotations(tree,
350 owner::getRawTypeAttributes,
351 owner::setTypeAttributes,
352 sym::setTypeAttributes);
353
354
355 boolean init;
356 // TODO - can <vnew> exist in this context?
357 if ((init = names.isInitOrVNew(owner.name)) || owner.name == names.clinit) {
358 owner = owner.owner;
359 apportionTypeAnnotations(tree,
360 init ? owner::getInitTypeAttributes : owner::getClassInitTypeAttributes,
361 init ? owner::setInitTypeAttributes : owner::setClassInitTypeAttributes,
362 sym::appendUniqueTypeAttributes);
363 }
364 if (localContext.self != null && localContext.self.getKind() == ElementKind.FIELD) {
365 owner = localContext.self;
366 apportionTypeAnnotations(tree,
367 owner::getRawTypeAttributes,
368 owner::setTypeAttributes,
369 sym::appendUniqueTypeAttributes);
370 }
371 }
372
373 //create the method declaration hoisting the lambda body
374 JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field),
375 sym.name,
376 make.QualIdent(lambdaType.getReturnType().tsym).setType(lambdaType.getReturnType()),
377 List.nil(),
378 localContext.syntheticParams,
379 lambdaType.getThrownTypes() == null ?
380 List.nil() :
381 make.Types(lambdaType.getThrownTypes()),
382 null,
383 null);
384 lambdaDecl.sym = sym;
385 lambdaDecl.type = lambdaType;
386
387 //translate lambda body
388 //As the lambda body is translated, all references to lambda locals,
389 //captured variables, enclosing members are adjusted accordingly
390 //to refer to the static method parameters (rather than i.e. accessing
391 //captured members directly).
392 lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl));
393
394 boolean dedupe = false;
395 if (deduplicateLambdas && !debugLinesOrVars && !localContext.isSerializable()) {
396 DedupedLambda dedupedLambda = new DedupedLambda(lambdaDecl.sym, lambdaDecl.body);
1652 clinits.put(csym, clinit);
1653 return clinit;
1654 }
1655
1656 /* if no clinit is found at Attr, then let's try at clinits.
1657 */
1658 clinit = (MethodSymbol)clinits.get(csym);
1659 if (clinit == null) {
1660 /* no luck, let's create a new one
1661 */
1662 clinit = makePrivateSyntheticMethod(STATIC,
1663 names.clinit,
1664 new MethodType(List.nil(), syms.voidType,
1665 List.nil(), syms.methodClass),
1666 csym);
1667 clinits.put(csym, clinit);
1668 }
1669 return clinit;
1670 } else {
1671 //get the first constructor and treat it as the instance init sym
1672 Name constructorName = csym.isConcreteValueClass() ? names.vnew : names.init;
1673 for (Symbol s : csym.members_field.getSymbolsByName(constructorName)) {
1674 return s;
1675 }
1676 }
1677 Assert.error("init not found");
1678 return null;
1679 }
1680
1681 private JCTree directlyEnclosingLambda() {
1682 if (frameStack.isEmpty()) {
1683 return null;
1684 }
1685 List<Frame> frameStack2 = frameStack;
1686 while (frameStack2.nonEmpty()) {
1687 switch (frameStack2.head.tree.getTag()) {
1688 case CLASSDEF:
1689 case METHODDEF:
1690 return null;
1691 case LAMBDA:
1692 return frameStack2.head.tree;
1693 default:
1757 return null;
1758 }
1759
1760 private TranslationContext<?> context() {
1761 for (Frame frame : frameStack) {
1762 TranslationContext<?> context = contextMap.get(frame.tree);
1763 if (context != null) {
1764 return context;
1765 }
1766 }
1767 return null;
1768 }
1769
1770 /**
1771 * This is used to filter out those identifiers that needs to be adjusted
1772 * when translating away lambda expressions
1773 */
1774 private boolean lambdaIdentSymbolFilter(Symbol sym) {
1775 return (sym.kind == VAR || sym.kind == MTH)
1776 && !sym.isStatic()
1777 && !names.isInitOrVNew(sym.name);
1778 }
1779
1780 /**
1781 * This is used to filter out those select nodes that need to be adjusted
1782 * when translating away lambda expressions - at the moment, this is the
1783 * set of nodes that select `this' (qualified this)
1784 */
1785 private boolean lambdaFieldAccessFilter(JCFieldAccess fAccess) {
1786 return (context instanceof LambdaTranslationContext lambdaContext)
1787 && !fAccess.sym.isStatic()
1788 && fAccess.name == names._this
1789 && (fAccess.sym.owner.kind == TYP)
1790 && !lambdaContext.translatedSymbols.get(CAPTURED_OUTER_THIS).isEmpty();
1791 }
1792
1793 /**
1794 * This is used to filter out those new class expressions that need to
1795 * be qualified with an enclosing tree
1796 */
1797 private boolean lambdaNewClassFilter(TranslationContext<?> context, JCNewClass tree) {
1855 this.owner = owner(true);
1856 this.depth = frameStack.size() - 1;
1857 this.prev = context();
1858 ClassSymbol csym =
1859 types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.target, ABSTRACT | INTERFACE);
1860 this.bridges = types.functionalInterfaceBridges(csym);
1861 }
1862
1863 /** does this functional expression need to be created using alternate metafactory? */
1864 boolean needsAltMetafactory() {
1865 return tree.target.isIntersection() ||
1866 isSerializable() ||
1867 bridges.length() > 1;
1868 }
1869
1870 /** does this functional expression require serialization support? */
1871 boolean isSerializable() {
1872 if (forceSerializable) {
1873 return true;
1874 }
1875 return types.asSuper(tree.target.referenceProjectionOrSelf(), syms.serializableType.tsym) != null;
1876 }
1877
1878 /**
1879 * @return Name of the enclosing method to be folded into synthetic
1880 * method name
1881 */
1882 String enclosingMethodName() {
1883 return syntheticMethodNameComponent(owner.name);
1884 }
1885
1886 /**
1887 * @return Method name in a form that can be folded into a
1888 * component of a synthetic method name
1889 */
1890 String syntheticMethodNameComponent(Name name) {
1891 if (name == null) {
1892 return "null";
1893 }
1894 String methodName = name.toString();
1895 if (methodName.equals("<clinit>")) {
1896 methodName = "static";
1897 } else if (methodName.equals("<init>")) {
1898 methodName = "new";
1899 } else if (methodName.equals("<vnew>")) {
1900 methodName = "vnew";
1901 }
1902 return methodName;
1903 }
1904 }
1905
1906 /**
1907 * This class retains all the useful information about a lambda expression;
1908 * the contents of this class are filled by the LambdaAnalyzer visitor,
1909 * and the used by the main translation routines in order to adjust references
1910 * to captured locals/members, etc.
1911 */
1912 class LambdaTranslationContext extends TranslationContext<JCLambda> {
1913
1914 /** variable in the enclosing context to which this lambda is assigned */
1915 final Symbol self;
1916
1917 /** variable in the enclosing context to which this lambda is assigned */
1918 final Symbol assignedTo;
1919
1920 Map<LambdaSymbolKind, Map<Symbol, Symbol>> translatedSymbols;
2335 TypeVar tv = (TypeVar) t;
2336 return isIntersectionOrUnionType(tv.getUpperBound());
2337 }
2338 return false;
2339 }
2340
2341 /**
2342 * Does this reference need to be converted to a lambda
2343 * (i.e. var args need to be expanded or "super" is used)
2344 */
2345 final boolean needsConversionToLambda() {
2346 return interfaceParameterIsIntersectionOrUnionType() ||
2347 isSuper ||
2348 needsVarArgsConversion() ||
2349 isArrayOp() ||
2350 (!nestmateLambdas && isPrivateInOtherClass()) ||
2351 isProtectedInSuperClassOfEnclosingClassInOtherPackage(tree.sym, owner) ||
2352 !receiverAccessible() ||
2353 (tree.getMode() == ReferenceMode.NEW &&
2354 tree.kind != ReferenceKind.ARRAY_CTOR &&
2355 (tree.sym.owner.isDirectlyOrIndirectlyLocal() || tree.sym.owner.isInner() || tree.sym.owner.isValueClass()));
2356 }
2357
2358 Type generatedRefSig() {
2359 return types.erasure(tree.sym.type);
2360 }
2361
2362 Type bridgedRefSig() {
2363 return types.erasure(types.findDescriptorSymbol(tree.target.tsym).type);
2364 }
2365 }
2366 }
2367 // </editor-fold>
2368
2369 /*
2370 * These keys provide mappings for various translated lambda symbols
2371 * and the prevailing order must be maintained.
2372 */
2373 enum LambdaSymbolKind {
2374 PARAM, // original to translated lambda parameters
2375 LOCAL_VAR, // original to translated lambda locals
|