< prev index next >

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

Print this page

        

*** 47,56 **** --- 47,57 ---- import com.sun.tools.javac.code.TypeMetadata.Annotations; import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError; import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext; import com.sun.tools.javac.comp.Check.CheckContext; import com.sun.tools.javac.comp.DeferredAttr.AttrMode; + import com.sun.tools.javac.comp.MatchBindingsComputer.BindingSymbol; import com.sun.tools.javac.jvm.*; import static com.sun.tools.javac.resources.CompilerProperties.Fragments.Diamond; import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArg; import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArgs; import com.sun.tools.javac.resources.CompilerProperties.Errors;
*** 73,82 **** --- 74,85 ---- import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.code.TypeTag.WILDCARD; import com.sun.tools.javac.comp.Analyzer.AnalyzerMode; + import com.sun.tools.javac.comp.MatchBindingsComputer.BindingSymbol; + import com.sun.tools.javac.tree.JCTree.JCBreak; import static com.sun.tools.javac.tree.JCTree.Tag.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; import com.sun.tools.javac.util.Log.DeferredDiagnosticHandler; import com.sun.tools.javac.util.Log.DiscardDiagnosticHandler;
*** 118,127 **** --- 121,131 ---- final DeferredLintHandler deferredLintHandler; final TypeEnvs typeEnvs; final Dependencies dependencies; final Annotate annotate; final ArgumentAttr argumentAttr; + final MatchBindingsComputer matchBindingsComputer; public static Attr instance(Context context) { Attr instance = context.get(attrKey); if (instance == null) instance = new Attr(context);
*** 153,162 **** --- 157,167 ---- typeAnnotations = TypeAnnotations.instance(context); deferredLintHandler = DeferredLintHandler.instance(context); typeEnvs = TypeEnvs.instance(context); dependencies = Dependencies.instance(context); argumentAttr = ArgumentAttr.instance(context); + matchBindingsComputer = MatchBindingsComputer.instance(context); Options options = Options.instance(context); Source source = Source.instance(context); allowPoly = Feature.POLY.allowedInSource(source);
*** 293,302 **** --- 298,309 ---- !((base == null || TreeInfo.isThisQualifier(base)) && isAssignableAsBlankFinal(v, env)))) { if (v.isResourceVariable()) { //TWR resource log.error(pos, Errors.TryResourceMayNotBeAssigned(v)); + } else if ((v.flags() & MATCH_BINDING) != 0) { + log.error(pos, Errors.PatternBindingMayNotBeAssigned(v)); } else { log.error(pos, Errors.CantAssignValToFinalVar(v)); } } }
*** 1317,1348 **** } public void visitDoLoop(JCDoWhileLoop tree) { attribStat(tree.body, env.dup(tree)); attribExpr(tree.cond, env, syms.booleanType); result = null; } public void visitWhileLoop(JCWhileLoop tree) { attribExpr(tree.cond, env, syms.booleanType); ! attribStat(tree.body, env.dup(tree)); result = null; } public void visitForLoop(JCForLoop tree) { Env<AttrContext> loopEnv = env.dup(env.tree, env.info.dup(env.info.scope.dup())); try { attribStats(tree.init, loopEnv); ! if (tree.cond != null) attribExpr(tree.cond, loopEnv, syms.booleanType); ! loopEnv.tree = tree; // before, we were not in loop! ! attribStats(tree.step, loopEnv); ! attribStat(tree.body, loopEnv); result = null; } finally { ! loopEnv.info.scope.leave(); } } public void visitForeachLoop(JCEnhancedForLoop tree) { Env<AttrContext> loopEnv = --- 1324,1394 ---- } public void visitDoLoop(JCDoWhileLoop tree) { attribStat(tree.body, env.dup(tree)); attribExpr(tree.cond, env, syms.booleanType); + if (!breaksOutOf(tree, tree.body)) { + List<BindingSymbol> bindings = matchBindingsComputer.getMatchBindings(tree.cond, false); + + bindings.forEach(env.info.scope::enter); + bindings.forEach(BindingSymbol::preserveBinding); + } result = null; } public void visitWhileLoop(JCWhileLoop tree) { attribExpr(tree.cond, env, syms.booleanType); ! // include x.T in while's body ! Env<AttrContext> whileEnv = bindingEnv(env, matchBindingsComputer.getMatchBindings(tree.cond, true)); ! try { ! attribStat(tree.body, whileEnv.dup(tree)); ! } finally { ! whileEnv.info.scope.leave(); ! } ! if (!breaksOutOf(tree, tree.body)) { ! List<BindingSymbol> bindings = matchBindingsComputer.getMatchBindings(tree.cond, false); ! ! bindings.forEach(env.info.scope::enter); ! bindings.forEach(BindingSymbol::preserveBinding); ! } result = null; } + private boolean breaksOutOf(JCTree loop, JCTree body) { + preFlow(body); + return flow.breaksOutOf(env, loop, body, make); + } + public void visitForLoop(JCForLoop tree) { Env<AttrContext> loopEnv = env.dup(env.tree, env.info.dup(env.info.scope.dup())); try { attribStats(tree.init, loopEnv); ! List<BindingSymbol> matchBindings = List.nil(); ! if (tree.cond != null) { ! attribExpr(tree.cond, loopEnv, syms.booleanType); ! // include x.T in the evaluation scopes of body & step. ! matchBindings = matchBindingsComputer.getMatchBindings(tree.cond, true); ! } ! Env<AttrContext> bodyEnv = bindingEnv(loopEnv, matchBindings); ! try { ! bodyEnv.tree = tree; // before, we were not in loop! ! attribStats(tree.step, bodyEnv); ! attribStat(tree.body, bodyEnv); ! } finally { ! bodyEnv.info.scope.leave(); ! } result = null; } finally { ! loopEnv.info.scope.leave(); // all injected match bindings vanish here. ! } ! if (!breaksOutOf(tree, tree.body)) { ! List<BindingSymbol> bindings = matchBindingsComputer.getMatchBindings(tree.cond, false); ! ! bindings.forEach(env.info.scope::enter); ! bindings.forEach(BindingSymbol::preserveBinding); } } public void visitForeachLoop(JCEnhancedForLoop tree) { Env<AttrContext> loopEnv =
*** 1690,1701 **** ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ? unknownExprInfo : resultInfo.dup(conditionalContext(resultInfo.checkContext)); ! Type truetype = attribTree(tree.truepart, env, condInfo); ! Type falsetype = attribTree(tree.falsepart, env, condInfo); Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(List.of(tree.truepart.pos(), tree.falsepart.pos()), List.of(truetype, falsetype)) : pt(); if (condtype.constValue() != null && --- 1736,1765 ---- ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ? unknownExprInfo : resultInfo.dup(conditionalContext(resultInfo.checkContext)); ! /* if e = "x ? y : z", then: ! include x.T in y ! include x.F in z ! */ ! ! Type truetype; ! Env<AttrContext> trueEnv = bindingEnv(env, matchBindingsComputer.getMatchBindings(tree.cond, true)); ! try { ! truetype = attribTree(tree.truepart, trueEnv, condInfo); ! } finally { ! trueEnv.info.scope.leave(); ! } ! ! Type falsetype; ! Env<AttrContext> falseEnv = bindingEnv(env, matchBindingsComputer.getMatchBindings(tree.cond, false)); ! try { ! falsetype = attribTree(tree.falsepart, falseEnv, condInfo); ! } finally { ! falseEnv.info.scope.leave(); ! } Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(List.of(tree.truepart.pos(), tree.falsepart.pos()), List.of(truetype, falsetype)) : pt(); if (condtype.constValue() != null &&
*** 1846,1864 **** FLOAT, DOUBLE, BOOLEAN, }; public void visitIf(JCIf tree) { attribExpr(tree.cond, env, syms.booleanType); ! attribStat(tree.thenpart, env); ! if (tree.elsepart != null) ! attribStat(tree.elsepart, env); chk.checkEmptyIf(tree); result = null; } public void visitExec(JCExpressionStatement tree) { //a fresh environment is required for 292 inference to work properly --- //see Infer.instantiatePolymorphicSignatureInstance() Env<AttrContext> localEnv = env.dup(tree); attribExpr(tree.expr, localEnv); --- 1910,1988 ---- FLOAT, DOUBLE, BOOLEAN, }; + Env<AttrContext> bindingEnv(Env<AttrContext> env, List<BindingSymbol> bindings) { + Env<AttrContext> env1 = env.dup(env.tree, env.info.dup(env.info.scope.dup())); + bindings.forEach(env1.info.scope::enter); + return env1; + } + public void visitIf(JCIf tree) { attribExpr(tree.cond, env, syms.booleanType); ! ! // if (x) { y } [ else z ] include x.T in y; include x.F in z ! ! List<BindingSymbol> thenBindings = matchBindingsComputer.getMatchBindings(tree.cond, true); ! Env<AttrContext> thenEnv = bindingEnv(env, thenBindings); ! ! try { ! attribStat(tree.thenpart, thenEnv); ! } finally { ! thenEnv.info.scope.leave(); ! } ! ! preFlow(tree.thenpart); ! boolean aliveAfterThen = flow.aliveAfter(env, tree.thenpart, make); ! boolean aliveAfterElse; ! List<BindingSymbol> elseBindings = matchBindingsComputer.getMatchBindings(tree.cond, false); ! ! if (tree.elsepart != null) { ! Env<AttrContext> elseEnv = bindingEnv(env, elseBindings); ! try { ! attribStat(tree.elsepart, elseEnv); ! } finally { ! elseEnv.info.scope.leave(); ! } ! preFlow(tree.elsepart); ! aliveAfterElse = flow.aliveAfter(env, tree.elsepart, make); ! } else { ! aliveAfterElse = true; ! } ! chk.checkEmptyIf(tree); + + List<BindingSymbol> afterIfBindings = List.nil(); + + if (aliveAfterThen && !aliveAfterElse) { + afterIfBindings = thenBindings; + } else if (aliveAfterElse && !aliveAfterThen) { + afterIfBindings = elseBindings; + } + + afterIfBindings.forEach(env.info.scope::enter); + afterIfBindings.forEach(BindingSymbol::preserveBinding); + result = null; } + void preFlow(JCTree tree) { + new PostAttrAnalyzer() { + @Override + public void scan(JCTree tree) { + if (tree == null || + (tree.type != null && + tree.type == Type.stuckType)) { + //don't touch stuck expressions! + return; + } + super.scan(tree); + } + }.scan(tree); + } + public void visitExec(JCExpressionStatement tree) { //a fresh environment is required for 292 inference to work properly --- //see Infer.instantiatePolymorphicSignatureInstance() Env<AttrContext> localEnv = env.dup(tree); attribExpr(tree.expr, localEnv);
*** 3536,3546 **** } public void visitBinary(JCBinary tree) { // Attribute arguments. Type left = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.lhs, env)); ! Type right = chk.checkNonVoid(tree.rhs.pos(), attribExpr(tree.rhs, env)); // Find operator. Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag(), left, right); Type owntype = types.createErrorType(tree.type); if (operator != operators.noOpSymbol && !left.isErroneous() && --- 3660,3690 ---- } public void visitBinary(JCBinary tree) { // Attribute arguments. Type left = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.lhs, env)); ! // If e = "x && y", then, include x.T in y; If e = "x || y", then, include x.F in y ! List<BindingSymbol> matchBindings; ! switch (tree.getTag()) { ! case AND: ! matchBindings = matchBindingsComputer.getMatchBindings(tree.lhs, true); ! break; ! case OR: ! matchBindings = matchBindingsComputer.getMatchBindings(tree.lhs, false); ! break; ! default: ! matchBindings = List.nil(); ! break; ! } ! Env<AttrContext> rhsEnv = bindingEnv(env, matchBindings); ! Type right; ! try { ! right = chk.checkNonVoid(tree.rhs.pos(), attribExpr(tree.rhs, rhsEnv)); ! } finally { ! rhsEnv.info.scope.leave(); ! } ! // Find operator. Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag(), left, right); Type owntype = types.createErrorType(tree.type); if (operator != operators.noOpSymbol && !left.isErroneous() &&
*** 3602,3624 **** } public void visitTypeTest(JCInstanceOf tree) { Type exprtype = chk.checkNullOrRefType( tree.expr.pos(), attribExpr(tree.expr, env)); ! Type clazztype = attribType(tree.clazz, env); ! if (!clazztype.hasTag(TYPEVAR)) { ! clazztype = chk.checkClassOrArrayType(tree.clazz.pos(), clazztype); ! } ! if (!clazztype.isErroneous() && !types.isReifiable(clazztype)) { ! log.error(tree.clazz.pos(), Errors.IllegalGenericTypeForInstof); ! clazztype = types.createErrorType(clazztype); } - chk.validate(tree.clazz, env, false); chk.checkCastable(tree.expr.pos(), exprtype, clazztype); result = check(tree, syms.booleanType, KindSelector.VAL, resultInfo); } public void visitIndexed(JCArrayAccess tree) { Type owntype = types.createErrorType(tree.type); Type atype = attribExpr(tree.indexed, env); attribExpr(tree.index, env, syms.intType); if (types.isArray(atype)) --- 3746,3793 ---- } public void visitTypeTest(JCInstanceOf tree) { Type exprtype = chk.checkNullOrRefType( tree.expr.pos(), attribExpr(tree.expr, env)); ! Type clazztype; ! if (tree.pattern.getTag() == BINDINGPATTERN) { ! attribTree(tree.pattern, env, unknownExprInfo); ! clazztype = tree.pattern.type; ! if (!clazztype.hasTag(TYPEVAR)) { ! JCBindingPattern pattern = (JCBindingPattern) tree.pattern; ! clazztype = chk.checkClassOrArrayType(pattern.vartype.pos(), clazztype); ! } ! } else { ! clazztype = attribType(tree.pattern, env); ! if (!clazztype.hasTag(TYPEVAR)) { ! clazztype = chk.checkClassOrArrayType(tree.pattern.pos(), clazztype); ! } ! if (!clazztype.isErroneous() && !types.isReifiable(clazztype)) { ! log.error(tree.pattern.pos(), Errors.IllegalGenericTypeForInstof); ! clazztype = types.createErrorType(clazztype); ! } ! chk.validate(tree.pattern, env, false); } chk.checkCastable(tree.expr.pos(), exprtype, clazztype); result = check(tree, syms.booleanType, KindSelector.VAL, resultInfo); } + public void visitBindingPattern(JCBindingPattern tree) { + if (tree.vartype != null) { + ResultInfo varInfo = new ResultInfo(KindSelector.TYP, resultInfo.pt, resultInfo.checkContext); + tree.type = attribTree(tree.vartype, env, varInfo); + } else { + tree.type = resultInfo.pt; + } + VarSymbol v = tree.symbol = new BindingSymbol(tree.name, tree.vartype != null ? tree.vartype.type : (tree.type.hasTag(BOT) ? syms.objectType : tree.type), env.info.scope.owner); + if (chk.checkUnique(tree.pos(), v, env.info.scope)) { + chk.checkTransparentVar(tree.pos(), v, env.info.scope); + // env.info.scope.enter(v); // we inject into scopes expressly at various points. + } + result = tree.type; + } + public void visitIndexed(JCArrayAccess tree) { Type owntype = types.createErrorType(tree.type); Type atype = attribExpr(tree.indexed, env); attribExpr(tree.index, env, syms.intType); if (types.isArray(atype))
*** 5005,5016 **** if (tree.clazz != null && tree.clazz.type != null) validateAnnotatedType(tree.clazz, tree.clazz.type); super.visitTypeCast(tree); } public void visitTypeTest(JCInstanceOf tree) { ! if (tree.clazz != null && tree.clazz.type != null) ! validateAnnotatedType(tree.clazz, tree.clazz.type); super.visitTypeTest(tree); } public void visitNewClass(JCNewClass tree) { if (tree.clazz != null && tree.clazz.type != null) { if (tree.clazz.hasTag(ANNOTATED_TYPE)) { --- 5174,5185 ---- if (tree.clazz != null && tree.clazz.type != null) validateAnnotatedType(tree.clazz, tree.clazz.type); super.visitTypeCast(tree); } public void visitTypeTest(JCInstanceOf tree) { ! if (tree.pattern != null && !(tree.pattern instanceof JCPattern) && tree.pattern.type != null) ! validateAnnotatedType(tree.pattern, tree.pattern.type); super.visitTypeTest(tree); } public void visitNewClass(JCNewClass tree) { if (tree.clazz != null && tree.clazz.type != null) { if (tree.clazz.hasTag(ANNOTATED_TYPE)) {
*** 5267,5276 **** --- 5436,5455 ---- } super.visitVarDef(that); } @Override + public void visitBindingPattern(JCBindingPattern that) { + //initTypeIfNeeded(that); + if (that.symbol == null) { + that.symbol = new BindingSymbol(that.name, that.type, syms.noSymbol); + that.symbol.adr = 0; + } + super.visitBindingPattern(that); + } + + @Override public void visitNewClass(JCNewClass that) { if (that.constructor == null) { that.constructor = new MethodSymbol(0, names.init, dummyMethodType(), syms.noSymbol); }
< prev index next >