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