@Override
  public KotlinTypeInfo visitTryExpression(
      @NotNull KtTryExpression expression, ExpressionTypingContext typingContext) {
    ExpressionTypingContext context = typingContext.replaceContextDependency(INDEPENDENT);
    KtExpression tryBlock = expression.getTryBlock();
    List<KtCatchClause> catchClauses = expression.getCatchClauses();
    KtFinallySection finallyBlock = expression.getFinallyBlock();
    List<KotlinType> types = new ArrayList<KotlinType>();
    for (KtCatchClause catchClause : catchClauses) {
      KtParameter catchParameter = catchClause.getCatchParameter();
      KtExpression catchBody = catchClause.getCatchBody();
      if (catchParameter != null) {
        components.identifierChecker.checkDeclaration(catchParameter, context.trace);
        ModifiersChecker.ModifiersCheckingProcedure modifiersChecking =
            components.modifiersChecker.withTrace(context.trace);
        modifiersChecking.checkParameterHasNoValOrVar(
            catchParameter, VAL_OR_VAR_ON_CATCH_PARAMETER);
        ModifierCheckerCore.INSTANCE$.check(catchParameter, context.trace, null);

        VariableDescriptor variableDescriptor =
            components.descriptorResolver.resolveLocalVariableDescriptor(
                context.scope, catchParameter, context.trace);
        KotlinType throwableType = components.builtIns.getThrowable().getDefaultType();
        components.dataFlowAnalyzer.checkType(
            variableDescriptor.getType(),
            catchParameter,
            context.replaceExpectedType(throwableType));
        if (catchBody != null) {
          LexicalWritableScope catchScope = newWritableScopeImpl(context, "Catch scope");
          catchScope.addVariableDescriptor(variableDescriptor);
          KotlinType type =
              facade.getTypeInfo(catchBody, context.replaceScope(catchScope)).getType();
          if (type != null) {
            types.add(type);
          }
        }
      }
    }

    KotlinTypeInfo result = TypeInfoFactoryKt.noTypeInfo(context);
    if (finallyBlock != null) {
      result =
          facade.getTypeInfo(
              finallyBlock.getFinalExpression(), context.replaceExpectedType(NO_EXPECTED_TYPE));
    }

    KotlinType type = facade.getTypeInfo(tryBlock, context).getType();
    if (type != null) {
      types.add(type);
    }
    if (types.isEmpty()) {
      return result.clearType();
    } else {
      return result.replaceType(CommonSupertypes.commonSupertype(types));
    }
  }
  public KotlinTypeInfo visitForExpression(
      KtForExpression expression,
      ExpressionTypingContext contextWithExpectedType,
      boolean isStatement) {
    if (!isStatement)
      return components.dataFlowAnalyzer.illegalStatementType(
          expression, contextWithExpectedType, facade);

    ExpressionTypingContext context =
        contextWithExpectedType
            .replaceExpectedType(NO_EXPECTED_TYPE)
            .replaceContextDependency(INDEPENDENT);
    // Preliminary analysis
    PreliminaryLoopVisitor loopVisitor = PreliminaryLoopVisitor.visitLoop(expression);
    context =
        context.replaceDataFlowInfo(
            loopVisitor.clearDataFlowInfoForAssignedLocalVariables(context.dataFlowInfo));

    KtExpression loopRange = expression.getLoopRange();
    KotlinType expectedParameterType = null;
    KotlinTypeInfo loopRangeInfo;
    if (loopRange != null) {
      ExpressionReceiver loopRangeReceiver =
          getExpressionReceiver(facade, loopRange, context.replaceScope(context.scope));
      loopRangeInfo = facade.getTypeInfo(loopRange, context);
      if (loopRangeReceiver != null) {
        expectedParameterType =
            components.forLoopConventionsChecker.checkIterableConvention(
                loopRangeReceiver, context);
      }
    } else {
      loopRangeInfo = TypeInfoFactoryKt.noTypeInfo(context);
    }

    LexicalWritableScope loopScope = newWritableScopeImpl(context, "Scope with for-loop index");

    KtParameter loopParameter = expression.getLoopParameter();
    if (loopParameter != null) {
      VariableDescriptor variableDescriptor =
          createLoopParameterDescriptor(loopParameter, expectedParameterType, context);
      components
          .modifiersChecker
          .withTrace(context.trace)
          .checkModifiersForLocalDeclaration(loopParameter, variableDescriptor);
      components.identifierChecker.checkDeclaration(loopParameter, context.trace);

      loopScope.addVariableDescriptor(variableDescriptor);
    } else {
      KtMultiDeclaration multiParameter = expression.getMultiParameter();
      if (multiParameter != null && loopRange != null) {
        KotlinType elementType =
            expectedParameterType == null
                ? ErrorUtils.createErrorType("Loop range has no type")
                : expectedParameterType;
        TransientReceiver iteratorNextAsReceiver = new TransientReceiver(elementType);
        components.annotationResolver.resolveAnnotationsWithArguments(
            loopScope, multiParameter.getModifierList(), context.trace);
        components.multiDeclarationResolver.defineLocalVariablesFromMultiDeclaration(
            loopScope, multiParameter, iteratorNextAsReceiver, loopRange, context);
        components
            .modifiersChecker
            .withTrace(context.trace)
            .checkModifiersForMultiDeclaration(multiParameter);
        components
            .modifiersChecker
            .withTrace(context.trace)
            .checkParameterHasNoValOrVar(multiParameter, VAL_OR_VAR_ON_LOOP_MULTI_PARAMETER);
        components.identifierChecker.checkDeclaration(multiParameter, context.trace);
      }
    }

    KtExpression body = expression.getBody();
    KotlinTypeInfo bodyTypeInfo;
    if (body != null) {
      bodyTypeInfo =
          components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
              loopScope,
              Collections.singletonList(body),
              CoercionStrategy.NO_COERCION,
              context.replaceDataFlowInfo(loopRangeInfo.getDataFlowInfo()));
    } else {
      bodyTypeInfo = loopRangeInfo;
    }

    return components
        .dataFlowAnalyzer
        .checkType(
            bodyTypeInfo.replaceType(components.builtIns.getUnitType()),
            expression,
            contextWithExpectedType)
        .replaceDataFlowInfo(loopRangeInfo.getDataFlowInfo());
  }