Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect nullability analysis in increment operator #29961

Open
jcouv opened this issue Sep 17, 2018 · 0 comments
Open

Incorrect nullability analysis in increment operator #29961

jcouv opened this issue Sep 17, 2018 · 0 comments

Comments

@jcouv
Copy link
Member

jcouv commented Sep 17, 2018

        public override BoundNode VisitIncrementOperator(BoundIncrementOperator node)
        {
            Debug.Assert(!IsConditionalState);

            VisitRvalue(node.Operand);
            var operandType = _resultType;
            bool setResult = false;

            if (this.State.Reachable)
            {
                // PROTOTYPE(NullableReferenceTypes): Update increment method based on operand type.
                MethodSymbol incrementOperator = (node.OperatorKind.IsUserDefined() && (object)node.MethodOpt != null && node.MethodOpt.ParameterCount == 1) ? node.MethodOpt : null;
                TypeSymbolWithAnnotations targetTypeOfOperandConversion;
                AssignmentKind assignmentKind = AssignmentKind.Assignment;
                ParameterSymbol target = null;

                // PROTOTYPE(NullableReferenceTypes): Update conversion method based on operand type.
                if (node.OperandConversion.IsUserDefined && (object)node.OperandConversion.Method != null && node.OperandConversion.Method.ParameterCount == 1)
                {
                    targetTypeOfOperandConversion = node.OperandConversion.Method.ReturnType;
                }
                else if ((object)incrementOperator != null)
                {
                    targetTypeOfOperandConversion = incrementOperator.Parameters[0].Type;
                    assignmentKind = AssignmentKind.Argument;
                    target = incrementOperator.Parameters[0];
                }
                else
                {
                    // Either a built-in increment, or an error case.
                    targetTypeOfOperandConversion = default;
                }

                TypeSymbolWithAnnotations resultOfOperandConversionType;

                if (!targetTypeOfOperandConversion.IsNull)
                {
                    // PROTOTYPE(NullableReferenceTypes): Should something special be done for targetTypeOfOperandConversion for lifted case?
                    resultOfOperandConversionType = ApplyConversion(
                        node.Operand,
                        node.Operand,
                        node.OperandConversion,
                        targetTypeOfOperandConversion,
                        operandType,
                        checkConversion: true,
                        fromExplicitCast: false,
                        useLegacyWarnings: false,
                        assignmentKind,
                        target,
                        reportTopLevelWarnings: true,
                        reportNestedWarnings: true);
                }
                else
                {
                    resultOfOperandConversionType = operandType;
                }

                TypeSymbolWithAnnotations resultOfIncrementType;
                if ((object)incrementOperator == null)
                {
                    resultOfIncrementType = resultOfOperandConversionType;
                }
                else
                {
                    resultOfIncrementType = incrementOperator.ReturnType;
                }

                resultOfIncrementType = ApplyConversion(
                    node,
                    node,
                    node.ResultConversion,
                    operandType,
                    resultOfIncrementType,
                    checkConversion: true,
                    fromExplicitCast: false,
                    useLegacyWarnings: false,
                    AssignmentKind.Assignment);

                // PROTOTYPE(NullableReferenceTypes): Check node.Type.IsErrorType() instead?
                if (!node.HasErrors)
                {
                    var op = node.OperatorKind.Operator();
                    _resultType = (op == UnaryOperatorKind.PrefixIncrement || op == UnaryOperatorKind.PrefixDecrement) ? resultOfIncrementType : operandType;
                    setResult = true;

                    TrackNullableStateForAssignment(node, operandType, MakeSlot(node.Operand), valueType: resultOfIncrementType);
                }
            }

            if (!setResult)
            {
                this.SetResult(node);
            }

            return null;
        }
@jcouv jcouv added this to the 16.0 milestone Sep 17, 2018
@jaredpar jaredpar added the Bug label Sep 18, 2018
@jaredpar jaredpar added this to Misc in Nullable Board Jan 28, 2019
@gafter gafter modified the milestones: 16.0, 16.1 Feb 26, 2019
@jcouv jcouv modified the milestones: 16.1, 16.2 Apr 23, 2019
@jcouv jcouv modified the milestones: 16.2, Compiler.Next Jun 18, 2019
@jcouv jcouv moved this from Misc to APIs in Nullable Board Mar 25, 2020
@jcouv jcouv moved this from APIs to User Defined Operator in Nullable Board Mar 25, 2020
@jaredpar jaredpar modified the milestones: Compiler.Next, Backlog Sep 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Nullable Board
User Defined Operator
Development

No branches or pull requests

3 participants