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; }
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);
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 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 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; }
protected LightweightBoundTypeArgument copyBoundTypeArgument(LightweightTypeReference typeReference, LightweightBoundTypeArgument boundTypeArgument) { return new LightweightBoundTypeArgument(typeReference, boundTypeArgument.getSource(), boundTypeArgument.getOrigin(), boundTypeArgument.getDeclaredVariance(), boundTypeArgument.getActualVariance()); }
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; }
LightweightBoundTypeArgument copy = new LightweightBoundTypeArgument( parentHint.getTypeReference().copyInto(getReferenceOwner()), parentHint.getSource(), parentHint.getOrigin(), parentHint.getDeclaredVariance(), parentHint.getActualVariance()); LightweightBoundTypeArgument copy = new LightweightBoundTypeArgument( parentHint.getTypeReference().copyInto(getReferenceOwner()), parentHint.getSource(), parentHint.getOrigin(), parentHint.getDeclaredVariance(),
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); } } } }
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); }
public void acceptHint(Object handle, LightweightBoundTypeArgument boundTypeArgument) { if (boundTypeArgument.getSource() == BoundTypeArgumentSource.RESOLVED) { if (resolvedTypeParameters == null) { resolvedTypeParameters = new SharedKeysAwareSet<Object>(shared.allResolvedTypeParameters); if (boundTypeArgument.getTypeReference() instanceof UnboundTypeReference && boundTypeArgument.getSource() != BoundTypeArgumentSource.CONSTRAINT) { UnboundTypeReference other = (UnboundTypeReference) boundTypeArgument.getTypeReference(); Object otherHandle = other.getHandle(); if (existingValue.getActualVariance() == boundTypeArgument.getActualVariance() && existingValue.getDeclaredVariance() == boundTypeArgument.getDeclaredVariance() && existingValue.getSource() == boundTypeArgument.getSource()) { return;
@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; }
} else { LightweightBoundTypeArgument delegateHint = new LightweightBoundTypeArgument( upperBound, original.getSource(), hint.getOrigin(), hint.getDeclaredVariance(), original.getActualVariance()); result.add(delegateHint);
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); } } } } } }
int result = flags; for(LightweightBoundTypeArgument leftHint: leftHints) { if (leftHint.getSource() == BoundTypeArgumentSource.CONSTRAINT) { final LightweightTypeReference leftHintReference = leftHint.getTypeReference(); if (!leftHintReference.getUniqueIdentifier().equals(right.getUniqueIdentifier())) {
@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); } }
LightweightBoundTypeArgument copy = new LightweightBoundTypeArgument( boundTypeArgument.getTypeReference().copyInto(parent.getReferenceOwner()), boundTypeArgument.getSource(), boundTypeArgument.getOrigin(), boundTypeArgument.getDeclaredVariance(), boundTypeArgument.getActualVariance());
@Override protected void addHint(UnboundTypeReference typeParameter, LightweightTypeReference reference) { if (!typeParameter.internalIsResolved() && getExpectedVariance() == VarianceInfo.INVARIANT) { if (getExpectedVariance() == getActualVariance() && reference.getKind() != LightweightTypeReference.KIND_UNBOUND_TYPE_REFERENCE) { doAddHint(typeParameter, reference, BoundTypeArgumentSource.INFERRED_EXPECTATION); } else if (getActualVariance() == VarianceInfo.IN && !typeParameter.hasSignificantHints()) { if (reference.getKind() != LightweightTypeReference.KIND_UNBOUND_TYPE_REFERENCE) { doAddHint(typeParameter, reference, BoundTypeArgumentSource.INFERRED_EXPECTATION); } else { UnboundTypeReference casted = (UnboundTypeReference)reference; List<LightweightBoundTypeArgument> hints = casted.getAllHints(); for(LightweightBoundTypeArgument hint: hints) { // avoid bogus transitive hints, e.g. if a reference was used with another variance // INFERRED_LATER serves as an indicator for these hints if (hint.getSource() == BoundTypeArgumentSource.INFERRED_LATER) { return; } } doAddHint(typeParameter, reference, BoundTypeArgumentSource.INFERRED_EXPECTATION); } } } }