Exemple #1
0
  /**
   * Collect the substitutes into a map for certain type variables inside the receiver type e.g.
   * Collection<T>.collectSubstitutes(Collection<List<X>>, Map), will populate Map with: T -->
   * List<X> Constraints: A << F corresponds to: F.collectSubstitutes(..., A, ...,
   * CONSTRAINT_EXTENDS (1)) A = F corresponds to: F.collectSubstitutes(..., A, ...,
   * CONSTRAINT_EQUAL (0)) A >> F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_SUPER
   * (2))
   */
  public void collectSubstitutes(
      Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) {

    if ((this.tagBits & TagBits.HasTypeVariable) == 0) return;
    if (actualType == TypeBinding.NULL) return;

    switch (actualType.kind()) {
      case Binding.ARRAY_TYPE:
        int actualDim = actualType.dimensions();
        if (actualDim == this.dimensions) {
          this.leafComponentType.collectSubstitutes(
              scope, actualType.leafComponentType(), inferenceContext, constraint);
        } else if (actualDim > this.dimensions) {
          ArrayBinding actualReducedType =
              this.environment.createArrayType(
                  actualType.leafComponentType(), actualDim - this.dimensions);
          this.leafComponentType.collectSubstitutes(
              scope, actualReducedType, inferenceContext, constraint);
        }
        break;
      case Binding.TYPE_PARAMETER:
        // TypeVariableBinding variable = (TypeVariableBinding) otherType;
        // TODO (philippe) should consider array bounds, and recurse
        break;
    }
  }
  /* This method replaces the version that used to sit in LE. The parameter `annotations' is a flattened sequence of annotations,
     where each dimension's annotations end with a sentinel null. Leaf type can be an already annotated type.

     See ArrayBinding.swapUnresolved for further special case handling if incoming leafType is a URB that would resolve to a raw
     type later.
  */
  public ArrayBinding getArrayType(
      TypeBinding leafType, int dimensions, AnnotationBinding[] annotations) {

    ArrayBinding nakedType = null;
    TypeBinding[] derivedTypes = getDerivedTypes(leafType);
    for (int i = 0, length = derivedTypes.length; i < length; i++) {
      TypeBinding derivedType = derivedTypes[i];
      if (derivedType == null) break;
      if (!derivedType.isArrayType()
          || derivedType.dimensions() != dimensions
          || derivedType.leafComponentType() != leafType) // $IDENTITY-COMPARISON$
      continue;
      if (Util.effectivelyEqual(derivedType.getTypeAnnotations(), annotations))
        return (ArrayBinding) derivedType;
      if (!derivedType.hasTypeAnnotations()) nakedType = (ArrayBinding) derivedType;
    }
    if (nakedType == null) nakedType = super.getArrayType(leafType, dimensions);

    if (!haveTypeAnnotations(leafType, annotations)) return nakedType;

    ArrayBinding arrayType = new ArrayBinding(leafType, dimensions, this.environment);
    arrayType.id = nakedType.id;
    arrayType.setTypeAnnotations(annotations, this.isAnnotationBasedNullAnalysisEnabled);
    return (ArrayBinding) cacheDerivedType(leafType, nakedType, arrayType);
  }
 public TypeBinding checkResolvedType(
     TypeBinding type, Scope scope, int location, boolean hasError) {
   // SH}
   if (type.isArrayType() && ((ArrayBinding) type).leafComponentType == TypeBinding.VOID) {
     scope.problemReporter().cannotAllocateVoidArray(this);
     return null;
   }
   if (!(this
           instanceof
           QualifiedTypeReference) // QualifiedTypeReference#getTypeBinding called above will have
                                   // already checked deprecation
       && isTypeUseDeprecated(type, scope)) {
     reportDeprecatedType(type, scope);
   }
   type =
       scope
           .environment()
           .convertToRawType(type, false /*do not force conversion of enclosing types*/);
   if (type.leafComponentType().isRawType()
       && (this.bits & ASTNode.IgnoreRawTypeCheck) == 0
       && scope.compilerOptions().getSeverity(CompilerOptions.RawTypeReference)
           != ProblemSeverities.Ignore) {
     scope.problemReporter().rawTypeReference(this, type);
   }
   if (hasError) {
     resolveAnnotations(scope, 0); // don't apply null defaults to buggy type
     return type;
   } else {
     // store the computed type only if no error, otherwise keep the problem type instead
     this.resolvedType = type;
     resolveAnnotations(scope, location);
     return this
         .resolvedType; // pick up value that may have been changed in resolveAnnotations(..)
   }
 }
