Home | History | Annotate | Download | only in lower
      1 /*
      2  * Copyright 2016 Google Inc. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.turbine.lower;
     18 
     19 import static com.google.turbine.binder.DisambiguateTypeAnnotations.groupRepeated;
     20 
     21 import com.google.common.base.Function;
     22 import com.google.common.collect.ImmutableList;
     23 import com.google.common.collect.ImmutableList.Builder;
     24 import com.google.common.collect.ImmutableMap;
     25 import com.google.common.collect.ImmutableSet;
     26 import com.google.turbine.binder.bound.AnnotationValue;
     27 import com.google.turbine.binder.bound.ClassValue;
     28 import com.google.turbine.binder.bound.EnumConstantValue;
     29 import com.google.turbine.binder.bound.SourceTypeBoundClass;
     30 import com.google.turbine.binder.bound.TypeBoundClass;
     31 import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo;
     32 import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo;
     33 import com.google.turbine.binder.bound.TypeBoundClass.ParamInfo;
     34 import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo;
     35 import com.google.turbine.binder.bytecode.BytecodeBoundClass;
     36 import com.google.turbine.binder.env.CompoundEnv;
     37 import com.google.turbine.binder.env.Env;
     38 import com.google.turbine.binder.env.SimpleEnv;
     39 import com.google.turbine.binder.sym.ClassSymbol;
     40 import com.google.turbine.binder.sym.Symbol;
     41 import com.google.turbine.binder.sym.TyVarSymbol;
     42 import com.google.turbine.bytecode.ClassFile;
     43 import com.google.turbine.bytecode.ClassFile.AnnotationInfo;
     44 import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue;
     45 import com.google.turbine.bytecode.ClassFile.MethodInfo.ParameterInfo;
     46 import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo;
     47 import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo.Target;
     48 import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo.TargetType;
     49 import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo.ThrowsTarget;
     50 import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo.TypePath;
     51 import com.google.turbine.bytecode.ClassWriter;
     52 import com.google.turbine.bytecode.sig.Sig;
     53 import com.google.turbine.bytecode.sig.Sig.MethodSig;
     54 import com.google.turbine.bytecode.sig.Sig.TySig;
     55 import com.google.turbine.bytecode.sig.SigWriter;
     56 import com.google.turbine.model.Const;
     57 import com.google.turbine.model.TurbineFlag;
     58 import com.google.turbine.model.TurbineVisibility;
     59 import com.google.turbine.type.AnnoInfo;
     60 import com.google.turbine.type.Type;
     61 import com.google.turbine.type.Type.ArrayTy;
     62 import com.google.turbine.type.Type.ClassTy;
     63 import com.google.turbine.type.Type.ClassTy.SimpleClassTy;
     64 import com.google.turbine.type.Type.TyVar;
     65 import com.google.turbine.type.Type.WildTy;
     66 import com.google.turbine.types.Erasure;
     67 import java.lang.annotation.RetentionPolicy;
     68 import java.util.ArrayDeque;
     69 import java.util.ArrayList;
     70 import java.util.Collections;
     71 import java.util.Deque;
     72 import java.util.LinkedHashSet;
     73 import java.util.List;
     74 import java.util.Map;
     75 import java.util.Set;
     76 import javax.annotation.Nullable;
     77 
     78 /** Lowering from bound classes to bytecode. */
     79 public class Lower {
     80 
     81   /** The lowered compilation output. */
     82   public static class Lowered {
     83     private final ImmutableMap<String, byte[]> bytes;
     84     private final ImmutableSet<ClassSymbol> symbols;
     85 
     86     public Lowered(ImmutableMap<String, byte[]> bytes, ImmutableSet<ClassSymbol> symbols) {
     87       this.bytes = bytes;
     88       this.symbols = symbols;
     89     }
     90 
     91     /** Returns the bytecode for classes in the compilation. */
     92     public ImmutableMap<String, byte[]> bytes() {
     93       return bytes;
     94     }
     95 
     96     /** Returns the set of all referenced symbols in the compilation. */
     97     public ImmutableSet<ClassSymbol> symbols() {
     98       return symbols;
     99     }
    100   }
    101 
    102   /** Lowers all given classes to bytecode. */
    103   public static Lowered lowerAll(
    104       ImmutableMap<ClassSymbol, SourceTypeBoundClass> units,
    105       CompoundEnv<ClassSymbol, BytecodeBoundClass> classpath) {
    106     CompoundEnv<ClassSymbol, TypeBoundClass> env =
    107         CompoundEnv.<ClassSymbol, TypeBoundClass>of(classpath).append(new SimpleEnv<>(units));
    108     ImmutableMap.Builder<String, byte[]> result = ImmutableMap.builder();
    109     Set<ClassSymbol> symbols = new LinkedHashSet<>();
    110     for (ClassSymbol sym : units.keySet()) {
    111       result.put(sym.binaryName(), lower(units.get(sym), env, sym, symbols));
    112     }
    113     return new Lowered(result.build(), ImmutableSet.copyOf(symbols));
    114   }
    115 
    116   /** Lowers a class to bytecode. */
    117   public static byte[] lower(
    118       SourceTypeBoundClass info,
    119       Env<ClassSymbol, TypeBoundClass> env,
    120       ClassSymbol sym,
    121       Set<ClassSymbol> symbols) {
    122     return new Lower(env).lower(info, sym, symbols);
    123   }
    124 
    125   private final LowerSignature sig = new LowerSignature();
    126   private final Env<ClassSymbol, TypeBoundClass> env;
    127 
    128   public Lower(Env<ClassSymbol, TypeBoundClass> env) {
    129     this.env = env;
    130   }
    131 
    132   private byte[] lower(SourceTypeBoundClass info, ClassSymbol sym, Set<ClassSymbol> symbols) {
    133     int access = classAccess(info);
    134     String name = sig.descriptor(sym);
    135     String signature = sig.classSignature(info);
    136     String superName = info.superclass() != null ? sig.descriptor(info.superclass()) : null;
    137     List<String> interfaces = new ArrayList<>();
    138     for (ClassSymbol i : info.interfaces()) {
    139       interfaces.add(sig.descriptor(i));
    140     }
    141 
    142     List<ClassFile.MethodInfo> methods = new ArrayList<>();
    143     for (MethodInfo m : info.methods()) {
    144       if (TurbineVisibility.fromAccess(m.access()) == TurbineVisibility.PRIVATE) {
    145         // TODO(cushon): drop private members earlier?
    146         continue;
    147       }
    148       methods.add(lowerMethod(m, sym));
    149     }
    150 
    151     ImmutableList.Builder<ClassFile.FieldInfo> fields = ImmutableList.builder();
    152     for (FieldInfo f : info.fields()) {
    153       if ((f.access() & TurbineFlag.ACC_PRIVATE) == TurbineFlag.ACC_PRIVATE) {
    154         // TODO(cushon): drop private members earlier?
    155         continue;
    156       }
    157       fields.add(lowerField(f));
    158     }
    159 
    160     ImmutableList<AnnotationInfo> annotations = lowerAnnotations(info.annotations());
    161 
    162     ImmutableList<ClassFile.InnerClass> inners = collectInnerClasses(sym, info);
    163 
    164     ImmutableList<TypeAnnotationInfo> typeAnnotations = classTypeAnnotations(info);
    165 
    166     ClassFile classfile =
    167         new ClassFile(
    168             access,
    169             name,
    170             signature,
    171             superName,
    172             interfaces,
    173             methods,
    174             fields.build(),
    175             annotations,
    176             inners,
    177             typeAnnotations);
    178 
    179     symbols.addAll(sig.classes);
    180 
    181     return ClassWriter.writeClass(classfile);
    182   }
    183 
    184   private ClassFile.MethodInfo lowerMethod(final MethodInfo m, final ClassSymbol sym) {
    185     int access = m.access();
    186     Function<TyVarSymbol, TyVarInfo> tenv = new TyVarEnv(m.tyParams());
    187     String name = m.name();
    188     String desc = methodDescriptor(m, tenv);
    189     String signature = sig.methodSignature(env, m, sym);
    190     ImmutableList.Builder<String> exceptions = ImmutableList.builder();
    191     if (!m.exceptions().isEmpty()) {
    192       for (Type e : m.exceptions()) {
    193         exceptions.add(sig.descriptor(((ClassTy) Erasure.erase(e, tenv)).sym()));
    194       }
    195     }
    196 
    197     ElementValue defaultValue = m.defaultValue() != null ? annotationValue(m.defaultValue()) : null;
    198 
    199     ImmutableList<AnnotationInfo> annotations = lowerAnnotations(m.annotations());
    200 
    201     ImmutableList<ImmutableList<AnnotationInfo>> paramAnnotations = parameterAnnotations(m);
    202 
    203     ImmutableList<TypeAnnotationInfo> typeAnnotations = methodTypeAnnotations(m);
    204 
    205     ImmutableList<ClassFile.MethodInfo.ParameterInfo> parameters = methodParameters(m);
    206 
    207     return new ClassFile.MethodInfo(
    208         access,
    209         name,
    210         desc,
    211         signature,
    212         exceptions.build(),
    213         defaultValue,
    214         annotations,
    215         paramAnnotations,
    216         typeAnnotations,
    217         parameters);
    218   }
    219 
    220   private ImmutableList<ParameterInfo> methodParameters(MethodInfo m) {
    221     ImmutableList.Builder<ParameterInfo> result = ImmutableList.builder();
    222     for (ParamInfo p : m.parameters()) {
    223       result.add(new ParameterInfo(p.name(), p.access() & PARAMETER_ACCESS_MASK));
    224     }
    225     return result.build();
    226   }
    227 
    228   private static final int PARAMETER_ACCESS_MASK =
    229       TurbineFlag.ACC_MANDATED | TurbineFlag.ACC_FINAL | TurbineFlag.ACC_SYNTHETIC;
    230 
    231   private ImmutableList<ImmutableList<AnnotationInfo>> parameterAnnotations(MethodInfo m) {
    232     ImmutableList.Builder<ImmutableList<AnnotationInfo>> annotations = ImmutableList.builder();
    233     for (ParamInfo parameter : m.parameters()) {
    234       if (parameter.synthetic()) {
    235         continue;
    236       }
    237       if (parameter.annotations().isEmpty()) {
    238         annotations.add(ImmutableList.of());
    239         continue;
    240       }
    241       ImmutableList.Builder<AnnotationInfo> parameterAnnotations = ImmutableList.builder();
    242       for (AnnoInfo annotation : parameter.annotations()) {
    243         Boolean visible = isVisible(annotation.sym());
    244         if (visible == null) {
    245           continue;
    246         }
    247         String desc = sig.objectType(annotation.sym());
    248         parameterAnnotations.add(
    249             new AnnotationInfo(desc, visible, annotationValues(annotation.values())));
    250       }
    251       annotations.add(parameterAnnotations.build());
    252     }
    253     return annotations.build();
    254   }
    255 
    256   private String methodDescriptor(MethodInfo m, Function<TyVarSymbol, TyVarInfo> tenv) {
    257     ImmutableList<Sig.TyParamSig> typarams = ImmutableList.of();
    258     ImmutableList.Builder<TySig> fparams = ImmutableList.builder();
    259     for (ParamInfo t : m.parameters()) {
    260       fparams.add(sig.signature(Erasure.erase(t.type(), tenv)));
    261     }
    262     TySig result = sig.signature(Erasure.erase(m.returnType(), tenv));
    263     ImmutableList<TySig> excns = ImmutableList.of();
    264     return SigWriter.method(new MethodSig(typarams, fparams.build(), result, excns));
    265   }
    266 
    267   private ClassFile.FieldInfo lowerField(FieldInfo f) {
    268     final String name = f.name();
    269     Function<TyVarSymbol, TyVarInfo> tenv = new TyVarEnv(Collections.emptyMap());
    270     String desc = SigWriter.type(sig.signature(Erasure.erase(f.type(), tenv)));
    271     String signature = sig.fieldSignature(f.type());
    272 
    273     ImmutableList<AnnotationInfo> annotations = lowerAnnotations(f.annotations());
    274 
    275     ImmutableList.Builder<TypeAnnotationInfo> typeAnnotations = ImmutableList.builder();
    276     lowerTypeAnnotations(
    277         typeAnnotations, f.type(), TargetType.FIELD, TypeAnnotationInfo.EMPTY_TARGET);
    278 
    279     return new ClassFile.FieldInfo(
    280         f.access(), name, desc, signature, f.value(), annotations, typeAnnotations.build());
    281   }
    282 
    283   /** Creates inner class attributes for all referenced inner classes. */
    284   private ImmutableList<ClassFile.InnerClass> collectInnerClasses(
    285       ClassSymbol origin, SourceTypeBoundClass info) {
    286     Set<ClassSymbol> all = new LinkedHashSet<>();
    287     addEnclosing(env, all, origin);
    288     for (ClassSymbol sym : info.children().values()) {
    289       addEnclosing(env, all, sym);
    290     }
    291     for (ClassSymbol sym : sig.classes) {
    292       addEnclosing(env, all, sym);
    293     }
    294     ImmutableList.Builder<ClassFile.InnerClass> inners = ImmutableList.builder();
    295     for (ClassSymbol innerSym : all) {
    296       inners.add(innerClass(env, innerSym));
    297     }
    298     return inners.build();
    299   }
    300 
    301   /**
    302    * Record all enclosing declarations of a symbol, to make sure the necessary InnerClass attributes
    303    * are added.
    304    *
    305    * <p>javac expects InnerClass attributes for enclosing classes to appear before their member
    306    * classes' entries.
    307    */
    308   private void addEnclosing(
    309       Env<ClassSymbol, TypeBoundClass> env, Set<ClassSymbol> all, ClassSymbol sym) {
    310     ClassSymbol owner = env.get(sym).owner();
    311     if (owner != null) {
    312       addEnclosing(env, all, owner);
    313       all.add(sym);
    314     }
    315   }
    316 
    317   /**
    318    * Creates an inner class attribute, given an inner class that was referenced somewhere in the
    319    * class.
    320    */
    321   private ClassFile.InnerClass innerClass(
    322       Env<ClassSymbol, TypeBoundClass> env, ClassSymbol innerSym) {
    323     TypeBoundClass inner = env.get(innerSym);
    324 
    325     String innerName = innerSym.binaryName().substring(inner.owner().binaryName().length() + 1);
    326 
    327     int access = inner.access();
    328     access &= ~(TurbineFlag.ACC_SUPER | TurbineFlag.ACC_STRICT);
    329 
    330     return new ClassFile.InnerClass(
    331         innerSym.binaryName(), inner.owner().binaryName(), innerName, access);
    332   }
    333 
    334   /** Updates visibility, and unsets access bits that can only be set in InnerClass. */
    335   private int classAccess(SourceTypeBoundClass info) {
    336     int access = info.access();
    337     access &= ~(TurbineFlag.ACC_STATIC | TurbineFlag.ACC_PRIVATE | TurbineFlag.ACC_STRICT);
    338     if ((access & TurbineFlag.ACC_PROTECTED) != 0) {
    339       access &= ~TurbineFlag.ACC_PROTECTED;
    340       access |= TurbineFlag.ACC_PUBLIC;
    341     }
    342     return access;
    343   }
    344 
    345   /**
    346    * Looks up {@link TyVarInfo}s.
    347    *
    348    * <p>We could generalize {@link com.google.turbine.binder.lookup.Scope} instead, but this isn't
    349    * needed anywhere else.
    350    */
    351   class TyVarEnv implements Function<TyVarSymbol, TyVarInfo> {
    352 
    353     private final Map<TyVarSymbol, TyVarInfo> tyParams;
    354 
    355     /** @param tyParams the initial lookup scope, e.g. a method's formal type parameters. */
    356     public TyVarEnv(Map<TyVarSymbol, TyVarInfo> tyParams) {
    357       this.tyParams = tyParams;
    358     }
    359 
    360     @Override
    361     public TyVarInfo apply(TyVarSymbol sym) {
    362       TyVarInfo result = tyParams.get(sym);
    363       if (result != null) {
    364         return result;
    365       }
    366       // type variables can only be declared by methods and classes,
    367       // and we've already handled methods
    368       Symbol ownerSym = sym.owner();
    369       if (ownerSym.symKind() != Symbol.Kind.CLASS) {
    370         throw new AssertionError(sym);
    371       }
    372       // anything that lexically encloses the class being lowered
    373       // must be in the same compilation unit, so we have source
    374       // information for it
    375       TypeBoundClass owner = env.get((ClassSymbol) ownerSym);
    376       return owner.typeParameterTypes().get(sym);
    377     }
    378   }
    379 
    380   private ImmutableList<AnnotationInfo> lowerAnnotations(ImmutableList<AnnoInfo> annotations) {
    381     ImmutableList.Builder<AnnotationInfo> lowered = ImmutableList.builder();
    382     for (AnnoInfo annotation : annotations) {
    383       AnnotationInfo anno = lowerAnnotation(annotation);
    384       if (anno == null) {
    385         continue;
    386       }
    387       lowered.add(anno);
    388     }
    389     return lowered.build();
    390   }
    391 
    392   private AnnotationInfo lowerAnnotation(AnnoInfo annotation) {
    393     Boolean visible = isVisible(annotation.sym());
    394     if (visible == null) {
    395       return null;
    396     }
    397     return new AnnotationInfo(
    398         sig.objectType(annotation.sym()), visible, annotationValues(annotation.values()));
    399   }
    400 
    401   /**
    402    * Returns true if the annotation is visible at runtime, false if it is not visible at runtime,
    403    * and {@code null} if it should not be retained in bytecode.
    404    */
    405   @Nullable
    406   private Boolean isVisible(ClassSymbol sym) {
    407     RetentionPolicy retention = env.get(sym).annotationMetadata().retention();
    408     switch (retention) {
    409       case CLASS:
    410         return false;
    411       case RUNTIME:
    412         return true;
    413       case SOURCE:
    414         return null;
    415       default:
    416         throw new AssertionError(retention);
    417     }
    418   }
    419 
    420   private ImmutableMap<String, ElementValue> annotationValues(ImmutableMap<String, Const> values) {
    421     ImmutableMap.Builder<String, ElementValue> result = ImmutableMap.builder();
    422     for (Map.Entry<String, Const> entry : values.entrySet()) {
    423       result.put(entry.getKey(), annotationValue(entry.getValue()));
    424     }
    425     return result.build();
    426   }
    427 
    428   private ElementValue annotationValue(Const value) {
    429     switch (value.kind()) {
    430       case CLASS_LITERAL:
    431         {
    432           ClassValue classValue = (ClassValue) value;
    433           return new ElementValue.ConstClassValue(SigWriter.type(sig.signature(classValue.type())));
    434         }
    435       case ENUM_CONSTANT:
    436         {
    437           EnumConstantValue enumValue = (EnumConstantValue) value;
    438           return new ElementValue.EnumConstValue(
    439               sig.objectType(enumValue.sym().owner()), enumValue.sym().name());
    440         }
    441       case ARRAY:
    442         {
    443           Const.ArrayInitValue arrayValue = (Const.ArrayInitValue) value;
    444           List<ElementValue> values = new ArrayList<>();
    445           for (Const element : arrayValue.elements()) {
    446             values.add(annotationValue(element));
    447           }
    448           return new ElementValue.ArrayValue(values);
    449         }
    450       case ANNOTATION:
    451         {
    452           AnnotationValue annotationValue = (AnnotationValue) value;
    453           Boolean visible = isVisible(annotationValue.sym());
    454           if (visible == null) {
    455             visible = true;
    456           }
    457           return new ElementValue.AnnotationValue(
    458               new AnnotationInfo(
    459                   sig.objectType(annotationValue.sym()),
    460                   visible,
    461                   annotationValues(annotationValue.values())));
    462         }
    463       case PRIMITIVE:
    464         return new ElementValue.ConstValue((Const.Value) value);
    465       default:
    466         throw new AssertionError(value.kind());
    467     }
    468   }
    469 
    470   /** Lower type annotations in a class declaration's signature. */
    471   private ImmutableList<TypeAnnotationInfo> classTypeAnnotations(SourceTypeBoundClass info) {
    472     ImmutableList.Builder<TypeAnnotationInfo> result = ImmutableList.builder();
    473     {
    474       if (info.superClassType() != null) {
    475         lowerTypeAnnotations(
    476             result,
    477             info.superClassType(),
    478             TargetType.SUPERTYPE,
    479             new TypeAnnotationInfo.SuperTypeTarget(-1));
    480       }
    481       int idx = 0;
    482       for (Type i : info.interfaceTypes()) {
    483         lowerTypeAnnotations(
    484             result, i, TargetType.SUPERTYPE, new TypeAnnotationInfo.SuperTypeTarget(idx++));
    485       }
    486     }
    487     typeParameterAnnotations(
    488         result,
    489         info.typeParameterTypes().values(),
    490         TargetType.CLASS_TYPE_PARAMETER,
    491         TargetType.CLASS_TYPE_PARAMETER_BOUND);
    492     return result.build();
    493   }
    494 
    495   /** Lower type annotations in a method declaration's signature. */
    496   private ImmutableList<TypeAnnotationInfo> methodTypeAnnotations(MethodInfo m) {
    497     ImmutableList.Builder<TypeAnnotationInfo> result = ImmutableList.builder();
    498 
    499     typeParameterAnnotations(
    500         result,
    501         m.tyParams().values(),
    502         TargetType.METHOD_TYPE_PARAMETER,
    503         TargetType.METHOD_TYPE_PARAMETER_BOUND);
    504 
    505     {
    506       int idx = 0;
    507       for (Type e : m.exceptions()) {
    508         lowerTypeAnnotations(result, e, TargetType.METHOD_THROWS, new ThrowsTarget(idx++));
    509       }
    510     }
    511 
    512     if (m.receiver() != null) {
    513       lowerTypeAnnotations(
    514           result,
    515           m.receiver().type(),
    516           TargetType.METHOD_RECEIVER_PARAMETER,
    517           TypeAnnotationInfo.EMPTY_TARGET);
    518     }
    519 
    520     lowerTypeAnnotations(
    521         result, m.returnType(), TargetType.METHOD_RETURN, TypeAnnotationInfo.EMPTY_TARGET);
    522 
    523     {
    524       int idx = 0;
    525       for (ParamInfo p : m.parameters()) {
    526         if (p.synthetic()) {
    527           continue;
    528         }
    529         lowerTypeAnnotations(
    530             result,
    531             p.type(),
    532             TargetType.METHOD_FORMAL_PARAMETER,
    533             new TypeAnnotationInfo.FormalParameterTarget(idx++));
    534       }
    535     }
    536 
    537     return result.build();
    538   }
    539 
    540   /**
    541    * Lower type annotations on class or method type parameters, either on the parameters themselves
    542    * or on bounds.
    543    */
    544   private void typeParameterAnnotations(
    545       Builder<TypeAnnotationInfo> result,
    546       Iterable<TyVarInfo> typeParameters,
    547       TargetType targetType,
    548       TargetType boundTargetType) {
    549     int typeParameterIndex = 0;
    550     for (TyVarInfo p : typeParameters) {
    551       for (AnnoInfo anno : groupRepeated(env, p.annotations())) {
    552         AnnotationInfo info = lowerAnnotation(anno);
    553         if (info == null) {
    554           continue;
    555         }
    556         result.add(
    557             new TypeAnnotationInfo(
    558                 targetType,
    559                 new TypeAnnotationInfo.TypeParameterTarget(typeParameterIndex),
    560                 TypePath.root(),
    561                 info));
    562       }
    563       if (p.superClassBound() != null) {
    564         lowerTypeAnnotations(
    565             result,
    566             p.superClassBound(),
    567             boundTargetType,
    568             new TypeAnnotationInfo.TypeParameterBoundTarget(typeParameterIndex, 0));
    569       }
    570       int boundIndex = 1; // super class bound index is always 0; interface bounds start at 1
    571       for (Type i : p.interfaceBounds()) {
    572         lowerTypeAnnotations(
    573             result,
    574             i,
    575             boundTargetType,
    576             new TypeAnnotationInfo.TypeParameterBoundTarget(typeParameterIndex, boundIndex++));
    577       }
    578       typeParameterIndex++;
    579     }
    580   }
    581 
    582   private void lowerTypeAnnotations(
    583       Builder<TypeAnnotationInfo> result, Type type, TargetType targetType, Target target) {
    584     new LowerTypeAnnotations(result, targetType, target)
    585         .lowerTypeAnnotations(type, TypePath.root());
    586   }
    587 
    588   class LowerTypeAnnotations {
    589     private final ImmutableList.Builder<TypeAnnotationInfo> result;
    590     private final TargetType targetType;
    591     private final Target target;
    592 
    593     public LowerTypeAnnotations(
    594         Builder<TypeAnnotationInfo> result, TargetType targetType, Target target) {
    595       this.result = result;
    596       this.targetType = targetType;
    597       this.target = target;
    598     }
    599 
    600     /**
    601      * Lower all type annotations present in a type.
    602      *
    603      * <p>Recursively descends into nested types, and accumulates a type path structure to locate
    604      * the annotation in the signature.
    605      */
    606     private void lowerTypeAnnotations(Type type, TypePath path) {
    607       switch (type.tyKind()) {
    608         case TY_VAR:
    609           lowerTypeAnnotations(((TyVar) type).annos(), path);
    610           break;
    611         case CLASS_TY:
    612           lowerClassTypeTypeAnnotations((ClassTy) type, path);
    613           break;
    614         case ARRAY_TY:
    615           lowerArrayTypeAnnotations(type, path);
    616           break;
    617         case WILD_TY:
    618           lowerWildTyTypeAnnotations((WildTy) type, path);
    619           break;
    620         case PRIM_TY:
    621           lowerTypeAnnotations(((Type.PrimTy) type).annos(), path);
    622           break;
    623         case VOID_TY:
    624           break;
    625         default:
    626           throw new AssertionError(type.tyKind());
    627       }
    628     }
    629 
    630     /** Lower a list of type annotations. */
    631     private void lowerTypeAnnotations(ImmutableList<AnnoInfo> annos, TypePath path) {
    632       for (AnnoInfo anno : groupRepeated(env, annos)) {
    633         AnnotationInfo info = lowerAnnotation(anno);
    634         if (info == null) {
    635           continue;
    636         }
    637         result.add(new TypeAnnotationInfo(targetType, target, path, info));
    638       }
    639     }
    640 
    641     private void lowerWildTyTypeAnnotations(WildTy type, TypePath path) {
    642       switch (type.boundKind()) {
    643         case NONE:
    644           lowerTypeAnnotations(type.annotations(), path);
    645           break;
    646         case UPPER:
    647         case LOWER:
    648           lowerTypeAnnotations(type.annotations(), path);
    649           lowerTypeAnnotations(type.bound(), path.wild());
    650           break;
    651         default:
    652           throw new AssertionError(type.boundKind());
    653       }
    654     }
    655 
    656     private void lowerArrayTypeAnnotations(Type type, TypePath path) {
    657       Type base = type;
    658       Deque<ArrayTy> flat = new ArrayDeque<>();
    659       while (base instanceof ArrayTy) {
    660         ArrayTy arrayTy = (ArrayTy) base;
    661         flat.addFirst(arrayTy);
    662         base = arrayTy.elementType();
    663       }
    664       for (ArrayTy arrayTy : flat) {
    665         lowerTypeAnnotations(arrayTy.annos(), path);
    666         path = path.array();
    667       }
    668       lowerTypeAnnotations(base, path);
    669     }
    670 
    671     private void lowerClassTypeTypeAnnotations(ClassTy type, TypePath path) {
    672       for (SimpleClassTy simple : type.classes) {
    673         lowerTypeAnnotations(simple.annos(), path);
    674         int idx = 0;
    675         for (Type a : simple.targs()) {
    676           lowerTypeAnnotations(a, path.typeArgument(idx++));
    677         }
    678         path = path.nested();
    679       }
    680     }
    681   }
    682 }
    683