changeset 31937 | ad43a6639c4a |
parent 30014 | fc1f2b200c1f |
child 32709 | 55d136799f79 |
31936:02f1cfc234a0 | 31937:ad43a6639c4a |
---|---|
23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package com.sun.tools.javac.comp; |
26 package com.sun.tools.javac.comp; |
27 |
27 |
28 import com.sun.tools.javac.code.Type.TypeMapping; |
|
29 import com.sun.tools.javac.tree.JCTree; |
28 import com.sun.tools.javac.tree.JCTree; |
30 import com.sun.tools.javac.tree.JCTree.JCTypeCast; |
29 import com.sun.tools.javac.tree.JCTree.JCTypeCast; |
31 import com.sun.tools.javac.tree.TreeInfo; |
30 import com.sun.tools.javac.tree.TreeInfo; |
32 import com.sun.tools.javac.util.*; |
31 import com.sun.tools.javac.util.*; |
33 import com.sun.tools.javac.util.GraphUtils.DottableNode; |
32 import com.sun.tools.javac.util.GraphUtils.DottableNode; |
110 Options options = Options.instance(context); |
109 Options options = Options.instance(context); |
111 allowGraphInference = Source.instance(context).allowGraphInference() |
110 allowGraphInference = Source.instance(context).allowGraphInference() |
112 && options.isUnset("useLegacyInference"); |
111 && options.isUnset("useLegacyInference"); |
113 dependenciesFolder = options.get("dumpInferenceGraphsTo"); |
112 dependenciesFolder = options.get("dumpInferenceGraphsTo"); |
114 pendingGraphs = List.nil(); |
113 pendingGraphs = List.nil(); |
114 |
|
115 emptyContext = new InferenceContext(this, List.<Type>nil()); |
|
115 } |
116 } |
116 |
117 |
117 /** A value for prototypes that admit any type, including polymorphic ones. */ |
118 /** A value for prototypes that admit any type, including polymorphic ones. */ |
118 public static final Type anyPoly = new JCNoType(); |
119 public static final Type anyPoly = new JCNoType(); |
119 |
120 |
168 boolean allowBoxing, |
169 boolean allowBoxing, |
169 boolean useVarargs, |
170 boolean useVarargs, |
170 Resolve.MethodResolutionContext resolveContext, |
171 Resolve.MethodResolutionContext resolveContext, |
171 Warner warn) throws InferenceException { |
172 Warner warn) throws InferenceException { |
172 //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG |
173 //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG |
173 final InferenceContext inferenceContext = new InferenceContext(tvars); //B0 |
174 final InferenceContext inferenceContext = new InferenceContext(this, tvars); //B0 |
174 inferenceException.clear(); |
175 inferenceException.clear(); |
175 try { |
176 try { |
176 DeferredAttr.DeferredAttrContext deferredAttrContext = |
177 DeferredAttr.DeferredAttrContext deferredAttrContext = |
177 resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn); |
178 resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn); |
178 |
179 |
408 } |
409 } |
409 |
410 |
410 /** |
411 /** |
411 * Infer cyclic inference variables as described in 15.12.2.8. |
412 * Infer cyclic inference variables as described in 15.12.2.8. |
412 */ |
413 */ |
413 private void instantiateAsUninferredVars(List<Type> vars, InferenceContext inferenceContext) { |
414 void instantiateAsUninferredVars(List<Type> vars, InferenceContext inferenceContext) { |
414 ListBuffer<Type> todo = new ListBuffer<>(); |
415 ListBuffer<Type> todo = new ListBuffer<>(); |
415 //step 1 - create fresh tvars |
416 //step 1 - create fresh tvars |
416 for (Type t : vars) { |
417 for (Type t : vars) { |
417 UndetVar uv = (UndetVar)inferenceContext.asUndetVar(t); |
418 UndetVar uv = (UndetVar)inferenceContext.asUndetVar(t); |
418 List<Type> upperBounds = uv.getBounds(InferenceBound.UPPER); |
419 List<Type> upperBounds = uv.getBounds(InferenceBound.UPPER); |
526 //(this means the target contains no wildcards!) |
527 //(this means the target contains no wildcards!) |
527 return funcInterface; |
528 return funcInterface; |
528 } else { |
529 } else { |
529 Type formalInterface = funcInterface.tsym.type; |
530 Type formalInterface = funcInterface.tsym.type; |
530 InferenceContext funcInterfaceContext = |
531 InferenceContext funcInterfaceContext = |
531 new InferenceContext(funcInterface.tsym.type.getTypeArguments()); |
532 new InferenceContext(this, funcInterface.tsym.type.getTypeArguments()); |
532 |
533 |
533 Assert.check(paramTypes != null); |
534 Assert.check(paramTypes != null); |
534 //get constraints from explicit params (this is done by |
535 //get constraints from explicit params (this is done by |
535 //checking that explicit param types are equal to the ones |
536 //checking that explicit param types are equal to the ones |
536 //in the functional interface descriptors) |
537 //in the functional interface descriptors) |
708 * Performs basic bound checking - i.e. is the instantiated type for a given |
709 * Performs basic bound checking - i.e. is the instantiated type for a given |
709 * inference variable compatible with its bounds? |
710 * inference variable compatible with its bounds? |
710 */ |
711 */ |
711 CHECK_BOUNDS() { |
712 CHECK_BOUNDS() { |
712 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
713 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
713 Infer infer = inferenceContext.infer(); |
714 Infer infer = inferenceContext.infer; |
714 uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), infer.types); |
715 uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), infer.types); |
715 infer.checkCompatibleUpperBounds(uv, inferenceContext); |
716 infer.checkCompatibleUpperBounds(uv, inferenceContext); |
716 if (uv.inst != null) { |
717 if (uv.inst != null) { |
717 Type inst = uv.inst; |
718 Type inst = uv.inst; |
718 for (Type u : uv.getBounds(InferenceBound.UPPER)) { |
719 for (Type u : uv.getBounds(InferenceBound.UPPER)) { |
744 * inference routine that is designed as to maximize compatibility with JDK 7. |
745 * inference routine that is designed as to maximize compatibility with JDK 7. |
745 * Note: this is not used in graph mode. |
746 * Note: this is not used in graph mode. |
746 */ |
747 */ |
747 EQ_CHECK_LEGACY() { |
748 EQ_CHECK_LEGACY() { |
748 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
749 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
749 Infer infer = inferenceContext.infer(); |
750 Infer infer = inferenceContext.infer; |
750 Type eq = null; |
751 Type eq = null; |
751 for (Type e : uv.getBounds(InferenceBound.EQ)) { |
752 for (Type e : uv.getBounds(InferenceBound.EQ)) { |
752 Assert.check(!inferenceContext.free(e)); |
753 Assert.check(!inferenceContext.free(e)); |
753 if (eq != null && !isSameType(e, eq, infer)) { |
754 if (eq != null && !isSameType(e, eq, infer)) { |
754 infer.reportBoundError(uv, BoundErrorKind.EQ); |
755 infer.reportBoundError(uv, BoundErrorKind.EQ); |
778 * Check consistency of equality constraints. |
779 * Check consistency of equality constraints. |
779 */ |
780 */ |
780 EQ_CHECK() { |
781 EQ_CHECK() { |
781 @Override |
782 @Override |
782 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
783 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
783 Infer infer = inferenceContext.infer(); |
784 Infer infer = inferenceContext.infer; |
784 for (Type e : uv.getBounds(InferenceBound.EQ)) { |
785 for (Type e : uv.getBounds(InferenceBound.EQ)) { |
785 if (e.containsAny(inferenceContext.inferenceVars())) continue; |
786 if (e.containsAny(inferenceContext.inferenceVars())) continue; |
786 for (Type u : uv.getBounds(InferenceBound.UPPER)) { |
787 for (Type u : uv.getBounds(InferenceBound.UPPER)) { |
787 if (!isSubtype(e, inferenceContext.asUndetVar(u), warn, infer)) { |
788 if (!isSubtype(e, inferenceContext.asUndetVar(u), warn, infer)) { |
788 infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER); |
789 infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER); |
805 * Given a bound set containing {@code alpha <: T} and {@code alpha :> S} |
806 * Given a bound set containing {@code alpha <: T} and {@code alpha :> S} |
806 * perform {@code S <: T} (which could lead to new bounds). |
807 * perform {@code S <: T} (which could lead to new bounds). |
807 */ |
808 */ |
808 CROSS_UPPER_LOWER() { |
809 CROSS_UPPER_LOWER() { |
809 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
810 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
810 Infer infer = inferenceContext.infer(); |
811 Infer infer = inferenceContext.infer; |
811 for (Type b1 : uv.getBounds(InferenceBound.UPPER)) { |
812 for (Type b1 : uv.getBounds(InferenceBound.UPPER)) { |
812 for (Type b2 : uv.getBounds(InferenceBound.LOWER)) { |
813 for (Type b2 : uv.getBounds(InferenceBound.LOWER)) { |
813 if (!isSubtype(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), warn , infer)) { |
814 if (!isSubtype(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), warn , infer)) { |
814 infer.reportBoundError(uv, BoundErrorKind.BAD_UPPER_LOWER); |
815 infer.reportBoundError(uv, BoundErrorKind.BAD_UPPER_LOWER); |
815 } |
816 } |
828 * Given a bound set containing {@code alpha <: T} and {@code alpha == S} |
829 * Given a bound set containing {@code alpha <: T} and {@code alpha == S} |
829 * perform {@code S <: T} (which could lead to new bounds). |
830 * perform {@code S <: T} (which could lead to new bounds). |
830 */ |
831 */ |
831 CROSS_UPPER_EQ() { |
832 CROSS_UPPER_EQ() { |
832 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
833 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
833 Infer infer = inferenceContext.infer(); |
834 Infer infer = inferenceContext.infer; |
834 for (Type b1 : uv.getBounds(InferenceBound.UPPER)) { |
835 for (Type b1 : uv.getBounds(InferenceBound.UPPER)) { |
835 for (Type b2 : uv.getBounds(InferenceBound.EQ)) { |
836 for (Type b2 : uv.getBounds(InferenceBound.EQ)) { |
836 if (!isSubtype(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), warn, infer)) { |
837 if (!isSubtype(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), warn, infer)) { |
837 infer.reportBoundError(uv, BoundErrorKind.BAD_UPPER_EQUAL); |
838 infer.reportBoundError(uv, BoundErrorKind.BAD_UPPER_EQUAL); |
838 } |
839 } |
851 * Given a bound set containing {@code alpha :> S} and {@code alpha == T} |
852 * Given a bound set containing {@code alpha :> S} and {@code alpha == T} |
852 * perform {@code S <: T} (which could lead to new bounds). |
853 * perform {@code S <: T} (which could lead to new bounds). |
853 */ |
854 */ |
854 CROSS_EQ_LOWER() { |
855 CROSS_EQ_LOWER() { |
855 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
856 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
856 Infer infer = inferenceContext.infer(); |
857 Infer infer = inferenceContext.infer; |
857 for (Type b1 : uv.getBounds(InferenceBound.EQ)) { |
858 for (Type b1 : uv.getBounds(InferenceBound.EQ)) { |
858 for (Type b2 : uv.getBounds(InferenceBound.LOWER)) { |
859 for (Type b2 : uv.getBounds(InferenceBound.LOWER)) { |
859 if (!isSubtype(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), warn, infer)) { |
860 if (!isSubtype(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), warn, infer)) { |
860 infer.reportBoundError(uv, BoundErrorKind.BAD_EQUAL_LOWER); |
861 infer.reportBoundError(uv, BoundErrorKind.BAD_EQUAL_LOWER); |
861 } |
862 } |
876 * perform {@code T = S} (which could lead to new bounds). |
877 * perform {@code T = S} (which could lead to new bounds). |
877 */ |
878 */ |
878 CROSS_UPPER_UPPER() { |
879 CROSS_UPPER_UPPER() { |
879 @Override |
880 @Override |
880 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
881 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
881 Infer infer = inferenceContext.infer(); |
882 Infer infer = inferenceContext.infer; |
882 List<Type> boundList = uv.getBounds(InferenceBound.UPPER).stream() |
883 List<Type> boundList = uv.getBounds(InferenceBound.UPPER).stream() |
883 .collect(infer.types.closureCollector(true, infer.types::isSameType)); |
884 .collect(infer.types.closureCollector(true, infer.types::isSameType)); |
884 List<Type> boundListTail = boundList.tail; |
885 List<Type> boundListTail = boundList.tail; |
885 while (boundList.nonEmpty()) { |
886 while (boundList.nonEmpty()) { |
886 List<Type> tmpTail = boundListTail; |
887 List<Type> tmpTail = boundListTail; |
926 * Given a bound set containing {@code alpha == S} and {@code alpha == T} |
927 * Given a bound set containing {@code alpha == S} and {@code alpha == T} |
927 * perform {@code S == T} (which could lead to new bounds). |
928 * perform {@code S == T} (which could lead to new bounds). |
928 */ |
929 */ |
929 CROSS_EQ_EQ() { |
930 CROSS_EQ_EQ() { |
930 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
931 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
931 Infer infer = inferenceContext.infer(); |
932 Infer infer = inferenceContext.infer; |
932 for (Type b1 : uv.getBounds(InferenceBound.EQ)) { |
933 for (Type b1 : uv.getBounds(InferenceBound.EQ)) { |
933 for (Type b2 : uv.getBounds(InferenceBound.EQ)) { |
934 for (Type b2 : uv.getBounds(InferenceBound.EQ)) { |
934 if (b1 != b2) { |
935 if (b1 != b2) { |
935 if (!isSameType(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), infer)) { |
936 if (!isSameType(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), infer)) { |
936 infer.reportBoundError(uv, BoundErrorKind.BAD_EQ); |
937 infer.reportBoundError(uv, BoundErrorKind.BAD_EQ); |
950 * Given a bound set containing {@code alpha <: beta} propagate lower bounds |
951 * Given a bound set containing {@code alpha <: beta} propagate lower bounds |
951 * from alpha to beta; also propagate upper bounds from beta to alpha. |
952 * from alpha to beta; also propagate upper bounds from beta to alpha. |
952 */ |
953 */ |
953 PROP_UPPER() { |
954 PROP_UPPER() { |
954 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
955 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
955 Infer infer = inferenceContext.infer(); |
956 Infer infer = inferenceContext.infer; |
956 for (Type b : uv.getBounds(InferenceBound.UPPER)) { |
957 for (Type b : uv.getBounds(InferenceBound.UPPER)) { |
957 if (inferenceContext.inferenceVars().contains(b)) { |
958 if (inferenceContext.inferenceVars().contains(b)) { |
958 UndetVar uv2 = (UndetVar)inferenceContext.asUndetVar(b); |
959 UndetVar uv2 = (UndetVar)inferenceContext.asUndetVar(b); |
959 if (uv2.isCaptured()) continue; |
960 if (uv2.isCaptured()) continue; |
960 //alpha <: beta |
961 //alpha <: beta |
982 * Given a bound set containing {@code alpha :> beta} propagate lower bounds |
983 * Given a bound set containing {@code alpha :> beta} propagate lower bounds |
983 * from beta to alpha; also propagate upper bounds from alpha to beta. |
984 * from beta to alpha; also propagate upper bounds from alpha to beta. |
984 */ |
985 */ |
985 PROP_LOWER() { |
986 PROP_LOWER() { |
986 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
987 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
987 Infer infer = inferenceContext.infer(); |
988 Infer infer = inferenceContext.infer; |
988 for (Type b : uv.getBounds(InferenceBound.LOWER)) { |
989 for (Type b : uv.getBounds(InferenceBound.LOWER)) { |
989 if (inferenceContext.inferenceVars().contains(b)) { |
990 if (inferenceContext.inferenceVars().contains(b)) { |
990 UndetVar uv2 = (UndetVar)inferenceContext.asUndetVar(b); |
991 UndetVar uv2 = (UndetVar)inferenceContext.asUndetVar(b); |
991 if (uv2.isCaptured()) continue; |
992 if (uv2.isCaptured()) continue; |
992 //alpha :> beta |
993 //alpha :> beta |
1014 * Given a bound set containing {@code alpha == beta} propagate lower/upper |
1015 * Given a bound set containing {@code alpha == beta} propagate lower/upper |
1015 * bounds from alpha to beta and back. |
1016 * bounds from alpha to beta and back. |
1016 */ |
1017 */ |
1017 PROP_EQ() { |
1018 PROP_EQ() { |
1018 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
1019 public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { |
1019 Infer infer = inferenceContext.infer(); |
1020 Infer infer = inferenceContext.infer; |
1020 for (Type b : uv.getBounds(InferenceBound.EQ)) { |
1021 for (Type b : uv.getBounds(InferenceBound.EQ)) { |
1021 if (inferenceContext.inferenceVars().contains(b)) { |
1022 if (inferenceContext.inferenceVars().contains(b)) { |
1022 UndetVar uv2 = (UndetVar)inferenceContext.asUndetVar(b); |
1023 UndetVar uv2 = (UndetVar)inferenceContext.asUndetVar(b); |
1023 if (uv2.isCaptured()) continue; |
1024 if (uv2.isCaptured()) continue; |
1024 //alpha == beta |
1025 //alpha == beta |
1522 * bounds are merged together using lub(). |
1523 * bounds are merged together using lub(). |
1523 */ |
1524 */ |
1524 LOWER(InferenceBound.LOWER) { |
1525 LOWER(InferenceBound.LOWER) { |
1525 @Override |
1526 @Override |
1526 Type solve(UndetVar uv, InferenceContext inferenceContext) { |
1527 Type solve(UndetVar uv, InferenceContext inferenceContext) { |
1527 Infer infer = inferenceContext.infer(); |
1528 Infer infer = inferenceContext.infer; |
1528 List<Type> lobounds = filterBounds(uv, inferenceContext); |
1529 List<Type> lobounds = filterBounds(uv, inferenceContext); |
1529 //note: lobounds should have at least one element |
1530 //note: lobounds should have at least one element |
1530 Type owntype = lobounds.tail.tail == null ? lobounds.head : infer.types.lub(lobounds); |
1531 Type owntype = lobounds.tail.tail == null ? lobounds.head : infer.types.lub(lobounds); |
1531 if (owntype.isPrimitive() || owntype.hasTag(ERROR)) { |
1532 if (owntype.isPrimitive() || owntype.hasTag(ERROR)) { |
1532 throw infer.inferenceException |
1533 throw infer.inferenceException |
1551 if (t.getBounds(InferenceBound.EQ, InferenceBound.LOWER, InferenceBound.UPPER) |
1552 if (t.getBounds(InferenceBound.EQ, InferenceBound.LOWER, InferenceBound.UPPER) |
1552 .diff(t.getDeclaredBounds()).nonEmpty()) { |
1553 .diff(t.getDeclaredBounds()).nonEmpty()) { |
1553 //not an unbounded undet var |
1554 //not an unbounded undet var |
1554 return false; |
1555 return false; |
1555 } |
1556 } |
1556 Infer infer = inferenceContext.infer(); |
1557 Infer infer = inferenceContext.infer; |
1557 for (Type db : t.getDeclaredBounds()) { |
1558 for (Type db : t.getDeclaredBounds()) { |
1558 if (t.isInterface()) continue; |
1559 if (t.isInterface()) continue; |
1559 if (infer.types.asSuper(infer.syms.runtimeExceptionType, db.tsym) != null) { |
1560 if (infer.types.asSuper(infer.syms.runtimeExceptionType, db.tsym) != null) { |
1560 //declared bound is a supertype of RuntimeException |
1561 //declared bound is a supertype of RuntimeException |
1561 return true; |
1562 return true; |
1565 return false; |
1566 return false; |
1566 } |
1567 } |
1567 |
1568 |
1568 @Override |
1569 @Override |
1569 Type solve(UndetVar uv, InferenceContext inferenceContext) { |
1570 Type solve(UndetVar uv, InferenceContext inferenceContext) { |
1570 return inferenceContext.infer().syms.runtimeExceptionType; |
1571 return inferenceContext.infer.syms.runtimeExceptionType; |
1571 } |
1572 } |
1572 }, |
1573 }, |
1573 /** |
1574 /** |
1574 * Instantiate an inference variables using its (ground) upper bounds. Such |
1575 * Instantiate an inference variables using its (ground) upper bounds. Such |
1575 * bounds are merged together using glb(). |
1576 * bounds are merged together using glb(). |
1576 */ |
1577 */ |
1577 UPPER(InferenceBound.UPPER) { |
1578 UPPER(InferenceBound.UPPER) { |
1578 @Override |
1579 @Override |
1579 Type solve(UndetVar uv, InferenceContext inferenceContext) { |
1580 Type solve(UndetVar uv, InferenceContext inferenceContext) { |
1580 Infer infer = inferenceContext.infer(); |
1581 Infer infer = inferenceContext.infer; |
1581 List<Type> hibounds = filterBounds(uv, inferenceContext); |
1582 List<Type> hibounds = filterBounds(uv, inferenceContext); |
1582 //note: hibounds should have at least one element |
1583 //note: hibounds should have at least one element |
1583 Type owntype = hibounds.tail.tail == null ? hibounds.head : infer.types.glb(hibounds); |
1584 Type owntype = hibounds.tail.tail == null ? hibounds.head : infer.types.glb(hibounds); |
1584 if (owntype.isPrimitive() || owntype.hasTag(ERROR)) { |
1585 if (owntype.isPrimitive() || owntype.hasTag(ERROR)) { |
1585 throw infer.inferenceException |
1586 throw infer.inferenceException |
1616 !inferenceContext.free(t.getBounds(InferenceBound.UPPER, InferenceBound.LOWER)); |
1617 !inferenceContext.free(t.getBounds(InferenceBound.UPPER, InferenceBound.LOWER)); |
1617 } |
1618 } |
1618 |
1619 |
1619 @Override |
1620 @Override |
1620 Type solve(UndetVar uv, InferenceContext inferenceContext) { |
1621 Type solve(UndetVar uv, InferenceContext inferenceContext) { |
1621 Infer infer = inferenceContext.infer(); |
1622 Infer infer = inferenceContext.infer; |
1622 Type upper = UPPER.filterBounds(uv, inferenceContext).nonEmpty() ? |
1623 Type upper = UPPER.filterBounds(uv, inferenceContext).nonEmpty() ? |
1623 UPPER.solve(uv, inferenceContext) : |
1624 UPPER.solve(uv, inferenceContext) : |
1624 infer.syms.objectType; |
1625 infer.syms.objectType; |
1625 Type lower = LOWER.filterBounds(uv, inferenceContext).nonEmpty() ? |
1626 Type lower = LOWER.filterBounds(uv, inferenceContext).nonEmpty() ? |
1626 LOWER.solve(uv, inferenceContext) : |
1627 LOWER.solve(uv, inferenceContext) : |
2080 */ |
2081 */ |
2081 interface FreeTypeListener { |
2082 interface FreeTypeListener { |
2082 void typesInferred(InferenceContext inferenceContext); |
2083 void typesInferred(InferenceContext inferenceContext); |
2083 } |
2084 } |
2084 |
2085 |
2085 /** |
2086 final InferenceContext emptyContext; |
2086 * An inference context keeps track of the set of variables that are free |
|
2087 * in the current context. It provides utility methods for opening/closing |
|
2088 * types to their corresponding free/closed forms. It also provide hooks for |
|
2089 * attaching deferred post-inference action (see PendingCheck). Finally, |
|
2090 * it can be used as an entry point for performing upper/lower bound inference |
|
2091 * (see InferenceKind). |
|
2092 */ |
|
2093 class InferenceContext { |
|
2094 |
|
2095 /** list of inference vars as undet vars */ |
|
2096 List<Type> undetvars; |
|
2097 |
|
2098 /** list of inference vars in this context */ |
|
2099 List<Type> inferencevars; |
|
2100 |
|
2101 Map<FreeTypeListener, List<Type>> freeTypeListeners = new HashMap<>(); |
|
2102 |
|
2103 List<FreeTypeListener> freetypeListeners = List.nil(); |
|
2104 |
|
2105 public InferenceContext(List<Type> inferencevars) { |
|
2106 this.undetvars = inferencevars.map(fromTypeVarFun); |
|
2107 this.inferencevars = inferencevars; |
|
2108 } |
|
2109 //where |
|
2110 TypeMapping<Void> fromTypeVarFun = new TypeMapping<Void>() { |
|
2111 @Override |
|
2112 public Type visitTypeVar(TypeVar tv, Void aVoid) { |
|
2113 return new UndetVar(tv, types); |
|
2114 } |
|
2115 |
|
2116 @Override |
|
2117 public Type visitCapturedType(CapturedType t, Void aVoid) { |
|
2118 return new CapturedUndetVar(t, types); |
|
2119 } |
|
2120 }; |
|
2121 |
|
2122 /** |
|
2123 * add a new inference var to this inference context |
|
2124 */ |
|
2125 void addVar(TypeVar t) { |
|
2126 this.undetvars = this.undetvars.prepend(fromTypeVarFun.apply(t)); |
|
2127 this.inferencevars = this.inferencevars.prepend(t); |
|
2128 } |
|
2129 |
|
2130 /** |
|
2131 * returns the list of free variables (as type-variables) in this |
|
2132 * inference context |
|
2133 */ |
|
2134 List<Type> inferenceVars() { |
|
2135 return inferencevars; |
|
2136 } |
|
2137 |
|
2138 /** |
|
2139 * returns the list of uninstantiated variables (as type-variables) in this |
|
2140 * inference context |
|
2141 */ |
|
2142 List<Type> restvars() { |
|
2143 return filterVars(new Filter<UndetVar>() { |
|
2144 public boolean accepts(UndetVar uv) { |
|
2145 return uv.inst == null; |
|
2146 } |
|
2147 }); |
|
2148 } |
|
2149 |
|
2150 /** |
|
2151 * returns the list of instantiated variables (as type-variables) in this |
|
2152 * inference context |
|
2153 */ |
|
2154 List<Type> instvars() { |
|
2155 return filterVars(new Filter<UndetVar>() { |
|
2156 public boolean accepts(UndetVar uv) { |
|
2157 return uv.inst != null; |
|
2158 } |
|
2159 }); |
|
2160 } |
|
2161 |
|
2162 /** |
|
2163 * Get list of bounded inference variables (where bound is other than |
|
2164 * declared bounds). |
|
2165 */ |
|
2166 final List<Type> boundedVars() { |
|
2167 return filterVars(new Filter<UndetVar>() { |
|
2168 public boolean accepts(UndetVar uv) { |
|
2169 return uv.getBounds(InferenceBound.UPPER) |
|
2170 .diff(uv.getDeclaredBounds()) |
|
2171 .appendList(uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)).nonEmpty(); |
|
2172 } |
|
2173 }); |
|
2174 } |
|
2175 |
|
2176 /* Returns the corresponding inference variables. |
|
2177 */ |
|
2178 private List<Type> filterVars(Filter<UndetVar> fu) { |
|
2179 ListBuffer<Type> res = new ListBuffer<>(); |
|
2180 for (Type t : undetvars) { |
|
2181 UndetVar uv = (UndetVar)t; |
|
2182 if (fu.accepts(uv)) { |
|
2183 res.append(uv.qtype); |
|
2184 } |
|
2185 } |
|
2186 return res.toList(); |
|
2187 } |
|
2188 |
|
2189 /** |
|
2190 * is this type free? |
|
2191 */ |
|
2192 final boolean free(Type t) { |
|
2193 return t.containsAny(inferencevars); |
|
2194 } |
|
2195 |
|
2196 final boolean free(List<Type> ts) { |
|
2197 for (Type t : ts) { |
|
2198 if (free(t)) return true; |
|
2199 } |
|
2200 return false; |
|
2201 } |
|
2202 |
|
2203 /** |
|
2204 * Returns a list of free variables in a given type |
|
2205 */ |
|
2206 final List<Type> freeVarsIn(Type t) { |
|
2207 ListBuffer<Type> buf = new ListBuffer<>(); |
|
2208 for (Type iv : inferenceVars()) { |
|
2209 if (t.contains(iv)) { |
|
2210 buf.add(iv); |
|
2211 } |
|
2212 } |
|
2213 return buf.toList(); |
|
2214 } |
|
2215 |
|
2216 final List<Type> freeVarsIn(List<Type> ts) { |
|
2217 ListBuffer<Type> buf = new ListBuffer<>(); |
|
2218 for (Type t : ts) { |
|
2219 buf.appendList(freeVarsIn(t)); |
|
2220 } |
|
2221 ListBuffer<Type> buf2 = new ListBuffer<>(); |
|
2222 for (Type t : buf) { |
|
2223 if (!buf2.contains(t)) { |
|
2224 buf2.add(t); |
|
2225 } |
|
2226 } |
|
2227 return buf2.toList(); |
|
2228 } |
|
2229 |
|
2230 /** |
|
2231 * Replace all free variables in a given type with corresponding |
|
2232 * undet vars (used ahead of subtyping/compatibility checks to allow propagation |
|
2233 * of inference constraints). |
|
2234 */ |
|
2235 final Type asUndetVar(Type t) { |
|
2236 return types.subst(t, inferencevars, undetvars); |
|
2237 } |
|
2238 |
|
2239 final List<Type> asUndetVars(List<Type> ts) { |
|
2240 ListBuffer<Type> buf = new ListBuffer<>(); |
|
2241 for (Type t : ts) { |
|
2242 buf.append(asUndetVar(t)); |
|
2243 } |
|
2244 return buf.toList(); |
|
2245 } |
|
2246 |
|
2247 List<Type> instTypes() { |
|
2248 ListBuffer<Type> buf = new ListBuffer<>(); |
|
2249 for (Type t : undetvars) { |
|
2250 UndetVar uv = (UndetVar)t; |
|
2251 buf.append(uv.inst != null ? uv.inst : uv.qtype); |
|
2252 } |
|
2253 return buf.toList(); |
|
2254 } |
|
2255 |
|
2256 /** |
|
2257 * Replace all free variables in a given type with corresponding |
|
2258 * instantiated types - if one or more free variable has not been |
|
2259 * fully instantiated, it will still be available in the resulting type. |
|
2260 */ |
|
2261 Type asInstType(Type t) { |
|
2262 return types.subst(t, inferencevars, instTypes()); |
|
2263 } |
|
2264 |
|
2265 List<Type> asInstTypes(List<Type> ts) { |
|
2266 ListBuffer<Type> buf = new ListBuffer<>(); |
|
2267 for (Type t : ts) { |
|
2268 buf.append(asInstType(t)); |
|
2269 } |
|
2270 return buf.toList(); |
|
2271 } |
|
2272 |
|
2273 /** |
|
2274 * Add custom hook for performing post-inference action |
|
2275 */ |
|
2276 void addFreeTypeListener(List<Type> types, FreeTypeListener ftl) { |
|
2277 freeTypeListeners.put(ftl, freeVarsIn(types)); |
|
2278 } |
|
2279 |
|
2280 /** |
|
2281 * Mark the inference context as complete and trigger evaluation |
|
2282 * of all deferred checks. |
|
2283 */ |
|
2284 void notifyChange() { |
|
2285 notifyChange(inferencevars.diff(restvars())); |
|
2286 } |
|
2287 |
|
2288 void notifyChange(List<Type> inferredVars) { |
|
2289 InferenceException thrownEx = null; |
|
2290 for (Map.Entry<FreeTypeListener, List<Type>> entry : |
|
2291 new HashMap<>(freeTypeListeners).entrySet()) { |
|
2292 if (!Type.containsAny(entry.getValue(), inferencevars.diff(inferredVars))) { |
|
2293 try { |
|
2294 entry.getKey().typesInferred(this); |
|
2295 freeTypeListeners.remove(entry.getKey()); |
|
2296 } catch (InferenceException ex) { |
|
2297 if (thrownEx == null) { |
|
2298 thrownEx = ex; |
|
2299 } |
|
2300 } |
|
2301 } |
|
2302 } |
|
2303 //inference exception multiplexing - present any inference exception |
|
2304 //thrown when processing listeners as a single one |
|
2305 if (thrownEx != null) { |
|
2306 throw thrownEx; |
|
2307 } |
|
2308 } |
|
2309 |
|
2310 /** |
|
2311 * Save the state of this inference context |
|
2312 */ |
|
2313 List<Type> save() { |
|
2314 ListBuffer<Type> buf = new ListBuffer<>(); |
|
2315 for (Type t : undetvars) { |
|
2316 UndetVar uv = (UndetVar)t; |
|
2317 UndetVar uv2 = new UndetVar((TypeVar)uv.qtype, types); |
|
2318 for (InferenceBound ib : InferenceBound.values()) { |
|
2319 for (Type b : uv.getBounds(ib)) { |
|
2320 uv2.addBound(ib, b, types); |
|
2321 } |
|
2322 } |
|
2323 uv2.inst = uv.inst; |
|
2324 buf.add(uv2); |
|
2325 } |
|
2326 return buf.toList(); |
|
2327 } |
|
2328 |
|
2329 /** |
|
2330 * Restore the state of this inference context to the previous known checkpoint |
|
2331 */ |
|
2332 void rollback(List<Type> saved_undet) { |
|
2333 Assert.check(saved_undet != null && saved_undet.length() == undetvars.length()); |
|
2334 //restore bounds (note: we need to preserve the old instances) |
|
2335 for (Type t : undetvars) { |
|
2336 UndetVar uv = (UndetVar)t; |
|
2337 UndetVar uv_saved = (UndetVar)saved_undet.head; |
|
2338 for (InferenceBound ib : InferenceBound.values()) { |
|
2339 uv.setBounds(ib, uv_saved.getBounds(ib)); |
|
2340 } |
|
2341 uv.inst = uv_saved.inst; |
|
2342 saved_undet = saved_undet.tail; |
|
2343 } |
|
2344 } |
|
2345 |
|
2346 /** |
|
2347 * Copy variable in this inference context to the given context |
|
2348 */ |
|
2349 void dupTo(final InferenceContext that) { |
|
2350 that.inferencevars = that.inferencevars.appendList( |
|
2351 inferencevars.diff(that.inferencevars)); |
|
2352 that.undetvars = that.undetvars.appendList( |
|
2353 undetvars.diff(that.undetvars)); |
|
2354 //set up listeners to notify original inference contexts as |
|
2355 //propagated vars are inferred in new context |
|
2356 for (Type t : inferencevars) { |
|
2357 that.freeTypeListeners.put(new FreeTypeListener() { |
|
2358 public void typesInferred(InferenceContext inferenceContext) { |
|
2359 InferenceContext.this.notifyChange(); |
|
2360 } |
|
2361 }, List.of(t)); |
|
2362 } |
|
2363 } |
|
2364 |
|
2365 private void solve(GraphStrategy ss, Warner warn) { |
|
2366 solve(ss, new HashMap<Type, Set<Type>>(), warn); |
|
2367 } |
|
2368 |
|
2369 /** |
|
2370 * Solve with given graph strategy. |
|
2371 */ |
|
2372 private void solve(GraphStrategy ss, Map<Type, Set<Type>> stuckDeps, Warner warn) { |
|
2373 GraphSolver s = new GraphSolver(this, stuckDeps, warn); |
|
2374 s.solve(ss); |
|
2375 } |
|
2376 |
|
2377 /** |
|
2378 * Solve all variables in this context. |
|
2379 */ |
|
2380 public void solve(Warner warn) { |
|
2381 solve(new LeafSolver() { |
|
2382 public boolean done() { |
|
2383 return restvars().isEmpty(); |
|
2384 } |
|
2385 }, warn); |
|
2386 } |
|
2387 |
|
2388 /** |
|
2389 * Solve all variables in the given list. |
|
2390 */ |
|
2391 public void solve(final List<Type> vars, Warner warn) { |
|
2392 solve(new BestLeafSolver(vars) { |
|
2393 public boolean done() { |
|
2394 return !free(asInstTypes(vars)); |
|
2395 } |
|
2396 }, warn); |
|
2397 } |
|
2398 |
|
2399 /** |
|
2400 * Solve at least one variable in given list. |
|
2401 */ |
|
2402 public void solveAny(List<Type> varsToSolve, Map<Type, Set<Type>> optDeps, Warner warn) { |
|
2403 solve(new BestLeafSolver(varsToSolve.intersect(restvars())) { |
|
2404 public boolean done() { |
|
2405 return instvars().intersect(varsToSolve).nonEmpty(); |
|
2406 } |
|
2407 }, optDeps, warn); |
|
2408 } |
|
2409 |
|
2410 /** |
|
2411 * Apply a set of inference steps |
|
2412 */ |
|
2413 private boolean solveBasic(EnumSet<InferenceStep> steps) { |
|
2414 return solveBasic(inferencevars, steps); |
|
2415 } |
|
2416 |
|
2417 private boolean solveBasic(List<Type> varsToSolve, EnumSet<InferenceStep> steps) { |
|
2418 boolean changed = false; |
|
2419 for (Type t : varsToSolve.intersect(restvars())) { |
|
2420 UndetVar uv = (UndetVar)asUndetVar(t); |
|
2421 for (InferenceStep step : steps) { |
|
2422 if (step.accepts(uv, this)) { |
|
2423 uv.inst = step.solve(uv, this); |
|
2424 changed = true; |
|
2425 break; |
|
2426 } |
|
2427 } |
|
2428 } |
|
2429 return changed; |
|
2430 } |
|
2431 |
|
2432 /** |
|
2433 * Instantiate inference variables in legacy mode (JLS 15.12.2.7, 15.12.2.8). |
|
2434 * During overload resolution, instantiation is done by doing a partial |
|
2435 * inference process using eq/lower bound instantiation. During check, |
|
2436 * we also instantiate any remaining vars by repeatedly using eq/upper |
|
2437 * instantiation, until all variables are solved. |
|
2438 */ |
|
2439 public void solveLegacy(boolean partial, Warner warn, EnumSet<InferenceStep> steps) { |
|
2440 while (true) { |
|
2441 boolean stuck = !solveBasic(steps); |
|
2442 if (restvars().isEmpty() || partial) { |
|
2443 //all variables have been instantiated - exit |
|
2444 break; |
|
2445 } else if (stuck) { |
|
2446 //some variables could not be instantiated because of cycles in |
|
2447 //upper bounds - provide a (possibly recursive) default instantiation |
|
2448 instantiateAsUninferredVars(restvars(), this); |
|
2449 break; |
|
2450 } else { |
|
2451 //some variables have been instantiated - replace newly instantiated |
|
2452 //variables in remaining upper bounds and continue |
|
2453 for (Type t : undetvars) { |
|
2454 UndetVar uv = (UndetVar)t; |
|
2455 uv.substBounds(inferenceVars(), instTypes(), types); |
|
2456 } |
|
2457 } |
|
2458 } |
|
2459 checkWithinBounds(this, warn); |
|
2460 } |
|
2461 |
|
2462 private Infer infer() { |
|
2463 //back-door to infer |
|
2464 return Infer.this; |
|
2465 } |
|
2466 |
|
2467 @Override |
|
2468 public String toString() { |
|
2469 return "Inference vars: " + inferencevars + '\n' + |
|
2470 "Undet vars: " + undetvars; |
|
2471 } |
|
2472 |
|
2473 /* Method Types.capture() generates a new type every time it's applied |
|
2474 * to a wildcard parameterized type. This is intended functionality but |
|
2475 * there are some cases when what you need is not to generate a new |
|
2476 * captured type but to check that a previously generated captured type |
|
2477 * is correct. There are cases when caching a captured type for later |
|
2478 * reuse is sound. In general two captures from the same AST are equal. |
|
2479 * This is why the tree is used as the key of the map below. This map |
|
2480 * stores a Type per AST. |
|
2481 */ |
|
2482 Map<JCTree, Type> captureTypeCache = new HashMap<>(); |
|
2483 |
|
2484 Type cachedCapture(JCTree tree, Type t, boolean readOnly) { |
|
2485 Type captured = captureTypeCache.get(tree); |
|
2486 if (captured != null) { |
|
2487 return captured; |
|
2488 } |
|
2489 |
|
2490 Type result = types.capture(t); |
|
2491 if (result != t && !readOnly) { // then t is a wildcard parameterized type |
|
2492 captureTypeCache.put(tree, result); |
|
2493 } |
|
2494 return result; |
|
2495 } |
|
2496 } |
|
2497 |
|
2498 final InferenceContext emptyContext = new InferenceContext(List.<Type>nil()); |
|
2499 // </editor-fold> |
2087 // </editor-fold> |
2500 } |
2088 } |