@Override
      public StackValue innerValue(
          DeclarationDescriptor d,
          LocalLookup localLookup,
          GenerationState state,
          MutableClosure closure,
          Type classType) {
        VariableDescriptor vd = (VariableDescriptor) d;

        boolean idx = localLookup != null && localLookup.lookupLocal(vd);
        if (!idx) return null;

        Type sharedVarType = state.getTypeMapper().getSharedVarType(vd);
        Type localType = state.getTypeMapper().mapType(vd);
        Type type = sharedVarType != null ? sharedVarType : localType;

        String fieldName = "$" + vd.getName();
        StackValue innerValue =
            sharedVarType != null
                ? StackValue.fieldForSharedVar(localType, classType, fieldName)
                : StackValue.field(type, classType, fieldName, false);

        closure.recordField(fieldName, type);
        closure.captureVariable(new EnclosedValueDescriptor(fieldName, d, innerValue, type));

        return innerValue;
      }
      @Override
      public StackValue innerValue(
          DeclarationDescriptor d,
          LocalLookup localLookup,
          GenerationState state,
          MutableClosure closure,
          Type classType) {
        FunctionDescriptor vd = (FunctionDescriptor) d;

        boolean idx = localLookup != null && localLookup.lookupLocal(vd);
        if (!idx) return null;

        BindingContext bindingContext = state.getBindingContext();
        Type localType = asmTypeForAnonymousClass(bindingContext, vd);

        MutableClosure localFunClosure =
            bindingContext.get(CLOSURE, bindingContext.get(CLASS_FOR_FUNCTION, vd));
        if (localFunClosure != null && JvmCodegenUtil.isConst(localFunClosure)) {
          // This is an optimization: we can obtain an instance of a const closure simply by
          // GETSTATIC ...$instance
          // (instead of passing this instance to the constructor and storing as a field)
          return StackValue.field(localType, localType, JvmAbi.INSTANCE_FIELD, true);
        }

        String fieldName = "$" + vd.getName();
        StackValue innerValue = StackValue.field(localType, classType, fieldName, false);

        closure.recordField(fieldName, localType);
        closure.captureVariable(new EnclosedValueDescriptor(fieldName, d, innerValue, localType));

        return innerValue;
      }
      @Override
      public StackValue innerValue(
          DeclarationDescriptor d,
          LocalLookup enclosingLocalLookup,
          GenerationState state,
          MutableClosure closure,
          Type classType) {
        if (closure.getEnclosingReceiverDescriptor() != d) return null;

        JetType receiverType = ((CallableDescriptor) d).getReceiverParameter().getType();
        Type type = state.getTypeMapper().mapType(receiverType);
        StackValue innerValue = StackValue.field(type, classType, CAPTURED_RECEIVER_FIELD, false);
        closure.setCaptureReceiver();

        return innerValue;
      }