< prev index next >

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

Print this page

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










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










































 210         };
 211 
 212         abstract ProjectionKind complement();


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







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

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

 310                                 bound = t.getUpperBound();
 311                                 break;
 312                             case DOWNWARDS:

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













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

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















5339 }

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

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

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