Exemple #1
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 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;

    if (actualType.isCapture()) {
      CaptureBinding capture = (CaptureBinding) actualType;
      actualType = capture.wildcard;
    }

    switch (constraint) {
      case TypeConstants.CONSTRAINT_EXTENDS: // A << F
        switch (this.boundKind) {
          case Wildcard.UNBOUND: // F={?}
            //						switch (actualType.kind()) {
            //						case Binding.WILDCARD_TYPE :
            //							WildcardBinding actualWildcard = (WildcardBinding) actualType;
            //							switch(actualWildcard.kind) {
            //								case Wildcard.UNBOUND: // A={?} << F={?}  --> 0
            //									break;
            //								case Wildcard.EXTENDS: // A={? extends V} << F={?} ---> 0
            //									break;
            //								case Wildcard.SUPER: // A={? super V} << F={?} ---> 0
            //									break;
            //							}
            //							break;
            //						case Binding.INTERSECTION_TYPE :// A={? extends V1&...&Vn} << F={?} ---> 0
            //							break;
            //						default :// A=V << F={?} ---> 0
            //							break;
            //						}
            break;
          case Wildcard.EXTENDS: // F={? extends U}
            switch (actualType.kind()) {
              case Binding.WILDCARD_TYPE:
                WildcardBinding actualWildcard = (WildcardBinding) actualType;
                switch (actualWildcard.boundKind) {
                  case Wildcard.UNBOUND: // A={?} << F={? extends U}  --> 0
                    break;
                  case Wildcard.EXTENDS: // A={? extends V} << F={? extends U} ---> V << U
                    this.bound.collectSubstitutes(
                        scope,
                        actualWildcard.bound,
                        inferenceContext,
                        TypeConstants.CONSTRAINT_EXTENDS);
                    break;
                  case Wildcard.SUPER: // A={? super V} << F={? extends U} ---> 0
                    break;
                }
                break;
              case Binding
                  .INTERSECTION_TYPE: // A={? extends V1&...&Vn} << F={? extends U} ---> V1 << U,
                                      // ..., Vn << U
                WildcardBinding actualIntersection = (WildcardBinding) actualType;
                this.bound.collectSubstitutes(
                    scope,
                    actualIntersection.bound,
                    inferenceContext,
                    TypeConstants.CONSTRAINT_EXTENDS);
                for (int i = 0, length = actualIntersection.otherBounds.length; i < length; i++) {
                  this.bound.collectSubstitutes(
                      scope,
                      actualIntersection.otherBounds[i],
                      inferenceContext,
                      TypeConstants.CONSTRAINT_EXTENDS);
                }
                break;
              default: // A=V << F={? extends U} ---> V << U
                this.bound.collectSubstitutes(
                    scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
                break;
            }
            break;
          case Wildcard.SUPER: // F={? super U}
            switch (actualType.kind()) {
              case Binding.WILDCARD_TYPE:
                WildcardBinding actualWildcard = (WildcardBinding) actualType;
                switch (actualWildcard.boundKind) {
                  case Wildcard.UNBOUND: // A={?} << F={? super U}  --> 0
                    break;
                  case Wildcard.EXTENDS: // A={? extends V} << F={? super U} ---> 0
                    break;
                  case Wildcard.SUPER: // A={? super V} << F={? super U} ---> 0
                    this.bound.collectSubstitutes(
                        scope,
                        actualWildcard.bound,
                        inferenceContext,
                        TypeConstants.CONSTRAINT_SUPER);
                    for (int i = 0,
                            length =
                                actualWildcard.otherBounds == null
                                    ? 0
                                    : actualWildcard.otherBounds.length;
                        i < length;
                        i++) {
                      this.bound.collectSubstitutes(
                          scope,
                          actualWildcard.otherBounds[i],
                          inferenceContext,
                          TypeConstants.CONSTRAINT_SUPER);
                    }
                    break;
                }
                break;
              case Binding.INTERSECTION_TYPE: // A={? extends V1&...&Vn} << F={? super U} ---> 0
                break;
              default: // A=V << F={? super U} ---> V >> U
                this.bound.collectSubstitutes(
                    scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
                break;
            }
            break;
        }
        break;
      case TypeConstants.CONSTRAINT_EQUAL: // A == F
        switch (this.boundKind) {
          case Wildcard.UNBOUND: // F={?}
            //						switch (actualType.kind()) {
            //						case Binding.WILDCARD_TYPE :
            //							WildcardBinding actualWildcard = (WildcardBinding) actualType;
            //							switch(actualWildcard.kind) {
            //								case Wildcard.UNBOUND: // A={?} == F={?}  --> 0
            //									break;
            //								case Wildcard.EXTENDS: // A={? extends V} == F={?} ---> 0
            //									break;
            //								case Wildcard.SUPER: // A={? super V} == F={?} ---> 0
            //									break;
            //							}
            //							break;
            //						case Binding.INTERSECTION_TYPE :// A={? extends V1&...&Vn} == F={?} ---> 0
            //							break;
            //						default :// A=V == F={?} ---> 0
            //							break;
            //						}
            break;
          case Wildcard.EXTENDS: // F={? extends U}
            switch (actualType.kind()) {
              case Binding.WILDCARD_TYPE:
                WildcardBinding actualWildcard = (WildcardBinding) actualType;
                switch (actualWildcard.boundKind) {
                  case Wildcard.UNBOUND: // A={?} == F={? extends U}  --> 0
                    break;
                  case Wildcard.EXTENDS: // A={? extends V} == F={? extends U} ---> V == U
                    this.bound.collectSubstitutes(
                        scope,
                        actualWildcard.bound,
                        inferenceContext,
                        TypeConstants.CONSTRAINT_EQUAL);
                    for (int i = 0,
                            length =
                                actualWildcard.otherBounds == null
                                    ? 0
                                    : actualWildcard.otherBounds.length;
                        i < length;
                        i++) {
                      this.bound.collectSubstitutes(
                          scope,
                          actualWildcard.otherBounds[i],
                          inferenceContext,
                          TypeConstants.CONSTRAINT_EQUAL);
                    }
                    break;
                  case Wildcard.SUPER: // A={? super V} == F={? extends U} ---> 0
                    break;
                }
                break;
              case Binding
                  .INTERSECTION_TYPE: // A={? extends V1&...&Vn} == F={? extends U} ---> V1 == U,
                                      // ..., Vn == U
                WildcardBinding actuaIntersection = (WildcardBinding) actualType;
                this.bound.collectSubstitutes(
                    scope,
                    actuaIntersection.bound,
                    inferenceContext,
                    TypeConstants.CONSTRAINT_EQUAL);
                for (int i = 0,
                        length =
                            actuaIntersection.otherBounds == null
                                ? 0
                                : actuaIntersection.otherBounds.length;
                    i < length;
                    i++) {
                  this.bound.collectSubstitutes(
                      scope,
                      actuaIntersection.otherBounds[i],
                      inferenceContext,
                      TypeConstants.CONSTRAINT_EQUAL);
                }
                break;
              default: // A=V == F={? extends U} ---> 0
                break;
            }
            break;
          case Wildcard.SUPER: // F={? super U}
            switch (actualType.kind()) {
              case Binding.WILDCARD_TYPE:
                WildcardBinding actualWildcard = (WildcardBinding) actualType;
                switch (actualWildcard.boundKind) {
                  case Wildcard.UNBOUND: // A={?} == F={? super U}  --> 0
                    break;
                  case Wildcard.EXTENDS: // A={? extends V} == F={? super U} ---> 0
                    break;
                  case Wildcard.SUPER: // A={? super V} == F={? super U} ---> 0
                    this.bound.collectSubstitutes(
                        scope,
                        actualWildcard.bound,
                        inferenceContext,
                        TypeConstants.CONSTRAINT_EQUAL);
                    for (int i = 0,
                            length =
                                actualWildcard.otherBounds == null
                                    ? 0
                                    : actualWildcard.otherBounds.length;
                        i < length;
                        i++) {
                      this.bound.collectSubstitutes(
                          scope,
                          actualWildcard.otherBounds[i],
                          inferenceContext,
                          TypeConstants.CONSTRAINT_EQUAL);
                    }
                    break;
                }
                break;
              case Binding.INTERSECTION_TYPE: // A={? extends V1&...&Vn} == F={? super U} ---> 0
                break;
              default: // A=V == F={? super U} ---> 0
                break;
            }
            break;
        }
        break;
      case TypeConstants.CONSTRAINT_SUPER: // A >> F
        switch (this.boundKind) {
          case Wildcard.UNBOUND: // F={?}
            //						switch (actualType.kind()) {
            //						case Binding.WILDCARD_TYPE :
            //							WildcardBinding actualWildcard = (WildcardBinding) actualType;
            //							switch(actualWildcard.kind) {
            //								case Wildcard.UNBOUND: // A={?} >> F={?}  --> 0
            //									break;
            //								case Wildcard.EXTENDS: // A={? extends V} >> F={?} ---> 0
            //									break;
            //								case Wildcard.SUPER: // A={? super V} >> F={?} ---> 0
            //									break;
            //							}
            //							break;
            //						case Binding.INTERSECTION_TYPE :// A={? extends V1&...&Vn} >> F={?} ---> 0
            //							break;
            //						default :// A=V >> F={?} ---> 0
            //							break;
            //						}
            break;
          case Wildcard.EXTENDS: // F={? extends U}
            switch (actualType.kind()) {
              case Binding.WILDCARD_TYPE:
                WildcardBinding actualWildcard = (WildcardBinding) actualType;
                switch (actualWildcard.boundKind) {
                  case Wildcard.UNBOUND: // A={?} >> F={? extends U}  --> 0
                    break;
                  case Wildcard.EXTENDS: // A={? extends V} >> F={? extends U} ---> V >> U
                    this.bound.collectSubstitutes(
                        scope,
                        actualWildcard.bound,
                        inferenceContext,
                        TypeConstants.CONSTRAINT_SUPER);
                    for (int i = 0,
                            length =
                                actualWildcard.otherBounds == null
                                    ? 0
                                    : actualWildcard.otherBounds.length;
                        i < length;
                        i++) {
                      this.bound.collectSubstitutes(
                          scope,
                          actualWildcard.otherBounds[i],
                          inferenceContext,
                          TypeConstants.CONSTRAINT_SUPER);
                    }
                    break;
                  case Wildcard.SUPER: // A={? super V} >> F={? extends U} ---> 0
                    break;
                }
                break;
              case Binding
                  .INTERSECTION_TYPE: // A={? extends V1&...&Vn} >> F={? extends U} ---> V1 >> U,
                                      // ..., Vn >> U
                WildcardBinding actualIntersection = (WildcardBinding) actualType;
                this.bound.collectSubstitutes(
                    scope,
                    actualIntersection.bound,
                    inferenceContext,
                    TypeConstants.CONSTRAINT_SUPER);
                for (int i = 0,
                        length =
                            actualIntersection.otherBounds == null
                                ? 0
                                : actualIntersection.otherBounds.length;
                    i < length;
                    i++) {
                  this.bound.collectSubstitutes(
                      scope,
                      actualIntersection.otherBounds[i],
                      inferenceContext,
                      TypeConstants.CONSTRAINT_SUPER);
                }
                break;
              default: // A=V == F={? extends U} ---> 0
                break;
            }
            break;
          case Wildcard.SUPER: // F={? super U}
            switch (actualType.kind()) {
              case Binding.WILDCARD_TYPE:
                WildcardBinding actualWildcard = (WildcardBinding) actualType;
                switch (actualWildcard.boundKind) {
                  case Wildcard.UNBOUND: // A={?} >> F={? super U}  --> 0
                    break;
                  case Wildcard.EXTENDS: // A={? extends V} >> F={? super U} ---> 0
                    break;
                  case Wildcard.SUPER: // A={? super V} >> F={? super U} ---> V >> U
                    this.bound.collectSubstitutes(
                        scope,
                        actualWildcard.bound,
                        inferenceContext,
                        TypeConstants.CONSTRAINT_SUPER);
                    for (int i = 0,
                            length =
                                actualWildcard.otherBounds == null
                                    ? 0
                                    : actualWildcard.otherBounds.length;
                        i < length;
                        i++) {
                      this.bound.collectSubstitutes(
                          scope,
                          actualWildcard.otherBounds[i],
                          inferenceContext,
                          TypeConstants.CONSTRAINT_SUPER);
                    }
                    break;
                }
                break;
              case Binding.INTERSECTION_TYPE: // A={? extends V1&...&Vn} >> F={? super U} ---> 0
                break;
              default: // A=V >> F={? super U} ---> 0
                break;
            }
            break;
        }
        break;
    }
  }