< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java

Print this page

 186      */
 187     public Type skipTypeVars(Type site, boolean capture) {
 188         while (site.hasTag(TYPEVAR)) {
 189             site = site.getUpperBound();
 190         }
 191         return capture ? capture(site) : site;
 192     }
 193     // </editor-fold>
 194 
 195     // <editor-fold defaultstate="collapsed" desc="projections">
 196 
 197     /**
 198      * A projection kind. See {@link TypeProjection}
 199      */
 200     enum ProjectionKind {
 201         UPWARDS() {
 202             @Override
 203             ProjectionKind complement() {
 204                 return DOWNWARDS;
 205             }










 206         },
 207         DOWNWARDS() {
 208             @Override
 209             ProjectionKind complement() {
 210                 return UPWARDS;
 211             }










































 212         };
 213 
 214         abstract ProjectionKind complement();


 215     }
 216 
 217     /**
 218      * This visitor performs upwards and downwards projections on types.
 219      *
 220      * A projection is defined as a function that takes a type T, a set of type variables V and that
 221      * produces another type S.
 222      *
 223      * An upwards projection maps a type T into a type S such that (i) T has no variables in V,
 224      * and (ii) S is an upper bound of T.
 225      *
 226      * A downwards projection maps a type T into a type S such that (i) T has no variables in V,
 227      * and (ii) S is a lower bound of T.
 228      *
 229      * Note that projections are only allowed to touch variables in V. Therefore, it is possible for
 230      * a projection to leave its input type unchanged if it does not contain any variables in V.
 231      *
 232      * Moreover, note that while an upwards projection is always defined (every type as an upper bound),
 233      * a downwards projection is not always defined.
 234      *
 235      * Examples:
 236      *
 237      * {@code upwards(List<#CAP1>, [#CAP1]) = List<? extends String>, where #CAP1 <: String }
 238      * {@code downwards(List<#CAP2>, [#CAP2]) = List<? super String>, where #CAP2 :> String }
 239      * {@code upwards(List<#CAP1>, [#CAP2]) = List<#CAP1> }
 240      * {@code downwards(List<#CAP1>, [#CAP1]) = not defined }
 241      */
 242     class TypeProjection extends TypeMapping<ProjectionKind> {
 243 
 244         List<Type> vars;
 245         Set<Type> seen = new HashSet<>();
 246 
 247         public TypeProjection(List<Type> vars) {
 248             this.vars = vars;
 249         }
 250 
 251         @Override
 252         public Type visitClassType(ClassType t, ProjectionKind pkind) {
 253             if (t.isCompound()) {
 254                 List<Type> components = directSupertypes(t);
 255                 List<Type> components1 = components.map(c -> c.map(this, pkind));
 256                 if (components == components1) return t;
 257                 else return makeIntersectionType(components1);







 258             } else {
 259                 Type outer = t.getEnclosingType();
 260                 Type outer1 = visit(outer, pkind);
 261                 List<Type> typarams = t.getTypeArguments();
 262                 List<Type> formals = t.tsym.type.getTypeArguments();
 263                 ListBuffer<Type> typarams1 = new ListBuffer<>();
 264                 boolean changed = false;
 265                 for (Type actual : typarams) {
 266                     Type t2 = mapTypeArgument(t, formals.head.getUpperBound(), actual, pkind);
 267                     if (t2.hasTag(BOT)) {
 268                         //not defined
 269                         return syms.botType;
 270                     }
 271                     typarams1.add(t2);
 272                     changed |= actual != t2;
 273                     formals = formals.tail;
 274                 }
 275                 if (outer1 == outer && !changed) return t;
 276                 else return new ClassType(outer1, typarams1.toList(), t.tsym, t.getMetadata()) {
 277                     @Override

 292                 //undefined
 293                 return syms.botType;
 294             } else {
 295                 return new ArrayType(elemtype1, t.tsym, t.metadata) {
 296                     @Override
 297                     protected boolean needsStripping() {
 298                         return true;
 299                     }
 300                 };
 301             }
 302         }
 303 
 304         @Override
 305         public Type visitTypeVar(TypeVar t, ProjectionKind pkind) {
 306             if (vars.contains(t)) {
 307                 if (seen.add(t)) {
 308                     try {
 309                         final Type bound;
 310                         switch (pkind) {
 311                             case UPWARDS:

 312                                 bound = t.getUpperBound();
 313                                 break;
 314                             case DOWNWARDS:

 315                                 bound = (t.getLowerBound() == null) ?
 316                                         syms.botType :
 317                                         t.getLowerBound();
 318                                 break;
 319                             default:
 320                                 Assert.error();
 321                                 return null;
 322                         }
 323                         return bound.map(this, pkind);
 324                     } finally {
 325                         seen.remove(t);
 326                     }
 327                 } else {
 328                     //cycle
 329                     return pkind == ProjectionKind.UPWARDS ?
 330                             syms.objectType : syms.botType;
 331                 }
 332             } else {
 333                 return t;
 334             }
 335         }
 336 
 337         private Type mapTypeArgument(Type site, Type declaredBound, Type t, ProjectionKind pkind) {
 338             return t.containsAny(vars) ?
 339                     t.map(new TypeArgumentProjection(site, declaredBound), pkind) :
 340                     t;
 341         }
 342 
 343         class TypeArgumentProjection extends TypeMapping<ProjectionKind> {
 344 
 345             Type site;
 346             Type declaredBound;
 347 
 348             TypeArgumentProjection(Type site, Type declaredBound) {
 349                 this.site = site;
 350                 this.declaredBound = declaredBound;
 351             }
 352 
 353             @Override
 354             public Type visitType(Type t, ProjectionKind pkind) {
 355                 //type argument is some type containing restricted vars
 356                 if (pkind == ProjectionKind.DOWNWARDS) {
 357                     //not defined
 358                     return syms.botType;
 359                 }
 360                 Type upper = t.map(TypeProjection.this, ProjectionKind.UPWARDS);
 361                 Type lower = t.map(TypeProjection.this, ProjectionKind.DOWNWARDS);
 362                 List<Type> formals = site.tsym.type.getTypeArguments();
 363                 BoundKind bk;
 364                 Type bound;
 365                 if (!isSameType(upper, syms.objectType) &&
 366                         (declaredBound.containsAny(formals) ||
 367                          !isSubtype(declaredBound, upper))) {
 368                     bound = upper;
 369                     bk = EXTENDS;
 370                 } else if (!lower.hasTag(BOT)) {
 371                     bound = lower;
 372                     bk = SUPER;
 373                 } else {
 374                     bound = syms.objectType;
 375                     bk = UNBOUND;
 376                 }
 377                 return makeWildcard(bound, bk);
 378             }
 379 
 380             @Override
 381             public Type visitWildcardType(WildcardType wt, ProjectionKind pkind) {
 382                 //type argument is some wildcard whose bound contains restricted vars
 383                 Type bound = syms.botType;
 384                 BoundKind bk = wt.kind;
 385                 switch (wt.kind) {
 386                     case EXTENDS:
 387                         bound = wt.type.map(TypeProjection.this, pkind);
 388                         if (bound.hasTag(BOT)) {
 389                             return syms.botType;
 390                         }
 391                         break;
 392                     case SUPER:
 393                         bound = wt.type.map(TypeProjection.this, pkind.complement());
 394                         if (bound.hasTag(BOT)) {
 395                             bound = syms.objectType;
 396                             bk = UNBOUND;
 397                         }
 398                         break;
 399                 }
 400                 return makeWildcard(bound, bk);
 401             }
 402 
 403             private Type makeWildcard(Type bound, BoundKind bk) {
 404                 return new WildcardType(bound, bk, syms.boundClass) {
 405                     @Override
 406                     protected boolean needsStripping() {
 407                         return true;
 408                     }
 409                 };
 410             }
 411         }
 412     }
 413 
 414     /**
 415      * Computes an upward projection of given type, and vars. See {@link TypeProjection}.
 416      *
 417      * @param t the type to be projected
 418      * @param vars the set of type variables to be mapped
 419      * @return the type obtained as result of the projection
 420      */
 421     public Type upward(Type t, List<Type> vars) {
 422         return t.map(new TypeProjection(vars), ProjectionKind.UPWARDS);













 423     }
 424 
 425     /**
 426      * Computes the set of captured variables mentioned in a given type. See {@link CaptureScanner}.
 427      * This routine is typically used to computed the input set of variables to be used during
 428      * an upwards projection (see {@link Types#upward(Type, List)}).
 429      *
 430      * @param t the type where occurrences of captured variables have to be found
 431      * @return the set of captured variables found in t
 432      */
 433     public List<Type> captures(Type t) {
 434         CaptureScanner cs = new CaptureScanner();
 435         Set<Type> captures = new HashSet<>();
 436         cs.visit(t, captures);
 437         return List.from(captures);
 438     }
 439 
 440     /**
 441      * This visitor scans a type recursively looking for occurrences of captured type variables.
 442      */

5317                 return syms.doubleType;
5318             case ClassFile.CONSTANT_MethodHandle:
5319                 return syms.methodHandleType;
5320             case ClassFile.CONSTANT_MethodType:
5321                 return syms.methodTypeType;
5322             case ClassFile.CONSTANT_Dynamic:
5323                 return ((DynamicVarSymbol)c).type;
5324             default:
5325                 throw new AssertionError("Not a loadable constant: " + c.poolTag());
5326         }
5327     }
5328     // </editor-fold>
5329 
5330     public void newRound() {
5331         descCache._map.clear();
5332         isDerivedRawCache.clear();
5333         implCache._map.clear();
5334         membersCache._map.clear();
5335         closureCache.clear();
5336     }
























