< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java

Print this page
rev 51258 : imported patch switch
rev 51259 : imported patch switch.01


  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.comp;
  27 
  28 import java.util.*;
  29 import java.util.function.BiConsumer;

  30 
  31 import javax.lang.model.element.ElementKind;
  32 import javax.tools.JavaFileObject;
  33 
  34 import com.sun.source.tree.CaseTree.CaseKind;
  35 import com.sun.source.tree.IdentifierTree;
  36 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
  37 import com.sun.source.tree.MemberSelectTree;
  38 import com.sun.source.tree.TreeVisitor;
  39 import com.sun.source.util.SimpleTreeVisitor;
  40 import com.sun.tools.javac.code.*;
  41 import com.sun.tools.javac.code.Lint.LintCategory;
  42 import com.sun.tools.javac.code.Scope.WriteableScope;
  43 import com.sun.tools.javac.code.Source.Feature;
  44 import com.sun.tools.javac.code.Symbol.*;
  45 import com.sun.tools.javac.code.Type.*;
  46 import com.sun.tools.javac.code.TypeMetadata.Annotations;
  47 import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
  48 import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
  49 import com.sun.tools.javac.comp.Check.CheckContext;


 690     }
 691 
 692     WriteableScope copyScope(WriteableScope sc) {
 693         WriteableScope newScope = WriteableScope.create(sc.owner);
 694         List<Symbol> elemsList = List.nil();
 695         for (Symbol sym : sc.getSymbols()) {
 696             elemsList = elemsList.prepend(sym);
 697         }
 698         for (Symbol s : elemsList) {
 699             newScope.enter(s);
 700         }
 701         return newScope;
 702     }
 703 
 704     /** Derived visitor method: attribute an expression tree.
 705      */
 706     public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt) {
 707         return attribTree(tree, env, new ResultInfo(KindSelector.VAL, !pt.hasTag(ERROR) ? pt : Type.noType));
 708     }
 709 
 710     /** Derived visitor method: attribute an expression tree.
 711      */
 712     public Type attribExpr(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
 713         return attribTree(tree, env, resultInfo);
 714     }
 715 
 716     /** Derived visitor method: attribute an expression tree with
 717      *  no constraints on the computed type.
 718      */
 719     public Type attribExpr(JCTree tree, Env<AttrContext> env) {
 720         return attribTree(tree, env, unknownExprInfo);
 721     }
 722 
 723     /** Derived visitor method: attribute a type tree.
 724      */
 725     public Type attribType(JCTree tree, Env<AttrContext> env) {
 726         Type result = attribType(tree, env, Type.noType);
 727         return result;
 728     }
 729 
 730     /** Derived visitor method: attribute a type tree.
 731      */
 732     Type attribType(JCTree tree, Env<AttrContext> env, Type pt) {
 733         Type result = attribTree(tree, env, new ResultInfo(KindSelector.TYP, pt));
 734         return result;
 735     }


1407             attribStats(c.stats, caseEnv);
1408         });
1409         result = null;
1410     }
1411 
1412     public void visitSwitchExpression(JCSwitchExpression tree) {
1413         tree.polyKind = (pt().hasTag(NONE) && pt() != Type.recoveryType && pt() != Infer.anyPoly) ?
1414                 PolyKind.STANDALONE : PolyKind.POLY;
1415 
1416         if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
1417             //this means we are returning a poly conditional from void-compatible lambda expression
1418             resultInfo.checkContext.report(tree, diags.fragment(Fragments.SwitchExpressionTargetCantBeVoid));
1419             result = tree.type = types.createErrorType(resultInfo.pt);
1420             return;
1421         }
1422 
1423         ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
1424                 unknownExprInfo :
1425                 resultInfo.dup(switchExpressionContext(resultInfo.checkContext));
1426 

1427         ListBuffer<Type> caseTypes = new ListBuffer<>();
1428 
1429         handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> {
1430             caseEnv.info.breakResult = condInfo;
1431             attribStats(c.stats, caseEnv);
1432             new TreeScanner() {
1433                 @Override
1434                 public void visitBreak(JCBreak brk) {
1435                     if (brk.target == tree)

1436                         caseTypes.append(brk.value != null ? brk.value.type : syms.errType);

1437                     super.visitBreak(brk);
1438                 }
1439 
1440                 @Override public void visitClassDef(JCClassDecl tree) {}
1441                 @Override public void visitLambda(JCLambda tree) {}
1442                 @Override public void visitMethodDef(JCMethodDecl tree) {}
1443             }.scan(c.stats);
1444         });
1445 
1446         Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, caseTypes.toList()) : pt();





