示例#1
0
  public InlineCodegen(
      @NotNull ExpressionCodegen codegen,
      @NotNull GenerationState state,
      @NotNull SimpleFunctionDescriptor functionDescriptor,
      @NotNull JetElement callElement,
      @Nullable ReifiedTypeParameterMappings typeParameterMappings) {
    assert InlineUtil.isInline(functionDescriptor)
        : "InlineCodegen could inline only inline function: " + functionDescriptor;

    this.state = state;
    this.typeMapper = state.getTypeMapper();
    this.codegen = codegen;
    this.callElement = callElement;
    this.functionDescriptor = functionDescriptor.getOriginal();

    reifiedTypeInliner = new ReifiedTypeInliner(typeParameterMappings);

    initialFrameSize = codegen.getFrameMap().getCurrentSize();

    context = (MethodContext) getContext(functionDescriptor, state);
    jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind());

    // TODO: implement AS_FUNCTION inline strategy
    InlineStrategy inlineStrategy = InlineUtil.getInlineStrategy(functionDescriptor);
    this.asFunctionInline = false;

    isSameModule =
        JvmCodegenUtil.isCallInsideSameModuleAsDeclared(
            functionDescriptor, codegen.getContext(), state.getOutDirectory());

    sourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper();
    reportIncrementalInfo(
        functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal());
  }
  public static boolean shouldBeInlined(@NotNull CallableDescriptor descriptor) {
    if (descriptor instanceof SimpleFunctionDescriptor) {
      return InlineUtil.isInline(descriptor);
    }

    if (descriptor instanceof ValueParameterDescriptor) {
      return InlineUtil.isInline(descriptor.getContainingDeclaration())
          && InlineUtil.isInlineLambdaParameter((ParameterDescriptor) descriptor);
    }

    return false;
  }
示例#3
0
 /*lambda or callable reference*/
 public static boolean isInliningParameter(
     JetExpression expression, ValueParameterDescriptor valueParameterDescriptor) {
   // TODO deparenthisise typed
   JetExpression deparenthesized = JetPsiUtil.deparenthesize(expression);
   return InlineUtil.isInlineLambdaParameter(valueParameterDescriptor)
       && isInlinableParameterExpression(deparenthesized);
 }
示例#4
0
  private void checkValueParameter(
      @NotNull CallCheckerContext context,
      @NotNull CallableDescriptor targetDescriptor,
      @NotNull ValueArgument targetArgument,
      @NotNull ValueParameterDescriptor targetParameterDescriptor) {
    KtExpression argumentExpression = targetArgument.getArgumentExpression();
    if (argumentExpression == null) {
      return;
    }
    CallableDescriptor argumentCallee = getCalleeDescriptor(context, argumentExpression, false);

    if (argumentCallee != null && inlinableParameters.contains(argumentCallee)) {
      if (InlineUtil.isInline(targetDescriptor)
          && isInlinableParameter(targetParameterDescriptor)) {
        if (allowsNonLocalReturns(argumentCallee)
            && !allowsNonLocalReturns(targetParameterDescriptor)) {
          context
              .getTrace()
              .report(NON_LOCAL_RETURN_NOT_ALLOWED.on(argumentExpression, argumentExpression));
        } else {
          checkNonLocalReturn(context, argumentCallee, argumentExpression);
        }
      } else {
        context
            .getTrace()
            .report(USAGE_IS_NOT_INLINABLE.on(argumentExpression, argumentExpression, descriptor));
      }
    }
  }
示例#5
0
 public InlineChecker(@NotNull FunctionDescriptor descriptor) {
   assert InlineUtil.isInline(descriptor)
       : "This extension should be created only for inline functions: " + descriptor;
   this.descriptor = descriptor;
   this.isEffectivelyPublicApiFunction = DescriptorUtilsKt.isEffectivelyPublicApi(descriptor);
   this.isEffectivelyPrivateApiFunction = DescriptorUtilsKt.isEffectivelyPrivateApi(descriptor);
   for (ValueParameterDescriptor param : descriptor.getValueParameters()) {
     if (isInlinableParameter(param)) {
       inlinableParameters.add(param);
     }
   }
 }
示例#6
0
  private static boolean isInvokeOrInlineExtension(@NotNull CallableDescriptor descriptor) {
    if (!(descriptor instanceof SimpleFunctionDescriptor)) {
      return false;
    }

    DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
    boolean isInvoke =
        descriptor.getName().equals(OperatorNameConventions.INVOKE)
            && containingDeclaration instanceof ClassDescriptor
            && FunctionTypesKt.isFunctionType(
                ((ClassDescriptor) containingDeclaration).getDefaultType());

    return isInvoke || InlineUtil.isInline(descriptor);
  }
