File: Symbols\PartialPropertiesTests.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Symbol\Microsoft.CodeAnalysis.CSharp.Symbol.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Symbol.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols
{
    public class PartialPropertiesTests : CSharpTestBase
    {
        [Theory]
        [InlineData("partial int P { get; set; }")]
        [InlineData("partial int P { get; }")]
        [InlineData("partial int P { set; }")]
        [InlineData("partial int P { get; init; }")]
        [InlineData("partial int P { init; }")]
        public void MissingDeclaration_01(string definitionPart)
        {
            // definition without implementation
            var source = $$"""
                partial class C
                {
                    {{definitionPart}}
                }
                """;
            var comp = CreateCompilation([source, IsExternalInitTypeDefinition]);
            comp.VerifyEmitDiagnostics(
                // (3,17): error CS9248: Partial property 'C.P' must have an implementation part.
                //     partial int P { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "P").WithArguments("C.P").WithLocation(3, 17)
                );
 
            var cClass = comp.GetMember<NamedTypeSymbol>("C");
            var prop = cClass.GetMember<SourcePropertySymbol>("P");
            Assert.True(prop.IsPartialDefinition);
            Assert.Null(prop.PartialImplementationPart);
 
            var members = cClass.GetMembers().SelectAsArray(m => m.ToTestDisplayString());
            switch (definitionPart)
            {
                case "partial int P { get; set; }":
                    AssertEx.Equal([
                        "System.Int32 C.P { get; set; }",
                        "System.Int32 C.P.get",
                        "void C.P.set",
                        "C..ctor()"
                        ], members);
                    break;
                case "partial int P { get; }":
                    AssertEx.Equal([
                        "System.Int32 C.P { get; }",
                        "System.Int32 C.P.get",
                        "C..ctor()"
                        ], members);
                    break;
                case "partial int P { set; }":
                    AssertEx.Equal([
                        "System.Int32 C.P { set; }",
                        "void C.P.set",
                        "C..ctor()"
                        ], members);
                    break;
                case "partial int P { get; init; }":
                    AssertEx.Equal([
                        "System.Int32 C.P { get; init; }",
                        "System.Int32 C.P.get",
                        "void modreq(System.Runtime.CompilerServices.IsExternalInit) C.P.init",
                        "C..ctor()"
                        ], members);
                    break;
                case "partial int P { init; }":
                    AssertEx.Equal([
                        "System.Int32 C.P { init; }",
                        "void modreq(System.Runtime.CompilerServices.IsExternalInit) C.P.init",
                        "C..ctor()"
                        ], members);
                    break;
                default:
                    throw ExceptionUtilities.Unreachable();
            }
        }
 
        [Theory]
        [InlineData("partial int P { get => throw null!; set { } }")]
        [InlineData("partial int P { get => throw null!; }")]
        [InlineData("partial int P { set { } }")]
        [InlineData("partial int P { get => throw null!; init { } }")]
        [InlineData("partial int P { init { } }")]
        public void MissingDeclaration_02(string implementationPart)
        {
            // implementation without definition
            var source = $$"""
                partial class C
                {
                    {{implementationPart}}
                }
                """;
            var comp = CreateCompilation([source, IsExternalInitTypeDefinition]);
            comp.VerifyEmitDiagnostics(
                // (3,17): error CS9249: Partial property 'C.P' must have a definition part.
                //     partial int P { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "P").WithArguments("C.P").WithLocation(3, 17)
                );
 
            var cClass = comp.GetMember<NamedTypeSymbol>("C");
            var prop = cClass.GetMember<SourcePropertySymbol>("P");
            Assert.True(prop.IsPartialImplementation);
            Assert.Null(prop.PartialDefinitionPart);
 
            var members = cClass.GetMembers().SelectAsArray(m => m.ToTestDisplayString());
            switch (implementationPart)
            {
                case "partial int P { get => throw null!; set { } }":
                    AssertEx.Equal([
                        "System.Int32 C.P { get; set; }",
                        "System.Int32 C.P.get",
                        "void C.P.set",
                        "C..ctor()"
                        ], members);
                    break;
                case "partial int P { get => throw null!; }":
                    AssertEx.Equal([
                        "System.Int32 C.P { get; }",
                        "System.Int32 C.P.get",
                        "C..ctor()"
                        ], members);
                    break;
                case "partial int P { set { } }":
                    AssertEx.Equal([
                        "System.Int32 C.P { set; }",
                        "void C.P.set",
                        "C..ctor()"
                        ], members);
                    break;
                case "partial int P { get => throw null!; init { } }":
                    AssertEx.Equal([
                        "System.Int32 C.P { get; init; }",
                        "System.Int32 C.P.get",
                        "void modreq(System.Runtime.CompilerServices.IsExternalInit) C.P.init",
                        "C..ctor()"
                        ], members);
                    break;
                case "partial int P { init { } }":
                    AssertEx.Equal([
                        "System.Int32 C.P { init; }",
                        "void modreq(System.Runtime.CompilerServices.IsExternalInit) C.P.init",
                        "C..ctor()"
                        ], members);
                    break;
                default:
                    throw ExceptionUtilities.Unreachable();
            }
        }
 
        [Fact]
        public void DuplicateDeclaration_01()
        {
            // duplicate definition
            var source = """
                partial class C
                {
                    partial int P { get; set; }
                    partial int P { get; set; }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,17): error CS9248: Partial property 'C.P' must have an implementation part.
                //     partial int P { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "P").WithArguments("C.P").WithLocation(3, 17),
                // (4,17): error CS9250: A partial property may not have multiple defining declarations, and cannot be an auto-property.
                //     partial int P { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateDefinition, "P").WithLocation(4, 17),
                // (4,17): error CS0102: The type 'C' already contains a definition for 'P'
                //     partial int P { get; set; }
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "P").WithArguments("C", "P").WithLocation(4, 17)
                );
        }
 
        [Fact]
        public void DuplicateDeclaration_02()
        {
            // duplicate definition with single implementation
            var source = """
                partial class C
                {
                    partial int P { get; set; }
                    partial int P { get; set; }
                    partial int P { get => throw null!; set { } }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,17): error CS9250: A partial property may not have multiple defining declarations, and cannot be an auto-property.
                //     partial int P { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateDefinition, "P").WithLocation(4, 17),
                // (4,17): error CS0102: The type 'C' already contains a definition for 'P'
                //     partial int P { get; set; }
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "P").WithArguments("C", "P").WithLocation(4, 17)
                );
        }
 
        [Fact]
        public void DuplicateDeclaration_03()
        {
            // duplicate implementation
            var source = """
                partial class C
                {
                    partial int P { get => throw null!; set { } }
                    partial int P { get => throw null!; set { } }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,17): error CS9249: Partial property 'C.P' must have a definition part.
                //     partial int P { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "P").WithArguments("C.P").WithLocation(3, 17),
                // (4,17): error CS9251: A partial property may not have multiple implementing declarations
                //     partial int P { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateImplementation, "P").WithLocation(4, 17),
                // (4,17): error CS0102: The type 'C' already contains a definition for 'P'
                //     partial int P { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "P").WithArguments("C", "P").WithLocation(4, 17)
                );
        }
 
        [Fact]
        public void DuplicateDeclaration_04()
        {
            // duplicate implementation with single definition
            var source = """
                partial class C
                {
                    partial int P { get; set; }
                    partial int P { get => throw null!; set { } }
                    partial int P { get => throw null!; set { } }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (5,17): error CS9251: A partial property may not have multiple implementing declarations
                //     partial int P { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateImplementation, "P").WithLocation(5, 17),
                // (5,17): error CS0102: The type 'C' already contains a definition for 'P'
                //     partial int P { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "P").WithArguments("C", "P").WithLocation(5, 17)
                );
        }
 
        [Fact]
        public void DuplicateDeclaration_05()
        {
            // duplicate implementation and duplicate definition
            var source = """
                partial class C
                {
                    partial int P { get; set; }
                    partial int P { get; set; }
                    partial int P { get => throw null!; set { } }
                    partial int P { get => throw null!; set { } }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,17): error CS9250: A partial property may not have multiple defining declarations, and cannot be an auto-property.
                //     partial int P { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateDefinition, "P").WithLocation(4, 17),
                // (4,17): error CS0102: The type 'C' already contains a definition for 'P'
                //     partial int P { get; set; }
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "P").WithArguments("C", "P").WithLocation(4, 17),
                // (6,17): error CS9251: A partial property may not have multiple implementing declarations
                //     partial int P { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateImplementation, "P").WithLocation(6, 17),
                // (6,17): error CS0102: The type 'C' already contains a definition for 'P'
                //     partial int P { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "P").WithArguments("C", "P").WithLocation(6, 17)
                );
        }
 
        [Fact]
        public void DuplicateDeclaration_06()
        {
            // partial method and partial property have the same name
            var source = """
                partial class C
                {
                    public partial int P { get; set; }
                    public partial int P() => 1;
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,24): error CS9248: Partial property 'C.P' must have an implementation part.
                //     public partial int P { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "P").WithArguments("C.P").WithLocation(3, 24),
                // (4,24): error CS0759: No defining declaration found for implementing declaration of partial method 'C.P()'
                //     public partial int P() => 1;
                Diagnostic(ErrorCode.ERR_PartialMethodMustHaveLatent, "P").WithArguments("C.P()").WithLocation(4, 24),
                // (4,24): error CS0102: The type 'C' already contains a definition for 'P'
                //     public partial int P() => 1;
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "P").WithArguments("C", "P").WithLocation(4, 24)
                );
        }
 
        [Fact]
        public void DuplicateDeclaration_07()
        {
            // partial method and partial property accessor have the same metadata name
            var source = """
                partial class C
                {
                    public partial int P { get; }
                    public partial int get_P() => 1;
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,24): error CS9248: Partial property 'C.P' must have an implementation part.
                //     public partial int P { get; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "P").WithArguments("C.P").WithLocation(3, 24),
                // (3,28): error CS0082: Type 'C' already reserves a member called 'get_P' with the same parameter types
                //     public partial int P { get; }
                Diagnostic(ErrorCode.ERR_MemberReserved, "get").WithArguments("get_P", "C").WithLocation(3, 28)
                );
        }
 
        [Fact]
        public void DuplicateDeclaration_08()
        {
            // multiple implementing declarations where accessors are "split" across declarations
            var source = """
                partial class C
                {
                    public partial int P { get; set; }
                    public partial int P { get => 1; }
                    public partial int P { set { } }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,24): error CS9252: Property accessor 'C.P.set' must be implemented because it is declared on the definition part
                //     public partial int P { get => 1; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingAccessor, "P").WithArguments("C.P.set").WithLocation(4, 24),
                // (5,24): error CS9251: A partial property may not have multiple implementing declarations
                //     public partial int P { set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateImplementation, "P").WithLocation(5, 24),
                // (5,24): error CS0102: The type 'C' already contains a definition for 'P'
                //     public partial int P { set { } }
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "P").WithArguments("C", "P").WithLocation(5, 24)
                );
 
            if (comp.GetMembers("C.P") is not [SourcePropertySymbol prop, SourcePropertySymbol duplicateProp])
                throw ExceptionUtilities.UnexpectedValue(comp.GetMembers("C.P"));
 
            Assert.True(prop.IsPartialDefinition);
            Assert.Equal("System.Int32 C.P { get; set; }", prop.ToTestDisplayString());
            Assert.Equal("System.Int32 C.P { get; }", prop.PartialImplementationPart.ToTestDisplayString());
 
            Assert.True(duplicateProp.IsPartialImplementation);
            Assert.Null(duplicateProp.PartialDefinitionPart);
            Assert.Equal("System.Int32 C.P { set; }", duplicateProp.ToTestDisplayString());
        }
 
        [Fact]
        public void DuplicateDeclaration_08_Definition()
        {
            // multiple defining declarations where accessors are "split" across declarations
            var source = """
                partial class C
                {
                    public partial int P { get; }
                    public partial int P { set; }
                    public partial int P { get => 1; set { } }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,24): error CS9250: A partial property may not have multiple defining declarations, and cannot be an auto-property.
                //     public partial int P { set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateDefinition, "P").WithLocation(4, 24),
                // (4,24): error CS0102: The type 'C' already contains a definition for 'P'
                //     public partial int P { set; }
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "P").WithArguments("C", "P").WithLocation(4, 24),
                // (5,24): error CS9253: Property accessor 'C.P.set' does not implement any accessor declared on the definition part
                //     public partial int P { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyUnexpectedAccessor, "P").WithArguments("C.P.set").WithLocation(5, 24)
                );
 
            if (comp.GetMembers("C.P") is not [SourcePropertySymbol prop, SourcePropertySymbol duplicateProp])
                throw ExceptionUtilities.UnexpectedValue(comp.GetMembers("C.P"));
 
            Assert.True(prop.IsPartialDefinition);
            Assert.Equal("System.Int32 C.P { get; }", prop.ToTestDisplayString());
            Assert.Equal("System.Int32 C.P { get; set; }", prop.PartialImplementationPart.ToTestDisplayString());
 
            Assert.True(duplicateProp.IsPartialDefinition);
            Assert.Null(duplicateProp.PartialImplementationPart);
            Assert.Equal("System.Int32 C.P { set; }", duplicateProp.ToTestDisplayString());
        }
 
        [Fact]
        public void DuplicateDeclaration_09()
        {
            // partial indexer and partial property Item
            var source = """
                partial class C
                {
                    public partial int this[int i] { get; }
                    public partial int Item => 1;
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,24): error CS9248: Partial property 'C.this[int]' must have an implementation part.
                //     public partial int this[int i] { get; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments("C.this[int]").WithLocation(3, 24),
                // (3,24): error CS0102: The type 'C' already contains a definition for 'Item'
                //     public partial int this[int i] { get; }
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "this").WithArguments("C", "Item").WithLocation(3, 24),
                // (4,24): error CS9249: Partial property 'C.Item' must have a definition part.
                //     public partial int Item => 1;
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "Item").WithArguments("C.Item").WithLocation(4, 24)
                );
        }
 
        [Fact]
        public void DuplicateDeclaration_10()
        {
            // partial parameterless (error) indexer and partial property Item
            var source = """
                partial class C
                {
                    public partial int this[] { get; }
                    public partial int Item => 1;
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,24): error CS9248: Partial property 'C.this' must have an implementation part.
                //     public partial int this[] { get; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments("C.this").WithLocation(3, 24),
                // (3,24): error CS0102: The type 'C' already contains a definition for 'Item'
                //     public partial int this[] { get; }
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "this").WithArguments("C", "Item").WithLocation(3, 24),
                // (3,29): error CS1551: Indexers must have at least one parameter
                //     public partial int this[] { get; }
                Diagnostic(ErrorCode.ERR_IndexerNeedsParam, "]").WithLocation(3, 29),
                // (4,24): error CS9249: Partial property 'C.Item' must have a definition part.
                //     public partial int Item => 1;
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "Item").WithArguments("C.Item").WithLocation(4, 24)
                );
        }
 
        [Fact]
        public void MissingAccessor_01()
        {
            // implementation missing setter
            var source = """
                partial class C
                {
                    partial int P { get; set; }
                    partial int P { get => throw null!; }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,17): error CS9252: Property accessor 'C.P.set' must be implemented because it is declared on the definition part
                //     partial int P { get => throw null!; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingAccessor, "P").WithArguments("C.P.set").WithLocation(4, 17)
                );
        }
 
        [Fact]
        public void MissingAccessor_02()
        {
            // implementation missing getter
            var source = """
                partial class C
                {
                    partial int P { get; set; }
                    partial int P { set { } }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,17): error CS9252: Property accessor 'C.P.get' must be implemented because it is declared on the definition part
                //     partial int P { set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingAccessor, "P").WithArguments("C.P.get").WithLocation(4, 17)
                );
        }
 
        [Fact]
        public void MissingAccessor_03()
        {
            // implementation missing init
            var source = """
                partial class C
                {
                    partial int P { get; init; }
                    partial int P { get => throw null!; }
                }
                """;
            var comp = CreateCompilation([source, IsExternalInitTypeDefinition]);
            comp.VerifyEmitDiagnostics(
                // (4,17): error CS9252: Property accessor 'C.P.init' must be implemented because it is declared on the definition part
                //     partial int P { get => throw null!; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingAccessor, "P").WithArguments("C.P.init").WithLocation(4, 17)
                );
        }
 
        [Theory]
        [InlineData("get")]
        [InlineData("set")]
        [InlineData("init")]
        public void MissingAccessor_04(string accessorKind)
        {
            // duplicate property definitions, one with a single accessor, one empty
            var source = $$"""
                partial class C
                {
                    partial int P { {{accessorKind}}; }
                    partial int P { }
                }
                """;
            var comp = CreateCompilation([source, IsExternalInitTypeDefinition]);
            comp.VerifyEmitDiagnostics(
                // (3,17): error CS9248: Partial property 'C.P' must have an implementation part.
                //     partial int P { {{accessorKind}}; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "P").WithArguments("C.P").WithLocation(3, 17),
                // (4,17): error CS9250: A partial property may not have multiple defining declarations, and cannot be an auto-property.
                //     partial int P { }
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateDefinition, "P").WithLocation(4, 17),
                // (4,17): error CS0102: The type 'C' already contains a definition for 'P'
                //     partial int P { }
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "P").WithArguments("C", "P").WithLocation(4, 17),
                // (4,17): error CS0548: 'C.P': property or indexer must have at least one accessor
                //     partial int P { }
                Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "P").WithArguments("C.P").WithLocation(4, 17)
                );
        }
 
        [Theory]
        [InlineData("get")]
        [InlineData("set")]
        [InlineData("init")]
        public void MissingAccessor_05(string accessorKind)
        {
            // implementation single accessor, definition empty
            var source = $$"""
                partial class C
                {
                    partial int P { {{accessorKind}} => throw null!; }
                    partial int P { }
                }
                """;
            var comp = CreateCompilation([source, IsExternalInitTypeDefinition]);
            comp.VerifyEmitDiagnostics(
                // (3,17): error CS9253: Property accessor 'C.P.{accessorKind}' does not implement any accessor declared on the definition part
                //     partial int P { {{accessorKind}} => throw null!; }
                Diagnostic(ErrorCode.ERR_PartialPropertyUnexpectedAccessor, "P").WithArguments($"C.P.{accessorKind}").WithLocation(3, 17),
                // (4,17): error CS0548: 'C.P': property or indexer must have at least one accessor
                //     partial int P { }
                Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "P").WithArguments("C.P").WithLocation(4, 17)
                );
        }
 
        [Fact]
        public void UnexpectedAccessor_01()
        {
            // implementation unexpected setter
            var source = """
                partial class C
                {
                    partial int P { get; }
                    partial int P { get => throw null!; set { } }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,17): error CS9253: Property accessor 'C.P.set' does not implement any accessor declared on the definition part
                //     partial int P { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyUnexpectedAccessor, "P").WithArguments("C.P.set").WithLocation(4, 17)
                );
        }
 
        [Fact]
        public void UnexpectedAccessor_02()
        {
            // implementation unexpected getter
            var source = """
                partial class C
                {
                    partial int P { set; }
                    partial int P { get => throw null!; set { } }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,17): error CS9253: Property accessor 'C.P.get' does not implement any accessor declared on the definition part
                //     partial int P { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyUnexpectedAccessor, "P").WithArguments("C.P.get").WithLocation(4, 17)
                );
        }
 
        [Fact]
        public void UnexpectedAccessor_03()
        {
            // implementation unexpected init
            var source = """
                partial class C
                {
                    partial int P { get; }
                    partial int P { get => throw null!; init { } }
                }
                """;
            var comp = CreateCompilation([source, IsExternalInitTypeDefinition]);
            comp.VerifyEmitDiagnostics(
                // (4,17): error CS9253: Property accessor 'C.P.init' does not implement any accessor declared on the definition part
                //     partial int P { get => throw null!; init { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyUnexpectedAccessor, "P").WithArguments("C.P.init").WithLocation(4, 17)
                );
        }
 
        [Fact]
        public void AccessorKind_01()
        {
            // definition has set but implementation has init
            var source = """
                partial class C
                {
                    partial int P { get; set; }
                    partial int P { get => throw null!; init { } }
                }
                """;
 
            var comp = CreateCompilation([source, IsExternalInitTypeDefinition]);
            comp.VerifyEmitDiagnostics(
                // (4,41): error CS9254: Property accessor 'C.P.init' must be 'set' to match the definition part       
                //     partial int P { get => throw null!; init { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyInitMismatch, "init").WithArguments("C.P.init", "set").WithLocation(4, 41)
                );
        }
 
        [Fact]
        public void AccessorKind_02()
        {
            // definition has init but implementation has set
            var source = """
                partial class C
                {
                    partial int P { get; init; }
                    partial int P { get => throw null!; set { } }
                }
                """;
            var comp = CreateCompilation([source, IsExternalInitTypeDefinition]);
            comp.VerifyEmitDiagnostics(
                // (4,41): error CS9254: Property accessor 'C.P.set' must be 'init' to match the definition part
                //     partial int P { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyInitMismatch, "set").WithArguments("C.P.set", "init").WithLocation(4, 41)
                );
        }
 
        [Fact]
        public void Extern_01()
        {
            var source = """
                public partial class C
                {
                    public partial int P { get; set; }
                    public extern partial int P { get; set; }
                }
                """;
 
            var verifier = CompileAndVerify(
                [source, IsExternalInitTypeDefinition],
                sourceSymbolValidator: verifySource,
                symbolValidator: verifyMetadata,
                // PEVerify fails when extern methods lack an implementation
                verify: Verification.Skipped);
            verifier.VerifyDiagnostics();
 
            void verifySource(ModuleSymbol module)
            {
                var prop = module.GlobalNamespace.GetMember<SourcePropertySymbol>("C.P");
                Assert.True(prop.GetPublicSymbol().IsExtern);
                Assert.True(prop.GetMethod!.GetPublicSymbol().IsExtern);
                Assert.True(prop.SetMethod!.GetPublicSymbol().IsExtern);
                Assert.True(prop.PartialImplementationPart!.GetPublicSymbol().IsExtern);
                Assert.True(prop.PartialImplementationPart!.GetMethod!.GetPublicSymbol().IsExtern);
                Assert.True(prop.PartialImplementationPart!.SetMethod!.GetPublicSymbol().IsExtern);
            }
 
            void verifyMetadata(ModuleSymbol module)
            {
                var prop = module.GlobalNamespace.GetMember<PropertySymbol>("C.P");
                // IsExtern doesn't round trip from metadata when DllImportAttribute is missing
                // This is consistent with the behavior for methods
                Assert.False(prop.GetPublicSymbol().IsExtern);
                Assert.False(prop.GetMethod!.GetPublicSymbol().IsExtern);
                Assert.False(prop.SetMethod!.GetPublicSymbol().IsExtern);
            }
        }
 
        [Fact]
        public void Extern_02()
        {
            var source = """
                partial class C
                {
                    extern partial int P { get; set; }
                    extern partial int P { get; set; }
                }
                """;
            var comp = CreateCompilation([source, IsExternalInitTypeDefinition]);
            comp.VerifyEmitDiagnostics(
                // (3,24): error CS9249: Partial property 'C.P' must have a definition part.
                //     extern partial int P { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "P").WithArguments("C.P").WithLocation(3, 24),
                // (4,24): error CS9251: A partial property may not have multiple implementing declarations
                //     extern partial int P { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateImplementation, "P").WithLocation(4, 24),
                // (4,24): error CS0102: The type 'C' already contains a definition for 'P'
                //     extern partial int P { get; set; }
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "P").WithArguments("C", "P").WithLocation(4, 24)
                );
 
            var members = comp.GetMembers("C.P").SelectAsArray(m => (SourcePropertySymbol)m);
            Assert.Equal(2, members.Length);
            Assert.True(members[0].IsExtern);
            Assert.True(members[0].IsPartialImplementation);
            Assert.True(members[1].IsExtern);
            Assert.True(members[1].IsPartialImplementation);
        }
 
        /// <summary>Based on <see cref="ExtendedPartialMethodsTests.Extern_Symbols" /> as a starting point.</summary>
        [Fact]
        public void Extern_03()
        {
            var source = """
                using System.Runtime.InteropServices;
 
                public partial class C
                {
                    public static partial int P { get; set; }
                    public static extern partial int P
                    {
                        [DllImport("something.dll")]
                        get;
 
                        [DllImport("something.dll")]
                        set;
                    }
                }
                """;
            var verifier = CompileAndVerify(
                [source, IsExternalInitTypeDefinition],
                symbolValidator: module => verify(module, isSource: false),
                sourceSymbolValidator: module => verify(module, isSource: true));
            verifier.VerifyDiagnostics();
 
            void verify(ModuleSymbol module, bool isSource)
            {
                var prop = module.GlobalNamespace.GetMember<PropertySymbol>("C.P");
                Assert.True(prop.GetPublicSymbol().IsExtern);
                verifyAccessor(prop.GetMethod!);
                verifyAccessor(prop.SetMethod!);
 
                if (isSource)
                {
                    var implPart = ((SourcePropertySymbol)prop).PartialImplementationPart!;
                    Assert.True(implPart.GetPublicSymbol().IsExtern);
                    verifyAccessor(implPart.GetMethod!);
                    verifyAccessor(implPart.SetMethod!);
                }
            }
 
            void verifyAccessor(MethodSymbol accessor)
            {
                Assert.True(accessor.GetPublicSymbol().IsExtern);
 
                var importData = accessor.GetDllImportData()!;
                Assert.NotNull(importData);
                Assert.Equal("something.dll", importData.ModuleName);
                Assert.Equal(accessor.MetadataName, importData.EntryPointName); // e.g. 'get_P'
                Assert.Equal(CharSet.None, importData.CharacterSet);
                Assert.False(importData.SetLastError);
                Assert.False(importData.ExactSpelling);
                Assert.Equal(MethodImplAttributes.PreserveSig, accessor.ImplementationAttributes);
                Assert.Equal(CallingConvention.Winapi, importData.CallingConvention);
                Assert.Null(importData.BestFitMapping);
                Assert.Null(importData.ThrowOnUnmappableCharacter);
            }
        }
 
        /// <summary>Based on 'AttributeTests_WellKnownAttributes.TestPseudoAttributes_DllImport_OperatorsAndAccessors'.</summary>
        [Theory]
        [CombinatorialData]
        public void TestPseudoAttributes_DllImport(bool attributesOnDefinition)
        {
            var source = $$"""
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
 
public partial class C
{
    public static partial int F 
    { 
        {{(attributesOnDefinition ? @"[DllImport(""a"")]" : "")}} get;
        {{(attributesOnDefinition ? @"[DllImport(""b"")]" : "")}} set;
    }
 
    public extern static partial int F 
    { 
        {{(attributesOnDefinition ? "" : @"[DllImport(""a"")]")}} get;
        {{(attributesOnDefinition ? "" : @"[DllImport(""b"")]")}} set;
    }
}
""";
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview.WithNoRefSafetyRulesAttribute(), assemblyValidator: (assembly) =>
            {
                var metadataReader = assembly.GetMetadataReader();
 
                // no backing fields should be generated -- all members are "extern" members:
                Assert.Equal(0, metadataReader.FieldDefinitions.AsEnumerable().Count());
 
                Assert.Equal(2, metadataReader.GetTableRowCount(TableIndex.ModuleRef));
                Assert.Equal(2, metadataReader.GetTableRowCount(TableIndex.ImplMap));
                var visitedEntryPoints = new Dictionary<string, bool>();
 
                foreach (var method in metadataReader.GetImportedMethods())
                {
                    string moduleName = metadataReader.GetString(metadataReader.GetModuleReference(method.GetImport().Module).Name);
                    string entryPointName = metadataReader.GetString(method.Name);
                    switch (entryPointName)
                    {
                        case "get_F":
                            Assert.Equal("a", moduleName);
                            break;
 
                        case "set_F":
                            Assert.Equal("b", moduleName);
                            break;
 
                        default:
                            throw TestExceptionUtilities.UnexpectedValue(entryPointName);
                    }
 
                    // This throws if we visit one entry point name twice.
                    visitedEntryPoints.Add(entryPointName, true);
                }
 
                Assert.Equal(2, visitedEntryPoints.Count);
            });
        }
 
        [Fact]
        public void Semantics_01()
        {
            // happy definition + implementation case
            var source = """
                using System;
 
                var c = new C { P = 1 };
                Console.Write(c.P);
 
                partial class C
                {
                    public partial int P { get; set; }
                }
 
                partial class C
                {
                    private int _p;
                    public partial int P { get => _p; set => _p = value; }
                }
                """;
            var verifier = CompileAndVerify(source, expectedOutput: "1");
            verifier.VerifyDiagnostics();
            verifier.VerifyIL("C.P.get", """
                {
                  // Code size        7 (0x7)
                  .maxstack  1
                  IL_0000:  ldarg.0
                  IL_0001:  ldfld      "int C._p"
                  IL_0006:  ret
                }
                """);
            verifier.VerifyIL("C.P.set", """
                {
                  // Code size        8 (0x8)
                  .maxstack  2
                  IL_0000:  ldarg.0
                  IL_0001:  ldarg.1
                  IL_0002:  stfld      "int C._p"
                  IL_0007:  ret
                }
                """);
 
            var comp = (CSharpCompilation)verifier.Compilation;
            var cClass = comp.GetMember<NamedTypeSymbol>("C");
            var members = cClass.GetMembers().SelectAsArray(m => m.ToTestDisplayString());
            AssertEx.Equal([
                "System.Int32 C.P { get; set; }",
                "System.Int32 C.P.get",
                "void C.P.set",
                "System.Int32 C._p",
                "C..ctor()"
                ], members);
 
            var propDefinition = comp.GetMember<SourcePropertySymbol>("C.P");
            Assert.True(propDefinition.IsPartialDefinition);
 
            var propImplementation = propDefinition.PartialImplementationPart!;
            Assert.True(propImplementation.IsPartialImplementation());
 
            Assert.Same(propDefinition, propImplementation.PartialDefinitionPart);
            Assert.Null(propImplementation.PartialImplementationPart);
            Assert.Same(propImplementation, propDefinition.PartialImplementationPart);
            Assert.Null(propDefinition.PartialDefinitionPart);
 
            Assert.Same(propDefinition.GetMethod, comp.GetMember<MethodSymbol>("C.get_P"));
            Assert.Same(propDefinition.SetMethod, comp.GetMember<MethodSymbol>("C.set_P"));
 
            verifyAccessor(propDefinition.GetMethod!, propImplementation.GetMethod!);
            verifyAccessor(propDefinition.SetMethod!, propImplementation.SetMethod!);
 
            void verifyAccessor(MethodSymbol definitionAccessor, MethodSymbol implementationAccessor)
            {
                Assert.True(definitionAccessor.IsPartialDefinition());
                Assert.True(implementationAccessor.IsPartialImplementation());
 
                Assert.Same(implementationAccessor, definitionAccessor.PartialImplementationPart);
                Assert.Null(definitionAccessor.PartialDefinitionPart);
                Assert.Same(definitionAccessor, implementationAccessor.PartialDefinitionPart);
                Assert.Null(implementationAccessor.PartialImplementationPart);
            }
        }
 
        [Theory]
        [InlineData("public partial int P { get => _p; }")]
        [InlineData("public partial int P => _p;")]
        public void Semantics_02(string implementationPart)
        {
            // get-only
            var source = $$"""
                using System;
 
                var c = new C();
                Console.Write(c.P);
 
                partial class C
                {
                    public partial int P { get; }
                }
 
                partial class C
                {
                    private int _p = 1;
                    {{implementationPart}}
                }
                """;
            var verifier = CompileAndVerify(source, expectedOutput: "1");
            verifier.VerifyDiagnostics();
            verifier.VerifyIL("C.P.get", """
                {
                  // Code size        7 (0x7)
                  .maxstack  1
                  IL_0000:  ldarg.0
                  IL_0001:  ldfld      "int C._p"
                  IL_0006:  ret
                }
                """);
 
            var comp = (CSharpCompilation)verifier.Compilation;
            var cClass = comp.GetMember<NamedTypeSymbol>("C");
            var members = cClass.GetMembers().SelectAsArray(m => m.ToTestDisplayString());
            AssertEx.Equal([
                "System.Int32 C.P { get; }",
                "System.Int32 C.P.get",
                "System.Int32 C._p",
                "C..ctor()"
                ], members);
 
            var propDefinition = comp.GetMember<SourcePropertySymbol>("C.P");
            Assert.True(propDefinition.IsPartialDefinition);
 
            var propImplementation = propDefinition.PartialImplementationPart!;
            Assert.True(propImplementation.IsPartialImplementation());
 
            Assert.Same(propDefinition, propImplementation.PartialDefinitionPart);
            Assert.Null(propImplementation.PartialImplementationPart);
            Assert.Same(propImplementation, propDefinition.PartialImplementationPart);
            Assert.Null(propDefinition.PartialDefinitionPart);
 
            Assert.Null(propDefinition.SetMethod);
            Assert.Null(propImplementation.SetMethod);
 
            var definitionAccessor = propDefinition.GetMethod!;
            var implementationAccessor = propImplementation.GetMethod!;
            Assert.True(definitionAccessor.IsPartialDefinition());
            Assert.True(implementationAccessor.IsPartialImplementation());
 
            Assert.Same(implementationAccessor, definitionAccessor.PartialImplementationPart);
            Assert.Null(definitionAccessor.PartialDefinitionPart);
            Assert.Same(definitionAccessor, implementationAccessor.PartialDefinitionPart);
            Assert.Null(implementationAccessor.PartialImplementationPart);
        }
 
        [Theory]
        [InlineData("set")]
        [InlineData("init")]
        public void Semantics_03(string accessorKind)
        {
            // set/init-only
            var source = $$"""
                using System;
 
                var c = new C() { P = 1 };
 
                partial class C
                {
                    public partial int P { {{accessorKind}}; }
                }
 
                partial class C
                {
                    public partial int P
                    {
                        {{accessorKind}}
                        {
                            Console.Write(value);
                        }
                    }
                }
                """;
            var verifier = CompileAndVerify([source, IsExternalInitTypeDefinition], expectedOutput: "1");
            verifier.VerifyDiagnostics();
            verifier.VerifyIL($"C.P.{accessorKind}", """
                {
                  // Code size        7 (0x7)
                  .maxstack  1
                  IL_0000:  ldarg.1
                  IL_0001:  call       "void System.Console.Write(int)"
                  IL_0006:  ret
                }
                """);
 
            var comp = (CSharpCompilation)verifier.Compilation;
            var cClass = comp.GetMember<NamedTypeSymbol>("C");
            var members = cClass.GetMembers().SelectAsArray(m => m.ToTestDisplayString());
 
            if (accessorKind == "set")
            {
                AssertEx.Equal([
                    "System.Int32 C.P { set; }",
                    "void C.P.set",
                    "C..ctor()"
                    ], members);
            }
            else
            {
                AssertEx.Equal([
                    "System.Int32 C.P { init; }",
                    "void modreq(System.Runtime.CompilerServices.IsExternalInit) C.P.init",
                    "C..ctor()"
                    ],
                    members);
            }
 
            var propDefinition = comp.GetMember<SourcePropertySymbol>("C.P");
            Assert.True(propDefinition.IsPartialDefinition);
 
            var propImplementation = propDefinition.PartialImplementationPart!;
            Assert.True(propImplementation.IsPartialImplementation());
 
            Assert.Same(propDefinition, propImplementation.PartialDefinitionPart);
            Assert.Null(propImplementation.PartialImplementationPart);
            Assert.Same(propImplementation, propDefinition.PartialImplementationPart);
            Assert.Null(propDefinition.PartialDefinitionPart);
 
            Assert.Null(propDefinition.GetMethod);
            Assert.Null(propImplementation.GetMethod);
 
            var definitionAccessor = propDefinition.SetMethod!;
            var implementationAccessor = propImplementation.SetMethod!;
            Assert.True(definitionAccessor.IsPartialDefinition());
            Assert.True(implementationAccessor.IsPartialImplementation());
 
            Assert.Same(implementationAccessor, definitionAccessor.PartialImplementationPart);
            Assert.Null(definitionAccessor.PartialDefinitionPart);
            Assert.Same(definitionAccessor, implementationAccessor.PartialDefinitionPart);
            Assert.Null(implementationAccessor.PartialImplementationPart);
        }
 
        [Theory]
        [InlineData("public partial int P { get => _p; set => _p = value; }")]
        [InlineData("public partial int P { set => _p = value; get => _p; }")]
        public void Semantics_04(string implementationPart)
        {
            // ordering difference between def and impl
            var source = $$"""
                using System;
 
                var c = new C() { P = 1 };
                Console.Write(c.P);
 
                partial class C
                {
                    public partial int P { get; set; }
 
                    private int _p;
                    {{implementationPart}}
                }
                """;
 
            var verifier = CompileAndVerify(source, expectedOutput: "1");
            verifier.VerifyDiagnostics();
            var comp = (CSharpCompilation)verifier.Compilation;
 
            var members = comp.GetMember<NamedTypeSymbol>("C").GetMembers().SelectAsArray(m => m.ToTestDisplayString());
            AssertEx.Equal([
                "System.Int32 C.P { get; set; }",
                "System.Int32 C.P.get",
                "void C.P.set",
                "System.Int32 C._p",
                "C..ctor()"
                ], members);
 
            var reference = comp.EmitToImageReference();
            var comp1 = CreateCompilation([], options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), references: [reference]);
            var members1 = comp1.GetMember<NamedTypeSymbol>("C").GetMembers().SelectAsArray(m => m.ToTestDisplayString());
            AssertEx.Equal([
                "System.Int32 C._p",
                "System.Int32 C.P.get",
                "void C.P.set",
                "C..ctor()",
                "System.Int32 C.P { get; set; }"
                ], members1);
        }
 
        [Theory]
        [InlineData("public partial int P { get => _p; set => _p = value; }")]
        [InlineData("public partial int P { set => _p = value; get => _p; }")]
        public void Semantics_05(string implementationPart)
        {
            // ordering difference between def and impl (def set before get)
            var source = $$"""
                using System;
 
                var c = new C() { P = 1 };
                Console.Write(c.P);
 
                partial class C
                {
                    public partial int P { set; get; }
 
                    private int _p;
                    {{implementationPart}}
                }
                """;
 
            var verifier = CompileAndVerify(source, expectedOutput: "1");
            verifier.VerifyDiagnostics();
            var comp = (CSharpCompilation)verifier.Compilation;
 
            var members = comp.GetMember<NamedTypeSymbol>("C").GetMembers().SelectAsArray(m => m.ToTestDisplayString());
            // set accessor appears before get accessor, otherwise member order and symbol display is the same as Semantics_04
            AssertEx.Equal([
                "System.Int32 C.P { get; set; }",
                "void C.P.set",
                "System.Int32 C.P.get",
                "System.Int32 C._p",
                "C..ctor()"
                ], members);
 
            var reference = comp.EmitToImageReference();
            var comp1 = CreateCompilation([], options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), references: [reference]);
            var members1 = comp1.GetMember<NamedTypeSymbol>("C").GetMembers().SelectAsArray(m => m.ToTestDisplayString());
            AssertEx.Equal([
                "System.Int32 C._p",
                "void C.P.set",
                "System.Int32 C.P.get",
                "C..ctor()",
                "System.Int32 C.P { get; set; }"
                ], members1);
        }
 
        [Fact]
        public void ModifierDifference_Accessibility_Property()
        {
            var source = """
                partial class C
                {
                    public partial int P1 { get; set; }
                    partial int P2 { get; set; }
                }
 
                partial class C
                {
                    partial int P1 { get => throw null!; set { } }
                    protected partial int P2 { get => throw null!; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (9,17): error CS8799: Both partial member declarations must have identical accessibility modifiers.
                //     partial int P1 { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberAccessibilityDifference, "P1").WithLocation(9, 17),
                // (10,27): error CS8799: Both partial member declarations must have identical accessibility modifiers.
                //     protected partial int P2 { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberAccessibilityDifference, "P2").WithLocation(10, 27));
        }
 
        // Property accessor modifiers can only include:
        // - accessibility modifiers
        // - readonly modifier
        // The test burden for accessors is further reduced by the fact that explicit accessibility
        // is only permitted when it is more restrictive than the containing property.
 
        [Fact]
        public void ModifierDifference_Accessibility_Accessors()
        {
            // access modifier mismatch on accessors
            var source = """
                partial class C
                {
                    public partial int P { get; private set; }
                }
 
                partial class C
                {
                    public partial int P { internal get => throw null!; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
 
            comp.VerifyEmitDiagnostics(
                // (8,37): error CS8799: Both partial member declarations must have identical accessibility modifiers.
                //     public partial int P { internal get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberAccessibilityDifference, "get").WithLocation(8, 37),
                // (8,57): error CS8799: Both partial member declarations must have identical accessibility modifiers.
                //     public partial int P { internal get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberAccessibilityDifference, "set").WithLocation(8, 57));
        }
 
        [Fact]
        public void Semantics_Readonly_01()
        {
            var source = """
                using System;
 
                class Program
                {
                    static void Main()
                    {
                        M(new S());
                    }
 
                    static void M(in S s)
                    {
                        Console.Write(s.P1);
                        Console.Write(s.P2);
                        // We can't exercise S.P2.set here because non-readonly setters will error instead of implicitly copying the receiver.
                        s.P3 = 3;
                        Console.Write(s.P3);
                        Console.Write(s.P4);
                    }
                }
 
                partial struct S
                {
                    public readonly partial int P1 { get; }
                    public readonly partial int P1 { get => 1; }
 
                    public partial int P2 { readonly get; set; }
                    public partial int P2 { readonly get => 2; set { } }
 
                    public partial int P3 { get; readonly set; }
                    public partial int P3 { get => 3; readonly set { } }
 
                    public partial int P4 { get; }
                    public partial int P4 { get => 4; }
                }
                """;
 
            var verifier = CompileAndVerify(source, expectedOutput: "1234");
            verifier.VerifyDiagnostics();
 
            // non-readonly accessors need to copy the value to temp before invoking.
            verifier.VerifyIL("Program.M", """
                {
                  // Code size       68 (0x44)
                  .maxstack  2
                  .locals init (S V_0)
                  IL_0000:  ldarg.0
                  IL_0001:  call       "readonly int S.P1.get"
                  IL_0006:  call       "void System.Console.Write(int)"
                  IL_000b:  ldarg.0
                  IL_000c:  call       "readonly int S.P2.get"
                  IL_0011:  call       "void System.Console.Write(int)"
                  IL_0016:  ldarg.0
                  IL_0017:  ldc.i4.3
                  IL_0018:  call       "readonly void S.P3.set"
                  IL_001d:  ldarg.0
                  IL_001e:  ldobj      "S"
                  IL_0023:  stloc.0
                  IL_0024:  ldloca.s   V_0
                  IL_0026:  call       "int S.P3.get"
                  IL_002b:  call       "void System.Console.Write(int)"
                  IL_0030:  ldarg.0
                  IL_0031:  ldobj      "S"
                  IL_0036:  stloc.0
                  IL_0037:  ldloca.s   V_0
                  IL_0039:  call       "int S.P4.get"
                  IL_003e:  call       "void System.Console.Write(int)"
                  IL_0043:  ret
                }
                """);
 
            var comp = (CSharpCompilation)verifier.Compilation;
        }
 
        [Fact]
        public void ModifierDifference_Readonly_Property()
        {
            // readonly modifier mismatch on property
            var source = """
                partial struct S
                {
                    readonly partial int P1 { get; set; }
                    partial int P2 { get; set; }
                    readonly partial int P3 { get; set; }
                }
 
                partial struct S
                {
                    partial int P1 { get => throw null!; set { } }
                    readonly partial int P2 { get => throw null!; set { } }
                    readonly partial int P3 { get => throw null!; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
 
            comp.VerifyEmitDiagnostics(
                // (10,17): error CS8663: Both partial member declarations must be readonly or neither may be readonly
                //     partial int P1 { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "P1").WithLocation(10, 17),
                // (11,26): error CS8663: Both partial member declarations must be readonly or neither may be readonly
                //     readonly partial int P2 { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "P2").WithLocation(11, 26));
        }
 
        [Fact]
        public void ModifierDifference_Readonly_Accessors()
        {
            // readonly modifier mismatch on accessors
            var source = """
                partial struct S
                {
                    public partial int P { readonly get; set; }
                }
 
                partial struct S
                {
                    public partial int P { get => throw null!; readonly set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
 
            comp.VerifyEmitDiagnostics(
                // (8,28): error CS8663: Both partial member declarations must be readonly or neither may be readonly
                //     public partial int P { get => throw null!; readonly set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "get").WithLocation(8, 28),
                // (8,57): error CS8663: Both partial member declarations must be readonly or neither may be readonly
                //     public partial int P { get => throw null!; readonly set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "set").WithLocation(8, 57));
        }
 
        [Fact]
        public void Accessibility_ExplicitDefault()
        {
            // properties can explicitly specify the default accessibility
            var source = """
                using System;
 
                partial class C
                {
                    private partial int P1 { get; }
 
                    static void Main()
                    {
                        Console.Write(new C().P1);
                    }
                }
 
                partial class C
                {
                    private partial int P1 { get => 1; }
                }
                """;
 
            var verifier = CompileAndVerify(source, expectedOutput: "1");
            verifier.VerifyDiagnostics();
        }
 
        [Fact]
        public void Accessibility_ExplicitDefault_IsRespected()
        {
            var source = """
                using System;
 
                class Program
                {
                    static void Main()
                    {
                        Console.Write(new C().P1); // 1
                    }
 
                }
 
                partial class C
                {
                    private partial int P1 { get; }
                }
 
                partial class C
                {
                    private partial int P1 { get => 1; }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (7,31): error CS0122: 'C.P1' is inaccessible due to its protection level
                //         Console.Write(new C().P1); // 1
                Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("C.P1").WithLocation(7, 31));
 
            var p1Def = comp.GetMember<SourcePropertySymbol>("C.P1");
            Assert.True(p1Def.IsPartialDefinition);
            Assert.Equal(Accessibility.Private, p1Def.DeclaredAccessibility);
 
            var p1DefPublic = p1Def.GetPublicSymbol();
            Assert.Equal(Accessibility.Private, p1DefPublic.DeclaredAccessibility);
        }
 
        [Fact]
        public void ModifierDifference_Accessibility_ExplicitDefault_01()
        {
            // only one part explicitly specifies the default accessibility
            var source = """
                partial class C
                {
                    private partial int P1 { get; set; }
                    partial int P2 { get; set; }
                }
 
                partial class C
                {
                    partial int P1 { get => throw null!; set { } }
                    private partial int P2 { get => throw null!; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (9,17): error CS8799: Both partial member declarations must have identical accessibility modifiers.
                //     partial int P1 { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberAccessibilityDifference, "P1").WithLocation(9, 17),
                // (10,25): error CS8799: Both partial member declarations must have identical accessibility modifiers.
                //     private partial int P2 { get => throw null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberAccessibilityDifference, "P2").WithLocation(10, 25));
        }
 
        [Fact]
        public void ModifierDifference_Accessibility_ExplicitDefault_02()
        {
            var source = """
                using System;
 
                partial class C
                {
                    private partial int P1 { get; set; }
                    partial int P2 { private get; private set; }
                }
 
                partial class C
                {
                    partial int P1 { private get => 1; private set; }
                    partial int P2 { private get => 1; private set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (6,17): error CS0274: Cannot specify accessibility modifiers for both accessors of the property or indexer 'C.P2'
                //     partial int P2 { private get; private set; }
                Diagnostic(ErrorCode.ERR_DuplicatePropertyAccessMods, "P2").WithArguments("C.P2").WithLocation(6, 17),
                // (6,30): error CS0273: The accessibility modifier of the 'C.P2.get' accessor must be more restrictive than the property or indexer 'C.P2'
                //     partial int P2 { private get; private set; }
                Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("C.P2.get", "C.P2").WithLocation(6, 30),
                // (6,43): error CS0273: The accessibility modifier of the 'C.P2.set' accessor must be more restrictive than the property or indexer 'C.P2'
                //     partial int P2 { private get; private set; }
                Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "set").WithArguments("C.P2.set", "C.P2").WithLocation(6, 43),
                // (11,17): error CS8799: Both partial member declarations must have identical accessibility modifiers.
                //     partial int P1 { private get => 1; private set; }
                Diagnostic(ErrorCode.ERR_PartialMemberAccessibilityDifference, "P1").WithLocation(11, 17),
                // (11,30): warning CS9266: The 'get' accessor of property 'C.P1' should use 'field' because the other accessor is using it.
                //     partial int P1 { private get => 1; private set; }
                Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(11, 30),
                // (11,30): error CS8799: Both partial member declarations must have identical accessibility modifiers.
                //     partial int P1 { private get => 1; private set; }
                Diagnostic(ErrorCode.ERR_PartialMemberAccessibilityDifference, "get").WithLocation(11, 30),
                // (11,48): error CS8799: Both partial member declarations must have identical accessibility modifiers.
                //     partial int P1 { private get => 1; private set; }
                Diagnostic(ErrorCode.ERR_PartialMemberAccessibilityDifference, "set").WithLocation(11, 48));
        }
 
        [Fact]
        public void TypeDifference_01()
        {
            var source = """
                using System.Collections.Generic;
 
                partial class C
                {
                    partial int P1 { get; set; }
                    partial string P1 { get => ""; set { } }
 
                    partial List<int> P2 { get; set; }
                    partial List<string> P2 { get => []; set { } }
 
                    partial IEnumerable<object> P3 { get; set; }
                    partial IEnumerable<string> P3 { get => []; set { } }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (6,20): error CS9255: Both partial property declarations must have the same type.
                //     partial string P1 { get => ""; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyTypeDifference, "P1").WithLocation(6, 20),
                // (9,26): error CS9255: Both partial property declarations must have the same type.
                //     partial List<string> P2 { get => []; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyTypeDifference, "P2").WithLocation(9, 26),
                // (12,33): error CS9255: Both partial property declarations must have the same type.
                //     partial IEnumerable<string> P3 { get => []; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyTypeDifference, "P3").WithLocation(12, 33));
        }
 
        [Fact]
        public void TypeDifference_02()
        {
            var source = """
                #nullable enable
                partial class C
                {
                    partial string? P1 { get; set; }
                    partial string P1 { get => ""; set { } }
 
                    partial string P2 { get; set; }
                    partial string? P2 { get => ""; set { } }
 
                    partial string?[] P3 { get; set; }
                    partial string[] P3 { get => []; set { } }
 
                    partial string[] P4 { get; set; }
                    partial string?[] P4 { get => []; set { } }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (5,20): error CS9256: Partial property declarations 'string? C.P1' and 'string C.P1' have signature differences.
                //     partial string P1 { get => ""; set { } }
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "P1").WithArguments("string? C.P1", "string C.P1").WithLocation(5, 20),
                // (8,21): error CS9256: Partial property declarations 'string C.P2' and 'string? C.P2' have signature differences.
                //     partial string? P2 { get => ""; set { } }
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "P2").WithArguments("string C.P2", "string? C.P2").WithLocation(8, 21),
                // (11,22): error CS9256: Partial property declarations 'string?[] C.P3' and 'string[] C.P3' have signature differences.
                //     partial string[] P3 { get => []; set { } }
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "P3").WithArguments("string?[] C.P3", "string[] C.P3").WithLocation(11, 22),
                // (14,23): error CS9256: Partial property declarations 'string[] C.P4' and 'string?[] C.P4' have signature differences.
                //     partial string?[] P4 { get => []; set { } }
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "P4").WithArguments("string[] C.P4", "string?[] C.P4").WithLocation(14, 23));
        }
 
        [Fact]
        public void NullableDifference_NullableWarningsDisabled()
        {
            // 'safe' nullable differences for partial methods are still reported even when nullable warnings are disabled.
            // For simplicity we replicate this behavior for partial properties.
            var source = """
                partial class C
                {
                    public partial string? P1 { get; set; }
                    public partial string P1 { get => ""; set { } }
 
                    public partial string P2 { get; set; }
                    public partial string? P2 { get => ""; set { } }
 
                    public partial string? M1();
                    public partial string M1() => "";
 
                    public partial string M2();
                    public partial string? M2() => "";
                }
                """;
 
            var comp = CreateCompilation(source, options: TestOptions.DebugDll.WithNullableContextOptions(NullableContextOptions.Enable));
            comp.VerifyEmitDiagnostics(
                // (4,27): warning CS9256: Partial property declarations 'string? C.P1' and 'string C.P1' have signature differences.
                //     public partial string P1 { get => ""; set { } }
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "P1").WithArguments("string? C.P1", "string C.P1").WithLocation(4, 27),
                // (7,28): warning CS9256: Partial property declarations 'string C.P2' and 'string? C.P2' have signature differences.
                //     public partial string? P2 { get => ""; set { } }
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "P2").WithArguments("string C.P2", "string? C.P2").WithLocation(7, 28),
                // (10,27): warning CS8826: Partial method declarations 'string? C.M1()' and 'string C.M1()' have signature differences.
                //     public partial string M1() => "";
                Diagnostic(ErrorCode.WRN_PartialMethodTypeDifference, "M1").WithArguments("string? C.M1()", "string C.M1()").WithLocation(10, 27),
                // (13,28): warning CS8819: Nullability of reference types in return type doesn't match partial definition.
                //     public partial string? M2() => "";
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnPartial, "M2").WithLocation(13, 28));
 
            comp = CreateCompilation(source, options: TestOptions.DebugDll.WithNullableContextOptions(NullableContextOptions.Annotations));
            comp.VerifyEmitDiagnostics(
                // (4,27): warning CS9256: Partial property declarations 'string? C.P1' and 'string C.P1' have signature differences.
                //     public partial string P1 { get => ""; set { } }
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "P1").WithArguments("string? C.P1", "string C.P1").WithLocation(4, 27),
                // (7,28): warning CS9256: Partial property declarations 'string C.P2' and 'string? C.P2' have signature differences.
                //     public partial string? P2 { get => ""; set { } }
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "P2").WithArguments("string C.P2", "string? C.P2").WithLocation(7, 28),
                // (10,27): warning CS8826: Partial method declarations 'string? C.M1()' and 'string C.M1()' have signature differences.
                //     public partial string M1() => "";
                Diagnostic(ErrorCode.WRN_PartialMethodTypeDifference, "M1").WithArguments("string? C.M1()", "string C.M1()").WithLocation(10, 27));
        }
 
        [Fact]
        public void NullableDifference_Oblivious()
        {
            var source = """
                #nullable enable
                partial class C<T>
                {
                    public partial T P1 { get; set; }
                    public partial T? P2 { get; set; }
                #nullable disable
                    public partial T P3 { get; set; }
                }
 
                #nullable disable
                partial class C<T>
                {
                    public partial T P1 { get => default!; set { } }
                    public partial T P2 { get => default!; set { } }
                #nullable enable
                    public partial T P3 { get => default!; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
 
            var p1 = comp.GetMember<SourcePropertySymbol>("C.P1");
            Assert.True(p1.IsPartialDefinition);
            Assert.Equal(NullableAnnotation.NotAnnotated, p1.TypeWithAnnotations.NullableAnnotation);
 
            var p2 = comp.GetMember<SourcePropertySymbol>("C.P2");
            Assert.True(p2.IsPartialDefinition);
            Assert.Equal(NullableAnnotation.Annotated, p2.TypeWithAnnotations.NullableAnnotation);
 
            var p3 = comp.GetMember<SourcePropertySymbol>("C.P3");
            Assert.True(p3.IsPartialDefinition);
            Assert.Equal(NullableAnnotation.Oblivious, p3.TypeWithAnnotations.NullableAnnotation);
        }
 
        [Fact]
        public void NullableDifference_Analysis()
        {
            // The implementation part signature is used to analyze the implementation part bodies.
            // The definition part signature is used to analyze use sites.
            // This is consistent with methods.
            var source = """
                #nullable enable
                partial class C
                {
                    public partial string this[string? x] { get; set; }
                    public partial string? this[string x] // 1
                    {
                        get => x.ToString();
                        set => x.ToString();
                    }
                    
                    public partial string? this[string x, bool ignored] { get; set; }
                    public partial string this[string? x, bool ignored] // 2
                    {
                        get => x.ToString(); // 3
                        set => x.ToString(); // 4
                    }
                
                    public partial string this[bool ignored] { get; }
                    public partial string? this[bool ignored] // 5
                    {
                        get => null;
                    }
                
                    public partial string? this[int ignored] { get; }
                    public partial string this[int ignored] // 6
                    {
                        get => null; // 7
                    }
 
                    void Usage()
                    {
                        this[x: null].ToString();
                        this[x: null, ignored: false].ToString(); // 8, 9
                    }
                }
                """;
 
            var verifier = CompileAndVerify(source, symbolValidator: verify, sourceSymbolValidator: verify);
            verifier.VerifyDiagnostics(
                // (5,28): warning CS9256: Partial property declarations 'string C.this[string? x]' and 'string? C.this[string x]' have signature differences.
                //     public partial string? this[string x] // 1
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "this").WithArguments("string C.this[string? x]", "string? C.this[string x]").WithLocation(5, 28),
                // (12,27): warning CS9256: Partial property declarations 'string? C.this[string x, bool ignored]' and 'string C.this[string? x, bool ignored]' have signature differences.
                //     public partial string this[string? x, bool ignored] // 2
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "this").WithArguments("string? C.this[string x, bool ignored]", "string C.this[string? x, bool ignored]").WithLocation(12, 27),
                // (14,16): warning CS8602: Dereference of a possibly null reference.
                //         get => x.ToString(); // 3
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(14, 16),
                // (15,16): warning CS8602: Dereference of a possibly null reference.
                //         set => x.ToString(); // 4
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(15, 16),
                // (19,28): warning CS9256: Partial property declarations 'string C.this[bool ignored]' and 'string? C.this[bool ignored]' have signature differences.
                //     public partial string? this[bool ignored] // 5
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "this").WithArguments("string C.this[bool ignored]", "string? C.this[bool ignored]").WithLocation(19, 28),
                // (25,27): warning CS9256: Partial property declarations 'string? C.this[int ignored]' and 'string C.this[int ignored]' have signature differences.
                //     public partial string this[int ignored] // 6
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "this").WithArguments("string? C.this[int ignored]", "string C.this[int ignored]").WithLocation(25, 27),
                // (27,16): warning CS8603: Possible null reference return.
                //         get => null; // 7
                Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(27, 16),
                // (33,9): warning CS8602: Dereference of a possibly null reference.
                //         this[x: null, ignored: false].ToString(); // 8, 9
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "this[x: null, ignored: false]").WithLocation(33, 9),
                // (33,17): warning CS8625: Cannot convert null literal to non-nullable reference type.
                //         this[x: null, ignored: false].ToString(); // 8, 9
                Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(33, 17));
 
            void verify(ModuleSymbol module)
            {
                var indexers = module.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers;
                Assert.Equal(4, indexers.Length);
                AssertEx.Equal("System.String C.this[System.String? x] { get; set; }", indexers[0].ToTestDisplayString());
                AssertEx.Equal("System.String? C.this[System.String x, System.Boolean ignored] { get; set; }", indexers[1].ToTestDisplayString());
                AssertEx.Equal("System.String C.this[System.Boolean ignored] { get; }", indexers[2].ToTestDisplayString());
                AssertEx.Equal("System.String? C.this[System.Int32 ignored] { get; }", indexers[3].ToTestDisplayString());
            }
        }
 
        [Fact]
        public void TypeDifference_03()
        {
            // tuple element name difference
            // this is an error for consistency with methods
            var source = """
                using System.Collections.Generic;
 
                partial class C
                {
                    partial (int a, int b) P1 { get; set; }
                    partial (int a, int x) P1 { get => default; set { } }
 
                    partial (int a, int b) P2 { get; set; }
                    partial (int x, int y) P2 { get => default; set { } }
 
                    partial List<(int a, int b)> P3 { get; set; }
                    partial List<(int x, int y)> P3 { get => null!; set { } }
 
                    partial List<(int, int)> P4 { get; set; }
                    partial List<(int x, int y)> P4 { get => null!; set { } }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (6,28): error CS8142: Both partial member declarations, 'C.P1' and 'C.P1', must use the same tuple element names.
                //     partial (int a, int x) P1 { get => default; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberInconsistentTupleNames, "P1").WithArguments("C.P1", "C.P1").WithLocation(6, 28),
                // (9,28): error CS8142: Both partial member declarations, 'C.P2' and 'C.P2', must use the same tuple element names.
                //     partial (int x, int y) P2 { get => default; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberInconsistentTupleNames, "P2").WithArguments("C.P2", "C.P2").WithLocation(9, 28),
                // (12,34): error CS8142: Both partial member declarations, 'C.P3' and 'C.P3', must use the same tuple element names.
                //     partial List<(int x, int y)> P3 { get => null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberInconsistentTupleNames, "P3").WithArguments("C.P3", "C.P3").WithLocation(12, 34),
                // (15,34): error CS8142: Both partial member declarations, 'C.P4' and 'C.P4', must use the same tuple element names.
                //     partial List<(int x, int y)> P4 { get => null!; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberInconsistentTupleNames, "P4").WithArguments("C.P4", "C.P4").WithLocation(15, 34));
        }
 
        [Fact]
        public void Semantics_RefKind()
        {
            var source = """
                using System;
 
                var c = new C();
                ref int i = ref c.P1;
                c.P1++;
                Console.Write(i);
                Console.Write(c.P2);
 
                partial class C
                {
                    public partial ref int P1 { get; }
                    public partial ref readonly int P2 { get; }
 
                    private int _p;
                    public partial ref int P1 => ref _p;
                    public partial ref readonly int P2 { get => ref _p; }
                }
                """;
 
            var verifier = CompileAndVerify(source, expectedOutput: "11");
            verifier.VerifyDiagnostics();
            var comp = (CSharpCompilation)verifier.Compilation;
 
            var members = comp.GetMember<NamedTypeSymbol>("C").GetMembers().SelectAsArray(m => m.ToTestDisplayString());
            AssertEx.Equal([
                "ref System.Int32 C.P1 { get; }",
                "ref System.Int32 C.P1.get",
                "ref readonly modreq(System.Runtime.InteropServices.InAttribute) System.Int32 C.P2 { get; }",
                "ref readonly modreq(System.Runtime.InteropServices.InAttribute) System.Int32 C.P2.get",
                "System.Int32 C._p",
                "C..ctor()"
                ], members);
        }
 
        [Fact]
        public void RefKindDifference_01()
        {
            var source = """
                partial class C
                {
                    partial int P1 { get; }
                    partial ref int P1 { get => throw null!; }
 
                    partial int P2 { get; }
                    partial ref readonly int P2 { get => throw null!; }
 
                    partial ref int P3 { get; }
                    partial int P3 { get => throw null!; }
 
                    partial ref readonly int P4 { get; }
                    partial int P4 { get => throw null!; }
 
                    partial ref readonly int P5 { get; }
                    partial ref int P5 { get => throw null!; }
 
                    partial ref int P6 { get; }
                    partial ref readonly int P6 { get => throw null!; }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,21): error CS8818: Partial member declarations must have matching ref return values.
                //     partial ref int P1 { get => throw null!; }
                Diagnostic(ErrorCode.ERR_PartialMemberRefReturnDifference, "P1").WithLocation(4, 21),
                // (7,30): error CS8818: Partial member declarations must have matching ref return values.
                //     partial ref readonly int P2 { get => throw null!; }
                Diagnostic(ErrorCode.ERR_PartialMemberRefReturnDifference, "P2").WithLocation(7, 30),
                // (10,17): error CS8818: Partial member declarations must have matching ref return values.
                //     partial int P3 { get => throw null!; }
                Diagnostic(ErrorCode.ERR_PartialMemberRefReturnDifference, "P3").WithLocation(10, 17),
                // (13,17): error CS8818: Partial member declarations must have matching ref return values.
                //     partial int P4 { get => throw null!; }
                Diagnostic(ErrorCode.ERR_PartialMemberRefReturnDifference, "P4").WithLocation(13, 17),
                // (16,21): error CS8818: Partial member declarations must have matching ref return values.
                //     partial ref int P5 { get => throw null!; }
                Diagnostic(ErrorCode.ERR_PartialMemberRefReturnDifference, "P5").WithLocation(16, 21),
                // (19,30): error CS8818: Partial member declarations must have matching ref return values.
                //     partial ref readonly int P6 { get => throw null!; }
                Diagnostic(ErrorCode.ERR_PartialMemberRefReturnDifference, "P6").WithLocation(19, 30));
        }
 
        [Fact]
        public void AllTypeDifferences()
        {
            // Verify which diagnostics are reported when multiple kinds of type differences are present
            var source = """
                #nullable enable
 
                partial class C
                {
                    public partial ref (int x, string? y) Prop { get; }
                    public partial ref readonly (long x, string y) Prop => throw null!;
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (6,52): error CS9255: Both partial property declarations must have the same type.
                //     public partial ref readonly (long x, string y) Prop => throw null!;
                Diagnostic(ErrorCode.ERR_PartialPropertyTypeDifference, "Prop").WithLocation(6, 52),
                // (6,52): error CS8818: Partial member declarations must have matching ref return values.
                //     public partial ref readonly (long x, string y) Prop => throw null!;
                Diagnostic(ErrorCode.ERR_PartialMemberRefReturnDifference, "Prop").WithLocation(6, 52));
        }
 
        [Fact]
        public void Semantics_Static()
        {
            var source = """
                using System;
 
                C.P++;
                Console.Write(C.P);
 
                partial class C
                {
                    public static partial int P { get; set; }
 
                    public static partial int P { get => _p; set => _p = value; }
                    private static int _p;
                }
                """;
 
            var verifier = CompileAndVerify(source, expectedOutput: "1");
            verifier.VerifyDiagnostics();
            var comp = (CSharpCompilation)verifier.Compilation;
 
            var members = comp.GetMember<NamedTypeSymbol>("C").GetMembers().SelectAsArray(m => m.ToTestDisplayString());
            AssertEx.Equal([
                "System.Int32 C.P { get; set; }",
                "System.Int32 C.P.get",
                "void C.P.set",
                "System.Int32 C._p",
                "C..ctor()"
                ], members);
        }
 
        [Fact]
        public void StaticDifference()
        {
            var source = """
                partial class C
                {
                    public static partial int P1 { get; set; }
                    public partial int P1 { get => 1; set { } }
 
                    public partial int P2 { get; set; }
                    public static partial int P2 { get => 1; set { } }
                }
                """;
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,24): error CS0763: Both partial member declarations must be static or neither may be static
                //     public partial int P1 { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberStaticDifference, "P1").WithLocation(4, 24),
                // (7,31): error CS0763: Both partial member declarations must be static or neither may be static
                //     public static partial int P2 { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberStaticDifference, "P2").WithLocation(7, 31));
        }
 
        [Fact]
        public void Semantics_Unsafe()
        {
            var source = """
                using System;
 
                class Program
                {
                    static unsafe void Main()
                    {
                        int i = 1;
                        S s = new S() { P = &i };
                        Console.Write(*s.P);
                    }
                }
 
                partial struct S
                {
                    public unsafe partial int* P { get; set; }
 
                    public unsafe partial int* P { get => _p; set => _p = value; }
                    private unsafe int* _p;
                }
                """;
 
            var verifier = CompileAndVerify(source, options: TestOptions.UnsafeReleaseExe, verify: Verification.Fails, expectedOutput: "1");
            verifier.VerifyDiagnostics();
            var comp = (CSharpCompilation)verifier.Compilation;
 
            var members = comp.GetMember<NamedTypeSymbol>("S").GetMembers().SelectAsArray(m => m.ToTestDisplayString());
            AssertEx.Equal([
                "System.Int32* S.P { get; set; }",
                "System.Int32* S.P.get",
                "void S.P.set",
                "System.Int32* S._p",
                "S..ctor()"
                ], members);
        }
 
        [Fact]
        public void UnsafeDifference_01()
        {
            // 'unsafe' modifiers are required to match across property declarations.
            // Therefore an error is reported on implementation of 'P2' even though both parts are "effectively unsafe".
            var source = """
                partial class C
                {
                    public partial int P1 { get; set; }
                    public unsafe partial int P2 { get; set; }
                }
 
                unsafe partial class C
                {
                    public unsafe partial int P1 { get => 1; set { } }
                    public partial int P2 { get => 1; set { } }
                }
                """;
            var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseDll);
            comp.VerifyEmitDiagnostics(
                // (9,31): error CS0764: Both partial member declarations must be unsafe or neither may be unsafe
                //     public unsafe partial int P1 { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberUnsafeDifference, "P1").WithLocation(9, 31),
                // (10,24): error CS0764: Both partial member declarations must be unsafe or neither may be unsafe
                //     public partial int P2 { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberUnsafeDifference, "P2").WithLocation(10, 24));
 
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,15): error CS0227: Unsafe code may only appear if compiling with /unsafe
                // partial class C
                Diagnostic(ErrorCode.ERR_IllegalUnsafe, "C").WithLocation(1, 15),
                // (4,31): error CS0227: Unsafe code may only appear if compiling with /unsafe
                //     public unsafe partial int P2 { get; set; }
                Diagnostic(ErrorCode.ERR_IllegalUnsafe, "P2").WithLocation(4, 31),
                // (9,31): error CS0227: Unsafe code may only appear if compiling with /unsafe
                //     public unsafe partial int P1 { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_IllegalUnsafe, "P1").WithLocation(9, 31));
        }
 
        [Fact]
        public void UnsafeDifference_02()
        {
            // A difference in unsafe context only matters when unsafe types are used in the signature
            var source = """
                unsafe partial class C
                {
                    public partial int* P1 { get; set; }
                    public partial int P2 { get; set; }
                }
 
                partial class C
                {
                    public partial int* P1 { get => null; set { } }
                    public partial int P2 { get => 1; set { } }
                }
                """;
            var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseDll);
            comp.VerifyEmitDiagnostics(
                // (9,20): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
                //     public partial int* P1 { get => null; set { } }
                Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(9, 20));
        }
 
        [Fact]
        public void Semantics_ExtendedModifier()
        {
            var source = """
                using System;
 
                C c = new C();
                Console.Write(c.P);
 
                c = new D1();
                Console.Write(c.P);
 
                c = new D2();
                Console.Write(c.P);
 
                c = new D3();
                Console.Write(c.P);
                Console.Write(new D3().P);
 
                partial class C
                {
                    public virtual partial int P { get; }
                    public virtual partial int P => 0;
                }
 
                partial class D1 : C
                {
                    public override partial int P { get; }
                    public override partial int P => 1;
                }
 
                partial class D2 : C
                {
                    public sealed override partial int P { get; }
                    public sealed override partial int P => 2;
                }
 
                partial class D3 : C
                {
                    public new partial int P { get; }
                    public new partial int P => 3;
                }
                """;
 
            var verifier = CompileAndVerify(source, expectedOutput: "01203");
            verifier.VerifyDiagnostics();
        }
 
        [Fact]
        public void ExtendedDifference_01()
        {
            var source = """
                partial class C
                {
                    public virtual partial int P1 { get; }
                    public partial int P1 => 1; // 1
 
                    public partial int P2 { get; }
                    public virtual partial int P2 => 1; // 2
                }
 
                partial class D1 : C
                {
                    public partial int P1 { get; } // 3
                    public override partial int P1 => 1; // 4
 
                    public override partial int P2 { get; } // 5
                    public partial int P2 => 1; // 6
                }
 
                partial class D2 : C
                {
                    public partial int P1 { get; } // 7 
                    public sealed override partial int P1 => 1; // 8
 
                    public sealed override partial int P2 { get; } // 9
                    public partial int P2 => 1; // 10
                }
 
                partial class D3 : C
                {
                    public sealed partial int P1 { get; } // 11, 12
                    public override partial int P1 => 1; // 13
 
                    public override partial int P2 { get; } // 14
                    public sealed partial int P2 => 1; // 15
                }
 
                partial class D4 : C
                {
                    public partial int P1 { get; } // 16
                    public new partial int P1 => 1; // 17
 
                    public new partial int P2 { get; }
                    public partial int P2 => 1; // 18
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,24): error CS8800: Both partial member declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers.
                //     public partial int P1 => 1; // 1
                Diagnostic(ErrorCode.ERR_PartialMemberExtendedModDifference, "P1").WithLocation(4, 24),
                // (7,32): error CS8800: Both partial member declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers.
                //     public virtual partial int P2 => 1; // 2
                Diagnostic(ErrorCode.ERR_PartialMemberExtendedModDifference, "P2").WithLocation(7, 32),
                // (12,24): warning CS0114: 'D1.P1' hides inherited member 'C.P1'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public partial int P1 { get; } // 3
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "P1").WithArguments("D1.P1", "C.P1").WithLocation(12, 24),
                // (13,33): error CS8800: Both partial member declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers.
                //     public override partial int P1 => 1; // 4
                Diagnostic(ErrorCode.ERR_PartialMemberExtendedModDifference, "P1").WithLocation(13, 33),
                // (15,33): error CS0506: 'D1.P2': cannot override inherited member 'C.P2' because it is not marked virtual, abstract, or override
                //     public override partial int P2 { get; } // 5
                Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "P2").WithArguments("D1.P2", "C.P2").WithLocation(15, 33),
                // (16,24): error CS8800: Both partial member declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers.
                //     public partial int P2 => 1; // 6
                Diagnostic(ErrorCode.ERR_PartialMemberExtendedModDifference, "P2").WithLocation(16, 24),
                // (21,24): warning CS0114: 'D2.P1' hides inherited member 'C.P1'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public partial int P1 { get; } // 7
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "P1").WithArguments("D2.P1", "C.P1").WithLocation(21, 24),
                // (22,40): error CS8800: Both partial member declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers.
                //     public sealed override partial int P1 => 1; // 8
                Diagnostic(ErrorCode.ERR_PartialMemberExtendedModDifference, "P1").WithLocation(22, 40),
                // (24,40): error CS0506: 'D2.P2': cannot override inherited member 'C.P2' because it is not marked virtual, abstract, or override
                //     public sealed override partial int P2 { get; } // 9
                Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "P2").WithArguments("D2.P2", "C.P2").WithLocation(24, 40),
                // (25,24): error CS8800: Both partial member declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers.
                //     public partial int P2 => 1; // 10
                Diagnostic(ErrorCode.ERR_PartialMemberExtendedModDifference, "P2").WithLocation(25, 24),
                // (30,31): warning CS0114: 'D3.P1' hides inherited member 'C.P1'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public sealed partial int P1 { get; } // 11, 12
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "P1").WithArguments("D3.P1", "C.P1").WithLocation(30, 31),
                // (30,31): error CS0238: 'D3.P1' cannot be sealed because it is not an override
                //     public sealed partial int P1 { get; } // 11, 12
                Diagnostic(ErrorCode.ERR_SealedNonOverride, "P1").WithArguments("D3.P1").WithLocation(30, 31),
                // (31,33): error CS8800: Both partial member declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers.
                //     public override partial int P1 => 1; // 13
                Diagnostic(ErrorCode.ERR_PartialMemberExtendedModDifference, "P1").WithLocation(31, 33),
                // (33,33): error CS0506: 'D3.P2': cannot override inherited member 'C.P2' because it is not marked virtual, abstract, or override
                //     public override partial int P2 { get; } // 14
                Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "P2").WithArguments("D3.P2", "C.P2").WithLocation(33, 33),
                // (34,31): error CS8800: Both partial member declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers.
                //     public sealed partial int P2 => 1; // 15
                Diagnostic(ErrorCode.ERR_PartialMemberExtendedModDifference, "P2").WithLocation(34, 31),
                // (39,24): warning CS0114: 'D4.P1' hides inherited member 'C.P1'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public partial int P1 { get; } // 16
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "P1").WithArguments("D4.P1", "C.P1").WithLocation(39, 24),
                // (40,28): error CS8800: Both partial member declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers.
                //     public new partial int P1 => 1; // 17
                Diagnostic(ErrorCode.ERR_PartialMemberExtendedModDifference, "P1").WithLocation(40, 28),
                // (43,24): error CS8800: Both partial member declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers.
                //     public partial int P2 => 1; // 18
                Diagnostic(ErrorCode.ERR_PartialMemberExtendedModDifference, "P2").WithLocation(43, 24));
        }
 
        [Fact]
        public void Abstract()
        {
            // 'abstract' is not permitted on partial declarations
            var source = """
                abstract partial class C
                {
                    public abstract partial int P1 { get; set; }
 
                    public abstract partial int P2 { get => ""; set { } }
 
                    public abstract partial int P3 { get; set; }
                    public abstract partial int P3 { get => ""; set { } }
 
                    public abstract partial int P4 { get; set; }
                    public partial int P4 { get => ""; set { } }
 
                    public partial int P5 { get; set; }
                    public abstract partial int P5 { get => ""; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,33): error CS9248: Partial property 'C.P1' must have an implementation part.
                //     public abstract partial int P1 { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "P1").WithArguments("C.P1").WithLocation(3, 33),
                // (3,33): error CS0750: A partial member cannot have the 'abstract' modifier
                //     public abstract partial int P1 { get; set; }
                Diagnostic(ErrorCode.ERR_PartialMemberCannotBeAbstract, "P1").WithLocation(3, 33),
                // (5,33): error CS9249: Partial property 'C.P2' must have a definition part.
                //     public abstract partial int P2 { get => ""; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "P2").WithArguments("C.P2").WithLocation(5, 33),
                // (5,33): error CS0750: A partial member cannot have the 'abstract' modifier
                //     public abstract partial int P2 { get => ""; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberCannotBeAbstract, "P2").WithLocation(5, 33),
                // (5,38): error CS0500: 'C.P2.get' cannot declare a body because it is marked abstract
                //     public abstract partial int P2 { get => ""; set { } }
                Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("C.P2.get").WithLocation(5, 38),
                // (5,49): error CS0500: 'C.P2.set' cannot declare a body because it is marked abstract
                //     public abstract partial int P2 { get => ""; set { } }
                Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("C.P2.set").WithLocation(5, 49),
                // (7,33): error CS0750: A partial member cannot have the 'abstract' modifier
                //     public abstract partial int P3 { get; set; }
                Diagnostic(ErrorCode.ERR_PartialMemberCannotBeAbstract, "P3").WithLocation(7, 33),
                // (8,38): error CS0500: 'C.P3.get' cannot declare a body because it is marked abstract
                //     public abstract partial int P3 { get => ""; set { } }
                Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("C.P3.get").WithLocation(8, 38),
                // (8,49): error CS0500: 'C.P3.set' cannot declare a body because it is marked abstract
                //     public abstract partial int P3 { get => ""; set { } }
                Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("C.P3.set").WithLocation(8, 49),
                // (10,33): error CS0750: A partial member cannot have the 'abstract' modifier
                //     public abstract partial int P4 { get; set; }
                Diagnostic(ErrorCode.ERR_PartialMemberCannotBeAbstract, "P4").WithLocation(10, 33),
                // (11,36): error CS0029: Cannot implicitly convert type 'string' to 'int'
                //     public partial int P4 { get => ""; set { } }
                Diagnostic(ErrorCode.ERR_NoImplicitConv, @"""""").WithArguments("string", "int").WithLocation(11, 36),
                // (14,38): error CS0500: 'C.P5.get' cannot declare a body because it is marked abstract
                //     public abstract partial int P5 { get => ""; set { } }
                Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("C.P5.get").WithLocation(14, 38),
                // (14,49): error CS0500: 'C.P5.set' cannot declare a body because it is marked abstract
                //     public abstract partial int P5 { get => ""; set { } }
                Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("C.P5.set").WithLocation(14, 49));
        }
 
        [Fact]
        public void Semantics_Required()
        {
            var source = """
                using System;
 
                partial class C
                {
                    public required partial string P1 { get; set; }
                    public required partial string P1 { get => ""; set { Console.Write(value); } }
 
                    static void Main()
                    {
                        _ = new C() { P1 = "A" };
                    }
                }
                """;
 
            var verifier = CompileAndVerify([source, RequiredMemberAttribute, SetsRequiredMembersAttribute, CompilerFeatureRequiredAttribute], expectedOutput: "A");
            verifier.VerifyDiagnostics();
            verifier.VerifyIL("C.Main", """
                {
                  // Code size       16 (0x10)
                  .maxstack  2
                  IL_0000:  newobj     "C..ctor()"
                  IL_0005:  ldstr      "A"
                  IL_000a:  callvirt   "void C.P1.set"
                  IL_000f:  ret
                }
                """);
        }
 
        [Fact]
        public void Required_CreationSiteError()
        {
            var source = """
                partial class C
                {
                    public required partial string P1 { get; set; }
                    public required partial string P1 { get => ""; set { } }
 
                    static void Main()
                    {
                        _ = new C();
                    }
                }
                """;
 
            var comp = CreateCompilation([source, RequiredMemberAttribute, SetsRequiredMembersAttribute, CompilerFeatureRequiredAttribute]);
            comp.VerifyEmitDiagnostics(
                // (8,17): error CS9035: Required member 'C.P1' must be set in the object initializer or attribute constructor.
                //         _ = new C();
                Diagnostic(ErrorCode.ERR_RequiredMemberMustBeSet, "C").WithArguments("C.P1").WithLocation(8, 17));
        }
 
        [Fact]
        public void Required_Difference()
        {
            var source = """
                partial class C
                {
                    public required partial string P1 { get; set; }
                    public partial string P1 { get => ""; set { } }
 
                    public partial string P2 { get; set; }
                    public required partial string P2 { get => ""; set { } }
 
                    static void Main()
                    {
                        _ = new C();
                    }
                }
                """;
 
            var comp = CreateCompilation([source, RequiredMemberAttribute, SetsRequiredMembersAttribute, CompilerFeatureRequiredAttribute]);
            comp.VerifyEmitDiagnostics(
                // (4,27): error CS9257: Both partial property declarations must be required or neither may be required
                //     public partial string P1 { get => ""; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyRequiredDifference, "P1").WithLocation(4, 27),
                // (7,36): error CS9257: Both partial property declarations must be required or neither may be required
                //     public required partial string P2 { get => ""; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyRequiredDifference, "P2").WithLocation(7, 36),
                // (11,17): error CS9035: Required member 'C.P1' must be set in the object initializer or attribute constructor.
                //         _ = new C();
                Diagnostic(ErrorCode.ERR_RequiredMemberMustBeSet, "C").WithArguments("C.P1").WithLocation(11, 17));
        }
 
        [Fact]
        public void AliasDifference()
        {
            var source = """
                namespace NS;
 
                using MyInt = System.Int32;
                using MyInt2 = System.Int32;
 
                partial class C
                {
                    public partial int P1 { get; set; }
                    public partial MyInt P1 { get => 1; set { } }
 
                    public partial MyInt P2 { get; set; }
                    public partial MyInt2 P2 { get => 2; set { } }
 
                    public partial string P3 { get; set; }
                    public partial MyInt P3 { get => 3; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (15,26): error CS9255: Both partial property declarations must have the same type.
                //     public partial MyInt P3 { get => 3; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyTypeDifference, "P3").WithLocation(15, 26));
        }
 
        [Fact]
        public void ExplicitImplementation()
        {
            var source = """
                interface I
                {
                    public int P { get; set; }
                }
 
                partial class C1 : I
                {
                    partial int I.P { get; set; }
                    partial int I.P { get => 1; set { } }
                }
 
                partial class C2 : I
                {
                    partial int I.P { get; set; }
                }
 
                partial class C3 : I
                {
                    partial int I.P { get => 1; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (8,19): error CS0754: A partial member may not explicitly implement an interface member
                //     partial int I.P { get; set; }
                Diagnostic(ErrorCode.ERR_PartialMemberNotExplicit, "P").WithLocation(8, 19),
                // (14,19): error CS9248: Partial property 'C2.I.P' must have an implementation part.
                //     partial int I.P { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "P").WithArguments("C2.I.P").WithLocation(14, 19),
                // (14,19): error CS0754: A partial member may not explicitly implement an interface member
                //     partial int I.P { get; set; }
                Diagnostic(ErrorCode.ERR_PartialMemberNotExplicit, "P").WithLocation(14, 19),
                // (19,19): error CS9249: Partial property 'C3.I.P' must have a definition part.
                //     partial int I.P { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "P").WithArguments("C3.I.P").WithLocation(19, 19),
                // (19,19): error CS0754: A partial member may not explicitly implement an interface member
                //     partial int I.P { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberNotExplicit, "P").WithLocation(19, 19));
        }
 
        [Fact]
        public void NotInPartialType()
        {
            var source = """
                class C
                {
                    partial int P1 { get; set; }
                    partial int P1 { get => 1; set { } }
 
                    partial int P2 { get; set; }
 
                    partial int P3 { get => 1; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,17): error CS0751: A partial member must be declared within a partial type
                //     partial int P1 { get; set; }
                Diagnostic(ErrorCode.ERR_PartialMemberOnlyInPartialClass, "P1").WithLocation(3, 17),
                // (6,17): error CS9248: Partial property 'C.P2' must have an implementation part.
                //     partial int P2 { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "P2").WithArguments("C.P2").WithLocation(6, 17),
                // (6,17): error CS0751: A partial member must be declared within a partial type
                //     partial int P2 { get; set; }
                Diagnostic(ErrorCode.ERR_PartialMemberOnlyInPartialClass, "P2").WithLocation(6, 17),
                // (8,17): error CS9249: Partial property 'C.P3' must have a definition part.
                //     partial int P3 { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "P3").WithArguments("C.P3").WithLocation(8, 17),
                // (8,17): error CS0751: A partial member must be declared within a partial type
                //     partial int P3 { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberOnlyInPartialClass, "P3").WithLocation(8, 17));
        }
 
        [Fact]
        public void Semantics_Indexers_01()
        {
            var source = """
                using System;
 
                partial class C
                {
                    public partial int this[int i] { get; set; }
                    public partial int this[int i]
                    {
                        get => i;
                        set
                        {
                            Console.Write(i);
                            Console.Write(value);
                        }
                    }
 
                    static void Main()
                    {
                        var c = new C();
                        Console.Write(c[1]);
                        c[2] = 3;
                    }
                }
                """;
            var verifier = CompileAndVerify(source, expectedOutput: "123");
            verifier.VerifyDiagnostics();
        }
 
        [Theory]
        [InlineData("ref")]
        [InlineData("out")]
        public void RefKindDifference_IndexerParameter_01(string refKind)
        {
            // byvalue is distinct from byreference for signature matching
            var source = $$"""
                partial class C1
                {
                    public partial int this[int i] { get; set; }
                    public partial int this[{{refKind}} int i] { get => i = 0; set => i = 0; }
                }
 
                partial class C2
                {
                    public partial int this[{{refKind}} int i] { get; set; }
                    public partial int this[int i] { get => i; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,24): error CS9248: Partial property 'C1.this[int]' must have an implementation part.
                //     public partial int this[int i] { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments("C1.this[int]").WithLocation(3, 24),
                // (4,24): error CS9249: Partial property 'C1.this[ref int]' must have a definition part.
                //     public partial int this[ref int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "this").WithArguments($"C1.this[{refKind} int]").WithLocation(4, 24),
                // (4,29): error CS0631: ref and out are not valid in this context
                //     public partial int this[ref int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_IllegalRefParam, refKind).WithLocation(4, 29),
                // (9,24): error CS9248: Partial property 'C2.this[ref int]' must have an implementation part.
                //     public partial int this[ref int i] { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments($"C2.this[{refKind} int]").WithLocation(9, 24),
                // (9,29): error CS0631: ref and out are not valid in this context
                //     public partial int this[ref int i] { get; set; }
                Diagnostic(ErrorCode.ERR_IllegalRefParam, refKind).WithLocation(9, 29),
                // (10,24): error CS9249: Partial property 'C2.this[int]' must have a definition part.
                //     public partial int this[int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "this").WithArguments("C2.this[int]").WithLocation(10, 24));
        }
 
        [Theory]
        [InlineData("in")]
        [InlineData("ref readonly")]
        public void RefKindDifference_IndexerParameter_02(string refKind)
        {
            var source = $$"""
                partial class C1
                {
                    public partial int this[int i] { get; set; }
                    public partial int this[{{refKind}} int i] { get => i; set { } }
                }
 
                partial class C2
                {
                    public partial int this[{{refKind}} int i] { get; set; }
                    public partial int this[int i] { get => i; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,24): error CS9248: Partial property 'C1.this[int]' must have an implementation part.
                //     public partial int this[int i] { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments("C1.this[int]").WithLocation(3, 24),
                // (4,24): error CS9249: Partial property 'C1.this[in int]' must have a definition part.
                //     public partial int this[in int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "this").WithArguments($"C1.this[{refKind} int]").WithLocation(4, 24),
                // (9,24): error CS9248: Partial property 'C2.this[in int]' must have an implementation part.
                //     public partial int this[in int i] { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments($"C2.this[{refKind} int]").WithLocation(9, 24),
                // (10,24): error CS9249: Partial property 'C2.this[int]' must have a definition part.
                //     public partial int this[int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "this").WithArguments("C2.this[int]").WithLocation(10, 24));
        }
 
        [Fact]
        public void RefKindDifference_IndexerParameter_03()
        {
            var source = """
                partial class C1
                {
                    public partial int this[ref int i] { get; set; }
                    public partial int this[out int i] { get => i = 0; set => i = 0; }
                }
 
                partial class C2
                {
                    public partial int this[out int i] { get; set; }
                    public partial int this[ref int i] { get => i; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,24): error CS9248: Partial property 'C1.this[ref int]' must have an implementation part.
                //     public partial int this[ref int i] { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments("C1.this[ref int]").WithLocation(3, 24),
                // (3,29): error CS0631: ref and out are not valid in this context
                //     public partial int this[ref int i] { get; set; }
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "ref").WithLocation(3, 29),
                // (4,24): error CS9249: Partial property 'C1.this[out int]' must have a definition part.
                //     public partial int this[out int i] { get => i = 0; set => i = 0; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "this").WithArguments("C1.this[out int]").WithLocation(4, 24),
                // (4,24): error CS0111: Type 'C1' already defines a member called 'this' with the same parameter types
                //     public partial int this[out int i] { get => i = 0; set => i = 0; }
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "C1").WithLocation(4, 24),
                // (4,29): error CS0631: ref and out are not valid in this context
                //     public partial int this[out int i] { get => i = 0; set => i = 0; }
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "out").WithLocation(4, 29),
                // (9,24): error CS9248: Partial property 'C2.this[out int]' must have an implementation part.
                //     public partial int this[out int i] { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments("C2.this[out int]").WithLocation(9, 24),
                // (9,29): error CS0631: ref and out are not valid in this context
                //     public partial int this[out int i] { get; set; }
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "out").WithLocation(9, 29),
                // (10,24): error CS9249: Partial property 'C2.this[ref int]' must have a definition part.
                //     public partial int this[ref int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "this").WithArguments("C2.this[ref int]").WithLocation(10, 24),
                // (10,24): error CS0111: Type 'C2' already defines a member called 'this' with the same parameter types
                //     public partial int this[ref int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "C2").WithLocation(10, 24),
                // (10,29): error CS0631: ref and out are not valid in this context
                //     public partial int this[ref int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "ref").WithLocation(10, 29));
        }
 
        [Fact]
        public void RefKindDifference_IndexerParameter_04()
        {
            // note: this non-merging behavior in presence of ref kind differences is consistent with partial methods
            var source = """
                partial class C1
                {
                    public partial int this[in int i] { get; set; }
                    public partial int this[ref readonly int i] { get => i; set { } }
                }
 
                partial class C2
                {
                    public partial int this[ref readonly int i] { get; set; }
                    public partial int this[in int i] { get => i; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,24): error CS9248: Partial property 'C1.this[in int]' must have an implementation part.
                //     public partial int this[in int i] { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments("C1.this[in int]").WithLocation(3, 24),
                // (4,24): error CS9249: Partial property 'C1.this[ref readonly int]' must have a definition part.
                //     public partial int this[ref readonly int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "this").WithArguments("C1.this[ref readonly int]").WithLocation(4, 24),
                // (4,24): error CS0111: Type 'C1' already defines a member called 'this' with the same parameter types
                //     public partial int this[ref readonly int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "C1").WithLocation(4, 24),
                // (9,24): error CS9248: Partial property 'C2.this[ref readonly int]' must have an implementation part.
                //     public partial int this[ref readonly int i] { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments("C2.this[ref readonly int]").WithLocation(9, 24),
                // (10,24): error CS9249: Partial property 'C2.this[in int]' must have a definition part.
                //     public partial int this[in int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "this").WithArguments("C2.this[in int]").WithLocation(10, 24),
                // (10,24): error CS0111: Type 'C2' already defines a member called 'this' with the same parameter types
                //     public partial int this[in int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "C2").WithLocation(10, 24));
        }
 
        [Theory]
        [InlineData("in", "ref")]
        [InlineData("in", "out")]
        [InlineData("ref readonly", "ref")]
        [InlineData("ref readonly", "out")]
        public void RefKindDifference_IndexerParameter_05(string goodRefKind, string badRefKind)
        {
            // Show that errors occur when declarations differ between allowed vs. disallowed parameter ref kinds.
            var source = $$"""
                partial class C1
                {
                    public partial int this[{{goodRefKind}} int i] { get; set; }
                    public partial int this[{{badRefKind}} int i] { get => i = 0; set => i = 0; }
                }
 
                partial class C2
                {
                    public partial int this[{{badRefKind}} int i] { get; set; }
                    public partial int this[{{goodRefKind}} int i] { get => i; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,24): error CS9248: Partial property 'C1.this[in int]' must have an implementation part.
                //     public partial int this[in int i] { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments($"C1.this[{goodRefKind} int]").WithLocation(3, 24),
                // (4,24): error CS9249: Partial property 'C1.this[ref int]' must have a definition part.
                //     public partial int this[ref int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "this").WithArguments($"C1.this[{badRefKind} int]").WithLocation(4, 24),
                // (4,24): error CS0111: Type 'C1' already defines a member called 'this' with the same parameter types
                //     public partial int this[ref int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "C1").WithLocation(4, 24),
                // (4,29): error CS0631: ref and out are not valid in this context
                //     public partial int this[ref int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_IllegalRefParam, badRefKind).WithLocation(4, 29),
                // (9,24): error CS9248: Partial property 'C2.this[ref int]' must have an implementation part.
                //     public partial int this[ref int i] { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments($"C2.this[{badRefKind} int]").WithLocation(9, 24),
                // (9,29): error CS0631: ref and out are not valid in this context
                //     public partial int this[ref int i] { get; set; }
                Diagnostic(ErrorCode.ERR_IllegalRefParam, badRefKind).WithLocation(9, 29),
                // (10,24): error CS9249: Partial property 'C2.this[in int]' must have a definition part.
                //     public partial int this[in int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "this").WithArguments($"C2.this[{goodRefKind} int]").WithLocation(10, 24),
                // (10,24): error CS0111: Type 'C2' already defines a member called 'this' with the same parameter types
                //     public partial int this[in int i] { get => i; set { } }
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "C2").WithLocation(10, 24));
        }
 
        [Fact]
        public void TypeDifference_IndexerParameter()
        {
            var source = """
                partial class C
                {
                    public partial int this[int i] { get; set; }
                    public partial int this[string s] { get => 1; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,24): error CS9248: Partial property 'C.this[int]' must have an implementation part.
                //     public partial int this[int i] { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments("C.this[int]").WithLocation(3, 24),
                // (4,24): error CS9249: Partial property 'C.this[string]' must have a definition part.
                //     public partial int this[string s] { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "this").WithArguments("C.this[string]").WithLocation(4, 24));
        }
 
        [Fact]
        public void NullabilityDifference_IndexerParameter()
        {
            var source = $$"""
                #nullable enable
                partial class C
                {
                    public partial int this[string s] { get; set; }
                    public partial int this[string? s] { get => 1; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (5,24): warning CS9256: Partial property declarations 'int C.this[string s]' and 'int C.this[string? s]' have signature differences.
                //     public partial int this[string? s] { get => 1; set { } }
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "this").WithArguments("int C.this[string s]", "int C.this[string? s]").WithLocation(5, 24));
        }
 
        [Fact]
        public void DynamicDifference_IndexerParameter()
        {
            var source = """
                #nullable enable
                partial class C
                {
                    public partial int this[dynamic[] s] { get; set; }
                    public partial int this[object[] s] { get => 1; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (5,24): warning CS9256: Partial property declarations 'int C.this[dynamic[] s]' and 'int C.this[object[] s]' have signature differences. 
                //     public partial int this[object[] s] { get => 1; set { } }
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "this").WithArguments("int C.this[dynamic[] s]", "int C.this[object[] s]").WithLocation(5, 24));
        }
 
        [Fact]
        public void Semantics_Params()
        {
            var source = """
                using System;
                using System.Collections.Generic;
 
                partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                        _ = c[1, 2, 3];
                        _ = c["a", "b", "c"];
                    }
 
                    public partial int this[params int[] arr] { get; }
                    public partial int this[params int[] arr]
                    {
                        get
                        {
                            foreach (var i in arr)
                                Console.Write(i);
 
                            return 0;
                        }
                    }
 
                    public partial int this[params IEnumerable<string> enumerable] { get; }
                    public partial int this[params IEnumerable<string> enumerable]
                    {
                        get
                        {
                            foreach (var i in enumerable)
                                Console.Write(i);
 
                            return 0;
                        }
                    }
 
                }
                """;
 
            var verifier = CompileAndVerify(source, expectedOutput: "123abc");
            verifier.VerifyDiagnostics();
        }
 
        [Fact]
        public void ParamsDifference_IndexerParameter()
        {
            var source = """
                #nullable enable
                using System.Collections.Generic;
 
                partial class C
                {
                    public partial int this[params object[] arr] { get; set; }
                    public partial int this[object[] arr] { get => 1; set { } }
 
                    public partial int this[IEnumerable<object> enumerable] { get; set; }
                    public partial int this[params IEnumerable<object> enumerable] { get => 1; set { } }
 
                    public partial int this[object[] enumerable, int _] { get; set; }
                    public partial int this[params object[] enumerable, int _] { get => 1; set { } }
                }
 
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (7,24): error CS0758: Both partial member declarations must use a params parameter or neither may use a params parameter
                //     public partial int this[object[] arr] { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberParamsDifference, "this").WithLocation(7, 24),
                // (10,24): error CS0758: Both partial member declarations must use a params parameter or neither may use a params parameter
                //     public partial int this[params IEnumerable<object> enumerable] { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberParamsDifference, "this").WithLocation(10, 24),
                // (13,29): error CS0231: A params parameter must be the last parameter in a parameter list
                //     public partial int this[params object[] enumerable, int _] { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_ParamsLast, "params object[] enumerable").WithLocation(13, 29));
        }
 
        [Fact]
        public void Semantics_Scoped()
        {
            var source = """
                using System;
 
                Console.Write(new C().M()._i);
 
                ref struct RS(ref int i)
                {
                    public ref int _i = ref i;
                }
 
                partial class C
                {
                    static int s_i = 1;
 
                    public partial RS this[scoped RS rs] { get; }
                    public partial RS this[scoped RS rs] { get => new RS(ref s_i); }
 
                    public RS M()
                    {
                        int i = 0;
                        RS rs = new RS(ref i);
                        return this[rs]; // ok
                    }
                }
                """;
 
            var verifier = CompileAndVerify(
                source,
                targetFramework: TargetFramework.Net70,
                verify: Verification.Fails,
                expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "1" : null);
            verifier.VerifyDiagnostics();
        }
 
        [Fact]
        public void Scoped_Errors()
        {
            var source = """
                ref struct RS(ref int i) { }
 
                partial class C1
                {
                    public partial RS this[scoped RS rs] { get; }
                    public partial RS this[scoped RS rs] { get => rs; } // 1
                }
 
                partial class C2
                {
                    public partial RS this[RS rs] { get; }
                    public partial RS this[RS rs] { get => rs; } // ok
 
                    public RS M()
                    {
                        int i = 0;
                        RS rs = new RS(ref i);
                        return this[rs]; // error
                    }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,23): warning CS9113: Parameter 'i' is unread.
                // ref struct RS(ref int i) { }
                Diagnostic(ErrorCode.WRN_UnreadPrimaryConstructorParameter, "i").WithArguments("i").WithLocation(1, 23),
                // (6,51): error CS8352: Cannot use variable 'scoped RS rs' in this context because it may expose referenced variables outside of their declaration scope
                //     public partial RS this[scoped RS rs] { get => rs; } // 1
                Diagnostic(ErrorCode.ERR_EscapeVariable, "rs").WithArguments("scoped RS rs").WithLocation(6, 51),
                // (18,16): error CS8347: Cannot use a result of 'C2.this[RS]' in this context because it may expose variables referenced by parameter 'rs' outside of their declaration scope
                //         return this[rs]; // error
                Diagnostic(ErrorCode.ERR_EscapeCall, "this[rs]").WithArguments("C2.this[RS]", "rs").WithLocation(18, 16),
                // (18,21): error CS8352: Cannot use variable 'rs' in this context because it may expose referenced variables outside of their declaration scope  
                //         return this[rs]; // error
                Diagnostic(ErrorCode.ERR_EscapeVariable, "rs").WithArguments("rs").WithLocation(18, 21));
        }
 
        [Fact]
        public void ScopedDifference_IndexerParameter()
        {
            var source = """
                #nullable enable
 
                ref struct RS { }
 
                partial class C
                {
                    public partial RS this[scoped RS rs] { get; set; }
                    public partial RS this[RS rs] { get => default; set { } }
 
                    public partial RS this[RS rs, int _] { get; set; }
                    public partial RS this[scoped RS rs, int _] { get => default; set { } }
                }
 
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (8,23): error CS8988: The 'scoped' modifier of parameter 'rs' doesn't match partial definition.
                //     public partial RS this[RS rs] { get => default; set { } }
                Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfPartial, "this").WithArguments("rs").WithLocation(8, 23),
                // (11,23): error CS8988: The 'scoped' modifier of parameter 'rs' doesn't match partial definition.
                //     public partial RS this[scoped RS rs, int _] { get => default; set { } }
                Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfPartial, "this").WithArguments("rs").WithLocation(11, 23));
        }
 
        [Theory]
        [InlineData("in")]
        [InlineData("ref readonly")]
        public void ScopedDifference_IndexerParameter_SupportedRefKind(string refKind)
        {
            var source = $$"""
                #nullable enable
 
                ref struct RS { }
 
                partial class C
                {
                    public partial RS this[scoped {{refKind}} int i] { get; set; }
                    public partial RS this[{{refKind}} int i] { get => default; set { } }
 
                    public partial RS this[{{refKind}} int i, int _] { get; set; }
                    public partial RS this[scoped {{refKind}} int i, int _] { get => default; set { } }
                }

                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (8,23): error CS8988: The 'scoped' modifier of parameter 'i' doesn't match partial definition.
                //     public partial RS this[in int i] { get => default; set { } }
                Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfPartial, "this").WithArguments("i").WithLocation(8, 23),
                // (11,23): error CS8988: The 'scoped' modifier of parameter 'i' doesn't match partial definition.
                //     public partial RS this[scoped in int i, int _] { get => default; set { } }
                Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfPartial, "this").WithArguments("i").WithLocation(11, 23));
        }
 
        [Fact]
        public void ScopedDifference_IndexerParameter_UnsupportedRefKind()
        {
            var source = $$"""
                #nullable enable
 
                ref struct RS { }
 
                partial class C
                {
                    public partial RS this[scoped ref int i] { get; set; }
                    public partial RS this[ref int i] { get => default; set { } }
 
                    public partial RS this[ref int i, int _] { get; set; }
                    public partial RS this[scoped ref int i, int _] { get => default; set { } }
                }

                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (7,35): error CS0631: ref and out are not valid in this context
                //     public partial RS this[scoped ref int i] { get; set; }
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "ref").WithLocation(7, 35),
                // (8,23): error CS8988: The 'scoped' modifier of parameter 'i' doesn't match partial definition.
                //     public partial RS this[ref int i] { get => default; set { } }
                Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfPartial, "this").WithArguments("i").WithLocation(8, 23),
                // (8,28): error CS0631: ref and out are not valid in this context
                //     public partial RS this[ref int i] { get => default; set { } }
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "ref").WithLocation(8, 28),
                // (10,28): error CS0631: ref and out are not valid in this context
                //     public partial RS this[ref int i, int _] { get; set; }
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "ref").WithLocation(10, 28),
                // (11,23): error CS8988: The 'scoped' modifier of parameter 'i' doesn't match partial definition.
                //     public partial RS this[scoped ref int i, int _] { get => default; set { } }
                Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfPartial, "this").WithArguments("i").WithLocation(11, 23),
                // (11,35): error CS0631: ref and out are not valid in this context
                //     public partial RS this[scoped ref int i, int _] { get => default; set { } }
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "ref").WithLocation(11, 35));
        }
 
        [Fact]
        public void Semantics_OptionalParameters()
        {
            var source = """
                using System;
 
                var c = new C();
                Console.Write(c[1]);
                Console.Write(c[1, 2]);
 
                partial class C
                {
                    public partial int this[int x, int y = 1] { get; }
                    public partial int this[int x, int y] { get => y; }
                }
                """;
 
            var verifier = CompileAndVerify(source, expectedOutput: "12");
            verifier.VerifyDiagnostics();
        }
 
        [Fact]
        public void OptionalParameters_OnImplementationPart_ResultsInAWarning()
        {
            // A warning is reported for optional parameters on implementation part, even if it matches the definition part.
            var source = """
                partial class C
                {
                    public partial int this[int x, int y = 1] { get; set; }
                    public partial int this[int x, int y = 1] { get => y; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,40): warning CS1066: The default value specified for parameter 'y' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     public partial int this[int x, int y = 1] { get => y; set { } }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "y").WithArguments("y").WithLocation(4, 40));
        }
 
        [Fact]
        public void OptionalParameters_OnImplementationPart_NotRespectedAtCallSite_Semantics()
        {
            var source = """
                using System;
 
                partial class C
                {
                    static void Main()
                    {
                        var c = new C();
                        Console.Write(c[0, 0]);
                        Console.Write(c["a", 0]);
                        Console.Write(c["a"]);
                    }
 
                    public partial int this[int x, int y] { get; set; }
                    public partial int this[int x, int y = 1] { get => y; set { } }
 
                    public partial int this[string x, int y = 1] { get; set; }
                    public partial int this[string x, int y = 2] { get => y; set { } }
                }
                """;
 
            var verifier = CompileAndVerify(source, expectedOutput: "001");
            verifier.VerifyDiagnostics(
                // (14,40): warning CS1066: The default value specified for parameter 'y' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     public partial int this[int x, int y = 1] { get => y; set { } }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "y").WithArguments("y").WithLocation(14, 40),
                // (17,43): warning CS1066: The default value specified for parameter 'y' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     public partial int this[string x, int y = 2] { get => y; set { } }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "y").WithArguments("y").WithLocation(17, 43));
        }
 
        [Fact]
        public void OptionalParameters_OnImplementationPart_NotRespectedAtCallSite()
        {
            var source = """
                using System;
 
                partial class C
                {
                    static void Main()
                    {
                        var c = new C();
                        Console.Write(c[0]);
                    }
 
                    public partial int this[int x, int y] { get; set; }
                    public partial int this[int x, int y = 1] { get => y; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (8,23): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'C.this[int, int]'
                //         Console.Write(c[0]);
                Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "c[0]").WithArguments("y", "C.this[int, int]").WithLocation(8, 23),
                // (12,40): warning CS1066: The default value specified for parameter 'y' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     public partial int this[int x, int y = 1] { get => y; set { } }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "y").WithArguments("y").WithLocation(12, 40));
        }
 
        [Fact]
        public void OptionalParameters_AllParametersAreOptional()
        {
            // An indexer access needs at least one argument in order to be valid
            var source = """
                partial class C
                {
                    void M()
                    {
                        _ = this[];
                        _ = this[1];
                    }
 
                    public partial int this[int x = 1, int y = 2] { get; set; }
                    public partial int this[int x = 1, int y = 2] { get => y; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (5,18): error CS0443: Syntax error; value expected
                //         _ = this[];
                Diagnostic(ErrorCode.ERR_ValueExpected, "]").WithLocation(5, 18),
                // (10,33): warning CS1066: The default value specified for parameter 'x' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     public partial int this[int x = 1, int y = 2] { get => y; set { } }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "x").WithArguments("x").WithLocation(10, 33),
                // (10,44): warning CS1066: The default value specified for parameter 'y' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     public partial int this[int x = 1, int y = 2] { get => y; set { } }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "y").WithArguments("y").WithLocation(10, 44));
        }
 
        [Fact]
        public void Indexers_MissingOrUnexpectedDeclarations()
        {
            var source = """
                partial class C
                {
                    public partial int this[int x] { get; set; } // missing impl
 
                    public partial int this[int x, int y] { get => 1; set { } } // missing decl
 
                    public partial int this[int x, int y, int z] { get; set; } // duplicate decl
                    public partial int this[int x, int y, int z] { get; set; }
                    public partial int this[int x, int y, int z] { get => 1; set { } }
 
                    public partial int this[int x, int y, int z, int a] { get; set; } // duplicate impl
                    public partial int this[int x, int y, int z, int a] { get => 1; set { } }
                    public partial int this[int x, int y, int z, int a] { get => 1; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,24): error CS9248: Partial property 'C.this[int]' must have an implementation part.
                //     public partial int this[int x] { get; set; } // missing impl
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingImplementation, "this").WithArguments("C.this[int]").WithLocation(3, 24),
                // (5,24): error CS9249: Partial property 'C.this[int, int]' must have a definition part.
                //     public partial int this[int x, int y] { get => 1; set { } } // missing decl
                Diagnostic(ErrorCode.ERR_PartialPropertyMissingDefinition, "this").WithArguments("C.this[int, int]").WithLocation(5, 24),
                // (8,24): error CS9250: A partial property may not have multiple defining declarations, and cannot be an auto-property.
                //     public partial int this[int x, int y, int z] { get; set; }
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateDefinition, "this").WithLocation(8, 24),
                // (8,24): error CS0111: Type 'C' already defines a member called 'this' with the same parameter types
                //     public partial int this[int x, int y, int z] { get; set; }
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "C").WithLocation(8, 24),
                // (13,24): error CS9251: A partial property may not have multiple implementing declarations
                //     public partial int this[int x, int y, int z, int a] { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateImplementation, "this").WithLocation(13, 24),
                // (13,24): error CS0111: Type 'C' already defines a member called 'this' with the same parameter types
                //     public partial int this[int x, int y, int z, int a] { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "C").WithLocation(13, 24));
        }
 
        [Fact]
        public void Indexers_ReturnTypeDifference()
        {
            var source = """
                partial class C
                {
                    public partial int[] this[int x] { get; set; }
                    public partial string[] this[int x] { get => []; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,29): error CS9255: Both partial property declarations must have the same type.
                //     public partial string[] this[int x] { get => []; set { } }
                Diagnostic(ErrorCode.ERR_PartialPropertyTypeDifference, "this").WithLocation(4, 29));
        }
 
        [Fact]
        public void Indexers_TupleElementNameDifference()
        {
            var source = """
                partial class C
                {
                    // in return type
                    public partial (int x, int y)[] this[int x] { get; set; }
                    public partial (int a, int b)[] this[int x] { get => []; set { } }
                    
                    // in parameter type
                    public partial int this[(int x, int y) pair] { get; set; }
                    public partial int this[(int a, int b) pair] { get => 1; set { } }
 
                    // in both return and parameter type
                    public partial (int x, int y)[] this[(int x, int y, int z) pair] { get; set; }
                    public partial (int a, int b)[] this[(int a, int b, int c) pair] { get => []; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (5,37): error CS8142: Both partial member declarations, 'C.this[int]' and 'C.this[int]', must use the same tuple element names.
                //     public partial (int a, int b)[] this[int x] { get => []; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberInconsistentTupleNames, "this").WithArguments("C.this[int]", "C.this[int]").WithLocation(5, 37),
                // (9,24): error CS8142: Both partial member declarations, 'C.this[(int x, int y)]' and 'C.this[(int a, int b)]', must use the same tuple element names.
                //     public partial int this[(int a, int b) pair] { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberInconsistentTupleNames, "this").WithArguments("C.this[(int x, int y)]", "C.this[(int a, int b)]").WithLocation(9, 24),
                // (13,37): error CS8142: Both partial member declarations, 'C.this[(int x, int y, int z)]' and 'C.this[(int a, int b, int c)]', must use the same tuple element names.
                //     public partial (int a, int b)[] this[(int a, int b, int c) pair] { get => []; set { } }
                Diagnostic(ErrorCode.ERR_PartialMemberInconsistentTupleNames, "this").WithArguments("C.this[(int x, int y, int z)]", "C.this[(int a, int b, int c)]").WithLocation(13, 37));
        }
 
        [Theory]
        [InlineData("A(1)", "B(2)")]
        [InlineData("B(2)", "A(1)")]
        public void Attributes_Property_01(string declAttribute, string implAttribute)
        {
            // Name or arguments to attributes doesn't affect order of emit.
            // Attributes on the declaration part precede attributes on the implementation part.
            var source = $$"""
                #pragma warning disable CS9113 // Primary constructor parameter is unread
 
                using System;
                
                class A(int i) : Attribute { }
                class B(int i) : Attribute { }
 
                partial class C
                {
                    [{{declAttribute}}]
                    public partial int P { get; set; }
 
                    [{{implAttribute}}]
                    public partial int P { get => 1; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
 
            var property = comp.GetMember<SourcePropertySymbol>("C.P");
            AssertEx.Equal([declAttribute, implAttribute], property.GetAttributes().ToStrings());
            AssertEx.Equal([declAttribute, implAttribute], property.PartialImplementationPart!.GetAttributes().ToStrings());
        }
 
        [Theory]
        [InlineData("A(1)", "B(2)")]
        [InlineData("B(2)", "A(1)")]
        public void Attributes_Property_02(string declAttribute, string implAttribute)
        {
            // Lexical order of the partial declarations themselves doesn't affect order that attributes are emitted.
            var source = $$"""            
                #pragma warning disable CS9113 // Primary constructor parameter is unread
 
                using System;
                
                class A(int i) : Attribute { }
                class B(int i) : Attribute { }
 
                partial class C
                {
                    [{{implAttribute}}]
                    public partial int P { get => 1; set { } }
 
                    [{{declAttribute}}]
                    public partial int P { get; set; }
                }
                """;
 
            var verifier = CompileAndVerify(source, symbolValidator: module => verify(module, isSource: false), sourceSymbolValidator: module => verify(module, isSource: true));
            verifier.VerifyDiagnostics();
 
            void verify(ModuleSymbol module, bool isSource)
            {
                var property = module.GlobalNamespace.GetMember<PropertySymbol>("C.P");
                AssertEx.Equal([declAttribute, implAttribute], property.GetAttributes().ToStrings());
                if (isSource)
                {
                    AssertEx.Equal([declAttribute, implAttribute], ((SourcePropertySymbol)property).PartialImplementationPart!.GetAttributes().ToStrings());
                }
            }
        }
 
        [Fact]
        public void Attributes_Property_03()
        {
            // Order of attributes within a part is preserved.
            var source = """
                #pragma warning disable CS9113 // Primary constructor parameter is unread
 
                using System;
                
                [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
                class A(int i) : Attribute { }
                [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
                class B(int i) : Attribute { }
 
                partial class C
                {
                    [A(2), B(2)]
                    public partial int P { get => 1; set { } }
 
                    [A(1), B(1)]
                    public partial int P { get; set; }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
 
            var property = comp.GetMember<SourcePropertySymbol>("C.P");
            AssertEx.Equal(["A(1)", "B(1)", "A(2)", "B(2)"], property.GetAttributes().ToStrings());
            AssertEx.Equal(["A(1)", "B(1)", "A(2)", "B(2)"], property.PartialImplementationPart!.GetAttributes().ToStrings());
        }
 
        [Fact]
        public void Attributes_GetAccessor()
        {
            // Order of attributes within a part is preserved.
            var source = """
                #pragma warning disable CS9113 // Primary constructor parameter is unread
 
                using System;
                
                [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
                class A(int i) : Attribute { }
                [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
                class B(int i) : Attribute { }
 
                partial class C
                {
                    public partial int P
                    {
                        [A(2), B(2)]
                        get => 1;
                        set { }
                    }
 
                    public partial int P
                    {
                        [A(1), B(1)]
                        get;
                        set;
                    }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
 
            var accessor = comp.GetMember<MethodSymbol>("C.get_P");
            AssertEx.Equal(["A(1)", "B(1)", "A(2)", "B(2)"], accessor.GetAttributes().ToStrings());
            AssertEx.Equal(["A(1)", "B(1)", "A(2)", "B(2)"], accessor.PartialImplementationPart!.GetAttributes().ToStrings());
        }
 
        [Theory]
        [CombinatorialData]
        public void Attributes_SetAccessor(bool definitionFirst)
        {
            var definitionPart = """
                    public partial int P
                    {
                        get;
                        [A(1), B(1)]
                        set;
                    }
                """;
 
            var implementationPart = """
                    public partial int P
                    {
                        get => 1;
                        [A(2), B(2)]
                        set { }
                    }
                """;
 
            var source = $$"""
                #pragma warning disable CS9113 // Primary constructor parameter is unread
 
                using System;
                
                
                [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
                class A(int i) : Attribute { }
                [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
                class B(int i) : Attribute { }
 
                partial class C
                {
                    {{(definitionFirst ? definitionPart : implementationPart)}}
 
                    {{(definitionFirst ? implementationPart : definitionPart)}}
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
 
            var accessor = comp.GetMember<MethodSymbol>("C.set_P");
            AssertEx.Equal(["A(1)", "B(1)", "A(2)", "B(2)"], accessor.GetAttributes().ToStrings());
            AssertEx.Equal(["A(1)", "B(1)", "A(2)", "B(2)"], accessor.PartialImplementationPart!.GetAttributes().ToStrings());
        }
 
        [Fact]
        public void Attributes_SetValueParam()
        {
            // Just as with parameter attributes on partial methods,
            // the implementation part attributes are emitted before the definition part attributes.
            var source = """
                #pragma warning disable CS9113 // Primary constructor parameter is unread
 
                using System;
                
                [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
                class A(int i) : Attribute { }
                [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
                class B(int i) : Attribute { }
 
                partial class C
                {
                    public partial int P
                    {
                        get => 1;
                        [param: A(2), B(2)]
                        set { }
                    }
 
                    public partial int P
                    {
                        get;
                        [param: A(1), B(1)]
                        set;
                    }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
 
            var accessor = comp.GetMember<MethodSymbol>("C.set_P");
            AssertEx.Equal([], accessor.GetAttributes().ToStrings());
            AssertEx.Equal([], accessor.PartialImplementationPart.GetAttributes().ToStrings());
            AssertEx.Equal(["A(2)", "B(2)", "A(1)", "B(1)"], accessor.Parameters.Single().GetAttributes().ToStrings());
            AssertEx.Equal(["A(2)", "B(2)", "A(1)", "B(1)"], accessor.PartialImplementationPart!.Parameters.Single().GetAttributes().ToStrings());
        }
 
        [Fact]
        public void Attributes_Indexer()
        {
            var source = """
                #pragma warning disable CS9113 // Primary constructor parameter is unread
 
                using System;
                
                [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
                class A(int i) : Attribute { }
                [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
                class B(int i) : Attribute { }
 
                partial class C
                {
                    [A(2), B(2)]
                    public partial int this[int i] { get => 1; set { } }
 
                    [A(1), B(1)]
                    public partial int this[int i] { get; set; }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
 
            var indexer = (SourcePropertySymbol)comp.GetMember<NamedTypeSymbol>("C").Indexers.Single();
            AssertEx.Equal(["A(1)", "B(1)", "A(2)", "B(2)"], indexer.GetAttributes().ToStrings());
            AssertEx.Equal(["A(1)", "B(1)", "A(2)", "B(2)"], indexer.PartialImplementationPart!.GetAttributes().ToStrings());
        }
 
        [Fact]
        public void Attributes_IndexerParameter()
        {
            // Unlike other symbol kinds, for parameters, the implementation part attributes are emitted first, then the definition part attributes.
            // This is consistent with partial methods.
            var source = """
                #pragma warning disable CS9113 // Primary constructor parameter is unread
 
                using System;
                
                [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
                class A(int i) : Attribute { }
                [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
                class B(int i) : Attribute { }
 
                partial class C
                {
                    public partial int this[[A(2), B(2)] int i] { get => 1; set { } }
 
                    public partial int this[[A(1), B(1)] int i] { get; set; }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
 
            var indexer = (SourcePropertySymbol)comp.GetMember<NamedTypeSymbol>("C").Indexers.Single();
 
            verify(indexer.Parameters.Single());
            verify(indexer.GetMethod!.Parameters.Single());
            verify(indexer.SetMethod!.Parameters[0]);
 
            verify(indexer.PartialImplementationPart!.Parameters.Single());
            verify(indexer.PartialImplementationPart!.GetMethod!.Parameters.Single());
            verify(indexer.PartialImplementationPart!.SetMethod!.Parameters[0]);
 
            void verify(ParameterSymbol param)
            {
                AssertEx.Equal(["A(2)", "B(2)", "A(1)", "B(1)"], param.GetAttributes().ToStrings());
            }
        }
 
        [Fact]
        public void Attributes_Property_DisallowedDuplicates()
        {
            var source = """
                using System;
 
                class Attr : Attribute { }
 
                partial class C
                {
                    [Attr]
                    public partial int P
                    {
                        [Attr]
                        get;
 
                        [Attr]
                        [param: Attr] set; // 1
                    }
 
                    [Attr] // 2
                    public partial int P
                    {
                        [Attr] // 3
                        get => 1;
 
                        [Attr] // 4
                        [param: Attr] set { }
                    }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (14,17): error CS0579: Duplicate 'Attr' attribute
                //         [param: Attr] set; // 1
                Diagnostic(ErrorCode.ERR_DuplicateAttribute, "Attr").WithArguments("Attr").WithLocation(14, 17),
                // (17,6): error CS0579: Duplicate 'Attr' attribute
                //     [Attr] // 2
                Diagnostic(ErrorCode.ERR_DuplicateAttribute, "Attr").WithArguments("Attr").WithLocation(17, 6),
                // (20,10): error CS0579: Duplicate 'Attr' attribute
                //         [Attr] // 3
                Diagnostic(ErrorCode.ERR_DuplicateAttribute, "Attr").WithArguments("Attr").WithLocation(20, 10),
                // (23,10): error CS0579: Duplicate 'Attr' attribute
                //         [Attr] // 4
                Diagnostic(ErrorCode.ERR_DuplicateAttribute, "Attr").WithArguments("Attr").WithLocation(23, 10));
 
            var property = comp.GetMember<SourcePropertySymbol>("C.P");
            AssertEx.Equal(["Attr", "Attr"], property.GetAttributes().ToStrings());
            AssertEx.Equal(["Attr", "Attr"], property.GetMethod!.GetAttributes().ToStrings());
            AssertEx.Equal(["Attr", "Attr"], property.SetMethod!.GetAttributes().ToStrings());
            AssertEx.Equal(["Attr", "Attr"], property.SetMethod!.Parameters.Single().GetAttributes().ToStrings());
        }
 
        [Fact]
        public void Attributes_Indexer_DisallowedDuplicates()
        {
            var source = """
                using System;
 
                class Attr : Attribute { }
 
                partial class C
                {
                    [Attr]
                    public partial int this[
                        [Attr] int x, // 1
                        [Attr] int y] // 2
                    {
                        [Attr] get;
                        [Attr]
                        [param: Attr] set; // 3
                    }
 
                    [Attr] // 4
                    public partial int this[
                        [Attr] int x,
                        [Attr] int y]
                    {
                        [Attr] // 5
                        get => 1;
 
                        [Attr] // 6
                        [param: Attr] set { }
                    }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (9,10): error CS0579: Duplicate 'Attr' attribute
                //         [Attr] int x, // 1
                Diagnostic(ErrorCode.ERR_DuplicateAttribute, "Attr").WithArguments("Attr").WithLocation(9, 10),
                // (10,10): error CS0579: Duplicate 'Attr' attribute
                //         [Attr] int y] // 2
                Diagnostic(ErrorCode.ERR_DuplicateAttribute, "Attr").WithArguments("Attr").WithLocation(10, 10),
                // (14,17): error CS0579: Duplicate 'Attr' attribute
                //         [param: Attr] set; // 3
                Diagnostic(ErrorCode.ERR_DuplicateAttribute, "Attr").WithArguments("Attr").WithLocation(14, 17),
                // (17,6): error CS0579: Duplicate 'Attr' attribute
                //     [Attr] // 4
                Diagnostic(ErrorCode.ERR_DuplicateAttribute, "Attr").WithArguments("Attr").WithLocation(17, 6),
                // (22,10): error CS0579: Duplicate 'Attr' attribute
                //         [Attr] // 5
                Diagnostic(ErrorCode.ERR_DuplicateAttribute, "Attr").WithArguments("Attr").WithLocation(22, 10),
                // (25,10): error CS0579: Duplicate 'Attr' attribute
                //         [Attr] // 6
                Diagnostic(ErrorCode.ERR_DuplicateAttribute, "Attr").WithArguments("Attr").WithLocation(25, 10));
 
            var property = (SourcePropertySymbol)comp.GetMember<NamedTypeSymbol>("C").Indexers.Single();
            AssertEx.Equal(["Attr", "Attr"], property.GetAttributes().ToStrings());
            AssertEx.Equal(["Attr", "Attr"], property.GetMethod!.GetAttributes().ToStrings());
            AssertEx.Equal(["Attr", "Attr"], property.GetMethod!.Parameters[0].GetAttributes().ToStrings());
            AssertEx.Equal(["Attr", "Attr"], property.GetMethod!.Parameters[1].GetAttributes().ToStrings());
            AssertEx.Equal(["Attr", "Attr"], property.SetMethod!.GetAttributes().ToStrings());
            AssertEx.Equal(["Attr", "Attr"], property.SetMethod!.Parameters[0].GetAttributes().ToStrings());
            AssertEx.Equal(["Attr", "Attr"], property.SetMethod!.Parameters[1].GetAttributes().ToStrings());
            AssertEx.Equal(["Attr", "Attr"], property.SetMethod!.Parameters[2].GetAttributes().ToStrings());
        }
 
        [Fact]
        public void Attributes_Property_BackingField()
        {
            var source = """
                using System;
 
                class Attr : Attribute { }
 
                partial class C
                {
                    [field: Attr]
                    public partial int P { get; set; }
 
                    [field: Attr]
                    public partial int P { get => 1; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (7,6): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'property'. All attributes in this block will be ignored.
                //     [field: Attr]
                Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(7, 6),
                // (10,6): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'property'. All attributes in this block will be ignored.
                //     [field: Attr]
                Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(10, 6));
 
            // https://github.com/dotnet/roslyn/issues/57012
            // 'field' keyword in properties feature should test partial properties where the implementation uses 'field' and one or both parts have 'field:' targeted attribute lists.
            var property = comp.GetMember<SourcePropertySymbol>("C.P");
            AssertEx.Equal([], property.GetAttributes().ToStrings());
        }
 
        [Fact]
        public void PropertyInitializer()
        {
            var source = """
                partial class C
                {
                    public partial string P1 { get; set; } = "a";
                    public partial string P1 { get => ""; set { } }
 
                    public partial string P2 { get; set; }
                    public partial string P2 { get => ""; set { } } = "b";
 
                    public partial string P3 { get; set; } = "c";
                    public partial string P3 { get => ""; set { } } = "d";
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,27): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers.
                //     public partial string P1 { get; set; } = "a";
                Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P1").WithLocation(3, 27),
                // (7,27): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers.
                //     public partial string P2 { get => ""; set { } } = "b";
                Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P2").WithLocation(7, 27),
                // (9,27): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers.
                //     public partial string P3 { get; set; } = "c";
                Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P3").WithLocation(9, 27),
                // (10,27): error CS9263: A partial property cannot have an initializer on both the definition and implementation.
                //     public partial string P3 { get => ""; set { } } = "d";
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateInitializer, "P3").WithLocation(10, 27),
                // (10,27): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers.
                //     public partial string P3 { get => ""; set { } } = "d";
                Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P3").WithLocation(10, 27));
 
            AssertEx.Equal([
                "System.String C.<P1>k__BackingField",
                "System.String C.P1 { get; set; }",
                "System.String C.P1.get",
                "void C.P1.set",
                "System.String C.P2 { get; set; }",
                "System.String C.P2.get",
                "void C.P2.set",
                "System.String C.<P2>k__BackingField",
                "System.String C.<P3>k__BackingField",
                "System.String C.P3 { get; set; }",
                "System.String C.P3.get",
                "void C.P3.set",
                "C..ctor()"],
                comp.GetMember<NamedTypeSymbol>("C").GetMembers().SelectAsArray(m => m.ToTestDisplayString()));
 
            Assert.Empty(comp.GetMember<FieldSymbol>("C.<P1>k__BackingField").GetAttributes());
            Assert.Empty(comp.GetMember<FieldSymbol>("C.<P2>k__BackingField").GetAttributes());
            Assert.Empty(comp.GetMember<FieldSymbol>("C.<P3>k__BackingField").GetAttributes());
        }
 
        [Fact]
        public void PropertyInitializer_ContainsErrors()
        {
            var source = """
                partial class C
                {
                    public partial string P1 { get; set; } = ERROR;
                    public partial string P1 { get => ""; set { } }
 
                    public partial string P2 { get; set; }
                    public partial string P2 { get => ""; set { } } = ERROR;
 
                    public partial string P3 { get; set; } = ERROR;
                    public partial string P3 { get => ""; set { } } = ERROR;
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,27): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers.
                //     public partial string P1 { get; set; } = ERROR;
                Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P1").WithLocation(3, 27),
                // (3,46): error CS0103: The name 'ERROR' does not exist in the current context
                //     public partial string P1 { get; set; } = ERROR;
                Diagnostic(ErrorCode.ERR_NameNotInContext, "ERROR").WithArguments("ERROR").WithLocation(3, 46),
                // (7,27): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers.
                //     public partial string P2 { get => ""; set { } } = ERROR;
                Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P2").WithLocation(7, 27),
                // (7,55): error CS0103: The name 'ERROR' does not exist in the current context
                //     public partial string P2 { get => ""; set { } } = ERROR;
                Diagnostic(ErrorCode.ERR_NameNotInContext, "ERROR").WithArguments("ERROR").WithLocation(7, 55),
                // (9,27): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers.
                //     public partial string P3 { get; set; } = ERROR;
                Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P3").WithLocation(9, 27),
                // (9,46): error CS0103: The name 'ERROR' does not exist in the current context
                //     public partial string P3 { get; set; } = ERROR;
                Diagnostic(ErrorCode.ERR_NameNotInContext, "ERROR").WithArguments("ERROR").WithLocation(9, 46),
                // (10,27): error CS9263: A partial property cannot have an initializer on both the definition and implementation.
                //     public partial string P3 { get => ""; set { } } = ERROR;
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateInitializer, "P3").WithLocation(10, 27),
                // (10,27): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers.
                //     public partial string P3 { get => ""; set { } } = ERROR;
                Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P3").WithLocation(10, 27),
                // (10,55): error CS0103: The name 'ERROR' does not exist in the current context
                //     public partial string P3 { get => ""; set { } } = ERROR;
                Diagnostic(ErrorCode.ERR_NameNotInContext, "ERROR").WithArguments("ERROR").WithLocation(10, 55));
 
            AssertEx.Equal([
                "System.String C.<P1>k__BackingField",
                "System.String C.P1 { get; set; }",
                "System.String C.P1.get",
                "void C.P1.set",
                "System.String C.P2 { get; set; }",
                "System.String C.P2.get",
                "void C.P2.set",
                "System.String C.<P2>k__BackingField",
                "System.String C.<P3>k__BackingField",
                "System.String C.P3 { get; set; }",
                "System.String C.P3.get",
                "void C.P3.set",
                "C..ctor()"],
                comp.GetMember<NamedTypeSymbol>("C").GetMembers().SelectAsArray(m => m.ToTestDisplayString()));
 
            Assert.Empty(comp.GetMember<FieldSymbol>("C.<P1>k__BackingField").GetAttributes());
            Assert.Empty(comp.GetMember<FieldSymbol>("C.<P2>k__BackingField").GetAttributes());
            Assert.Empty(comp.GetMember<FieldSymbol>("C.<P3>k__BackingField").GetAttributes());
        }
 
        [Fact]
        public void PropertyInitializer_AndFieldTargetedAttribute()
        {
            // A synthesized field symbol is created when property has an initializer, even if the property is not an auto-property.
            var source = """
                public class Attr1 : System.Attribute { }
                public class Attr2 : System.Attribute { }
 
                partial class C
                {
                    [field: Attr1]
                    public partial string P1 { get; set; } = "a";
                    [field: Attr2]
                    public partial string P1 { get => ""; set { } }
 
                    [field: Attr1]
                    public partial string P2 { get; set; }
                    [field: Attr2]
                    public partial string P2 { get => ""; set { } } = "b";
 
                    [field: Attr1]
                    public partial string P3 { get; set; } = "c";
                    [field: Attr2]
                    public partial string P3 { get => ""; set { } } = "d";
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (6,6): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'property'. All attributes in this block will be ignored.
                //     [field: Attr1]
                Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(6, 6),
                // (7,27): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers.
                //     public partial string P1 { get; set; } = "a";
                Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P1").WithLocation(7, 27),
                // (8,6): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'property'. All attributes in this block will be ignored.
                //     [field: Attr2]
                Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(8, 6),
                // (11,6): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'property'. All attributes in this block will be ignored.
                //     [field: Attr1]
                Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(11, 6),
                // (13,6): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'property'. All attributes in this block will be ignored.
                //     [field: Attr2]
                Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(13, 6),
                // (14,27): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers.
                //     public partial string P2 { get => ""; set { } } = "b";
                Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P2").WithLocation(14, 27),
                // (16,6): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'property'. All attributes in this block will be ignored.
                //     [field: Attr1]
                Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(16, 6),
                // (17,27): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers.
                //     public partial string P3 { get; set; } = "c";
                Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P3").WithLocation(17, 27),
                // (18,6): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'property'. All attributes in this block will be ignored.
                //     [field: Attr2]
                Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(18, 6),
                // (19,27): error CS9263: A partial property cannot have an initializer on both the definition and implementation.
                //     public partial string P3 { get => ""; set { } } = "d";
                Diagnostic(ErrorCode.ERR_PartialPropertyDuplicateInitializer, "P3").WithLocation(19, 27),
                // (19,27): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers.
                //     public partial string P3 { get => ""; set { } } = "d";
                Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P3").WithLocation(19, 27));
 
            AssertEx.Equal([
                "System.String C.<P1>k__BackingField",
                "System.String C.P1 { get; set; }",
                "System.String C.P1.get",
                "void C.P1.set",
                "System.String C.P2 { get; set; }",
                "System.String C.P2.get",
                "void C.P2.set",
                "System.String C.<P2>k__BackingField",
                "System.String C.<P3>k__BackingField",
                "System.String C.P3 { get; set; }",
                "System.String C.P3.get",
                "void C.P3.set",
                "C..ctor()"],
                comp.GetMember<NamedTypeSymbol>("C").GetMembers().SelectAsArray(m => m.ToTestDisplayString()));
 
            Assert.Empty(comp.GetMember<FieldSymbol>("C.<P1>k__BackingField").GetAttributes());
            Assert.Empty(comp.GetMember<FieldSymbol>("C.<P2>k__BackingField").GetAttributes());
            Assert.Empty(comp.GetMember<FieldSymbol>("C.<P3>k__BackingField").GetAttributes());
        }
 
        [Theory]
        [InlineData("", "[UnscopedRef] ")]
        [InlineData("[UnscopedRef] ", "")]
        public void Attributes_UnscopedRef(string defAttrs, string implAttrs)
        {
            // There aren't many interesting scenarios to test with UnscopedRef because:
            // - no out parameters (so no removing the implicit 'scoped' from them)
            // - no ref parameters either (so no interesting differences in ref safety analysis for ref readonlys marked with `[UnscopedRef]`)
            var source = $$"""
                #pragma warning disable CS9113 // Primary constructor parameter is unread
 
                using System.Diagnostics.CodeAnalysis;
 
                public ref struct RS([UnscopedRef] ref readonly int ri) { }
 
                partial class C
                {
                    public partial RS this[{{defAttrs}}ref readonly int i] { get; }
                    public partial RS this[{{implAttrs}}ref readonly int i]
                    {
                        get => new RS(in i);
                    }
                }
                """;
 
            var comp = CreateCompilation([source, UnscopedRefAttributeDefinition]);
            comp.VerifyEmitDiagnostics();
 
            var indexer = (SourcePropertySymbol)comp.GetMember<NamedTypeSymbol>("C").Indexers.Single();
            Assert.True(indexer.Parameters[0].HasUnscopedRefAttribute);
            Assert.True(indexer.PartialImplementationPart!.Parameters[0].HasUnscopedRefAttribute);
            Assert.True(indexer.GetMethod!.Parameters[0].HasUnscopedRefAttribute);
            Assert.True(indexer.GetMethod!.PartialImplementationPart!.Parameters[0].HasUnscopedRefAttribute);
        }
 
        [Fact]
        public void Attributes_CallerLineNumber_OnDefinition()
        {
            var source = $$"""
                using System;
                using System.Runtime.CompilerServices;
 
                partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                #line 1
                        Console.Write(c[2]);
                    }
 
                    public partial int this[int x, [CallerLineNumber] int lineNumber = 0] { get; }
                    public partial int this[int x, int lineNumber]
                    {
                        get
                        {
                            Console.Write(lineNumber);
                            return x;
                        }
                    }
                }
                """;
            var verifier = CompileAndVerify(source, expectedOutput: "12", symbolValidator: verify);
            verifier.VerifyDiagnostics();
 
            void verify(ModuleSymbol module)
            {
                var indexer = (PropertySymbol)module.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers.Single();
                AssertEx.Equal(["System.Runtime.CompilerServices.CallerLineNumberAttribute"], indexer.Parameters[1].GetAttributes().ToStrings());
            }
        }
 
        [Fact]
        public void Attributes_CallerLineNumber_OnImplementation()
        {
            var source = $$"""
                using System;
                using System.Runtime.CompilerServices;
 
                partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                #line 1
                        Console.Write(c[2]);
                    }
 
                    public partial int this[int x, int lineNumber = 0] { get; }
                    public partial int this[int x, [CallerLineNumber] int lineNumber]
                    {
                        get
                        {
                            Console.Write(lineNumber);
                            return x;
                        }
                    }
                }
                """;
            var verifier = CompileAndVerify(source, expectedOutput: "02", symbolValidator: verify);
            verifier.VerifyDiagnostics(
                // (5,37): warning CS4024: The CallerLineNumberAttribute applied to parameter 'lineNumber' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     public partial int this[int x, [CallerLineNumber] int lineNumber]
                Diagnostic(ErrorCode.WRN_CallerLineNumberParamForUnconsumedLocation, "CallerLineNumber").WithArguments("lineNumber").WithLocation(5, 37));
 
            void verify(ModuleSymbol module)
            {
                // https://github.com/dotnet/roslyn/issues/73482
                // The attribute is still written out to metadata even though it is ignored in source.
                // We could consider changing this for both properties and methods.
                var indexer = (PropertySymbol)module.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers.Single();
                AssertEx.Equal(["System.Runtime.CompilerServices.CallerLineNumberAttribute"], indexer.Parameters[1].GetAttributes().ToStrings());
            }
        }
 
        [Fact]
        public void Attributes_CallerFilePath_OnDefinition()
        {
            var source = ($$"""
                using System;
                using System.Runtime.CompilerServices;
 
                partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                        Console.Write(c[2]);
                    }
 
                    public partial int this[int x, [CallerFilePath] string filePath = "0"] { get; }
                    public partial int this[int x, string filePath]
                    {
                        get
                        {
                            Console.Write(filePath);
                            return x;
                        }
                    }
                }
                """, filePath: "Program.cs");
            var verifier = CompileAndVerify(source, expectedOutput: "Program.cs2", symbolValidator: verify);
            verifier.VerifyDiagnostics();
 
            void verify(ModuleSymbol module)
            {
                var indexer = (PropertySymbol)module.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers.Single();
                AssertEx.Equal(["System.Runtime.CompilerServices.CallerFilePathAttribute"], indexer.Parameters[1].GetAttributes().ToStrings());
            }
        }
 
        [Fact]
        public void Attributes_CallerFilePath_OnImplementation()
        {
            var source = ($$"""
                using System;
                using System.Runtime.CompilerServices;
 
                partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                        Console.Write(c[2]);
                    }
 
                    public partial int this[int x, string filePath = "0"] { get; }
                    public partial int this[int x, [CallerFilePath] string filePath]
                    {
                        get
                        {
                            Console.Write(filePath);
                            return x;
                        }
                    }
                }
                """, filePath: "Program.cs");
            var verifier = CompileAndVerify(source, expectedOutput: "02", symbolValidator: verify);
            verifier.VerifyDiagnostics(
                // Program.cs(13,37): warning CS4025: The CallerFilePathAttribute applied to parameter 'filePath' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     public partial int this[int x, [CallerFilePath] string filePath]
                Diagnostic(ErrorCode.WRN_CallerFilePathParamForUnconsumedLocation, "CallerFilePath").WithArguments("filePath").WithLocation(13, 37));
 
            void verify(ModuleSymbol module)
            {
                // https://github.com/dotnet/roslyn/issues/73482
                // The attribute is still written out to metadata even though it is ignored in source.
                // We could consider changing this for both properties and methods.
                var indexer = (PropertySymbol)module.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers.Single();
                AssertEx.Equal(["System.Runtime.CompilerServices.CallerFilePathAttribute"], indexer.Parameters[1].GetAttributes().ToStrings());
            }
        }
 
        [Fact]
        public void Attributes_CallerMemberName_OnDefinition()
        {
            var source = $$"""
                using System;
                using System.Runtime.CompilerServices;
 
                partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                        Console.Write(c[2]);
                    }
 
                    public partial int this[int x, [CallerMemberName] string filePath = "0"] { get; }
                    public partial int this[int x, string filePath]
                    {
                        get
                        {
                            Console.Write(filePath);
                            return x;
                        }
                    }
                }
                """;
            var verifier = CompileAndVerify(source, expectedOutput: "Main2", symbolValidator: verify);
            verifier.VerifyDiagnostics();
 
            void verify(ModuleSymbol module)
            {
                var indexer = (PropertySymbol)module.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers.Single();
                AssertEx.Equal(["System.Runtime.CompilerServices.CallerMemberNameAttribute"], indexer.Parameters[1].GetAttributes().ToStrings());
            }
        }
 
        [Fact]
        public void Attributes_CallerMemberName_OnImplementation()
        {
            var source = $$"""
                using System;
                using System.Runtime.CompilerServices;
 
                partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                        Console.Write(c[2]);
                    }
 
                    public partial int this[int x, string filePath = "0"] { get; }
                    public partial int this[int x, [CallerMemberName] string filePath]
                    {
                        get
                        {
                            Console.Write(filePath);
                            return x;
                        }
                    }
                }
                """;
            var verifier = CompileAndVerify(source, expectedOutput: "02", symbolValidator: verify);
            verifier.VerifyDiagnostics(
                // (13,37): warning CS4026: The CallerMemberNameAttribute applied to parameter 'filePath' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     public partial int this[int x, [CallerMemberName] string filePath]
                Diagnostic(ErrorCode.WRN_CallerMemberNameParamForUnconsumedLocation, "CallerMemberName").WithArguments("filePath").WithLocation(13, 37));
 
            void verify(ModuleSymbol module)
            {
                // https://github.com/dotnet/roslyn/issues/73482
                // The attribute is still written out to metadata even though it is ignored in source.
                // We could consider changing this for both properties and methods.
                var indexer = (PropertySymbol)module.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers.Single();
                AssertEx.Equal(["System.Runtime.CompilerServices.CallerMemberNameAttribute"], indexer.Parameters[1].GetAttributes().ToStrings());
            }
        }
 
        [Fact]
        public void Attributes_CallerArgumentExpression_OnDefinition()
        {
            var source = $$"""
                using System;
                using System.Runtime.CompilerServices;
 
                namespace System.Runtime.CompilerServices
                {
                    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = false)]
                    public sealed class CallerArgumentExpressionAttribute : Attribute
                    {
                        public CallerArgumentExpressionAttribute(string parameterName)
                        {
                            ParameterName = parameterName;
                        }
                        public string ParameterName { get; }
                    }
                }
 
                partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                        Console.Write(c[GetNumber()]);
                    }
 
                    public static int GetNumber() => 2;
 
                    public partial int this[int x, [CallerArgumentExpression("x")] string argumentExpression = "0"] { get; }
                    public partial int this[int x, string argumentExpression]
                    {
                        get
                        {
                            Console.Write(argumentExpression);
                            return x;
                        }
                    }
                }
                """;
            var verifier = CompileAndVerify(source, expectedOutput: "GetNumber()2", symbolValidator: verify);
            verifier.VerifyDiagnostics();
 
            void verify(ModuleSymbol module)
            {
                var indexer = (PropertySymbol)module.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers.Single();
                AssertEx.Equal(["""System.Runtime.CompilerServices.CallerArgumentExpressionAttribute("x")"""], indexer.Parameters[1].GetAttributes().ToStrings());
            }
        }
 
        [Fact]
        public void Attributes_CallerArgumentExpression_OnImplementation()
        {
            var source = """
                using System;
                using System.Runtime.CompilerServices;
 
                namespace System.Runtime.CompilerServices
                {
                    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = false)]
                    public sealed class CallerArgumentExpressionAttribute : Attribute
                    {
                        public CallerArgumentExpressionAttribute(string parameterName)
                        {
                            ParameterName = parameterName;
                        }
                        public string ParameterName { get; }
                    }
                }
 
                partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                        Console.Write(c[GetNumber()]);
                    }
 
                    public static int GetNumber() => 2;
 
                    public partial int this[int x, string argumentExpression = "0"] { get; }
                    public partial int this[int x, [CallerArgumentExpression("x")] string argumentExpression]
                    {
                        get
                        {
                            Console.Write(argumentExpression);
                            return x;
                        }
                    }
                }
                """;
            var verifier = CompileAndVerify(source, expectedOutput: "02", symbolValidator: verify);
            verifier.VerifyDiagnostics(
                // (28,37): warning CS8966: The CallerArgumentExpressionAttribute applied to parameter 'argumentExpression' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     public partial int this[int x, [CallerArgumentExpression("x")] string argumentExpression]
                Diagnostic(ErrorCode.WRN_CallerArgumentExpressionParamForUnconsumedLocation, "CallerArgumentExpression").WithArguments("argumentExpression").WithLocation(28, 37));
 
            void verify(ModuleSymbol module)
            {
                // https://github.com/dotnet/roslyn/issues/73482
                // The attribute is still written out to metadata even though it is ignored in source.
                // We could consider changing this for both properties and methods.
                var indexer = (PropertySymbol)module.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers.Single();
                AssertEx.Equal(["""System.Runtime.CompilerServices.CallerArgumentExpressionAttribute("x")"""], indexer.Parameters[1].GetAttributes().ToStrings());
            }
        }
 
        [Fact]
        public void CallerMemberName_SetterValueParam_ImplementationPart()
        {
            // Counterpart to test 'AttributeTests_CallerInfoAttributes.CallerMemberName_SetterValueParam'
            // There is no way in C# to call a setter without passing an argument for the value, so the CallerMemberName effectively does nothing.
            // It would be reasonable to also warn here about the CallerInfo attribute on implementation,
            // but this is a corner case that clearly won't work regardless of which part the attribute is on, so it's not a big deal that the warning is missing.
            // Verify that our checks for caller-info attributes on implementation part parameters behave gracefully here.
            var source = """
                using System;
                using System.Runtime.CompilerServices;
                using System.Runtime.InteropServices;
 
                partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                        c[1] = "1";
                    }
 
                    public partial string this[int x] { set; }
                    public partial string this[int x]
                    {
                        [param: Optional, DefaultParameterValue("0")]
                        [param: CallerMemberName]
                        set
                        {
                            Console.Write(value);
                        }
                    }
                }
                """;
 
            var verifier = CompileAndVerify(source, expectedOutput: "1");
            verifier.VerifyDiagnostics();
        }
 
        [Theory]
        [InlineData("[AllowNull] ", "")]
        [InlineData("", "[AllowNull] ")]
        public void AllowNull_Property(string defAttrs, string implAttrs)
        {
            var source = $$"""
                #nullable enable
 
                using System;
                using System.Diagnostics.CodeAnalysis;
 
                partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                        try
                        {
                            c.Prop = null; // no warning
                        }
                        catch
                        {
                            Console.Write(1);
                        }
                    }
 
                    {{defAttrs}}
                    public partial string Prop { get; set; }
 
                    {{implAttrs}}
                    public partial string Prop
                    {
                        get => "";
                        set
                        {
                            value.ToString(); // warning
                        }
                    }
                }
                """;
 
            var verifier = CompileAndVerify([source, AllowNullAttributeDefinition], expectedOutput: "1");
            verifier.VerifyDiagnostics(
                // (30,13): warning CS8602: Dereference of a possibly null reference.
                //             value.ToString(); // warning
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "value").WithLocation(30, 13));
        }
 
        [Theory]
        [InlineData("[AllowNull] ", "")]
        [InlineData("", "[AllowNull] ")]
        public void AllowNull_IndexerParam(string defAttrs, string implAttrs)
        {
            var source = $$"""
                #nullable enable
 
                using System;
                using System.Diagnostics.CodeAnalysis;
 
                partial class C
                {
                    public static void Main()
                    {
                        var c = new C();
                        try
                        {
                            _ = c[null]; // no warning
                        }
                        catch
                        {
                            Console.Write(1);
                        }
                    }
 
                    public partial string this[{{defAttrs}}string s] { get; }
                    public partial string this[{{implAttrs}}string s]
                    {
                        get
                        {
                            return s.ToString(); // https://github.com/dotnet/roslyn/issues/73484: missing a warning here
                        }
                    }
                }
                """;
 
            var verifier = CompileAndVerify([source, AllowNullAttributeDefinition], expectedOutput: "1");
            verifier.VerifyDiagnostics();
        }
 
        [Fact]
        public void Obsolete_01()
        {
            var source = """
                using System;
 
                partial class C
                {
                    [Obsolete]
                    public partial int Prop { get; }
 
                    public partial int Prop { get => M(); } // no diagnostic for use of obsolete member
 
                    [Obsolete]
                    int M() => 1;
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
        }
 
        [Fact]
        public void Obsolete_02()
        {
            var source = """
                using System;
 
                partial class C
                {
                    public partial int this[int x, int y = VALUE] { get; } // no diagnostic for use of obsolete const
 
                    [Obsolete]
                    public partial int this[int x, int y] => x;
 
                    [Obsolete]
                    public const int VALUE = 1;
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
        }
 
        [Fact]
        public void Obsolete_03()
        {
            var source = """
                using System;
 
                partial class C
                {
                    public partial int this[int x, int y = VALUE] { get; } // 1
 
                    public partial int this[int x, int y] { [Obsolete] get => x; }
 
                    [Obsolete]
                    public const int VALUE = 1;
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (5,44): warning CS0612: 'C.VALUE' is obsolete
                //     public partial int this[int x, int y = VALUE] { get; } // 1
                Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "VALUE").WithArguments("C.VALUE").WithLocation(5, 44));
        }
 
        [Theory]
        [CombinatorialData]
        public void Obsolete_04(
            [CombinatorialValues("public partial int Prop { [Obsolete] get; }", "[Obsolete] public partial int Prop { get; }")]
            string declPart,
            [CombinatorialValues("public partial int Prop { get => M(); }", "public partial int Prop => M();")]
            string implPart)
        {
            // note that one of the combinations here is redundant with Obsolete_01, but that seems fine,
            // as a failure in Obsolete_01 may be easier to triage.
            var source = $$"""
                using System;
 
                partial class C
                {
                    {{declPart}}
                    {{implPart}} // no diagnostic for use of obsolete member
 
                    [Obsolete]
                    int M() => 1;
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
        }
 
        [Theory]
        [InlineData("[Obsolete]", "")]
        [InlineData("", "[Obsolete]")]
        public void Obsolete_05(string defAttrs, string implAttrs)
        {
            var source = $$"""
                using System;
 
                partial class C
                {
                    {{defAttrs}}
                    public partial int this[int x] { get; }
 
                    {{implAttrs}}
                    public partial int this[int x] { get => x; }
                }
 
                class D
                {
                    void M()
                    {
                        var c = new C();
                        _ = c[1]; // 1
                    }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (17,13): warning CS0612: 'C.this[int]' is obsolete
                //         _ = c[1]; // 1
                Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "c[1]").WithArguments("C.this[int]").WithLocation(17, 13));
        }
 
        [Theory]
        [InlineData("[Obsolete]", "")]
        [InlineData("", "[Obsolete]")]
        public void Obsolete_06(string defAttrs, string implAttrs)
        {
            var source = $$"""
                using System;
 
                partial class C
                {
                    public partial int this[int x] { {{defAttrs}} get; }
 
                    public partial int this[int x] { {{implAttrs}} get => x; }
                }
 
                class D
                {
                    void M()
                    {
                        var c = new C();
                        _ = c[1]; // 1
                    }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (15,13): warning CS0612: 'C.this[int].get' is obsolete
                //         _ = c[1]; // 1
                Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "c[1]").WithArguments("C.this[int].get").WithLocation(15, 13));
        }
 
        [Fact]
        public void UnmanagedCallersOnly()
        {
            var source = $$"""
                using System.Runtime.InteropServices;
 
                partial class C
                {
                    [UnmanagedCallersOnly] // 1
                    public partial int P1 { get; }
                    public partial int P1 => 1;
 
                    public partial int P2 { get; }
                    [UnmanagedCallersOnly] // 2
                    public partial int P2 => 1;
 
                    public partial int P3 { [UnmanagedCallersOnly] get; } // 3
                    public partial int P3 => 1;
 
                    public partial int P4 { get; }
                    public partial int P4 { [UnmanagedCallersOnly] get => 1; } // 4
                }
                """;
 
            var comp = CreateCompilation([source, UnmanagedCallersOnlyAttributeDefinition]);
            comp.VerifyEmitDiagnostics(
                // (5,6): error CS0592: Attribute 'UnmanagedCallersOnly' is not valid on this declaration type. It is only valid on 'method' declarations.
                //     [UnmanagedCallersOnly] // 1
                Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "UnmanagedCallersOnly").WithArguments("UnmanagedCallersOnly", "method").WithLocation(5, 6),
                // (10,6): error CS0592: Attribute 'UnmanagedCallersOnly' is not valid on this declaration type. It is only valid on 'method' declarations.
                //     [UnmanagedCallersOnly] // 2
                Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "UnmanagedCallersOnly").WithArguments("UnmanagedCallersOnly", "method").WithLocation(10, 6),
                // (13,30): error CS8896: 'UnmanagedCallersOnly' can only be applied to ordinary static non-abstract, non-virtual methods or static local functions.
                //     public partial int P3 { [UnmanagedCallersOnly] get; } // 3
                Diagnostic(ErrorCode.ERR_UnmanagedCallersOnlyRequiresStatic, "UnmanagedCallersOnly").WithLocation(13, 30),
                // (17,30): error CS8896: 'UnmanagedCallersOnly' can only be applied to ordinary static non-abstract, non-virtual methods or static local functions.
                //     public partial int P4 { [UnmanagedCallersOnly] get => 1; } // 4
                Diagnostic(ErrorCode.ERR_UnmanagedCallersOnlyRequiresStatic, "UnmanagedCallersOnly").WithLocation(17, 30));
        }
 
        /// <remarks>See also <cref name="DocumentationCommentCompilerTests.PartialIndexer_Paramref_03"/></remarks>
        [Fact]
        public void IndexerParameterNameDifference()
        {
            var source = """
                using System;
 
                partial class C
                {
                    public partial int this[int p1] { get; set; }
                    public partial int this[int p2] { get => p2; set => p2.ToString(); }
 
                    static void Main()
                    {
                        var c = new C();
                        Console.Write(c[p1: 1]);
                    }
                }
                """;
 
            var verifier = CompileAndVerify(source, expectedOutput: "1", symbolValidator: verify, sourceSymbolValidator: verify);
            verifier.VerifyDiagnostics(
                // (6,24): warning CS9256: Partial property declarations 'int C.this[int p1]' and 'int C.this[int p2]' have signature differences.
                //     public partial int this[int p2] { get => p2; set { } }
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "this").WithArguments("int C.this[int p1]", "int C.this[int p2]").WithLocation(6, 24));
 
            void verify(ModuleSymbol module)
            {
                var indexer = module.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers.Single();
                Assert.Equal("p1", indexer.Parameters.Single().Name);
            }
        }
 
        /// <remarks>See also <cref name="DocumentationCommentCompilerTests.PartialIndexer_Paramref_03"/></remarks>
        [Fact]
        public void IndexerParameterNameDifference_Attributes()
        {
            var source = """
                using System;
 
                [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
                public class Attr(string s) : Attribute { } // 1 (unread parameter)
 
                partial class C
                {
                    [Attr(nameof(p1))]
                    [Attr(nameof(p2))] // 2
                    public partial int this[int p1]
                    {
                        get;
 
                        [param: Attr(nameof(p1))] // 3
                        [param: Attr(nameof(p2))]
                        set;
                    }
 
                    [Attr(nameof(p1))]
                    [Attr(nameof(p2))] // 4
                    public partial int this[int p2] // 5
                    {
                        get => p2;
 
                        [param: Attr(nameof(p1))] // 6
                        [param: Attr(nameof(p2))]
                        set => p2.ToString();
                    }
 
                    [Attr(nameof(p1))]
                    [Attr(nameof(p2))] // 7
                    public partial void M(
                        [Attr(nameof(p1))] // 8
                        [Attr(nameof(p2))]
                        int p1);
                    public partial void M( // 9
                        [Attr(nameof(p1))] // 10
                        [Attr(nameof(p2))]
                        int p2) { }
                }
                """;
 
            var verifier = CreateCompilation(source);
            verifier.VerifyDiagnostics(
                // (4,26): warning CS9113: Parameter 's' is unread.
                // public class Attr(string s) : Attribute { } // 1 (unread parameter)
                Diagnostic(ErrorCode.WRN_UnreadPrimaryConstructorParameter, "s").WithArguments("s").WithLocation(4, 26),
                // (9,18): error CS0103: The name 'p2' does not exist in the current context
                //     [Attr(nameof(p2))] // 2
                Diagnostic(ErrorCode.ERR_NameNotInContext, "p2").WithArguments("p2").WithLocation(9, 18),
                // (14,29): error CS0103: The name 'p1' does not exist in the current context
                //         [param: Attr(nameof(p1))] // 3
                Diagnostic(ErrorCode.ERR_NameNotInContext, "p1").WithArguments("p1").WithLocation(14, 29),
                // (20,18): error CS0103: The name 'p2' does not exist in the current context
                //     [Attr(nameof(p2))] // 4
                Diagnostic(ErrorCode.ERR_NameNotInContext, "p2").WithArguments("p2").WithLocation(20, 18),
                // (21,24): warning CS9256: Partial property declarations 'int C.this[int p1]' and 'int C.this[int p2]' have signature differences.
                //     public partial int this[int p2] // 5
                Diagnostic(ErrorCode.WRN_PartialPropertySignatureDifference, "this").WithArguments("int C.this[int p1]", "int C.this[int p2]").WithLocation(21, 24),
                // (25,29): error CS0103: The name 'p1' does not exist in the current context
                //         [param: Attr(nameof(p1))] // 6
                Diagnostic(ErrorCode.ERR_NameNotInContext, "p1").WithArguments("p1").WithLocation(25, 29),
                // (31,18): error CS0103: The name 'p2' does not exist in the current context
                //     [Attr(nameof(p2))] // 7
                Diagnostic(ErrorCode.ERR_NameNotInContext, "p2").WithArguments("p2").WithLocation(31, 18),
                // (33,22): error CS0103: The name 'p1' does not exist in the current context
                //         [Attr(nameof(p1))] // 8
                Diagnostic(ErrorCode.ERR_NameNotInContext, "p1").WithArguments("p1").WithLocation(33, 22),
                // (36,25): warning CS8826: Partial method declarations 'void C.M(int p1)' and 'void C.M(int p2)' have signature differences.
                //     public partial void M( // 9
                Diagnostic(ErrorCode.WRN_PartialMethodTypeDifference, "M").WithArguments("void C.M(int p1)", "void C.M(int p2)").WithLocation(36, 25),
                // (37,22): error CS0103: The name 'p1' does not exist in the current context
                //         [Attr(nameof(p1))] // 10
                Diagnostic(ErrorCode.ERR_NameNotInContext, "p1").WithArguments("p1").WithLocation(37, 22));
        }
 
        [Fact]
        public void BindExpressionInPropertyWithoutAccessors()
        {
            // Exercise an assertion in 'BinderFactoryVisitor.VisitAccessorDeclaration'.
            var source = """
                class C
                {
                    int X = 1;
                    public int P
                    {
                        Console.Write(X);
                    }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (3,9): warning CS0414: The field 'C.X' is assigned but its value is never used
                //     int X = 1;
                Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "X").WithArguments("C.X").WithLocation(3, 9),
                // (4,16): error CS0548: 'C.P': property or indexer must have at least one accessor
                //     public int P
                Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "P").WithArguments("C.P").WithLocation(4, 16),
                // (6,9): error CS1014: A get or set accessor expected
                //         Console.Write(X);
                Diagnostic(ErrorCode.ERR_GetOrSetExpected, "Console").WithLocation(6, 9),
                // (6,16): error CS1014: A get or set accessor expected
                //         Console.Write(X);
                Diagnostic(ErrorCode.ERR_GetOrSetExpected, ".").WithLocation(6, 16),
                // (6,17): error CS1014: A get or set accessor expected
                //         Console.Write(X);
                Diagnostic(ErrorCode.ERR_GetOrSetExpected, "Write").WithLocation(6, 17),
                // (6,22): error CS1513: } expected
                //         Console.Write(X);
                Diagnostic(ErrorCode.ERR_RbraceExpected, "(").WithLocation(6, 22),
                // (6,24): error CS8124: Tuple must contain at least two elements.
                //         Console.Write(X);
                Diagnostic(ErrorCode.ERR_TupleTooFewElements, ")").WithLocation(6, 24),
                // (6,25): error CS1519: Invalid token ';' in class, record, struct, or interface member declaration
                //         Console.Write(X);
                Diagnostic(ErrorCode.ERR_InvalidMemberDecl, ";").WithArguments(";").WithLocation(6, 25),
                // (8,1): error CS1022: Type or namespace definition, or end-of-file expected
                // }
                Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(8, 1));
 
            var tree = comp.SyntaxTrees[0];
            var model = comp.GetSemanticModel(tree);
            var node = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(name => name.ToString() == "X").Last();
            Assert.Equal(SyntaxKind.TupleElement, node.Parent!.Kind());
            var symbolInfo = model.GetSymbolInfo(node);
            Assert.Null(symbolInfo.Symbol);
            Assert.Empty(symbolInfo.CandidateSymbols);
        }
 
        [Fact]
        public void LangVersion_01()
        {
            var source = """
                partial class C
                {
                    public partial int P { get; set; }
                    public partial int P { get => 1; set { } }
 
                    public partial int this[int i] { get; }
                    public partial int this[int i] { get => i; }
                }
                """;
 
            var comp = CreateCompilation(source, parseOptions: TestOptions.Regular13);
            comp.VerifyEmitDiagnostics();
 
            comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
            comp.VerifyEmitDiagnostics(
                // (3,24): error CS8703: The modifier 'partial' is not valid for this item in C# 12.0. Please use language version '13.0' or greater.
                //     public partial int P { get; set; }
                Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P").WithArguments("partial", "12.0", "13.0").WithLocation(3, 24),
                // (4,24): error CS8703: The modifier 'partial' is not valid for this item in C# 12.0. Please use language version '13.0' or greater.
                //     public partial int P { get => 1; set { } }
                Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P").WithArguments("partial", "12.0", "13.0").WithLocation(4, 24),
                // (6,24): error CS8703: The modifier 'partial' is not valid for this item in C# 12.0. Please use language version '13.0' or greater.
                //     public partial int this[int i] { get; }
                Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("partial", "12.0", "13.0").WithLocation(6, 24),
                // (7,24): error CS8703: The modifier 'partial' is not valid for this item in C# 12.0. Please use language version '13.0' or greater.
                //     public partial int this[int i] { get => i; }
                Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("partial", "12.0", "13.0").WithLocation(7, 24));
        }
 
        [Fact]
        public void GetDeclaredSymbol_01()
        {
            var source = ("""
                partial class C
                {
                    public partial int Prop { get; }
                    public partial int Prop { get => 1; }
                }
                """.NormalizeLineEndings(), "Program.cs");
 
            var comp = CreateCompilation(source);
            var tree = comp.SyntaxTrees[0];
 
            var model = comp.GetSemanticModel(tree);
            var properties = tree.GetRoot().DescendantNodes().OfType<PropertyDeclarationSyntax>().ToArray();
            Assert.Equal(2, properties.Length);
 
            var defSymbol = model.GetDeclaredSymbol(properties[0])!;
            Assert.Equal("System.Int32 C.Prop { get; }", defSymbol.ToTestDisplayString());
 
            var implSymbol = model.GetDeclaredSymbol(properties[1])!;
            Assert.Equal("System.Int32 C.Prop { get; }", implSymbol.ToTestDisplayString());
 
            Assert.NotEqual(defSymbol, implSymbol);
            Assert.Same(implSymbol, defSymbol.PartialImplementationPart);
            Assert.Same(defSymbol, implSymbol.PartialDefinitionPart);
            Assert.True(defSymbol.IsPartialDefinition);
            Assert.False(implSymbol.IsPartialDefinition);
 
            // This is consistent with partial methods.
            Assert.Equal("SourceFile(Program.cs[43..47))", defSymbol.Locations.Single().ToString());
            Assert.Equal("SourceFile(Program.cs[81..85))", implSymbol.Locations.Single().ToString());
        }
 
        [Fact]
        public void GetDeclaredSymbol_02()
        {
            // Property contained in generic type. Check original definition and constructed symbols.
            var source = ("""
                partial class C<T>
                {
                    public partial int Prop { get; }
                    public partial int Prop { get => 1; }
                }
                """.NormalizeLineEndings(), "Program.cs");
 
            var comp = CreateCompilation(source);
            var tree = comp.SyntaxTrees[0];
 
            var model = comp.GetSemanticModel(tree);
            var properties = tree.GetRoot().DescendantNodes().OfType<PropertyDeclarationSyntax>().ToArray();
            Assert.Equal(2, properties.Length);
 
            var defSymbol = model.GetDeclaredSymbol(properties[0])!;
            Assert.Equal("System.Int32 C<T>.Prop { get; }", defSymbol.ToTestDisplayString());
 
            var implSymbol = model.GetDeclaredSymbol(properties[1])!;
            Assert.Equal("System.Int32 C<T>.Prop { get; }", implSymbol.ToTestDisplayString());
 
            Assert.NotEqual(defSymbol, implSymbol);
            Assert.Same(implSymbol, defSymbol.PartialImplementationPart);
            Assert.Same(defSymbol, implSymbol.PartialDefinitionPart);
 
            Assert.True(defSymbol.IsPartialDefinition);
            Assert.False(implSymbol.IsPartialDefinition);
 
            // This is consistent with partial methods.
            Assert.Equal("SourceFile(Program.cs[46..50))", defSymbol.Locations.Single().ToString());
            Assert.Equal("SourceFile(Program.cs[84..88))", implSymbol.Locations.Single().ToString());
 
            var intSymbol = comp.GetSpecialType(SpecialType.System_Int32);
            var cOfTSymbol = defSymbol.ContainingType!;
            var cOfIntSymbol = cOfTSymbol.Construct([intSymbol]);
 
            // Constructed symbols always return null/false from the partial-related public APIs
            var defOfIntSymbol = (IPropertySymbol)cOfIntSymbol.GetMember("Prop");
            Assert.Equal("System.Int32 C<System.Int32>.Prop { get; }", defOfIntSymbol.ToTestDisplayString());
            Assert.Null(defOfIntSymbol.PartialImplementationPart);
            Assert.False(defOfIntSymbol.IsPartialDefinition);
        }
 
        [Fact]
        public void GetDeclaredSymbol_03()
        {
            // Indexer
            var source = ("""
                partial class C
                {
                    public partial int this[int i] { get; }
                    public partial int this[int i] { get => 1; }
                }
                """.NormalizeLineEndings(), "Program.cs");
 
            var comp = CreateCompilation(source);
            var tree = comp.SyntaxTrees[0];
 
            var model = comp.GetSemanticModel(tree);
            var indexers = tree.GetRoot().DescendantNodes().OfType<IndexerDeclarationSyntax>().ToArray();
            Assert.Equal(2, indexers.Length);
 
            var defSymbol = model.GetDeclaredSymbol(indexers[0])!;
            Assert.Equal("System.Int32 C.this[System.Int32 i] { get; }", defSymbol.ToTestDisplayString());
 
            var implSymbol = model.GetDeclaredSymbol(indexers[1])!;
            Assert.Equal("System.Int32 C.this[System.Int32 i] { get; }", implSymbol.ToTestDisplayString());
 
            Assert.NotEqual(defSymbol, implSymbol);
            Assert.Same(implSymbol, defSymbol.PartialImplementationPart);
            Assert.Same(defSymbol, implSymbol.PartialDefinitionPart);
 
            Assert.True(defSymbol.IsPartialDefinition);
            Assert.False(implSymbol.IsPartialDefinition);
 
            // This is consistent with partial methods.
            Assert.Equal("SourceFile(Program.cs[43..47))", defSymbol.Locations.Single().ToString());
            Assert.Equal("SourceFile(Program.cs[88..92))", implSymbol.Locations.Single().ToString());
        }
 
        [Fact]
        public void GetDeclaredSymbol_04()
        {
            // Indexer parameter
            var source = ("""
                partial class C
                {
                    public partial int this[int i] { get; }
                    public partial int this[int i] { get => 1; }
                }
                """.NormalizeLineEndings(), "Program.cs");
 
            var comp = CreateCompilation(source);
            var tree = comp.SyntaxTrees[0];
 
            var model = comp.GetSemanticModel(tree);
            var parameters = tree.GetRoot().DescendantNodes().OfType<ParameterSyntax>().ToArray();
            Assert.Equal(2, parameters.Length);
 
            var defSymbol = model.GetDeclaredSymbol(parameters[0])!;
            Assert.Equal("System.Int32 i", defSymbol.ToTestDisplayString());
 
            var implSymbol = model.GetDeclaredSymbol(parameters[1])!;
            Assert.Equal("System.Int32 i", implSymbol.ToTestDisplayString());
 
            Assert.NotEqual(defSymbol, implSymbol);
            Assert.Same(implSymbol, ((IPropertySymbol)defSymbol.ContainingSymbol).PartialImplementationPart!.Parameters[0]);
            Assert.Same(defSymbol, ((IPropertySymbol)implSymbol.ContainingSymbol).PartialDefinitionPart!.Parameters[0]);
 
            // This is consistent with partial methods.
            Assert.Equal("SourceFile(Program.cs[52..53))", defSymbol.Locations.Single().ToString());
            Assert.Equal("SourceFile(Program.cs[97..98))", implSymbol.Locations.Single().ToString());
        }
 
        [Fact]
        public void OnlyOneAccessorHasBodyOnImplementation()
        {
            var source = """
                partial class C
                {
                    public partial int Prop1 { get; set; }
                    public partial int Prop1 { get => 1; set; }
 
                    public partial int Prop2 { get; set; }
                    public partial int Prop2 { get; set { } }
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (4,32): warning CS9266: The 'get' accessor of property 'C.Prop1' should use 'field' because the other accessor is using it.
                //     public partial int Prop1 { get => 1; set; }
                Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.Prop1").WithLocation(4, 32),
                // (7,37): warning CS9266: The 'set' accessor of property 'C.Prop2' should use 'field' because the other accessor is using it.
                //     public partial int Prop2 { get; set { } }
                Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.Prop2").WithLocation(7, 37));
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/74679")]
        public void WRN_SequentialOnPartialClass_NotReportedForPartialProperty_01()
        {
            var source = """
                partial struct S
                {
                    partial int I { get; }
                }
 
                partial struct S
                {
                    public S() => i = 42;
                    private readonly int i;
                    partial int I => i;
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/74679")]
        public void WRN_SequentialOnPartialClass_NotReportedForPartialProperty_02()
        {
            var source = """
                partial struct S
                {
                    partial int I { get; }
                }
 
                partial struct S
                {
                    partial int I => i;
                }
 
                partial struct S
                {
                    public S() => i = 42;
                    private readonly int i;
                }
                """;
 
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
        }
    }
}