@Override public LightweightTypeReference getInvariantBoundSubstitute() { if (internalGetResolvedTo() != null) return resolvedTo.getInvariantBoundSubstitute(); return super.getInvariantBoundSubstitute(); }
protected LightweightTypeReference getCollectionElementType(XCollectionLiteral literal) { LightweightTypeReference type = getLightweightType(literal); if (type == null) throw new IllegalStateException(); if(type.isArray()) { LightweightTypeReference result = type.getComponentType(); if (result == null) throw new IllegalStateException(); return result; } else if(type.isSubtypeOf(Collection.class) && type.hasTypeArguments()) { return type.getTypeArguments().get(0).getInvariantBoundSubstitute(); } return type.getOwner().newReferenceToObject(); }
@Override protected WildcardTypeReference doCopyInto(ITypeReferenceOwner owner) { WildcardTypeReference result = owner.newWildcardTypeReference(); if (upperBounds != null && !upperBounds.isEmpty()) { for(LightweightTypeReference upperBound: upperBounds) { LightweightTypeReference copiedUpperBound = upperBound.copyInto(owner).getInvariantBoundSubstitute(); if (!(copiedUpperBound.isPrimitive() || copiedUpperBound.isPrimitiveVoid())) { result.addUpperBound(copiedUpperBound); } } } if (lowerBound != null) { LightweightTypeReference copiedLowerBound = lowerBound.copyInto(owner).getInvariantBoundSubstitute(); if (!(copiedLowerBound.isPrimitive() || copiedLowerBound.isPrimitiveVoid())) { result.setLowerBound(copiedLowerBound); } } return result; }
/** * Creates a map type reference that comes as close as possible / necessary to its expected type. */ protected LightweightTypeReference createMapTypeReference(JvmGenericType mapType, LightweightTypeReference pairType, LightweightTypeReference expectation, ITypeReferenceOwner owner) { List<LightweightTypeReference> leftAndRight = pairType.getTypeArguments(); LightweightTypeReference left = leftAndRight.get(0).getInvariantBoundSubstitute(); LightweightTypeReference right = leftAndRight.get(1).getInvariantBoundSubstitute(); LightweightTypeReference mapExpectation = getMapExpectation(expectation); if (mapExpectation != null) { List<LightweightTypeReference> typeArguments = expectation.getTypeArguments(); left = doNormalizeElementType(left, typeArguments.get(0)); right = doNormalizeElementType(right, typeArguments.get(1)); } ParameterizedTypeReference result = owner.newParameterizedTypeReference(mapType); result.addTypeArgument(left.copyInto(owner)); result.addTypeArgument(right.copyInto(owner)); if (mapExpectation != null && !expectation.isAssignableFrom(result)) { // expectation does not match the computed type, but looks good according to the element types: // use expected type if (matchesExpectation(left, mapExpectation.getTypeArguments().get(0)) && matchesExpectation(right, mapExpectation.getTypeArguments().get(1))) { return expectation; } } return result; }
type = type.getUpperBoundSubstitute(); } else { type = type.getInvariantBoundSubstitute();
/** * Returns a projection of this type to the instance level. That is, type arguments will * be replaced by their invariant bounds. * * The instance projection of <code>ArrayList<? extends Iterable<? extends String>></code> * is <code>ArrayList<Iterable<? extends String>></code> since it is possible to create instances * of <code>ArrayList<Iterable<? extends String>></code>. */ public ParameterizedTypeReference toInstanceTypeReference() { ParameterizedTypeReference result = getOwner().newParameterizedTypeReference(getType()); for(LightweightTypeReference typeArgument: getTypeArguments()) { result.addTypeArgument(typeArgument.getInvariantBoundSubstitute()); } return result; } }
@Override public ParameterizedTypeReference toInstanceTypeReference() { LightweightTypeReference outerInstanceTypeReference = ((ParameterizedTypeReference) outer).toInstanceTypeReference(); InnerTypeReference result = new InnerTypeReference(getOwner(), outerInstanceTypeReference, getType()); for(LightweightTypeReference typeArgument: getTypeArguments()) { result.addTypeArgument(typeArgument.getInvariantBoundSubstitute()); } return result; } }
@Override public ParameterizedTypeReference toInstanceTypeReference() { ParameterizedTypeReference outerInstanceTypeReference = ((ParameterizedTypeReference) outer).toInstanceTypeReference(); InnerTypeReference result = getOwner().newParameterizedTypeReference(outerInstanceTypeReference, getType()); for(LightweightTypeReference typeArgument: getTypeArguments()) { result.addTypeArgument(typeArgument.getInvariantBoundSubstitute()); } return result; } }
protected LightweightMergedBoundTypeArgument getSingleArgumentAsMergedArgument(LightweightBoundTypeArgument argument) { LightweightTypeReference typeReference = argument.getTypeReference(); VarianceInfo varianceInfo = argument.getDeclaredVariance().mergeDeclaredWithActual(argument.getActualVariance()); if (argument.getDeclaredVariance() == VarianceInfo.IN && varianceInfo == VarianceInfo.INVARIANT) { if (typeReference.getKind() == LightweightTypeReference.KIND_WILDCARD_TYPE_REFERENCE) { typeReference = typeReference.getInvariantBoundSubstitute(); } } return new LightweightMergedBoundTypeArgument(typeReference, varianceInfo); }
protected int doIsConformant(ParameterizedTypeReference left, ArrayTypeReference right, int flags) { if (left.isType(Object.class) || left.isType(Serializable.class) || left.isType(Cloneable.class)) { return flags | SUCCESS | SUBTYPE; } if ((flags & ALLOW_SYNONYMS) != 0) { // Arrays are generally assignable to List and its supertypes if (left.isType(List.class) || left.isType(Collection.class) || left.isType(Iterable.class)) { List<LightweightTypeReference> arguments = left.getTypeArguments(); if (arguments.isEmpty()) { // type argument is bound to Object return flags | SUCCESS | DEMAND_CONVERSION; } LightweightTypeReference componentType = right.getComponentType().getWrapperTypeIfPrimitive(); int result = doIsConformant(arguments.get(0).getInvariantBoundSubstitute(), componentType, flags); if ((result & SUCCESS) != 0) { return result | DEMAND_CONVERSION; } } } return flags; }
resolvedTo = resolvedTo.getInvariantBoundSubstitute(); } else if (varianceHints.isEmpty() && typeArgument.getVariance() == VarianceInfo.OUT && allHints.size() == 1) { LightweightBoundTypeArgument singleHint = allHints.get(0); constraintTypeRef.getDeclaredVariance() == VarianceInfo.OUT && constraintTypeRef.getActualVariance() == VarianceInfo.INVARIANT) { if (resolvedTo.getKind() == LightweightTypeReference.KIND_WILDCARD_TYPE_REFERENCE && ((WildcardTypeReference) resolvedTo).getLowerBound() != null) { if(resolvedTo.getInvariantBoundSubstitute().isAssignableFrom(constraintTypeRef.getTypeReference())) { WildcardTypeReference wildcard = resolvedTo.getOwner().newWildcardTypeReference(); wildcard.addUpperBound(resolvedTo.getInvariantBoundSubstitute()); resolvedTo = wildcard;
@Override protected void doVisitArrayTypeReference(ArrayTypeReference reference, ParameterizedTypeReference declaration) { JvmType type = declaration.getType(); if (type instanceof JvmTypeParameter) { if (shouldProcess((JvmTypeParameter) type)) { JvmTypeParameter typeParameter = (JvmTypeParameter) type; processTypeParameter(typeParameter, reference); } } else { if (!declaration.isRawType() && (declaration.isType(List.class) || declaration.isType(Collection.class) || declaration.isType(Iterable.class))) { LightweightTypeReference elementType = declaration.getTypeArguments().get(0); LightweightTypeReference componentType = reference.getComponentType(); outerVisit(componentType.getInvariantBoundSubstitute(), elementType); } } } }
UnboundTypeReference typeReference = state.getResolvedTypes().createUnboundTypeReference(expression, declaredTypeParameter); if (explicitTypeArgument != null && explicitTypeArgument.isValidHint()) { LightweightTypeReference substitute = explicitTypeArgument.getInvariantBoundSubstitute(); typeReference.acceptHint(substitute, BoundTypeArgumentSource.EXPLICIT, expression, VarianceInfo.INVARIANT, VarianceInfo.INVARIANT);
@Override protected LightweightTypeReference doVisitWildcardTypeReference(WildcardTypeReference reference, Set<JvmTypeParameter> visiting) { if (reference.isResolved() && reference.isOwnedBy(getOwner())) return reference; WildcardTypeReference result = getOwner().newWildcardTypeReference(); LightweightTypeReference lowerBound = reference.getLowerBound(); if (lowerBound != null) { LightweightTypeReference visited = visitTypeArgument(lowerBound, visiting, true); if (visited.isWildcard()) { LightweightTypeReference substitute = visited.getInvariantBoundSubstitute(); result.setLowerBound(substitute); } else { result.setLowerBound(visited); } } for(LightweightTypeReference upperBound: reference.getUpperBounds()) { LightweightTypeReference visitedArgument = visitTypeArgument(upperBound, visiting); LightweightTypeReference upperBoundSubstitute = visitedArgument.getUpperBoundSubstitute(); result.addUpperBound(upperBoundSubstitute); } if (result.getUpperBounds().isEmpty()) { throw new IllegalStateException("UpperBounds may not be empty"); } return result; } };
ITypeReferenceOwner owner = state.getReferenceOwner(); if(commonSetType != null) { LightweightTypeReference commonElementType = commonSetType.getTypeArguments().get(0).getInvariantBoundSubstitute(); if(isMapLiteral(expectedType, commonElementType)) { LightweightTypeReference mapTypeReference = createMapTypeReference(mapType, commonElementType, expectedType, owner);
if (boundTypeArgument.getVariance() == VarianceInfo.OUT) { WildcardTypeReference wildcard = getOwner().newWildcardTypeReference(); wildcard.addUpperBound(result.getInvariantBoundSubstitute()); result = wildcard; } else if (boundTypeArgument.getVariance() == VarianceInfo.IN) { WildcardTypeReference wildcard = getOwner().newWildcardTypeReference(); wildcard.addUpperBound(getObjectReference()); wildcard.setLowerBound(result.getInvariantBoundSubstitute()); result = wildcard;
existingReference.acceptHint(boundTypeReference.getInvariantBoundSubstitute(), BoundTypeArgumentSource.INFERRED, boundTypeArgument, VarianceInfo.OUT, VarianceInfo.OUT);