src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
changeset 47959 5dd899009525
parent 47458 945935416d7c
child 48054 702043a4cdeb
equal deleted inserted replaced
47958:d34958cb3163 47959:5dd899009525
   235      * {@code upwards(List<#CAP1>, [#CAP1]) = List<? extends String>, where #CAP1 <: String }
   235      * {@code upwards(List<#CAP1>, [#CAP1]) = List<? extends String>, where #CAP1 <: String }
   236      * {@code downwards(List<#CAP2>, [#CAP2]) = List<? super String>, where #CAP2 :> String }
   236      * {@code downwards(List<#CAP2>, [#CAP2]) = List<? super String>, where #CAP2 :> String }
   237      * {@code upwards(List<#CAP1>, [#CAP2]) = List<#CAP1> }
   237      * {@code upwards(List<#CAP1>, [#CAP2]) = List<#CAP1> }
   238      * {@code downwards(List<#CAP1>, [#CAP1]) = not defined }
   238      * {@code downwards(List<#CAP1>, [#CAP1]) = not defined }
   239      */
   239      */
   240     class TypeProjection extends StructuralTypeMapping<ProjectionKind> {
   240     class TypeProjection extends TypeMapping<ProjectionKind> {
   241 
   241 
   242         List<Type> vars;
   242         List<Type> vars;
   243         Set<Type> seen = new HashSet<>();
   243         Set<Type> seen = new HashSet<>();
   244 
   244 
   245         public TypeProjection(List<Type> vars) {
   245         public TypeProjection(List<Type> vars) {
   255                 else return makeIntersectionType(components1);
   255                 else return makeIntersectionType(components1);
   256             } else {
   256             } else {
   257                 Type outer = t.getEnclosingType();
   257                 Type outer = t.getEnclosingType();
   258                 Type outer1 = visit(outer, pkind);
   258                 Type outer1 = visit(outer, pkind);
   259                 List<Type> typarams = t.getTypeArguments();
   259                 List<Type> typarams = t.getTypeArguments();
   260                 List<Type> typarams1 = typarams.map(ta -> mapTypeArgument(ta, pkind));
   260                 List<Type> formals = t.tsym.type.getTypeArguments();
   261                 if (typarams1.stream().anyMatch(ta -> ta.hasTag(BOT))) {
   261                 ListBuffer<Type> typarams1 = new ListBuffer<>();
   262                     //not defined
   262                 boolean changed = false;
   263                     return syms.botType;
   263                 for (Type actual : typarams) {
   264                 }
   264                     Type t2 = mapTypeArgument(t, formals.head.getUpperBound(), actual, pkind);
   265                 if (outer1 == outer && typarams1 == typarams) return t;
   265                     if (t2.hasTag(BOT)) {
   266                 else return new ClassType(outer1, typarams1, t.tsym, t.getMetadata()) {
   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()) {
   267                     @Override
   275                     @Override
   268                     protected boolean needsStripping() {
   276                     protected boolean needsStripping() {
   269                         return true;
   277                         return true;
   270                     }
   278                     }
   271                 };
   279                 };
   272             }
   280             }
   273         }
   281         }
   274 
   282 
   275         protected Type makeWildcard(Type upper, Type lower) {
   283         @Override
   276             BoundKind bk;
   284         public Type visitArrayType(ArrayType t, ProjectionKind s) {
   277             Type bound;
   285             Type elemtype = t.elemtype;
   278             if (upper.hasTag(BOT)) {
   286             Type elemtype1 = visit(elemtype, s);
   279                 upper = syms.objectType;
   287             if (elemtype1 == elemtype) {
   280             }
   288                 return t;
   281             boolean isUpperObject = isSameType(upper, syms.objectType);
   289             } else if (elemtype1.hasTag(BOT)) {
   282             if (!lower.hasTag(BOT) && isUpperObject) {
   290                 //undefined
   283                 bound = lower;
   291                 return syms.botType;
   284                 bk = SUPER;
       
   285             } else {
   292             } else {
   286                 bound = upper;
   293                 return new ArrayType(elemtype1, t.tsym, t.metadata) {
   287                 bk = isUpperObject ? UNBOUND : EXTENDS;
   294                     @Override
   288             }
   295                     protected boolean needsStripping() {
   289             return new WildcardType(bound, bk, syms.boundClass);
   296                         return true;
       
   297                     }
       
   298                 };
       
   299             }
   290         }
   300         }
   291 
   301 
   292         @Override
   302         @Override
   293         public Type visitTypeVar(TypeVar t, ProjectionKind pkind) {
   303         public Type visitTypeVar(TypeVar t, ProjectionKind pkind) {
   294             if (vars.contains(t)) {
   304             if (vars.contains(t)) {
   320             } else {
   330             } else {
   321                 return t;
   331                 return t;
   322             }
   332             }
   323         }
   333         }
   324 
   334 
   325         @Override
   335         private Type mapTypeArgument(Type site, Type declaredBound, Type t, ProjectionKind pkind) {
   326         public Type visitWildcardType(WildcardType wt, ProjectionKind pkind) {
   336             return t.containsAny(vars) ?
   327             switch (pkind) {
   337                     t.map(new TypeArgumentProjection(site, declaredBound), pkind) :
   328                 case UPWARDS:
   338                     t;
   329                     return wt.isExtendsBound() ?
   339         }
   330                             wt.type.map(this, pkind) :
   340 
   331                             syms.objectType;
   341         class TypeArgumentProjection extends TypeMapping<ProjectionKind> {
   332                 case DOWNWARDS:
   342 
   333                     return wt.isSuperBound() ?
   343             Type site;
   334                             wt.type.map(this, pkind) :
   344             Type declaredBound;
   335                             syms.botType;
   345 
   336                 default:
   346             TypeArgumentProjection(Type site, Type declaredBound) {
   337                     Assert.error();
   347                 this.site = site;
   338                     return null;
   348                 this.declaredBound = declaredBound;
   339             }
   349             }
   340         }
   350 
   341 
   351             @Override
   342         private Type mapTypeArgument(Type t, ProjectionKind pkind) {
   352             public Type visitType(Type t, ProjectionKind pkind) {
   343             if (!t.containsAny(vars)) {
   353                 //type argument is some type containing restricted vars
   344                 return t;
   354                 if (pkind == ProjectionKind.DOWNWARDS) {
   345             } else if (!t.hasTag(WILDCARD) && pkind == ProjectionKind.DOWNWARDS) {
   355                     //not defined
   346                 //not defined
   356                     return syms.botType;
   347                 return syms.botType;
   357                 }
   348             } else {
   358                 Type upper = t.map(TypeProjection.this, ProjectionKind.UPWARDS);
   349                 Type upper = t.map(this, pkind);
   359                 Type lower = t.map(TypeProjection.this, ProjectionKind.DOWNWARDS);
   350                 Type lower = t.map(this, pkind.complement());
   360                 List<Type> formals = site.tsym.type.getTypeArguments();
   351                 return makeWildcard(upper, lower);
   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                 };
   352             }
   408             }
   353         }
   409         }
   354     }
   410     }
   355 
   411 
   356     /**
   412     /**