5337 }

 186      */
 187     public Type skipTypeVars(Type site, boolean capture) {
 188         while (site.hasTag(TYPEVAR)) {
 189             site = site.getUpperBound();
 190         }
 191         return capture ? capture(site) : site;
 192     }
 193     // </editor-fold>
 194 
 195     // <editor-fold defaultstate="collapsed" desc="projections">
 196 
 197     /**
 198      * A projection kind. See {@link TypeProjection}
 199      */
 200     enum ProjectionKind {
 201         UPWARDS() {
 202             @Override
 203             ProjectionKind complement() {
 204                 return DOWNWARDS;
 205             }
 206 
 207             @Override
 208             boolean allowIntersectionTypes() {
 209                 return true;
 210             }
 211 
 212             @Override
 213             ProjectionKind withIntersectionTypes(boolean allowIntersectionTypes) {
 214                 return allowIntersectionTypes ? this : UPWARDS_NO_INTERSECTION;
 215             }
 216         },
 217         DOWNWARDS() {
 218             @Override
 219             ProjectionKind complement() {
 220                 return UPWARDS;
 221             }
 222 
 223             @Override
 224             boolean allowIntersectionTypes() {
 225                 return true;
 226             }
 227 
 228             @Override
 229             ProjectionKind withIntersectionTypes(boolean allowIntersectionTypes) {
 230                 return allowIntersectionTypes ? this : DOWNWARDS_NO_INTERSECTION;
 231             }
 232         },
 233         UPWARDS_NO_INTERSECTION() {
 234             @Override
 235             ProjectionKind complement() {
 236                 return DOWNWARDS_NO_INTERSECTION;
 237             }
 238 
 239             @Override
 240             boolean allowIntersectionTypes() {
 241                 return false;
 242             }
 243 
 244             @Override
 245             ProjectionKind withIntersectionTypes(boolean allowIntersectionTypes) {
 246                 return allowIntersectionTypes ? UPWARDS : this;
 247             }
 248         },
 249         DOWNWARDS_NO_INTERSECTION() {
 250             @Override
 251             ProjectionKind complement() {
 252                 return UPWARDS_NO_INTERSECTION;
 253             }
 254 
 255             @Override
 256             boolean allowIntersectionTypes() {
 257                 return false;
 258             }
 259 
 260             @Override
 261             ProjectionKind withIntersectionTypes(boolean allowIntersectionTypes) {
 262                 return allowIntersectionTypes ? DOWNWARDS : this;
 263             }
 264         };
 265 
 266         abstract ProjectionKind complement();
 267         abstract boolean allowIntersectionTypes();
 268         abstract ProjectionKind withIntersectionTypes(boolean allowIntersectionTypes);
 269     }
 270 
 271     /**
 272      * This visitor performs upwards and downwards projections on types.
 273      *
 274      * A projection is defined as a function that takes a type T, a set of type variables V and that
 275      * produces another type S.
 276      *
 277      * An upwards projection maps a type T into a type S such that (i) T has no variables in V,
 278      * and (ii) S is an upper bound of T.
 279      *
 280      * A downwards projection maps a type T into a type S such that (i) T has no variables in V,
 281      * and (ii) S is a lower bound of T.
 282      *
 283      * Note that projections are only allowed to touch variables in V. Therefore, it is possible for
 284      * a projection to leave its input type unchanged if it does not contain any variables in V.
 285      *
 286      * Moreover, note that while an upwards projection is always defined (every type as an upper bound),
 287      * a downwards projection is not always defined.
 288      *
 289      * Examples:
 290      *
 291      * {@code upwards(List<#CAP1>, [#CAP1]) = List<? extends String>, where #CAP1 <: String }
 292      * {@code downwards(List<#CAP2>, [#CAP2]) = List<? super String>, where #CAP2 :> String }
 293      * {@code upwards(List<#CAP1>, [#CAP2]) = List<#CAP1> }
 294      * {@code downwards(List<#CAP1>, [#CAP1]) = not defined }
 295      */
 296     class TypeProjection extends TypeMapping<ProjectionKind> {
 297 
 298         List<Type> vars;
 299         Set<Type> seen = new HashSet<>();
 300 
 301         public TypeProjection(List<Type> vars) {
 302             this.vars = vars;
 303         }
 304 
 305         @Override
 306         public Type visitClassType(ClassType t, ProjectionKind pkind) {
 307             if (t.isUnion() || t.isIntersection()) {
 308                 if (pkind.allowIntersectionTypes()) {
 309                     List<Type> components = directSupertypes(t);
 310                     List<Type> components1 = components.map(c -> c.map(this, pkind));
 311                     if (components == components1) return t;
 312                     else return makeIntersectionType(components1);
 313                 } else if (t.isIntersection()) {
 314                     return visit(((IntersectionClassType)t).getExplicitComponents().head, pkind);
 315                 } else {
 316                     Assert.check(t.isUnion());
 317                     return visit(((UnionClassType)t).getLub(), pkind);
 318                 }
 319             } else {
 320                 Type outer = t.getEnclosingType();
 321                 Type outer1 = visit(outer, pkind);
 322                 List<Type> typarams = t.getTypeArguments();
 323                 List<Type> formals = t.tsym.type.getTypeArguments();
 324                 ListBuffer<Type> typarams1 = new ListBuffer<>();
 325                 boolean changed = false;
 326                 for (Type actual : typarams) {
 327                     Type t2 = mapTypeArgument(t, formals.head.getUpperBound(), actual, pkind);
 328                     if (t2.hasTag(BOT)) {
 329                         //not defined
 330                         return syms.botType;
 331                     }
 332                     typarams1.add(t2);
 333                     changed |= actual != t2;
 334                     formals = formals.tail;
 335                 }
 336                 if (outer1 == outer && !changed) return t;
 337                 else return new ClassType(outer1, typarams1.toList(), t.tsym, t.getMetadata()) {
 338                     @Override

 353                 //undefined
 354                 return syms.botType;
 355             } else {
 356                 return new ArrayType(elemtype1, t.tsym, t.metadata) {
 357                     @Override
 358                     protected boolean needsStripping() {
 359                         return true;
 360                     }
 361                 };
 362             }
 363         }
 364 
 365         @Override
 366         public Type visitTypeVar(TypeVar t, ProjectionKind pkind) {
 367             if (vars.contains(t)) {
 368                 if (seen.add(t)) {
 369                     try {
 370                         final Type bound;
 371                         switch (pkind) {
 372                             case UPWARDS:
 373                             case UPWARDS_NO_INTERSECTION:
 374                                 bound = t.getUpperBound();
 375                                 break;
 376                             case DOWNWARDS:
 377                             case DOWNWARDS_NO_INTERSECTION:
 378                                 bound = (t.getLowerBound() == null) ?
 379                                         syms.botType :
 380                                         t.getLowerBound();
 381                                 break;
 382                             default:
 383                                 Assert.error();
 384                                 return null;
 385                         }
 386                         return bound.map(this, pkind);
 387                     } finally {
 388                         seen.remove(t);
 389                     }
 390                 } else {
 391                     //cycle
 392                     return (pkind == ProjectionKind.UPWARDS || pkind == ProjectionKind.UPWARDS_NO_INTERSECTION) ?
 393                             syms.objectType : syms.botType;
 394                 }
 395             } else {
 396                 return t;
 397             }
 398         }
 399 
 400         private Type mapTypeArgument(Type site, Type declaredBound, Type t, ProjectionKind pkind) {
 401             return (t.containsAny(vars) || (!pkind.allowIntersectionTypes() && !chk.checkDenotable(t))) ?
 402                     t.map(new TypeArgumentProjection(site, declaredBound), pkind) :
 403                     t;
 404         }
 405 
 406         class TypeArgumentProjection extends TypeMapping<ProjectionKind> {
 407 
 408             Type site;
 409             Type declaredBound;
 410 
 411             TypeArgumentProjection(Type site, Type declaredBound) {
 412                 this.site = site;
 413                 this.declaredBound = declaredBound;
 414             }
 415 
 416             @Override
 417             public Type visitType(Type t, ProjectionKind pkind) {
 418                 //type argument is some type containing restricted vars
 419                 if (pkind == ProjectionKind.DOWNWARDS || pkind == ProjectionKind.DOWNWARDS_NO_INTERSECTION) {
 420                     //not defined
 421                     return syms.botType;
 422                 }
 423                 Type upper = t.map(TypeProjection.this, ProjectionKind.UPWARDS.withIntersectionTypes(pkind.allowIntersectionTypes()));
 424                 Type lower = t.map(TypeProjection.this, ProjectionKind.DOWNWARDS);
 425                 List<Type> formals = site.tsym.type.getTypeArguments();
 426                 BoundKind bk;
 427                 Type bound;
 428                 if (!isSameType(upper, syms.objectType) &&
 429                         (declaredBound.containsAny(formals) ||
 430                          !isSubtype(declaredBound, upper))) {
 431                     bound = upper;
 432                     bk = EXTENDS;
 433                 } else if (!lower.hasTag(BOT) && (!lower.isIntersection() || pkind.allowIntersectionTypes())) {
 434                     bound = lower;
 435                     bk = SUPER;
 436                 } else {
 437                     bound = syms.objectType;
 438                     bk = UNBOUND;
 439                 }
 440                 return makeWildcard(bound, bk);
 441             }
 442 
 443             @Override
 444             public Type visitWildcardType(WildcardType wt, ProjectionKind pkind) {
 445                 //type argument is some wildcard whose bound contains restricted vars
 446                 Type bound = syms.botType;
 447                 BoundKind bk = wt.kind;
 448                 switch (wt.kind) {
 449                     case EXTENDS:
 450                         bound = wt.type.map(TypeProjection.this, pkind);
 451                         if (bound.hasTag(BOT)) {
 452                             return syms.botType;
 453                         }
 454                         break;
 455                     case SUPER:
 456                         bound = wt.type.map(TypeProjection.this, pkind.withIntersectionTypes(true).complement());
 457                         if (bound.hasTag(BOT) || (bound.isIntersection() && !pkind.allowIntersectionTypes())) {
 458                             bound = syms.objectType;
 459                             bk = UNBOUND;
 460                         }
 461                         break;
 462                 }
 463                 return makeWildcard(bound, bk);
 464             }
 465 
 466             private Type makeWildcard(Type bound, BoundKind bk) {
 467                 return new WildcardType(bound, bk, syms.boundClass) {
 468                     @Override
 469                     protected boolean needsStripping() {
 470                         return true;
 471                     }
 472                 };
 473             }
 474         }
 475     }
 476 
 477     /**
 478      * Computes an upward projection of given type, and vars. See {@link TypeProjection}.
 479      *
 480      * @param t the type to be projected
 481      * @param vars the set of type variables to be mapped
 482      * @return the type obtained as result of the projection
 483      */
 484     public Type upward(Type t, List<Type> vars) {
 485         return upward(t, true, vars);
 486     }
 487 
 488     /**
 489      * Computes an upward projection of given type, and vars. See {@link TypeProjection}.
 490      *
 491      * @param t the type to be projected
 492      * @param allowIntersection whether intersection types should be allowed in the projection
 493      * @param vars the set of type variables to be mapped
 494      * @return the type obtained as result of the projection
 495      */
 496     public Type upward(Type t, boolean allowIntersection, List<Type> vars) {
 497         return t.map(new TypeProjection(vars),
 498                 allowIntersection ? ProjectionKind.UPWARDS : ProjectionKind.UPWARDS_NO_INTERSECTION);
 499     }
 500 
 501     /**
 502      * Computes the set of captured variables mentioned in a given type. See {@link CaptureScanner}.
 503      * This routine is typically used to computed the input set of variables to be used during
 504      * an upwards projection (see {@link Types#upward(Type, List)}).
 505      *
 506      * @param t the type where occurrences of captured variables have to be found
 507      * @return the set of captured variables found in t
 508      */
 509     public List<Type> captures(Type t) {
 510         CaptureScanner cs = new CaptureScanner();
 511         Set<Type> captures = new HashSet<>();
 512         cs.visit(t, captures);
 513         return List.from(captures);
 514     }
 515 
 516     /**
 517      * This visitor scans a type recursively looking for occurrences of captured type variables.
 518      */

5393                 return syms.doubleType;
5394             case ClassFile.CONSTANT_MethodHandle:
5395                 return syms.methodHandleType;
5396             case ClassFile.CONSTANT_MethodType:
5397                 return syms.methodTypeType;
5398             case ClassFile.CONSTANT_Dynamic:
5399                 return ((DynamicVarSymbol)c).type;
5400             default:
5401                 throw new AssertionError("Not a loadable constant: " + c.poolTag());
5402         }
5403     }
5404     // </editor-fold>
5405 
5406     public void newRound() {
5407         descCache._map.clear();
5408         isDerivedRawCache.clear();
5409         implCache._map.clear();
5410         membersCache._map.clear();
5411         closureCache.clear();
5412     }
5413 
5414     // code reflection
5415 
5416     // The predicates below do not use a predefined symbol in Symtab.
5417     // This is deliberate, as we cannot initialize symbols in modules
5418     // other than java.base at startup.
5419 
5420     public boolean isQuoted(Type type) {
5421         Symbol s = type.tsym;
5422         return s != null &&
5423                 s.kind == TYP &&
5424                 s.name.equals(names.quoted) &&
5425                 s.packge().fullname.equals(names.jdk_incubator_code) &&
5426                 s.packge().modle.name.equals(names.jdk_incubator_code);
5427     }
5428 
5429     public boolean isQuotable(Type type) {
5430         Symbol s = type.tsym;
5431         return s != null &&
5432                 s.kind == TYP &&
5433                 s.name.equals(names.quotable) &&
5434                 s.packge().fullname.equals(names.jdk_incubator_code) &&
5435                 s.packge().modle.name.equals(names.jdk_incubator_code);
5436     }
5437 }
< prev index next >