1447 
1448         result = tree.type = check(tree, owntype, KindSelector.VAL, resultInfo);
1449     }
1450     //where:
1451         CheckContext switchExpressionContext(CheckContext checkContext) {
1452             return new Check.NestedCheckContext(checkContext) {
1453                 //this will use enclosing check context to check compatibility of
1454                 //subexpression against target type; if we are in a method check context,
1455                 //depending on whether boxing is allowed, we could have incompatibilities
1456                 @Override
1457                 public void report(DiagnosticPosition pos, JCDiagnostic details) {
1458                     enclosingContext.report(pos, diags.fragment(Fragments.IncompatibleTypeInSwitchExpression(details)));
1459                 }
1460             };
1461         }
1462 
1463     private void handleSwitch(JCTree switchTree,
1464                               JCExpression selector,
1465                               List<JCCase> cases,
1466                               BiConsumer<JCCase, Env<AttrContext>> attribCase) {


1672 
1673         tree.polyKind = (!allowPoly ||
1674                 pt().hasTag(NONE) && pt() != Type.recoveryType && pt() != Infer.anyPoly ||
1675                 isBooleanOrNumeric(env, tree)) ?
1676                 PolyKind.STANDALONE : PolyKind.POLY;
1677 
1678         if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
1679             //this means we are returning a poly conditional from void-compatible lambda expression
1680             resultInfo.checkContext.report(tree, diags.fragment(Fragments.ConditionalTargetCantBeVoid));
1681             result = tree.type = types.createErrorType(resultInfo.pt);
1682             return;
1683         }
1684 
1685         ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
1686                 unknownExprInfo :
1687                 resultInfo.dup(conditionalContext(resultInfo.checkContext));
1688 
1689         Type truetype = attribTree(tree.truepart, env, condInfo);
1690         Type falsetype = attribTree(tree.falsepart, env, condInfo);
1691 
1692         Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, List.of(truetype, falsetype)) : pt();


