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
|