protected void mergeTypeParametersIntoParent(ResolvedTypes parent) {
   for (UnboundTypeReference unbound : basicGetTypeParameters().values()) {
     LightweightTypeReference resolvedTo = unbound.getResolvedTo();
     if (resolvedTo == null) {
       List<JvmTypeParameter> typeParameters = basicGetDeclardTypeParameters();
       if (typeParameters != null && typeParameters.contains(unbound.getTypeParameter())) {
         unbound.tryResolve();
         if (!unbound.internalIsResolved()) {
           if (unbound.getExpression() instanceof XConstructorCall) {
             unbound.resolve(); // resolve against constraints
           } else {
             unbound.acceptHint(
                 unbound.getOwner().newParameterizedTypeReference(unbound.getTypeParameter()),
                 BoundTypeArgumentSource.RESOLVED,
                 unbound,
                 VarianceInfo.INVARIANT,
                 VarianceInfo.INVARIANT);
           }
         }
       } else {
         LightweightTypeReference reference = unbound.copyInto(parent.getReferenceOwner());
         if (reference instanceof UnboundTypeReference) {
           parent.acceptUnboundTypeReference(
               unbound.getHandle(), (UnboundTypeReference) reference);
         }
       }
     }
   }
   Map<Object, List<LightweightBoundTypeArgument>> typeParameterHints =
       basicGetTypeParameterHints();
   for (Map.Entry<Object, List<LightweightBoundTypeArgument>> hint :
       typeParameterHints.entrySet()) {
     if (!parent.isResolved(hint.getKey())) {
       List<LightweightBoundTypeArgument> boundTypeArguments = hint.getValue();
       for (LightweightBoundTypeArgument boundTypeArgument : boundTypeArguments) {
         if (boundTypeArgument.getOrigin() instanceof VarianceInfo) {
           parent.acceptHint(hint.getKey(), boundTypeArgument);
         } else {
           LightweightBoundTypeArgument copy =
               new LightweightBoundTypeArgument(
                   boundTypeArgument.getTypeReference().copyInto(parent.getReferenceOwner()),
                   boundTypeArgument.getSource(),
                   boundTypeArgument.getOrigin(),
                   boundTypeArgument.getDeclaredVariance(),
                   boundTypeArgument.getActualVariance());
           parent.acceptHint(hint.getKey(), copy);
         }
       }
     }
   }
 }
 protected void mergeTypesIntoParent(ResolvedTypes parent) {
   Map<JvmIdentifiableElement, LightweightTypeReference> types = basicGetTypes();
   if (!types.isEmpty()) {
     for (Map.Entry<JvmIdentifiableElement, LightweightTypeReference> entry : types.entrySet()) {
       LightweightTypeReference value = entry.getValue();
       if (value instanceof UnboundTypeReference
           && super.isResolved(((UnboundTypeReference) value).getHandle())) {
         parent.setType(
             entry.getKey(), value.getUpperBoundSubstitute().copyInto(parent.getReferenceOwner()));
       } else {
         parent.setType(entry.getKey(), value.copyInto(parent.getReferenceOwner()));
       }
     }
   }
 }
 protected void mergeExpressionTypesIntoParent(ResolvedTypes parent) {
   Map<XExpression, List<TypeData>> expressionTypes = basicGetExpressionTypes();
   if (!expressionTypes.isEmpty()) {
     for (Map.Entry<XExpression, List<TypeData>> entry : expressionTypes.entrySet()) {
       List<TypeData> list = entry.getValue();
       for (int i = 0, size = list.size(); i < size; i++) {
         parent.acceptType(entry.getKey(), prepareMerge(list.get(i), parent.getReferenceOwner()));
       }
     }
   }
 }