Skip to content

Verify nullability analysis of ref, out and in arguments #29958

@jcouv

Description

@jcouv
        private void VisitArgumentEvaluate(ImmutableArray<BoundExpression> arguments, ImmutableArray<RefKind> refKindsOpt, int i, bool preserveConditionalState)
        {
            Debug.Assert(!IsConditionalState);
            RefKind refKind = GetRefKind(refKindsOpt, i);
            var argument = arguments[i];
            if (refKind != RefKind.Out)
            {
                // PROTOTYPE(NullReferenceTypes): `ref` arguments should be treated as l-values
                // for assignment. See `ref x3` in NullableReferenceTypesTests.PassingParameters_01.
                if (preserveConditionalState)
                {
                    Visit(argument);
                    // No Unsplit
                }
                else
                {
                    VisitRvalue(argument);
                }
            }
            else
            {
                // As far as we can tell, there is no scenario relevant to nullability analysis
                // where splitting an L-value (for instance with a ref ternary) would affect the result.
                VisitLvalue(argument);
            }
        }


        private static (ImmutableArray<BoundExpression> Arguments, ImmutableArray<Conversion> Conversions) RemoveArgumentConversions(
            ImmutableArray<BoundExpression> arguments,
            ImmutableArray<RefKind> refKindsOpt)
        {
            int n = arguments.Length;
            var conversions = default(ImmutableArray<Conversion>);
            if (n > 0)
            {
                var argumentsBuilder = ArrayBuilder<BoundExpression>.GetInstance(n);
                var conversionsBuilder = ArrayBuilder<Conversion>.GetInstance(n);
                bool includedConversion = false;
                for (int i = 0; i < n; i++)
                {
                    RefKind refKind = GetRefKind(refKindsOpt, i);
                    var argument = arguments[i];
                    var conversion = Conversion.Identity;
                    // https://github.com/dotnet/roslyn/issues/29958 Should `RefKind.In` be treated similarly to `RefKind.None`?
                    if (refKind == RefKind.None)
                    {
                        var before = argument;
                        (argument, conversion) = RemoveConversion(argument, includeExplicitConversions: false);
                        if (argument != before)
                        {
                            includedConversion = true;
                        }
                    }
                    argumentsBuilder.Add(argument);
                    conversionsBuilder.Add(conversion);
                }
                if (includedConversion)
                {
                    arguments = argumentsBuilder.ToImmutable();
                    conversions = conversionsBuilder.ToImmutable();
                }
                argumentsBuilder.Free();
                conversionsBuilder.Free();
            }
            return (arguments, conversions);
        }

Note: this issue is referenced in code. Find those references before closing this issue.

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions