private ConcreteType maybeAddAutoboxes(ConcreteType cType, JSType jsType, String prop) {
      jsType = jsType.restrictByNotNullOrUndefined();
      if (jsType instanceof UnionType) {
        for (JSType alt : ((UnionType) jsType).getAlternates()) {
          return maybeAddAutoboxes(cType, alt, prop);
        }
      }

      if (jsType.autoboxesTo() != null) {
        JSType autoboxed = jsType.autoboxesTo();
        return cType.unionWith(tt.getConcreteInstance((ObjectType) autoboxed));
      } else if (jsType.unboxesTo() != null) {
        return cType.unionWith(tt.getConcreteInstance((ObjectType) jsType));
      }

      return cType;
    }
    /**
     * Add concrete types for autoboxing types if necessary. The concrete type system does not track
     * native types, like string, so add them if they are present in the JSType for the node.
     */
    private ConcreteType maybeAddAutoboxes(ConcreteType cType, Node node, String prop) {
      JSType jsType = node.getJSType();
      if (jsType == null) {
        return cType;
      } else if (jsType.isUnknownType()) {
        for (JSTypeNative nativeType : nativeTypes) {
          ConcreteType concrete =
              tt.getConcreteInstance(tt.getTypeRegistry().getNativeObjectType(nativeType));
          if (concrete != null && !concrete.getPropertyType(prop).isNone()) {
            cType = cType.unionWith(concrete);
          }
        }
        return cType;
      }

      return maybeAddAutoboxes(cType, jsType, prop);
    }