Exemple #4
0
  /* Answer true if the receiver type can be assigned to the argument type (right)
   */
  public boolean isCompatibleWith(TypeBinding otherType) {
    if (this == otherType) return true;

    switch (otherType.kind()) {
      case Binding.ARRAY_TYPE:
        ArrayBinding otherArray = (ArrayBinding) otherType;
        if (otherArray.leafComponentType.isBaseType())
          return false; // relying on the fact that all equal arrays are identical
        if (dimensions == otherArray.dimensions)
          return leafComponentType.isCompatibleWith(otherArray.leafComponentType);
        if (dimensions < otherArray.dimensions)
          return false; // cannot assign 'String[]' into 'Object[][]' but can assign 'byte[][]' into
                        // 'Object[]'
        break;
      case Binding.BASE_TYPE:
        return false;
      case Binding.WILDCARD_TYPE:
      case Binding.INTERSECTION_TYPE:
        return ((WildcardBinding) otherType).boundCheck(this);

      case Binding.TYPE_PARAMETER:
        // check compatibility with capture of ? super X
        if (otherType.isCapture()) {
          CaptureBinding otherCapture = (CaptureBinding) otherType;
          TypeBinding otherLowerBound;
          if ((otherLowerBound = otherCapture.lowerBound) != null) {
            if (!otherLowerBound.isArrayType()) return false;
            return this.isCompatibleWith(otherLowerBound);
          }
        }
        return false;
    }
    // Check dimensions - Java does not support explicitly sized dimensions for types.
    // However, if it did, the type checking support would go here.
    switch (otherType.leafComponentType().id) {
      case TypeIds.T_JavaLangObject:
      case TypeIds.T_JavaLangCloneable:
      case TypeIds.T_JavaIoSerializable:
        return true;
    }
    return false;
  }
  /** Collect argument type mapping, handling varargs */
  private static ParameterizedGenericMethodBinding inferFromArgumentTypes(
      Scope scope,
      MethodBinding originalMethod,
      TypeBinding[] arguments,
      TypeBinding[] parameters,
      InferenceContext inferenceContext) {
    if (originalMethod.isVarargs()) {
      int paramLength = parameters.length;
      int minArgLength = paramLength - 1;
      int argLength = arguments.length;
      // process mandatory arguments
      for (int i = 0; i < minArgLength; i++) {
        parameters[i].collectSubstitutes(
            scope, arguments[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
        if (inferenceContext.status == InferenceContext.FAILED)
          return null; // impossible substitution
      }
      // process optional arguments
      if (minArgLength < argLength) {
        TypeBinding varargType = parameters[minArgLength]; // last arg type - as is ?
        TypeBinding lastArgument = arguments[minArgLength];
        checkVarargDimension:
        {
          if (paramLength == argLength) {
            if (lastArgument == TypeBinding.NULL) break checkVarargDimension;
            switch (lastArgument.dimensions()) {
              case 0:
                break; // will remove one dim
              case 1:
                if (!lastArgument.leafComponentType().isBaseType()) break checkVarargDimension;
                break; // will remove one dim
              default:
                break checkVarargDimension;
            }
          }
          // eliminate one array dimension
          varargType = ((ArrayBinding) varargType).elementsType();
        }
        for (int i = minArgLength; i < argLength; i++) {
          varargType.collectSubstitutes(
              scope, arguments[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
          if (inferenceContext.status == InferenceContext.FAILED)
            return null; // impossible substitution
        }
      }
    } else {
      int paramLength = parameters.length;
      for (int i = 0; i < paramLength; i++) {
        parameters[i].collectSubstitutes(
            scope, arguments[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
        if (inferenceContext.status == InferenceContext.FAILED)
          return null; // impossible substitution
      }
    }
    TypeVariableBinding[] originalVariables = originalMethod.typeVariables;
    if (!resolveSubstituteConstraints(
        scope, originalVariables, inferenceContext, false /*ignore Ti<:Uk*/))
      return null; // impossible substitution

    // apply inferred variable substitutions - replacing unresolved variable with original ones in
    // param method
    TypeBinding[] inferredSustitutes = inferenceContext.substitutes;
    TypeBinding[] actualSubstitutes = inferredSustitutes;
    for (int i = 0, varLength = originalVariables.length; i < varLength; i++) {
      if (inferredSustitutes[i] == null) {
        if (actualSubstitutes == inferredSustitutes) {
          System.arraycopy(
              inferredSustitutes,
              0,
              actualSubstitutes = new TypeBinding[varLength],
              0,
              i); // clone to replace null with original variable in param method
        }
        actualSubstitutes[i] = originalVariables[i];
      } else if (actualSubstitutes != inferredSustitutes) {
        actualSubstitutes[i] = inferredSustitutes[i];
      }
    }
    ParameterizedGenericMethodBinding paramMethod =
        scope.environment().createParameterizedGenericMethod(originalMethod, actualSubstitutes);
    return paramMethod;
  }
 // return: ReductionResult or ConstraintFormula[]
 public Object reduce(InferenceContext18 inferenceContext) {
   switch (this.relation) {
     case COMPATIBLE:
       // 18.2.2:
       if (this.left.isProperType(true) && this.right.isProperType(true)) {
         return this.left.isCompatibleWith(this.right, inferenceContext.scope)
                 || this.left.isBoxingCompatibleWith(this.right, inferenceContext.scope)
             ? TRUE
             : FALSE;
       }
       if (this.left.isPrimitiveType()) {
         TypeBinding sPrime = inferenceContext.environment.computeBoxingType(this.left);
         return ConstraintTypeFormula.create(sPrime, this.right, COMPATIBLE, this.isSoft);
       }
       if (this.right.isPrimitiveType()) {
         TypeBinding tPrime = inferenceContext.environment.computeBoxingType(this.right);
         return ConstraintTypeFormula.create(this.left, tPrime, SAME, this.isSoft);
       }
       switch (this.right.kind()) {
         case Binding.ARRAY_TYPE:
           if (this.right.leafComponentType().kind() != Binding.PARAMETERIZED_TYPE) break;
           // $FALL-THROUGH$ array of parameterized is handled below:
         case Binding.PARAMETERIZED_TYPE:
           {
             //															  this.right = G<T1,T2,...> or G<T1,T2,...>[]k
             TypeBinding gs =
                 this.left.findSuperTypeOriginatingFrom(
                     this.right); // G<S1,S2,...> or G<S1,S2,...>[]k
             if (gs != null && gs.leafComponentType().isRawType()) {
               inferenceContext.recordUncheckedConversion(this);
               return TRUE;
             }
             break;
           }
       }
       return ConstraintTypeFormula.create(this.left, this.right, SUBTYPE, this.isSoft);
     case SUBTYPE:
       // 18.2.3:
       return reduceSubType(inferenceContext.scope, this.left, this.right);
     case SUPERTYPE:
       // 18.2.3:
       return reduceSubType(inferenceContext.scope, this.right, this.left);
     case SAME:
       if (inferenceContext.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled)
         if (!checkIVFreeTVmatch(this.left, this.right)) checkIVFreeTVmatch(this.right, this.left);
       // 18.2.4:
       return reduceTypeEquality(inferenceContext.object);
     case TYPE_ARGUMENT_CONTAINED:
       // 18.2.3:
       if (this.right.kind()
           != Binding.WILDCARD_TYPE) { // "If T is a type" ... all alternatives require "wildcard"
         if (this.left.kind() != Binding.WILDCARD_TYPE) {
           return ConstraintTypeFormula.create(this.left, this.right, SAME, this.isSoft);
         } else {
           return FALSE;
         }
       } else {
         WildcardBinding t = (WildcardBinding) this.right;
         if (t.boundKind == Wildcard.UNBOUND) return TRUE;
         if (t.boundKind == Wildcard.EXTENDS) {
           if (this.left.kind() != Binding.WILDCARD_TYPE) {
             return ConstraintTypeFormula.create(this.left, t.bound, SUBTYPE, this.isSoft);
           } else {
             WildcardBinding s = (WildcardBinding) this.left;
             switch (s.boundKind) {
               case Wildcard.UNBOUND:
                 return ConstraintTypeFormula.create(
                     inferenceContext.object, t.bound, SUBTYPE, this.isSoft);
               case Wildcard.EXTENDS:
                 return ConstraintTypeFormula.create(s.bound, t.bound, SUBTYPE, this.isSoft);
               case Wildcard.SUPER:
                 return ConstraintTypeFormula.create(
                     inferenceContext.object, t.bound, SAME, this.isSoft);
               default:
                 throw new IllegalArgumentException(
                     "Unexpected boundKind " + s.boundKind); // $NON-NLS-1$
             }
           }
         } else { // SUPER
           if (this.left.kind() != Binding.WILDCARD_TYPE) {
             return ConstraintTypeFormula.create(t.bound, this.left, SUBTYPE, this.isSoft);
           } else {
             WildcardBinding s = (WildcardBinding) this.left;
             if (s.boundKind == Wildcard.SUPER) {
               return ConstraintTypeFormula.create(t.bound, s.bound, SUBTYPE, this.isSoft);
             } else {
               return FALSE;
             }
           }
         }
       }
     default:
       throw new IllegalStateException("Unexpected relation kind " + this.relation); // $NON-NLS-1$
   }
 }
  /* Private subroutine for public APIs. Create an annotated version of the type. To materialize the annotated version, we can't use new since
     this is a general purpose method designed to deal type bindings of all types. "Clone" the incoming type, specializing for any enclosing type
     that may itself be possibly be annotated. This is so the binding for @Outer Outer.Inner != Outer.@Inner Inner != @Outer Outer.@Inner Inner.
     Likewise so the bindings for @Readonly List<@NonNull String> != @Readonly List<@Nullable String> != @Readonly List<@Interned String>
  */
  private TypeBinding getAnnotatedType(
      TypeBinding type, TypeBinding enclosingType, AnnotationBinding[] annotations) {
    if (type.kind() == Binding.PARAMETERIZED_TYPE) {
      return getParameterizedType(
          type.actualType(), type.typeArguments(), (ReferenceBinding) enclosingType, annotations);
    }
    TypeBinding nakedType = null;
    TypeBinding[] derivedTypes = getDerivedTypes(type);
    for (int i = 0, length = derivedTypes.length; i < length; i++) {
      TypeBinding derivedType = derivedTypes[i];
      if (derivedType == null) break;

      if (derivedType.enclosingType() != enclosingType
          || !Util.effectivelyEqual(
              derivedType.typeArguments(), type.typeArguments())) // $IDENTITY-COMPARISON$
      continue;

      switch (type.kind()) {
        case Binding.ARRAY_TYPE:
          if (!derivedType.isArrayType()
              || derivedType.dimensions() != type.dimensions()
              || derivedType.leafComponentType()
                  != type.leafComponentType()) // $IDENTITY-COMPARISON$
          continue;
          break;
        case Binding.RAW_TYPE:
          if (!derivedType.isRawType()
              || derivedType.actualType() != type.actualType()) // $IDENTITY-COMPARISON$
          continue;
          break;
        case Binding.WILDCARD_TYPE:
          if (!derivedType.isWildcard()
              || derivedType.actualType() != type.actualType()
              || derivedType.rank() != type.rank()
              || derivedType.boundKind() != type.boundKind()) // $IDENTITY-COMPARISON$
          continue;
          if (derivedType.bound() != type.bound()
              || !Util.effectivelyEqual(
                  derivedType.additionalBounds(), type.additionalBounds())) // $IDENTITY-COMPARISON$
          continue;
          break;
        default:
          switch (derivedType.kind()) {
            case Binding.ARRAY_TYPE:
            case Binding.RAW_TYPE:
            case Binding.WILDCARD_TYPE:
            case Binding.INTERSECTION_CAST_TYPE:
            case Binding.INTERSECTION_TYPE:
              continue;
          }
          break;
      }
      if (Util.effectivelyEqual(derivedType.getTypeAnnotations(), annotations)) {
        return derivedType;
      }
      if (!derivedType.hasTypeAnnotations()) nakedType = derivedType;
    }
    if (nakedType == null) nakedType = getUnannotatedType(type);

    if (!haveTypeAnnotations(type, enclosingType, null, annotations)) return nakedType;

    TypeBinding annotatedType = type.clone(enclosingType);
    annotatedType.id = nakedType.id;
    annotatedType.setTypeAnnotations(annotations, this.isAnnotationBasedNullAnalysisEnabled);
    TypeBinding keyType;
    switch (type.kind()) {
      case Binding.ARRAY_TYPE:
        keyType = type.leafComponentType();
        break;
      case Binding.RAW_TYPE:
      case Binding.WILDCARD_TYPE:
        keyType = type.actualType();
        break;
      default:
        keyType = nakedType;
        break;
    }
    return cacheDerivedType(keyType, nakedType, annotatedType);
  }
 protected TypeBinding internalResolveType(Scope scope, int location) {
   // handle the error here
   this.constant = Constant.NotAConstant;
   if (this.resolvedType != null) { // is a shared type reference which was already resolved
     if (this.resolvedType.isValidBinding()) {
       return this.resolvedType;
     } else {
       switch (this.resolvedType.problemId()) {
         case ProblemReasons.NotFound:
         case ProblemReasons.NotVisible:
         case ProblemReasons.InheritedNameHidesEnclosingName:
           TypeBinding type = this.resolvedType.closestMatch();
           if (type == null) return null;
           return scope
               .environment()
               .convertToRawType(type, false /*do not force conversion of enclosing types*/);
         default:
           return null;
       }
     }
   }
   boolean hasError;
   // {ObjectTeams: don't let SelectionNodeFound(null) prevent alternate searching strategies:
   SelectionNodeFound caughtException = null;
   TypeBinding type = null;
   try {
     // base import scope first:
     CompilationResult compilationResult = scope.referenceCompilationUnit().compilationResult();
     CompilationResult.CheckPoint cp = compilationResult.getCheckPoint(scope.referenceContext());
     try {
       type =
           checkResolveUsingBaseImportScope(
               scope, location, false); // apply TOLERATE strategy only as a last resort below
       // copied from below:
       if (type != null && type.isValidBinding()) {
         type =
             scope
                 .environment()
                 .convertToRawType(type, false /*do not force conversion of enclosing types*/);
         if (type.leafComponentType().isRawType()
             && (this.bits & ASTNode.IgnoreRawTypeCheck) == 0
             && scope.compilerOptions().getSeverity(CompilerOptions.RawTypeReference)
                 != ProblemSeverities.Ignore) {
           scope.problemReporter().rawTypeReference(this, type);
         }
         return type;
       }
     } catch (SelectionNodeFound snf) {
       if (snf.binding != null) throw snf; // found a valid node.
       caughtException = snf;
     } finally {
       if (caughtException != null || (type == null) || !type.isValidBinding())
         compilationResult.rollBack(cp);
     }
     // ~orig~:
     type = this.resolvedType = getTypeBinding(scope);
     if (type == null) {
       return null; // detected cycle while resolving hierarchy
     }
     // :~giro~
   } catch (SelectionNodeFound snf) {
     if (snf.binding != null) throw snf; // found a valid node.
     caughtException = snf;
   }
   // a third chance trying an anchored type:
   try {
     if ((caughtException != null) || (this.resolvedType.problemId() == ProblemReasons.NotFound)) {
       // anchored type
       TypeBinding result = resolveAnchoredType(scope);
       if (result != null) // did we do any better than before?
       type = this.resolvedType = result; // if non-null but ProblemBinding report below.
     }
   } catch (SelectionNodeFound snf2) {
     caughtException = snf2; // throw the newer exception instead.
   }
   // a forth chance trying a TOLERATED base imported type:
   try {
     if ((caughtException != null) || (this.resolvedType.problemId() == ProblemReasons.NotFound)) {
       if (this.baseclassDecapsulation == DecapsulationState.TOLERATED) {
         TypeBinding result = checkResolveUsingBaseImportScope(scope, -1, true);
         if (result != null) // did we do any better than before?
         type = this.resolvedType = result; // if non-null but ProblemBinding report below.
       }
     }
   } catch (SelectionNodeFound snf2) {
     caughtException = snf2; // throw the newer exception instead.
   } finally {
     // the attempt to prevent an exception failed:
     if (caughtException != null) throw caughtException;
   }
   // SH}
   if ((hasError = !type.isValidBinding()) == true) {
     reportInvalidType(scope);
     switch (type.problemId()) {
       case ProblemReasons.NotFound:
       case ProblemReasons.NotVisible:
       case ProblemReasons.InheritedNameHidesEnclosingName:
         type = type.closestMatch();
         if (type == null) return null;
         break;
       default:
         return null;
     }
   }
   // {ObjectTeams: Split method to make tail accessible:
   return checkResolvedType(type, scope, location, hasError);
 }
Exemple #9
0
  public static boolean checkInvocationArguments(
      BlockScope scope,
      Expression receiver,
      TypeBinding receiverType,
      MethodBinding method,
      Expression[] arguments,
      TypeBinding[] argumentTypes,
      boolean argsContainCast,
      InvocationSite invocationSite) {
    TypeBinding[] params = method.parameters;
    int paramLength = params.length;
    boolean isRawMemberInvocation =
        !method.isStatic()
            && !receiverType.isUnboundWildcard()
            && method.declaringClass.isRawType()
            && method.hasSubstitutedParameters();

    boolean uncheckedBoundCheck =
        (method.tagBits & TagBits.HasUncheckedTypeArgumentForBoundCheck) != 0;
    MethodBinding rawOriginalGenericMethod = null;
    if (!isRawMemberInvocation) {
      if (method instanceof ParameterizedGenericMethodBinding) {
        ParameterizedGenericMethodBinding paramMethod = (ParameterizedGenericMethodBinding) method;
        if (paramMethod.isRaw && method.hasSubstitutedParameters()) {
          rawOriginalGenericMethod = method.original();
        }
      }
    }
    int invocationStatus = INVOCATION_ARGUMENT_OK;
    if (arguments == null) {
      if (method.isVarargs()) {
        TypeBinding parameterType =
            ((ArrayBinding) params[paramLength - 1])
                .elementsType(); // no element was supplied for vararg parameter
        if (!parameterType.isReifiable()) {
          scope
              .problemReporter()
              .unsafeGenericArrayForVarargs(parameterType, (ASTNode) invocationSite);
        }
      }
    } else {
      if (method.isVarargs()) {
        // 4 possibilities exist for a call to the vararg method foo(int i, long ... value) :
        // foo(1), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new long[] {1, 2})
        int lastIndex = paramLength - 1;
        for (int i = 0; i < lastIndex; i++) {
          TypeBinding originalRawParam =
              rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i];
          invocationStatus |=
              checkInvocationArgument(
                  scope, arguments[i], params[i], argumentTypes[i], originalRawParam);
        }
        int argLength = arguments.length;
        if (lastIndex < argLength) { // vararg argument was provided
          TypeBinding parameterType = params[lastIndex];
          TypeBinding originalRawParam = null;

          if (paramLength != argLength
              || parameterType.dimensions() != argumentTypes[lastIndex].dimensions()) {
            parameterType =
                ((ArrayBinding) parameterType)
                    .elementsType(); // single element was provided for vararg parameter
            if (!parameterType.isReifiable()) {
              scope
                  .problemReporter()
                  .unsafeGenericArrayForVarargs(parameterType, (ASTNode) invocationSite);
            }
            originalRawParam =
                rawOriginalGenericMethod == null
                    ? null
                    : ((ArrayBinding) rawOriginalGenericMethod.parameters[lastIndex])
                        .elementsType();
          }
          for (int i = lastIndex; i < argLength; i++) {
            invocationStatus |=
                checkInvocationArgument(
                    scope, arguments[i], parameterType, argumentTypes[i], originalRawParam);
          }
        }
        if (paramLength == argLength) { // 70056
          int varargsIndex = paramLength - 1;
          ArrayBinding varargsType = (ArrayBinding) params[varargsIndex];
          TypeBinding lastArgType = argumentTypes[varargsIndex];
          int dimensions;
          if (lastArgType == TypeBinding.NULL) {
            if (!(varargsType.leafComponentType().isBaseType() && varargsType.dimensions() == 1))
              scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
          } else if (varargsType.dimensions <= (dimensions = lastArgType.dimensions())) {
            if (lastArgType.leafComponentType().isBaseType()) {
              dimensions--;
            }
            if (varargsType.dimensions < dimensions) {
              scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
            } else if (varargsType.dimensions == dimensions
                && lastArgType != varargsType
                && lastArgType.leafComponentType().erasure()
                    != varargsType.leafComponentType.erasure()
                && lastArgType.isCompatibleWith(varargsType.elementsType())
                && lastArgType.isCompatibleWith(varargsType)) {
              scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
            }
          }
        }
      } else {
        for (int i = 0; i < paramLength; i++) {
          TypeBinding originalRawParam =
              rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i];
          invocationStatus |=
              checkInvocationArgument(
                  scope, arguments[i], params[i], argumentTypes[i], originalRawParam);
        }
      }
      if (argsContainCast) {
        CastExpression.checkNeedForArgumentCasts(
            scope, receiver, receiverType, method, arguments, argumentTypes, invocationSite);
      }
    }
    if ((invocationStatus & INVOCATION_ARGUMENT_WILDCARD) != 0) {
      scope
          .problemReporter()
          .wildcardInvocation((ASTNode) invocationSite, receiverType, method, argumentTypes);
    } else if (!method.isStatic()
        && !receiverType.isUnboundWildcard()
        && method.declaringClass.isRawType()
        && method.hasSubstitutedParameters()) {
      scope.problemReporter().unsafeRawInvocation((ASTNode) invocationSite, method);
    } else if (rawOriginalGenericMethod != null
        || uncheckedBoundCheck
        || ((invocationStatus & INVOCATION_ARGUMENT_UNCHECKED) != 0
            && method instanceof ParameterizedGenericMethodBinding
        /*&& method.returnType != scope.environment().convertToRawType(method.returnType.erasure(), true)*/ )) {
      scope
          .problemReporter()
          .unsafeRawGenericMethodInvocation((ASTNode) invocationSite, method, argumentTypes);
      return true;
    }
    return false;
  }
Exemple #10
0
  public TypeBinding resolveTypeExpecting(BlockScope scope, TypeBinding expectedType) {
    // Array initializers can only occur on the right hand side of an assignment
    // expression, therefore the expected type contains the valid information
    // concerning the type that must be enforced by the elements of the array initializer.

    // this method is recursive... (the test on isArrayType is the stop case)

    this.constant = Constant.NotAConstant;

    if (expectedType instanceof ArrayBinding) {
      // allow new List<?>[5]
      if ((this.bits & IsAnnotationDefaultValue)
          == 0) { // annotation default value need only to be commensurate JLS9.7
        // allow new List<?>[5] - only check for generic array when no initializer, since also
        // checked inside initializer resolution
        TypeBinding leafComponentType = expectedType.leafComponentType();
        if (!leafComponentType.isReifiable()) {
          scope.problemReporter().illegalGenericArray(leafComponentType, this);
        }
      }
      this.resolvedType = this.binding = (ArrayBinding) expectedType;
      if (this.expressions == null) return this.binding;
      TypeBinding elementType = this.binding.elementsType();
      for (int i = 0, length = this.expressions.length; i < length; i++) {
        Expression expression = this.expressions[i];
        expression.setExpectedType(elementType);
        TypeBinding expressionType =
            expression instanceof ArrayInitializer
                ? expression.resolveTypeExpecting(scope, elementType)
                : expression.resolveType(scope);
        if (expressionType == null) continue;

        // Compile-time conversion required?
        if (elementType
            != expressionType) // must call before computeConversion() and typeMismatchError()
        scope.compilationUnitScope().recordTypeConversion(elementType, expressionType);

        if (expression.isConstantValueOfTypeAssignableToType(expressionType, elementType)
            || expressionType.isCompatibleWith(elementType)) {
          expression.computeConversion(scope, elementType, expressionType);
        } else if (scope.isBoxingCompatibleWith(expressionType, elementType)
            || (expressionType.isBaseType() // narrowing then boxing ?
                && scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 // autoboxing
                && !elementType.isBaseType()
                && expression.isConstantValueOfTypeAssignableToType(
                    expressionType, scope.environment().computeBoxingType(elementType)))) {
          expression.computeConversion(scope, elementType, expressionType);
        } else {
          scope.problemReporter().typeMismatchError(expressionType, elementType, expression, null);
        }
      }
      return this.binding;
    }

    // infer initializer type for error reporting based on first element
    TypeBinding leafElementType = null;
    int dim = 1;
    if (this.expressions == null) {
      leafElementType = scope.getJavaLangObject();
    } else {
      Expression expression = this.expressions[0];
      while (expression != null && expression instanceof ArrayInitializer) {
        dim++;
        Expression[] subExprs = ((ArrayInitializer) expression).expressions;
        if (subExprs == null) {
          leafElementType = scope.getJavaLangObject();
          expression = null;
          break;
        }
        expression = ((ArrayInitializer) expression).expressions[0];
      }
      if (expression != null) {
        leafElementType = expression.resolveType(scope);
      }
      // fault-tolerance - resolve other expressions as well
      for (int i = 1, length = this.expressions.length; i < length; i++) {
        expression = this.expressions[i];
        if (expression != null) {
          expression.resolveType(scope);
        }
      }
    }
    if (leafElementType != null) {
      this.resolvedType = scope.createArrayType(leafElementType, dim);
      if (expectedType != null)
        scope.problemReporter().typeMismatchError(this.resolvedType, expectedType, this, null);
    }
    return null;
  }