protected LightweightBoundTypeArgument copyBoundTypeArgument(LightweightTypeReference typeReference, LightweightBoundTypeArgument boundTypeArgument) { return new LightweightBoundTypeArgument(typeReference, boundTypeArgument.getSource(), boundTypeArgument.getOrigin(), boundTypeArgument.getDeclaredVariance(), boundTypeArgument.getActualVariance()); }
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; }
private void addVariance(LightweightBoundTypeArgument boundTypeArgument, List<VarianceInfo> result, Object origin, Set<Object> seenOrigin) { if (seenOrigin.add(origin) || origin == null || boundTypeArgument.isValidVariancePair()) { result.add(boundTypeArgument.getActualVariance()); } }
protected boolean hasSignificantHints(List<LightweightBoundTypeArgument> hints, boolean constraintsAreSignificant) { for (LightweightBoundTypeArgument hint: hints) { if (!(hint.getOrigin() instanceof VarianceInfo)) { if (constraintsAreSignificant || hint.getSource() != BoundTypeArgumentSource.CONSTRAINT) return true; } } return false; }
private boolean isTransitiveHintFromReslved(LightweightBoundTypeArgument boundTypeArgument, Object origin, BoundTypeArgumentSource source) { return (origin instanceof LightweightBoundTypeArgument && ((LightweightBoundTypeArgument) origin).getSource() == BoundTypeArgumentSource.RESOLVED) && source == BoundTypeArgumentSource.INFERRED && boundTypeArgument.getActualVariance() == VarianceInfo.OUT; }
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); }
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; }
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 LightweightBoundTypeArgument boundByConstraint(LightweightTypeReference reference, Object origin) { return new LightweightBoundTypeArgument(reference.getWrapperTypeIfPrimitive(), BoundTypeArgumentSource.CONSTRAINT, origin, VarianceInfo.OUT, VarianceInfo.OUT); }
@Override protected LightweightTypeReference doVisitUnboundTypeReference(UnboundTypeReference reference, Object param) { if (reference.internalIsResolved()) { return super.doVisitUnboundTypeReference(reference, param); } else { List<LightweightBoundTypeArgument> hints = reference.getAllHints(); for (LightweightBoundTypeArgument hint : hints) { BoundTypeArgumentSource source = hint.getSource(); if (source == BoundTypeArgumentSource.INFERRED || source == BoundTypeArgumentSource.EXPECTATION || source == BoundTypeArgumentSource.INFERRED_CONSTRAINT) { reference.tryResolve(); if (reference.internalIsResolved()) { return reference.accept(this, param); } } } } return reference; }
if (VarianceInfo.OUT.equals(singleArgument.getActualVariance()) && singleArgument.getActualVariance().equals(singleArgument.getDeclaredVariance())) { LightweightTypeReference singleReference = singleArgument.getTypeReference(); if (singleReference.isResolved()) return candidate.isAssignableFrom(singleReference, TypeConformanceComputationArgument.DEFAULT);
List<LightweightBoundTypeArgument> expectationHints = null; for(LightweightBoundTypeArgument hint: allHints) { if (hint.getOrigin() instanceof VarianceInfo) { varianceHints.add((VarianceInfo) hint.getOrigin()); } else { if (hint.getSource() == BoundTypeArgumentSource.CONSTRAINT) { hasContraintHints = true; if (hint.getSource() == BoundTypeArgumentSource.INFERRED) { if (inferredHints.isEmpty()) { hasInferred = true; if (hint.getSource() == BoundTypeArgumentSource.INFERRED_EXPECTATION) { if (expectationHints == null) { expectationHints = Lists.newArrayListWithCapacity(2); if (!hasInferred && hint.getSource() == BoundTypeArgumentSource.INFERRED_CONSTRAINT) { inferredConstraintHints.add(hint);
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 void acceptHint(VarianceInfo variance) { acceptHint(new LightweightBoundTypeArgument(null, null, variance, null, null)); }
@Override protected void doVisitUnboundTypeReference(UnboundTypeReference reference, UnboundTypeReference declaration) { if (declaration.internalIsResolved() || getOwner().isResolved(declaration.getHandle())) { declaration.tryResolve(); outerVisit(declaration, reference, declaration, getExpectedVariance(), getActualVariance()); } else { if (getParametersToProcess().contains(declaration.getTypeParameter()) && VarianceInfo.OUT == getActualVariance() && VarianceInfo.OUT == getExpectedVariance()) { if (getDefaultSource() == BoundTypeArgumentSource.EXPECTATION) { List<LightweightBoundTypeArgument> hints = reference.getAllHints(); for(int i = 0; i < hints.size(); i++) { if (hints.get(i).getSource() == BoundTypeArgumentSource.INFERRED) { return; } } } } acceptHint(declaration, reference); } }
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); } else { LightweightBoundTypeArgument delegateHint = new LightweightBoundTypeArgument( upperBound, original.getSource(), hint.getOrigin(), hint.getDeclaredVariance(), original.getActualVariance()); result.add(delegateHint); if (original.getDeclaredVariance() == VarianceInfo.OUT && original.getActualVariance() == VarianceInfo.INVARIANT) { if (hint.getDeclaredVariance() == VarianceInfo.OUT && hint.getActualVariance() == VarianceInfo.INVARIANT) { continue;
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); } } } }
protected boolean canResolveTo(LightweightTypeReference reference, List<LightweightBoundTypeArgument> allHints) { List<LightweightBoundTypeArgument> inferredHints = Lists.newArrayListWithCapacity(allHints.size()); List<LightweightBoundTypeArgument> effectiveHints = Lists.newArrayListWithCapacity(allHints.size()); EnumSet<VarianceInfo> varianceHints = EnumSet.noneOf(VarianceInfo.class); for(LightweightBoundTypeArgument hint: allHints) { if (hint.getOrigin() instanceof VarianceInfo) { varianceHints.add((VarianceInfo) hint.getOrigin()); } else { effectiveHints.add(hint); if (hint.getSource() == BoundTypeArgumentSource.INFERRED) { inferredHints.add(hint); } } } if (effectiveHints.isEmpty()) return false; boolean result = getServices().getBoundTypeArgumentMerger().isPossibleMergeResult(!inferredHints.isEmpty() ? inferredHints : effectiveHints, reference); return result; }
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; }
private LightweightBoundTypeArgument boundByInference(LightweightTypeReference reference) { return new LightweightBoundTypeArgument(reference.getWrapperTypeIfPrimitive(), BoundTypeArgumentSource.INFERRED, getOrigin(), getExpectedVariance(), getActualVariance()); } }