Code review comment: The reason why I decided to do this was because `data.typeChecker.checkExpr` uses the expected type for doing 2 things in the end [here](https://github.com/ballerina-platform/ballerina-lang/blob/52c6286330176b87df7d8f145c89cde21d5f8df7/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java#L236),  1. Check if the actual type is a subtype of the expected type and if not give an error 2. Add an implicit cast if needed  When it comes to optional field assignments for 1 it must treat expected type for a field type `T` as `T?` and for 2 it must treat it as just `T`.  But since we are type checking the `expr` part of the assignment, which don't have information about what it is being used for currently, and there for we can't distinguish between these expected types.  I think there are 2 ways to actually fix this,  1. Add information directly to BLangExpression node that it is being used in such a manner and in the type check we treat expected type differently for 1 and 2 (this is done in [#272284f](https://github.com/ballerina-platform/ballerina-lang/pull/41917/commits/272284fa31f3a7b906cab3591980f0b0170c0d1a)). While this requires the minimum amount of change this means we are leaking information about the parent node to the child nodes in the AST, which I think is bad 2. Speical case the flow for the type checker when we have an optional field assignement. This would mean we either have to change the public API of the type checker such that we can pass information from here all the way down to [`checkType`](https://github.com/ballerina-platform/ballerina-lang/blob/52c6286330176b87df7d8f145c89cde21d5f8df7/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java#L236), or pass the informatio using `AnalyzerData` by giving a anther API to be used in case of optional field access similar to [`checkExpr`](https://github.com/ballerina-platform/ballerina-lang/blob/52c6286330176b87df7d8f145c89cde21d5f8df7/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java#L365). This would still means each expression node must do the right thing by either calling an appropriately modified version of `checkType` or passing on this information to `checkType` by modifying the public API.   I feel 2 is the "correct" solution but given the way our code is structured this means a very large modification. Option 1 (and setting and resetting the `implConversionExpr`) both require minimal changes but are "incorrect" in different ways.  I am not sure which of these 3 possible options is the best. WDYT?

Code under review:
public void visit(BLangAssignment assignNode, AnalyzerData data) {
        BLangExpression varRef = assignNode.varRef;
        if (varRef.getKind() == NodeKind.INDEX_BASED_ACCESS_EXPR ||
                varRef.getKind() == NodeKind.FIELD_BASED_ACCESS_EXPR) {
            ((BLangAccessExpression) varRef).leafNode = true;
        }

        
        setTypeOfVarRefInAssignment(varRef, data);
        data.expType = varRef.getBType();

        validateFunctionVarRef(varRef, data);

        checkInvalidTypeDef(varRef);
        BType actualExpectedType = null;
        
        
        
        if (data.expType != symTable.semanticError && isAssignmentToOptionalField(assignNode)) {
            actualExpectedType = data.expType;
            data.expType = types.addNilForNillableAccessType(actualExpectedType);
        }

        BLangExpression expr = assignNode.expr;
        data.typeChecker.checkExpr(expr, data.env, data.expType, data.prevEnvs, data.commonAnalyzerData);
        if (actualExpectedType != null && expr.impConversionExpr != null) {
            data.typeChecker.resetImpConversionExpr(expr, expr.getBType(), actualExpectedType);
        }

        validateWorkerAnnAttachments(assignNode.expr, data);

        resetTypeNarrowing(varRef, data);
    }

Line commented on: BLangExpression expr = assignNode.expr;

Revised code:
public void visit(BLangAssignment assignNode, AnalyzerData data) {
        BLangExpression varRef = assignNode.varRef;
        if (varRef.getKind() == NodeKind.INDEX_BASED_ACCESS_EXPR ||
                varRef.getKind() == NodeKind.FIELD_BASED_ACCESS_EXPR) {
            ((BLangAccessExpression) varRef).leafNode = true;
        }

        
        setTypeOfVarRefInAssignment(varRef, data);
        data.expType = varRef.getBType();

        validateFunctionVarRef(varRef, data);

        checkInvalidTypeDef(varRef);
        BType actualExpectedType = null;
        
        
        
        if (data.expType != symTable.semanticError && isAssignmentToOptionalField(assignNode)) {
            actualExpectedType = data.expType;
            data.expType = types.addNilForNillableAccessType(actualExpectedType);
        }

        BLangExpression expr = assignNode.expr;
        data.typeChecker.checkExpr(expr, data.env, data.expType, data.prevEnvs, data.commonAnalyzerData);
        if (actualExpectedType != null && expr.impConversionExpr != null) {
            data.typeChecker.resetImpConversionExpr(expr, expr.getBType(), actualExpectedType);
        }

        validateWorkerAnnAttachments(assignNode.expr, data);

        resetTypeNarrowing(varRef, data);
    }