1693         if (condtype.constValue() != null &&
1694                 truetype.constValue() != null &&
1695                 falsetype.constValue() != null &&
1696                 !owntype.hasTag(NONE)) {
1697             //constant folding
1698             owntype = cfolder.coerce(condtype.isTrue() ? truetype : falsetype, owntype);
1699         }
1700         result = check(tree, owntype, KindSelector.VAL, resultInfo);
1701     }
1702     //where
1703         private boolean isBooleanOrNumeric(Env<AttrContext> env, JCExpression tree) {
1704             switch (tree.getTag()) {
1705                 case LITERAL: return ((JCLiteral)tree).typetag.isSubRangeOf(DOUBLE) ||
1706                               ((JCLiteral)tree).typetag == BOOLEAN ||
1707                               ((JCLiteral)tree).typetag == BOT;
1708                 case LAMBDA: case REFERENCE: return false;
1709                 case PARENS: return isBooleanOrNumeric(env, ((JCParens)tree).expr);
1710                 case CONDEXPR:
1711                     JCConditional condTree = (JCConditional)tree;
1712                     return isBooleanOrNumeric(env, condTree.truepart) &&


1753                 //this will use enclosing check context to check compatibility of
1754                 //subexpression against target type; if we are in a method check context,
1755                 //depending on whether boxing is allowed, we could have incompatibilities
1756                 @Override
1757                 public void report(DiagnosticPosition pos, JCDiagnostic details) {
1758                     enclosingContext.report(pos, diags.fragment(Fragments.IncompatibleTypeInConditional(details)));
1759                 }
1760             };
1761         }
1762 
1763         /** Compute the type of a conditional expression, after
1764          *  checking that it exists.  See JLS 15.25. Does not take into
1765          *  account the special case where condition and both arms
1766          *  are constants.
1767          *
1768          *  @param pos      The source position to be used for error
1769          *                  diagnostics.
1770          *  @param thentype The type of the expression's then-part.
1771          *  @param elsetype The type of the expression's else-part.
1772          */
1773         Type condType(DiagnosticPosition pos,
1774                       List<Type> condTypes) {
1775             if (condTypes.isEmpty()) {
1776                 return syms.objectType; //TODO: how to handle?
1777             }
1778             if (condTypes.size() == 1) {
1779                 return condTypes.head;
1780             }
1781             Type first = condTypes.head;
1782             // If same type, that is the result
1783             if (condTypes.tail.stream().allMatch(t -> types.isSameType(first, t)))
1784                 return first.baseType();
1785 
1786             List<Type> unboxedTypes = condTypes.stream()
1787                                                .map(t -> t.isPrimitive() ? t : types.unboxedType(t))
1788                                                .collect(List.collector());
1789 
1790             // Otherwise, if both arms can be converted to a numeric
1791             // type, return the least numeric type that fits both arms
1792             // (i.e. return larger of the two, or return int if one
1793             // arm is short, the other is char).
1794             if (unboxedTypes.stream().allMatch(t -> t.isPrimitive())) {


1804                 }
1805 
1806                 for (TypeTag tag : primitiveTags) {
1807                     Type candidate = syms.typeOfTag[tag.ordinal()];
1808                     if (unboxedTypes.stream().allMatch(t -> types.isSubtype(t, candidate))) {
1809                         return candidate;
1810                     }
1811                 }
1812             }
1813 
1814             // Those were all the cases that could result in a primitive
1815             condTypes = condTypes.stream()
1816                                  .map(t -> t.isPrimitive() ? types.boxedClass(t).type : t)
1817                                  .collect(List.collector());
1818 
1819             for (Type type : condTypes) {
1820                 if (condTypes.stream().filter(t -> t != type).allMatch(t -> types.isAssignable(t, type)))
1821                     return type.baseType();
1822             }
1823 
1824             if (condTypes.stream().anyMatch(t -> t.hasTag(VOID))) {
1825                 //XXX:
1826                 log.error(pos,
1827                           Errors.NeitherConditionalSubtype(condTypes.head,
1828                                                            condTypes.tail.head));
1829                 return condTypes.head.baseType();
1830             }
1831 
1832             // both are known to be reference types.  The result is
1833             // lub(thentype,elsetype). This cannot fail, as it will
1834             // always be possible to infer "Object" if nothing better.
1835             return types.lub(condTypes.stream().map(t -> t.baseType()).collect(List.collector()));
1836         }
1837 
1838     final static TypeTag[] primitiveTags = new TypeTag[]{
1839         BYTE,
1840         CHAR,
1841         SHORT,
1842         INT,
1843         LONG,
1844         FLOAT,
1845         DOUBLE,
1846         BOOLEAN,
1847     };
1848 
1849     public void visitIf(JCIf tree) {
1850         attribExpr(tree.cond, env, syms.booleanType);




  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.comp;
  27 
  28 import java.util.*;
  29 import java.util.function.BiConsumer;
  30 import java.util.stream.Collectors;
  31 
  32 import javax.lang.model.element.ElementKind;
  33 import javax.tools.JavaFileObject;
  34 
  35 import com.sun.source.tree.CaseTree.CaseKind;
  36 import com.sun.source.tree.IdentifierTree;
  37 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
  38 import com.sun.source.tree.MemberSelectTree;
  39 import com.sun.source.tree.TreeVisitor;
  40 import com.sun.source.util.SimpleTreeVisitor;
  41 import com.sun.tools.javac.code.*;
  42 import com.sun.tools.javac.code.Lint.LintCategory;
  43 import com.sun.tools.javac.code.Scope.WriteableScope;
  44 import com.sun.tools.javac.code.Source.Feature;
  45 import com.sun.tools.javac.code.Symbol.*;
  46 import com.sun.tools.javac.code.Type.*;
  47 import com.sun.tools.javac.code.TypeMetadata.Annotations;
  48 import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
  49 import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
  50 import com.sun.tools.javac.comp.Check.CheckContext;


 691     }
 692 
 693     WriteableScope copyScope(WriteableScope sc) {
 694         WriteableScope newScope = WriteableScope.create(sc.owner);
 695         List<Symbol> elemsList = List.nil();
 696         for (Symbol sym : sc.getSymbols()) {
 697             elemsList = elemsList.prepend(sym);
 698         }
 699         for (Symbol s : elemsList) {
 700             newScope.enter(s);
 701         }
 702         return newScope;
 703     }
 704 
 705     /** Derived visitor method: attribute an expression tree.
 706      */
 707     public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt) {
 708         return attribTree(tree, env, new ResultInfo(KindSelector.VAL, !pt.hasTag(ERROR) ? pt : Type.noType));
 709     }
 710 






 711     /** Derived visitor method: attribute an expression tree with
 712      *  no constraints on the computed type.
 713      */
 714     public Type attribExpr(JCTree tree, Env<AttrContext> env) {
 715         return attribTree(tree, env, unknownExprInfo);
 716     }
 717 
 718     /** Derived visitor method: attribute a type tree.
 719      */
 720     public Type attribType(JCTree tree, Env<AttrContext> env) {
 721         Type result = attribType(tree, env, Type.noType);
 722         return result;
 723     }
 724 
 725     /** Derived visitor method: attribute a type tree.
 726      */
 727     Type attribType(JCTree tree, Env<AttrContext> env, Type pt) {
 728         Type result = attribTree(tree, env, new ResultInfo(KindSelector.TYP, pt));
 729         return result;
 730     }


