@Nullable
 public static List<ValueParameterDescriptor> getSubstitutedValueParameters(
     FunctionDescriptor substitutedDescriptor,
     @NotNull FunctionDescriptor functionDescriptor,
     @NotNull TypeSubstitutor substitutor) {
   List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
   List<ValueParameterDescriptor> unsubstitutedValueParameters =
       functionDescriptor.getValueParameters();
   for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size();
       i < unsubstitutedValueParametersSize;
       i++) {
     ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i);
     // TODO : Lazy?
     JetType substitutedType =
         substitutor.substitute(unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE);
     JetType varargElementType = unsubstitutedValueParameter.getVarargElementType();
     JetType substituteVarargElementType =
         varargElementType == null
             ? null
             : substitutor.substitute(varargElementType, Variance.IN_VARIANCE);
     if (substitutedType == null) return null;
     result.add(
         new ValueParameterDescriptorImpl(
             substitutedDescriptor,
             unsubstitutedValueParameter,
             unsubstitutedValueParameter.getAnnotations(),
             unsubstitutedValueParameter.isVar(),
             substitutedType,
             substituteVarargElementType));
   }
   return result;
 }
Пример #2
0
  private TypeSubstitutor createTypeSubstitutorWithDefaultForUnknownTypeParameter(
      @Nullable final TypeProjection defaultTypeProjection) {
    return TypeSubstitutor.create(
        new TypeSubstitution() {
          @Override
          public TypeProjection get(TypeConstructor key) {
            DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor();
            if (declarationDescriptor instanceof TypeParameterDescriptor) {
              TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor;

              JetType value = ConstraintsUtil.getValue(getTypeConstraints(descriptor));
              if (value != null
                  && !TypeUtils.dependsOnTypeParameterConstructors(
                      value, Collections.singleton(DONT_CARE.getConstructor()))) {
                return new TypeProjection(value);
              }
              if (typeParameterConstraints.containsKey(descriptor)) {
                return defaultTypeProjection;
              }
            }
            return null;
          }

          @Override
          public boolean isEmpty() {
            return false;
          }

          @Override
          public String toString() {
            return typeParameterConstraints.toString();
          }
        });
  }
 @Nullable
 public static FunctionDescriptor substituteFunctionDescriptor(
     @NotNull List<JetType> typeArguments, @NotNull FunctionDescriptor functionDescriptor) {
   Map<TypeConstructor, TypeProjection> substitutionContext =
       createSubstitutionContext(functionDescriptor, typeArguments);
   return functionDescriptor.substitute(TypeSubstitutor.create(substitutionContext));
 }
Пример #4
0
  @NotNull
  private static FunctionDescriptor substituteSuperFunction(
      @NotNull Map<ClassDescriptor, JetType> superclassToSupertype,
      @NotNull FunctionDescriptor superFun) {
    DeclarationDescriptor superFunContainer = superFun.getContainingDeclaration();
    assert superFunContainer instanceof ClassDescriptor : superFunContainer;

    JetType supertype = superclassToSupertype.get(superFunContainer);
    assert supertype != null : "Couldn't find super type for super function: " + superFun;
    TypeSubstitutor supertypeSubstitutor = TypeSubstitutor.create(supertype);

    FunctionDescriptor substitutedSuperFun = superFun.substitute(supertypeSubstitutor);
    assert substitutedSuperFun != null;
    return substitutedSuperFun;
  }
