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

changeset 1571
af8417e590f4
parent 1550
1df20330f6bd
child 1628
5ddecb91d843
equal deleted inserted replaced
1570:f91144b7da75 1571:af8417e590f4
1307 private Map<InferenceBound, List<Type>> bounds; 1307 private Map<InferenceBound, List<Type>> bounds;
1308 1308
1309 /** inference variable's inferred type (set from Infer.java) */ 1309 /** inference variable's inferred type (set from Infer.java) */
1310 public Type inst = null; 1310 public Type inst = null;
1311 1311
1312 /** number of declared (upper) bounds */
1313 public int declaredCount;
1314
1312 /** inference variable's change listener */ 1315 /** inference variable's change listener */
1313 public UndetVarListener listener = null; 1316 public UndetVarListener listener = null;
1314 1317
1315 @Override 1318 @Override
1316 public <R,S> R accept(Type.Visitor<R,S> v, S s) { 1319 public <R,S> R accept(Type.Visitor<R,S> v, S s) {
1317 return v.visitUndetVar(this, s); 1320 return v.visitUndetVar(this, s);
1318 } 1321 }
1319 1322
1320 public UndetVar(TypeVar origin, Types types) { 1323 public UndetVar(TypeVar origin, Types types) {
1321 this(origin, types, true);
1322 }
1323
1324 public UndetVar(TypeVar origin, Types types, boolean includeBounds) {
1325 super(UNDETVAR, origin); 1324 super(UNDETVAR, origin);
1326 bounds = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class); 1325 bounds = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class);
1327 bounds.put(InferenceBound.UPPER, includeBounds ? types.getBounds(origin) : List.<Type>nil()); 1326 List<Type> declaredBounds = types.getBounds(origin);
1327 declaredCount = declaredBounds.length();
1328 bounds.put(InferenceBound.UPPER, declaredBounds);
1328 bounds.put(InferenceBound.LOWER, List.<Type>nil()); 1329 bounds.put(InferenceBound.LOWER, List.<Type>nil());
1329 bounds.put(InferenceBound.EQ, List.<Type>nil()); 1330 bounds.put(InferenceBound.EQ, List.<Type>nil());
1330 } 1331 }
1331 1332
1332 public String toString() { 1333 public String toString() {
1338 if (inst != null) return inst.baseType(); 1339 if (inst != null) return inst.baseType();
1339 else return this; 1340 else return this;
1340 } 1341 }
1341 1342
1342 /** get all bounds of a given kind */ 1343 /** get all bounds of a given kind */
1343 public List<Type> getBounds(InferenceBound ib) { 1344 public List<Type> getBounds(InferenceBound... ibs) {
1344 return bounds.get(ib); 1345 ListBuffer<Type> buf = ListBuffer.lb();
1346 for (InferenceBound ib : ibs) {
1347 buf.appendList(bounds.get(ib));
1348 }
1349 return buf.toList();
1350 }
1351
1352 /** get the list of declared (upper) bounds */
1353 public List<Type> getDeclaredBounds() {
1354 ListBuffer<Type> buf = ListBuffer.lb();
1355 int count = 0;
1356 for (Type b : getBounds(InferenceBound.UPPER)) {
1357 if (count++ == declaredCount) break;
1358 buf.append(b);
1359 }
1360 return buf.toList();
1345 } 1361 }
1346 1362
1347 /** add a bound of a given kind - this might trigger listener notification */ 1363 /** add a bound of a given kind - this might trigger listener notification */
1348 public void addBound(InferenceBound ib, Type bound, Types types) { 1364 public void addBound(InferenceBound ib, Type bound, Types types) {
1365 Type bound2 = toTypeVarMap.apply(bound);
1349 List<Type> prevBounds = bounds.get(ib); 1366 List<Type> prevBounds = bounds.get(ib);
1350 for (Type b : prevBounds) { 1367 for (Type b : prevBounds) {
1351 if (types.isSameType(b, bound)) { 1368 //check for redundancy - use strict version of isSameType on tvars
1352 return; 1369 //(as the standard version will lead to false positives w.r.t. clones ivars)
1370 if (types.isSameType(b, bound2, true)) return;
1371 }
1372 bounds.put(ib, prevBounds.prepend(bound2));
1373 notifyChange(EnumSet.of(ib));
1374 }
1375 //where
1376 Type.Mapping toTypeVarMap = new Mapping("toTypeVarMap") {
1377 @Override
1378 public Type apply(Type t) {
1379 if (t.hasTag(UNDETVAR)) {
1380 UndetVar uv = (UndetVar)t;
1381 return uv.qtype;
1382 } else {
1383 return t.map(this);
1384 }
1353 } 1385 }
1354 } 1386 };
1355 bounds.put(ib, prevBounds.prepend(bound));
1356 notifyChange(EnumSet.of(ib));
1357 }
1358 1387
1359 /** replace types in all bounds - this might trigger listener notification */ 1388 /** replace types in all bounds - this might trigger listener notification */
1360 public void substBounds(List<Type> from, List<Type> to, Types types) { 1389 public void substBounds(List<Type> from, List<Type> to, Types types) {
1361 EnumSet<InferenceBound> changed = EnumSet.noneOf(InferenceBound.class); 1390 List<Type> instVars = from.diff(to);
1362 Map<InferenceBound, List<Type>> bounds2 = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class); 1391 //if set of instantiated ivars is empty, there's nothing to do!
1363 for (Map.Entry<InferenceBound, List<Type>> _entry : bounds.entrySet()) { 1392 if (instVars.isEmpty()) return;
1364 InferenceBound ib = _entry.getKey(); 1393 final EnumSet<InferenceBound> boundsChanged = EnumSet.noneOf(InferenceBound.class);
1365 List<Type> prevBounds = _entry.getValue(); 1394 UndetVarListener prevListener = listener;
1366 List<Type> newBounds = types.subst(prevBounds, from, to); 1395 try {
1367 bounds2.put(ib, newBounds); 1396 //setup new listener for keeping track of changed bounds
1368 if (prevBounds != newBounds) { 1397 listener = new UndetVarListener() {
1369 changed.add(ib); 1398 public void varChanged(UndetVar uv, Set<InferenceBound> ibs) {
1399 boundsChanged.addAll(ibs);
1400 }
1401 };
1402 for (Map.Entry<InferenceBound, List<Type>> _entry : bounds.entrySet()) {
1403 InferenceBound ib = _entry.getKey();
1404 List<Type> prevBounds = _entry.getValue();
1405 ListBuffer<Type> newBounds = ListBuffer.lb();
1406 ListBuffer<Type> deps = ListBuffer.lb();
1407 //step 1 - re-add bounds that are not dependent on ivars
1408 for (Type t : prevBounds) {
1409 if (!t.containsAny(instVars)) {
1410 newBounds.append(t);
1411 } else {
1412 deps.append(t);
1413 }
1414 }
1415 //step 2 - replace bounds
1416 bounds.put(ib, newBounds.toList());
1417 //step 3 - for each dependency, add new replaced bound
1418 for (Type dep : deps) {
1419 addBound(ib, types.subst(dep, from, to), types);
1420 }
1370 } 1421 }
1371 } 1422 } finally {
1372 if (!changed.isEmpty()) { 1423 listener = prevListener;
1373 bounds = bounds2; 1424 if (!boundsChanged.isEmpty()) {
1374 notifyChange(changed); 1425 notifyChange(boundsChanged);
1426 }
1375 } 1427 }
1376 } 1428 }
1377 1429
1378 private void notifyChange(EnumSet<InferenceBound> ibs) { 1430 private void notifyChange(EnumSet<InferenceBound> ibs) {
1379 if (listener != null) { 1431 if (listener != null) {

mercurial