< prev index next >

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

Print this page




  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 com.sun.tools.javac.code.Source.Feature;
  29 import com.sun.tools.javac.code.Type.UndetVar.UndetVarListener;
  30 import com.sun.tools.javac.code.Types.TypeMapping;
  31 import com.sun.tools.javac.comp.Attr.CheckMode;
  32 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  33 import com.sun.tools.javac.resources.CompilerProperties.Notes;
  34 import com.sun.tools.javac.tree.JCTree;
  35 import com.sun.tools.javac.tree.JCTree.JCTypeCast;
  36 import com.sun.tools.javac.tree.TreeInfo;
  37 import com.sun.tools.javac.util.*;
  38 import com.sun.tools.javac.util.GraphUtils.DottableNode;
  39 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  40 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  41 import com.sun.tools.javac.util.List;
  42 import com.sun.tools.javac.code.*;
  43 import com.sun.tools.javac.code.Type.*;
  44 import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
  45 import com.sun.tools.javac.code.Symbol.*;
  46 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
  47 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
  48 import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph;
  49 import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph.Node;
  50 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
  51 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;


 262 
 263         private List<Type> roots(MethodType mt, DeferredAttrContext deferredAttrContext) {
 264             if (deferredAttrContext != null && deferredAttrContext.mode == AttrMode.CHECK) {
 265                 ListBuffer<Type> roots = new ListBuffer<>();
 266                 roots.add(mt.getReturnType());
 267                 for (DeferredAttr.DeferredAttrNode n : deferredAttrContext.deferredAttrNodes) {
 268                     roots.addAll(n.deferredStuckPolicy.stuckVars());
 269                     roots.addAll(n.deferredStuckPolicy.depVars());
 270                 }
 271                 List<Type> thrownVars = deferredAttrContext.inferenceContext.inferencevars.stream()
 272                                 .filter(tv -> (tv.tsym.flags() & Flags.THROWS) != 0).collect(List.collector());
 273                 List<Type> result = roots.toList();
 274                 result = result.appendList(thrownVars.diff(result));
 275                 return result;
 276             } else {
 277                 return List.of(mt.getReturnType());
 278             }
 279         }
 280 
 281     /**
 282      * A partially infered method/constructor type; such a type can be checked multiple times
 283      * against different targets.
 284      */
 285     public class PartiallyInferredMethodType extends MethodType {
 286         public PartiallyInferredMethodType(MethodType mtype, InferenceContext inferenceContext, Env<AttrContext> env, Warner warn) {
 287             super(mtype.getParameterTypes(), mtype.getReturnType(), mtype.getThrownTypes(), mtype.tsym);
 288             this.inferenceContext = inferenceContext;
 289             this.env = env;
 290             this.warn = warn;
 291         }
 292 
 293         /** The inference context. */
 294         final InferenceContext inferenceContext;
 295 
 296         /** The attribution environment. */
 297         Env<AttrContext> env;
 298 
 299         /** The warner. */
 300         final Warner warn;
 301 
 302         @Override
 303         public boolean isPartial() {
 304             return true;
 305         }
 306 
 307         /**
 308          * Checks this type against a target; this means generating return type constraints, solve
 309          * and then roll back the results (to avoid poolluting the context).
 310          */
 311         Type check(Attr.ResultInfo resultInfo) {
 312             Warner noWarnings = new Warner(null);
 313             List<Type> saved_undet = null;
 314             try {
 315                 /** we need to save the inference context before generating target type constraints.
 316                  *  This constraints may pollute the inference context and make it useless in case we
 317                  *  need to use it several times: with several targets.
 318                  */
 319                 saved_undet = inferenceContext.save();
 320                 boolean unchecked = warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED);
 321                 if (!unchecked) {
 322                     boolean shouldPropagate = shouldPropagate(getReturnType(), resultInfo, inferenceContext);
 323 
 324                     InferenceContext minContext = shouldPropagate ?
 325                             inferenceContext.min(roots(asMethodType(), null), false, warn) :
 326                             inferenceContext;
 327 
 328                     MethodType other = (MethodType)minContext.update(asMethodType());
 329                     Type newRestype = generateReturnConstraints(env.tree, resultInfo,  //B3


1604         GraphInferenceSteps(EnumSet<InferenceStep> steps) {
1605             this.steps = steps;
1606         }
1607     }
1608 
1609     /**
1610      * There are two kinds of dependencies between inference variables. The basic
1611      * kind of dependency (or bound dependency) arises when a variable mention
1612      * another variable in one of its bounds. There's also a more subtle kind
1613      * of dependency that arises when a variable 'might' lead to better constraints
1614      * on another variable (this is typically the case with variables holding up
1615      * stuck expressions).
1616      */
1617     enum DependencyKind implements GraphUtils.DependencyKind {
1618 
1619         /** bound dependency */
1620         BOUND("dotted"),
1621         /** stuck dependency */
1622         STUCK("dashed");
1623 
1624         final String dotSyle;
1625 
1626         private DependencyKind(String dotSyle) {
1627             this.dotSyle = dotSyle;
1628         }
1629     }
1630 
1631     /**
1632      * This is the graph inference solver - the solver organizes all inference variables in
1633      * a given inference context by bound dependencies - in the general case, such dependencies
1634      * would lead to a cyclic directed graph (hence the name); the dependency info is used to build
1635      * an acyclic graph, where all cyclic variables are bundled together. An inference
1636      * step corresponds to solving a node in the acyclic graph - this is done by
1637      * relying on a given strategy (see GraphStrategy).
1638      */
1639     class GraphSolver {
1640 
1641         InferenceContext inferenceContext;
1642         Warner warn;
1643 
1644         GraphSolver(InferenceContext inferenceContext, Warner warn) {
1645             this.inferenceContext = inferenceContext;
1646             this.warn = warn;
1647         }


1812                  * topology.
1813                  */
1814                 private void graphChanged(Node from, Node to) {
1815                     if (removeDependency(from)) {
1816                         if (to != null) {
1817                             addDependency(to);
1818                         }
1819                     }
1820                 }
1821 
1822                 @Override
1823                 public Properties nodeAttributes() {
1824                     Properties p = new Properties();
1825                     p.put("label", "\"" + toString() + "\"");
1826                     return p;
1827                 }
1828 
1829                 @Override
1830                 public Properties dependencyAttributes(Node sink, GraphUtils.DependencyKind dk) {
1831                     Properties p = new Properties();
1832                     p.put("style", ((DependencyKind)dk).dotSyle);
1833                     StringBuilder buf = new StringBuilder();
1834                     String sep = "";
1835                     for (Type from : data) {
1836                         UndetVar uv = (UndetVar)inferenceContext.asUndetVar(from);
1837                         for (Type bound : uv.getBounds(InferenceBound.values())) {
1838                             if (bound.containsAny(List.from(sink.data))) {
1839                                 buf.append(sep);
1840                                 buf.append(bound);
1841                                 sep = ",";
1842                             }
1843                         }
1844                     }
1845                     p.put("label", "\"" + buf.toString() + "\"");
1846                     return p;
1847                 }
1848             }
1849 
1850             /** the nodes in the inference graph */
1851             ArrayList<Node> nodes;
1852 




  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 com.sun.tools.javac.code.Source.Feature;
  29 import com.sun.tools.javac.code.Type.UndetVar.UndetVarListener;
  30 import com.sun.tools.javac.code.Types.TypeMapping;

  31 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  32 import com.sun.tools.javac.resources.CompilerProperties.Notes;
  33 import com.sun.tools.javac.tree.JCTree;
  34 import com.sun.tools.javac.tree.JCTree.JCTypeCast;
  35 import com.sun.tools.javac.tree.TreeInfo;
  36 import com.sun.tools.javac.util.*;
  37 import com.sun.tools.javac.util.GraphUtils.DottableNode;
  38 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  39 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  40 import com.sun.tools.javac.util.List;
  41 import com.sun.tools.javac.code.*;
  42 import com.sun.tools.javac.code.Type.*;
  43 import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
  44 import com.sun.tools.javac.code.Symbol.*;
  45 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
  46 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
  47 import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph;
  48 import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph.Node;
  49 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
  50 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;


 261 
 262         private List<Type> roots(MethodType mt, DeferredAttrContext deferredAttrContext) {
 263             if (deferredAttrContext != null && deferredAttrContext.mode == AttrMode.CHECK) {
 264                 ListBuffer<Type> roots = new ListBuffer<>();
 265                 roots.add(mt.getReturnType());
 266                 for (DeferredAttr.DeferredAttrNode n : deferredAttrContext.deferredAttrNodes) {
 267                     roots.addAll(n.deferredStuckPolicy.stuckVars());
 268                     roots.addAll(n.deferredStuckPolicy.depVars());
 269                 }
 270                 List<Type> thrownVars = deferredAttrContext.inferenceContext.inferencevars.stream()
 271                                 .filter(tv -> (tv.tsym.flags() & Flags.THROWS) != 0).collect(List.collector());
 272                 List<Type> result = roots.toList();
 273                 result = result.appendList(thrownVars.diff(result));
 274                 return result;
 275             } else {
 276                 return List.of(mt.getReturnType());
 277             }
 278         }
 279 
 280     /**
 281      * A partially inferred method/constructor type; such a type can be checked multiple times
 282      * against different targets.
 283      */
 284     public class PartiallyInferredMethodType extends MethodType {
 285         public PartiallyInferredMethodType(MethodType mtype, InferenceContext inferenceContext, Env<AttrContext> env, Warner warn) {
 286             super(mtype.getParameterTypes(), mtype.getReturnType(), mtype.getThrownTypes(), mtype.tsym);
 287             this.inferenceContext = inferenceContext;
 288             this.env = env;
 289             this.warn = warn;
 290         }
 291 
 292         /** The inference context. */
 293         final InferenceContext inferenceContext;
 294 
 295         /** The attribution environment. */
 296         Env<AttrContext> env;
 297 
 298         /** The warner. */
 299         final Warner warn;
 300 
 301         @Override
 302         public boolean isPartial() {
 303             return true;
 304         }
 305 
 306         /**
 307          * Checks this type against a target; this means generating return type constraints, solve
 308          * and then roll back the results (to avoid polluting the context).
 309          */
 310         Type check(Attr.ResultInfo resultInfo) {
 311             Warner noWarnings = new Warner(null);
 312             List<Type> saved_undet = null;
 313             try {
 314                 /** we need to save the inference context before generating target type constraints.
 315                  *  This constraints may pollute the inference context and make it useless in case we
 316                  *  need to use it several times: with several targets.
 317                  */
 318                 saved_undet = inferenceContext.save();
 319                 boolean unchecked = warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED);
 320                 if (!unchecked) {
 321                     boolean shouldPropagate = shouldPropagate(getReturnType(), resultInfo, inferenceContext);
 322 
 323                     InferenceContext minContext = shouldPropagate ?
 324                             inferenceContext.min(roots(asMethodType(), null), false, warn) :
 325                             inferenceContext;
 326 
 327                     MethodType other = (MethodType)minContext.update(asMethodType());
 328                     Type newRestype = generateReturnConstraints(env.tree, resultInfo,  //B3


1603         GraphInferenceSteps(EnumSet<InferenceStep> steps) {
1604             this.steps = steps;
1605         }
1606     }
1607 
1608     /**
1609      * There are two kinds of dependencies between inference variables. The basic
1610      * kind of dependency (or bound dependency) arises when a variable mention
1611      * another variable in one of its bounds. There's also a more subtle kind
1612      * of dependency that arises when a variable 'might' lead to better constraints
1613      * on another variable (this is typically the case with variables holding up
1614      * stuck expressions).
1615      */
1616     enum DependencyKind implements GraphUtils.DependencyKind {
1617 
1618         /** bound dependency */
1619         BOUND("dotted"),
1620         /** stuck dependency */
1621         STUCK("dashed");
1622 
1623         final String dotStyle;
1624 
1625         private DependencyKind(String dotStyle) {
1626             this.dotStyle = dotStyle;
1627         }
1628     }
1629 
1630     /**
1631      * This is the graph inference solver - the solver organizes all inference variables in
1632      * a given inference context by bound dependencies - in the general case, such dependencies
1633      * would lead to a cyclic directed graph (hence the name); the dependency info is used to build
1634      * an acyclic graph, where all cyclic variables are bundled together. An inference
1635      * step corresponds to solving a node in the acyclic graph - this is done by
1636      * relying on a given strategy (see GraphStrategy).
1637      */
1638     class GraphSolver {
1639 
1640         InferenceContext inferenceContext;
1641         Warner warn;
1642 
1643         GraphSolver(InferenceContext inferenceContext, Warner warn) {
1644             this.inferenceContext = inferenceContext;
1645             this.warn = warn;
1646         }


1811                  * topology.
1812                  */
1813                 private void graphChanged(Node from, Node to) {
1814                     if (removeDependency(from)) {
1815                         if (to != null) {
1816                             addDependency(to);
1817                         }
1818                     }
1819                 }
1820 
1821                 @Override
1822                 public Properties nodeAttributes() {
1823                     Properties p = new Properties();
1824                     p.put("label", "\"" + toString() + "\"");
1825                     return p;
1826                 }
1827 
1828                 @Override
1829                 public Properties dependencyAttributes(Node sink, GraphUtils.DependencyKind dk) {
1830                     Properties p = new Properties();
1831                     p.put("style", ((DependencyKind)dk).dotStyle);
1832                     StringBuilder buf = new StringBuilder();
1833                     String sep = "";
1834                     for (Type from : data) {
1835                         UndetVar uv = (UndetVar)inferenceContext.asUndetVar(from);
1836                         for (Type bound : uv.getBounds(InferenceBound.values())) {
1837                             if (bound.containsAny(List.from(sink.data))) {
1838                                 buf.append(sep);
1839                                 buf.append(bound);
1840                                 sep = ",";
1841                             }
1842                         }
1843                     }
1844                     p.put("label", "\"" + buf.toString() + "\"");
1845                     return p;
1846                 }
1847             }
1848 
1849             /** the nodes in the inference graph */
1850             ArrayList<Node> nodes;
1851 


< prev index next >