Пример #5
0
  /**
   * Remember that we are trying to cast something of type {@code supertype} to {@code subtype}.
   *
   * <p>Since at runtime we can only check the class (type constructor), the rest of the subtype
   * should be known statically, from supertype. This method reconstructs all static information
   * that can be obtained from supertype.
   *
   * <p>Example 1: supertype = Collection<String> subtype = List<...> result = List<String>, all
   * arguments are inferred
   *
   * <p>Example 2: supertype = Any subtype = List<...> result = List<*>, some arguments were not
   * inferred, replaced with '*'
   */
  public static TypeReconstructionResult findStaticallyKnownSubtype(
      @NotNull JetType supertype, @NotNull TypeConstructor subtypeConstructor) {
    assert !supertype.isNullable() : "This method only makes sense for non-nullable types";

    // Assume we are casting an expression of type Collection<Foo> to List<Bar>
    // First, let's make List<T>, where T is a type variable
    ClassifierDescriptor descriptor = subtypeConstructor.getDeclarationDescriptor();
    assert descriptor != null : "Can't create default type for " + subtypeConstructor;
    JetType subtypeWithVariables = descriptor.getDefaultType();

    // Now, let's find a supertype of List<T> that is a Collection of something,
    // in this case it will be Collection<T>
    JetType supertypeWithVariables =
        TypeCheckingProcedure.findCorrespondingSupertype(subtypeWithVariables, supertype);

    final List<TypeParameterDescriptor> variables =
        subtypeWithVariables.getConstructor().getParameters();

    Map<TypeConstructor, TypeProjection> substitution;
    if (supertypeWithVariables != null) {
      // Now, let's try to unify Collection<T> and Collection<Foo> solution is a map from T to Foo
      TypeUnifier.UnificationResult solution =
          TypeUnifier.unify(
              new TypeProjectionImpl(supertype),
              new TypeProjectionImpl(supertypeWithVariables),
              new Predicate<TypeConstructor>() {
                @Override
                public boolean apply(TypeConstructor typeConstructor) {
                  ClassifierDescriptor descriptor = typeConstructor.getDeclarationDescriptor();
                  return descriptor instanceof TypeParameterDescriptor
                      && variables.contains(descriptor);
                }
              });
      substitution = Maps.newHashMap(solution.getSubstitution());
    } else {
      // If there's no corresponding supertype, no variables are determined
      // This may be OK, e.g. in case 'Any as List<*>'
      substitution = Maps.newHashMapWithExpectedSize(variables.size());
    }

    // If some of the parameters are not determined by unification, it means that these parameters
    // are lost,
    // let's put stars instead, so that we can only cast to something like List<*>, e.g. (a: Any) as
    // List<*>
    boolean allArgumentsInferred = true;
    for (TypeParameterDescriptor variable : variables) {
      TypeProjection value = substitution.get(variable.getTypeConstructor());
      if (value == null) {
        substitution.put(
            variable.getTypeConstructor(), SubstitutionUtils.makeStarProjection(variable));
        allArgumentsInferred = false;
      }
    }

    // At this point we have values for all type parameters of List
    // Let's make a type by substituting them: List<T> -> List<Foo>
    JetType substituted =
        TypeSubstitutor.create(substitution).substitute(subtypeWithVariables, Variance.INVARIANT);

    return new TypeReconstructionResult(substituted, allArgumentsInferred);
  }
public class FunctionDescriptorUtil {
  private static final TypeSubstitutor MAKE_TYPE_PARAMETERS_FRESH =
      TypeSubstitutor.create(
          new TypeSubstitution() {

            @Override
            public TypeProjection get(TypeConstructor key) {
              return null;
            }

            @Override
            public boolean isEmpty() {
              return false;
            }

            @Override
            public String toString() {
              return "FunctionDescriptorUtil.MAKE_TYPE_PARAMETERS_FRESH";
            }
          });

  public static Map<TypeConstructor, TypeProjection> createSubstitutionContext(
      @NotNull FunctionDescriptor functionDescriptor, List<JetType> typeArguments) {
    if (functionDescriptor.getTypeParameters().isEmpty()) return Collections.emptyMap();

    Map<TypeConstructor, TypeProjection> result = new HashMap<TypeConstructor, TypeProjection>();

    int typeArgumentsSize = typeArguments.size();
    List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
    assert typeArgumentsSize == typeParameters.size();
    for (int i = 0; i < typeArgumentsSize; i++) {
      TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
      JetType typeArgument = typeArguments.get(i);
      result.put(typeParameterDescriptor.getTypeConstructor(), new TypeProjection(typeArgument));
    }
    return result;
  }

