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);
1644 clinits.put(csym, clinit);
1645 return clinit;
1646 }
1647
1648 /* if no clinit is found at Attr, then let's try at clinits.
1649 */
1650 clinit = (MethodSymbol)clinits.get(csym);
1651 if (clinit == null) {
1652 /* no luck, let's create a new one
1653 */
1654 clinit = makePrivateSyntheticMethod(STATIC,
1655 names.clinit,
1656 new MethodType(List.nil(), syms.voidType,
1657 List.nil(), syms.methodClass),
1658 csym);
1659 clinits.put(csym, clinit);
1660 }
1661 return clinit;
1662 } else {
1663 //get the first constructor and treat it as the instance init sym
1664 for (Symbol s : csym.members_field.getSymbolsByName(names.init)) {
1665 return s;
1666 }
1667 }
1668 Assert.error("init not found");
1669 return null;
1670 }
1671
1672 private JCTree directlyEnclosingLambda() {
1673 if (frameStack.isEmpty()) {
1674 return null;
1675 }
1676 List<Frame> frameStack2 = frameStack;
1677 while (frameStack2.nonEmpty()) {
1678 switch (frameStack2.head.tree.getTag()) {
1679 case CLASSDEF:
1680 case METHODDEF:
1681 return null;
1682 case LAMBDA:
1683 return frameStack2.head.tree;
1684 default:
1748 return null;
1749 }
1750
1751 private TranslationContext<?> context() {
1752 for (Frame frame : frameStack) {
1753 TranslationContext<?> context = contextMap.get(frame.tree);
1754 if (context != null) {
1755 return context;
1756 }
1757 }
1758 return null;
1759 }
1760
1761 /**
1762 * This is used to filter out those identifiers that needs to be adjusted
1763 * when translating away lambda expressions
1764 */
1765 private boolean lambdaIdentSymbolFilter(Symbol sym) {
1766 return (sym.kind == VAR || sym.kind == MTH)
1767 && !sym.isStatic()
1768 && sym.name != names.init;
1769 }
1770
1771 /**
1772 * This is used to filter out those select nodes that need to be adjusted
1773 * when translating away lambda expressions - at the moment, this is the
1774 * set of nodes that select `this' (qualified this)
1775 */
1776 private boolean lambdaFieldAccessFilter(JCFieldAccess fAccess) {
1777 return (context instanceof LambdaTranslationContext lambdaContext)
1778 && !fAccess.sym.isStatic()
1779 && fAccess.name == names._this
1780 && (fAccess.sym.owner.kind == TYP)
1781 && !lambdaContext.translatedSymbols.get(CAPTURED_OUTER_THIS).isEmpty();
1782 }
1783
1784 /**
1785 * This is used to filter out those new class expressions that need to
1786 * be qualified with an enclosing tree
1787 */
1788 private boolean lambdaNewClassFilter(TranslationContext<?> context, JCNewClass tree) {
1846 this.owner = owner(true);
1847 this.depth = frameStack.size() - 1;
1848 this.prev = context();
1849 ClassSymbol csym =
1850 types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.target, ABSTRACT | INTERFACE);
1851 this.bridges = types.functionalInterfaceBridges(csym);
1852 }
1853
1854 /** does this functional expression need to be created using alternate metafactory? */
1855 boolean needsAltMetafactory() {
1856 return tree.target.isIntersection() ||
1857 isSerializable() ||
1858 bridges.length() > 1;
1859 }
1860
1861 /** does this functional expression require serialization support? */
1862 boolean isSerializable() {
1863 if (forceSerializable) {
1864 return true;
1865 }
1866 return types.asSuper(tree.target, syms.serializableType.tsym) != null;
1867 }
1868
1869 /**
1870 * @return Name of the enclosing method to be folded into synthetic
1871 * method name
1872 */
1873 String enclosingMethodName() {
1874 return syntheticMethodNameComponent(owner.name);
1875 }
1876
1877 /**
1878 * @return Method name in a form that can be folded into a
1879 * component of a synthetic method name
1880 */
1881 String syntheticMethodNameComponent(Name name) {
1882 if (name == null) {
1883 return "null";
1884 }
1885 String methodName = name.toString();
1886 if (methodName.equals("<clinit>")) {
1887 methodName = "static";
1888 } else if (methodName.equals("<init>")) {
1889 methodName = "new";
1890 }
1891 return methodName;
1892 }
1893 }
1894
1895 /**
1896 * This class retains all the useful information about a lambda expression;
1897 * the contents of this class are filled by the LambdaAnalyzer visitor,
1898 * and the used by the main translation routines in order to adjust references
1899 * to captured locals/members, etc.
1900 */
1901 class LambdaTranslationContext extends TranslationContext<JCLambda> {
1902
1903 /** variable in the enclosing context to which this lambda is assigned */
1904 final Symbol self;
1905
1906 /** variable in the enclosing context to which this lambda is assigned */
1907 final Symbol assignedTo;
1908
1909 Map<LambdaSymbolKind, Map<Symbol, Symbol>> translatedSymbols;
2324 TypeVar tv = (TypeVar) t;
2325 return isIntersectionOrUnionType(tv.getUpperBound());
2326 }
2327 return false;
2328 }
2329
2330 /**
2331 * Does this reference need to be converted to a lambda
2332 * (i.e. var args need to be expanded or "super" is used)
2333 */
2334 final boolean needsConversionToLambda() {
2335 return interfaceParameterIsIntersectionOrUnionType() ||
2336 isSuper ||
2337 needsVarArgsConversion() ||
2338 isArrayOp() ||
2339 (!nestmateLambdas && isPrivateInOtherClass()) ||
2340 isProtectedInSuperClassOfEnclosingClassInOtherPackage(tree.sym, owner) ||
2341 !receiverAccessible() ||
2342 (tree.getMode() == ReferenceMode.NEW &&
2343 tree.kind != ReferenceKind.ARRAY_CTOR &&
2344 (tree.sym.owner.isDirectlyOrIndirectlyLocal() || tree.sym.owner.isInner()));
2345 }
2346
2347 Type generatedRefSig() {
2348 return types.erasure(tree.sym.type);
2349 }
2350
2351 Type bridgedRefSig() {
2352 return types.erasure(types.findDescriptorSymbol(tree.target.tsym).type);
2353 }
2354 }
2355 }
2356 // </editor-fold>
2357
2358 /*
2359 * These keys provide mappings for various translated lambda symbols
2360 * and the prevailing order must be maintained.
2361 */
2362 enum LambdaSymbolKind {
2363 PARAM, // original to translated lambda parameters
2364 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);
1645 clinits.put(csym, clinit);
1646 return clinit;
1647 }
1648
1649 /* if no clinit is found at Attr, then let's try at clinits.
1650 */
1651 clinit = (MethodSymbol)clinits.get(csym);
1652 if (clinit == null) {
1653 /* no luck, let's create a new one
1654 */
1655 clinit = makePrivateSyntheticMethod(STATIC,
1656 names.clinit,
1657 new MethodType(List.nil(), syms.voidType,
1658 List.nil(), syms.methodClass),
1659 csym);
1660 clinits.put(csym, clinit);
1661 }
1662 return clinit;
1663 } else {
1664 //get the first constructor and treat it as the instance init sym
1665 Name constructorName = csym.isConcreteValueClass() ? names.vnew : names.init;
1666 for (Symbol s : csym.members_field.getSymbolsByName(constructorName)) {
1667 return s;
1668 }
1669 }
1670 Assert.error("init not found");
1671 return null;
1672 }
1673
1674 private JCTree directlyEnclosingLambda() {
1675 if (frameStack.isEmpty()) {
1676 return null;
1677 }
1678 List<Frame> frameStack2 = frameStack;
1679 while (frameStack2.nonEmpty()) {
1680 switch (frameStack2.head.tree.getTag()) {
1681 case CLASSDEF:
1682 case METHODDEF:
1683 return null;
1684 case LAMBDA:
1685 return frameStack2.head.tree;
1686 default:
1750 return null;
1751 }
1752
1753 private TranslationContext<?> context() {
1754 for (Frame frame : frameStack) {
1755 TranslationContext<?> context = contextMap.get(frame.tree);
1756 if (context != null) {
1757 return context;
1758 }
1759 }
1760 return null;
1761 }
1762
1763 /**
1764 * This is used to filter out those identifiers that needs to be adjusted
1765 * when translating away lambda expressions
1766 */
1767 private boolean lambdaIdentSymbolFilter(Symbol sym) {
1768 return (sym.kind == VAR || sym.kind == MTH)
1769 && !sym.isStatic()
1770 && !names.isInitOrVNew(sym.name);
1771 }
1772
1773 /**
1774 * This is used to filter out those select nodes that need to be adjusted
1775 * when translating away lambda expressions - at the moment, this is the
1776 * set of nodes that select `this' (qualified this)
1777 */
1778 private boolean lambdaFieldAccessFilter(JCFieldAccess fAccess) {
1779 return (context instanceof LambdaTranslationContext lambdaContext)
1780 && !fAccess.sym.isStatic()
1781 && fAccess.name == names._this
1782 && (fAccess.sym.owner.kind == TYP)
1783 && !lambdaContext.translatedSymbols.get(CAPTURED_OUTER_THIS).isEmpty();
1784 }
1785
1786 /**
1787 * This is used to filter out those new class expressions that need to
1788 * be qualified with an enclosing tree
1789 */
1790 private boolean lambdaNewClassFilter(TranslationContext<?> context, JCNewClass tree) {
1848 this.owner = owner(true);
1849 this.depth = frameStack.size() - 1;
1850 this.prev = context();
1851 ClassSymbol csym =
1852 types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.target, ABSTRACT | INTERFACE);
1853 this.bridges = types.functionalInterfaceBridges(csym);
1854 }
1855
1856 /** does this functional expression need to be created using alternate metafactory? */
1857 boolean needsAltMetafactory() {
1858 return tree.target.isIntersection() ||
1859 isSerializable() ||
1860 bridges.length() > 1;
1861 }
1862
1863 /** does this functional expression require serialization support? */
1864 boolean isSerializable() {
1865 if (forceSerializable) {
1866 return true;
1867 }
1868 return types.asSuper(tree.target.referenceProjectionOrSelf(), syms.serializableType.tsym) != null;
1869 }
1870
1871 /**
1872 * @return Name of the enclosing method to be folded into synthetic
1873 * method name
1874 */
1875 String enclosingMethodName() {
1876 return syntheticMethodNameComponent(owner.name);
1877 }
1878
1879 /**
1880 * @return Method name in a form that can be folded into a
1881 * component of a synthetic method name
1882 */
1883 String syntheticMethodNameComponent(Name name) {
1884 if (name == null) {
1885 return "null";
1886 }
1887 String methodName = name.toString();
1888 if (methodName.equals("<clinit>")) {
1889 methodName = "static";
1890 } else if (methodName.equals("<init>")) {
1891 methodName = "new";
1892 } else if (methodName.equals("<vnew>")) {
1893 methodName = "vnew";
1894 }
1895 return methodName;
1896 }
1897 }
1898
1899 /**
1900 * This class retains all the useful information about a lambda expression;
1901 * the contents of this class are filled by the LambdaAnalyzer visitor,
1902 * and the used by the main translation routines in order to adjust references
1903 * to captured locals/members, etc.
1904 */
1905 class LambdaTranslationContext extends TranslationContext<JCLambda> {
1906
1907 /** variable in the enclosing context to which this lambda is assigned */
1908 final Symbol self;
1909
1910 /** variable in the enclosing context to which this lambda is assigned */
1911 final Symbol assignedTo;
1912
1913 Map<LambdaSymbolKind, Map<Symbol, Symbol>> translatedSymbols;
2328 TypeVar tv = (TypeVar) t;
2329 return isIntersectionOrUnionType(tv.getUpperBound());
2330 }
2331 return false;
2332 }
2333
2334 /**
2335 * Does this reference need to be converted to a lambda
2336 * (i.e. var args need to be expanded or "super" is used)
2337 */
2338 final boolean needsConversionToLambda() {
2339 return interfaceParameterIsIntersectionOrUnionType() ||
2340 isSuper ||
2341 needsVarArgsConversion() ||
2342 isArrayOp() ||
2343 (!nestmateLambdas && isPrivateInOtherClass()) ||
2344 isProtectedInSuperClassOfEnclosingClassInOtherPackage(tree.sym, owner) ||
2345 !receiverAccessible() ||
2346 (tree.getMode() == ReferenceMode.NEW &&
2347 tree.kind != ReferenceKind.ARRAY_CTOR &&
2348 (tree.sym.owner.isDirectlyOrIndirectlyLocal() || tree.sym.owner.isInner() || tree.sym.owner.isValueClass()));
2349 }
2350
2351 Type generatedRefSig() {
2352 return types.erasure(tree.sym.type);
2353 }
2354
2355 Type bridgedRefSig() {
2356 return types.erasure(types.findDescriptorSymbol(tree.target.tsym).type);
2357 }
2358 }
2359 }
2360 // </editor-fold>
2361
2362 /*
2363 * These keys provide mappings for various translated lambda symbols
2364 * and the prevailing order must be maintained.
2365 */
2366 enum LambdaSymbolKind {
2367 PARAM, // original to translated lambda parameters
2368 LOCAL_VAR, // original to translated lambda locals
|