@Override protected Map<JvmTypeParameter, LightweightMergedBoundTypeArgument> computeContextTypeParameterMapping() { if (typeArguments.isEmpty()) { return super.computeContextTypeParameterMapping(); } Map<JvmTypeParameter, LightweightMergedBoundTypeArgument> result = Maps.newHashMap(super.computeContextTypeParameterMapping()); List<JvmTypeParameter> typeParameters = getDeclaration().getTypeParameters(); for(int i = 0; i < Math.min(typeParameters.size(), typeArguments.size()); i++) { result.put(typeParameters.get(i), new LightweightMergedBoundTypeArgument(typeArguments.get(i), VarianceInfo.INVARIANT)); } return result; }
@Override /* @Nullable */ protected LightweightTypeReference getBoundTypeArgument(ParameterizedTypeReference reference, JvmTypeParameter type, Set<JvmTypeParameter> visiting) { LightweightMergedBoundTypeArgument boundTypeArgument = getTypeParameterMapping().get(type); if (boundTypeArgument != null && boundTypeArgument.getTypeReference() != reference) { LightweightTypeReference boundReference = boundTypeArgument.getTypeReference(); if (boundTypeArgument.getVariance() == VarianceInfo.OUT) { WildcardTypeReference wildcard = getOwner().newWildcardTypeReference(); wildcard.addUpperBound(boundReference); boundReference = wildcard; } return boundReference.accept(this, visiting); } return null; } };
@Override /* @Nullable */ protected LightweightMergedBoundTypeArgument getBoundTypeArgument(JvmTypeParameter typeParameter, ConstraintVisitingInfo info) { LightweightMergedBoundTypeArgument result = super.getBoundTypeArgument(typeParameter, info); if (result != null) { LightweightTypeReference typeReference = result.getTypeReference(); if (result.getVariance() == VarianceInfo.INVARIANT) { if (typeReference.isWildcard() && typeReference.getLowerBoundSubstitute().isAny() && typeReference.getUpperBoundSubstitute().isType(Object.class)) { // assume unbound wildcard - use the constraints of the respective type parameter if (!typeParameter.getConstraints().isEmpty()) { JvmTypeConstraint constraint = typeParameter.getConstraints().get(0); if (constraint instanceof JvmUpperBound) { LightweightTypeReference reference = getOwner().toLightweightTypeReference(constraint.getTypeReference()); return new LightweightMergedBoundTypeArgument(reference, VarianceInfo.OUT); } } } } if (declaratorParameterMapping.containsKey(typeParameter) && typeReference.isWildcard()) { wasCapturedWildcard = true; } } return result; }
@Override protected LightweightTypeReference doVisitUnboundTypeReference(UnboundTypeReference reference, ConstraintVisitingInfo visiting) { if (!handle.equals(reference.getHandle())) { return reference; } JvmTypeParameter typeParameter = reference.getTypeParameter(); if (!visiting.tryVisit(typeParameter)) { LightweightTypeReference mappedReference = getDeclaredUpperBound(typeParameter, visiting); getTypeParameterMapping().put(typeParameter, new LightweightMergedBoundTypeArgument(mappedReference, VarianceInfo.INVARIANT)); if (mappedReference != null) return mappedReference; return getObjectReference(); } try { LightweightMergedBoundTypeArgument boundTypeArgument = getTypeParameterMapping().get(typeParameter); if (boundTypeArgument != null && boundTypeArgument.getTypeReference() != reference) { LightweightTypeReference result = boundTypeArgument.getTypeReference().accept(this, visiting); return result; } else { LightweightTypeReference mappedReference = getDeclaredUpperBound(visiting.getCurrentDeclarator(), visiting.getCurrentIndex(), visiting); getTypeParameterMapping().put(typeParameter, new LightweightMergedBoundTypeArgument(mappedReference, VarianceInfo.INVARIANT)); return mappedReference; } } finally { visiting.didVisit(typeParameter); } }
protected JvmTypeParameter findMappedParameter(JvmTypeParameter parameter, Map<JvmTypeParameter, LightweightMergedBoundTypeArgument> mapping, Collection<JvmTypeParameter> visited) { for(Map.Entry<JvmTypeParameter, LightweightMergedBoundTypeArgument> entry: mapping.entrySet()) { LightweightMergedBoundTypeArgument reference = entry.getValue(); JvmType type = reference.getTypeReference().getType(); if (parameter == type) { if (visited.add(entry.getKey())) return entry.getKey(); return null; } } return null; } }
} else { LightweightMergedBoundTypeArgument mergeResult = state.getMergeResult(left); if (mergeResult != null && mergeResult.getVariance() != null) { return isConformantMergeResult(mergeResult, right, flags);
if (visiting.getCurrentDeclarator() != null) { LightweightTypeReference mappedReference = getDeclaredUpperBound(visiting.getCurrentDeclarator(), visiting.getCurrentIndex(), visiting); getTypeParameterMapping().put((JvmTypeParameter)type, new LightweightMergedBoundTypeArgument(mappedReference, VarianceInfo.INVARIANT)); return mappedReference; } else { LightweightMergedBoundTypeArgument candidate = getTypeParameterMapping().get(typeParameter); if (candidate != null && candidate.getTypeReference() != null) return candidate.getTypeReference(); LightweightTypeReference mappedReference = getDeclaredUpperBound(typeParameter, visiting); if (mappedReference == null) { mappedReference = getObjectReference(); getTypeParameterMapping().put((JvmTypeParameter)type, new LightweightMergedBoundTypeArgument(mappedReference, VarianceInfo.INVARIANT)); return mappedReference; try { LightweightMergedBoundTypeArgument boundTypeArgument = getBoundTypeArgument(typeParameter, visiting); if (boundTypeArgument != null && boundTypeArgument.getTypeReference() != reference) { LightweightTypeReference result = boundTypeArgument.getTypeReference().accept(this, visiting); 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()); LightweightTypeReference mappedReference = getUnmappedSubstitute(reference, (JvmTypeParameter) type, visiting); if (mappedReference != null) {
@Override protected LightweightTypeReference doVisitUnboundTypeReference(UnboundTypeReference reference, ConstraintVisitingInfo visiting) { JvmTypeParameter typeParameter = reference.getTypeParameter(); if (!visiting.tryVisit(typeParameter)) { LightweightTypeReference mappedReference = getDeclaredUpperBound(typeParameter, visiting); getTypeParameterMapping().put(typeParameter, new LightweightMergedBoundTypeArgument(mappedReference, VarianceInfo.INVARIANT)); if (mappedReference != null) return mappedReference; return getObjectReference(); } try { LightweightMergedBoundTypeArgument boundTypeArgument = getTypeParameterMapping().get(typeParameter); if (boundTypeArgument != null && boundTypeArgument.getTypeReference() != reference) { LightweightTypeReference result = boundTypeArgument.getTypeReference().accept(this, visiting); return result; } else { JvmTypeParameterDeclarator currentDeclarator = visiting.getCurrentDeclarator(); LightweightTypeReference mappedReference = currentDeclarator != null ? getDeclaredUpperBound(currentDeclarator, visiting.getCurrentIndex(), visiting) : getDeclaredUpperBound(typeParameter, visiting); if (mappedReference == null) mappedReference = getObjectReference(); getTypeParameterMapping().put(typeParameter, new LightweightMergedBoundTypeArgument(mappedReference, VarianceInfo.INVARIANT)); return mappedReference; } } finally { visiting.didVisit(typeParameter); } }
@Override public List<LightweightTypeReference> getTypeArguments() { if (typeArguments == null) { List<JvmTypeParameter> typeParameters = getDeclaredTypeParameters(); if (typeParameters.isEmpty() || getTypeParameterMapping().isEmpty()) { typeArguments = Collections.emptyList(); } else { List<LightweightTypeReference> result = Lists.newArrayListWithCapacity(typeParameters.size()); for(JvmTypeParameter parameter: typeParameters) { LightweightMergedBoundTypeArgument typeArgument = getTypeParameterMapping().get(parameter); result.add(typeArgument.getTypeReference()); } typeArguments = result; } } return typeArguments; }
public static void resolveAgainstActualType(final LightweightTypeReference declaredType, LightweightTypeReference actualType, Collection<JvmTypeParameter> typeParameters, Map<JvmTypeParameter, LightweightMergedBoundTypeArgument> typeParameterMapping, BoundTypeArgumentSource source, ITypeReferenceOwner owner) { if (declaredType.isRawType() || actualType.isRawType()) return; TypeArgumentFromComputedTypeCollector implementation = new TypeArgumentFromComputedTypeCollector(typeParameters, source, owner); implementation.populateTypeParameterMapping(declaredType, actualType); Map<JvmTypeParameter, List<LightweightBoundTypeArgument>> parameterMapping = implementation.rawGetTypeParameterMapping(); for(Map.Entry<JvmTypeParameter, List<LightweightBoundTypeArgument>> entry: parameterMapping.entrySet()) { LightweightMergedBoundTypeArgument boundTypeArgument = typeParameterMapping.get(entry.getKey()); if (boundTypeArgument != null ) { List<LightweightBoundTypeArgument> computedBoundTypeArguments = entry.getValue(); for(LightweightBoundTypeArgument computedBoundTypeArgument: computedBoundTypeArguments) { if (computedBoundTypeArgument.getSource() == BoundTypeArgumentSource.RESOLVED) { VarianceInfo varianceInfo = computedBoundTypeArgument.getDeclaredVariance().mergeDeclaredWithActual(computedBoundTypeArgument.getActualVariance()); typeParameterMapping.put(entry.getKey(), new LightweightMergedBoundTypeArgument(computedBoundTypeArgument.getTypeReference(), varianceInfo)); } else if (boundTypeArgument.getTypeReference() instanceof UnboundTypeReference) { UnboundTypeReference typeReference = (UnboundTypeReference) boundTypeArgument.getTypeReference(); if (!typeReference.internalIsResolved()) { if (!(computedBoundTypeArgument.getTypeReference() instanceof UnboundTypeReference) || ((UnboundTypeReference) computedBoundTypeArgument.getTypeReference()).getHandle() != typeReference.getHandle()) typeReference.acceptHint(computedBoundTypeArgument); } } } } } }
LightweightMergedBoundTypeArgument typeArgument = getServices().getBoundTypeArgumentMerger().merge(!inferredHints.isEmpty() ? inferredHints : effectiveHints, getOwner()); if (typeArgument != null) { resolvedTo = typeArgument.getTypeReference(); if (resolvedTo != null) { boolean outResolvedToInvariant = varianceHints.contains(VarianceInfo.OUT) && varianceHints.size() == 1 && typeArgument.getVariance() == VarianceInfo.INVARIANT; if (outResolvedToInvariant && (resolvedTo.getKind() == LightweightTypeReference.KIND_WILDCARD_TYPE_REFERENCE)) { resolvedTo = resolvedTo.getUpperBoundSubstitute(); resolvedTo = constraintTypeRef; } else if (varianceHints.contains(VarianceInfo.IN) && varianceHints.size() == 1 && typeArgument.getVariance() == VarianceInfo.INVARIANT && (resolvedTo instanceof WildcardTypeReference)) { resolvedTo = resolvedTo.getInvariantBoundSubstitute(); } else if (varianceHints.isEmpty() && typeArgument.getVariance() == VarianceInfo.OUT && allHints.size() == 1) { LightweightBoundTypeArgument singleHint = allHints.get(0); if (singleHint.getDeclaredVariance() == VarianceInfo.INVARIANT && singleHint.getSource() == BoundTypeArgumentSource.INFERRED_LATER) { resolvedTo = wildcard; } else if (varianceHints.isEmpty() && inferredConstraintHints.size() == 1 && typeArgument.getVariance() == VarianceInfo.INVARIANT) { LightweightBoundTypeArgument constraintTypeRef = inferredConstraintHints.get(0); if (constraintTypeRef.getTypeReference().getKind() != LightweightTypeReference.KIND_WILDCARD_TYPE_REFERENCE && this, VarianceInfo.INVARIANT, typeArgument.getVariance())); if (hasContraintHints) { propageResolvedTypeToConstraints(allHints);
protected LightweightTypeReference getBoundTypeArgument(ParameterizedTypeReference reference, JvmTypeParameter type, Visiting visiting) { LightweightMergedBoundTypeArgument boundTypeArgument = typeParameterMapping.get(type); if (boundTypeArgument != null) { LightweightTypeReference boundReference = boundTypeArgument.getTypeReference(); if (boundReference != null && reference != boundReference && boundReference.getType() != type) { return boundReference.accept(this, visiting); } } return null; }
protected void initializeMapping(JvmTypeParameter typeParameter, Map<JvmTypeParameter, LightweightMergedBoundTypeArgument> result) { UnboundTypeReference typeReference = state.getResolvedTypes().createUnboundTypeReference(expression, typeParameter); result.put(typeParameter, new LightweightMergedBoundTypeArgument(typeReference, VarianceInfo.INVARIANT)); }
typeReference.acceptHint(substitute, BoundTypeArgumentSource.EXPLICIT, expression, VarianceInfo.INVARIANT, VarianceInfo.INVARIANT); typeParameterMapping.put(declaredTypeParameter, new LightweightMergedBoundTypeArgument(typeReference, VarianceInfo.INVARIANT)); JvmTypeParameter declaredTypeParameter = declaredTypeParameters.get(i); LightweightMergedBoundTypeArgument boundTypeArgument = typeParameterMapping.get(declaredTypeParameter); LightweightTypeReference boundReference = boundTypeArgument.getTypeReference(); if (boundReference instanceof UnboundTypeReference) { initializeConstraintMapping(declaredTypeParameter, substitutor, (UnboundTypeReference) boundReference);
if (merged == null) return false; VarianceInfo variance = merged.getVariance(); LightweightTypeReference type = merged.getTypeReference(); if (variance == null || type == null) { return false;
public static JvmTypeParameter findMappedParameter(JvmTypeParameter parameter, Map<JvmTypeParameter, LightweightMergedBoundTypeArgument> mapping, Collection<JvmTypeParameter> visited) { for(Map.Entry<JvmTypeParameter, LightweightMergedBoundTypeArgument> entry: mapping.entrySet()) { LightweightTypeReference reference = entry.getValue().getTypeReference(); JvmType type = null; if (reference instanceof UnboundTypeReference) { type = ((UnboundTypeReference) reference).getTypeParameter(); } else { type = reference.getType(); } if (parameter == type) { if (visited.add(entry.getKey())) return entry.getKey(); return null; } } return null; }
@Override protected void initializeMapping(JvmTypeParameter typeParameter, Map<JvmTypeParameter, LightweightMergedBoundTypeArgument> result) { ITypeReferenceOwner owner = getState().getReferenceOwner(); if (typeParameter.getDeclarator() instanceof JvmType && owner.getDeclaredTypeParameters().contains(typeParameter)) { LightweightTypeReference typeReference = owner.newParameterizedTypeReference(typeParameter); result.put(typeParameter, new LightweightMergedBoundTypeArgument(typeReference, VarianceInfo.INVARIANT)); } else { super.initializeMapping(typeParameter, result); } }
@Override /* @Nullable */ protected LightweightMergedBoundTypeArgument getBoundTypeArgument(JvmTypeParameter type, ConstraintVisitingInfo info) { LightweightMergedBoundTypeArgument result = super.getBoundTypeArgument(type, info); if (result != null && result.getTypeReference().getType() == type) { return null; } return result; } };
result.addComponent(upperBound); data.getTypeParameterMapping().put(typeParameter, new LightweightMergedBoundTypeArgument(result, VarianceInfo.INVARIANT)); } else if (upperBounds.size() == 1) { data.getTypeParameterMapping().put(typeParameter, new LightweightMergedBoundTypeArgument(upperBounds.get(0), VarianceInfo.INVARIANT));
@Override /* @Nullable */ protected LightweightTypeReference getUnmappedSubstitute(ParameterizedTypeReference reference, JvmTypeParameter type, ConstraintVisitingInfo visiting) { if (!ignoreDeclaredTypeParameters) { if (isDeclaredTypeParameter(type)) { return reference; } } ConstraintAwareTypeArgumentCollector collector = new ConstraintAwareTypeArgumentCollector(getOwner()); LightweightTraversalData data = new LightweightTraversalData(); data.getTypeParameterMapping().putAll(getTypeParameterMapping()); reference.accept(collector, data); LightweightMergedBoundTypeArgument boundTypeArgument = data.getTypeParameterMapping().get(type); if (boundTypeArgument != null && boundTypeArgument.getTypeReference() != reference) { return boundTypeArgument.getTypeReference().accept(this, visiting); } if (boundTypeArgument != null) return boundTypeArgument.getTypeReference(); return null; }