  @Nullable
  public static List<ValueParameterDescriptor> getSubstitutedValueParameters(
      FunctionDescriptor substitutedDescriptor,
      @NotNull FunctionDescriptor functionDescriptor,
      @NotNull TypeSubstitutor substitutor) {
    List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
    List<ValueParameterDescriptor> unsubstitutedValueParameters =
        functionDescriptor.getValueParameters();
    for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size();
        i < unsubstitutedValueParametersSize;
        i++) {
      ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i);
      // TODO : Lazy?
      JetType substitutedType =
          substitutor.substitute(unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE);
      JetType varargElementType = unsubstitutedValueParameter.getVarargElementType();
      JetType substituteVarargElementType =
          varargElementType == null
              ? null
              : substitutor.substitute(varargElementType, Variance.IN_VARIANCE);
      if (substitutedType == null) return null;
      result.add(
          new ValueParameterDescriptorImpl(
              substitutedDescriptor,
              unsubstitutedValueParameter,
              unsubstitutedValueParameter.getAnnotations(),
              unsubstitutedValueParameter.isVar(),
              substitutedType,
              substituteVarargElementType));
    }
    return result;
  }

  @Nullable
  public static JetType getSubstitutedReturnType(
      @NotNull FunctionDescriptor functionDescriptor, TypeSubstitutor substitutor) {
    return substitutor.substitute(functionDescriptor.getReturnType(), Variance.OUT_VARIANCE);
  }

  @Nullable
  public static FunctionDescriptor substituteFunctionDescriptor(
      @NotNull List<JetType> typeArguments, @NotNull FunctionDescriptor functionDescriptor) {
    Map<TypeConstructor, TypeProjection> substitutionContext =
        createSubstitutionContext(functionDescriptor, typeArguments);
    return functionDescriptor.substitute(TypeSubstitutor.create(substitutionContext));
  }

  @NotNull
  public static JetScope getFunctionInnerScope(
      @NotNull JetScope outerScope,
      @NotNull FunctionDescriptor descriptor,
      @NotNull BindingTrace trace) {
    WritableScope parameterScope =
        new WritableScopeImpl(
            outerScope,
            descriptor,
            new TraceBasedRedeclarationHandler(trace),
            "Function inner scope");
    ReceiverParameterDescriptor receiver = descriptor.getReceiverParameter();
    if (receiver != null) {
      parameterScope.setImplicitReceiver(receiver);
    }
    for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
      parameterScope.addTypeParameterDescriptor(typeParameter);
    }
    for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) {
      parameterScope.addVariableDescriptor(valueParameterDescriptor);
    }
    parameterScope.addLabeledDeclaration(descriptor);
    parameterScope.changeLockLevel(WritableScope.LockLevel.READING);
    return parameterScope;
  }

  public static void initializeFromFunctionType(
      @NotNull FunctionDescriptorImpl functionDescriptor,
      @NotNull JetType functionType,
      @Nullable ReceiverParameterDescriptor expectedThisObject,
      @NotNull Modality modality,
      @NotNull Visibility visibility) {

    assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(functionType);
    functionDescriptor.initialize(
        KotlinBuiltIns.getInstance().getReceiverType(functionType),
        expectedThisObject,
        Collections.<TypeParameterDescriptorImpl>emptyList(),
        KotlinBuiltIns.getInstance().getValueParameters(functionDescriptor, functionType),
        KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(functionType),
        modality,
        visibility);
  }

  public static <D extends CallableDescriptor> D alphaConvertTypeParameters(D candidate) {
    return (D) candidate.substitute(MAKE_TYPE_PARAMETERS_FRESH);
  }

  public static FunctionDescriptor getInvokeFunction(@NotNull JetType functionType) {
    assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(functionType);

    ClassifierDescriptor classDescriptorForFunction =
        functionType.getConstructor().getDeclarationDescriptor();
    assert classDescriptorForFunction instanceof ClassDescriptor;
    Collection<FunctionDescriptor> invokeFunctions =
        ((ClassDescriptor) classDescriptorForFunction)
            .getMemberScope(functionType.getArguments())
            .getFunctions(Name.identifier("invoke"));
    assert invokeFunctions.size() == 1;
    return invokeFunctions.iterator().next();
  }
}
 @Nullable
 public static JetType getSubstitutedReturnType(
     @NotNull FunctionDescriptor functionDescriptor, TypeSubstitutor substitutor) {
   return substitutor.substitute(functionDescriptor.getReturnType(), Variance.OUT_VARIANCE);
 }