示例#7
0
  /*descriptor is null for captured vars*/
  public boolean shouldPutValue(
      @NotNull Type type,
      @Nullable StackValue stackValue,
      @Nullable ValueParameterDescriptor descriptor) {

    if (stackValue == null) {
      // default or vararg
      return true;
    }

    // remap only inline functions (and maybe non primitives)
    // TODO - clean asserion and remapping logic
    if (isPrimitive(type) != isPrimitive(stackValue.type)) {
      // don't remap boxing/unboxing primitives - lost identity and perfomance
      return true;
    }

    if (stackValue instanceof StackValue.Local) {
      return false;
    }

    StackValue field = stackValue;
    if (stackValue instanceof StackValue.FieldForSharedVar) {
      field = ((StackValue.FieldForSharedVar) stackValue).receiver;
    }

    // check that value corresponds to captured inlining parameter
    if (field instanceof StackValue.Field) {
      DeclarationDescriptor varDescriptor = ((StackValue.Field) field).descriptor;
      // check that variable is inline function parameter
      return !(varDescriptor instanceof ParameterDescriptor
          && InlineUtil.isInlineLambdaParameter((ParameterDescriptor) varDescriptor)
          && InlineUtil.isInline(varDescriptor.getContainingDeclaration()));
    }

    return true;
  }
示例#8
0
 private static boolean isInlinableParameter(@NotNull ParameterDescriptor descriptor) {
   return InlineUtil.isInlineLambdaParameter(descriptor)
       && !descriptor.getType().isMarkedNullable();
 }
  @Override
  public KotlinTypeInfo visitReturnExpression(
      @NotNull KtReturnExpression expression, ExpressionTypingContext context) {
    KtElement labelTargetElement = LabelResolver.INSTANCE.resolveControlLabel(expression, context);

    KtExpression returnedExpression = expression.getReturnedExpression();

    KotlinType expectedType = NO_EXPECTED_TYPE;
    KotlinType resultType = components.builtIns.getNothingType();
    KtDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, KtDeclaration.class);

    if (parentDeclaration instanceof KtParameter) {
      // In a default value for parameter
      context.trace.report(RETURN_NOT_ALLOWED.on(expression));
    }

    if (expression.getTargetLabel() == null) {
      while (parentDeclaration instanceof KtMultiDeclaration) {
        // TODO: It's hacking fix for KT-5100: Strange "Return is not allowed here" for
        // multi-declaration initializer with elvis expression
        parentDeclaration = PsiTreeUtil.getParentOfType(parentDeclaration, KtDeclaration.class);
      }

      assert parentDeclaration != null
          : "Can't find parent declaration for " + expression.getText();
      DeclarationDescriptor declarationDescriptor =
          context.trace.get(DECLARATION_TO_DESCRIPTOR, parentDeclaration);
      Pair<FunctionDescriptor, PsiElement> containingFunInfo =
          BindingContextUtils.getContainingFunctionSkipFunctionLiterals(
              declarationDescriptor, false);
      FunctionDescriptor containingFunctionDescriptor = containingFunInfo.getFirst();

      if (containingFunctionDescriptor != null) {
        if (!InlineUtil.checkNonLocalReturnUsage(
                containingFunctionDescriptor, expression, context.trace)
            || isClassInitializer(containingFunInfo)) {
          // Unqualified, in a function literal
          context.trace.report(RETURN_NOT_ALLOWED.on(expression));
          resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
        }

        expectedType =
            getFunctionExpectedReturnType(
                containingFunctionDescriptor, (KtElement) containingFunInfo.getSecond(), context);
      } else {
        // Outside a function
        context.trace.report(RETURN_NOT_ALLOWED.on(expression));
        resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
      }
    } else if (labelTargetElement != null) {
      SimpleFunctionDescriptor functionDescriptor = context.trace.get(FUNCTION, labelTargetElement);
      if (functionDescriptor != null) {
        expectedType =
            getFunctionExpectedReturnType(functionDescriptor, labelTargetElement, context);
        if (!InlineUtil.checkNonLocalReturnUsage(functionDescriptor, expression, context.trace)) {
          // Qualified, non-local
          context.trace.report(RETURN_NOT_ALLOWED.on(expression));
          resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
        }
      } else {
        context.trace.report(NOT_A_RETURN_LABEL.on(expression, expression.getLabelName()));
      }
    }
    if (returnedExpression != null) {
      facade.getTypeInfo(
          returnedExpression,
          context
              .replaceExpectedType(expectedType)
              .replaceScope(context.scope)
              .replaceContextDependency(INDEPENDENT));
    } else {
      if (expectedType != null
          && !noExpectedType(expectedType)
          && !KotlinBuiltIns.isUnit(expectedType)
          && !isDontCarePlaceholder(expectedType)) // for lambda with implicit return type Unit
      {
        context.trace.report(RETURN_TYPE_MISMATCH.on(expression, expectedType));
      }
    }
    return components.dataFlowAnalyzer.createCheckedTypeInfo(resultType, context, expression);
  }