1402             attribStats(c.stats, caseEnv);
1403         });
1404         result = null;
1405     }
1406 
1407     public void visitSwitchExpression(JCSwitchExpression tree) {
1408         tree.polyKind = (pt().hasTag(NONE) && pt() != Type.recoveryType && pt() != Infer.anyPoly) ?
1409                 PolyKind.STANDALONE : PolyKind.POLY;
1410 
1411         if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
1412             //this means we are returning a poly conditional from void-compatible lambda expression
1413             resultInfo.checkContext.report(tree, diags.fragment(Fragments.SwitchExpressionTargetCantBeVoid));
1414             result = tree.type = types.createErrorType(resultInfo.pt);
1415             return;
1416         }
1417 
1418         ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
1419                 unknownExprInfo :
1420                 resultInfo.dup(switchExpressionContext(resultInfo.checkContext));
1421 
1422         ListBuffer<DiagnosticPosition> caseTypePositions = new ListBuffer<>();
1423         ListBuffer<Type> caseTypes = new ListBuffer<>();
1424 
1425         handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> {
1426             caseEnv.info.breakResult = condInfo;
1427             attribStats(c.stats, caseEnv);
1428             new TreeScanner() {
1429                 @Override
1430                 public void visitBreak(JCBreak brk) {
1431                     if (brk.target == tree) {
1432                         caseTypePositions.append(brk.value != null ? brk.value.pos() : brk.pos());
1433                         caseTypes.append(brk.value != null ? brk.value.type : syms.errType);
1434                     }
1435                     super.visitBreak(brk);
1436                 }
1437 
1438                 @Override public void visitClassDef(JCClassDecl tree) {}
1439                 @Override public void visitLambda(JCLambda tree) {}

1440             }.scan(c.stats);
1441         });
1442 
1443         if (tree.cases.isEmpty()) {
1444             log.error(tree.pos(),
1445                       Errors.SwitchExpressionEmpty);
1446         }
1447 
1448         Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(caseTypePositions.toList(), caseTypes.toList()) : pt();
1449 
1450         result = tree.type = check(tree, owntype, KindSelector.VAL, resultInfo);
1451     }
1452     //where:
1453         CheckContext switchExpressionContext(CheckContext checkContext) {
1454             return new Check.NestedCheckContext(checkContext) {
1455                 //this will use enclosing check context to check compatibility of
1456                 //subexpression against target type; if we are in a method check context,
1457                 //depending on whether boxing is allowed, we could have incompatibilities
1458                 @Override
1459                 public void report(DiagnosticPosition pos, JCDiagnostic details) {
1460                     enclosingContext.report(pos, diags.fragment(Fragments.IncompatibleTypeInSwitchExpression(details)));
1461                 }
1462             };
1463         }
1464 
1465     private void handleSwitch(JCTree switchTree,
1466                               JCExpression selector,
1467                               List<JCCase> cases,
1468                               BiConsumer<JCCase, Env<AttrContext>> attribCase) {


1674 
1675         tree.polyKind = (!allowPoly ||
1676                 pt().hasTag(NONE) && pt() != Type.recoveryType && pt() != Infer.anyPoly ||
1677                 isBooleanOrNumeric(env, tree)) ?
1678                 PolyKind.STANDALONE : PolyKind.POLY;
1679 
1680         if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
1681             //this means we are returning a poly conditional from void-compatible lambda expression
1682             resultInfo.checkContext.report(tree, diags.fragment(Fragments.ConditionalTargetCantBeVoid));
1683             result = tree.type = types.createErrorType(resultInfo.pt);
1684             return;
1685         }
1686 
1687         ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
1688                 unknownExprInfo :
1689                 resultInfo.dup(conditionalContext(resultInfo.checkContext));
1690 
1691         Type truetype = attribTree(tree.truepart, env, condInfo);
1692         Type falsetype = attribTree(tree.falsepart, env, condInfo);
1693 
1694         Type owntype = (tree.polyKind == PolyKind.STANDALONE) ?
1695                 condType(List.of(tree.truepart.pos(), tree.falsepart.pos()),
1696                          List.of(truetype, falsetype)) : pt();
1697         if (condtype.constValue() != null &&
1698                 truetype.constValue() != null &&
1699                 falsetype.constValue() != null &&
1700                 !owntype.hasTag(NONE)) {
1701             //constant folding
1702             owntype = cfolder.coerce(condtype.isTrue() ? truetype : falsetype, owntype);
1703         }
1704         result = check(tree, owntype, KindSelector.VAL, resultInfo);
1705     }
1706     //where
1707         private boolean isBooleanOrNumeric(Env<AttrContext> env, JCExpression tree) {
1708             switch (tree.getTag()) {
1709                 case LITERAL: return ((JCLiteral)tree).typetag.isSubRangeOf(DOUBLE) ||
1710                               ((JCLiteral)tree).typetag == BOOLEAN ||
1711                               ((JCLiteral)tree).typetag == BOT;
1712                 case LAMBDA: case REFERENCE: return false;
1713                 case PARENS: return isBooleanOrNumeric(env, ((JCParens)tree).expr);
1714                 case CONDEXPR:
1715                     JCConditional condTree = (JCConditional)tree;
1716                     return isBooleanOrNumeric(env, condTree.truepart) &&


1757                 //this will use enclosing check context to check compatibility of
1758                 //subexpression against target type; if we are in a method check context,
1759                 //depending on whether boxing is allowed, we could have incompatibilities
1760                 @Override
1761                 public void report(DiagnosticPosition pos, JCDiagnostic details) {
1762                     enclosingContext.report(pos, diags.fragment(Fragments.IncompatibleTypeInConditional(details)));
1763                 }
1764             };
1765         }
1766 
1767         /** Compute the type of a conditional expression, after
1768          *  checking that it exists.  See JLS 15.25. Does not take into
1769          *  account the special case where condition and both arms
1770          *  are constants.
1771          *
1772          *  @param pos      The source position to be used for error
1773          *                  diagnostics.
1774          *  @param thentype The type of the expression's then-part.
1775          *  @param elsetype The type of the expression's else-part.
1776          */
1777         Type condType(List<DiagnosticPosition> positions, List<Type> condTypes) {

1778             if (condTypes.isEmpty()) {
1779                 return syms.objectType; //TODO: how to handle?
1780             }
1781             if (condTypes.size() == 1) {
1782                 return condTypes.head;
1783             }
1784             Type first = condTypes.head;
1785             // If same type, that is the result
1786             if (condTypes.tail.stream().allMatch(t -> types.isSameType(first, t)))
1787                 return first.baseType();
1788 
1789             List<Type> unboxedTypes = condTypes.stream()
1790                                                .map(t -> t.isPrimitive() ? t : types.unboxedType(t))
1791                                                .collect(List.collector());
1792 
1793             // Otherwise, if both arms can be converted to a numeric
1794             // type, return the least numeric type that fits both arms
1795             // (i.e. return larger of the two, or return int if one
1796             // arm is short, the other is char).
1797             if (unboxedTypes.stream().allMatch(t -> t.isPrimitive())) {


1807                 }
1808 
1809                 for (TypeTag tag : primitiveTags) {
1810                     Type candidate = syms.typeOfTag[tag.ordinal()];
1811                     if (unboxedTypes.stream().allMatch(t -> types.isSubtype(t, candidate))) {
1812                         return candidate;
1813                     }
1814                 }
1815             }
1816 
1817             // Those were all the cases that could result in a primitive
1818             condTypes = condTypes.stream()
1819                                  .map(t -> t.isPrimitive() ? types.boxedClass(t).type : t)
1820                                  .collect(List.collector());
1821 
1822             for (Type type : condTypes) {
1823                 if (condTypes.stream().filter(t -> t != type).allMatch(t -> types.isAssignable(t, type)))
1824                     return type.baseType();
1825             }
1826 
1827             Iterator<DiagnosticPosition> posIt = positions.iterator();
1828 
1829             condTypes = condTypes.stream()
1830                                  .map(t -> chk.checkNonVoid(posIt.next(), t))
1831                                  .collect(List.collector());


1832 
1833             // both are known to be reference types.  The result is
1834             // lub(thentype,elsetype). This cannot fail, as it will
1835             // always be possible to infer "Object" if nothing better.
1836             return types.lub(condTypes.stream().map(t -> t.baseType()).collect(List.collector()));
1837         }
1838 
1839     final static TypeTag[] primitiveTags = new TypeTag[]{
1840         BYTE,
1841         CHAR,
1842         SHORT,
1843         INT,
1844         LONG,
1845         FLOAT,
1846         DOUBLE,
1847         BOOLEAN,
1848     };
1849 
1850     public void visitIf(JCIf tree) {
1851         attribExpr(tree.cond, env, syms.booleanType);


< prev index next >