src/share/classes/com/sun/tools/javac/code/Type.java

changeset 1550
1df20330f6bd
parent 1521
71f35e4b93a5
child 1628
5ddecb91d843
     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Type.java	Tue Feb 05 21:55:41 2013 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Type.java	Wed Feb 06 14:03:39 2013 +0000
     1.3 @@ -1309,6 +1309,9 @@
     1.4          /** inference variable's inferred type (set from Infer.java) */
     1.5          public Type inst = null;
     1.6  
     1.7 +        /** number of declared (upper) bounds */
     1.8 +        public int declaredCount;
     1.9 +
    1.10          /** inference variable's change listener */
    1.11          public UndetVarListener listener = null;
    1.12  
    1.13 @@ -1318,13 +1321,11 @@
    1.14          }
    1.15  
    1.16          public UndetVar(TypeVar origin, Types types) {
    1.17 -            this(origin, types, true);
    1.18 -        }
    1.19 -
    1.20 -        public UndetVar(TypeVar origin, Types types, boolean includeBounds) {
    1.21              super(UNDETVAR, origin);
    1.22              bounds = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class);
    1.23 -            bounds.put(InferenceBound.UPPER, includeBounds ? types.getBounds(origin) : List.<Type>nil());
    1.24 +            List<Type> declaredBounds = types.getBounds(origin);
    1.25 +            declaredCount = declaredBounds.length();
    1.26 +            bounds.put(InferenceBound.UPPER, declaredBounds);
    1.27              bounds.put(InferenceBound.LOWER, List.<Type>nil());
    1.28              bounds.put(InferenceBound.EQ, List.<Type>nil());
    1.29          }
    1.30 @@ -1340,38 +1341,89 @@
    1.31          }
    1.32  
    1.33          /** get all bounds of a given kind */
    1.34 -        public List<Type> getBounds(InferenceBound ib) {
    1.35 -            return bounds.get(ib);
    1.36 +        public List<Type> getBounds(InferenceBound... ibs) {
    1.37 +            ListBuffer<Type> buf = ListBuffer.lb();
    1.38 +            for (InferenceBound ib : ibs) {
    1.39 +                buf.appendList(bounds.get(ib));
    1.40 +            }
    1.41 +            return buf.toList();
    1.42 +        }
    1.43 +
    1.44 +        /** get the list of declared (upper) bounds */
    1.45 +        public List<Type> getDeclaredBounds() {
    1.46 +            ListBuffer<Type> buf = ListBuffer.lb();
    1.47 +            int count = 0;
    1.48 +            for (Type b : getBounds(InferenceBound.UPPER)) {
    1.49 +                if (count++ == declaredCount) break;
    1.50 +                buf.append(b);
    1.51 +            }
    1.52 +            return buf.toList();
    1.53          }
    1.54  
    1.55          /** add a bound of a given kind - this might trigger listener notification */
    1.56          public void addBound(InferenceBound ib, Type bound, Types types) {
    1.57 +            Type bound2 = toTypeVarMap.apply(bound);
    1.58              List<Type> prevBounds = bounds.get(ib);
    1.59              for (Type b : prevBounds) {
    1.60 -                if (types.isSameType(b, bound)) {
    1.61 -                    return;
    1.62 -                }
    1.63 +                //check for redundancy - use strict version of isSameType on tvars
    1.64 +                //(as the standard version will lead to false positives w.r.t. clones ivars)
    1.65 +                if (types.isSameType(b, bound2, true)) return;
    1.66              }
    1.67 -            bounds.put(ib, prevBounds.prepend(bound));
    1.68 +            bounds.put(ib, prevBounds.prepend(bound2));
    1.69              notifyChange(EnumSet.of(ib));
    1.70          }
    1.71 +        //where
    1.72 +            Type.Mapping toTypeVarMap = new Mapping("toTypeVarMap") {
    1.73 +                @Override
    1.74 +                public Type apply(Type t) {
    1.75 +                    if (t.hasTag(UNDETVAR)) {
    1.76 +                        UndetVar uv = (UndetVar)t;
    1.77 +                        return uv.qtype;
    1.78 +                    } else {
    1.79 +                        return t.map(this);
    1.80 +                    }
    1.81 +                }
    1.82 +            };
    1.83  
    1.84          /** replace types in all bounds - this might trigger listener notification */
    1.85          public void substBounds(List<Type> from, List<Type> to, Types types) {
    1.86 -            EnumSet<InferenceBound> changed = EnumSet.noneOf(InferenceBound.class);
    1.87 -            Map<InferenceBound, List<Type>> bounds2 = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class);
    1.88 -            for (Map.Entry<InferenceBound, List<Type>> _entry : bounds.entrySet()) {
    1.89 -                InferenceBound ib = _entry.getKey();
    1.90 -                List<Type> prevBounds = _entry.getValue();
    1.91 -                List<Type> newBounds = types.subst(prevBounds, from, to);
    1.92 -                bounds2.put(ib, newBounds);
    1.93 -                if (prevBounds != newBounds) {
    1.94 -                    changed.add(ib);
    1.95 +            List<Type> instVars = from.diff(to);
    1.96 +            //if set of instantiated ivars is empty, there's nothing to do!
    1.97 +            if (instVars.isEmpty()) return;
    1.98 +            final EnumSet<InferenceBound> boundsChanged = EnumSet.noneOf(InferenceBound.class);
    1.99 +            UndetVarListener prevListener = listener;
   1.100 +            try {
   1.101 +                //setup new listener for keeping track of changed bounds
   1.102 +                listener = new UndetVarListener() {
   1.103 +                    public void varChanged(UndetVar uv, Set<InferenceBound> ibs) {
   1.104 +                        boundsChanged.addAll(ibs);
   1.105 +                    }
   1.106 +                };
   1.107 +                for (Map.Entry<InferenceBound, List<Type>> _entry : bounds.entrySet()) {
   1.108 +                    InferenceBound ib = _entry.getKey();
   1.109 +                    List<Type> prevBounds = _entry.getValue();
   1.110 +                    ListBuffer<Type> newBounds = ListBuffer.lb();
   1.111 +                    ListBuffer<Type> deps = ListBuffer.lb();
   1.112 +                    //step 1 - re-add bounds that are not dependent on ivars
   1.113 +                    for (Type t : prevBounds) {
   1.114 +                        if (!t.containsAny(instVars)) {
   1.115 +                            newBounds.append(t);
   1.116 +                        } else {
   1.117 +                            deps.append(t);
   1.118 +                        }
   1.119 +                    }
   1.120 +                    //step 2 - replace bounds
   1.121 +                    bounds.put(ib, newBounds.toList());
   1.122 +                    //step 3 - for each dependency, add new replaced bound
   1.123 +                    for (Type dep : deps) {
   1.124 +                        addBound(ib, types.subst(dep, from, to), types);
   1.125 +                    }
   1.126                  }
   1.127 -            }
   1.128 -            if (!changed.isEmpty()) {
   1.129 -                bounds = bounds2;
   1.130 -                notifyChange(changed);
   1.131 +            } finally {
   1.132 +                listener = prevListener;
   1.133 +                if (!boundsChanged.isEmpty()) {
   1.134 +                    notifyChange(boundsChanged);
   1.135 +                }
   1.136              }
   1.137          }
   1.138  

mercurial