private void processBoundTypeArgument(LightweightBoundTypeArgument boundTypeArgument, List<LightweightTypeReference> types, List<VarianceInfo> variances, Object origin, Set<Object> seenOrigin) { types.add(boundTypeArgument.getTypeReference()); addVariance(boundTypeArgument, variances, origin, seenOrigin); }
protected void addNonRecursiveHints(List<LightweightBoundTypeArgument> hints, Set<Object> seenHandles, List<LightweightBoundTypeArgument> result) { for(LightweightBoundTypeArgument hint: hints) { LightweightTypeReference reference = hint.getTypeReference(); if (reference instanceof UnboundTypeReference) { addNonRecursiveHints(hint, (UnboundTypeReference)reference, seenHandles, result); } else { if (!result.contains(hint)) result.add(hint); } } }
public List<LightweightBoundTypeArgument> getAllHints(Object handle) { List<LightweightBoundTypeArgument> actualHints = getHints(handle); int i = 0; while(i < actualHints.size()) { LightweightBoundTypeArgument hint = actualHints.get(i); if (hint.getTypeReference() instanceof UnboundTypeReference) { break; } i++; } if (i >= actualHints.size()) return actualHints; List<LightweightBoundTypeArgument> transitivity = Lists.newArrayList(); Set<Object> seenHandles = Sets.newHashSet(handle); transitivity.addAll(actualHints.subList(0, i)); List<LightweightBoundTypeArgument> allRemaining = actualHints.subList(i, actualHints.size()); addNonRecursiveHints(allRemaining, seenHandles, transitivity); return transitivity; }
protected boolean isUnknownReceiverType(LightweightTypeReference receiverType) { if (receiverType.isUnknown()) { return true; } if (receiverType instanceof UnboundTypeReference) { List<LightweightBoundTypeArgument> hints = ((UnboundTypeReference) receiverType).getAllHints(); for(LightweightBoundTypeArgument hint: hints) { LightweightTypeReference typeReference = hint.getTypeReference(); if (typeReference != null && typeReference.isUnknown()) return true; } } return false; }
private boolean isConstrainedRecursiveHintCheck(List<LightweightBoundTypeArgument> leftHints, LightweightTypeReference right) { boolean hasConstraints = false; for(LightweightBoundTypeArgument leftHint: leftHints) { if (leftHint.getSource() == BoundTypeArgumentSource.CONSTRAINT) { hasConstraints = true; } if (leftHint.getSource() == BoundTypeArgumentSource.INFERRED_LATER && leftHint.getActualVariance() == VarianceInfo.INVARIANT) { if (!hasConstraints) { return false; } LightweightTypeReference leftHintReference = leftHint.getTypeReference(); if (leftHintReference.getUniqueIdentifier().equals(right.getUniqueIdentifier())) { return true; } } } return false; }
protected void addNonRecursiveHints(LightweightBoundTypeArgument original, List<LightweightBoundTypeArgument> hints, Set<Object> seenHandles, List<LightweightBoundTypeArgument> result) { for(LightweightBoundTypeArgument hint: hints) { LightweightTypeReference reference = hint.getTypeReference(); if (reference instanceof UnboundTypeReference) { addNonRecursiveHints(original, (UnboundTypeReference)reference, seenHandles, result); } else { if (original.getDeclaredVariance() == VarianceInfo.IN && hint.getTypeReference() instanceof WildcardTypeReference) { LightweightTypeReference upperBound = hint.getTypeReference().getUpperBoundSubstitute(); if (upperBound instanceof UnboundTypeReference) { addNonRecursiveHints(original, (UnboundTypeReference)upperBound, seenHandles, result);
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); } } } } } }
LightweightBoundTypeArgument parentHint = parentHints.get(0); LightweightBoundTypeArgument copy = new LightweightBoundTypeArgument( parentHint.getTypeReference().copyInto(getReferenceOwner()), parentHint.getSource(), parentHint.getOrigin(), parentHint.getDeclaredVariance(), List<LightweightBoundTypeArgument> withParentHints = Lists.newArrayListWithCapacity(parentHints.size() + result.size()); for(LightweightBoundTypeArgument parentHint: parentHints) { if (parentHint.getTypeReference() == null) { withParentHints.add(parentHint); } else { LightweightBoundTypeArgument copy = new LightweightBoundTypeArgument( parentHint.getTypeReference().copyInto(getReferenceOwner()), parentHint.getSource(), parentHint.getOrigin(),
public LightweightTypeReference internalGetResolvedTo() { if (resolvedTo != null) { if (!getOwner().isResolved(handle)) { throw new IllegalStateException("owner should know that this one is resolved"); } return resolvedTo; } if (getOwner().isResolved(getHandle())) { List<LightweightBoundTypeArgument> hints = getOwner().getAllHints(getHandle()); if (hints.isEmpty()) { throw new IllegalStateException("cannot have empty hints if marked as resolved"); } if (hints.size() != 1) return null; LightweightBoundTypeArgument singleHint = hints.get(0); if (singleHint.getSource() == BoundTypeArgumentSource.RESOLVED) { resolvedTo = singleHint.getTypeReference(); if (!getOwner().isResolved(handle)) { throw new IllegalStateException("owner should know that this one is resolved"); } return resolvedTo; } } return null; }
private JvmOperation findImplementingOperation(UnboundTypeReference unboundTypeReference) { List<LightweightBoundTypeArgument> hints = unboundTypeReference.getAllHints(); for(LightweightBoundTypeArgument hint: hints) { LightweightTypeReference hintReference = hint.getTypeReference(); if (hintReference != null && (hint.getSource() == BoundTypeArgumentSource.INFERRED || hint.getSource() == BoundTypeArgumentSource.INFERRED_EXPECTATION)) { List<JvmType> rawTypes = hintReference.getRawTypes(); JvmOperation result = findImplementingOperation(rawTypes); if (result != null) { return result; } } } return null; }
protected void propageResolvedTypeToConstraints(List<LightweightBoundTypeArgument> hints) { if (!resolvedTo.isRawType()) { for(LightweightBoundTypeArgument hint: hints) { LightweightTypeReference hintReference = hint.getTypeReference(); if (hintReference != null && !hintReference.isRawType() && hint.getSource() == BoundTypeArgumentSource.CONSTRAINT) { DeferredTypeParameterHintCollector collector = new DeferredTypeParameterHintCollector(getOwner()) { @Override protected BoundTypeArgumentSource getTypeArgumentSource() { return BoundTypeArgumentSource.INFERRED_CONSTRAINT; } @Override protected void addHint(UnboundTypeReference typeParameter, LightweightTypeReference reference) { if (typeParameter.getHandle() != getHandle()) super.addHint(typeParameter, reference); } }; collector.processPairedReferences(hintReference, resolvedTo); } } } }
for(int i = 0; i < hints.size() && canAddHint; i++) { LightweightBoundTypeArgument hint = hints.get(i); if (hint.getTypeReference() == null || (hint.getSource() != BoundTypeArgumentSource.EXPECTATION && hint.getSource() != BoundTypeArgumentSource.INFERRED_CONSTRAINT)) { canAddHint = false;
if (boundTypeArgument.getTypeReference() instanceof UnboundTypeReference && boundTypeArgument.getSource() != BoundTypeArgumentSource.CONSTRAINT) { UnboundTypeReference other = (UnboundTypeReference) boundTypeArgument.getTypeReference(); Object otherHandle = other.getHandle(); if (ensureTypeParameterHintsMapExists().containsKey(handle)) { if (existingValue.getTypeReference() instanceof UnboundTypeReference) { if (((UnboundTypeReference) existingValue.getTypeReference()).getHandle() == otherHandle) { if (existingValue.getActualVariance() == boundTypeArgument.getActualVariance() && existingValue.getDeclaredVariance() == boundTypeArgument.getDeclaredVariance()
public void acceptHint(LightweightBoundTypeArgument hint) { if (internalIsResolved()) { throw new IllegalStateException("Cannot add hints to a resolved reference"); } if (hint.getSource() == BoundTypeArgumentSource.EXPLICIT) { LightweightTypeReference reference = hint.getTypeReference(); if (!(reference instanceof ParameterizedTypeReference) && !reference.isArray() && !reference.isUnknown()) { throw new IllegalArgumentException("cannot set " + hint + " as explicit hint"); } if (!getAllHints().isEmpty()) { throw new IllegalStateException("Cannot set explicit hint if other hints are present: " + getAllHints()); } this.resolvedTo = reference; getOwner().acceptHint(getHandle(), new LightweightBoundTypeArgument(resolvedTo, BoundTypeArgumentSource.RESOLVED, this, hint.getDeclaredVariance(), hint.getActualVariance())); return; } getOwner().acceptHint(this.getHandle(), hint); }
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); }
@Override public LightweightTypeReference doVisitUnboundTypeReference(UnboundTypeReference reference, Set<JvmTypeParameter> visiting) { if (reference.getHandle() == left.getHandle()) { if (right.getKind() == KIND_UNBOUND_TYPE_REFERENCE) { UnboundTypeReference rightUnbound = (UnboundTypeReference) right; List<LightweightBoundTypeArgument> rightHints = rightUnbound.getAllHints(); for(LightweightBoundTypeArgument rightHint: rightHints) { LightweightTypeReference rightHintReference = rightHint.getTypeReference(); if (rightHintReference != null && leftHintReference.getUniqueIdentifier().equals(rightHintReference.getUniqueIdentifier())) { return super.doVisitUnboundTypeReference(reference, visiting); } } } return rightTypeArgument.getTypeReference(); } return super.doVisitUnboundTypeReference(reference, visiting); } };
for(LightweightBoundTypeArgument leftHint: leftHints) { if (leftHint.getSource() == BoundTypeArgumentSource.CONSTRAINT) { final LightweightTypeReference leftHintReference = leftHint.getTypeReference(); if (!leftHintReference.getUniqueIdentifier().equals(right.getUniqueIdentifier())) { final LightweightMergedBoundTypeArgument rightTypeArgument = new LightweightMergedBoundTypeArgument(right.getWrapperTypeIfPrimitive(), VarianceInfo.INVARIANT);
LightweightBoundTypeArgument singleArgument = allArguments.get(0); if (VarianceInfo.OUT.equals(singleArgument.getActualVariance()) && singleArgument.getActualVariance().equals(singleArgument.getDeclaredVariance())) { LightweightTypeReference singleReference = singleArgument.getTypeReference(); if (singleReference.isResolved()) return candidate.isAssignableFrom(singleReference, TypeConformanceComputationArgument.DEFAULT);
} else { LightweightBoundTypeArgument copy = new LightweightBoundTypeArgument( boundTypeArgument.getTypeReference().copyInto(parent.getReferenceOwner()), boundTypeArgument.getSource(), boundTypeArgument.getOrigin(), boundTypeArgument.getDeclaredVariance(),
protected boolean isExpectedType(LightweightTypeReference expectation, Class<?> clazz) { if (expectation != null) { if (expectation.isResolved() && isSubtypeButNotSynonym(expectation, clazz)) { return true; } if (expectation instanceof UnboundTypeReference) { if (expectation.getOwner().newParameterizedTypeReference(((UnboundTypeReference) expectation).getTypeParameter()).isSubtypeOf(clazz)) { return true; } List<LightweightBoundTypeArgument> hints = ((UnboundTypeReference) expectation).getAllHints(); for(LightweightBoundTypeArgument hint: hints) { LightweightTypeReference hintReference = hint.getTypeReference(); if (hintReference != null && isSubtypeButNotSynonym(hintReference, clazz)) { return true; } } } else if (expectation instanceof ParameterizedTypeReference) { return isSubtypeButNotSynonym(expectation, clazz); } } return false; }