File: Semantics\ExtensionOperatorsTests.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Emit3\Microsoft.CodeAnalysis.CSharp.Emit3.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Emit3.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.
#nullable disable
 
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
using static Microsoft.CodeAnalysis.CSharp.UnitTests.UserDefinedCompoundAssignmentOperatorsTests;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics
{
    [CompilerTrait(CompilerFeature.Extensions)]
    public class ExtensionOperatorsTests : CompilingTestBase
    {
        [Fact]
        public void Conversions_001_Declaration()
        {
            var src = $$$"""
static class Extensions
{
    extension(S1)
    {
        public static implicit operator int(S1 x) => 0;
    }
 
    extension(S2)
    {
        public static explicit operator int(S2 x) => 0;
    }
}
 
struct S1
{}
 
struct S2
{}
 
static class C1
{
    static void Test()
    {
        var s1 = new S1();
        var i1 = (int)s1;
 
        var s2 = new S2();
        var i2 = (int)s2;
    }
}
""";
            var comp = CreateCompilation(src);
            comp.VerifyEmitDiagnostics(
                // (5,41): error CS9282: This member is not allowed in an extension block
                //         public static implicit operator int(S1 x) => 0;
                Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "int").WithLocation(5, 41),
                // (10,41): error CS9282: This member is not allowed in an extension block
                //         public static explicit operator int(S2 x) => 0;
                Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "int").WithLocation(10, 41),
                // (25,18): error CS0030: Cannot convert type 'S1' to 'int'
                //         var i1 = (int)s1;
                Diagnostic(ErrorCode.ERR_NoExplicitConv, "(int)s1").WithArguments("S1", "int").WithLocation(25, 18),
                // (28,18): error CS0030: Cannot convert type 'S2' to 'int'
                //         var i2 = (int)s2;
                Diagnostic(ErrorCode.ERR_NoExplicitConv, "(int)s2").WithArguments("S2", "int").WithLocation(28, 18)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Unary_001_Declaration([CombinatorialValues("+", "-", "!", "~")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x) => default;
        public static S1? operator {{{op}}}(S1? x) => default;
    }
}
 
static class Extensions2
{
    extension(S1)
    {
        public static S2 operator {{{op}}}(S1 x) => default;
        public static S1 operator {{{op}}}(S2 x) => default;
    }
}
 
static class Extensions3
{
    extension(S1)
    {
        public static void operator {{{op}}}(S1 x) {}
    }
}
 
static class Extensions4
{
    extension(S1)
    {
        static S1 operator {{{op}}}(S1 x) => default;
    }
 
    extension(S2)
    {
        public S2 operator {{{op}}}(S2 x) => default;
    }
 
    extension(C1)
    {
        public static S1 operator {{{op}}}(C1 x) => default;
    }
}
 
static class Extensions5
{
    extension(S1?)
    {
        public static S1 operator {{{op}}}(S1 x) => default;
        public static S2 operator {{{op}}}(S1? x) => default;
    }
}
 
struct S1
{}
 
struct S2
{}
 
static class C1
{}
""";
            var comp = CreateCompilation(src);
            comp.VerifyEmitDiagnostics(
                // (6,36): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static S1? operator +(S1? x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, op).WithLocation(6, 36),
                // (15,35): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static S1 operator +(S2 x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, op).WithLocation(15, 35),
                // (23,37): error CS0590: User-defined operators cannot return void
                //         public static void operator +(S1 x) {}
                Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, op).WithLocation(23, 37),
                // (31,28): error CS0558: User-defined operator 'Extensions4.extension(S1).operator +(S1)' must be declared static and public
                //         static S1 operator +(S1 x) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, op).WithArguments("Extensions4.extension(S1).operator " + op + "(S1)").WithLocation(31, 28),
                // (36,28): error CS0558: User-defined operator 'Extensions4.extension(S2).operator +(S2)' must be declared static and public
                //         public S2 operator +(S2 x) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, op).WithArguments("Extensions4.extension(S2).operator " + op + "(S2)").WithLocation(36, 28),
                // (41,35): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public static S1 operator +(C1 x) => default;
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, op).WithLocation(41, 35),
                // (41,37): error CS0721: 'C1': static types cannot be used as parameters
                //         public static S1 operator +(C1 x) => default;
                Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C1").WithArguments("C1").WithLocation(41, 37),
                // (49,35): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static S1 operator +(S1 x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, op).WithLocation(49, 35)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Unary_002_Declaration([CombinatorialValues("++", "--")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x) => default;
        public static S1? operator {{{op}}}(S1? x) => default;
    }
}
 
static class Extensions2
{
    extension(S1)
    {
        public static S2 operator {{{op}}}(S1 x) => default;
        public static S1 operator {{{op}}}(S2 x) => default;
    }
}
 
static class Extensions3
{
    extension(S1)
    {
        static S1 operator {{{op}}}(S1 x) => default;
    }
 
    extension(S2)
    {
        public S2 operator {{{op}}}(S2 x) => default;
    }
 
    extension(C1)
    {
        public static C1 operator {{{op}}}(C1 x) => default;
    }
}
 
static class Extensions4
{
    extension(S1?)
    {
        public static S1 operator {{{op}}}(S1 x) => default;
        public static S1 operator {{{op}}}(S1? x) => default;
    }
}
 
static class Extensions5
{
    extension(S1?)
    {
        public static S1? operator {{{op}}}(S1? x) => default;
    }
}
 
struct S1
{}
 
struct S2
{}
 
static class C1
{}
""";
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (6,36): error CS9318: The parameter type for ++ or -- operator must be the extended type.
                //         public static S1? operator ++(S1? x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionIncDecSignature, op).WithLocation(6, 36),
                // (14,35): error CS0448: The return type for ++ or -- operator must match the parameter type or be derived from the parameter type
                //         public static S2 operator ++(S1 x) => default;
                Diagnostic(ErrorCode.ERR_BadIncDecRetType, op).WithLocation(14, 35),
                // (15,35): error CS9318: The parameter type for ++ or -- operator must be the extended type.
                //         public static S1 operator ++(S2 x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionIncDecSignature, op).WithLocation(15, 35),
                // (23,28): error CS0558: User-defined operator 'Extensions3.extension(S1).operator ++(S1)' must be declared static and public
                //         static S1 operator ++(S1 x) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, op).WithArguments("Extensions3.extension(S1).operator " + op + "(S1)").WithLocation(23, 28),
                // (28,28): error CS0558: User-defined operator 'Extensions3.extension(S2).operator ++(S2)' must be declared static and public
                //         public S2 operator ++(S2 x) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, op).WithArguments("Extensions3.extension(S2).operator " + op + "(S2)").WithLocation(28, 28),
                // (33,23): error CS0722: 'C1': static types cannot be used as return types
                //         public static C1 operator ++(C1 x) => default;
                Diagnostic(ErrorCode.ERR_ReturnTypeIsStaticClass, "C1").WithArguments("C1").WithLocation(33, 23),
                // (33,35): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public static C1 operator ++(C1 x) => default;
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, op).WithLocation(33, 35),
                // (33,38): error CS0721: 'C1': static types cannot be used as parameters
                //         public static C1 operator ++(C1 x) => default;
                Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C1").WithArguments("C1").WithLocation(33, 38),
                // (41,35): error CS9318: The parameter type for ++ or -- operator must be the extended type.
                //         public static S1 operator ++(S1 x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionIncDecSignature, op).WithLocation(41, 35),
                // (42,35): error CS0448: The return type for ++ or -- operator must match the parameter type or be derived from the parameter type
                //         public static S1 operator ++(S1? x) => default;
                Diagnostic(ErrorCode.ERR_BadIncDecRetType, op).WithLocation(42, 35)
                );
        }
 
        [Fact]
        public void Unary_003_Declaration()
        {
            var src = """
static class Extensions1
{
    extension(S1)
    {
#line 100
        public static bool operator true(S1 x) => default;
        public static bool operator false(S1 x) => default;
        public static bool operator true(S1? x) => default;
        public static bool operator false(S1? x) => default;
    }
}
 
static class Extensions2
{
    extension(S1)
    {
#line 200
        public static bool operator true(S1 x) => default;
    }
 
    extension(S1)
    {
#line 300
        public static bool operator false(S1 x) => default;
    }
}
 
static class Extensions3
{
    extension(S1)
    {
#line 400
        public static bool operator true(S1 x) => default;
    }
 
    extension(S2)
    {
        public static bool operator false(S2 x) => default;
    }
}
 
static class Extensions4
{
    extension(S1)
    {
#line 500
        public static S1 operator true(S1 x) => default;
    }
}
 
static class Extensions5
{
    extension(S1)
    {
#line 600
        public static bool operator true(S2 x) => default;
        public static bool operator false(S2 x) => default;
    }
}
 
static class Extensions6
{
    extension(S1)
    {
#line 700
        static bool operator true(S1 x) => default;
        public bool operator false(S1 x) => default;
    }
 
    extension(C1)
    {
#line 800
        public static bool operator true(C1 x) => default;
        public static bool operator false(C1 x) => default;
    }
}
 
static class Extensions7
{
    extension(S1?)
    {
#line 900
        public static bool operator true(S1 x) => default;
        public static bool operator false(S1 x) => default;
        public static bool operator true(S1? x) => default;
        public static bool operator false(S1? x) => default;
    }
}
 
struct S1
{}
 
struct S2
{}
 
static class C1
{}
""";
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (102,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator true(S1? x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "true").WithLocation(102, 37),
                // (103,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator false(S1? x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "false").WithLocation(103, 37),
                // (400,37): error CS0216: The operator 'Extensions3.extension(S1).operator true(S1)' requires a matching operator 'false' to also be defined
                //         public static bool operator true(S1 x) => default;
                Diagnostic(ErrorCode.ERR_OperatorNeedsMatch, "true").WithArguments("Extensions3.extension(S1).operator true(S1)", "false").WithLocation(400, 37),
                // (405,37): error CS0216: The operator 'Extensions3.extension(S2).operator false(S2)' requires a matching operator 'true' to also be defined
                //         public static bool operator false(S2 x) => default;
                Diagnostic(ErrorCode.ERR_OperatorNeedsMatch, "false").WithArguments("Extensions3.extension(S2).operator false(S2)", "true").WithLocation(405, 37),
                // (500,35): error CS0215: The return type of operator True or False must be bool
                //         public static S1 operator true(S1 x) => default;
                Diagnostic(ErrorCode.ERR_OpTFRetType, "true").WithLocation(500, 35),
                // (500,35): error CS0216: The operator 'Extensions4.extension(S1).operator true(S1)' requires a matching operator 'false' to also be defined
                //         public static S1 operator true(S1 x) => default;
                Diagnostic(ErrorCode.ERR_OperatorNeedsMatch, "true").WithArguments("Extensions4.extension(S1).operator true(S1)", "false").WithLocation(500, 35),
                // (600,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator true(S2 x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "true").WithLocation(600, 37),
                // (601,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator false(S2 x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "false").WithLocation(601, 37),
                // (700,30): error CS0558: User-defined operator 'Extensions6.extension(S1).operator true(S1)' must be declared static and public
                //         static bool operator true(S1 x) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, "true").WithArguments("Extensions6.extension(S1).operator true(S1)").WithLocation(700, 30),
                // (701,30): error CS0558: User-defined operator 'Extensions6.extension(S1).operator false(S1)' must be declared static and public
                //         public bool operator false(S1 x) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, "false").WithArguments("Extensions6.extension(S1).operator false(S1)").WithLocation(701, 30),
                // (800,37): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public static bool operator true(C1 x) => default;
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, "true").WithLocation(800, 37),
                // (800,42): error CS0721: 'C1': static types cannot be used as parameters
                //         public static bool operator true(C1 x) => default;
                Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C1").WithArguments("C1").WithLocation(800, 42),
                // (801,37): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public static bool operator false(C1 x) => default;
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, "false").WithLocation(801, 37),
                // (801,43): error CS0721: 'C1': static types cannot be used as parameters
                //         public static bool operator false(C1 x) => default;
                Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C1").WithArguments("C1").WithLocation(801, 43),
                // (900,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator true(S1 x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "true").WithLocation(900, 37),
                // (901,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator false(S1 x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "false").WithLocation(901, 37)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Unary_004_Declaration([CombinatorialValues("+", "-", "!", "~")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x) => default;
    }
}
 
public struct S1
{}
""";
            var comp = CreateCompilation(src);
            CompileAndVerify(comp, symbolValidator: verify, sourceSymbolValidator: verify).VerifyDiagnostics();
 
            void verify(ModuleSymbol m)
            {
                var name = UnaryOperatorName(op);
                var method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + name);
 
                AssertEx.Equal("Extensions1." + name + "(S1)", method.ToDisplayString());
                Assert.Equal(MethodKind.Ordinary, method.MethodKind);
                Assert.True(method.IsStatic);
                Assert.False(method.IsExtensionMethod);
                Assert.False(method.HasSpecialName);
                Assert.False(method.HasRuntimeSpecialName);
                Assert.False(method.HasUnsupportedMetadata);
            }
        }
 
        private static string UnaryOperatorName(string op)
        {
            return OperatorFacts.UnaryOperatorNameFromSyntaxKind(SyntaxFactory.ParseToken(op).Kind(), isChecked: false);
        }
 
        [Theory]
        [CombinatorialData]
        public void Unary_005_Declaration([CombinatorialValues("++", "--")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x) => default;
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src);
            CompileAndVerify(comp, symbolValidator: verify, sourceSymbolValidator: verify).VerifyDiagnostics();
 
            void verify(ModuleSymbol m)
            {
                var name = UnaryOperatorName(op);
                var method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + name);
 
                AssertEx.Equal("Extensions1." + name + "(S1)", method.ToDisplayString());
                Assert.Equal(MethodKind.Ordinary, method.MethodKind);
                Assert.True(method.IsStatic);
                Assert.False(method.IsExtensionMethod);
                Assert.False(method.HasSpecialName);
                Assert.False(method.HasRuntimeSpecialName);
                Assert.False(method.HasUnsupportedMetadata);
            }
        }
 
        [Fact]
        public void Unary_006_Declaration()
        {
            var src = """
static class Extensions1
{
    extension(S1)
    {
        public static bool operator true(S1 x) => default;
        public static bool operator false(S1 x) => default;
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src);
            CompileAndVerify(comp, symbolValidator: verify, sourceSymbolValidator: verify).VerifyDiagnostics();
 
            void verify(ModuleSymbol m)
            {
                var method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + WellKnownMemberNames.TrueOperatorName);
                AssertEx.Equal("Extensions1." + WellKnownMemberNames.TrueOperatorName + "(S1)", method.ToDisplayString());
                verifyMethod(method);
 
                method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + WellKnownMemberNames.FalseOperatorName);
                AssertEx.Equal("Extensions1." + WellKnownMemberNames.FalseOperatorName + "(S1)", method.ToDisplayString());
                verifyMethod(method);
            }
 
            static void verifyMethod(MethodSymbol method)
            {
                Assert.Equal(MethodKind.Ordinary, method.MethodKind);
                Assert.True(method.IsStatic);
                Assert.False(method.IsExtensionMethod);
                Assert.False(method.HasSpecialName);
                Assert.False(method.HasRuntimeSpecialName);
                Assert.False(method.HasUnsupportedMetadata);
            }
        }
 
        [Theory]
        [CombinatorialData]
        public void Unary_007_Declaration([CombinatorialValues("+", "-", "!", "~", "++", "--")] string op, [CombinatorialValues("virtual", "abstract", "new", "override", "sealed", "readonly", "extern")] string modifier)
        {
            var src = $$$"""
static class Extensions1
{
    extension(S1)
    {
        {{{modifier}}}
        public static S1 operator {{{op}}}(S1 x) => default;
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src);
            comp.VerifyEmitDiagnostics(
                // (6,35): error CS0106: The modifier 'abstract' is not valid for this item
                //         public static S1 operator !(S1 x) => default;
                Diagnostic(ErrorCode.ERR_BadMemberFlag, op).WithArguments(modifier).WithLocation(6, 35)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Unary_008_Declaration([CombinatorialValues("virtual", "abstract", "new", "override", "sealed", "readonly", "extern")] string modifier)
        {
            var src = $$$"""
static class Extensions1
{
    extension(S1)
    {
        {{{modifier}}}
        public static bool operator true(S1 x) => default;
 
        {{{modifier}}}
        public static bool operator false(S1 x) => default;
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src);
            comp.VerifyEmitDiagnostics(
                // (6,37): error CS0106: The modifier 'abstract' is not valid for this item
                //         public static bool operator true(S1 x) => default;
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "true").WithArguments(modifier).WithLocation(6, 37),
                // (9,37): error CS0106: The modifier 'abstract' is not valid for this item
                //         public static bool operator false(S1 x) => default;
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "false").WithArguments(modifier).WithLocation(9, 37)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Unary_009_Declaration([CombinatorialValues("-", "++", "--")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(S1)
    {
        public static S1 operator checked {{{op}}}(S1 x) => default;
        public static S1 operator {{{op}}}(S1 x) => default;
    }
}
 
static class Extensions2
{
    extension(S1)
    {
#line 100
        public static S1 operator checked {{{op}}}(S1 x) => default;
    }
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x) => default;
    }
}
 
static class Extensions3
{
    extension(S1)
    {
        public static S1 operator checked {{{op}}}(S1 x) => default;
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src);
            comp.VerifyEmitDiagnostics(
                // (112,43): error CS9025: The operator 'Extensions3.extension(S1).operator checked ++(S1)' requires a matching non-checked version of the operator to also be defined
                //         public static S1 operator checked ++(S1 x) => default;
                Diagnostic(ErrorCode.ERR_CheckedOperatorNeedsMatch, op).WithArguments("Extensions3.extension(S1).operator checked " + op + "(S1)").WithLocation(112, 43)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Unary_010_Consumption(bool fromMetadata)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            return new S1 { F = x.F + 1 };
        }
    }
}
 
public struct S1
{
    public int F;
}
""";
 
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1() { F = 101 };
        var s2 = +s1;
        System.Console.Write(":");
        System.Console.Write(s1.F);
        System.Console.Write(":");
        System.Console.Write(s2.F);
    }
}
""";
 
            var comp1 = CreateCompilation(src1);
            var comp1Ref = fromMetadata ? comp1.EmitToImageReference() : comp1.ToMetadataReference();
 
            var comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:101:102").VerifyDiagnostics();
 
            var tree = comp2.SyntaxTrees.First();
            var model = comp2.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(S1).operator +(S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:101:102").VerifyDiagnostics();
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            comp2.VerifyEmitDiagnostics(
                // (6,18): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                //         var s2 = +s1;
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "+s1").WithArguments("extensions").WithLocation(6, 18)
                );
 
            var src3 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        Extensions1.op_UnaryPlus(s1);
    }
}
""";
            var comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp3, expectedOutput: "operator1:0").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp3, expectedOutput: "operator1:0").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            CompileAndVerify(comp3, expectedOutput: "operator1:0").VerifyDiagnostics();
 
            var src4 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1.op_UnaryPlus();
        S1.op_UnaryPlus(s1);
    }
}
""";
            var comp4 = CreateCompilation(src4, references: [comp1Ref]);
            comp4.VerifyEmitDiagnostics(
                // (6,12): error CS1061: 'S1' does not contain a definition for 'op_UnaryPlus' and no accessible extension method 'op_UnaryPlus' accepting a first argument of type 'S1' could be found (are you missing a using directive or an assembly reference?)
                //         s1.op_UnaryPlus();
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "op_UnaryPlus").WithArguments("S1", "op_UnaryPlus").WithLocation(6, 12),
                // (7,12): error CS0117: 'S1' does not contain a definition for 'op_UnaryPlus'
                //         S1.op_UnaryPlus(s1);
                Diagnostic(ErrorCode.ERR_NoSuchMember, "op_UnaryPlus").WithArguments("S1", "op_UnaryPlus").WithLocation(7, 12)
                );
        }
 
        [Fact]
        public void Unary_011_Consumption_PredefinedComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S2 x) => throw null;
    }
}
 
public struct S2
{
    public static implicit operator int(S2 x)
    {
        System.Console.Write("operator2");
        return 0;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        int x = +s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("int.operator +(int)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("System.Int32", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Unary_012_Consumption_NonExtensionComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S2 x) => throw null;
    }
}
 
public struct S2
{
    public static S2 operator +(S2 x)
    {
        System.Console.Write("operator2");
        return x;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = +s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("S2.operator +(S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Unary_013_Consumption_ScopeByScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(S1)
        {
            public static S1 operator +(S1 x)
            {
                System.Console.Write("operator1");
                return x;
            }
        }
    }
 
    namespace NS2
    {
        public static class Extensions3
        {
            extension(S2)
            {
                public static S2 operator +(S2 x) => throw null;
            }
        }
 
        class Program
        {
            static void Main()
            {
                var s1 = new S1();
                _ = +s1;
            }
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("NS1.Extensions2.extension(S1).operator +(S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Unary_014_Consumption_NonExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1
{
    public static I1 operator -(I1 x) => x;
}
 
public interface I3
{
    public static I3 operator -(I3 x) => x;
}
 
public interface I4 : I1, I3
{
}
 
public interface I2 : I4
{
}
 
public static class Extensions1
{
    extension(I2)
    {
        public static I2 operator -(I2 x) => x;
    }
}
 
class Test2 : I2
{
    static void Main()
    {
        I2 x = new Test2();
        var y = -x;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (32,17): error CS0035: Operator '-' is ambiguous on an operand of type 'I2'
                //         var y = -x;
                Diagnostic(ErrorCode.ERR_AmbigUnaryOp, "-x").WithArguments("-", "I2").WithLocation(32, 17)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("I1.operator -(I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("I3.operator -(I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/78830")]
        public void Unary_015_Consumption_ExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1;
public interface I3;
public interface I4 : I1, I3;
public interface I2 : I4;
 
public static class Extensions1
{
    extension(I2)
    {
        public static I2 operator -(I2 x) => x;
    }
}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(I1)
        {
            public static I1 operator -(I1 x) => x;
        }
 
        extension(I3)
        {
            public static I3 operator -(I3 x) => x;
        }
    }
 
    class Test2 : I2
    {
        static void Main()
        {
            I2 x = new Test2();
            var y = -x;
        }
    }
}
""";
 
            var comp = CreateCompilation(src);
 
            // https://github.com/dotnet/roslyn/issues/78830: We might want to include more information into the error. Like what methods conflict.
            comp.VerifyEmitDiagnostics(
                // (34,21): error CS0035: Operator '-' is ambiguous on an operand of type 'I2'
                //             var y = -x;
                Diagnostic(ErrorCode.ERR_AmbigUnaryOp, "-x").WithArguments("-", "I2").WithLocation(34, 21)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("NS1.Extensions2.extension(I1).operator -(I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("NS1.Extensions2.extension(I3).operator -(I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Unary_016_Consumption_Lifted()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x)
        {
            System.Console.Write("operator1");
            return new S1 { F = x.F + 1 };
        }
    }
}
 
public struct S1
{
    public int F;
}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1() { F = 101 };
        var s2 = +s1;
        System.Console.Write(":");
        System.Console.Write(s2.Value.F);
        System.Console.Write(":");
        s1 = null;
        s2 = +s1;
        System.Console.Write(s2?.F ?? -1);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:102:-1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_017_Consumption_LiftedIsWorse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x) => throw null;
    }
    extension(S1?)
    {
        public static S1? operator +(S1? x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        _ = +s1;
        System.Console.Write(":");
        s1 = null;
        _ = +s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_018_Consumption_ExtendedTypeIsNullable()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1?)
    {
        public static S1? operator +(S1? x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = +s1;
        Extensions1.op_UnaryPlus(s1);
 
        S1? s2 = new S1();
        _ = +s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (21,13): error CS0023: Operator '+' cannot be applied to operand of type 'S1'
                //         _ = +s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "+s1").WithArguments("+", "S1").WithLocation(21, 13)
                );
        }
 
        [Fact]
        public void Unary_019_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S2 x) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S2(S1 x) => default;
}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = +s1;
        Extensions1.op_UnaryPlus(s1);
 
        S1? s2 = new S1();
        _ = +s2;
        Extensions1.op_UnaryPlus(s2);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (22,13): error CS0023: Operator '+' cannot be applied to operand of type 'S1'
                //         _ = +s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "+s1").WithArguments("+", "S1").WithLocation(22, 13),
                // (26,13): error CS0023: Operator '+' cannot be applied to operand of type 'S1?'
                //         _ = +s2;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "+s2").WithArguments("+", "S1?").WithLocation(26, 13),
                // (27,34): error CS1503: Argument 1: cannot convert from 'S1?' to 'S2'
                //         Extensions1.op_UnaryPlus(s2);
                Diagnostic(ErrorCode.ERR_BadArgType, "s2").WithArguments("1", "S1?", "S2").WithLocation(27, 34)
                );
        }
 
        [Fact]
        public void Unary_020_Consumption_Generic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(S1<T>) where T : struct
    {
        public static S1<T> operator +(S1<T> x)
        {
            System.Console.Write(typeof(T).ToString());
            return x;
        }
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1<int>();
        s1 = +s1;
        Extensions1.op_UnaryPlus(s1);
 
        S1<int>? s2 = new S1<int>();
        _ = (+s2).GetValueOrDefault();
        s2 = null;
        System.Console.Write(":");
        _ = (+s2).GetValueOrDefault();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "System.Int32System.Int32System.Int32:").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_020_Consumption_Generic_Worse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(S1<T>)
    {
        public static S1<T> operator +(S1<T> x)
        {
            System.Console.Write("[S1<T>]");
            return x;
        }
    }
 
    extension<T>(S1<T>?)
    {
        public static S1<T>? operator +(S1<T>? x)
        {
            System.Console.Write("[S1<T>?]");
            return x;
        }
    }
 
    extension(S1<int>)
    {
        public static S1<int> operator +(S1<int> x)
        {
            System.Console.Write("[S1<int>]");
            return x;
        }
    }
 
    extension<T>(S2<T>)
    {
        public static S2<T> operator +(in S2<T> x) => throw null;
 
        public static S2<T> operator +(S2<T> x)
        {
            System.Console.Write("[S2<T>]");
            return x;
        }
    }
 
    extension(S2<int>)
    {
        public static S2<int> operator +(in S2<int> x)
        {
            System.Console.Write("[in S2<int>]");
            return x;
        }
    }
}
 
public struct S1<T>
{}
 
public struct S2<T>
{}
 
class Program
{
    static void Main()
    {
        var s11 = new S1<int>();
        s11 = +s11;
        Extensions1.op_UnaryPlus(s11);
 
        System.Console.WriteLine();
 
        var s12 = new S1<byte>();
        s12 = +s12;
        Extensions1.op_UnaryPlus(s12);
 
        System.Console.WriteLine();
 
        var s21 = new S2<int>();
        s21 = +s21;
        Extensions1.op_UnaryPlus(s21);
 
        System.Console.WriteLine();
 
        var s22 = new S2<byte>();
        s22 = +s22;
        Extensions1.op_UnaryPlus(s22);
 
        System.Console.WriteLine();
 
        S1<int>? s13 = new S1<int>();
        s13 = +s13;
        s13 = null;
        s13 = +s13;
 
        System.Console.WriteLine();
 
        S1<byte>? s14 = new S1<byte>();
        s14 = +s14;
        s14 = null;
        s14 = +s14;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: @"
[S1<int>][S1<int>]
[S1<T>][S1<T>]
[in S2<int>][in S2<int>]
[S2<T>][S2<T>]
[S1<int>]
[S1<T>?][S1<T>?]
").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_021_Consumption_Generic_ConstraintsViolation()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(S1<T>) where T : class
    {
        public static S1<T> operator +(S1<T> x) => throw null;
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1<int>();
        _ = +s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (17,13): error CS0023: Operator '+' cannot be applied to operand of type 'S1<int>'
                //         _ = +s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "+s1").WithArguments("+", "S1<int>").WithLocation(17, 13)
                );
        }
 
        [Fact]
        public void Unary_022_Consumption_OverloadResolutionPriority()
        {
            var src = $$$"""
using System.Runtime.CompilerServices;
 
public static class Extensions1
{
    extension(C1)
    {
        [OverloadResolutionPriority(1)]
        public static C1 operator +(C1 x)
        {
            System.Console.Write("C1");
            return x;
        }
    }
    extension(C2)
    {
        public static C2 operator +(C2 x)
        {
            System.Console.Write("C2");
            return x;
        }
    }
    extension(C3)
    {
        public static C3 operator +(C3 x)
        {
            System.Console.Write("C3");
            return x;
        }
    }
    extension(C4)
    {
        public static C4 operator +(C4 x)
        {
            System.Console.Write("C4");
            return x;
        }
    }
}
 
public class C1;
public class C2 : C1;
 
public class C3;
public class C4 : C3;
 
class Program
{
    static void Main()
    {
        var c2 = new C2();
        _ = +c2;
        var c4 = new C4();
        _ = +c4;
    }
}
""";
 
            var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition], options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "C1C4").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_023_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x)
        {
            System.Console.Write("regular");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = -c1;
 
        checked
        {
            _ = -c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularregular").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_023_Consumption_Checked_CheckedFormNotSupported()
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator +(C1 x) => throw null;
        public static C1 operator checked +(C1 x) => throw null;
    }
}
 
public class C1;
""";
 
            var comp1 = CreateCompilation(src1);
            comp1.VerifyEmitDiagnostics(
                // (6,35): error CS9023: User-defined operator '+' cannot be declared checked
                //         public static C1 operator checked +(C1 x) => throw null;
                Diagnostic(ErrorCode.ERR_OperatorCantBeChecked, "checked").WithArguments("+").WithLocation(6, 35),
                // (6,43): error CS0111: Type 'Extensions1' already defines a member called 'op_UnaryPlus' with the same parameter types
                //         public static C1 operator checked +(C1 x) => throw null;
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "+").WithArguments("op_UnaryPlus", "Extensions1").WithLocation(6, 43)
                );
 
            var src2 = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator +(C1 x)
        {
            System.Console.Write("regular");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = +c1;
 
        checked
        {
            _ = +c1;
        }
    }
}
""";
 
            var comp2 = CreateCompilation(src2, options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "regularregular").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_024_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x)
        {
            System.Console.Write("regular");
            return x;
        }
        public static C1 operator checked -(C1 x)
        {
            System.Console.Write("checked");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = -c1;
 
        checked
        {
            _ = -c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_025_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x)
        {
            System.Console.Write("regular");
            return x;
        }
    }
    extension(C1)
    {
        public static C1 operator checked -(C1 x)
        {
            System.Console.Write("checked");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = -c1;
 
        checked
        {
            _ = -c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_026_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x)
        {
            return x;
        }
 
        public static C1 operator checked -(C1 x)
        {
            return x;
        }
    }
}
 
public static class Extensions2
{
    extension(C1)
    {
        public static C1 operator -(C1 x)
        {
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = -c1;
 
        checked
        {
            _ = -c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (35,13): error CS0035: Operator '-' is ambiguous on an operand of type 'C1'
                //         _ = -c1;
                Diagnostic(ErrorCode.ERR_AmbigUnaryOp, "-c1").WithArguments("-", "C1").WithLocation(35, 13),
                // (39,17): error CS0035: Operator '-' is ambiguous on an operand of type 'C1'
                //             _ = -c1;
                Diagnostic(ErrorCode.ERR_AmbigUnaryOp, "-c1").WithArguments("-", "C1").WithLocation(39, 17)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().Last();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("Extensions1.extension(C1).operator checked -(C1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("Extensions2.extension(C1).operator -(C1)", symbolInfo.CandidateSymbols[1].ToDisplayString());
        }
 
        [Fact]
        public void Unary_027_Consumption_CheckedLiftedIsWorse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator -(S1 x) => throw null;
        public static S1 operator checked -(S1 x) => throw null;
    }
    extension(S1?)
    {
        public static S1? operator -(S1? x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        _ = -s1;
        System.Console.Write(":");
 
        checked
        {
            _ = -s1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_028_Consumption_OverloadResolutionPlusRegularVsChecked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x)
        {
            System.Console.Write("C1");
            return x;
        }
        public static C1 operator checked -(C1 x)
        {
            System.Console.Write("checkedC1");
            return x;
        }
    }
    extension(C2)
    {
        public static C2 operator -(C2 x)
        {
            System.Console.Write("C2");
            return x;
        }
    }
}
 
public class C1;
public class C2 : C1;
public class C3 : C1;
 
class Program
{
    static void Main()
    {
        var c3 = new C3();
        _ = -c3;
 
        checked
        {
            _ = -c3;
        }
 
        var c2 = new C2();
        _ = -c2;
 
        checked
        {
            _ = -c2;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "C1checkedC1C2C2").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_029_Consumption()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1? operator +(S1? x)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public static void M1(S1? x) {}
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
#line 21
        _ = +s1;
        S1 s2 = new S1();
        _ = +s2;
 
        System.Nullable<S1>.M1(s1);
        S1.M1(s1);
        S1.M1(s2);
    }
}
 
public static class Extensions2
{
    extension(S2)
    {
        public static S2? operator +(S2 x)
        {
            return x;
        }
    }
}
 
public struct S2
{}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyEmitDiagnostics(
                // (5,36): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static S1? operator +(S1? x)
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "+").WithLocation(5, 36),
                // (21,13): error CS0023: Operator '+' cannot be applied to operand of type 'S1?'
                //         _ = +s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "+s1").WithArguments("+", "S1?").WithLocation(21, 13),
                // (25,9): error CS1929: 'S1?' does not contain a definition for 'M1' and the best extension method overload 'Extensions1.extension(S1).M1(S1?)' requires a receiver of type 'S1'
                //         System.Nullable<S1>.M1(s1);
                Diagnostic(ErrorCode.ERR_BadInstanceArgType, "System.Nullable<S1>").WithArguments("S1?", "M1", "Extensions1.extension(S1).M1(S1?)", "S1").WithLocation(25, 9)
                );
        }
 
        [Fact]
        public void Unary_030_Consumption_OnObject()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static object operator +(object x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
        _ = +s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_031_Consumption_NotOnDynamic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static object operator +(object x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
class Program
{
    static void Main()
    {
        dynamic s1 = new object();
        try
        {
            _ = +s1;
        }
        catch
        {
            System.Console.Write("exception");
        }
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "exception").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_032_Consumption_BadOperand()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static object operator +(object x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
class Program
{
    static void Main()
    {
        _ = +null;
        _ = +default;
        _ = +new();
        _ = +(() => 1);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (19,13): error CS8310: Operator '+' cannot be applied to operand '<null>'
                //         _ = +null;
                Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "+null").WithArguments("+", "<null>").WithLocation(19, 13),
                // (20,14): error CS8716: There is no target type for the default literal.
                //         _ = +default;
                Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(20, 14),
                // (21,14): error CS8754: There is no target type for 'new()'
                //         _ = +new();
                Diagnostic(ErrorCode.ERR_ImplicitObjectCreationNoTargetType, "new()").WithArguments("new()").WithLocation(21, 14),
                // (22,13): error CS0023: Operator '+' cannot be applied to operand of type 'lambda expression'
                //         _ = +(() => 1);
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "+(() => 1)").WithArguments("+", "lambda expression").WithLocation(22, 13)
                );
        }
 
        [Fact]
        public void Unary_033_Consumption_BadReceiver()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(__arglist)
    {
        public static object operator +(object x)
        {
            return x;
        }
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
        _ = +s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (3,15): error CS1669: __arglist is not valid in this context
                //     extension(__arglist)
                Diagnostic(ErrorCode.ERR_IllegalVarArgs, "__arglist").WithLocation(3, 15),
                // (5,39): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static object operator +(object x)
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "+").WithLocation(5, 39),
                // (17,13): error CS0023: Operator '+' cannot be applied to operand of type 'object'
                //         _ = +s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "+s1").WithArguments("+", "object").WithLocation(17, 13)
                );
        }
 
        [Fact]
        public void Unary_034_Consumption_Checked_Generic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T1>(C1<T1>)
    {
        public static C1<T1> operator -(C1<T1> x)
        {
            System.Console.Write("regular");
            return x;
        }
    }
    extension<T2>(C1<T2>)
    {
        public static C1<T2> operator checked -(C1<T2> x)
        {
            System.Console.Write("checked");
            return x;
        }
    }
}
 
public class C1<T>;
 
class Program
{
    static void Main()
    {
        var c1 = new C1<int>();
        _ = -c1;
 
        checked
        {
            _ = -c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Unary_035_Consumption_True(bool fromMetadata)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static bool operator true(S1 x)
        {
            System.Console.Write("operator1");
            return x.F;
        }
        public static bool operator false(S1 x) => throw null;
    }
}
 
public struct S1
{
    public bool F;
}
""";
 
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1() { F = true };
        if (s1)
        {
            System.Console.Write(":true:");
        }
 
        s1 = new S1() { F = false };
        if (s1)
        {}
        else
        {
            System.Console.Write(":false");
        }
    }
}
""";
 
            var comp1 = CreateCompilation(src1);
            var comp1Ref = fromMetadata ? comp1.EmitToImageReference() : comp1.ToMetadataReference();
 
            var comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "operator1:true:operator1:false").VerifyDiagnostics();
 
            var tree = comp2.SyntaxTrees.First();
            var model = comp2.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.IfStatementSyntax>().First().Condition;
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("s1", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp2, expectedOutput: "operator1:true:operator1:false").VerifyDiagnostics();
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            comp2.VerifyEmitDiagnostics(
                // (6,13): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                //         if (s1)
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "s1").WithArguments("extensions").WithLocation(6, 13),
                // (12,13): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                //         if (s1)
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "s1").WithArguments("extensions").WithLocation(12, 13)
                );
 
            var src3 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        Extensions1.op_True(s1);
    }
}
""";
            var comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp3, expectedOutput: "operator1").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp3, expectedOutput: "operator1").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            CompileAndVerify(comp3, expectedOutput: "operator1").VerifyDiagnostics();
 
            var src4 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1.op_True();
        S1.op_True(s1);
    }
}
""";
            var comp4 = CreateCompilation(src4, references: [comp1Ref]);
            comp4.VerifyEmitDiagnostics(
                // (6,12): error CS1061: 'S1' does not contain a definition for 'op_True' and no accessible extension method 'op_True' accepting a first argument of type 'S1' could be found (are you missing a using directive or an assembly reference?)
                //         s1.op_True();
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "op_True").WithArguments("S1", "op_True").WithLocation(6, 12),
                // (7,12): error CS0117: 'S1' does not contain a definition for 'op_True'
                //         S1.op_True(s1);
                Diagnostic(ErrorCode.ERR_NoSuchMember, "op_True").WithArguments("S1", "op_True").WithLocation(7, 12)
                );
        }
 
        [Fact]
        public void Unary_036_Consumption_True_ConversionComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static bool operator true(S2 x) => throw null;
        public static bool operator false(S2 x) => throw null;
    }
}
 
public struct S2
{
    public static implicit operator bool(S2 x)
    {
        System.Console.Write("operator2");
        return true;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        if(s2)
        {}
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_037_Consumption_True_NonExtensionComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static bool operator true(S2 x) => throw null;
        public static bool operator false(S2 x) => throw null;
    }
}
 
public struct S2
{
    public static bool operator true(S2 x)
    {
        System.Console.Write("operator2");
        return true;
    }
    public static bool operator false(S2 x) => throw null;
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        if(s2)
        {}
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_038_Consumption_True_ScopeByScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static bool operator true(S1 x) => throw null;
        public static bool operator false(S1 x) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(S1)
        {
            public static bool operator true(S1 x)
            {
                System.Console.Write("operator1");
                return true;
            }
            public static bool operator false(S1 x) => throw null;
        }
    }
 
    namespace NS2
    {
        public static class Extensions3
        {
            extension(S2)
            {
                public static bool operator true(S2 x) => throw null;
                public static bool operator false(S2 x) => throw null;
            }
        }
 
        class Program
        {
            static void Main()
            {
                var s1 = new S1();
                if(s1)
                {}
            }
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_039_Consumption_True_NonExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1
{
    public static bool operator true(I1 x) => true;
    public static bool operator false(I1 x) => false;
}
 
public interface I3
{
    public static bool operator true(I3 x) => true;
    public static bool operator false(I3 x) => false;
}
 
public interface I4 : I1, I3
{
}
 
public interface I2 : I4
{
}
 
public static class Extensions1
{
    extension(I2)
    {
        public static bool operator true(I2 x) => true;
        public static bool operator false(I2 x) => false;
    }
}
 
class Test2 : I2
{
    static void Main()
    {
        I2 x = new Test2();
        if(x)
        {}
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (35,12): error CS0029: Cannot implicitly convert type 'I2' to 'bool'
                //         if(x)
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "x").WithArguments("I2", "bool").WithLocation(35, 12)
                );
        }
 
        [Fact]
        public void Unary_040_Consumption_True_ExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1;
public interface I3;
public interface I4 : I1, I3;
public interface I2 : I4;
 
public static class Extensions1
{
    extension(I2)
    {
        public static bool operator true(I2 x) => true;
        public static bool operator false(I2 x) => false;
    }
}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(I1)
        {
            public static bool operator true(I1 x) => true;
            public static bool operator false(I1 x) => false;
        }
 
        extension(I3)
        {
            public static bool operator true(I3 x) => true;
            public static bool operator false(I3 x) => false;
        }
    }
 
    class Test2 : I2
    {
        static void Main()
        {
            I2 x = new Test2();
            if(x)
            {}
        }
    }
}
""";
 
            var comp = CreateCompilation(src);
 
            comp.VerifyEmitDiagnostics(
                // (37,16): error CS0029: Cannot implicitly convert type 'I2' to 'bool'
                //             if(x)
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "x").WithArguments("I2", "bool").WithLocation(37, 16)
                );
        }
 
        [Fact]
        public void Unary_041_Consumption_True_NoLiftedForm()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static bool operator true(S1 x)
        {
            System.Console.Write("operator1");
            return true;
        }
        public static bool operator false(S1 x) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        if (s1)
        {}
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (22,13): error CS0029: Cannot implicitly convert type 'S1?' to 'bool'
                //         if (s1)
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "s1").WithArguments("S1?", "bool").WithLocation(22, 13)
                );
        }
 
        [Fact]
        public void Unary_042_Consumption_True_ExtendedTypeIsNullable()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1?)
    {
        public static bool operator true(S1? x)
        {
            System.Console.Write("operator1");
            return true;
        }
        public static bool operator false(S1? x) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        if (s1)
        {}
        Extensions1.op_True(s1);
 
        S1? s2 = new S1();
        if (s2)
        {}
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (22,13): error CS0029: Cannot implicitly convert type 'S1' to 'bool'
                //         if (s1)
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "s1").WithArguments("S1", "bool").WithLocation(22, 13)
                );
        }
 
        [Fact]
        public void Unary_043_Consumption_True()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static bool operator true(S1? x)
        {
            System.Console.Write("operator1");
            return true;
        }
        public static bool operator false(S1? x) => throw null;
 
        public static void M1(S1? x) {}
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
#line 22
        if (s1)
        {}
        S1 s2 = new S1();
        if (s2)
        {}
 
        System.Nullable<S1>.M1(s1);
        S1.M1(s1);
        S1.M1(s2);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyEmitDiagnostics(
                // (5,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator true(S1? x)
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "true").WithLocation(5, 37),
                // (10,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator false(S1? x) => throw null;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "false").WithLocation(10, 37),
                // (22,13): error CS0029: Cannot implicitly convert type 'S1?' to 'bool'
                //         if (s1)
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "s1").WithArguments("S1?", "bool").WithLocation(22, 13),
                // (28,9): error CS1929: 'S1?' does not contain a definition for 'M1' and the best extension method overload 'Extensions1.extension(S1).M1(S1?)' requires a receiver of type 'S1'
                //         System.Nullable<S1>.M1(s1);
                Diagnostic(ErrorCode.ERR_BadInstanceArgType, "System.Nullable<S1>").WithArguments("S1?", "M1", "Extensions1.extension(S1).M1(S1?)", "S1").WithLocation(28, 9)
                );
        }
 
        [Fact]
        public void Unary_044_Consumption_True_OnObject()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static bool operator true(object x)
        {
            System.Console.Write("operator1");
            return true;
        }
        public static bool operator false(object x) => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
        if (s1)
        {}
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_045_Consumption_True_NotOnDynamic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static bool operator true(object x)
        {
            System.Console.Write("operator1");
            return true;
        }
        public static bool operator false(object x) => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        dynamic s1 = new object();
        try
        {
            if (s1)
            {}
        }
        catch
        {
            System.Console.Write("exception");
        }
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "exception").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Unary_046_Consumption_TupleComparison(bool fromMetadata)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static bool operator true(S1 x) => throw null;
        public static bool operator false(S1 x)
        {
            System.Console.Write("operator1");
            return true;
        }
    }
}
 
public struct S1
{
    public static S1 operator ==(S1 x, S1 y)
    {
        return x;
    }
    public static S1 operator !=(S1 x, S1 y) => throw null;
 
    public override bool Equals(object o) => throw null;
    public override int GetHashCode() => throw null;
}
""";
 
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        if ((s1, 1) == (s1, 1))
        {}
    }
}
""";
 
            var comp1 = CreateCompilation(src1);
            var comp1Ref = fromMetadata ? comp1.EmitToImageReference() : comp1.ToMetadataReference();
 
            var comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "operator1").VerifyDiagnostics();
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp2, expectedOutput: "operator1").VerifyDiagnostics();
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            comp2.VerifyEmitDiagnostics(
                // (6,13): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                //         if ((s1, 1) == (s1, 1))
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "(s1, 1) == (s1, 1)").WithArguments("extensions").WithLocation(6, 13)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Unary_047_Consumption_ExpressionTree([CombinatorialValues("+", "-", "!", "~")] string op)
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(S1 s1)
    {
        public static S1 operator {{{op}}}(S1 x)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public void Test()
        {
            Expression<System.Func<S1, S1>> ex = (s1) => {{{op}}}s1;
            ex.Compile()(s1);
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1, S1>> ex = (s1) => {{{op}}}s1;
 
        var s1 = new S1();
        ex.Compile()(s1);
 
        s1.Test();
 
        System.Console.Write(":");
        System.Console.Write(ex);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1operator1:s1 => " + (op is "!" or "~" ? "Not(" : op) + "s1" + (op is "!" or "~" ? ")" : "")).VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Unary_048_Consumption_Lifted_ExpressionTree([CombinatorialValues("+", "-", "!", "~")] string op)
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(S1 s1)
    {
        public static S1 operator {{{op}}}(S1 x)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public void Test()
        {
            Expression<System.Func<S1?, S1?>> ex = (s1) => {{{op}}}s1;
            var d = ex.Compile();
            
            d(s1);
            System.Console.Write(":");
            d(null);
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1?, S1?>> ex = (s1) => {{{op}}}s1;
 
        var s1 = new S1();
        var d = ex.Compile();
            
        d(s1);
        System.Console.Write(":");
        d(null);
 
        System.Console.Write(":");
        s1.Test();
 
        System.Console.Write(":");
        System.Console.Write(ex);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1::operator1::s1 => " + (op is "!" or "~" ? "Not(" : op) + "s1" + (op is "!" or "~" ? ")" : "")).VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_049_Consumption_True_ExpressionTree()
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(S1 s1)
    {
        public static bool operator true(S1 x)
        {
            System.Console.Write("operator1");
            return true;
        }
        public static bool operator false(S1 x) => throw null;
 
        public void Test()
        {
            Expression<System.Func<S1, int>> ex = (s1) => s1 ? 1 : 0;
            ex.Compile()(s1);
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1, int>> ex = (s1) => s1 ? 1 : 0;
 
        var s1 = new S1();
        ex.Compile()(s1);
 
        s1.Test();
 
        System.Console.Write(":");
        System.Console.Write(ex);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1operator1:s1 => IIF(op_True(s1), 1, 0)").VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_050_Consumption_True_ExpressionTree()
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(S1 s1)
    {
        public static bool operator true(S1 x)
        {
            System.Console.Write("operator1");
            return true;
        }
        public static bool operator false(S1 x) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1?, int>> ex = (s1) => s1 ? 1 : 0;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (23,56): error CS0029: Cannot implicitly convert type 'S1?' to 'bool'
                //         Expression<System.Func<S1?, int>> ex = (s1) => s1 ? 1 : 0;
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "s1").WithArguments("S1?", "bool").WithLocation(23, 56)
                );
        }
 
        [Fact]
        public void Unary_051_Consumption_True_ExpressionTree()
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(S1? s1)
    {
        public static bool operator true(S1? x)
        {
            System.Console.Write("operator1");
            return true;
        }
        public static bool operator false(S1? x) => throw null;
 
        public void Test()
        {
            Expression<System.Func<S1?, int>> ex = (s1) => s1 ? 1 : 0;
            ex.Compile()(s1);
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1?, int>> ex = (s1) => s1 ? 1 : 0;
 
        S1? s1 = new S1();
        ex.Compile()(s1);
 
        s1.Test();
 
        System.Console.Write(":");
        System.Console.Write(ex);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1operator1:s1 => IIF(op_True(s1), 1, 0)").VerifyDiagnostics();
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedUnaryOperator_RefStruct
        /// </summary>
        [Fact]
        public void Unary_052_RefSafety()
        {
            var source = """
class C
{
    S M1()
    {
        S s;
        s = +s; // 1
        return s;
    }
 
    S M2()
    {
        return +new S(); // 2
    }
 
    S M3(in S x)
    {
        S s;
        s = +x; // 3
        return s;
    }
 
    S M4(in S x)
    {
        return +x;
    }
 
    S M4s(scoped in S x)
    {
        return +x; // 4
    }
 
    S M5(in S x)
    {
        S s = +x;
        return s;
    }
 
    S M5s(scoped in S x)
    {
        S s = +x;
        return s; // 5
    }
 
    S M6()
    {
        S s = +new S();
        return s; // 6
    }
 
    void M7(in S x)
    {
        scoped S s;
        s = +x;
        s = +new S();
    }
}
 
ref struct S
{
}
 
static class Extensions
{
    extension(S)
    {
        public static S operator+(in S s) => throw null;
    }
}
""";
            CreateCompilation(source).VerifyDiagnostics(
                // (6,13): error CS8347: Cannot use a result of 'Extensions.extension(S).operator +(in S)' in this context because it may expose variables referenced by parameter 's' outside of their declaration scope
                //         s = +s; // 1
                Diagnostic(ErrorCode.ERR_EscapeCall, "+s").WithArguments("Extensions.extension(S).operator +(in S)", "s").WithLocation(6, 13),
                // (6,14): error CS8168: Cannot return local 's' by reference because it is not a ref local
                //         s = +s; // 1
                Diagnostic(ErrorCode.ERR_RefReturnLocal, "s").WithArguments("s").WithLocation(6, 14),
                // (12,16): error CS8347: Cannot use a result of 'Extensions.extension(S).operator +(in S)' in this context because it may expose variables referenced by parameter 's' outside of their declaration scope
                //         return +new S(); // 2
                Diagnostic(ErrorCode.ERR_EscapeCall, "+new S()").WithArguments("Extensions.extension(S).operator +(in S)", "s").WithLocation(12, 16),
                // (12,17): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return +new S(); // 2
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "new S()").WithLocation(12, 17),
                // (18,13): error CS8347: Cannot use a result of 'Extensions.extension(S).operator +(in S)' in this context because it may expose variables referenced by parameter 's' outside of their declaration scope
                //         s = +x; // 3
                Diagnostic(ErrorCode.ERR_EscapeCall, "+x").WithArguments("Extensions.extension(S).operator +(in S)", "s").WithLocation(18, 13),
                // (18,14): error CS9077: Cannot return a parameter by reference 'x' through a ref parameter; it can only be returned in a return statement
                //         s = +x; // 3
                Diagnostic(ErrorCode.ERR_RefReturnOnlyParameter, "x").WithArguments("x").WithLocation(18, 14),
                // (29,16): error CS8347: Cannot use a result of 'Extensions.extension(S).operator +(in S)' in this context because it may expose variables referenced by parameter 's' outside of their declaration scope
                //         return +x; // 4
                Diagnostic(ErrorCode.ERR_EscapeCall, "+x").WithArguments("Extensions.extension(S).operator +(in S)", "s").WithLocation(29, 16),
                // (29,17): error CS9075: Cannot return a parameter by reference 'x' because it is scoped to the current method
                //         return +x; // 4
                Diagnostic(ErrorCode.ERR_RefReturnScopedParameter, "x").WithArguments("x").WithLocation(29, 17),
                // (41,16): error CS8352: Cannot use variable 's' in this context because it may expose referenced variables outside of their declaration scope
                //         return s; // 5
                Diagnostic(ErrorCode.ERR_EscapeVariable, "s").WithArguments("s").WithLocation(41, 16),
                // (47,16): error CS8352: Cannot use variable 's' in this context because it may expose referenced variables outside of their declaration scope
                //         return s; // 6
                Diagnostic(ErrorCode.ERR_EscapeVariable, "s").WithArguments("s").WithLocation(47, 16)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedUnaryOperator_RefStruct_Scoped
        /// </summary>
        [Fact]
        public void Unary_053_RefSafety()
        {
            var source = """
ref struct R
{
    private ref readonly int _i;
    public R(in int i) { _i = ref i; }
}
class Program
{
    static R F()
    {
        return !new R(0);
    }
}
 
static class Extensions
{
    extension(R)
    {
        public static R operator !(scoped R r) => default;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics();
        }
 
        [Fact]
        public void Unary_054_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
 
    extension(C2)
    {
        public static C2 operator -(C2? x)
        {
            System.Console.Write("operator2");
            return new C2();
        }
    }
}
 
public class C1
{}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C1? x = null;
#line 23
        _ = -x;
        C1 y = new C1();
        y = -y;
        C2? z = null;
        _ = -z;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (23,14): warning CS8604: Possible null reference argument for parameter 'x' in 'C1 extension(C1).operator -(C1 x)'.
                //         _ = -x;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "C1 extension(C1).operator -(C1 x)").WithLocation(23, 14)
                );
        }
 
        [Fact]
        public void Unary_055_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1)
    {
        public static C1? operator -(C1 x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public class C1
{}
 
class Program
{
    static void Main()
    {
        var x = new C1();
        C1 y = -x;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (23,16): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         C1 y = -x;
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "-x").WithLocation(23, 16)
                );
        }
 
        [Fact]
        public void Unary_056_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T)
    {
        public static T operator -(T x)
        {
            return x;
        }
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        (-x).ToString();
        var y = new C2();
        (-y).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (22,10): warning CS8602: Dereference of a possibly null reference.
                //         (-x).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "-x").WithLocation(22, 10)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().ToArray();
 
            Assert.Equal(2, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator -(C2?)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2>(C2).operator -(C2)", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void Unary_057_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(C1<T>) where T : new()
    {
        public static T operator -(C1<T> x)
        {
            return x.F;
        }
    }
}
 
public class C1<T> where T : new()
{
    public T F = new T();
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        (-x).ToString();
        var y = Get(new C2());
        (-y).ToString();
    }
 
    static C1<T> Get<T>(T x) where T : new()
    {
        return new C1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (27,10): warning CS8602: Dereference of a possibly null reference.
                //         (-x).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "-x").WithLocation(27, 10)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().ToArray();
 
            Assert.Equal(2, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?>(C1<C2?>).operator -(C1<C2?>)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2>(C1<C2>).operator -(C1<C2>)", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void Unary_058_NullableAnalysis_Lifted()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(S1<T>) where T : new()
    {
        public static S1<T> operator -(S1<T> x)
        {
            return x;
        }
    }
}
 
public struct S1<T> where T : new()
{
    public T F;
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = -Get((C2?)null);
 
        if (x != null)
            x.Value.F.ToString();
 
        var y = -Get(new C2());
 
        if (y != null)
            y.Value.F.ToString();
    }
 
    static S1<T>? Get<T>(T x) where T : new()
    {
        return new S1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (29,13): warning CS8602: Dereference of a possibly null reference.
                //             x.Value.F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Value.F").WithLocation(29, 13)
                );
        }
 
        [Fact]
        public void Unary_059_NullableAnalysis_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T) where T : notnull
    {
        public static object operator -(T x)
        {
            return x;
        }
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        (-x).ToString();
        var y = new C2();
        (-y).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (22,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(T)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (-x).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "-x").WithArguments("Extensions1.extension<T>(T)", "T", "C2?").WithLocation(22, 10)
                );
        }
 
        [Fact]
        public void Unary_060_NullableAnalysis_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(C1<T>) where T : notnull, new()
    {
        public static T operator -(C1<T> x)
        {
            return x.F;
        }
    }
}
 
public class C1<T> where T : new()
{
    public T F = new T();
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        (-x).ToString();
        var y = Get(new C2());
        (-y).ToString();
    }
 
    static C1<T> Get<T>(T x) where T : new()
    {
        return new C1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (27,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(C1<T>)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (-x).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "-x").WithArguments("Extensions1.extension<T>(C1<T>)", "T", "C2?").WithLocation(27, 10),
                // (27,10): warning CS8602: Dereference of a possibly null reference.
                //         (-x).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "-x").WithLocation(27, 10)
                );
        }
 
        [Fact]
        public void Unary_061_NullableAnalysis_True()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1)
    {
        public static bool operator true(C1 x) => true;
        public static bool operator false(C1 x) => false;
    }
 
    extension(C2)
    {
        public static bool operator true(C2? x) => true;
        public static bool operator false(C2? x) => false;
    }
}
 
public class C1
{}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C1? x = null;
#line 20
        if (x)
        {}
 
        C1 y = new C1();
        if (y)
        {}
 
        C2? z= null;
        if (z)
        {}
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (20,13): warning CS8604: Possible null reference argument for parameter 'x' in 'bool extension(C1).operator true(C1 x)'.
                //         if (x)
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "bool extension(C1).operator true(C1 x)").WithLocation(20, 13)
                );
        }
 
        [Fact]
        public void Unary_062_NullableAnalysis_True_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T) where T : notnull
    {
        public static bool operator true(T x) => true;
        public static bool operator false(T x) => false;
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        if (x)
        {}
 
        var y = new C2();
        if (y)
        {}
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (20,13): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(T)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         if (x)
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "x").WithArguments("Extensions1.extension<T>(T)", "T", "C2?").WithLocation(20, 13)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Increment_001_Declaration([CombinatorialValues("++", "--")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(ref S1 s1)
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions2
{
    extension(ref S1 s1)
    {
        public S1 operator {{{op}}}() => throw null;
    }
}
 
static class Extensions3
{
    extension(ref S1 s1)
    {
        void operator {{{op}}}() {}
    }
    extension(C1)
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions4
{
    extension(ref S1? s1)
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions5
{
    extension(S1 s1)
    {
#line 600
        public void operator {{{op}}}() {}
    }
#line 700
    extension(ref C2 c2)
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions6
{
    extension(C2 c2)
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions7
{
    extension(in S1 s1)
    {
#line 800
        public void operator {{{op}}}() {}
    }
#line 900
    extension(in C2 c2)
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions8
{
    extension(ref readonly S1 s1)
    {
#line 1000
        public void operator {{{op}}}() {}
    }
#line 1100
    extension(ref readonly C2 c2)
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions9
{
    extension<T>(T t) where T : struct
    {
#line 1200
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions10
{
    extension<T>(T t) where T : class
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions11
{
    extension<T>(T t)
    {
#line 1300
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions12
{
    extension<T>(ref T t) where T : struct
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions13
{
#line 1400
    extension<T>(ref T t) where T : class
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions14
{
#line 1500
    extension<T>(ref T t)
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions15
{
#line 1600
    extension<T>(in T t) where T : struct
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions16
{
#line 1700
    extension<T>(in T t) where T : class
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions17
{
#line 1800
    extension<T>(in T t)
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions18
{
#line 1900
    extension<T>(ref readonly T t) where T : struct
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions19
{
#line 2000
    extension<T>(ref readonly T t) where T : class
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions20
{
#line 2100
    extension<T>(ref readonly T t)
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions21
{
    extension(C2)
    {
#line 2200
        public void operator {{{op}}}() {}
    }
}
 
struct S1
{}
 
static class C1
{}
 
class C2
{}
""";
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (13,28): error CS9503: The return type for this operator must be void
                //         public S1 operator ++() => throw null;
                Diagnostic(ErrorCode.ERR_OperatorMustReturnVoid, op).WithLocation(13, 28),
                // (21,23): error CS9501: User-defined operator 'Extensions3.extension(ref S1).operator ++()' must be declared public
                //         void operator ++() {}
                Diagnostic(ErrorCode.ERR_OperatorsMustBePublic, op).WithArguments("Extensions3.extension(ref S1).operator " + op + "()").WithLocation(21, 23),
                // (25,30): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public void operator ++() {}
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, op).WithLocation(25, 30),
                // (600,30): error CS9322: Cannot declare instance operator for a struct unless containing extension block receiver parameter is a 'ref' parameter
                //         public void operator ++() {}
                Diagnostic(ErrorCode.ERR_InstanceOperatorStructExtensionWrongReceiverRefKind, op).WithLocation(600, 30),
                // (700,19): error CS9300: The 'ref' receiver parameter of an extension block must be a value type or a generic type constrained to struct.
                //     extension(ref C2 c2)
                Diagnostic(ErrorCode.ERR_RefExtensionParameterMustBeValueTypeOrConstrainedToOne, "C2").WithLocation(700, 19),
                // (800,30): error CS9322: Cannot declare instance operator for a struct unless containing extension block receiver parameter is a 'ref' parameter
                //         public void operator ++() {}
                Diagnostic(ErrorCode.ERR_InstanceOperatorStructExtensionWrongReceiverRefKind, op).WithLocation(800, 30),
                // (900,18): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension(in C2 c2)
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "C2").WithLocation(900, 18),
                // (1000,30): error CS9322: Cannot declare instance operator for a struct unless containing extension block receiver parameter is a 'ref' parameter
                //         public void operator ++() {}
                Diagnostic(ErrorCode.ERR_InstanceOperatorStructExtensionWrongReceiverRefKind, op).WithLocation(1000, 30),
                // (1100,28): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension(ref readonly C2 c2)
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "C2").WithLocation(1100, 28),
                // (1200,30): error CS9322: Cannot declare instance operator for a struct unless containing extension block receiver parameter is a 'ref' parameter
                //         public void operator ++() {}
                Diagnostic(ErrorCode.ERR_InstanceOperatorStructExtensionWrongReceiverRefKind, op).WithLocation(1200, 30),
                // (1300,30): error CS9323: Cannot declare instance extension operator for a type that is not known to be a struct and is not known to be a class
                //         public void operator ++() {}
                Diagnostic(ErrorCode.ERR_InstanceOperatorExtensionWrongReceiverType, op).WithLocation(1300, 30),
                // (1400,22): error CS9300: The 'ref' receiver parameter of an extension block must be a value type or a generic type constrained to struct.
                //     extension<T>(ref T t) where T : class
                Diagnostic(ErrorCode.ERR_RefExtensionParameterMustBeValueTypeOrConstrainedToOne, "T").WithLocation(1400, 22),
                // (1500,22): error CS9300: The 'ref' receiver parameter of an extension block must be a value type or a generic type constrained to struct.
                //     extension<T>(ref T t)
                Diagnostic(ErrorCode.ERR_RefExtensionParameterMustBeValueTypeOrConstrainedToOne, "T").WithLocation(1500, 22),
                // (1600,21): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension<T>(in T t) where T : struct
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "T").WithLocation(1600, 21),
                // (1700,21): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension<T>(in T t) where T : class
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "T").WithLocation(1700, 21),
                // (1800,21): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension<T>(in T t)
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "T").WithLocation(1800, 21),
                // (1900,31): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension<T>(ref readonly T t) where T : struct
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "T").WithLocation(1900, 31),
                // (2000,31): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension<T>(ref readonly T t) where T : class
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "T").WithLocation(2000, 31),
                // (2100,31): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension<T>(ref readonly T t)
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "T").WithLocation(2100, 31),
                // (2200,30): error CS9303: 'operator ++': cannot declare instance members in an extension block with an unnamed receiver parameter
                //         public void operator ++() {}
                Diagnostic(ErrorCode.ERR_InstanceMemberWithUnnamedExtensionsParameter, op).WithArguments("operator " + op).WithLocation(2200, 30)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Increment_002_Declaration([CombinatorialValues("++", "--")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(ref S1 s1)
    {
        public void operator {{{op}}}() {}
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            CompileAndVerify(comp, symbolValidator: verify, sourceSymbolValidator: verify, verify: Verification.FailsPEVerify).VerifyDiagnostics();
 
            void verify(ModuleSymbol m)
            {
                var name = CompoundAssignmentOperatorName(op);
                var method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + name);
 
                AssertEx.Equal("Extensions1." + name + "(ref S1)", method.ToDisplayString());
                Assert.Equal(MethodKind.Ordinary, method.MethodKind);
                Assert.True(method.IsStatic);
                Assert.False(method.IsExtensionMethod);
                Assert.False(method.HasSpecialName);
                Assert.False(method.HasRuntimeSpecialName);
                Assert.False(method.HasUnsupportedMetadata);
            }
        }
 
        [Theory]
        [CombinatorialData]
        public void Increment_003_Declaration([CombinatorialValues("++", "--")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(S1 s1)
    {
        public void operator {{{op}}}() {}
        public static S1 operator {{{op}}}(S1 x) => default;
    }
}
 
class S1
{}
""";
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
 
            CompileAndVerify(comp, symbolValidator: verify, sourceSymbolValidator: verify, verify: Verification.FailsPEVerify).VerifyDiagnostics();
 
            void verify(ModuleSymbol m)
            {
                var name = CompoundAssignmentOperatorName(op);
                var method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + name);
 
                AssertEx.Equal("Extensions1." + name + "(S1)", method.ToDisplayString());
                Assert.Equal(MethodKind.Ordinary, method.MethodKind);
                Assert.True(method.IsStatic);
                Assert.False(method.IsExtensionMethod);
                Assert.False(method.HasSpecialName);
                Assert.False(method.HasRuntimeSpecialName);
                Assert.False(method.HasUnsupportedMetadata);
 
                name = op == "++" ? WellKnownMemberNames.IncrementOperatorName : WellKnownMemberNames.DecrementOperatorName;
                method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + name);
 
                AssertEx.Equal("Extensions1." + name + "(S1)", method.ToDisplayString());
                Assert.Equal(MethodKind.Ordinary, method.MethodKind);
                Assert.True(method.IsStatic);
                Assert.False(method.IsExtensionMethod);
                Assert.False(method.HasSpecialName);
                Assert.False(method.HasRuntimeSpecialName);
                Assert.False(method.HasUnsupportedMetadata);
            }
        }
 
        [Theory]
        [CombinatorialData]
        public void Increment_005_Declaration([CombinatorialValues("++", "--")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(ref S1 s1)
    {
        public void operator checked {{{op}}}() {}
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions2
{
    extension(ref S1 s1)
    {
#line 100
        public void operator checked {{{op}}}() {}
    }
    extension(ref S1 s1)
    {
        public void operator {{{op}}}() {}
    }
}
 
static class Extensions3
{
    extension(ref S1 s1)
    {
        public void operator checked {{{op}}}() {}
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (112,38): error CS9025: The operator 'Extensions3.extension(ref S1).operator checked ++()' requires a matching non-checked version of the operator to also be defined
                //         public void operator checked ++() {}
                Diagnostic(ErrorCode.ERR_CheckedOperatorNeedsMatch, op).WithArguments("Extensions3.extension(ref S1).operator checked " + op + "()").WithLocation(112, 38)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Increment_004_Declaration([CombinatorialValues("++", "--")] string op, [CombinatorialValues("virtual", "abstract", "new", "override", "sealed", "readonly", "extern")] string modifier)
        {
            var src = $$$"""
static class Extensions1
{
    extension(ref S1 s1)
    {
        {{{modifier}}}
        public void operator {{{op}}}() {}
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (6,30): error CS0106: The modifier 'abstract' is not valid for this item
                //         public void operator ++() {}
                Diagnostic(ErrorCode.ERR_BadMemberFlag, op).WithArguments(modifier).WithLocation(6, 30)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Increment_005_Consumption(bool fromMetadata)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator ++(S1 x)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            return new S1 { F = x.F + 1 };
        }
    }
}
 
public struct S1
{
    public int F;
}
""";
 
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1() { F = 101 };
        ++s1;
        System.Console.Write(":");
        System.Console.Write(s1.F);
        System.Console.Write(":");
        var s2 = ++s1;
        System.Console.Write(":");
        System.Console.Write(s2.F);
        System.Console.Write(":");
        System.Console.Write(s1.F);
    }
}
""";
 
            var comp1 = CreateCompilation(src1);
            var comp1Ref = fromMetadata ? comp1.EmitToImageReference() : comp1.ToMetadataReference();
 
            var comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:102:operator1:102:103:103").VerifyDiagnostics();
 
            var tree = comp2.SyntaxTrees.First();
            var model = comp2.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(S1).operator ++(S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:102:operator1:102:103:103").VerifyDiagnostics();
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            comp2.VerifyEmitDiagnostics(
                // (6,9): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                //         ++s1;
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "++s1").WithArguments("extensions").WithLocation(6, 9),
                // (10,18): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                //         var s2 = ++s1;
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "++s1").WithArguments("extensions").WithLocation(10, 18)
                );
 
            var src3 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        Extensions1.op_Increment(s1);
    }
}
""";
            var comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp3, expectedOutput: "operator1:0").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp3, expectedOutput: "operator1:0").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            CompileAndVerify(comp3, expectedOutput: "operator1:0").VerifyDiagnostics();
 
            var src4 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1.op_Increment();
        S1.op_Increment(s1);
    }
}
""";
            var comp4 = CreateCompilation(src4, references: [comp1Ref]);
            comp4.VerifyEmitDiagnostics(
                // (6,12): error CS1061: 'S1' does not contain a definition for 'op_Increment' and no accessible extension method 'op_Increment' accepting a first argument of type 'S1' could be found (are you missing a using directive or an assembly reference?)
                //         s1.op_Increment();
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "op_Increment").WithArguments("S1", "op_Increment").WithLocation(6, 12),
                // (7,12): error CS0117: 'S1' does not contain a definition for 'op_Increment'
                //         S1.op_Increment(s1);
                Diagnostic(ErrorCode.ERR_NoSuchMember, "op_Increment").WithArguments("S1", "op_Increment").WithLocation(7, 12)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Increment_006_Consumption(bool fromMetadata)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator ++()
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            x.F++;
        }
    }
}
 
public struct S1
{
    public int F;
}

""" + CompilerFeatureRequiredAttribute;
 
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1() { F = 101 };
        ++s1;
        System.Console.Write(":");
        System.Console.Write(s1.F);
        System.Console.Write(":");
        var s2 = ++s1;
        System.Console.Write(":");
        System.Console.Write(s2.F);
        System.Console.Write(":");
        System.Console.Write(s1.F);
    }
}
""";
 
            var comp1 = CreateCompilation(src1);
            var comp1Ref = fromMetadata ? comp1.EmitToImageReference() : comp1.ToMetadataReference();
 
            var comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:102:operator1:102:103:103").VerifyDiagnostics();
 
            var tree = comp2.SyntaxTrees.First();
            var model = comp2.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().ElementAt(1);
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(ref S1).operator ++()", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:102:operator1:102:103:103").VerifyDiagnostics();
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            comp2.VerifyEmitDiagnostics(
                // (6,9): error CS0023: Operator '++' cannot be applied to operand of type 'S1'
                //         ++s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s1").WithArguments("++", "S1").WithLocation(6, 9),
                // (10,18): error CS0023: Operator '++' cannot be applied to operand of type 'S1'
                //         var s2 = ++s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s1").WithArguments("++", "S1").WithLocation(10, 18)
                );
 
            var src3 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        Extensions1.op_IncrementAssignment(ref s1);
    }
}
""";
            var comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp3, expectedOutput: "operator1:0").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp3, expectedOutput: "operator1:0").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            CompileAndVerify(comp3, expectedOutput: "operator1:0").VerifyDiagnostics();
 
            var src4 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1.op_IncrementAssignment();
        S1.op_IncrementAssignment(ref s1);
    }
}
""";
            var comp4 = CreateCompilation(src4, references: [comp1Ref]);
            comp4.VerifyEmitDiagnostics(
                // (6,12): error CS1061: 'S1' does not contain a definition for 'op_IncrementAssignment' and no accessible extension method 'op_IncrementAssignment' accepting a first argument of type 'S1' could be found (are you missing a using directive or an assembly reference?)
                //         s1.op_IncrementAssignment();
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "op_IncrementAssignment").WithArguments("S1", "op_IncrementAssignment").WithLocation(6, 12),
                // (7,12): error CS0117: 'S1' does not contain a definition for 'op_IncrementAssignment'
                //         S1.op_IncrementAssignment(ref s1);
                Diagnostic(ErrorCode.ERR_NoSuchMember, "op_IncrementAssignment").WithArguments("S1", "op_IncrementAssignment").WithLocation(7, 12)
                );
 
            var src5 = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator ++()
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            x.F++;
        }
    }
}
 
public class C1
{
    public int F;
}

""" + CompilerFeatureRequiredAttribute;
 
            var src6 = $$$"""
class Program
{
    static void Main()
    {
        var c1 = new C1() { F = 101 };
        var c2 = c1;
        ++c1;
        System.Console.Write(":");
        System.Console.Write(c1.F);
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c1, c2) ? "True" : "False");
        System.Console.Write(":");
        var c3 = ++c1;
        System.Console.Write(":");
        System.Console.Write(c1.F);
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c1, c2) ? "True" : "False");
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c1, c3) ? "True" : "False");
    }
}
""";
 
            var comp5 = CreateCompilation(src5);
            var comp5Ref = fromMetadata ? comp5.EmitToImageReference() : comp5.ToMetadataReference();
 
            var comp6 = CreateCompilation(src6, references: [comp5Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp6, expectedOutput: "operator1:101:102:True:operator1:102:103:True:True").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_007_Consumption_PredefinedComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator ++(S2 x) => throw null;
    }
}
 
public struct S2
{
    public static implicit operator int(S2 x)
    {
        System.Console.Write("operator2");
        return 0;
    }
    public static implicit operator S2(int x)
    {
        System.Console.Write("operator3");
        return default;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        ++s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator3").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("S2.operator ++(S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_008_Consumption_PredefinedComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator ++() => throw null;
    }
}
 
public struct S2
{
    public static implicit operator int(S2 x)
    {
        System.Console.Write("operator2");
        return 0;
    }
    public static implicit operator S2(int x)
    {
        System.Console.Write("operator3");
        return default;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        ++s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator3").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("S2.operator ++(S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_009_Consumption_NonExtensionComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator ++(S2 x) => throw null;
    }
}
 
public struct S2
{
    public static S2 operator ++(S2 x)
    {
        System.Console.Write("operator2");
        return x;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = ++s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("S2.operator ++(S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_010_Consumption_NonExtensionComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator ++(S2 x) => throw null;
    }
}
 
public struct S2
{
    public void operator ++()
    {
        System.Console.Write("operator2");
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = ++s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("S2.operator ++()", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_011_Consumption_NonExtensionComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator ++() => throw null;
    }
}
 
public struct S2
{
    public static S2 operator ++(S2 x)
    {
        System.Console.Write("operator2");
        return x;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = ++s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("S2.operator ++(S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_012_Consumption_NonExtensionComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator ++() => throw null;
    }
}
 
public struct S2
{
    public void operator ++()
    {
        System.Console.Write("operator2");
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = ++s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("S2.operator ++()", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_013_Consumption_InstanceInTheSameScopeComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator ++()
        {
            System.Console.Write("operator2");
        }
 
        public static S2 operator ++(S2 y) => throw null;
    }
}
 
public struct S2
{
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = ++s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(ref S2).operator ++()", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_014_Consumption_InstanceInTheSameScopeComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator ++()
        {
            System.Console.Write("operator2");
        }
    }
    extension(S2)
    {
        public static S2 operator ++(S2 y) => throw null;
    }
}
 
public struct S2
{
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = ++s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(ref S2).operator ++()", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_015_Consumption_InstanceInTheSameScopeComesFirst()
        {
            var src = $$$"""
public static class Extensions2
{
    extension(S2)
    {
        public static S2 operator ++(S2 y) => throw null;
    }
}
 
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator ++()
        {
            System.Console.Write("operator2");
        }
    }
}
 
public struct S2
{
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = ++s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(ref S2).operator ++()", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_016_Consumption_StaticTriedAfterInapplicableInstanceInTheSameScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator ++() => throw null;
    }
    extension(S2)
    {
        public static S2 operator ++(S2 y)
        {
            System.Console.Write("operator2");
            return y;
        }
    }
}
 
public struct S1
{
}
 
public struct S2
{
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = ++s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_017_Consumption_ScopeByScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator ++(S1 x) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(S1)
        {
            public static S1 operator ++(S1 x)
            {
                System.Console.Write("operator1");
                return x;
            }
        }
    }
 
    namespace NS2
    {
        public static class Extensions3
        {
            extension(S2)
            {
                public static S2 operator ++(S2 x) => throw null;
            }
        }
 
        class Program
        {
            static void Main()
            {
                var s1 = new S1();
                _ = ++s1;
            }
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("NS1.Extensions2.extension(S1).operator ++(S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_018_Consumption_ScopeByScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator ++() => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(S1)
        {
            public static S1 operator ++(S1 x)
            {
                System.Console.Write("operator1");
                return x;
            }
        }
    }
 
    namespace NS2
    {
        public static class Extensions3
        {
            extension(ref S2 x)
            {
                public void operator ++() => throw null;
            }
        }
 
        class Program
        {
            static void Main()
            {
                var s1 = new S1();
                _ = ++s1;
            }
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("NS1.Extensions2.extension(S1).operator ++(S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_019_Consumption_ScopeByScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator ++() => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(ref S1 x)
        {
            public void operator ++()
            {
                System.Console.Write("operator1");
            }
        }
    }
 
    namespace NS2
    {
        public static class Extensions3
        {
            extension(ref S2 x)
            {
                public void operator ++() => throw null;
            }
        }
 
        class Program
        {
            static void Main()
            {
                var s1 = new S1();
                _ = ++s1;
            }
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("NS1.Extensions2.extension(ref S1).operator ++()", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_020_Consumption_ScopeByScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator ++(S1 x) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(ref S1 x)
        {
            public void operator ++()
            {
                System.Console.Write("operator1");
            }
        }
    }
 
    namespace NS2
    {
        public static class Extensions3
        {
            extension(S2)
            {
                public static S2 operator ++(S2 x) => throw null;
            }
        }
 
        class Program
        {
            static void Main()
            {
                var s1 = new S1();
                _ = ++s1;
            }
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("NS1.Extensions2.extension(ref S1).operator ++()", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_021_Consumption_NonExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1
{
    public static I1 operator --(I1 x) => x;
}
 
public interface I3
{
    public static I3 operator --(I3 x) => x;
}
 
public interface I4 : I1, I3
{
}
 
public interface I2 : I4
{
}
 
public static class Extensions1
{
    extension(I2 x)
    {
        public void operator --() {}
        public static I2 operator --(I2 y) => y;
    }
}
 
class Test2 : I2
{
    static void Main()
    {
        I2 x = new Test2();
        var y = --x;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (33,17): error CS0035: Operator '--' is ambiguous on an operand of type 'I2'
                //         var y = --x;
                Diagnostic(ErrorCode.ERR_AmbigUnaryOp, "--x").WithArguments("--", "I2").WithLocation(33, 17)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("I1.operator --(I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("I3.operator --(I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_022_Consumption_NonExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1
{
    public void operator --() {}
}
 
public interface I3
{
    public void operator --() {}
}
 
public interface I4 : I1, I3
{
}
 
public interface I2 : I4
{
}
 
public static class Extensions1
{
    extension(I2 x)
    {
        public void operator --() {}
        public static I2 operator --(I2 y) => y;
    }
}
 
class Test2 : I2
{
    static void Main()
    {
        I2 x = new Test2();
        var y = --x;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (33,17): error CS0121: The call is ambiguous between the following methods or properties: 'I1.operator --()' and 'I3.operator --()'
                //         var y = --x;
                Diagnostic(ErrorCode.ERR_AmbigCall, "--").WithArguments("I1.operator --()", "I3.operator --()").WithLocation(33, 17)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("I1.operator --()", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("I3.operator --()", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_023_Consumption_NonExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1
{
    public void operator --() {}
}
 
public interface I3
{
    public void operator --() {}
}
 
public interface I4 : I1, I3
{
}
 
public interface I2 : I4
{
    public static I2 operator --(I2 y) => y;
}
 
public static class Extensions1
{
    extension(I2 x)
    {
        public void operator --() {}
        public static I2 operator --(I2 y) => y;
    }
}
 
class Test2 : I2
{
    static void Main()
    {
        I2 x = new Test2();
#line 33
        var y = --x;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (33,17): error CS0121: The call is ambiguous between the following methods or properties: 'I1.operator --()' and 'I3.operator --()'
                //         var y = --x;
                Diagnostic(ErrorCode.ERR_AmbigCall, "--").WithArguments("I1.operator --()", "I3.operator --()").WithLocation(33, 17)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("I1.operator --()", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("I3.operator --()", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/78830")]
        public void Increment_024_Consumption_ExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1;
public interface I3;
public interface I4 : I1, I3;
public interface I2 : I4;
 
public static class Extensions1
{
    extension(I2 y)
    {
        public void operator --() {}
        public static I2 operator --(I2 x) => x;
    }
}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(I1)
        {
            public static I1 operator --(I1 x) => x;
        }
 
        extension(I3)
        {
            public static I3 operator --(I3 x) => x;
        }
    }
 
    class Test2 : I2
    {
        static void Main()
        {
            I2 x = new Test2();
            var y = --x;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src);
 
            // https://github.com/dotnet/roslyn/issues/78830: We might want to include more information into the error. Like what methods conflict.
            comp.VerifyEmitDiagnostics(
                // (35,21): error CS0035: Operator '--' is ambiguous on an operand of type 'I2'
                //             var y = --x;
                Diagnostic(ErrorCode.ERR_AmbigUnaryOp, "--x").WithArguments("--", "I2").WithLocation(35, 21)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("NS1.Extensions2.extension(I1).operator --(I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("NS1.Extensions2.extension(I3).operator --(I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_025_Consumption_ExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1;
public interface I3;
public interface I4 : I1, I3;
public interface I2 : I4;
 
public static class Extensions1
{
    extension(I2 y)
    {
        public void operator --() {}
        public static I2 operator --(I2 x) => x;
    }
}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(I1 x)
        {
            public void operator --() {}
        }
 
        extension(I3 x)
        {
            public void operator --() {}
        }
    }
 
    class Test2 : I2
    {
        static void Main()
        {
            I2 x = new Test2();
            var y = --x;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src);
 
            comp.VerifyEmitDiagnostics(
                // (35,21): error CS0121: The call is ambiguous between the following methods or properties: 'Extensions2.extension(I1).operator --()' and 'Extensions2.extension(I3).operator --()'
                //             var y = --x;
                Diagnostic(ErrorCode.ERR_AmbigCall, "--").WithArguments("NS1.Extensions2.extension(I1).operator --()", "NS1.Extensions2.extension(I3).operator --()").WithLocation(35, 21)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("NS1.Extensions2.extension(I1).operator --()", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("NS1.Extensions2.extension(I3).operator --()", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_026_Consumption_ExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1;
public interface I3;
public interface I4 : I1, I3;
public interface I2 : I4;
 
public static class Extensions1
{
    extension(I2 y)
    {
        public void operator --() {}
        public static I2 operator --(I2 x) => x;
    }
}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(I1 x)
        {
            public void operator --() {}
        }
 
        extension(I3 x)
        {
            public void operator --() {}
        }
 
        extension(I2)
        {
            public static I2 operator --(I2 x) => x;
        }
    }
 
    class Test2 : I2
    {
        static void Main()
        {
            I2 x = new Test2();
#line 35
            var y = --x;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src);
 
            comp.VerifyEmitDiagnostics(
                // (35,21): error CS0121: The call is ambiguous between the following methods or properties: 'Extensions2.extension(I1).operator --()' and 'Extensions2.extension(I3).operator --()'
                //             var y = --x;
                Diagnostic(ErrorCode.ERR_AmbigCall, "--").WithArguments("NS1.Extensions2.extension(I1).operator --()", "NS1.Extensions2.extension(I3).operator --()").WithLocation(35, 21)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("NS1.Extensions2.extension(I1).operator --()", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("NS1.Extensions2.extension(I3).operator --()", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Increment_027_Consumption_Lifted()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 y)
    {
        public void operator ++() => throw null;
 
        public static S1 operator ++(S1 x)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            return new S1 { F = x.F + 1 };
        }
    }
}
 
public struct S1
{
    public int F;
}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1() { F = 101 };
        ++s1;
        System.Console.Write(":");
        System.Console.Write(s1.Value.F);
        System.Console.Write(":");
        var s2 = ++s1;
        System.Console.Write(":");
        System.Console.Write(s2.Value.F);
        System.Console.Write(":");
        System.Console.Write(s1.Value.F);
        System.Console.Write(":");
        s1 = null;
        ++s1;
        System.Console.Write(s1?.F ?? -1);
        System.Console.Write(":");
        s2 = ++s1;
        System.Console.Write(s2?.F ?? -1);
        System.Console.Write(":");
        System.Console.Write(s1?.F ?? -1);
 
        System.Console.Write(" | ");
 
        s1 = new S1() { F = 101 };
        s1++;
        System.Console.Write(":");
        System.Console.Write(s1.Value.F);
        System.Console.Write(":");
        s2 = s1++;
        System.Console.Write(":");
        System.Console.Write(s2.Value.F);
        System.Console.Write(":");
        System.Console.Write(s1.Value.F);
        System.Console.Write(":");
        s1 = null;
        s1++;
        System.Console.Write(s1?.F ?? -1);
        System.Console.Write(":");
        s2 = s1++;
        System.Console.Write(s2?.F ?? -1);
        System.Console.Write(":");
        System.Console.Write(s1?.F ?? -1);
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:101:102:operator1:102:103:103:-1:-1:-1 | operator1:101:102:operator1:102:102:103:-1:-1:-1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_028_Consumption_Lifted()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator ++()
        {
            System.Console.Write("operator1");
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        _ = ++s1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (20,13): error CS0023: Operator '++' cannot be applied to operand of type 'S1?'
                //         _ = ++s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s1").WithArguments("++", "S1?").WithLocation(20, 13)
                );
        }
 
        [Fact]
        public void Increment_029_Consumption_LiftedIsWorse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator ++(S1 x) => throw null;
    }
    extension(S1?)
    {
        public static S1? operator ++(S1? x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        _ = ++s1;
        System.Console.Write(":");
        s1 = null;
        _ = ++s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_030_Consumption_ExtendedTypeIsNullable()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1?)
    {
        public static S1? operator ++(S1? x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = ++s1;
        Extensions1.op_Increment(s1);
 
        S1? s2 = new S1();
        _ = ++s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (21,13): error CS0023: Operator '++' cannot be applied to operand of type 'S1'
                //         _ = ++s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s1").WithArguments("++", "S1").WithLocation(21, 13)
                );
        }
 
        [Fact]
        public void Increment_031_Consumption_ExtendedTypeIsNullable()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1? x)
    {
        public void operator ++()
        {
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = ++s1;
        Extensions1.op_IncrementAssignment(s1);
        Extensions1.op_IncrementAssignment(ref s1);
 
        S1? s2 = new S1();
        _ = ++s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (19,13): error CS0023: Operator '++' cannot be applied to operand of type 'S1'
                //         _ = ++s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s1").WithArguments("++", "S1").WithLocation(19, 13),
                // (20,44): error CS1620: Argument 1 must be passed with the 'ref' keyword
                //         Extensions1.op_IncrementAssignment(s1);
                Diagnostic(ErrorCode.ERR_BadArgRef, "s1").WithArguments("1", "ref").WithLocation(20, 44),
                // (21,48): error CS1503: Argument 1: cannot convert from 'ref S1' to 'ref S1?'
                //         Extensions1.op_IncrementAssignment(ref s1);
                Diagnostic(ErrorCode.ERR_BadArgType, "s1").WithArguments("1", "ref S1", "ref S1?").WithLocation(21, 48)
                );
        }
 
        [Fact]
        public void Increment_032_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator ++(S2 x) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S2(S1 x) => default;
}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = ++s1;
        Extensions1.op_Increment(s1);
 
        S1? s2 = new S1();
        _ = ++s2;
        Extensions1.op_Increment(s2);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (22,13): error CS0023: Operator '++' cannot be applied to operand of type 'S1'
                //         _ = ++s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s1").WithArguments("++", "S1").WithLocation(22, 13),
                // (26,13): error CS0023: Operator '++' cannot be applied to operand of type 'S1?'
                //         _ = ++s2;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s2").WithArguments("++", "S1?").WithLocation(26, 13),
                // (27,34): error CS1503: Argument 1: cannot convert from 'S1?' to 'S2'
                //         Extensions1.op_Increment(s2);
                Diagnostic(ErrorCode.ERR_BadArgType, "s2").WithArguments("1", "S1?", "S2").WithLocation(27, 34)
                );
        }
 
        [Fact]
        public void Increment_033_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator ++() => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S2(S1 x) => default;
}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = ++s1;
        Extensions1.op_IncrementAssignment(ref s1);
 
        S1? s2 = new S1();
        _ = ++s2;
        Extensions1.op_IncrementAssignment(ref s2);
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (22,13): error CS0023: Operator '++' cannot be applied to operand of type 'S1'
                //         _ = ++s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s1").WithArguments("++", "S1").WithLocation(22, 13),
                // (23,48): error CS1503: Argument 1: cannot convert from 'ref S1' to 'ref S2'
                //         Extensions1.op_IncrementAssignment(ref s1);
                Diagnostic(ErrorCode.ERR_BadArgType, "s1").WithArguments("1", "ref S1", "ref S2").WithLocation(23, 48),
                // (26,13): error CS0023: Operator '++' cannot be applied to operand of type 'S1?'
                //         _ = ++s2;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s2").WithArguments("++", "S1?").WithLocation(26, 13),
                // (27,48): error CS1503: Argument 1: cannot convert from 'ref S1?' to 'ref S2'
                //         Extensions1.op_IncrementAssignment(ref s2);
                Diagnostic(ErrorCode.ERR_BadArgType, "s2").WithArguments("1", "ref S1?", "ref S2").WithLocation(27, 48)
                );
        }
 
        [Fact]
        public void Increment_034_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static S1 operator ++(object x)
        {
            System.Console.Write("operator1");
            return default;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        s1 = ++s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_035_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object x)
    {
        public void operator ++() => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = ++s1;
        Extensions1.op_IncrementAssignment(s1);
 
        S1? s2 = new S1();
        _ = ++s2;
        Extensions1.op_IncrementAssignment(s2);
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (17,13): error CS0023: Operator '++' cannot be applied to operand of type 'S1'
                //         _ = ++s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s1").WithArguments("++", "S1").WithLocation(17, 13),
                // (21,13): error CS0023: Operator '++' cannot be applied to operand of type 'S1?'
                //         _ = ++s2;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s2").WithArguments("++", "S1?").WithLocation(21, 13)
                );
        }
 
        [Fact]
        public void Increment_036_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static C1 operator ++(object x)
        {
            System.Console.Write("operator1");
            return null;
        }
    }
}
 
public class C1
{}
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        c1 = ++c1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_037_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1Base x)
    {
        public void operator ++()
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            x.F++;
        }
    }
}
 
 
public class C1Base
{
    public int F;
}
 
public class C1 : C1Base
{}
 
class Program
{
    static void Main()
    {
        var c1 = new C1() { F = 101 };
        var c2 = c1;
        ++c1;
        System.Console.Write(":");
        System.Console.Write(c1.F);
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c1, c2) ? "True" : "False");
        System.Console.Write(":");
        var c3 = ++c1;
        System.Console.Write(":");
        System.Console.Write(c1.F);
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c1, c2) ? "True" : "False");
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c1, c3) ? "True" : "False");
        System.Console.Write(":");
        c1++;
        System.Console.Write(":");
        System.Console.Write(c1.F);
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c1, c2) ? "True" : "False");
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:101:102:True:operator1:102:103:True:True:operator1:103:104:True").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_038_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(dynamic x)
    {
        public void operator ++()
        {
            System.Console.Write("operator1");
        }
    }
}
 
public class C1
{}
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        c1 = ++c1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (3,15): error CS1103: The receiver parameter of an extension cannot be of type 'dynamic'
                //     extension(dynamic x)
                Diagnostic(ErrorCode.ERR_BadTypeforThis, "dynamic").WithArguments("dynamic").WithLocation(3, 15)
                );
        }
 
        [Fact]
        public void Increment_039_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object x)
    {
        public void operator ++()
        {
            System.Console.Write("operator1");
        }
    }
}
 
public class C1
{}
 
class Program
{
    static void Main()
    {
        Test(new C1());
    }
 
    static void Test<T>(T c1) where T : class
    {
        ++c1;
        c1 = ++c1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_040_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref System.Span<int> x)
    {
        public void operator ++() => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        int[] a1 = null;
#line 17
        _ = ++a1;
        Extensions1.op_IncrementAssignment(ref a1);
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (17,13): error CS0023: Operator '++' cannot be applied to operand of type 'int[]'
                //         _ = ++a1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++a1").WithArguments("++", "int[]").WithLocation(17, 13),
                // (18,48): error CS1503: Argument 1: cannot convert from 'ref int[]' to 'ref System.Span<int>'
                //         Extensions1.op_IncrementAssignment(ref a1);
                Diagnostic(ErrorCode.ERR_BadArgType, "a1").WithArguments("1", "ref int[]", "ref System.Span<int>").WithLocation(18, 48)
                );
        }
 
        [Fact]
        public void Increment_041_Consumption_Generic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(S1<T>) where T : struct
    {
        public static S1<T> operator ++(S1<T> x)
        {
            System.Console.Write(typeof(T).ToString());
            return x;
        }
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1<int>();
        s1 = ++s1;
        Extensions1.op_Increment(s1);
 
        S1<int>? s2 = new S1<int>();
        _ = (++s2).GetValueOrDefault();
        s2 = null;
        System.Console.Write(":");
        _ = (++s2).GetValueOrDefault();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "System.Int32System.Int32System.Int32:").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_042_Consumption_Generic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(ref S1<T> x) where T : struct
    {
        public void operator ++()
        {
            System.Console.Write(typeof(T).ToString());
        }
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1<int>();
        s1 = ++s1;
        Extensions1.op_IncrementAssignment(ref s1);
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "System.Int32System.Int32").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_043_Consumption_Generic_Worse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(S1<T>)
    {
        public static S1<T> operator ++(S1<T> x)
        {
            System.Console.Write("[S1<T>]");
            return x;
        }
    }
 
    extension<T>(S1<T>?)
    {
        public static S1<T>? operator ++(S1<T>? x)
        {
            System.Console.Write("[S1<T>?]");
            return x;
        }
    }
 
    extension(S1<int>)
    {
        public static S1<int> operator ++(S1<int> x)
        {
            System.Console.Write("[S1<int>]");
            return x;
        }
    }
 
    extension<T>(S2<T>)
    {
        public static S2<T> operator ++(in S2<T> x) => throw null;
 
        public static S2<T> operator ++(S2<T> x)
        {
            System.Console.Write("[S2<T>]");
            return x;
        }
    }
 
    extension(S2<int>)
    {
        public static S2<int> operator ++(in S2<int> x)
        {
            System.Console.Write("[in S2<int>]");
            return x;
        }
    }
}
 
public struct S1<T>
{}
 
public struct S2<T>
{}
 
class Program
{
    static void Main()
    {
        var s11 = new S1<int>();
        s11 = ++s11;
        Extensions1.op_Increment(s11);
 
        System.Console.WriteLine();
 
        var s12 = new S1<byte>();
        s12 = ++s12;
        Extensions1.op_Increment(s12);
 
        System.Console.WriteLine();
 
        var s21 = new S2<int>();
        s21 = ++s21;
        Extensions1.op_Increment(s21);
 
        System.Console.WriteLine();
 
        var s22 = new S2<byte>();
        s22 = ++s22;
        Extensions1.op_Increment(s22);
 
        System.Console.WriteLine();
 
        S1<int>? s13 = new S1<int>();
        s13 = ++s13;
        s13 = null;
        s13 = ++s13;
 
        System.Console.WriteLine();
 
        S1<byte>? s14 = new S1<byte>();
        s14 = ++s14;
        s14 = null;
        s14 = ++s14;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: @"
[S1<int>][S1<int>]
[S1<T>][S1<T>]
[in S2<int>][in S2<int>]
[S2<T>][S2<T>]
[S1<int>]
[S1<T>?][S1<T>?]
").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_044_Consumption_Generic_Worse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(ref S1<T> x)
    {
        public void operator ++()
        {
            System.Console.Write("[S1<T>]");
        }
    }
 
    extension<T>(ref S1<T>? x)
    {
        public void operator ++()
        {
            System.Console.Write("[S1<T>?]");
        }
    }
 
    extension(ref S1<int> x)
    {
        public void operator ++()
        {
            System.Console.Write("[S1<int>]");
        }
    }
 
    extension(ref S1<int>? x)
    {
        public void operator ++()
        {
            System.Console.Write("[S1<int>?]");
        }
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s11 = new S1<int>();
        s11 = ++s11;
        Extensions1.op_IncrementAssignment(ref s11);
 
        System.Console.WriteLine();
 
        var s12 = new S1<byte>();
        s12 = ++s12;
        Extensions1.op_IncrementAssignment(ref s12);
 
        System.Console.WriteLine();
 
        S1<int>? s13 = new S1<int>();
        s13 = ++s13;
        s13 = null;
        s13 = ++s13;
 
        System.Console.WriteLine();
 
        S1<byte>? s14 = new S1<byte>();
        s14 = ++s14;
        s14 = null;
        s14 = ++s14;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: @"
[S1<int>][S1<int>]
[S1<T>][S1<T>]
[S1<int>?][S1<int>?]
[S1<T>?][S1<T>?]
").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_045_Consumption_Generic_ConstraintsViolation()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(S1<T>) where T : class
    {
        public static S1<T> operator ++(S1<T> x) => throw null;
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1<int>();
        _ = ++s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (17,13): error CS0023: Operator '++' cannot be applied to operand of type 'S1<int>'
                //         _ = ++s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s1").WithArguments("++", "S1<int>").WithLocation(17, 13)
                );
        }
 
        [Fact]
        public void Increment_046_Consumption_Generic_ConstraintsViolation()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(ref S1<T> x) where T : class
    {
        public void operator ++() => throw null;
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1<int>();
        _ = ++s1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (17,13): error CS0023: Operator '++' cannot be applied to operand of type 'S1<int>'
                //         _ = ++s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s1").WithArguments("++", "S1<int>").WithLocation(17, 13)
                );
        }
 
        [Fact]
        public void Increment_047_Consumption_OverloadResolutionPriority()
        {
            var src = $$$"""
using System.Runtime.CompilerServices;
 
public static class Extensions1
{
    extension(C1)
    {
        [OverloadResolutionPriority(1)]
        public static C2 operator ++(C1 x)
        {
            System.Console.Write("C1");
            return (C2)x;
        }
    }
    extension(C2)
    {
        public static C2 operator ++(C2 x)
        {
            System.Console.Write("C2");
            return x;
        }
    }
    extension(C3)
    {
        public static C4 operator ++(C3 x)
        {
            System.Console.Write("C3");
            return (C4)x;
        }
    }
    extension(C4)
    {
        public static C4 operator ++(C4 x)
        {
            System.Console.Write("C4");
            return x;
        }
    }
}
 
public class C1;
public class C2 : C1;
 
public class C3;
public class C4 : C3;
 
class Program
{
    static void Main()
    {
        var c2 = new C2();
        _ = ++c2;
        var c4 = new C4();
        _ = ++c4;
    }
}
""";
 
            var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition], options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "C1C4").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_048_Consumption_OverloadResolutionPriority()
        {
            var src = $$$"""
using System.Runtime.CompilerServices;
 
public static class Extensions1
{
    extension(C1 x)
    {
        [OverloadResolutionPriority(1)]
        public void operator ++()
        {
            System.Console.Write("C1");
        }
    }
    extension(C2 x)
    {
        public void operator ++()
        {
            System.Console.Write("C2");
        }
    }
    extension(C3 x)
    {
        public void operator ++()
        {
            System.Console.Write("C3");
        }
    }
    extension(C4 x)
    {
        public void operator ++()
        {
            System.Console.Write("C4");
        }
    }
}
 
public class C1;
public class C2 : C1;
 
public class C3;
public class C4 : C3;
 
class Program
{
    static void Main()
    {
        var c2 = new C2();
        _ = ++c2;
        var c4 = new C4();
        _ = ++c4;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition], options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "C1C4").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_049_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator --(C1 x)
        {
            System.Console.Write("regular");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = --c1;
 
        checked
        {
            _ = --c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularregular").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_050_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator --()
        {
            System.Console.Write("regular");
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = --c1;
 
        checked
        {
            _ = --c1;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularregular").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_051_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator --(C1 x)
        {
            System.Console.Write("regular");
            return x;
        }
        public static C1 operator checked --(C1 x)
        {
            System.Console.Write("checked");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = --c1;
 
        checked
        {
            _ = --c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_052_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator --()
        {
            System.Console.Write("regular");
        }
        public void operator checked --()
        {
            System.Console.Write("checked");
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = --c1;
 
        checked
        {
            _ = --c1;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_053_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator --(C1 x)
        {
            System.Console.Write("regular");
            return x;
        }
    }
    extension(C1)
    {
        public static C1 operator checked --(C1 x)
        {
            System.Console.Write("checked");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = --c1;
 
        checked
        {
            _ = --c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_054_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator --()
        {
            System.Console.Write("regular");
        }
    }
    extension(C1 x)
    {
        public void operator checked --()
        {
            System.Console.Write("checked");
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = --c1;
 
        checked
        {
            _ = --c1;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_055_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator --(C1 x)
        {
            return x;
        }
 
        public static C1 operator checked --(C1 x)
        {
            return x;
        }
    }
}
 
public static class Extensions2
{
    extension(C1)
    {
        public static C1 operator --(C1 x)
        {
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = --c1;
 
        checked
        {
            _ = --c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (35,13): error CS0035: Operator '--' is ambiguous on an operand of type 'C1'
                //         _ = --c1;
                Diagnostic(ErrorCode.ERR_AmbigUnaryOp, "--c1").WithArguments("--", "C1").WithLocation(35, 13),
                // (39,17): error CS0035: Operator '--' is ambiguous on an operand of type 'C1'
                //             _ = --c1;
                Diagnostic(ErrorCode.ERR_AmbigUnaryOp, "--c1").WithArguments("--", "C1").WithLocation(39, 17)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().Last();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("Extensions1.extension(C1).operator checked --(C1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("Extensions2.extension(C1).operator --(C1)", symbolInfo.CandidateSymbols[1].ToDisplayString());
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/78968")]
        public void Increment_056_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator --()
        {
        }
 
        public void operator checked --()
        {
        }
    }
}
 
public static class Extensions2
{
    extension(C1 x)
    {
        public void operator --()
        {
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = --c1;
 
        checked
        {
            _ = --c1;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
#if DEBUG
            comp.VerifyEmitDiagnostics(
                // (32,13): error CS0121: The call is ambiguous between the following methods or properties: 'Extensions2.extension(C1).operator --()' and 'Extensions1.extension(C1).operator --()'
                //         _ = --c1;
                Diagnostic(ErrorCode.ERR_AmbigCall, "--").WithArguments("Extensions2.extension(C1).operator --()", "Extensions1.extension(C1).operator --()").WithLocation(32, 13),
                // (36,17): error CS0121: The call is ambiguous between the following methods or properties: 'Extensions1.extension(C1).operator checked --()' and 'Extensions2.extension(C1).operator --()'
                //             _ = --c1;
                Diagnostic(ErrorCode.ERR_AmbigCall, "--").WithArguments("Extensions1.extension(C1).operator checked --()", "Extensions2.extension(C1).operator --()").WithLocation(36, 17)
                );
#else
            // https://github.com/dotnet/roslyn/issues/78968: Understand what is causing DEBUG/RELEASE behavior difference
            comp.VerifyEmitDiagnostics(
                // (32,13): error CS0121: The call is ambiguous between the following methods or properties: 'Extensions1.extension(C1).operator --()' and 'Extensions2.extension(C1).operator --()'
                //         _ = --c1;
                Diagnostic(ErrorCode.ERR_AmbigCall, "--").WithArguments("Extensions1.extension(C1).operator --()", "Extensions2.extension(C1).operator --()").WithLocation(32, 13),
                // (36,17): error CS0121: The call is ambiguous between the following methods or properties: 'Extensions1.extension(C1).operator checked --()' and 'Extensions2.extension(C1).operator --()'
                //             _ = --c1;
                Diagnostic(ErrorCode.ERR_AmbigCall, "--").WithArguments("Extensions1.extension(C1).operator checked --()", "Extensions2.extension(C1).operator --()").WithLocation(36, 17)
                );
#endif
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().Last();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("Extensions1.extension(C1).operator checked --()", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("Extensions2.extension(C1).operator --()", symbolInfo.CandidateSymbols[1].ToDisplayString());
        }
 
        [Fact]
        public void Increment_057_Consumption_CheckedLiftedIsWorse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator --(S1 x) => throw null;
        public static S1 operator checked --(S1 x) => throw null;
    }
    extension(S1?)
    {
        public static S1? operator --(S1? x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        _ = --s1;
        System.Console.Write(":");
 
        checked
        {
            _ = --s1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_058_Consumption_CheckedNoLiftedForm()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator --() => throw null;
        public void operator checked --() => throw null;
    }
    extension(ref S1? x)
    {
        public void operator --()
        {
            System.Console.Write("operator1");
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        _ = --s1;
        System.Console.Write(":");
 
        checked
        {
            _ = --s1;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_059_Consumption_OverloadResolutionPlusRegularVsChecked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C3 operator --(C1 x)
        {
            System.Console.Write("C1");
            return (C3)x;
        }
        public static C3 operator checked --(C1 x)
        {
            System.Console.Write("checkedC1");
            return (C3)x;
        }
    }
    extension(C2)
    {
        public static C2 operator --(C2 x)
        {
            System.Console.Write("C2");
            return x;
        }
    }
}
 
public class C1;
public class C2 : C1;
public class C3 : C1;
 
class Program
{
    static void Main()
    {
        var c3 = new C3();
        _ = --c3;
 
        checked
        {
            _ = --c3;
        }
 
        var c2 = new C2();
        _ = --c2;
 
        checked
        {
            _ = --c2;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "C1checkedC1C2C2").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_060_Consumption_OverloadResolutionPlusRegularVsChecked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator --()
        {
            System.Console.Write("C1");
        }
        public void operator checked --()
        {
            System.Console.Write("checkedC1");
        }
    }
    extension(C2 x)
    {
        public void operator --()
        {
            System.Console.Write("C2");
        }
    }
}
 
public class C1;
public class C2 : C1;
public class C3 : C1;
 
class Program
{
    static void Main()
    {
        var c3 = new C3();
        _ = --c3;
 
        checked
        {
            _ = --c3;
        }
 
        var c2 = new C2();
        _ = --c2;
 
        checked
        {
            _ = --c2;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "C1checkedC1C2C2").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_061_Consumption()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1? operator ++(S1? x)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public static void M1(S1? x) {}
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
#line 21
        _ = ++s1;
        S1 s2 = new S1();
        _ = ++s2;
 
        System.Nullable<S1>.M1(s1);
        S1.M1(s1);
        S1.M1(s2);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyEmitDiagnostics(
                // (5,36): error CS9318: The parameter type for ++ or -- operator must be the extended type.
                //         public static S1? operator ++(S1? x)
                Diagnostic(ErrorCode.ERR_BadExtensionIncDecSignature, "++").WithLocation(5, 36),
                // (21,13): error CS0023: Operator '++' cannot be applied to operand of type 'S1?'
                //         _ = ++s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s1").WithArguments("++", "S1?").WithLocation(21, 13),
                // (23,13): error CS0266: Cannot implicitly convert type 'S1?' to 'S1'. An explicit conversion exists (are you missing a cast?)
                //         _ = ++s2;
                Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "++s2").WithArguments("S1?", "S1").WithLocation(23, 13),
                // (25,9): error CS1929: 'S1?' does not contain a definition for 'M1' and the best extension method overload 'Extensions1.extension(S1).M1(S1?)' requires a receiver of type 'S1'
                //         System.Nullable<S1>.M1(s1);
                Diagnostic(ErrorCode.ERR_BadInstanceArgType, "System.Nullable<S1>").WithArguments("S1?", "M1", "Extensions1.extension(S1).M1(S1?)", "S1").WithLocation(25, 9)
                );
        }
 
        [Fact]
        public void Increment_062_Consumption_OnObject()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static object operator ++(object x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
        _ = ++s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_063_Consumption_OnObject()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object x)
    {
        public void operator ++()
        {
            System.Console.Write("operator1");
        }
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
        _ = ++s1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_064_Consumption_NotOnDynamic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object y)
    {
        public static object operator ++(object x)
        {
            System.Console.Write("operator1");
            return x;
        }
        public void operator ++()
        {
            System.Console.Write("operator2");
        }
    }
}
 
class Program
{
    static void Main()
    {
        dynamic s1 = new object();
        try
        {
            _ = ++s1;
        }
        catch
        {
            System.Console.Write("exception");
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "exception").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_065_Consumption_BadOperand()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object y)
    {
        public static object operator ++(object x)
        {
            System.Console.Write("operator1");
            return x;
        }
        public void operator ++()
        {
            System.Console.Write("operator2");
        }
    }
}
 
class Program
{
    static void Main()
    {
#line 19
        _ = ++null;
        _ = ++default;
        _ = ++new();
        _ = ++(() => 1);
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (19,15): error CS1059: The operand of an increment or decrement operator must be a variable, property or indexer
                //         _ = ++null;
                Diagnostic(ErrorCode.ERR_IncrementLvalueExpected, "null").WithLocation(19, 15),
                // (20,15): error CS1059: The operand of an increment or decrement operator must be a variable, property or indexer
                //         _ = ++default;
                Diagnostic(ErrorCode.ERR_IncrementLvalueExpected, "default").WithLocation(20, 15),
                // (21,15): error CS1059: The operand of an increment or decrement operator must be a variable, property or indexer
                //         _ = ++new();
                Diagnostic(ErrorCode.ERR_IncrementLvalueExpected, "new()").WithLocation(21, 15),
                // (22,16): error CS1059: The operand of an increment or decrement operator must be a variable, property or indexer
                //         _ = ++(() => 1);
                Diagnostic(ErrorCode.ERR_IncrementLvalueExpected, "() => 1").WithLocation(22, 16)
                );
        }
 
        [Fact]
        public void Increment_066_Consumption_BadOperand()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object y)
    {
        public void operator ++()
        {
            System.Console.Write("operator2");
        }
    }
}
 
class Program
{
    static object P {get; set;}
 
    static void Main()
    {
        _ = ++P;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (18,13): error CS0023: Operator '++' cannot be applied to operand of type 'object'
                //         _ = ++P;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++P").WithArguments("++", "object").WithLocation(18, 13)
                );
        }
 
        [Fact]
        public void Increment_067_Consumption_BadReceiver()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(__arglist)
    {
        public static object operator ++(object x)
        {
            return x;
        }
        public void operator ++()
        {
        }
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
#line 17
        _ = ++s1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (3,15): error CS1669: __arglist is not valid in this context
                //     extension(__arglist)
                Diagnostic(ErrorCode.ERR_IllegalVarArgs, "__arglist").WithLocation(3, 15),
                // (5,39): error CS9318: The parameter type for ++ or -- operator must be the extended type.
                //         public static object operator ++(object x)
                Diagnostic(ErrorCode.ERR_BadExtensionIncDecSignature, "++").WithLocation(5, 39),
                // (17,13): error CS0023: Operator '++' cannot be applied to operand of type 'object'
                //         _ = ++s1;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s1").WithArguments("++", "object").WithLocation(17, 13)
                );
        }
 
        [Fact]
        public void Increment_068_Consumption_Checked_Generic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T1>(C1<T1>)
    {
        public static C1<T1> operator --(C1<T1> x)
        {
            System.Console.Write("regular");
            return x;
        }
    }
    extension<T2>(C1<T2>)
    {
        public static C1<T2> operator checked --(C1<T2> x)
        {
            System.Console.Write("checked");
            return x;
        }
    }
}
 
public class C1<T>;
 
class Program
{
    static void Main()
    {
        var c1 = new C1<int>();
        _ = --c1;
 
        checked
        {
            _ = --c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_069_Consumption_Checked_Generic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T1>(C1<T1> x)
    {
        public void operator --()
        {
            System.Console.Write("regular");
        }
    }
    extension<T2>(C1<T2> x)
    {
        public void operator checked --()
        {
            System.Console.Write("checked");
        }
    }
}
 
public class C1<T>;
 
class Program
{
    static void Main()
    {
        var c1 = new C1<int>();
        _ = --c1;
 
        checked
        {
            _ = --c1;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Increment_070_Consumption_Postfix(bool fromMetadata)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator ++(S1 x)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            return new S1 { F = x.F + 1 };
        }
    }
}
 
public struct S1
{
    public int F;
}
""";
 
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1() { F = 101 };
        s1++;
        System.Console.Write(":");
        System.Console.Write(s1.F);
        System.Console.Write(":");
        var s2 = s1++;
        System.Console.Write(":");
        System.Console.Write(s2.F);
        System.Console.Write(":");
        System.Console.Write(s1.F);
    }
}
""";
 
            var comp1 = CreateCompilation(src1);
            var comp1Ref = fromMetadata ? comp1.EmitToImageReference() : comp1.ToMetadataReference();
 
            var comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:102:operator1:102:102:103").VerifyDiagnostics();
 
            var tree = comp2.SyntaxTrees.First();
            var model = comp2.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PostfixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(S1).operator ++(S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:102:operator1:102:102:103").VerifyDiagnostics();
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            comp2.VerifyEmitDiagnostics(
                // (6,9): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                //         s1++;
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "s1++").WithArguments("extensions").WithLocation(6, 9),
                // (10,18): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                //         var s2 = s1++;
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "s1++").WithArguments("extensions").WithLocation(10, 18)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Increment_071_Consumption_Postfix(bool fromMetadata)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator ++()
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            x.F++;
        }
    }
}
 
public struct S1
{
    public int F;
}

""" + CompilerFeatureRequiredAttribute;
 
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1() { F = 101 };
        s1++;
        System.Console.Write(":");
        System.Console.Write(s1.F);
    }
}
""";
 
            var comp1 = CreateCompilation(src1);
            var comp1Ref = fromMetadata ? comp1.EmitToImageReference() : comp1.ToMetadataReference();
 
            var comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:102").VerifyDiagnostics();
 
            var tree = comp2.SyntaxTrees.First();
            var model = comp2.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.PostfixUnaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(ref S1).operator ++()", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("System.Void", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:102").VerifyDiagnostics();
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            comp2.VerifyEmitDiagnostics(
                // (6,9): error CS0023: Operator '++' cannot be applied to operand of type 'S1'
                //         s1++;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "s1++").WithArguments("++", "S1").WithLocation(6, 9)
                );
 
            var src3 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        _ = s1++;
    }
}
""";
            var comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe);
            comp3.VerifyDiagnostics(
                // (6,13): error CS0023: Operator '++' cannot be applied to operand of type 'S1'
                //         _ = s1++;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "s1++").WithArguments("++", "S1").WithLocation(6, 13)
                );
 
            var src4 = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator ++()
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            x.F++;
        }
    }
}
 
public class C1
{
    public int F;
}

""" + CompilerFeatureRequiredAttribute;
 
            var src5 = $$$"""
class Program
{
    static void Main()
    {
        var c1 = new C1() { F = 101 };
        var c2 = c1;
        c1++;
        System.Console.Write(":");
        System.Console.Write(c1.F);
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c1, c2) ? "True" : "False");
    }
}
""";
 
            var comp4 = CreateCompilation(src4);
            var comp4Ref = fromMetadata ? comp4.EmitToImageReference() : comp4.ToMetadataReference();
 
            var comp5 = CreateCompilation(src5, references: [comp4Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp5, expectedOutput: "operator1:101:102:True").VerifyDiagnostics();
 
            var src6 = $$$"""
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1++;
    }
}
""";
            var comp6 = CreateCompilation(src6, references: [comp4Ref], options: TestOptions.DebugExe);
            comp6.VerifyDiagnostics(
                // (6,13): error CS0023: Operator '++' cannot be applied to operand of type 'C1'
                //         _ = c1++;
                Diagnostic(ErrorCode.ERR_BadUnaryOp, "c1++").WithArguments("++", "C1").WithLocation(6, 13)
                );
        }
 
        [Fact]
        public void Increment_072_Consumption_ExpressionTree()
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator ++(S1 x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1, S1>> ex = (s1) => ++s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (22,54): error CS0832: An expression tree may not contain an assignment operator
                //         Expression<System.Func<S1, S1>> ex = (s1) => ++s1;
                Diagnostic(ErrorCode.ERR_ExpressionTreeContainsAssignment, "++s1").WithLocation(22, 54)
                );
        }
 
        [Fact]
        public void Increment_073_Consumption_ExpressionTree()
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator --()
        {
            System.Console.Write("operator1");
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1, S1>> ex = (s1) => --s1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (21,54): error CS0832: An expression tree may not contain an assignment operator
                //         Expression<System.Func<S1, S1>> ex = (s1) => --s1;
                Diagnostic(ErrorCode.ERR_ExpressionTreeContainsAssignment, "--s1").WithLocation(21, 54)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_Scoped_Left
        /// </summary>
        [Fact]
        public void Increment_074_RefSafety()
        {
            var source = """
public ref struct C
{
    public static C X(scoped C left) => throw null;
    public void M(scoped C c1)
    {
#line 7
        ++c1;
#line 9
        c1 = X(c1);
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator ++(scoped C left) => throw null;
    }
}
""";
 
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics();
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_Scoped_Left
        /// </summary>
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/78964")]
        public void Increment_075_RefSafety()
        {
            var source = """
public ref struct C
{
    public static C X(scoped C left) => throw null;
    public C M(C c, scoped C c1)
    {
#line 7
        c = ++c1;
#line 9
        c = X(c1);
        return c;
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator ++(scoped C left) => throw null;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics(
                // The error is unexpected, but it is a preexisting condition - https://github.com/dotnet/roslyn/issues/78964.
 
                // (7,13): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         c = ++c1;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "++c1").WithArguments("scoped C c1").WithLocation(7, 13)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_Scoped_Left
        /// </summary>
        [Fact]
        public void Increment_076_RefSafety()
        {
            var source = """
public ref struct C
{
    public C M(C c, scoped C c1)
    {
#line 7
        c = c1++;
        return c;
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator ++(scoped C left) => throw null;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics(
                // (7,13): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         c = c1++;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1++").WithArguments("scoped C c1").WithLocation(7, 13)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_ScopedTarget_01
        /// </summary>
        [Fact]
        public void Increment_077_RefSafety()
        {
            var source = """
public ref struct C
{
    public C M(scoped C c, C c1)
    {
        c = ++c1;
        return c1;
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator ++(C right) => right;
    }
}
""";
            CreateCompilation(source).VerifyDiagnostics();
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_ScopedTarget_01
        /// </summary>
        [Fact]
        public void Increment_078_RefSafety()
        {
            var source = """
public ref struct C
{
    public C M(scoped C c, C c1)
    {
        c = c1++;
        return c1;
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator ++(C right) => right;
    }
}
""";
            CreateCompilation(source).VerifyDiagnostics();
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_Scoped_Left
        /// </summary>
        [Fact]
        public void Increment_079_RefSafety()
        {
            var source = """
public ref struct C
{
    public void X() => throw null;
    public void M(scoped C c1)
    {
#line 7
        ++c1;
#line 9
        c1.X();
    }
}
 
static class Extensions
{
    extension(scoped ref C left)
    {
        public void operator ++() => throw null;
    }
}
""";
 
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics();
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_Scoped_Left
        /// </summary>
        [Fact]
        public void Increment_080_RefSafety()
        {
            var source = """
public ref struct C
{
    public void X() => throw null;
    public C M(C c, scoped C c1)
    {
#line 7
        c = ++c1;
#line 9
        c1.X();
        c = c1;
        return c;
    }
}
 
static class Extensions
{
    extension(scoped ref C left)
    {
        public void operator ++() => throw null;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics(
                // (7,13): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         c = ++c1;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "++c1").WithArguments("scoped C c1").WithLocation(7, 13),
                // (10,13): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         c = c1;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(10, 13)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_ScopedTarget_01
        /// </summary>
        [Fact]
        public void Increment_081_RefSafety()
        {
            var source = """
public ref struct C
{
    public C M(scoped C c, C c1)
    {
        c = ++c1;
        return c1;
    }
}
 
static class Extensions
{
    extension(ref C right)
    {
        public void operator ++() {}
    }
}
 
""" + CompilerFeatureRequiredAttribute;
 
            CreateCompilation(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_082_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator --(C1 x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public class C1
{}
 
class Program
{
    static void Main()
    {
        C1? x = null;
        _ = --x;
        C1 y = new C1();
        y = --y;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (23,15): warning CS8604: Possible null reference argument for parameter 'x' in 'C1 extension(C1).operator --(C1 x)'.
                //         _ = --x;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "C1 extension(C1).operator --(C1 x)").WithLocation(23, 15)
                );
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/79011")]
        public void Increment_083_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1)
    {
        public static C1? operator --(C1 x)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public class C1
{}
 
class Program
{
    static void Main()
    {
        C1? x = new C1();
        C1 y = --x;
        C1 z = new C1();
        --z;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // This warning is unexpected - https://github.com/dotnet/roslyn/issues/79011
                // (23,16): warning CS8601: Possible null reference assignment.
                //         C1 y = --x;
                Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "--x").WithLocation(23, 16),
 
                // (23,16): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         C1 y = --x;
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "--x").WithLocation(23, 16),
                // (25,9): warning CS8601: Possible null reference assignment.
                //         --z;
                Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "--z").WithLocation(25, 9)
                );
        }
 
        [Fact]
        public void Increment_084_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T)
    {
        public static T operator --(T x)
        {
            return x;
        }
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        (--x).ToString();
        var y = new C2();
        (--y).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyDiagnostics(
                // (22,10): warning CS8602: Dereference of a possibly null reference.
                //         (--x).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "--x").WithLocation(22, 10)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().ToArray();
 
            Assert.Equal(2, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator --(C2?)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2>(C2).operator --(C2)", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void Increment_085_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(C1<T>) where T : new()
    {
        public static C1<T> operator --(C1<T> x)
        {
            return x;
        }
    }
}
 
public class C1<T> where T : new()
{
    public T F = new T();
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        (--x).F.ToString();
        var y = Get(new C2());
        (--y).F.ToString();
    }
 
    static C1<T> Get<T>(T x) where T : new()
    {
        return new C1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (27,9): warning CS8602: Dereference of a possibly null reference.
                //         (--x).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(--x).F").WithLocation(27, 9)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().ToArray();
 
            Assert.Equal(2, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?>(C1<C2?>).operator --(C1<C2?>)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2>(C1<C2>).operator --(C1<C2>)", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void Increment_086_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public class C1<T> where T : new()
{
    public T F = new T();
 
    public static C1<T> operator --(C1<T> x)
    {
        return x;
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
#line 27
        (--x).F.ToString();
        var y = Get(new C2());
        (--y).F.ToString();
    }
 
    static C1<T> Get<T>(T x) where T : new()
    {
        return new C1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (27,9): warning CS8602: Dereference of a possibly null reference.
                //         (--x).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(--x).F").WithLocation(27, 9)
                );
        }
 
        [Fact]
        public void Increment_087_NullableAnalysis_Lifted()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(S1<T>) where T : new()
    {
        public static S1<T> operator --(S1<T> x)
        {
            return x;
        }
    }
}
 
public struct S1<T> where T : new()
{
    public T F;
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = --Get((C2?)null);
 
        if (x != null)
            x.Value.F.ToString();
 
        var y = --Get(new C2());
 
        if (y != null)
            y.Value.F.ToString();
    }
 
    static ref S1<T>? Get<T>(T x) where T : new()
    {
        throw null!;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (29,13): warning CS8602: Dereference of a possibly null reference.
                //             x.Value.F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Value.F").WithLocation(29, 13)
                );
        }
 
        [Fact]
        public void Increment_088_NullableAnalysis_Lifted()
        {
            var src = $$$"""
#nullable enable
 
public struct S1<T> where T : new()
{
    public T F;
 
    public static S1<T> operator --(S1<T> x)
    {
        return x;
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = --Get((C2?)null);
 
        if (x != null)
#line 29
            x.Value.F.ToString();
 
        var y = --Get(new C2());
 
        if (y != null)
            y.Value.F.ToString();
    }
 
    static ref S1<T>? Get<T>(T x) where T : new()
    {
        throw null!;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (29,13): warning CS8602: Dereference of a possibly null reference.
                //             x.Value.F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Value.F").WithLocation(29, 13)
                );
        }
 
        [Fact]
        public void Increment_089_NullableAnalysis_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T) where T : notnull
    {
        public static T operator --(T x)
        {
            return x;
        }
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        (--x).ToString();
        var y = new C2();
        (--y).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyDiagnostics(
                // (22,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(T)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (--x).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "--x").WithArguments("Extensions1.extension<T>(T)", "T", "C2?").WithLocation(22, 10),
                // (22,10): warning CS8602: Dereference of a possibly null reference.
                //         (--x).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "--x").WithLocation(22, 10)
                );
        }
 
        [Fact]
        public void Increment_090_NullableAnalysis_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(C1<T>) where T : notnull, new()
    {
        public static C1<T> operator --(C1<T> x)
        {
            return x;
        }
    }
}
 
public class C1<T> where T : new()
{
    public T F = new T();
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        (--x).F.ToString();
        var y = Get(new C2());
        (--y).F.ToString();
    }
 
    static C1<T> Get<T>(T x) where T : new()
    {
        return new C1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (27,9): warning CS8602: Dereference of a possibly null reference.
                //         (--x).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(--x).F").WithLocation(27, 9),
                // (27,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(C1<T>)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (--x).F.ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "--x").WithArguments("Extensions1.extension<T>(C1<T>)", "T", "C2?").WithLocation(27, 10)
                );
        }
 
        [Fact]
        public void Increment_091_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator --() {}
    }
 
    extension(C2? x)
    {
        public void operator --() {}
    }
}
 
public class C1
{}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C1? x = null;
        var x1 = --x;
        x.ToString();
        x1.ToString();
 
        C1 y = new C1();
        var y1 = --y;
        y.ToString();
        y1.ToString();
 
        C2? z = null;
        var z1 = --z;
        z.ToString();
        z1.ToString();
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (27,20): warning CS8604: Possible null reference argument for parameter 'x' in 'extension(C1)'.
                //         var x1 = --x;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "extension(C1)").WithLocation(27, 20),
                // (38,9): warning CS8602: Dereference of a possibly null reference.
                //         z.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(38, 9),
                // (39,9): warning CS8602: Dereference of a possibly null reference.
                //         z1.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z1").WithLocation(39, 9)
                );
        }
 
        [Fact]
        public void Increment_092_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
using System.Diagnostics.CodeAnalysis;
 
public static class Extensions1
{
    extension([NotNull] ref S1? x)
    {
        public void operator --() { throw null!; }
    }
 
    extension([NotNull] C2? x)
    {
        public void operator --() { throw null!; }
    }
}
 
public struct S1
{}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        S1? x = null;
        var x1 = --x;
        _ = x.Value;
        _ = x1.Value;
 
        C2? z = null;
        var z1 = --z;
        z.ToString();
        z1.ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_093_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(ref S1? x)
    {
        public void operator --() {}
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? x = null;
        var x1 = --x;
        _ = x.Value;
        _ = x1.Value;
 
        S1? y = new S1();
        var y1 = --y;
        _ = y.Value;
        _ = y1.Value;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (20,13): warning CS8629: Nullable value type may be null.
                //         _ = x.Value;
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(20, 13),
                // (21,13): warning CS8629: Nullable value type may be null.
                //         _ = x1.Value;
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x1").WithLocation(21, 13),
                // (25,13): warning CS8629: Nullable value type may be null.
                //         _ = y.Value;
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(25, 13),
                // (26,13): warning CS8629: Nullable value type may be null.
                //         _ = y1.Value;
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y1").WithLocation(26, 13)
                );
        }
 
        [Fact]
        public void Increment_094_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(ref S1? x)
    {
        public void operator --() {}
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        _ = Get(new S1()).Value;
        var y1 = --Get(new S1());
#line 26
        _ = y1.Value;
    }
 
    [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("x")]
    static ref S1? Get(S1? x) => throw null!;
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (26,13): warning CS8629: Nullable value type may be null.
                //         _ = y1.Value;
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y1").WithLocation(26, 13)
                );
        }
 
        [Fact]
        public void Increment_095_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1Base x)
    {
        public void operator --() {}
    }
 
    extension(C2Base? x)
    {
        public void operator --() {}
    }
}
 
public class C1Base {}
public class C1 : C1Base {}
 
public class C2Base {}
public class C2 : C2Base {}
 
class Program
{
    static void Main()
    {
        C1? x = null;
        var x1 = --x;
        x.ToString();
        x1.ToString();
 
        C1 y = new C1();
        var y1 = --y;
        y.ToString();
        y1.ToString();
 
        C2? z = null;
        var z1 = --z;
        z.ToString();
        z1.ToString();
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (27,20): warning CS8604: Possible null reference argument for parameter 'x' in 'extension(C1Base)'.
                //         var x1 = --x;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "extension(C1Base)").WithLocation(27, 20),
                // (38,9): warning CS8602: Dereference of a possibly null reference.
                //         z.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(38, 9),
                // (39,9): warning CS8602: Dereference of a possibly null reference.
                //         z1.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z1").WithLocation(39, 9)
                );
        }
 
        [Fact]
        public void Increment_096_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C2Base<string> x)
    {
        public void operator --() {}
    }
}
 
public class C2Base<T> {}
public class C2<T> : C2Base<T> {}
 
class Program
{
    static void Main()
    {
        C2<string?> z = new C2<string?>();
        var z1 = --z;
        z.ToString();
        z1.ToString();
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (19,20): warning CS8620: Argument of type 'C2<string?>' cannot be used for parameter 'x' of type 'C2Base<string>' in 'extension(C2Base<string>)' due to differences in the nullability of reference types.
                //         var z1 = --z;
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("C2<string?>", "C2Base<string>", "x", "extension(C2Base<string>)").WithLocation(19, 20)
                );
        }
 
        [Fact]
        public void Increment_097_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
using System.Diagnostics.CodeAnalysis;
 
public static class Extensions1
{
    extension([NotNull] C2Base? x)
    {
        public void operator --() { throw null!; }
    }
}
 
public class C2Base
{}
 
public class C2 : C2Base
{}
 
class Program
{
    static void Main()
    {
        C2? z = null;
        var z1 = --z;
        z.ToString();
        z1.ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
        }
 
        [Fact]
        public void Increment_098_NullableAnalysis_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T x) where T : class
    {
        public void operator --() {}
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        (--x).ToString();
        var y = new C2();
        (--y).ToString();
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (19,10): warning CS8634: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(T)'. Nullability of type argument 'C2?' doesn't match 'class' constraint.
                //         (--x).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "--x").WithArguments("Extensions1.extension<T>(T)", "T", "C2?").WithLocation(19, 10),
                // (19,10): warning CS8602: Dereference of a possibly null reference.
                //         (--x).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "--x").WithLocation(19, 10)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().ToArray();
 
            Assert.Equal(2, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator --()", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2>(C2).operator --()", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void Increment_099_NullableAnalysis_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(C1<T> x) where T : notnull, new()
    {
        public void operator --() {}
    }
}
 
public class C1<T> where T : new()
{
    public T F = new T();
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        (--x).F.ToString();
        var y = Get(new C2());
        (--y).F.ToString();
    }
 
    static C1<T> Get<T>(T x) where T : new()
    {
        return new C1<T>();
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (24,9): warning CS8602: Dereference of a possibly null reference.
                //         (--x).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(--x).F").WithLocation(24, 9),
                // (24,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(C1<T>)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (--x).F.ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "--x").WithArguments("Extensions1.extension<T>(C1<T>)", "T", "C2?").WithLocation(24, 10)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.PrefixUnaryExpressionSyntax>().ToArray();
 
            Assert.Equal(2, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?>(C1<C2?>).operator --()", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2>(C1<C2>).operator --()", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void Increment_100_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T x) where T : class?
    {
        public void operator --() {}
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        (--x).ToString();
        var y = new C2();
        (--y).ToString();
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (19,10): warning CS8602: Dereference of a possibly null reference.
                //         (--x).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "--x").WithLocation(19, 10)
                );
        }
 
        [Fact]
        public void Increment_101_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(C1<T> x) where T : new()
    {
        public void operator --() {}
    }
}
 
public class C1<T> where T : new()
{
    public T F = new T();
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        (--x).F.ToString();
        var y = Get(new C2());
        (--y).F.ToString();
    }
 
    static C1<T> Get<T>(T x) where T : new()
    {
        return new C1<T>();
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (24,9): warning CS8602: Dereference of a possibly null reference.
                //         (--x).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(--x).F").WithLocation(24, 9)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_001_Declaration([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(S1)
    {
        public static S2 operator {{{op}}}(S1 x, S2 y) => default;
        public static S2? operator {{{op}}}(S1? x, S2 y) => default;
        public static S2 operator {{{op}}}(S2 y, S1 x) => default;
        public static S2? operator {{{op}}}(S2 y, S1? x) => default;
    }
}
 
static class Extensions2
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S2 x, S2 y) => default;
    }
}
 
static class Extensions3
{
    extension(S1)
    {
        public static void operator {{{op}}}(S1 x, S2 y) {}
    }
}
 
static class Extensions4
{
    extension(S1)
    {
        static S1 operator {{{op}}}(S1 x, S1 y) => default;
    }
 
    extension(S2)
    {
        public S2 operator {{{op}}}(S2 x, S2 y) => default;
    }
 
    extension(C1)
    {
        public static S1 operator {{{op}}}(C1 x, S1 y) => default;
    }
}
 
static class Extensions5
{
    extension(S1?)
    {
        public static S2 operator {{{op}}}(S1 x, S1 y) => default;
        public static S2 operator {{{op}}}(S1? x, S2 y) => default;
        public static S2 operator {{{op}}}(S2 y, S1? x) => default;
    }
}
 
struct S1
{}
 
struct S2
{}
 
static class C1
{}
""";
            var comp = CreateCompilation(src);
            comp.VerifyEmitDiagnostics(
                // (6,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator +(S1? x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, op).WithLocation(6, 36),
                // (8,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator +(S2 y, S1? x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, op).WithLocation(8, 36),
                // (16,35): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S1 operator -(S2 x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, op).WithLocation(16, 35),
                // (24,37): error CS0590: User-defined operators cannot return void
                //         public static void operator +(S1 x, S2 y) {}
                Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, op).WithLocation(24, 37),
                // (32,28): error CS0558: User-defined operator 'Extensions4.extension(S1).operator +(S1, S1)' must be declared static and public
                //         static S1 operator +(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, op).WithArguments("Extensions4.extension(S1).operator " + op + "(S1, S1)").WithLocation(32, 28),
                // (37,28): error CS0558: User-defined operator 'Extensions4.extension(S2).operator +(S2, S2)' must be declared static and public
                //         public S2 operator +(S2 x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, op).WithArguments("Extensions4.extension(S2).operator " + op + "(S2, S2)").WithLocation(37, 28),
                // (42,35): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public static S1 operator +(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, op).WithLocation(42, 35),
                // (42,37): error CS0721: 'C1': static types cannot be used as parameters
                //         public static S1 operator +(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C1").WithArguments("C1").WithLocation(42, 37),
                // (50,35): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2 operator +(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, op).WithLocation(50, 35)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_002_Declaration([CombinatorialValues("<<", ">>", ">>>")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(S1)
    {
        public static S2 operator {{{op}}}(S1 x, S2 y) => default;
        public static S2? operator {{{op}}}(S1? x, S2 y) => default;
    }
}
 
static class Extensions2
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S2 x, S1 y) => default;
    }
}
 
static class Extensions3
{
    extension(S1)
    {
        public static void operator {{{op}}}(S1 x, S2 y) {}
    }
}
 
static class Extensions4
{
    extension(S1)
    {
        static S1 operator {{{op}}}(S1 x, S1 y) => default;
    }
    extension(S2)
    {
        public S2 operator {{{op}}}(S2 x, S2 y) => default;
    }
    extension(C1)
    {
        public static S1 operator {{{op}}}(C1 x, S1 y) => default;
    }
}
 
static class Extensions5
{
    extension(S1?)
    {
        public static S2 operator {{{op}}}(S1 x, S1 y) => default;
        public static S2 operator {{{op}}}(S1? x, S2 y) => default;
        public static S2 operator {{{op}}}(S2 y, S1? x) => default;
    }
}
 
struct S1
{}
 
struct S2
{}
 
static class C1
{}
""";
            var comp = CreateCompilation(src);
            comp.VerifyEmitDiagnostics(
                // (6,36): error CS9320: The first operand of an overloaded shift operator must have the same type as the extended type
                //         public static S2? operator <<(S1? x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionShiftOperatorSignature, op).WithLocation(6, 36),
                // (14,35): error CS9320: The first operand of an overloaded shift operator must have the same type as the extended type
                //         public static S1 operator <<(S2 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionShiftOperatorSignature, op).WithLocation(14, 35),
                // (22,37): error CS0590: User-defined operators cannot return void
                //         public static void operator <<(S1 x, S2 y) {}
                Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, op).WithLocation(22, 37),
                // (30,28): error CS0558: User-defined operator 'Extensions4.extension(S1).operator <<(S1, S1)' must be declared static and public
                //         static S1 operator <<(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, op).WithArguments("Extensions4.extension(S1).operator " + op + "(S1, S1)").WithLocation(30, 28),
                // (34,28): error CS0558: User-defined operator 'Extensions4.extension(S2).operator <<(S2, S2)' must be declared static and public
                //         public S2 operator <<(S2 x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, op).WithArguments("Extensions4.extension(S2).operator " + op + "(S2, S2)").WithLocation(34, 28),
                // (38,35): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public static S1 operator >>>(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, op).WithLocation(38, 35),
                // (38,39): error CS0721: 'C1': static types cannot be used as parameters
                //         public static S1 operator >>>(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C1").WithArguments("C1").WithLocation(38, 39 - (op == ">>>" ? 0 : 1)),
                // (46,35): error CS9320: The first operand of an overloaded shift operator must have the same type as the extended type
                //         public static S2 operator <<(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionShiftOperatorSignature, op).WithLocation(46, 35),
                // (48,35): error CS9320: The first operand of an overloaded shift operator must have the same type as the extended type
                //         public static S2 operator <<(S2 y, S1? x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionShiftOperatorSignature, op).WithLocation(48, 35)
                );
        }
 
        [Fact]
        public void Binary_003_Declaration()
        {
            var src = """
static class Extensions1
{
    extension(S1)
    {
#line 100
        public static S2 operator !=(S1 x, S2 y) => default;
        public static S2 operator ==(S1 x, S2 y) => default;
        public static S2? operator !=(S1? x, S2 y) => default;
        public static S2? operator ==(S1? x, S2 y) => default;
        public static S2 operator !=(S2 y, S1 x) => default;
        public static S2 operator ==(S2 y, S1 x) => default;
        public static S2? operator !=(S2 y, S1? x) => default;
        public static S2? operator ==(S2 y, S1? x) => default;
    }
}
 
static class Extensions2
{
    extension(S1)
    {
#line 200
        public static bool operator !=(S1 x, S2 y) => default;
    }
 
    extension(S1)
    {
#line 300
        public static bool operator ==(S1 x, S2 y) => default;
    }
}
 
static class Extensions3
{
    extension(S1)
    {
#line 400
        public static bool operator !=(S1 x, S2 y) => default;
    }
 
    extension(S2)
    {
        public static bool operator ==(S2 x, S1 y) => default;
    }
}
 
static class Extensions4
{
    extension(S1)
    {
#line 500
        public static bool operator !=(S2 x, S2 y) => default;
        public static bool operator ==(S2 x, S2 y) => default;
    }
}
 
static class Extensions5
{
    extension(S1)
    {
#line 600
        public static void operator !=(S1 x, S2 y) {}
        public static void operator ==(S1 x, S2 y) {}
    }
}
 
static class Extensions6
{
    extension(S1)
    {
#line 700
        static S1 operator !=(S1 x, S1 y) => default;
        public S1 operator ==(S1 x, S1 y) => default;
    }
    extension(C1)
    {
#line 800
        public static S1 operator !=(C1 x, S1 y) => default;
        public static S1 operator ==(C1 x, S1 y) => default;
    }
}
 
static class Extensions7
{
    extension(S1?)
    {
#line 900
        public static S2 operator !=(S1 x, S1 y) => default;
        public static S2 operator !=(S1? x, S2 y) => default;
        public static S2 operator !=(S2 y, S1? x) => default;
 
        public static S2 operator ==(S1 x, S1 y) => default;
        public static S2 operator ==(S1? x, S2 y) => default;
        public static S2 operator ==(S2 y, S1? x) => default;
    }
}
 
struct S1
{}
 
struct S2
{}
 
static class C1
{}
""";
            var comp = CreateCompilation(src);
            comp.VerifyEmitDiagnostics(
                // (102,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator !=(S1? x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "!=").WithLocation(102, 36),
                // (103,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator ==(S1? x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "==").WithLocation(103, 36),
                // (106,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator !=(S2 y, S1? x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "!=").WithLocation(106, 36),
                // (107,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator ==(S2 y, S1? x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "==").WithLocation(107, 36),
                // (400,37): error CS0216: The operator 'Extensions3.extension(S1).operator !=(S1, S2)' requires a matching operator '==' to also be defined
                //         public static bool operator !=(S1 x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorNeedsMatch, "!=").WithArguments("Extensions3.extension(S1).operator !=(S1, S2)", "==").WithLocation(400, 37),
                // (405,37): error CS0216: The operator 'Extensions3.extension(S2).operator ==(S2, S1)' requires a matching operator '!=' to also be defined
                //         public static bool operator ==(S2 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorNeedsMatch, "==").WithArguments("Extensions3.extension(S2).operator ==(S2, S1)", "!=").WithLocation(405, 37),
                // (500,37): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static bool operator !=(S2 x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "!=").WithLocation(500, 37),
                // (501,37): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static bool operator ==(S2 x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "==").WithLocation(501, 37),
                // (600,37): error CS0590: User-defined operators cannot return void
                //         public static void operator !=(S1 x, S2 y) {}
                Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, "!=").WithLocation(600, 37),
                // (601,37): error CS0590: User-defined operators cannot return void
                //         public static void operator ==(S1 x, S2 y) {}
                Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, "==").WithLocation(601, 37),
                // (700,28): error CS0558: User-defined operator 'Extensions6.extension(S1).operator !=(S1, S1)' must be declared static and public
                //         static S1 operator !=(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, "!=").WithArguments("Extensions6.extension(S1).operator !=(S1, S1)").WithLocation(700, 28),
                // (701,28): error CS0558: User-defined operator 'Extensions6.extension(S1).operator ==(S1, S1)' must be declared static and public
                //         public S1 operator ==(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, "==").WithArguments("Extensions6.extension(S1).operator ==(S1, S1)").WithLocation(701, 28),
                // (800,35): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public static S1 operator !=(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, "!=").WithLocation(800, 35),
                // (800,38): error CS0721: 'C1': static types cannot be used as parameters
                //         public static S1 operator !=(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C1").WithArguments("C1").WithLocation(800, 38),
                // (801,35): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public static S1 operator ==(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, "==").WithLocation(801, 35),
                // (801,38): error CS0721: 'C1': static types cannot be used as parameters
                //         public static S1 operator ==(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C1").WithArguments("C1").WithLocation(801, 38),
                // (900,35): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2 operator !=(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "!=").WithLocation(900, 35),
                // (904,35): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2 operator ==(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "==").WithLocation(904, 35)
                );
        }
 
        [Fact]
        public void Binary_004_Declaration()
        {
            var src = """
static class Extensions1
{
    extension(S1)
    {
#line 100
        public static S2 operator >=(S1 x, S2 y) => default;
        public static S2 operator <=(S1 x, S2 y) => default;
        public static S2? operator >=(S1? x, S2 y) => default;
        public static S2? operator <=(S1? x, S2 y) => default;
        public static S2 operator >=(S2 y, S1 x) => default;
        public static S2 operator <=(S2 y, S1 x) => default;
        public static S2? operator >=(S2 y, S1? x) => default;
        public static S2? operator <=(S2 y, S1? x) => default;
    }
}
 
static class Extensions2
{
    extension(S1)
    {
#line 200
        public static bool operator >=(S1 x, S2 y) => default;
    }
 
    extension(S1)
    {
#line 300
        public static bool operator <=(S1 x, S2 y) => default;
    }
}
 
static class Extensions3
{
    extension(S1)
    {
#line 400
        public static bool operator >=(S1 x, S2 y) => default;
    }
 
    extension(S2)
    {
        public static bool operator <=(S2 x, S1 y) => default;
    }
}
 
static class Extensions4
{
    extension(S1)
    {
#line 500
        public static bool operator >=(S2 x, S2 y) => default;
        public static bool operator <=(S2 x, S2 y) => default;
    }
}
 
static class Extensions5
{
    extension(S1)
    {
#line 600
        public static void operator >=(S1 x, S2 y) {}
        public static void operator <=(S1 x, S2 y) {}
    }
}
 
static class Extensions6
{
    extension(S1)
    {
#line 700
        static S1 operator >=(S1 x, S1 y) => default;
        public S1 operator <=(S1 x, S1 y) => default;
    }
    extension(C1)
    {
#line 800
        public static S1 operator >=(C1 x, S1 y) => default;
        public static S1 operator <=(C1 x, S1 y) => default;
    }
}
 
static class Extensions7
{
    extension(S1?)
    {
#line 900
        public static S2 operator >=(S1 x, S1 y) => default;
        public static S2 operator >=(S1? x, S2 y) => default;
        public static S2 operator >=(S2 y, S1? x) => default;
 
        public static S2 operator <=(S1 x, S1 y) => default;
        public static S2 operator <=(S1? x, S2 y) => default;
        public static S2 operator <=(S2 y, S1? x) => default;
    }
}
 
struct S1
{}
 
struct S2
{}
 
static class C1
{}
""";
            var comp = CreateCompilation(src);
            comp.VerifyEmitDiagnostics(
                // (102,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator >=(S1? x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, ">=").WithLocation(102, 36),
                // (103,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator <=(S1? x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "<=").WithLocation(103, 36),
                // (106,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator >=(S2 y, S1? x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, ">=").WithLocation(106, 36),
                // (107,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator <=(S2 y, S1? x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "<=").WithLocation(107, 36),
                // (400,37): error CS0216: The operator 'Extensions3.extension(S1).operator >=(S1, S2)' requires a matching operator '<=' to also be defined
                //         public static bool operator >=(S1 x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorNeedsMatch, ">=").WithArguments("Extensions3.extension(S1).operator >=(S1, S2)", "<=").WithLocation(400, 37),
                // (405,37): error CS0216: The operator 'Extensions3.extension(S2).operator <=(S2, S1)' requires a matching operator '>=' to also be defined
                //         public static bool operator <=(S2 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorNeedsMatch, "<=").WithArguments("Extensions3.extension(S2).operator <=(S2, S1)", ">=").WithLocation(405, 37),
                // (500,37): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static bool operator >=(S2 x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, ">=").WithLocation(500, 37),
                // (501,37): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static bool operator <=(S2 x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "<=").WithLocation(501, 37),
                // (600,37): error CS0590: User-defined operators cannot return void
                //         public static void operator >=(S1 x, S2 y) {}
                Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, ">=").WithLocation(600, 37),
                // (601,37): error CS0590: User-defined operators cannot return void
                //         public static void operator <=(S1 x, S2 y) {}
                Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, "<=").WithLocation(601, 37),
                // (700,28): error CS0558: User-defined operator 'Extensions6.extension(S1).operator >=(S1, S1)' must be declared static and public
                //         static S1 operator >=(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, ">=").WithArguments("Extensions6.extension(S1).operator >=(S1, S1)").WithLocation(700, 28),
                // (701,28): error CS0558: User-defined operator 'Extensions6.extension(S1).operator <=(S1, S1)' must be declared static and public
                //         public S1 operator <=(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, "<=").WithArguments("Extensions6.extension(S1).operator <=(S1, S1)").WithLocation(701, 28),
                // (800,35): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public static S1 operator >=(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, ">=").WithLocation(800, 35),
                // (800,38): error CS0721: 'C1': static types cannot be used as parameters
                //         public static S1 operator >=(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C1").WithArguments("C1").WithLocation(800, 38),
                // (801,35): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public static S1 operator <=(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, "<=").WithLocation(801, 35),
                // (801,38): error CS0721: 'C1': static types cannot be used as parameters
                //         public static S1 operator <=(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C1").WithArguments("C1").WithLocation(801, 38),
                // (900,35): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2 operator >=(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, ">=").WithLocation(900, 35),
                // (904,35): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2 operator <=(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "<=").WithLocation(904, 35)
                );
        }
 
        [Fact]
        public void Binary_005_Declaration()
        {
            var src = """
static class Extensions1
{
    extension(S1)
    {
#line 100
        public static S2 operator >(S1 x, S2 y) => default;
        public static S2 operator <(S1 x, S2 y) => default;
        public static S2? operator >(S1? x, S2 y) => default;
        public static S2? operator <(S1? x, S2 y) => default;
        public static S2 operator >(S2 y, S1 x) => default;
        public static S2 operator <(S2 y, S1 x) => default;
        public static S2? operator >(S2 y, S1? x) => default;
        public static S2? operator <(S2 y, S1? x) => default;
    }
}
 
static class Extensions2
{
    extension(S1)
    {
#line 200
        public static bool operator >(S1 x, S2 y) => default;
    }
 
    extension(S1)
    {
#line 300
        public static bool operator <(S1 x, S2 y) => default;
    }
}
 
static class Extensions3
{
    extension(S1)
    {
#line 400
        public static bool operator >(S1 x, S2 y) => default;
    }
 
    extension(S2)
    {
        public static bool operator <(S2 x, S1 y) => default;
    }
}
 
static class Extensions4
{
    extension(S1)
    {
#line 500
        public static bool operator >(S2 x, S2 y) => default;
        public static bool operator <(S2 x, S2 y) => default;
    }
}
 
static class Extensions5
{
    extension(S1)
    {
#line 600
        public static void operator >(S1 x, S2 y) {}
        public static void operator <(S1 x, S2 y) {}
    }
}
 
static class Extensions6
{
    extension(S1)
    {
#line 700
        static S1 operator >(S1 x, S1 y) => default;
        public S1 operator <(S1 x, S1 y) => default;
    }
    extension(C1)
    {
#line 800
        public static S1 operator >(C1 x, S1 y) => default;
        public static S1 operator <(C1 x, S1 y) => default;
    }
}
 
static class Extensions7
{
    extension(S1?)
    {
#line 900
        public static S2 operator >(S1 x, S1 y) => default;
        public static S2 operator >(S1? x, S2 y) => default;
        public static S2 operator >(S2 y, S1? x) => default;
 
        public static S2 operator <(S1 x, S1 y) => default;
        public static S2 operator <(S1? x, S2 y) => default;
        public static S2 operator <(S2 y, S1? x) => default;
    }
}
 
struct S1
{}
 
struct S2
{}
 
static class C1
{}
""";
            var comp = CreateCompilation(src);
            comp.VerifyEmitDiagnostics(
                // (102,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator >(S1? x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, ">").WithLocation(102, 36),
                // (103,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator <(S1? x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "<").WithLocation(103, 36),
                // (106,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator >(S2 y, S1? x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, ">").WithLocation(106, 36),
                // (107,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator <(S2 y, S1? x) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "<").WithLocation(107, 36),
                // (400,37): error CS0216: The operator 'Extensions3.extension(S1).operator >(S1, S2)' requires a matching operator '<' to also be defined
                //         public static bool operator >(S1 x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorNeedsMatch, ">").WithArguments("Extensions3.extension(S1).operator >(S1, S2)", "<").WithLocation(400, 37),
                // (405,37): error CS0216: The operator 'Extensions3.extension(S2).operator <(S2, S1)' requires a matching operator '>' to also be defined
                //         public static bool operator <(S2 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorNeedsMatch, "<").WithArguments("Extensions3.extension(S2).operator <(S2, S1)", ">").WithLocation(405, 37),
                // (500,37): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static bool operator >(S2 x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, ">").WithLocation(500, 37),
                // (501,37): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static bool operator <(S2 x, S2 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "<").WithLocation(501, 37),
                // (600,37): error CS0590: User-defined operators cannot return void
                //         public static void operator >(S1 x, S2 y) {}
                Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, ">").WithLocation(600, 37),
                // (601,37): error CS0590: User-defined operators cannot return void
                //         public static void operator <(S1 x, S2 y) {}
                Diagnostic(ErrorCode.ERR_OperatorCantReturnVoid, "<").WithLocation(601, 37),
                // (700,28): error CS0558: User-defined operator 'Extensions6.extension(S1).operator >(S1, S1)' must be declared static and public
                //         static S1 operator >(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, ">").WithArguments("Extensions6.extension(S1).operator >(S1, S1)").WithLocation(700, 28),
                // (701,28): error CS0558: User-defined operator 'Extensions6.extension(S1).operator <(S1, S1)' must be declared static and public
                //         public S1 operator <(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorsMustBeStaticAndPublic, "<").WithArguments("Extensions6.extension(S1).operator <(S1, S1)").WithLocation(701, 28),
                // (800,35): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public static S1 operator >(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, ">").WithLocation(800, 35),
                // (800,37): error CS0721: 'C1': static types cannot be used as parameters
                //         public static S1 operator >(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C1").WithArguments("C1").WithLocation(800, 37),
                // (801,35): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public static S1 operator <(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, "<").WithLocation(801, 35),
                // (801,37): error CS0721: 'C1': static types cannot be used as parameters
                //         public static S1 operator <(C1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C1").WithArguments("C1").WithLocation(801, 37),
                // (900,35): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2 operator >(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, ">").WithLocation(900, 35),
                // (904,35): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2 operator <(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "<").WithLocation(904, 35)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_006_Declaration([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>", ">>>")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x, S1 y) => default;
    }
}
 
public struct S1
{}
""";
            var comp = CreateCompilation(src);
            CompileAndVerify(comp, symbolValidator: verify, sourceSymbolValidator: verify).VerifyDiagnostics();
 
            void verify(ModuleSymbol m)
            {
                var name = BinaryOperatorName(op);
                var method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + name);
 
                AssertEx.Equal("Extensions1." + name + "(S1, S1)", method.ToDisplayString());
                Assert.Equal(MethodKind.Ordinary, method.MethodKind);
                Assert.True(method.IsStatic);
                Assert.False(method.IsExtensionMethod);
                Assert.False(method.HasSpecialName);
                Assert.False(method.HasRuntimeSpecialName);
                Assert.False(method.HasUnsupportedMetadata);
            }
        }
 
        private static string BinaryOperatorName(string op)
        {
            var kind = op switch
            {
                ">>" => SyntaxKind.GreaterThanGreaterThanToken,
                ">>>" => SyntaxKind.GreaterThanGreaterThanGreaterThanToken,
                _ => SyntaxFactory.ParseToken(op).Kind(),
            };
            return OperatorFacts.BinaryOperatorNameFromSyntaxKind(kind, isChecked: false);
        }
 
        [Fact]
        public void Binary_007_Declaration()
        {
            var src = """
static class Extensions1
{
    extension(S1)
    {
        public static bool operator !=(S1 x, S1 y) => default;
        public static bool operator ==(S1 x, S1 y) => default;
        public static bool operator >=(S1 x, S1 y) => default;
        public static bool operator <=(S1 x, S1 y) => default;
        public static bool operator >(S1 x, S1 y) => default;
        public static bool operator <(S1 x, S1 y) => default;
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src);
            CompileAndVerify(comp, symbolValidator: verify, sourceSymbolValidator: verify).VerifyDiagnostics();
 
            void verify(ModuleSymbol m)
            {
                var method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + WellKnownMemberNames.EqualityOperatorName);
                AssertEx.Equal("Extensions1." + WellKnownMemberNames.EqualityOperatorName + "(S1, S1)", method.ToDisplayString());
                verifyMethod(method);
 
                method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + WellKnownMemberNames.InequalityOperatorName);
                AssertEx.Equal("Extensions1." + WellKnownMemberNames.InequalityOperatorName + "(S1, S1)", method.ToDisplayString());
                verifyMethod(method);
 
                method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + WellKnownMemberNames.GreaterThanOrEqualOperatorName);
                AssertEx.Equal("Extensions1." + WellKnownMemberNames.GreaterThanOrEqualOperatorName + "(S1, S1)", method.ToDisplayString());
                verifyMethod(method);
 
                method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + WellKnownMemberNames.LessThanOrEqualOperatorName);
                AssertEx.Equal("Extensions1." + WellKnownMemberNames.LessThanOrEqualOperatorName + "(S1, S1)", method.ToDisplayString());
                verifyMethod(method);
 
                method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + WellKnownMemberNames.GreaterThanOperatorName);
                AssertEx.Equal("Extensions1." + WellKnownMemberNames.GreaterThanOperatorName + "(S1, S1)", method.ToDisplayString());
                verifyMethod(method);
 
                method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + WellKnownMemberNames.LessThanOperatorName);
                AssertEx.Equal("Extensions1." + WellKnownMemberNames.LessThanOperatorName + "(S1, S1)", method.ToDisplayString());
                verifyMethod(method);
            }
 
            static void verifyMethod(MethodSymbol method)
            {
                Assert.Equal(MethodKind.Ordinary, method.MethodKind);
                Assert.True(method.IsStatic);
                Assert.False(method.IsExtensionMethod);
                Assert.False(method.HasSpecialName);
                Assert.False(method.HasRuntimeSpecialName);
                Assert.False(method.HasUnsupportedMetadata);
            }
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_008_Declaration([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>", ">>>")] string op, [CombinatorialValues("virtual", "abstract", "new", "override", "sealed", "readonly", "extern")] string modifier)
        {
            var src = $$$"""
static class Extensions1
{
    extension(S1)
    {
        {{{modifier}}}
        public static S1 operator {{{op}}}(S1 x, S1 y) => default;
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src);
            comp.VerifyEmitDiagnostics(
                // (6,35): error CS0106: The modifier 'abstract' is not valid for this item
                //         public static S1 operator -(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_BadMemberFlag, op).WithArguments(modifier).WithLocation(6, 35)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_009_Declaration([CombinatorialValues("virtual", "abstract", "new", "override", "sealed", "readonly", "extern")] string modifier)
        {
            var src = $$$"""
static class Extensions1
{
    extension(S1)
    {
        {{{modifier}}}
        public static bool operator !=(S1 x, S1 y) => default;
 
        {{{modifier}}}
        public static bool operator ==(S1 x, S1 y) => default;
 
        {{{modifier}}}
        public static bool operator >=(S1 x, S1 y) => default;
 
        {{{modifier}}}
        public static bool operator <=(S1 x, S1 y) => default;
 
        {{{modifier}}}
        public static bool operator >(S1 x, S1 y) => default;
 
        {{{modifier}}}
        public static bool operator <(S1 x, S1 y) => default;
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src);
            comp.VerifyEmitDiagnostics(
                    // (6,37): error CS0106: The modifier 'abstract' is not valid for this item
                    //         public static bool operator !=(S1 x, S1 y) => default;
                    Diagnostic(ErrorCode.ERR_BadMemberFlag, "!=").WithArguments(modifier).WithLocation(6, 37),
                    // (9,37): error CS0106: The modifier 'abstract' is not valid for this item
                    //         public static bool operator ==(S1 x, S1 y) => default;
                    Diagnostic(ErrorCode.ERR_BadMemberFlag, "==").WithArguments(modifier).WithLocation(9, 37),
                    // (12,37): error CS0106: The modifier 'abstract' is not valid for this item
                    //         public static bool operator >=(S1 x, S1 y) => default;
                    Diagnostic(ErrorCode.ERR_BadMemberFlag, ">=").WithArguments(modifier).WithLocation(12, 37),
                    // (15,37): error CS0106: The modifier 'abstract' is not valid for this item
                    //         public static bool operator <=(S1 x, S1 y) => default;
                    Diagnostic(ErrorCode.ERR_BadMemberFlag, "<=").WithArguments(modifier).WithLocation(15, 37),
                    // (18,37): error CS0106: The modifier 'abstract' is not valid for this item
                    //         public static bool operator >(S1 x, S1 y) => default;
                    Diagnostic(ErrorCode.ERR_BadMemberFlag, ">").WithArguments(modifier).WithLocation(18, 37),
                    // (21,37): error CS0106: The modifier 'abstract' is not valid for this item
                    //         public static bool operator <(S1 x, S1 y) => default;
                    Diagnostic(ErrorCode.ERR_BadMemberFlag, "<").WithArguments(modifier).WithLocation(21, 37)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_010_Declaration([CombinatorialValues("+", "-", "*", "/")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(S1)
    {
        public static S1 operator checked {{{op}}}(S1 x, S1 y) => default;
        public static S1 operator {{{op}}}(S1 x, S1 y) => default;
    }
}
 
static class Extensions2
{
    extension(S1)
    {
#line 100
        public static S1 operator checked {{{op}}}(S1 x, S1 y) => default;
    }
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x, S1 y) => default;
    }
}
 
static class Extensions3
{
    extension(S1)
    {
        public static S1 operator checked {{{op}}}(S1 x, S1 y) => default;
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src);
            comp.VerifyEmitDiagnostics(
                // (112,43): error CS9025: The operator 'Extensions3.extension(S1).operator checked +(S1, S1)' requires a matching non-checked version of the operator to also be defined
                //         public static S1 operator checked +(S1 x, S1 y) => default;
                Diagnostic(ErrorCode.ERR_CheckedOperatorNeedsMatch, op).WithArguments("Extensions3.extension(S1).operator checked " + op + "(S1, S1)").WithLocation(112, 43)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_011_Consumption(bool fromMetadata)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x, S1 y)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            System.Console.Write(y.F);
            return new S1 { F = x.F + y.F };
        }
    }
}
 
public struct S1
{
    public int F;
}
""";
 
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        var s11 = new S1() { F = 101 };
        var s12 = new S1() { F = 202 };
        var s2 = s11 + s12;
        System.Console.Write(":");
        System.Console.Write(s11.F);
        System.Console.Write(":");
        System.Console.Write(s12.F);
        System.Console.Write(":");
        System.Console.Write(s2.F);
    }
}
""";
 
            var comp1 = CreateCompilation(src1);
            var comp1Ref = fromMetadata ? comp1.EmitToImageReference() : comp1.ToMetadataReference();
 
            var comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:202:101:202:303").VerifyDiagnostics();
 
            var tree = comp2.SyntaxTrees.First();
            var model = comp2.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(S1).operator +(S1, S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:202:101:202:303").VerifyDiagnostics();
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            comp2.VerifyEmitDiagnostics(
                // (7,18): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                //         var s2 = s11 + s12;
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "s11 + s12").WithArguments("extensions").WithLocation(7, 18)
                );
 
            var src3 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        Extensions1.op_Addition(s1, s1);
    }
}
""";
            var comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp3, expectedOutput: "operator1:0:0").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp3, expectedOutput: "operator1:0:0").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            CompileAndVerify(comp3, expectedOutput: "operator1:0:0").VerifyDiagnostics();
 
            var src4 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1.op_Addition(s1);
        S1.op_Addition(s1, s1);
    }
}
""";
            var comp4 = CreateCompilation(src4, references: [comp1Ref]);
            comp4.VerifyEmitDiagnostics(
                // (6,12): error CS1061: 'S1' does not contain a definition for 'op_Addition' and no accessible extension method 'op_Addition' accepting a first argument of type 'S1' could be found (are you missing a using directive or an assembly reference?)
                //         s1.op_Addition(s1);
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "op_Addition").WithArguments("S1", "op_Addition").WithLocation(6, 12),
                // (7,12): error CS0117: 'S1' does not contain a definition for 'op_Addition'
                //         S1.op_Addition(s1, s1);
                Diagnostic(ErrorCode.ERR_NoSuchMember, "op_Addition").WithArguments("S1", "op_Addition").WithLocation(7, 12)
                );
        }
 
        [Fact]
        public void Binary_012_Consumption_PredefinedComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S2 x, S2 y) => throw null;
    }
}
 
public struct S2
{
    public static implicit operator int(S2 x)
    {
        System.Console.Write("operator2");
        return 0;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        int x = s2 + s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("int.operator +(int, int)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("System.Int32", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Binary_013_Consumption_NonExtensionComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S2 x, S2 y) => throw null;
    }
}
 
public struct S2
{
    public static S2 operator +(S2 x, S2 y)
    {
        System.Console.Write("operator2");
        return x;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = s2 + s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("S2.operator +(S2, S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Binary_014_Consumption_ScopeByScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x, S1 y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(S1)
        {
            public static S1 operator +(S1 x, S1 y)
            {
                System.Console.Write("operator1");
                return x;
            }
        }
    }
 
    namespace NS2
    {
        public static class Extensions3
        {
            extension(S2)
            {
                public static S2 operator +(S2 x, S2 y) => throw null;
            }
        }
 
        class Program
        {
            static void Main()
            {
                var s1 = new S1();
                _ = s1 + s1;
            }
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("NS1.Extensions2.extension(S1).operator +(S1, S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Binary_015_Consumption_NonExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1
{
    public static I1 operator -(I1 x, I1 y) => x;
}
 
public interface I3
{
    public static I3 operator -(I3 x, I3 y) => x;
}
 
public interface I4 : I1, I3
{
}
 
public interface I2 : I4
{
}
 
public static class Extensions1
{
    extension(I2)
    {
        public static I2 operator -(I2 x, I2 y) => x;
    }
}
 
class Test2 : I2
{
    static void Main()
    {
        I2 x = new Test2();
        var y = x - x;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (32,17): error CS0034: Operator '-' is ambiguous on operands of type 'I2' and 'I2'
                //         var y = x - x;
                Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "x - x").WithArguments("-", "I2", "I2").WithLocation(32, 17)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("I1.operator -(I1, I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("I3.operator -(I3, I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/78830")]
        public void Binary_016_Consumption_ExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1;
public interface I3;
public interface I4 : I1, I3;
public interface I2 : I4;
 
public static class Extensions1
{
    extension(I2)
    {
        public static I2 operator -(I2 x, I2 y) => x;
    }
}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(I1)
        {
            public static I1 operator -(I1 x, I1 y) => x;
        }
 
        extension(I3)
        {
            public static I3 operator -(I3 x, I3 y) => x;
        }
    }
 
    class Test2 : I2
    {
        static void Main()
        {
            I2 x = new Test2();
            var y = x - x;
        }
    }
}
""";
 
            var comp = CreateCompilation(src);
 
            // https://github.com/dotnet/roslyn/issues/78830: We might want to include more information into the error. Like what methods conflict.
            comp.VerifyEmitDiagnostics(
                // (34,21): error CS0034: Operator '-' is ambiguous on operands of type 'I2' and 'I2'
                //             var y = x - x;
                Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "x - x").WithArguments("-", "I2", "I2").WithLocation(34, 21)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("NS1.Extensions2.extension(I1).operator -(I1, I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("NS1.Extensions2.extension(I3).operator -(I3, I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_017_Consumption_Lifted([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>", ">>>")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s11 = new S1();
        S1? s12 = new S1();
        _ = s11 {{{op}}} s12;
        System.Console.Write(":");
        s11 = null;
        _ = s11 {{{op}}} s12;
        _ = s12 {{{op}}} s11;
        _ = s11 {{{op}}} s11;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_018_Consumption_Lifted([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>", ">>>")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s11 = new S1();
        S1 s12 = new S1();
        _ = s11 {{{op}}} s12;
        _ = s12 {{{op}}} s11;
        System.Console.Write(":");
        s11 = null;
        _ = s11 {{{op}}} s12;
        _ = s12 {{{op}}} s11;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1operator1:").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_019_Consumption_Lifted([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x, S2 y)
        {
            System.Console.Write("operator1");
            return x;
        }
        public static S1 operator {{{op}}}(S2 x, S1 y)
        {
            System.Console.Write("operator2");
            return y;
        }
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        S2? s2 = new S2();
        _ = s1 {{{op}}} s2;
        _ = s2 {{{op}}} s1;
        System.Console.Write(":");
        s1 = null;
        _ = s1 {{{op}}} s2;
        _ = s2 {{{op}}} s1;
        s1 = new S1();
        s2 = null;
        _ = s1 {{{op}}} s2;
        _ = s2 {{{op}}} s1;
        s1 = null;
        _ = s1 {{{op}}} s2;
        _ = s2 {{{op}}} s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1operator2:").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_020_Consumption_Lifted_Shift([CombinatorialValues("<<", ">>", ">>>")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x, S2 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        S2? s2 = new S2();
        _ = s1 {{{op}}} s2;
        System.Console.Write(":");
        s1 = null;
        _ = s1 {{{op}}} s2;
        s1 = new S1();
        s2 = null;
        _ = s1 {{{op}}} s2;
        s1 = null;
        _ = s1 {{{op}}} s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_021_Consumption_Lifted([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x, S2 y)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            System.Console.Write(y.F);
            return new S1 { F = x.F * 1000 + y.F };
        }
        public static S1 operator {{{op}}}(S2 x, S1 y)
        {
            System.Console.Write("operator2:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            System.Console.Write(y.F);
            return new S1 { F = x.F * 1000 + y.F };
        }
    }
}
 
public struct S1
{
    public int F;
}
 
public struct S2
{
    public int F;
}
 
class Program
{
    static void Main()
    {
        S1? s11 = new S1() { F = 101 };
        S2 s12 = new S2() { F = 202 };
        S1 s21 = new S1() { F = 303 };
        S2? s22 = new S2() { F = 404 };
        Print(s11 {{{op}}} s12);
        System.Console.WriteLine();
        Print(s12 {{{op}}} s11);
        System.Console.WriteLine();
        Print(s21 {{{op}}} s22);
        System.Console.WriteLine();
        Print(s22 {{{op}}} s21);
        System.Console.WriteLine();
        s11 = null;
        s22 = null;
        Print(s11 {{{op}}} s12);
        System.Console.WriteLine();
        Print(s12 {{{op}}} s11);
        System.Console.WriteLine();
        Print(s21 {{{op}}} s22);
        System.Console.WriteLine();
        Print(s22 {{{op}}} s21);
        System.Console.WriteLine();
        Print(s11 {{{op}}} s22);
        System.Console.WriteLine();
        Print(s22 {{{op}}} s11);
    }
 
    static void Print(S1? x)
    {
        System.Console.Write(":");
        System.Console.Write(x?.F ?? -1);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput:
@"
operator1:101:202:101202
operator2:202:101:202101
operator1:303:404:303404
operator2:404:303:404303
:-1
:-1
:-1
:-1
:-1
:-1
").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_022_Consumption_Lifted_Shift([CombinatorialValues("<<", ">>", ">>>")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x, S2 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
class Program
{
    static void Main()
    {
        S1? s11 = new S1();
        S2 s12 = new S2();
        S1 s21 = new S1();
        S2? s22 = new S2();
        _ = s11 {{{op}}} s12;
        _ = s21 {{{op}}} s22;
        System.Console.Write(":");
        s11 = null;
        s22 = null;
        _ = s11 {{{op}}} s12;
        _ = s21 {{{op}}} s22;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1operator1:").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_023_Consumption_LiftedIsWorse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x, S1 y) => throw null;
    }
    extension(S1?)
    {
        public static S1? operator +(S1? x, S1? y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        _ = s1 + s1;
        System.Console.Write(":");
        s1 = null;
        _ = s1 + s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_024_Consumption_ExtendedTypeIsNullable()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1?)
    {
        public static S1? operator +(S1? x, S1? y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = s1 + s1;
        Extensions1.op_Addition(s1, s1);
 
        S1? s2 = new S1();
        _ = s2 + s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (21,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s1 + s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 + s1").WithArguments("+", "S1", "S1").WithLocation(21, 13)
                );
        }
 
        [Fact]
        public void Binary_025_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S2 x, S2 y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S2(S1 x) => default;
}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        S2 s2 = new S2();
        _ = s1 + s2;
        _ = s2 + s1;
        _ = s1 + s1;
        Extensions1.op_Addition(s1, s1);
 
        S1? s3 = new S1();
        _ = s3 + s3;
        Extensions1.op_Addition(s3, s3);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (25,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s1 + s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 + s1").WithArguments("+", "S1", "S1").WithLocation(25, 13),
                // (29,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1?' and 'S1?'
                //         _ = s3 + s3;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s3 + s3").WithArguments("+", "S1?", "S1?").WithLocation(29, 13),
                // (30,33): error CS1503: Argument 1: cannot convert from 'S1?' to 'S2'
                //         Extensions1.op_Addition(s3, s3);
                Diagnostic(ErrorCode.ERR_BadArgType, "s3").WithArguments("1", "S1?", "S2").WithLocation(30, 33),
                // (30,37): error CS1503: Argument 2: cannot convert from 'S1?' to 'S2'
                //         Extensions1.op_Addition(s3, s3);
                Diagnostic(ErrorCode.ERR_BadArgType, "s3").WithArguments("2", "S1?", "S2").WithLocation(30, 37)
                );
 
            var src1 = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S2 x, S1 y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S2(S1 x) => default;
    public static implicit operator S1(S2 x) => default;
}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        S2 s2 = new S2();
        _ = s1 + s1;
        _ = s1 + s2;
        _ = s2 + s1;
        _ = s2 + s2;
        Extensions1.op_Addition(s1, s1);
        Extensions1.op_Addition(s1, s2);
    }
}
""";
 
            var comp1 = CreateCompilation(src1, options: TestOptions.DebugExe);
            comp1.VerifyEmitDiagnostics(
                // (24,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s1 + s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 + s1").WithArguments("+", "S1", "S1").WithLocation(24, 13),
                // (25,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1' and 'S2'
                //         _ = s1 + s2;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 + s2").WithArguments("+", "S1", "S2").WithLocation(25, 13)
                );
 
            var src2 = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S1 x, S2 y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S2(S1 x) => default;
    public static implicit operator S1(S2 x) => default;
}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        S2 s2 = new S2();
        _ = s1 + s1;
        _ = s1 + s2;
        _ = s2 + s1;
        _ = s2 + s2;
        Extensions1.op_Addition(s1, s1);
        Extensions1.op_Addition(s2, s1);
    }
}
""";
 
            var comp2 = CreateCompilation(src2, options: TestOptions.DebugExe);
            comp2.VerifyEmitDiagnostics(
                // (24,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s1 + s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 + s1").WithArguments("+", "S1", "S1").WithLocation(24, 13),
                // (26,13): error CS0019: Operator '+' cannot be applied to operands of type 'S2' and 'S1'
                //         _ = s2 + s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s2 + s1").WithArguments("+", "S2", "S1").WithLocation(26, 13)
                );
 
            var src3 = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2? operator +(S2? x, S1? y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S2(S1 x) => default;
    public static implicit operator S1(S2 x) => default;
}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        S2 s2 = new S2();
        _ = s1 + s1;
        _ = s1 + s2;
        _ = s2 + s1;
        _ = s2 + s2;
        Extensions1.op_Addition(s1, s1);
        Extensions1.op_Addition(s1, s2);
    }
}
""";
 
            var comp3 = CreateCompilation(src3, options: TestOptions.DebugExe);
            comp3.VerifyEmitDiagnostics(
                // (5,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator +(S2? x, S1? y) => throw null;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "+").WithLocation(5, 36),
                // (24,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s1 + s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 + s1").WithArguments("+", "S1", "S1").WithLocation(24, 13),
                // (25,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1' and 'S2'
                //         _ = s1 + s2;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 + s2").WithArguments("+", "S1", "S2").WithLocation(25, 13),
                // (26,13): error CS0019: Operator '+' cannot be applied to operands of type 'S2' and 'S1'
                //         _ = s2 + s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s2 + s1").WithArguments("+", "S2", "S1").WithLocation(26, 13),
                // (27,13): error CS0019: Operator '+' cannot be applied to operands of type 'S2' and 'S2'
                //         _ = s2 + s2;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s2 + s2").WithArguments("+", "S2", "S2").WithLocation(27, 13)
                );
 
            var src4 = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2? operator +(S1? x, S2? y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S2(S1 x) => default;
    public static implicit operator S1(S2 x) => default;
}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        S2 s2 = new S2();
        _ = s1 + s1;
        _ = s1 + s2;
        _ = s2 + s1;
        _ = s2 + s2;
        Extensions1.op_Addition(s1, s1);
        Extensions1.op_Addition(s2, s1);
    }
}
""";
 
            var comp4 = CreateCompilation(src4, options: TestOptions.DebugExe);
            comp4.VerifyEmitDiagnostics(
                // (5,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S2? operator +(S1? x, S2? y) => throw null;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "+").WithLocation(5, 36),
                // (24,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s1 + s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 + s1").WithArguments("+", "S1", "S1").WithLocation(24, 13),
                // (25,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1' and 'S2'
                //         _ = s1 + s2;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 + s2").WithArguments("+", "S1", "S2").WithLocation(25, 13),
                // (26,13): error CS0019: Operator '+' cannot be applied to operands of type 'S2' and 'S1'
                //         _ = s2 + s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s2 + s1").WithArguments("+", "S2", "S1").WithLocation(26, 13),
                // (27,13): error CS0019: Operator '+' cannot be applied to operands of type 'S2' and 'S2'
                //         _ = s2 + s2;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s2 + s2").WithArguments("+", "S2", "S2").WithLocation(27, 13)
                );
        }
 
        [Fact]
        public void Binary_026_Consumption_ReceiverTypeMismatch_Shift()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator <<(S2 x, S2 y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S2(S1 x) => default;
}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        S2 s2 = new S2();
        _ = s1 << s2;
        _ = s2 << s1;
        _ = s1 << s1;
        Extensions1.op_LeftShift(s1, s1);
 
        S1? s3 = new S1();
        _ = s3 << s3;
        Extensions1.op_LeftShift(s3, s3);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (23,13): error CS0019: Operator '<<' cannot be applied to operands of type 'S1' and 'S2'
                //         _ = s1 << s2;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 << s2").WithArguments("<<", "S1", "S2").WithLocation(23, 13),
                // (25,13): error CS0019: Operator '<<' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s1 << s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 << s1").WithArguments("<<", "S1", "S1").WithLocation(25, 13),
                // (29,13): error CS0019: Operator '<<' cannot be applied to operands of type 'S1?' and 'S1?'
                //         _ = s3 << s3;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s3 << s3").WithArguments("<<", "S1?", "S1?").WithLocation(29, 13),
                // (30,34): error CS1503: Argument 1: cannot convert from 'S1?' to 'S2'
                //         Extensions1.op_LeftShift(s3, s3);
                Diagnostic(ErrorCode.ERR_BadArgType, "s3").WithArguments("1", "S1?", "S2").WithLocation(30, 34),
                // (30,38): error CS1503: Argument 2: cannot convert from 'S1?' to 'S2'
                //         Extensions1.op_LeftShift(s3, s3);
                Diagnostic(ErrorCode.ERR_BadArgType, "s3").WithArguments("2", "S1?", "S2").WithLocation(30, 38)
                );
        }
 
        [Fact]
        public void Binary_027_Consumption_Generic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(S1<T>) where T : struct
    {
        public static S1<T> operator +(S1<T> x, S1<T> y)
        {
            System.Console.Write(typeof(T).ToString());
            return x;
        }
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1<int>();
        s1 = s1 + s1;
        Extensions1.op_Addition(s1, s1);
 
        S1<int>? s2 = new S1<int>();
        _ = (s2 + s2).GetValueOrDefault();
        s2 = null;
        System.Console.Write(":");
        _ = (s2 + s2).GetValueOrDefault();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "System.Int32System.Int32System.Int32:").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_027_Consumption_Generic_Worse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(S1<T>)
    {
        public static S1<T> operator +(S1<T> x, S1<T> y)
        {
            System.Console.Write("[S1<T>]");
            return x;
        }
    }
 
    extension<T>(S1<T>?)
    {
        public static S1<T>? operator +(S1<T>? x, S1<T>? y)
        {
            System.Console.Write("[S1<T>?]");
            return x;
        }
    }
 
    extension(S1<int>)
    {
        public static S1<int> operator +(S1<int> x, S1<int> y)
        {
            System.Console.Write("[S1<int>]");
            return x;
        }
    }
 
    extension<T>(S2<T>)
    {
        public static S2<T> operator +(in S2<T> x, S2<T> y) => throw null;
 
        public static S2<T> operator +(S2<T> x, S2<T> y)
        {
            System.Console.Write("[S2<T>]");
            return x;
        }
    }
 
    extension(S2<int>)
    {
        public static S2<int> operator +(in S2<int> x, S2<int> y)
        {
            System.Console.Write("[in S2<int>]");
            return x;
        }
    }
}
 
public struct S1<T>
{}
 
public struct S2<T>
{}
 
class Program
{
    static void Main()
    {
        var s11 = new S1<int>();
        s11 = s11 + s11;
        Extensions1.op_Addition(s11, s11);
 
        System.Console.WriteLine();
 
        var s12 = new S1<byte>();
        s12 = s12 + s12;
        Extensions1.op_Addition(s12, s12);
 
        System.Console.WriteLine();
 
        var s21 = new S2<int>();
        s21 = s21 + s21;
        Extensions1.op_Addition(s21, s21);
 
        System.Console.WriteLine();
 
        var s22 = new S2<byte>();
        s22 = s22 + s22;
        Extensions1.op_Addition(s22, s22);
 
        System.Console.WriteLine();
 
        S1<int>? s13 = new S1<int>();
        s13 = s13 + s13;
        s13 = null;
        s13 = s13 + s13;
 
        System.Console.WriteLine();
 
        S1<byte>? s14 = new S1<byte>();
        s14 = s14 + s14;
        s14 = null;
        s14 = s14 + s14;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: @"
[S1<int>][S1<int>]
[S1<T>][S1<T>]
[in S2<int>][in S2<int>]
[S2<T>][S2<T>]
[S1<int>]
[S1<T>?][S1<T>?]
").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_028_Consumption_Generic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(S1<T>) where T : struct
    {
        public static bool operator >(S1<T> x, S1<T> y)
        {
            System.Console.Write(typeof(T).ToString());
            return true;
        }
        public static bool operator <(S1<T> x, S1<T> y) => throw null;
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s11 = new S1<int>();
        var s12 = new S1<int>();
        bool b = s11 > s12;
        Extensions1.op_GreaterThan(s11, s12);
 
        S1<int>? s21 = new S1<int>();
        S1<int>? s22 = new S1<int>();
        b = s21 > s22;
        s22 = null;
        System.Console.Write(":");
        b = s21 > s22;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "System.Int32System.Int32System.Int32:").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_029_Consumption_Generic_ConstraintsViolation()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(S1<T>) where T : class
    {
        public static S1<T> operator +(S1<T> x, S1<T> y) => throw null;
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1<int>();
        _ = s1 + s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (17,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1<int>' and 'S1<int>'
                //         _ = s1 + s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 + s1").WithArguments("+", "S1<int>", "S1<int>").WithLocation(17, 13)
                );
        }
 
        [Fact]
        public void Binary_030_Consumption_OverloadResolutionPriority()
        {
            var src = $$$"""
using System.Runtime.CompilerServices;
 
public static class Extensions1
{
    extension(C1)
    {
        [OverloadResolutionPriority(1)]
        public static C1 operator +(C1 x, C1 y)
        {
            System.Console.Write("C1");
            return x;
        }
    }
    extension(C2)
    {
        public static C2 operator +(C2 x, C2 y)
        {
            System.Console.Write("C2");
            return x;
        }
    }
    extension(C3)
    {
        public static C3 operator +(C3 x, C3 y)
        {
            System.Console.Write("C3");
            return x;
        }
    }
    extension(C4)
    {
        public static C4 operator +(C4 x, C4 y)
        {
            System.Console.Write("C4");
            return x;
        }
    }
}
 
public class C1;
public class C2 : C1;
 
public class C3;
public class C4 : C3;
 
class Program
{
    static void Main()
    {
        var c2 = new C2();
        _ = c2 + c2;
        var c4 = new C4();
        _ = c4 + c4;
    }
}
""";
 
            var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition], options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "C1C4").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_031_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x, C1 y)
        {
            System.Console.Write("regular");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 - c1;
 
        checked
        {
            _ = c1 - c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularregular").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_031_Consumption_Checked_CheckedFormNotSupported()
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator |(C1 x, C1 y) => throw null;
        public static C1 operator checked |(C1 x, C1 y) => throw null;
    }
}
 
public class C1;
""";
 
            var comp1 = CreateCompilation(src1);
            comp1.VerifyEmitDiagnostics(
                // (6,35): error CS9023: User-defined operator '|' cannot be declared checked
                //         public static C1 operator checked |(C1 x, C1 y) => throw null;
                Diagnostic(ErrorCode.ERR_OperatorCantBeChecked, "checked").WithArguments("|").WithLocation(6, 35),
                // (6,43): error CS0111: Type 'Extensions1' already defines a member called 'op_BitwiseOr' with the same parameter types
                //         public static C1 operator checked |(C1 x, C1 y) => throw null;
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "|").WithArguments("op_BitwiseOr", "Extensions1").WithLocation(6, 43)
                );
 
            var src2 = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator |(C1 x, C1 y)
        {
            System.Console.Write("regular");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 | c1;
 
        checked
        {
            _ = c1 | c1;
        }
    }
}
""";
 
            var comp2 = CreateCompilation(src2, options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "regularregular").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_032_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x, C1 y)
        {
            System.Console.Write("regular");
            return x;
        }
        public static C1 operator checked -(C1 x, C1 y)
        {
            System.Console.Write("checked");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 - c1;
 
        checked
        {
            _ = c1 - c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_033_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x, C1 y)
        {
            System.Console.Write("regular");
            return x;
        }
    }
    extension(C1)
    {
        public static C1 operator checked -(C1 x, C1 y)
        {
            System.Console.Write("checked");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 - c1;
 
        checked
        {
            _ = c1 - c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_034_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x, C1 y)
        {
            return x;
        }
 
        public static C1 operator checked -(C1 x, C1 y)
        {
            return x;
        }
    }
}
 
public static class Extensions2
{
    extension(C1)
    {
        public static C1 operator -(C1 x, C1 y)
        {
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 - c1;
 
        checked
        {
            _ = c1 - c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (35,13): error CS0034: Operator '-' is ambiguous on operands of type 'C1' and 'C1'
                //         _ = c1 - c1;
                Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "c1 - c1").WithArguments("-", "C1", "C1").WithLocation(35, 13),
                // (39,17): error CS0034: Operator '-' is ambiguous on operands of type 'C1' and 'C1'
                //             _ = c1 - c1;
                Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "c1 - c1").WithArguments("-", "C1", "C1").WithLocation(39, 17)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().Last();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("Extensions1.extension(C1).operator checked -(C1, C1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("Extensions2.extension(C1).operator -(C1, C1)", symbolInfo.CandidateSymbols[1].ToDisplayString());
        }
 
        [Fact]
        public void Binary_035_Consumption_CheckedLiftedIsWorse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator -(S1 x, S1 y) => throw null;
        public static S1 operator checked -(S1 x, S1 y) => throw null;
    }
    extension(S1?)
    {
        public static S1? operator -(S1? x, S1? y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        _ = s1 - s1;
        System.Console.Write(":");
 
        checked
        {
            _ = s1 - s1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_036_Consumption_OverloadResolutionPlusRegularVsChecked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x, C1 y)
        {
            System.Console.Write("C1");
            return x;
        }
        public static C1 operator checked -(C1 x, C1 y)
        {
            System.Console.Write("checkedC1");
            return x;
        }
    }
    extension(C2)
    {
        public static C2 operator -(C2 x, C2 y)
        {
            System.Console.Write("C2");
            return x;
        }
    }
}
 
public class C1;
public class C2 : C1;
public class C3 : C1;
 
class Program
{
    static void Main()
    {
        var c3 = new C3();
        _ = c3 - c3;
 
        checked
        {
            _ = c3 - c3;
        }
 
        var c2 = new C2();
        _ = c2 - c2;
 
        checked
        {
            _ = c2 - c2;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "C1checkedC1C2C2").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_037_Consumption()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1? operator +(S1? x, S1? y)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public static void M1(S1? x) {}
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
#line 21
        _ = s1 + s1;
        S1 s2 = new S1();
        _ = s2 + s2;
 
        System.Nullable<S1>.M1(s1);
        S1.M1(s1);
        S1.M1(s2);
    }
}
 
public static class Extensions2
{
    extension(S2)
    {
        public static S2? operator +(S2 x, S2 y)
        {
            return x;
        }
    }
}
 
public struct S2
{}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyEmitDiagnostics(
                // (5,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S1? operator +(S1? x, S1? y)
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "+").WithLocation(5, 36),
                // (21,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1?' and 'S1?'
                //         _ = s1 + s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 + s1").WithArguments("+", "S1?", "S1?").WithLocation(21, 13),
                // (23,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s2 + s2;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s2 + s2").WithArguments("+", "S1", "S1").WithLocation(23, 13),
                // (25,9): error CS1929: 'S1?' does not contain a definition for 'M1' and the best extension method overload 'Extensions1.extension(S1).M1(S1?)' requires a receiver of type 'S1'
                //         System.Nullable<S1>.M1(s1);
                Diagnostic(ErrorCode.ERR_BadInstanceArgType, "System.Nullable<S1>").WithArguments("S1?", "M1", "Extensions1.extension(S1).M1(S1?)", "S1").WithLocation(25, 9)
                );
        }
 
        [Fact]
        public void Binary_038_Consumption_OnObject()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static object operator +(object x, object y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
        _ = s1 + s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_039_Consumption_NotOnDynamic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static object operator +(object x, object y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
class Program
{
    static void Main()
    {
        dynamic s1 = new object();
        var s2 = new object();
        try
        {
            _ = s1 + s2;
        }
        catch
        {
            System.Console.Write("exception1");
        }
 
        try
        {
            _ = s2 + s1;
        }
        catch
        {
            System.Console.Write("exception2");
        }
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "exception1exception2").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_040_Consumption_WithLambda()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x, System.Func<int> y)
        {
            System.Console.Write("operator1");
            return x;
        }
        public static S1 operator +(System.Func<int> y, S1 x)
        {
            System.Console.Write("operator2");
            return x;
        }
    }
}
 
public struct S1
{}
 
public class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = s1 + (() => 1);
        _ = (() => 1) + s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1operator2").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_041_Consumption_BadOperand()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x, S2 y)
        {
            System.Console.Write("operator1");
            return x;
        }
        public static S1 operator +(S2 y, S1 x)
        {
            System.Console.Write("operator2");
            return x;
        }
    }
}
 
public struct S1
{}
public struct S2
{}
 
public class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = s1 + new();
        _ = new() + s1;
        _ = new() + new();
        _ = s1 + default;
        _ = default + s1;
        _ = default + default;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (28,13): error CS8310: Operator '+' cannot be applied to operand 'new()'
                //         _ = s1 + new();
                Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "s1 + new()").WithArguments("+", "new()").WithLocation(28, 13),
                // (29,13): error CS8310: Operator '+' cannot be applied to operand 'new()'
                //         _ = new() + s1;
                Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "new() + s1").WithArguments("+", "new()").WithLocation(29, 13),
                // (30,13): error CS8310: Operator '+' cannot be applied to operand 'new()'
                //         _ = new() + new();
                Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "new() + new()").WithArguments("+", "new()").WithLocation(30, 13),
                // (31,13): error CS8310: Operator '+' cannot be applied to operand 'default'
                //         _ = s1 + default;
                Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "s1 + default").WithArguments("+", "default").WithLocation(31, 13),
                // (32,13): error CS8310: Operator '+' cannot be applied to operand 'default'
                //         _ = default + s1;
                Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default + s1").WithArguments("+", "default").WithLocation(32, 13),
                // (33,13): error CS8310: Operator '+' cannot be applied to operand 'default'
                //         _ = default + default;
                Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "default + default").WithArguments("+", "default").WithLocation(33, 13)
                );
        }
 
        [Fact]
        public void Binary_042_Consumption_BadReceiver()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(__arglist)
    {
        public static object operator +(object x, object y)
        {
            return x;
        }
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
        _ = s1 + s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (3,15): error CS1669: __arglist is not valid in this context
                //     extension(__arglist)
                Diagnostic(ErrorCode.ERR_IllegalVarArgs, "__arglist").WithLocation(3, 15),
                // (5,39): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static object operator +(object x, object y)
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "+").WithLocation(5, 39),
                // (17,13): error CS0019: Operator '+' cannot be applied to operands of type 'object' and 'object'
                //         _ = s1 + s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 + s1").WithArguments("+", "object", "object").WithLocation(17, 13)
                );
        }
 
        [Fact]
        public void Binary_043_Consumption_Checked_Generic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T1>(C1<T1>)
    {
        public static C1<T1> operator -(C1<T1> x, C1<T1> y)
        {
            System.Console.Write("regular");
            return x;
        }
    }
    extension<T2>(C1<T2>)
    {
        public static C1<T2> operator checked -(C1<T2> x, C1<T2> y)
        {
            System.Console.Write("checked");
            return x;
        }
    }
}
 
public class C1<T>;
 
class Program
{
    static void Main()
    {
        var c1 = new C1<int>();
        _ = c1 - c1;
 
        checked
        {
            _ = c1 - c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_044_Consumption_Logical(bool fromMetadata, [CombinatorialValues("&&", "||")] string op)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            System.Console.Write(y.F);
            return new S1 { F = x.F {{{op[0]}}} y.F };
        }
 
        public static bool operator true(S1 x)
        {
            System.Console.Write("operator2:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            return x.F;
        }
 
        public static bool operator false(S1 x)
        {
            System.Console.Write("operator3:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            return !x.F;
        }
    }
}
 
public struct S1
{
    public bool F;
}
""";
 
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        S1[] s = [new S1() { F = false }, new S1() { F = true }];
 
        foreach (var s1 in s)
        {
            foreach (var s2 in s)
            {
                Print(s1 {{{op}}} s2);
                System.Console.WriteLine();
            }
        }
    }
 
    static void Print(S1 x)
    {
        System.Console.Write(":");
        System.Console.Write(x.F);
    }
}
""";
 
            string expected = op == "&&" ?
@"
operator3:False::False
operator3:False::False
operator3:True:operator1:True:False:False
operator3:True:operator1:True:True:True
"
:
@"
operator2:False:operator1:False:False:False
operator2:False:operator1:False:True:True
operator2:True::True
operator2:True::True
";
 
            var comp1 = CreateCompilation(src1);
            var comp1Ref = fromMetadata ? comp1.EmitToImageReference() : comp1.ToMetadataReference();
 
            var comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: expected).VerifyDiagnostics();
 
            var tree = comp2.SyntaxTrees.First();
            var model = comp2.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(S1).operator " + op[0] + "(S1, S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp2, expectedOutput: expected).VerifyDiagnostics();
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            comp2.VerifyEmitDiagnostics(
                // (11,23): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                //                 Print(s1 && s2);
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "s1 " + op + " s2").WithArguments("extensions").WithLocation(11, 23)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_045_Consumption_Logical_InDifferentBlocks([CombinatorialValues("&&", "||")] string op)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
    extension(S1)
    {
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(S1 x)
        {
            System.Console.Write("operator2");
            return false;
        }
    }
    extension(S1)
    {
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(S1 x) => throw null;
    }
}
 
public struct S1
{}
""";
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1 = s1 {{{op}}} s1;
    }
}
""";
 
            var comp = CreateCompilation([src1, src2], options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1").VerifyDiagnostics();
 
            var comp1 = CreateCompilation(src1, options: TestOptions.DebugDll);
 
            comp = CreateCompilation(src2, references: [comp1.ToMetadataReference()], options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1").VerifyDiagnostics();
 
            comp = CreateCompilation(src2, references: [comp1.EmitToImageReference()], options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_046_Consumption_Logical_DifferentTupleNames([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension((int a, int b))
    {
        public static (int c, int d) operator {{{op[0]}}}((int e, int f) x, (int g, int h) y)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}((int i, int j) x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}((int k, int l) x) => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = (1, 2);
        s1 = s1 {{{op}}} s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_047_Consumption_Logical_DifferentParameterTypes([CombinatorialValues("&&", "||")] string op)
        {
            var src1 = $$$"""
namespace NS
{
    public static class Extensions1
    {
        extension(S1)
        {
            public static S1 operator {{{op[0]}}}(S1 x, S2 y)
            {
                System.Console.Write("operator1");
                return x;
            }
            public static bool operator {{{(op == "&&" ? "false" : "true")}}}(S1 x)
            {
                System.Console.Write("operator2");
                return false;
            }
 
            public static bool operator {{{(op == "&&" ? "true" : "false")}}}(S1 x) => throw null;
        }
    }
 
    class Program
    {
        static void Main()
        {
            S1 s1 = new S1();
            S2 s2 = new S2();
            _ = s1 {{{op}}} s2;
        }
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S1(S2 x) => default;
}
""";
            var src2 = $$$"""
public static class Extensions2
{
    extension(S1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator3");
            return x;
        }
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(S1 x)
        {
            System.Console.Write("operator4");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(S1 x) => throw null;
    }
}
""";
 
            var comp = CreateCompilation(src1, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (28,17): error CS0217: In order to be applicable as a short circuit operator a user-defined logical operator ('Extensions1.extension(S1).operator &(S1, S2)') must have the same return type and parameter types
                //             _ = s1 && s2;
                Diagnostic(ErrorCode.ERR_BadBoolOp, "s1 " + op + " s2").WithArguments("NS.Extensions1.extension(S1).operator " + op[0] + "(S1, S2)").WithLocation(28, 17)
                );
 
            comp = CreateCompilation([src1, src2], options: TestOptions.DebugExe);
 
            comp.VerifyEmitDiagnostics(
                // (28,17): error CS0217: In order to be applicable as a short circuit operator a user-defined logical operator ('Extensions1.extension(S1).operator &(S1, S2)') must have the same return type and parameter types
                //             _ = s1 && s2;
                Diagnostic(ErrorCode.ERR_BadBoolOp, "s1 " + op + " s2").WithArguments("NS.Extensions1.extension(S1).operator " + op[0] + "(S1, S2)").WithLocation(28, 17)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_048_Consumption_Logical_DifferentReturnType([CombinatorialValues("&&", "||")] string op)
        {
            var src1 = $$$"""
namespace NS
{
    public static class Extensions1
    {
        extension(S1)
        {
            public static S2 operator {{{op[0]}}}(S1 x, S1 y)
            {
                System.Console.Write("operator1");
                return default;
            }
            public static bool operator {{{(op == "&&" ? "false" : "true")}}}(S1 x)
            {
                System.Console.Write("operator2");
                return false;
            }
 
            public static bool operator {{{(op == "&&" ? "true" : "false")}}}(S1 x) => throw null;
        }
    }
 
    class Program
    {
        static void Main()
        {
            S1 s1 = new S1();
            S2 s2 = new S2();
            _ = s1 {{{op}}} s2;
        }
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S1(S2 x) => default;
}
""";
            var src2 = $$$"""
public static class Extensions2
{
    extension(S1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator3");
            return x;
        }
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(S1 x)
        {
            System.Console.Write("operator4");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(S1 x) => throw null;
    }
}
""";
 
            var comp = CreateCompilation(src1, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (28,17): error CS0217: In order to be applicable as a short circuit operator a user-defined logical operator ('Extensions1.extension(S1).operator &(S1, S1)') must have the same return type and parameter types
                //             _ = s1 && s2;
                Diagnostic(ErrorCode.ERR_BadBoolOp, "s1 " + op + " s2").WithArguments("NS.Extensions1.extension(S1).operator " + op[0] + "(S1, S1)").WithLocation(28, 17)
                );
 
            comp = CreateCompilation([src1, src2], options: TestOptions.DebugExe);
 
            comp.VerifyEmitDiagnostics(
                // (28,17): error CS0217: In order to be applicable as a short circuit operator a user-defined logical operator ('Extensions1.extension(S1).operator &(S1, S1)') must have the same return type and parameter types
                //             _ = s1 && s2;
                Diagnostic(ErrorCode.ERR_BadBoolOp, "s1 " + op + " s2").WithArguments("NS.Extensions1.extension(S1).operator " + op[0] + "(S1, S1)").WithLocation(28, 17)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_049_Consumption_Logical_TrueFalseBetterness([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T, S>((T, S))
    {
        public static (T, S) operator {{{op[0]}}}((T, S) x, (T, S) y)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public static bool operator true((T, S) x) => throw null;
        public static bool operator false((T, S) x) => throw null;
    }
 
    extension((int, int))
    {
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}((int, int) x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}((int, int) x) => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = (1, 2);
        s1 = s1 {{{op}}} s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            AssertEx.Equal("Extensions1.extension<int, int>((int, int)).operator " + op[0] + "((int, int), (int, int))", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_050_Consumption_Logical_TrueFalseApplicability([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator {{{op[0]}}}(C1 x, C1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(C1 x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(C1 x) => throw null;
    }
 
    extension(C2)
    {
        public static bool operator true(C2 x) => throw null;
        public static bool operator false(C2 x) => throw null;
    }
}
 
public class C1
{}
 
public class C2  : C1
{}
 
class Program
{
    static void Main()
    {
        C1 c1 = new C1();
        c1 = c1 {{{op}}} c1;
 
        C2 c2 = new C2();
        c1 = c2 {{{op}}} c2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1operator2operator1").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_051_Consumption_Logical_TrueFalseApplicability([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(C1 x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(C1 x) => throw null;
    }
 
    extension(C2)
    {
        public static C2 operator {{{op[0]}}}(C2 x, C2 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public class C1
{}
 
public class C2  : C1
{}
 
class Program
{
    static void Main()
    {
        C2 c2 = new C2();
        c2 = c2 {{{op}}} c2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_052_Consumption_Logical_TrueFalseApplicability([CombinatorialValues("&&", "||")] string op)
        {
            var src1 = $$$"""
namespace NS
{
    public static class Extensions1
    {
        extension(C1)
        {
            public static C1 operator {{{op[0]}}}(C1 x, C1 y) => throw null;
        }
 
        extension(C2)
        {
            public static bool operator true(C2 x) => throw null;
            public static bool operator false(C2 x) => throw null;
        }
    }
 
    class Program
    {
        static void Main()
        {
            C1 c1 = new C1();
            c1 = c1 {{{op}}} c1;
 
            C2 c2 = new C2();
            c1 = c2 {{{op}}} c2;
        }
    }
}
 
public class C1
{}
 
public class C2  : C1
{}
""";
            var src2 = $$$"""
public static class Extensions2
{
    extension(C1)
    {
        public static C1 operator {{{op[0]}}}(C1 x, C1 y) => throw null;
        public static bool operator true(C1 x) => throw null;
        public static bool operator false(C1 x) => throw null;
    }
}
""";
 
            var comp = CreateCompilation(src1, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (22,18): error CS0218: In order for 'NS.Extensions1.extension(C1).operator &(C1, C1)' to be applicable as a short circuit operator, its declaring type 'NS.Extensions1' must define operator true and operator false
                //         c1 = c1 && c1;
                Diagnostic(ErrorCode.ERR_MustHaveOpTF, "c1 " + op + " c1").WithArguments("NS.Extensions1.extension(C1).operator " + op[0] + "(C1, C1)", "NS.Extensions1").WithLocation(22, 18),
                // (25,18): error CS0218: In order for 'NS.Extensions1.extension(C1).operator &(C1, C1)' to be applicable as a short circuit operator, its declaring type 'NS.Extensions1' must define operator true and operator false
                //         c1 = c2 && c2;
                Diagnostic(ErrorCode.ERR_MustHaveOpTF, "c2 " + op + " c2").WithArguments("NS.Extensions1.extension(C1).operator " + op[0] + "(C1, C1)", "NS.Extensions1").WithLocation(25, 18)
                );
 
            comp = CreateCompilation([src1, src2], options: TestOptions.DebugExe);
 
            comp.VerifyEmitDiagnostics(
                // (22,18): error CS0218: In order for 'NS.Extensions1.extension(C1).operator &(C1, C1)' to be applicable as a short circuit operator, its declaring type 'NS.Extensions1' must define operator true and operator false
                //         c1 = c1 && c1;
                Diagnostic(ErrorCode.ERR_MustHaveOpTF, "c1 " + op + " c1").WithArguments("NS.Extensions1.extension(C1).operator " + op[0] + "(C1, C1)", "NS.Extensions1").WithLocation(22, 18),
                // (25,18): error CS0218: In order for 'NS.Extensions1.extension(C1).operator &(C1, C1)' to be applicable as a short circuit operator, its declaring type 'NS.Extensions1' must define operator true and operator false
                //         c1 = c2 && c2;
                Diagnostic(ErrorCode.ERR_MustHaveOpTF, "c2 " + op + " c2").WithArguments("NS.Extensions1.extension(C1).operator " + op[0] + "(C1, C1)", "NS.Extensions1").WithLocation(25, 18)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_053_Consumption_Logical_TrueOrFalseInDifferentClass([CombinatorialValues("&&", "||")] string op)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
    extension(S1)
    {
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(S1 x) => throw null;
    }
}
 
public static class Extensions2
{
    extension(S1)
    {
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(S1 x)
        {
            System.Console.Write("operator2");
            return false;
        }
    }
}
 
public struct S1
{}
""";
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1 = s1 {{{op}}} s1;
    }
}
""";
 
            var comp1 = CreateCompilation(src1);
            var comp2 = CreateCompilation(src2, references: [comp1.ToMetadataReference()], options: TestOptions.DebugExe);
            comp2.VerifyEmitDiagnostics(
                // (6,14): error CS0218: In order for 'Extensions1.extension(S1).operator &(S1, S1)' to be applicable as a short circuit operator, its declaring type 'Extensions1' must define operator true and operator false
                //         s1 = s1 && s1;
                Diagnostic(ErrorCode.ERR_MustHaveOpTF, "s1 " + op + " s1").WithArguments("Extensions1.extension(S1).operator " + op[0] + "(S1, S1)", "Extensions1").WithLocation(6, 14)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_054_Consumption_Logical_TrueOrFalseInDifferentClass([CombinatorialValues("&&", "||")] string op)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
    extension(S1)
    {
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(S1 x)
        {
            System.Console.Write("operator2");
            return false;
        }
    }
}
 
public static class Extensions2
{
    extension(S1)
    {
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(S1 x) => throw null;
    }
}
 
public struct S1
{}
""";
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1 = s1 {{{op}}} s1;
    }
}
""";
 
            var comp1 = CreateCompilation(src1);
            var comp2 = CreateCompilation(src2, references: [comp1.ToMetadataReference()], options: TestOptions.DebugExe);
            comp2.VerifyEmitDiagnostics(
                // (6,14): error CS0218: In order for 'Extensions1.extension(S1).operator &(S1, S1)' to be applicable as a short circuit operator, its declaring type 'Extensions1' must define operator true and operator false
                //         s1 = s1 && s1;
                Diagnostic(ErrorCode.ERR_MustHaveOpTF, "s1 " + op + " s1").WithArguments("Extensions1.extension(S1).operator " + op[0] + "(S1, S1)", "Extensions1").WithLocation(6, 14)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_055_Consumption_Logical_TrueOrFalseInDifferentClass([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public static class Extensions2
{
    extension(S1)
    {
        public static bool operator false(S1 x) => throw null;
        public static bool operator true(S1 x) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1();
#line 6
        s1 = s1 {{{op}}} s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (6,14): error CS0218: In order for 'Extensions1.extension(S1).operator &(S1, S1)' to be applicable as a short circuit operator, its declaring type 'Extensions1' must define operator true and operator false
                //         s1 = s1 && s1;
                Diagnostic(ErrorCode.ERR_MustHaveOpTF, "s1 " + op + " s1").WithArguments("Extensions1.extension(S1).operator " + op[0] + "(S1, S1)", "Extensions1").WithLocation(6, 14)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_056_Consumption_Logical_TrueFalseTakesNullable([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public static bool operator true(S1? x) => throw null;
 
        public static bool operator false(S1? x) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1 = s1 {{{op}}} s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (11,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator true(S1? x) => throw null;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "true").WithLocation(11, 37),
                // (13,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator false(S1? x) => throw null;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "false").WithLocation(13, 37)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_057_Consumption_Logical_TrueFalseTakesNullable([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
    extension(S1?)
    {
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(S1? x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(S1? x) => throw null;
 
        public static void M1(S1? x) {}
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1 = s1 {{{op}}} s1;
 
        S1.M1(s1);
        System.Nullable<S1>.M1(s1);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (33,14): error CS0218: In order for 'Extensions1.extension(S1).operator &(S1, S1)' to be applicable as a short circuit operator, its declaring type 'Extensions1' must define operator true and operator false
                //         s1 = s1 && s1;
                Diagnostic(ErrorCode.ERR_MustHaveOpTF, "s1 " + op + " s1").WithArguments("Extensions1.extension(S1).operator " + op[0] + "(S1, S1)", "Extensions1").WithLocation(33, 14),
                // (35,9): error CS1929: 'S1' does not contain a definition for 'M1' and the best extension method overload 'Extensions1.extension(S1?).M1(S1?)' requires a receiver of type 'S1?'
                //         S1.M1(s1);
                Diagnostic(ErrorCode.ERR_BadInstanceArgType, "S1").WithArguments("S1", "M1", "Extensions1.extension(S1?).M1(S1?)", "S1?").WithLocation(35, 9)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_058_Consumption_Logical_TrueFalseTakesNullable([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1? operator {{{op[0]}}}(S1? x, S1? y) => throw null;
    }
    extension(S1)
    {
        public static bool operator true(S1? x) => throw null;
 
        public static bool operator false(S1? x) => throw null;
 
        public static void M1(S1? x) {}
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1();
#line 33
        s1 = s1 {{{op}}} s1;
 
        S1.M1(s1);
        System.Nullable<S1>.M1(s1);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (5,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S1? operator &(S1? x, S1? y) => throw null;
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, op[..1]).WithLocation(5, 36),
                // (9,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator true(S1? x) => throw null;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "true").WithLocation(9, 37),
                // (11,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator false(S1? x) => throw null;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "false").WithLocation(11, 37),
                // (33,14): error CS0019: Operator '&&' cannot be applied to operands of type 'S1' and 'S1'
                //         s1 = s1 && s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 " + op + " s1").WithArguments(op, "S1", "S1").WithLocation(33, 14),
                // (36,9): error CS1929: 'S1?' does not contain a definition for 'M1' and the best extension method overload 'Extensions1.extension(S1).M1(S1?)' requires a receiver of type 'S1'
                //         System.Nullable<S1>.M1(s1);
                Diagnostic(ErrorCode.ERR_BadInstanceArgType, "System.Nullable<S1>").WithArguments("S1?", "M1", "Extensions1.extension(S1).M1(S1?)", "S1").WithLocation(36, 9)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_059_Consumption_Logical_TrueFalseTakesNullable([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1? operator {{{op[0]}}}(S1? x, S1? y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
    extension(S1?)
    {
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(S1? x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(S1? x) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1 = (s1 {{{op}}} s1).GetValueOrDefault();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (5,36): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static S1? operator &(S1? x, S1? y)
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, op[..1]).WithLocation(5, 36),
                // (31,15): error CS0019: Operator '&&' cannot be applied to operands of type 'S1' and 'S1'
                //         s1 = (s1 && s1).GetValueOrDefault();
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 " + op + " s1").WithArguments(op, "S1", "S1").WithLocation(31, 15)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_060_Consumption_Logical_TrueFalseTakesNullable([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1?)
    {
        public static S1? operator {{{op[0]}}}(S1? x, S1? y)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(S1? x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(S1? x) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        s1 = (s1 {{{op}}} s1).GetValueOrDefault();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_061_Consumption_Logical_TrueFalseTakesObject([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
    extension(object)
    {
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(object x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(object x) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1 = s1 {{{op}}} s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_062_Consumption_Logical_TrueFalseTakesSpan([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(int[])
    {
        public static int[] operator {{{op[0]}}}(int[] x, int[] y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
    extension(System.Span<int>)
    {
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(System.Span<int> x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(System.Span<int> x) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        var s1 = new int[] {};
        s1 = s1 {{{op}}} s1;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "operator2operator1" : null, verify: Verification.FailsPEVerify).VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_063_Consumption_Logical_TrueFalseTakesDifferentTuple([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension((int, int))
    {
        public static (int, int) operator {{{op[0]}}}((int, int) x, (int, int) y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
    extension((int, object))
    {
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}((int, object) x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}((int, object) x) => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = (1, 2);
        s1 = s1 {{{op}}} s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_064_Consumption_Logical_PredefinedComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator &(S2 x, S2 y) => throw null;
        public static bool operator true (S2 x) => throw null;
        public static bool operator false(S2 x) => throw null;
    }
}
 
public struct S2
{
    public static implicit operator bool(S2 x)
    {
        System.Console.Write("operator3");
        return true;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        bool x = s2 && s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator3operator3").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
 
            Assert.Equal("System.Boolean", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
        }
 
        [Fact]
        public void Binary_065_Consumption_Logical_NonExtensionComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator &(S2 x, S2 y) => throw null;
        public static bool operator false(S2 x) => throw null;
        public static bool operator true(S2 x) => throw null;
    }
}
 
public struct S2
{
    public static S2 operator &(S2 x, S2 y)
    {
        System.Console.Write("operator2");
        return x;
    }
    public static bool operator false(S2 x)
    {
        System.Console.Write("operator1");
        return false;
    }
 
    public static bool operator true(S2 x) => throw null;
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = s2 && s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("S2.operator &(S2, S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Binary_066_Consumption_Logical_NonExtensionComesFirst_DifferentParameterTypes()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator &(S2 x, S2 y) => throw null;
        public static bool operator false(S2 x) => throw null;
        public static bool operator true(S2 x) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static S2 operator &(S2 x, S1 y)
    {
        return x;
    }
 
    public static implicit operator S2(S1 x) => default;
}
 
class Program
{
    static void Main()
    {
        var s1 = new S1();
        var s2 = new S2();
        _ = s2 && s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyEmitDiagnostics(
                // (30,13): error CS0217: In order to be applicable as a short circuit operator a user-defined logical operator ('S2.operator &(S2, S1)') must have the same return type and parameter types
                //         _ = s2 && s1;
                Diagnostic(ErrorCode.ERR_BadBoolOp, "s2 && s1").WithArguments("S2.operator &(S2, S1)").WithLocation(30, 13)
                );
        }
 
        [Fact]
        public void Binary_067_Consumption_Logical_NonExtensionComesFirst_TrueFalseIsMissing()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator &(S2 x, S2 y) => throw null;
        public static bool operator false(S2 x) => throw null;
        public static bool operator true(S2 x) => throw null;
    }
}
 
public struct S2
{
    public static S2 operator &(S2 x, S2 y)
    {
        return x;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = s2 && s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyEmitDiagnostics(
                // (24,13): error CS0218: In order for 'S2.operator &(S2, S2)' to be applicable as a short circuit operator, its declaring type 'S2' must define operator true and operator false
                //         _ = s2 && s2;
                Diagnostic(ErrorCode.ERR_MustHaveOpTF, "s2 && s2").WithArguments("S2.operator &(S2, S2)", "S2").WithLocation(24, 13)
                );
        }
 
        [Fact]
        public void Binary_068_Consumption_Logical_ScopeByScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator &(S1 x, S1 y) => throw null;
        public static bool operator true(S1 x) => throw null;
        public static bool operator false(S1 x) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(S1)
        {
            public static S1 operator &(S1 x, S1 y)
            {
                System.Console.Write("operator2");
                return x;
            }
 
            public static bool operator true(S1 x) => throw null;
            public static bool operator false(S1 x)
            {
                System.Console.Write("operator1");
                return false;
            }
        }
    }
 
    namespace NS2
    {
        public static class Extensions3
        {
            extension(S2)
            {
                public static S2 operator &(S2 x, S2 y) => throw null;
                public static bool operator true(S2 x) => throw null;
                public static bool operator false(S2 x) => throw null;
            }
        }
 
        class Program
        {
            static void Main()
            {
                var s1 = new S1();
                _ = s1 && s1;
            }
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("NS1.Extensions2.extension(S1).operator &(S1, S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Binary_069_Consumption_Logical_NonExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1
{
    public static I1 operator &(I1 x, I1 y) => x;
    public static bool operator true(I1 x) => true;
    public static bool operator false(I1 x) => false;
}
 
public interface I3
{
    public static I3 operator &(I3 x, I3 y) => x;
    public static bool operator true(I3 x) => true;
    public static bool operator false(I3 x) => false;
}
 
public interface I4 : I1, I3
{
}
 
public interface I2 : I4
{
}
 
public static class Extensions1
{
    extension(I2)
    {
        public static I2 operator &(I2 x, I2 y) => x;
        public static bool operator true(I2 x) => true;
        public static bool operator false(I2 x) => false;
    }
}
 
class Test2 : I2
{
    static void Main()
    {
        I2 x = new Test2();
        var y = x && x;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (38,17): error CS0034: Operator '&&' is ambiguous on operands of type 'I2' and 'I2'
                //         var y = x && x;
                Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "x && x").WithArguments("&&", "I2", "I2").WithLocation(38, 17)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("I1.operator &(I1, I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("I3.operator &(I3, I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Binary_070_Consumption_Logical_NonExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1
{
    public static I1 operator &(I1 x, I1 y) => x;
}
 
public interface I3
{
    public static I3 operator &(I3 x, I3 y) => x;
}
 
public interface I4 : I1, I3
{
}
 
public interface I2 : I4
{
}
 
public static class Extensions1
{
    extension(I2)
    {
        public static I2 operator &(I2 x, I2 y) => x;
        public static bool operator true(I2 x) => true;
        public static bool operator false(I2 x) => false;
    }
}
 
class Test2 : I2
{
    static void Main()
    {
        I2 x = new Test2();
        var y = x && x;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
 
            comp.VerifyEmitDiagnostics(
                // (34,17): error CS0034: Operator '&&' is ambiguous on operands of type 'I2' and 'I2'
                //         var y = x && x;
                Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "x && x").WithArguments("&&", "I2", "I2").WithLocation(34, 17)
                );
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/78830")]
        public void Binary_071_Consumption_Logical_ExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1;
public interface I3;
public interface I4 : I1, I3;
public interface I2 : I4;
 
public static class Extensions1
{
    extension(I2)
    {
        public static I2 operator &(I2 x, I2 y) => x;
        public static bool operator true(I2 x) => true;
        public static bool operator false(I2 x) => false;
    }
}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(I1)
        {
            public static I1 operator &(I1 x, I1 y) => x;
            public static bool operator true(I1 x) => true;
            public static bool operator false(I1 x) => false;
        }
 
        extension(I3)
        {
            public static I3 operator &(I3 x, I3 y) => x;
            public static bool operator true(I3 x) => true;
            public static bool operator false(I3 x) => false;
        }
    }
 
    class Test2 : I2
    {
        static void Main()
        {
            I2 x = new Test2();
            var y = x && x;
        }
    }
}
""";
 
            var comp = CreateCompilation(src);
 
            // https://github.com/dotnet/roslyn/issues/78830: We might want to include more information into the error. Like what methods conflict.
            comp.VerifyEmitDiagnostics(
                // (40,21): error CS0034: Operator '&&' is ambiguous on operands of type 'I2' and 'I2'
                //             var y = x && x;
                Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "x && x").WithArguments("&&", "I2", "I2").WithLocation(40, 21)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("NS1.Extensions2.extension(I1).operator &(I1, I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("NS1.Extensions2.extension(I3).operator &(I3, I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void Binary_072_Consumption_Logical_ExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1;
public interface I3;
public interface I4 : I1, I3;
public interface I2 : I4;
 
public static class Extensions2
{
    extension(I2)
    {
        public static I2 operator &(I2 x, I2 y) => x;
        public static bool operator true(I2 x) => true;
        public static bool operator false(I2 x) => false;
    }
}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(I1)
        {
            public static I1 operator &(I1 x, I1 y) => x;
        }
 
        extension(I3)
        {
            public static I3 operator &(I3 x, I3 y) => x;
        }
    }
 
    class Test2 : I2
    {
        static void Main()
        {
            I2 x = new Test2();
            var y = x && x;
        }
    }
}
""";
 
            var comp = CreateCompilation(src);
 
            comp.VerifyEmitDiagnostics(
                // (36,21): error CS0034: Operator '&&' is ambiguous on operands of type 'I2' and 'I2'
                //             var y = x && x;
                Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "x && x").WithArguments("&&", "I2", "I2").WithLocation(36, 21)
                );
        }
 
        [Fact]
        public void Binary_073_Consumption_Logical_ExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1;
public interface I3;
public interface I4 : I1, I3;
public interface I2 : I4;
 
public static class Extensions2
{
    extension(I1)
    {
        public static I1 operator &(I1 x, I1 y) => x;
        public static bool operator true(I1 x) => true;
        public static bool operator false(I1 x) => false;
    }
 
    extension(I3)
    {
        public static I3 operator &(I3 x, I3 y) => x;
    }
}
 
class Test2 : I2
{
    static void Main()
    {
        I2 x = new Test2();
        var y = x && x;
    }
}
""";
 
            var comp = CreateCompilation(src);
 
            comp.VerifyEmitDiagnostics(
                // (26,17): error CS0034: Operator '&&' is ambiguous on operands of type 'I2' and 'I2'
                //         var y = x && x;
                Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "x && x").WithArguments("&&", "I2", "I2").WithLocation(26, 17)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_074_Consumption_Logical_Lifted([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            System.Console.Write(y.F);
            return new S1 { F = x.F {{{op[0]}}} y.F };
        }
    }
    extension(S1?)
    {
        public static bool operator true(S1? x)
        {
            System.Console.Write("operator2:");
            System.Console.Write(x?.F.ToString() ?? "null");
            System.Console.Write(":");
            return x?.F == true;
        }
 
        public static bool operator false(S1? x)
        {
            System.Console.Write("operator3:");
            System.Console.Write(x?.F.ToString() ?? "null");
            System.Console.Write(":");
            return x?.F == false;
        }
    }
}
 
public struct S1
{
    public bool F;
}
 
class Program
{
    static void Main()
    {
        S1?[] s = [new S1() { F = false }, new S1() { F = true }, null];
 
        foreach (var s1 in s)
        {
            foreach (var s2 in s)
            {
                Print(s1 {{{op}}} s2);
                System.Console.WriteLine();
            }
        }
    }
 
    static void Print(S1? x)
    {
        System.Console.Write(":");
        System.Console.Write(x?.F.ToString() ?? "null");
    }
}
""";
 
            string expected = op == "&&" ?
@"
operator3:False::False
operator3:False::False
operator3:False::False
operator3:True:operator1:True:False:False
operator3:True:operator1:True:True:True
operator3:True::null
operator3:null::null
operator3:null::null
operator3:null::null
"
:
@"
operator2:False:operator1:False:False:False
operator2:False:operator1:False:True:True
operator2:False::null
operator2:True::True
operator2:True::True
operator2:True::True
operator2:null::null
operator2:null::null
operator2:null::null
";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: expected).VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_075_Consumption_Logical_Lifted([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            System.Console.Write(y.F);
            return new S1 { F = x.F {{{op[0]}}} y.F };
        }
    }
    extension(S1?)
    {
        public static bool operator true(S1? x)
        {
            System.Console.Write("operator2:");
            System.Console.Write(x?.F.ToString() ?? "null");
            System.Console.Write(":");
            return x?.F == true;
        }
 
        public static bool operator false(S1? x)
        {
            System.Console.Write("operator3:");
            System.Console.Write(x?.F.ToString() ?? "null");
            System.Console.Write(":");
            return x?.F == false;
        }
    }
}
 
public struct S1
{
    public bool F;
}
 
class Program
{
    static void Main()
    {
        S1?[] s1 = [new S1() { F = false }, new S1() { F = true }, null];
        S1[] s2 = [new S1() { F = false }, new S1() { F = true }];
 
        foreach (var s11 in s1)
        {
            foreach (var s12 in s2)
            {
                Print(s11 {{{op}}} s12);
                System.Console.WriteLine();
            }
        }
 
        foreach (var s11 in s2)
        {
            foreach (var s12 in s1)
            {
                Print(s11 {{{op}}} s12);
                System.Console.WriteLine();
            }
        }
    }
 
    static void Print(S1? x)
    {
        System.Console.Write(":");
        System.Console.Write(x?.F.ToString() ?? "null");
    }
}
""";
 
            string expected = op == "&&" ?
@"
operator3:False::False
operator3:False::False
operator3:True:operator1:True:False:False
operator3:True:operator1:True:True:True
operator3:null::null
operator3:null::null
operator3:False::False
operator3:False::False
operator3:False::False
operator3:True:operator1:True:False:False
operator3:True:operator1:True:True:True
operator3:True::null
"
:
@"
operator2:False:operator1:False:False:False
operator2:False:operator1:False:True:True
operator2:True::True
operator2:True::True
operator2:null::null
operator2:null::null
operator2:False:operator1:False:False:False
operator2:False:operator1:False:True:True
operator2:False::null
operator2:True::True
operator2:True::True
operator2:True::True
";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: expected).VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_076_Consumption_Logical_LiftedIsWorse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator &(S1 x, S1 y) => throw null;
    }
    extension(S1?)
    {
        public static S1? operator &(S1? x, S1? y)
        {
            System.Console.Write("operator1");
            return x;
        }
        public static bool operator false(S1? x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator true(S1? x) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        _ = s1 && s1;
        System.Console.Write(":");
        s1 = null;
        _ = s1 && s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1:operator2operator1").VerifyDiagnostics();
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/78830")]
        public void Binary_077_Consumption_Logical_NoLiftedFormForTrueFalse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator &(S1 x, S1 y) => throw null;
        public static bool operator false(S1 x) => throw null;
        public static bool operator true(S1 x) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        _ = s1 && s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            // https://github.com/dotnet/roslyn/issues/78830: The wording is somewhat confusing because there are operators for S1, what is missing are the true/false operators for S1?.
            comp.VerifyEmitDiagnostics(
                // (19,13): error CS0218: In order for 'Extensions1.extension(S1).operator &(S1, S1)' to be applicable as a short circuit operator, its declaring type 'Extensions1' must define operator true and operator false
                //         _ = s1 && s1;
                Diagnostic(ErrorCode.ERR_MustHaveOpTF, "s1 && s1").WithArguments("Extensions1.extension(S1).operator &(S1, S1)", "Extensions1").WithLocation(19, 13)
                );
        }
 
        [Fact]
        public void Binary_078_Consumption_Logical_OnObject()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static object operator &(object x, object y)
        {
            System.Console.Write("operator1");
            return x;
        }
        public static bool operator false(object x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator true(object x) => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
        _ = s1 && s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_079_Consumption_Logical_NotOnDynamic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static object operator &(object x, object y)
        {
            System.Console.Write("operator1");
            return x;
        }
        public static bool operator false(object x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator true(object x) => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        dynamic s1 = new object();
        var s2 = new object();
 
        try
        {
            _ = s1 && s2;
        }
        catch
        {
            System.Console.Write("exception1");
        }
 
 
        try
        {
            _ = s1 && s1;
        }
        catch
        {
            System.Console.Write("exception2");
        }
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "exception1exception2").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_080_Consumption_Logical_NotOnDynamic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static object operator &(object x, object y)
        {
            System.Console.Write("operator1");
            return x;
        }
        public static bool operator false(object x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator true(object x) => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        dynamic s1 = new object();
        var s2 = new object();
        _ = s2 && s1;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.DebugExe);
 
            // Note, an attempt to do compile time optimization using non-dynamic static type of 's2' ignores true/false extensions.
            // This is desirable because runtime binder wouldn't be able to use them as well.
            comp.VerifyEmitDiagnostics(
                // (26,13): error CS7083: Expression must be implicitly convertible to Boolean or its type 'object' must define operator 'false'.
                //         _ = s2 && s1;
                Diagnostic(ErrorCode.ERR_InvalidDynamicCondition, "s2").WithArguments("object", "false").WithLocation(26, 13)
                );
        }
 
        [Fact]
        public void Binary_081_Consumption_Logical_WithLambda()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(System.Func<int>)
    {
        public static System.Func<int> operator &(System.Func<int> x, System.Func<int> y)
        {
            System.Console.Write("operator1");
            return x;
        }
        public static bool operator false(System.Func<int> x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator true(System.Func<int> x) => throw null;
    }
}
 
public struct S1
{}
 
public class Program
{
    static void Main()
    {
        System.Func<int> s1 = null;
        s1 = s1 && (() => 1);
        s1 = (() => 1) && s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1operator2operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_082_Consumption_Logical_WithLambda()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(System.Func<int>)
    {
        public static System.Func<int> operator &(System.Func<int> x, System.Func<int> y)
        {
            System.Console.Write("operator1");
            return x;
        }
        public static bool operator false(System.Func<int> x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator true(System.Func<int> x) => throw null;
    }
}
 
public struct S1
{}
 
public class Program
{
    static void Main()
    {
        _ = (() => 1) && (() => 1);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (27,13): error CS0019: Operator '&&' cannot be applied to operands of type 'lambda expression' and 'lambda expression'
                //         _ = (() => 1) && (() => 1);
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "(() => 1) && (() => 1)").WithArguments("&&", "lambda expression", "lambda expression").WithLocation(27, 13)
                );
        }
 
        [Fact]
        public void Binary_083_Consumption_Logical_BadOperand()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static object operator &(object x, object y)
        {
            System.Console.Write("operator1");
            return x;
        }
        public static bool operator false(object x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator true(object x) => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
        _ = s1 && new();
        _ = new() && s1;
        _ = new() && new();
        _ = s1 && default;
        _ = default && s1;
        _ = default && default;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (25,19): error CS8754: There is no target type for 'new()'
                //         _ = s1 && new();
                Diagnostic(ErrorCode.ERR_ImplicitObjectCreationNoTargetType, "new()").WithArguments("new()").WithLocation(25, 19),
                // (26,13): error CS8754: There is no target type for 'new()'
                //         _ = new() && s1;
                Diagnostic(ErrorCode.ERR_ImplicitObjectCreationNoTargetType, "new()").WithArguments("new()").WithLocation(26, 13),
                // (27,13): error CS8754: There is no target type for 'new()'
                //         _ = new() && new();
                Diagnostic(ErrorCode.ERR_ImplicitObjectCreationNoTargetType, "new()").WithArguments("new()").WithLocation(27, 13),
                // (27,22): error CS8754: There is no target type for 'new()'
                //         _ = new() && new();
                Diagnostic(ErrorCode.ERR_ImplicitObjectCreationNoTargetType, "new()").WithArguments("new()").WithLocation(27, 22),
                // (28,19): error CS8716: There is no target type for the default literal.
                //         _ = s1 && default;
                Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(28, 19),
                // (29,13): error CS8716: There is no target type for the default literal.
                //         _ = default && s1;
                Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(29, 13),
                // (30,13): error CS8716: There is no target type for the default literal.
                //         _ = default && default;
                Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(30, 13),
                // (30,24): error CS8716: There is no target type for the default literal.
                //         _ = default && default;
                Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(30, 24)
                );
        }
 
        [Fact]
        public void Binary_084_Consumption_Logical_BadReceiver()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(__arglist)
    {
        public static object operator &(object x, object y)
        {
            return x;
        }
        public static bool operator false(object x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator true(object x) => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
        _ = s1 && s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (3,15): error CS1669: __arglist is not valid in this context
                //     extension(__arglist)
                Diagnostic(ErrorCode.ERR_IllegalVarArgs, "__arglist").WithLocation(3, 15),
                // (5,39): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static object operator &(object x, object y)
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "&").WithLocation(5, 39),
                // (9,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator false(object x)
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "false").WithLocation(9, 37),
                // (15,37): error CS9317: The parameter of a unary operator must be the extended type.
                //         public static bool operator true(object x) => throw null;
                Diagnostic(ErrorCode.ERR_BadExtensionUnaryOperatorSignature, "true").WithLocation(15, 37),
                // (24,13): error CS0019: Operator '&&' cannot be applied to operands of type 'object' and 'object'
                //         _ = s1 && s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 && s1").WithArguments("&&", "object", "object").WithLocation(24, 13)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_085_Consumption_Logical_Generic([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T, S>((T, S))
    {
        public static (T, S) operator {{{op[0]}}}((T, S) x, (T, S) y)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}((T, S) x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}((T, S) x) => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = (1, 2);
        s1 = s1 {{{op}}} s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            AssertEx.Equal("Extensions1.extension<int, int>((int, int)).operator " + op[0] + "((int, int), (int, int))", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_086_Consumption_Logical_Generic([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T, S>((T, S))
    {
        public static (T, S) operator {{{op[0]}}}((T, S) x, (T, S) y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
 
    extension<U>(U)
    {
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(U x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(U x) => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = (1, 2);
        s1 = s1 {{{op}}} s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator1").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            AssertEx.Equal("Extensions1.extension<int, int>((int, int)).operator " + op[0] + "((int, int), (int, int))", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_087_Consumption_ExpressionTree([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>")] string op)
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(S1 s1)
    {
        public static S1 operator {{{op}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public void Test()
        {
            Expression<System.Func<S1, S1>> ex = (s1) => s1 {{{op}}} s1;
            ex.Compile()(s1);
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1, S1>> ex = (s1) => s1 {{{op}}} s1;
 
        var s1 = new S1();
        ex.Compile()(s1);
 
        s1.Test();
 
        System.Console.Write(":");
        System.Console.Write(ex);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1operator1:s1 => (s1 " + op + " s1)").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_088_Consumption_ExpressionTree_Lifted([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>")] string op)
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(S1 s1)
    {
        public static S1 operator {{{op}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public void Test()
        {
            Expression<System.Func<S1?, S1?>> ex = (s1) => s1 {{{op}}} s1;
            var d = ex.Compile();
            d(s1);
            System.Console.Write(":");
            d(null);
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1?, S1?>> ex = (s1) => s1 {{{op}}} s1;
 
        var s1 = new S1();
        var d = ex.Compile();
        d(s1);
        System.Console.Write(":");
        d(null);
 
        System.Console.Write(":");
        s1.Test();
 
        System.Console.Write(":");
        System.Console.Write(ex);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1::operator1::s1 => (s1 " + op + " s1)").VerifyDiagnostics();
        }
 
        [Fact]
        public void Binary_089_Consumption_UnsignedRightShift_ExpressionTree()
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(S1 s1)
    {
        public static S1 operator >>>(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1, S1>> ex = (s1) => s1 >>> s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (22,54): error CS7053: An expression tree may not contain '>>>'
                //         Expression<System.Func<S1, S1>> ex = (s1) => s1 >>> s1;
                Diagnostic(ErrorCode.ERR_FeatureNotValidInExpressionTree, "s1 >>> s1").WithArguments(">>>").WithLocation(22, 54)
                );
        }
 
        [Fact]
        public void Binary_090_Consumption_UnsignedRightShift_Lifted_ExpressionTree()
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(S1 s1)
    {
        public static S1 operator >>>(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1?, S1?>> ex = (s1) => s1 >>> s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (22,56): error CS7053: An expression tree may not contain '>>>'
                //         Expression<System.Func<S1?, S1?>> ex = (s1) => s1 >>> s1;
                Diagnostic(ErrorCode.ERR_FeatureNotValidInExpressionTree, "s1 >>> s1").WithArguments(">>>").WithLocation(22, 56)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_091_Consumption_Logical_ExpressionTree([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(S1 s1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(S1 x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(S1 x) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1, S1>> ex = (s1) => s1 {{{op}}} s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (30,54): error CS9324: An expression tree may not contain '&&' or '||' operators that use extension user defined operators.
                //         Expression<System.Func<S1, S1>> ex = (s1) => s1 && s1;
                Diagnostic(ErrorCode.ERR_ExpressionTreeContainsExtensionBasedConditionalLogicalOperator, "s1 " + op + " s1").WithLocation(30, 54)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void Binary_092_Consumption_Logical_Lifted_ExpressionTree([CombinatorialValues("&&", "||")] string op)
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(S1 s1)
    {
        public static S1 operator {{{op[0]}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
 
    extension(S1? s1)
    {
        public static bool operator {{{(op == "&&" ? "false" : "true")}}}(S1? x)
        {
            System.Console.Write("operator2");
            return false;
        }
 
        public static bool operator {{{(op == "&&" ? "true" : "false")}}}(S1? x) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1?, S1?>> ex = (s1) => s1 {{{op}}} s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (33,56): error CS9324: An expression tree may not contain '&&' or '||' operators that use extension user defined operators.
                //         Expression<System.Func<S1?, S1?>> ex = (s1) => s1 && s1;
                Diagnostic(ErrorCode.ERR_ExpressionTreeContainsExtensionBasedConditionalLogicalOperator, "s1 " + op + " s1").WithLocation(33, 56)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct
        /// </summary>
        [Fact]
        public void Binary_093_RefSafety()
        {
            var source = """
class C
{
    S M1()
    {
        S s;
        s = 100 + default(S); // 1
        return s;
    }
 
    S M2()
    {
        return 200 + default(S); // 2
    }
 
    S M3(in int x)
    {
        S s;
        s = x + default(S); // 3
        return s;
    }
 
    S M4(in int x)
    {
        return x + default(S);
    }
 
    S M4s(scoped in int x)
    {
        return x + default(S); // 4
    }
 
    S M5(in int x)
    {
        S s = x + default(S);
        return s;
    }
 
    S M5s(scoped in int x)
    {
        S s = x + default(S);
        return s; // 5
    }
 
    S M6()
    {
        S s = 300 + default(S);
        return s; // 6
    }
 
    void M7(in int x)
    {
        scoped S s;
        s = x + default(S);
        s = 100 + default(S);
    }
}
 
ref struct S
{
}
 
static class Extensions
{
    extension(S)
    {
        public static S operator+(in int x, S y) => throw null;
    }
}
""";
            CreateCompilation(source).VerifyDiagnostics(
                // (6,13): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         s = 100 + default(S); // 1
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "100").WithLocation(6, 13),
                // (6,13): error CS8347: Cannot use a result of 'Extensions.extension(S).operator +(in int, S)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
                //         s = 100 + default(S); // 1
                Diagnostic(ErrorCode.ERR_EscapeCall, "100 + default(S)").WithArguments("Extensions.extension(S).operator +(in int, S)", "x").WithLocation(6, 13),
                // (12,16): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return 200 + default(S); // 2
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "200").WithLocation(12, 16),
                // (12,16): error CS8347: Cannot use a result of 'Extensions.extension(S).operator +(in int, S)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
                //         return 200 + default(S); // 2
                Diagnostic(ErrorCode.ERR_EscapeCall, "200 + default(S)").WithArguments("Extensions.extension(S).operator +(in int, S)", "x").WithLocation(12, 16),
                // (18,13): error CS9077: Cannot return a parameter by reference 'x' through a ref parameter; it can only be returned in a return statement
                //         s = x + default(S); // 3
                Diagnostic(ErrorCode.ERR_RefReturnOnlyParameter, "x").WithArguments("x").WithLocation(18, 13),
                // (18,13): error CS8347: Cannot use a result of 'Extensions.extension(S).operator +(in int, S)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
                //         s = x + default(S); // 3
                Diagnostic(ErrorCode.ERR_EscapeCall, "x + default(S)").WithArguments("Extensions.extension(S).operator +(in int, S)", "x").WithLocation(18, 13),
                // (29,16): error CS9075: Cannot return a parameter by reference 'x' because it is scoped to the current method
                //         return x + default(S); // 4
                Diagnostic(ErrorCode.ERR_RefReturnScopedParameter, "x").WithArguments("x").WithLocation(29, 16),
                // (29,16): error CS8347: Cannot use a result of 'Extensions.extension(S).operator +(in int, S)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
                //         return x + default(S); // 4
                Diagnostic(ErrorCode.ERR_EscapeCall, "x + default(S)").WithArguments("Extensions.extension(S).operator +(in int, S)", "x").WithLocation(29, 16),
                // (41,16): error CS8352: Cannot use variable 's' in this context because it may expose referenced variables outside of their declaration scope
                //         return s; // 5
                Diagnostic(ErrorCode.ERR_EscapeVariable, "s").WithArguments("s").WithLocation(41, 16),
                // (47,16): error CS8352: Cannot use variable 's' in this context because it may expose referenced variables outside of their declaration scope
                //         return s; // 6
                Diagnostic(ErrorCode.ERR_EscapeVariable, "s").WithArguments("s").WithLocation(47, 16)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Nested
        /// </summary>
        [Fact]
        public void Binary_094_RefSafety()
        {
            var source = """
class C
{
    S M()
    {
        S s;
        s = default(S) + 100 + 200;
        return s;
    }
}
 
ref struct S
{
}
 
static class Extensions
{
    extension(S)
    {
        public static S operator+(S y, in int x) => throw null;
    }
}
""";
            CreateCompilation(source).VerifyDiagnostics(
                // (6,13): error CS8347: Cannot use a result of 'Extensions.extension(S).operator +(S, in int)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
                //         s = default(S) + 100 + 200;
                Diagnostic(ErrorCode.ERR_EscapeCall, "default(S) + 100").WithArguments("Extensions.extension(S).operator +(S, in int)", "x").WithLocation(6, 13),
                // (6,13): error CS8347: Cannot use a result of 'Extensions.extension(S).operator +(S, in int)' in this context because it may expose variables referenced by parameter 'y' outside of their declaration scope
                //         s = default(S) + 100 + 200;
                Diagnostic(ErrorCode.ERR_EscapeCall, "default(S) + 100 + 200").WithArguments("Extensions.extension(S).operator +(S, in int)", "y").WithLocation(6, 13),
                // (6,26): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         s = default(S) + 100 + 200;
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "100").WithLocation(6, 26)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Scoped_Left
        /// </summary>
        [Fact]
        public void Binary_095_RefSafety()
        {
            var source = """
ref struct R
{
    private ref readonly int _i;
    public R(in int i) { _i = ref i; }
}
class Program
{
    static R F()
    {
#line 11
        return new R(1) + new R(2);
    }
}
 
static class Extensions
{
    extension(R)
    {
        public static R operator +(scoped R x, R y) => default;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics(
                // (11,16): error CS8347: Cannot use a result of 'Extensions.extension(R).operator +(scoped R, R)' in this context because it may expose variables referenced by parameter 'y' outside of their declaration scope
                //         return new R(1) + new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1) + new R(2)").WithArguments("Extensions.extension(R).operator +(scoped R, R)", "y").WithLocation(11, 16),
                // (11,27): error CS8347: Cannot use a result of 'R.R(in int)' in this context because it may expose variables referenced by parameter 'i' outside of their declaration scope
                //         return new R(1) + new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(2)").WithArguments("R.R(in int)", "i").WithLocation(11, 27),
                // (11,33): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return new R(1) + new R(2);
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "2").WithLocation(11, 33)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Scoped_Right
        /// </summary>
        [Fact]
        public void Binary_096_RefSafety()
        {
            var source = """
ref struct R
{
    private ref readonly int _i;
    public R(in int i) { _i = ref i; }
}
class Program
{
    static R F()
    {
#line 11
        return new R(1) + new R(2);
    }
}
 
static class Extensions
{
    extension(R)
    {
        public static R operator +(R x, scoped R y) => default;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics(
                // (11,16): error CS8347: Cannot use a result of 'R.R(in int)' in this context because it may expose variables referenced by parameter 'i' outside of their declaration scope
                //         return new R(1) + new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1)").WithArguments("R.R(in int)", "i").WithLocation(11, 16),
                // (11,16): error CS8347: Cannot use a result of 'Extensions.extension(R).operator +(R, scoped R)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
                //         return new R(1) + new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1) + new R(2)").WithArguments("Extensions.extension(R).operator +(R, scoped R)", "x").WithLocation(11, 16),
                // (11,22): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return new R(1) + new R(2);
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "1").WithLocation(11, 22)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Scoped_Both
        /// </summary>
        [Fact]
        public void Binary_097_RefSafety()
        {
            var source = """
ref struct R
{
    private ref readonly int _i;
    public R(in int i) { _i = ref i; }
}
class Program
{
    static R F()
    {
        return new R(1) + new R(2);
    }
}
 
static class Extensions
{
    extension(R)
    {
        public static R operator +(scoped R x, scoped R y) => default;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics();
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Scoped_None
        /// </summary>
        [Fact]
        public void Binary_098_RefSafety()
        {
            var source = """
ref struct R
{
    private ref readonly int _i;
    public R(in int i) { _i = ref i; }
}
class Program
{
    static R F()
    {
#line 11
        return new R(1) + new R(2);
    }
}
 
static class Extensions
{
    extension(R)
    {
        public static R operator +(R x, R y) => default;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics(
                // (11,16): error CS8347: Cannot use a result of 'R.R(in int)' in this context because it may expose variables referenced by parameter 'i' outside of their declaration scope
                //         return new R(1) + new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1)").WithArguments("R.R(in int)", "i").WithLocation(11, 16),
                // (11,16): error CS8347: Cannot use a result of 'Extensions.extension(R).operator +(R, R)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
                //         return new R(1) + new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1) + new R(2)").WithArguments("Extensions.extension(R).operator +(R, R)", "x").WithLocation(11, 16),
                // (11,22): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return new R(1) + new R(2);
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "1").WithLocation(11, 22)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedLogical
        /// </summary>
        [Fact]
        public void Binary_099_RefSafety_Logical()
        {
            var text = @"
using System;
class Program
{
    static void Main()
    {
    }
 
    S1 Test()
    {
        S1 global = default;
        S1 local = stackalloc int[100];
 
        // ok
        local = global && local;
        local = local && local;
 
        // ok
        global = global && global;
 
        // error
        global = local && global;
 
        // error
        return global || local;
    }
}
 
ref struct S1
{
    public static implicit operator S1(Span<int> o) => default;
}
 
static class Extensions
{
    extension(S1)
    {
        public static bool operator true(S1 o) => true;
        public static bool operator false(S1 o) => false;
 
        public static S1 operator &(S1 x, S1 y) => x;
        public static S1 operator |(S1 x, S1 y) => x;
    }
}
";
            CreateCompilation(text, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics(
                // (22,18): error CS8352: Cannot use variable 'local' in this context because it may expose referenced variables outside of their declaration scope
                //         global = local && global;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "local").WithArguments("local").WithLocation(22, 18),
                // (22,18): error CS8347: Cannot use a result of 'Extensions.extension(S1).operator &(S1, S1)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
                //         global = local && global;
                Diagnostic(ErrorCode.ERR_EscapeCall, "local && global").WithArguments("Extensions.extension(S1).operator &(S1, S1)", "x").WithLocation(22, 18),
                // (25,16): error CS8347: Cannot use a result of 'Extensions.extension(S1).operator |(S1, S1)' in this context because it may expose variables referenced by parameter 'y' outside of their declaration scope
                //         return global || local;
                Diagnostic(ErrorCode.ERR_EscapeCall, "global || local").WithArguments("Extensions.extension(S1).operator |(S1, S1)", "y").WithLocation(25, 16),
                // (25,26): error CS8352: Cannot use variable 'local' in this context because it may expose referenced variables outside of their declaration scope
                //         return global || local;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "local").WithArguments("local").WithLocation(25, 26)
                 );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedLogicalOperator_RefStruct
        /// </summary>
        [Fact]
        public void Binary_100_RefSafety_Logical()
        {
            var source = """
class C
{
    S M1(S s1, S s2)
    {
        S s = s1 && s2;
        return s; // 1
    }
 
    S M2(S s1, S s2)
    {
        return s1 && s2; // 2
    }
 
    S M3(in S s1, in S s2)
    {
        S s = s1 && s2;
        return s;
    }
 
    S M4(scoped in S s1, in S s2)
    {
        S s = s1 && s2;
        return s; // 3
    }
 
    S M5(in S s1, scoped in S s2)
    {
        S s = s1 && s2;
        return s; // 4
    }
}
 
ref struct S
{
}
 
static class Extensions
{
    extension(S)
    {
        public static bool operator true(in S s) => throw null;
        public static bool operator false(in S s) => throw null;
        public static S operator &(in S x, in S y) => throw null;
        public static S operator |(in S x, in S y) => throw null;
    }
}
""";
            CreateCompilation(source).VerifyDiagnostics(
                // (6,16): error CS8352: Cannot use variable 's' in this context because it may expose referenced variables outside of their declaration scope
                //         return s; // 1
                Diagnostic(ErrorCode.ERR_EscapeVariable, "s").WithArguments("s").WithLocation(6, 16),
                // (11,16): error CS8166: Cannot return a parameter by reference 's1' because it is not a ref parameter
                //         return s1 && s2; // 2
                Diagnostic(ErrorCode.ERR_RefReturnParameter, "s1").WithArguments("s1").WithLocation(11, 16),
                // (11,16): error CS8347: Cannot use a result of 'Extensions.extension(S).operator &(in S, in S)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
                //         return s1 && s2; // 2
                Diagnostic(ErrorCode.ERR_EscapeCall, "s1 && s2").WithArguments("Extensions.extension(S).operator &(in S, in S)", "x").WithLocation(11, 16),
                // (23,16): error CS8352: Cannot use variable 's' in this context because it may expose referenced variables outside of their declaration scope
                //         return s; // 3
                Diagnostic(ErrorCode.ERR_EscapeVariable, "s").WithArguments("s").WithLocation(23, 16),
                // (29,16): error CS8352: Cannot use variable 's' in this context because it may expose referenced variables outside of their declaration scope
                //         return s; // 4
                Diagnostic(ErrorCode.ERR_EscapeVariable, "s").WithArguments("s").WithLocation(29, 16)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedLogicalOperator_RefStruct_Scoped_Left
        /// </summary>
        [Fact]
        public void Binary_101_RefSafety_Logical()
        {
            var source = """
ref struct R
{
    private ref readonly int _i;
    public R(in int i) { _i = ref i; }
}
class Program
{
    static R F()
    {
#line 13
        return new R(1) || new R(2);
    }
 
    static R F2()
    {
        return new R(1) | new R(2);
    }
}
 
static class Extensions
{
    extension(R)
    {
        public static bool operator true(R r) => true;
        public static bool operator false(R r) => false;
        public static R operator |(scoped R x, R y) => default;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics(
                // (13,16): error CS8347: Cannot use a result of 'Extensions.extension(R).operator |(scoped R, R)' in this context because it may expose variables referenced by parameter 'y' outside of their declaration scope
                //         return new R(1) || new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1) || new R(2)").WithArguments("Extensions.extension(R).operator |(scoped R, R)", "y").WithLocation(13, 16),
                // (13,28): error CS8347: Cannot use a result of 'R.R(in int)' in this context because it may expose variables referenced by parameter 'i' outside of their declaration scope
                //         return new R(1) || new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(2)").WithArguments("R.R(in int)", "i").WithLocation(13, 28),
                // (13,34): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return new R(1) || new R(2);
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "2").WithLocation(13, 34),
                // (18,16): error CS8347: Cannot use a result of 'Extensions.extension(R).operator |(scoped R, R)' in this context because it may expose variables referenced by parameter 'y' outside of their declaration scope
                //         return new R(1) | new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1) | new R(2)").WithArguments("Extensions.extension(R).operator |(scoped R, R)", "y").WithLocation(18, 16),
                // (18,27): error CS8347: Cannot use a result of 'R.R(in int)' in this context because it may expose variables referenced by parameter 'i' outside of their declaration scope
                //         return new R(1) | new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(2)").WithArguments("R.R(in int)", "i").WithLocation(18, 27),
                // (18,33): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return new R(1) | new R(2);
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "2").WithLocation(18, 33)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedLogicalOperator_RefStruct_Scoped_Right
        /// </summary>
        [Fact]
        public void Binary_102_RefSafety_Logical()
        {
            var source = """
ref struct R
{
    private ref readonly int _i;
    public R(in int i) { _i = ref i; }
}
class Program
{
    static R F()
    {
#line 13
        return new R(1) || new R(2);
    }
 
    static R F2()
    {
        return new R(1) | new R(2);
    }
}
 
static class Extensions
{
    extension(R)
    {
        public static bool operator true(R r) => true;
        public static bool operator false(R r) => false;
        public static R operator |(R x, scoped R y) => default;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics(
                // (13,16): error CS8347: Cannot use a result of 'R.R(in int)' in this context because it may expose variables referenced by parameter 'i' outside of their declaration scope
                //         return new R(1) || new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1)").WithArguments("R.R(in int)", "i").WithLocation(13, 16),
                // (13,16): error CS8347: Cannot use a result of 'Extensions.extension(R).operator |(R, scoped R)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
                //         return new R(1) || new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1) || new R(2)").WithArguments("Extensions.extension(R).operator |(R, scoped R)", "x").WithLocation(13, 16),
                // (13,22): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return new R(1) || new R(2);
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "1").WithLocation(13, 22),
                // (18,16): error CS8347: Cannot use a result of 'R.R(in int)' in this context because it may expose variables referenced by parameter 'i' outside of their declaration scope
                //         return new R(1) | new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1)").WithArguments("R.R(in int)", "i").WithLocation(18, 16),
                // (18,16): error CS8347: Cannot use a result of 'Extensions.extension(R).operator |(R, scoped R)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
                //         return new R(1) | new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1) | new R(2)").WithArguments("Extensions.extension(R).operator |(R, scoped R)", "x").WithLocation(18, 16),
                // (18,22): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return new R(1) | new R(2);
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "1").WithLocation(18, 22)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedLogicalOperator_RefStruct_Scoped_Both
        /// </summary>
        [Fact]
        public void Binary_103_RefSafety_Logical()
        {
            var source = """
ref struct R
{
    private ref readonly int _i;
    public R(in int i) { _i = ref i; }
}
class Program
{
    static R F()
    {
        return new R(1) || new R(2);
    }
 
    static R F2()
    {
        return new R(1) | new R(2);
    }
}
 
static class Extensions
{
    extension(R)
    {
        public static bool operator true(R r) => true;
        public static bool operator false(R r) => false;
        public static R operator |(scoped R x, scoped R y) => default;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics();
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedLogicalOperator_RefStruct_Scoped_None
        /// </summary>
        [Fact]
        public void Binary_104_RefSafety_Logical()
        {
            var source = """
ref struct R
{
    private ref readonly int _i;
    public R(in int i) { _i = ref i; }
}
class Program
{
    static R F()
    {
#line 13
        return new R(1) || new R(2);
    }
 
    static R F2()
    {
        return new R(1) | new R(2);
    }
}
 
static class Extensions
{
    extension(R)
    {
        public static bool operator true(R r) => true;
        public static bool operator false(R r) => false;
        public static R operator |(R x, R y) => default;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics(
                // (13,16): error CS8347: Cannot use a result of 'R.R(in int)' in this context because it may expose variables referenced by parameter 'i' outside of their declaration scope
                //         return new R(1) || new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1)").WithArguments("R.R(in int)", "i").WithLocation(13, 16),
                // (13,16): error CS8347: Cannot use a result of 'Extensions.extension(R).operator |(R, R)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
                //         return new R(1) || new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1) || new R(2)").WithArguments("Extensions.extension(R).operator |(R, R)", "x").WithLocation(13, 16),
                // (13,22): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return new R(1) || new R(2);
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "1").WithLocation(13, 22),
                // (18,16): error CS8347: Cannot use a result of 'R.R(in int)' in this context because it may expose variables referenced by parameter 'i' outside of their declaration scope
                //         return new R(1) | new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1)").WithArguments("R.R(in int)", "i").WithLocation(18, 16),
                // (18,16): error CS8347: Cannot use a result of 'Extensions.extension(R).operator |(R, R)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
                //         return new R(1) | new R(2);
                Diagnostic(ErrorCode.ERR_EscapeCall, "new R(1) | new R(2)").WithArguments("Extensions.extension(R).operator |(R, R)", "x").WithLocation(18, 16),
                // (18,22): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return new R(1) | new R(2);
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "1").WithLocation(18, 22)
                );
        }
 
        [Fact]
        public void Binary_105_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x, C1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
 
    extension(C2)
    {
        public static C2 operator -(C2? x, C2? y)
        {
            System.Console.Write("operator2");
            return new C2();
        }
    }
}
 
public class C1
{}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C1? x1 = null;
        C1? x2 = null;
        C1 y = new C1();
#line 25
        _ = x1 - y;
        y = y - x2;
 
        C2? z = null;
        _ = z - z;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (25,13): warning CS8604: Possible null reference argument for parameter 'x' in 'C1 extension(C1).operator -(C1 x, C1 y)'.
                //         _ = x1 - y;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "C1 extension(C1).operator -(C1 x, C1 y)").WithLocation(25, 13),
                // (26,17): warning CS8604: Possible null reference argument for parameter 'y' in 'C1 extension(C1).operator -(C1 x, C1 y)'.
                //         y = y - x2;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("y", "C1 extension(C1).operator -(C1 x, C1 y)").WithLocation(26, 17)
                );
        }
 
        [Fact]
        public void Binary_106_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1)
    {
        public static C1? operator -(C1 x, C1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public class C1
{}
 
class Program
{
    static void Main()
    {
        var x = new C1();
        C1 y = x - x;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (23,16): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         C1 y = x - x;
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x - x").WithLocation(23, 16)
                );
        }
 
        [Fact]
        public void Binary_107_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T)
    {
        public static T operator -(T x, T y)
        {
            return x;
        }
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x1 = null;
        C2? x2 = null;
        var y = new C2();
        (x1 - y).ToString();
        (y - x2).ToString();
        (y - y).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (24,10): warning CS8602: Dereference of a possibly null reference.
                //         (x1 - y).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1 - y").WithLocation(24, 10),
                // (25,10): warning CS8602: Dereference of a possibly null reference.
                //         (y - x2).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y - x2").WithLocation(25, 10)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().ToArray();
 
            Assert.Equal(3, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator -(C2?, C2?)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator -(C2?, C2?)", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2>(C2).operator -(C2, C2)", model.GetSymbolInfo(opNodes[2]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void Binary_108_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T)
    {
        public static T operator -(int x, T y)
        {
            return y;
        }
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        var y = new C2();
        (1 - x).ToString();
        (1 - y).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (23,10): warning CS8602: Dereference of a possibly null reference.
                //         (1 - x).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "1 - x").WithLocation(23, 10)
                );
        }
 
        [Fact]
        public void Binary_109_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T)
    {
        public static T operator -(T x, int y)
        {
            return x;
        }
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        var y = new C2();
        (x - 1).ToString();
        (y - 1).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (23,10): warning CS8602: Dereference of a possibly null reference.
                //         (x - 1).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x - 1").WithLocation(23, 10)
                );
        }
 
        [Fact]
        public void Binary_110_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T, S>(C1<T>) where T : new() where S : new()
    {
        public static T operator -(C1<T> x, C1<S> y)
        {
            return x.F;
        }
    }
}
 
public class C1<T> where T : new()
{
    public T F = new T();
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        var y = Get(new C2());
 
        (x - y).ToString();
        (y - x).ToString();
    }
 
    static C1<T> Get<T>(T x) where T : new()
    {
        return new C1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (29,10): warning CS8602: Dereference of a possibly null reference.
                //         (x - y).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x - y").WithLocation(29, 10)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().ToArray();
 
            Assert.Equal(2, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?, C2>(C1<C2?>).operator -(C1<C2?>, C1<C2>)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2, C2?>(C1<C2>).operator -(C1<C2>, C1<C2?>)", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void Binary_111_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T, S>(C1<T>) where T : new() where S : new()
    {
        public static T operator -(C1<S> y, C1<T> x)
        {
            return x.F;
        }
    }
}
 
public class C1<T> where T : new()
{
    public T F = new T();
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        var y = Get(new C2());
 
        (x - y).ToString();
        (y - x).ToString();
    }
 
    static C1<T> Get<T>(T x) where T : new()
    {
        return new C1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (30,10): warning CS8602: Dereference of a possibly null reference.
                //         (y - x).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y - x").WithLocation(30, 10)
                );
        }
 
        [Fact]
        public void Binary_112_NullableAnalysis_Lifted()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(S1<T>) where T : new()
    {
        public static S1<T> operator -(S1<T> x, int y)
        {
            return x;
        }
    }
}
 
public struct S1<T> where T : new()
{
    public T F;
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null) - 1;
 
        if (x != null)
            x.Value.F.ToString();
 
        var y = Get(new C2()) - 1;
 
        if (y != null)
            y.Value.F.ToString();
    }
 
    static S1<T>? Get<T>(T x) where T : new()
    {
        return new S1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (29,13): warning CS8602: Dereference of a possibly null reference.
                //             x.Value.F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Value.F").WithLocation(29, 13)
                );
        }
 
        [Fact]
        public void Binary_113_NullableAnalysis_Lifted()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(S1<T>) where T : new()
    {
        public static S1<T> operator -(int y, S1<T> x)
        {
            return x;
        }
    }
}
 
public struct S1<T> where T : new()
{
    public T F;
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = 1 - Get((C2?)null);
 
        if (x != null)
            x.Value.F.ToString();
 
        var y = 1 - Get(new C2());
 
        if (y != null)
            y.Value.F.ToString();
    }
 
    static S1<T>? Get<T>(T x) where T : new()
    {
        return new S1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (29,13): warning CS8602: Dereference of a possibly null reference.
                //             x.Value.F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Value.F").WithLocation(29, 13)
                );
        }
 
        [Fact]
        public void Binary_114_NullableAnalysis_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T) where T : notnull
    {
        public static object operator -(T x, T y)
        {
            return x;
        }
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        var y = new C2();
        (x - y).ToString();
        (y - x).ToString();
        (y - y).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (23,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(T)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (x - y).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "x - y").WithArguments("Extensions1.extension<T>(T)", "T", "C2?").WithLocation(23, 10),
                // (24,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(T)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (y - x).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "y - x").WithArguments("Extensions1.extension<T>(T)", "T", "C2?").WithLocation(24, 10)
                );
        }
 
        [Fact]
        public void Binary_115_NullableAnalysis_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T, S>(C1<T>) where T : notnull, new() where S : notnull, new()
    {
        public static T operator -(C1<T> x, C1<S> y)
        {
            return x.F;
        }
    }
}
 
public class C1<T> where T : new()
{
    public T F = new T();
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        var y = Get(new C2());
        (x - y).ToString();
        (y - x).ToString();
        (y - y).ToString();
    }
 
    static C1<T> Get<T>(T x) where T : new()
    {
        return new C1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (28,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T, S>(C1<T>)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (x - y).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "x - y").WithArguments("Extensions1.extension<T, S>(C1<T>)", "T", "C2?").WithLocation(28, 10),
                // (28,10): warning CS8602: Dereference of a possibly null reference.
                //         (x - y).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x - y").WithLocation(28, 10),
                // (29,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'S' in the generic type or method 'Extensions1.extension<T, S>(C1<T>)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (y - x).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "y - x").WithArguments("Extensions1.extension<T, S>(C1<T>)", "S", "C2?").WithLocation(29, 10)
                );
        }
 
        [Fact]
        public void Binary_116_NullableAnalysis_Logical()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator &(C1 x, C1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public static bool operator true(C1 x) => true;
        public static bool operator false(C1 x) => false;
    }
 
    extension(C2)
    {
        public static C2 operator &(C2? x, C2? y)
        {
            System.Console.Write("operator1");
            return new C2();
        }
 
        public static bool operator true(C2? x) => true;
        public static bool operator false(C2? x) => false;
    }
}
 
public class C1
{}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C1? x1 = null;
        C1? x2 = null;
        C1 y = new C1();
#line 28
        _ = x1 && y;
        y = y && x2;
 
        C2? z = null;
        _ = z && z;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (28,13): warning CS8604: Possible null reference argument for parameter 'x' in 'bool extension(C1).operator false(C1 x)'.
                //         _ = x1 && y;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "bool extension(C1).operator false(C1 x)").WithLocation(28, 13),
                // (28,13): warning CS8604: Possible null reference argument for parameter 'x' in 'C1 extension(C1).operator &(C1 x, C1 y)'.
                //         _ = x1 && y;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "C1 extension(C1).operator &(C1 x, C1 y)").WithLocation(28, 13),
                // (29,18): warning CS8604: Possible null reference argument for parameter 'y' in 'C1 extension(C1).operator &(C1 x, C1 y)'.
                //         y = y && x2;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("y", "C1 extension(C1).operator &(C1 x, C1 y)").WithLocation(29, 18)
                );
        }
 
        [Fact]
        public void Binary_117_NullableAnalysis_Logical()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1)
    {
        public static C1? operator &(C1 x, C1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public static bool operator true(C1 x) => true;
        public static bool operator false(C1 x) => false;
    }
}
 
public class C1
{}
 
class Program
{
    static void Main()
    {
        var x = new C1();
        C1 y = x && x;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (26,16): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         C1 y = x && x;
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x && x").WithLocation(26, 16)
                );
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/29605")]
        public void Binary_118_NullableAnalysis_Logical()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T)
    {
        public static T operator &(T x, T y)
        {
            return x;
        }
 
        public static bool operator true(T x) => true;
        public static bool operator false(T x) => false;
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x1 = null;
        C2? x2 = null;
        var y = new C2();
        (x1 && y).ToString();
        (y && x2).ToString();
        (y && y).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyDiagnostics(
                // (27,10): warning CS8602: Dereference of a possibly null reference.
                //         (x1 && y).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1 && y").WithLocation(27, 10),
                // (28,10): warning CS8602: Dereference of a possibly null reference.
                //         (y && x2).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y && x2").WithLocation(28, 10)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().ToArray();
 
            Assert.Equal(3, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator &(C2?, C2?)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator &(C2?, C2?)", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2>(C2).operator &(C2, C2)", model.GetSymbolInfo(opNodes[2]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void Binary_119_NullableAnalysis_Logical()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(C1<T>)
    {
        public static C1<T> operator &(C1<T> x, C1<T> y)
        {
            return x;
        }
 
        public static bool operator true(C1<T> x) => true;
        public static bool operator false(C1<T> x) => false;
    }
}
 
public interface C1<out T>
{
    public T F { get; }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        var y = Get(new C2());
 
        (x && y).F.ToString();
        (y && x).F.ToString();
 
        var z = Get((C2?)null);
        (y && z).F.ToString();
        (y && y).F.ToString();
    }
 
    static C1<T> Get<T>(T x)
    {
        throw null!;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (32,9): warning CS8602: Dereference of a possibly null reference.
                //         (x && y).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(x && y).F").WithLocation(32, 9),
                // (33,9): warning CS8602: Dereference of a possibly null reference.
                //         (y && x).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(y && x).F").WithLocation(33, 9),
                // (36,9): warning CS8602: Dereference of a possibly null reference.
                //         (y && z).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(y && z).F").WithLocation(36, 9)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().ToArray();
 
            Assert.Equal(4, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?>(C1<C2?>).operator &(C1<C2?>, C1<C2?>)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2?>(C1<C2?>).operator &(C1<C2?>, C1<C2?>)", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2?>(C1<C2?>).operator &(C1<C2?>, C1<C2?>)", model.GetSymbolInfo(opNodes[2]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2>(C1<C2>).operator &(C1<C2>, C1<C2>)", model.GetSymbolInfo(opNodes[3]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void Binary_120_NullableAnalysis_Logical()
        {
            var src = $$$"""
#nullable enable
 
public interface C1<out T>
{
    public T F { get; }
 
    public static C1<T> operator &(C1<T> x, C1<T> y)
    {
        return x;
    }
 
    public static bool operator true(C1<T> x) => true;
    public static bool operator false(C1<T> x) => false;
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        var y = Get(new C2());
 
        (x && y).F.ToString();
        (y && x).F.ToString();
 
        var z = Get((C2?)null);
        (y && z).F.ToString();
        (y && y).F.ToString();
    }
 
    static C1<T> Get<T>(T x)
    {
        throw null!;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (26,9): warning CS8602: Dereference of a possibly null reference.
                //         (x && y).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(x && y).F").WithLocation(26, 9),
                // (27,15): warning CS8620: Argument of type 'C1<C2?>' cannot be used for parameter 'y' of type 'C1<C2>' in 'C1<C2> C1<C2>.operator &(C1<C2> x, C1<C2> y)' due to differences in the nullability of reference types.
                //         (y && x).F.ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("C1<C2?>", "C1<C2>", "y", "C1<C2> C1<C2>.operator &(C1<C2> x, C1<C2> y)").WithLocation(27, 15),
                // (30,15): warning CS8620: Argument of type 'C1<C2?>' cannot be used for parameter 'y' of type 'C1<C2>' in 'C1<C2> C1<C2>.operator &(C1<C2> x, C1<C2> y)' due to differences in the nullability of reference types.
                //         (y && z).F.ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("C1<C2?>", "C1<C2>", "y", "C1<C2> C1<C2>.operator &(C1<C2> x, C1<C2> y)").WithLocation(30, 15)
                );
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/29605")]
        public void Binary_121_NullableAnalysis_Logical_Lifted()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(S1<T>) where T : new()
    {
        public static S1<T> operator &(S1<T> x, S1<T> y)
        {
            return x;
        }
    }
 
    extension<T>(S1<T>?) where T : new()
    {
        public static bool operator true(S1<T>? x) => true;
        public static bool operator false(S1<T>? x) => false;
    }
}
 
public struct S1<T> where T : new()
{
    public T F;
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        var x1 = x && x;
 
        if (x1 != null)
            x1.Value.F.ToString();
 
        var y = Get(new C2());
        var y1 = y && y;
 
        if (y1 != null)
            y1.Value.F.ToString();
    }
 
    static S1<T>? Get<T>(T x) where T : new()
    {
        return new S1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyDiagnostics(
                // (36,13): warning CS8602: Dereference of a possibly null reference.
                //             x1.Value.F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1.Value.F").WithLocation(36, 13)
                );
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/29605")]
        public void Binary_122_NullableAnalysis_Logical_Lifted()
        {
            var src = $$$"""
#nullable enable
 
public struct S1<T> where T : new()
{
    public T F;
 
    public static S1<T> operator &(S1<T> x, S1<T> y)
    {
        return x;
    }
 
    public static bool operator true(S1<T>? x) => true;
    public static bool operator false(S1<T>? x) => false;
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        var x1 = x && x;
 
        if (x1 != null)
            x1.Value.F.ToString();
 
        var y = Get(new C2());
        var y1 = y && y;
 
        if (y1 != null)
            y1.Value.F.ToString();
    }
 
    static S1<T>? Get<T>(T x) where T : new()
    {
        return new S1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyDiagnostics(
                // (27,13): warning CS8602: Dereference of a possibly null reference.
                //             x1.Value.F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1.Value.F").WithLocation(27, 13)
                );
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/29605")]
        public void Binary_123_NullableAnalysis_Logical_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T) where T : notnull
    {
        public static T operator &(T x, T y)
        {
            return x;
        }
    }
 
    extension<T>(T)
    {
        public static bool operator true(T x) => true;
        public static bool operator false(T x) => false;
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        var y = new C2();
        (x && y).ToString();
        (y && x).ToString();
        (y && y).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyDiagnostics(
                // (29,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(T)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (x && y).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "x && y").WithArguments("Extensions1.extension<T>(T)", "T", "C2?").WithLocation(29, 10),
                // (29,10): warning CS8602: Dereference of a possibly null reference.
                //         (x && y).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x && y").WithLocation(29, 10),
                // (30,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(T)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (y && x).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "y && x").WithArguments("Extensions1.extension<T>(T)", "T", "C2?").WithLocation(30, 10),
                // (30,10): warning CS8602: Dereference of a possibly null reference.
                //         (y && x).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y && x").WithLocation(30, 10)
                );
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/29605")]
        public void Binary_124_NullableAnalysis_Logical_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T)
    {
        public static T operator &(T x, T y)
        {
            return x;
        }
    }
 
    extension<T>(T) where T : notnull
    {
        public static bool operator true(T x) => true;
        public static bool operator false(T x) => false;
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        var y = new C2();
        (x && y).ToString();
        (y && x).ToString();
        (y && y).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyDiagnostics(
                // (29,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(T)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (x && y).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "x").WithArguments("Extensions1.extension<T>(T)", "T", "C2?").WithLocation(29, 10),
                // (29,10): warning CS8602: Dereference of a possibly null reference.
                //         (x && y).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x && y").WithLocation(29, 10),
                // (30,10): warning CS8602: Dereference of a possibly null reference.
                //         (y && x).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y && x").WithLocation(30, 10)
                );
        }
 
        [Fact]
        public void Binary_125_NullableAnalysis_Logical_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(C1<T>) where T : notnull
    {
        public static C1<T> operator &(C1<T> x, C1<T> y)
        {
            return x;
        }
 
        public static bool operator true(C1<T> x) => true;
        public static bool operator false(C1<T> x) => false;
    }
}
 
public interface C1<out T>
{
    public T F { get; }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        var y = Get(new C2());
        (x && y).F.ToString();
        (y && x).F.ToString();
        (y && y).F.ToString();
    }
 
    static C1<T> Get<T>(T x)
    {
        throw null!;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (31,9): warning CS8602: Dereference of a possibly null reference.
                //         (x && y).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(x && y).F").WithLocation(31, 9),
                // (31,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(C1<T>)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (x && y).F.ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "x && y").WithArguments("Extensions1.extension<T>(C1<T>)", "T", "C2?").WithLocation(31, 10),
                // (31,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(C1<T>)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (x && y).F.ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "x").WithArguments("Extensions1.extension<T>(C1<T>)", "T", "C2?").WithLocation(31, 10),
                // (32,9): warning CS8602: Dereference of a possibly null reference.
                //         (y && x).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(y && x).F").WithLocation(32, 9),
                // (32,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(C1<T>)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (y && x).F.ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "y && x").WithArguments("Extensions1.extension<T>(C1<T>)", "T", "C2?").WithLocation(32, 10),
                // (32,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(C1<T>)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (y && x).F.ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "y").WithArguments("Extensions1.extension<T>(C1<T>)", "T", "C2?").WithLocation(32, 10)
                );
        }
 
        [Fact]
        public void Binary_126_NullableAnalysis_Logical_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public interface C1<out T> where T : notnull
{
    public T F { get; }
 
    public static C1<T> operator &(C1<T> x, C1<T> y)
    {
        return x;
    }
 
    public static bool operator true(C1<T> x) => true;
    public static bool operator false(C1<T> x) => false;
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        var y = Get(new C2());
        (x && y).F.ToString();
        (y && x).F.ToString();
        (y && y).F.ToString();
    }
 
    static C1<T> Get<T>(T x) where T : notnull
    {
        throw null!;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (23,17): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Program.Get<T>(T)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         var x = Get((C2?)null);
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "Get").WithArguments("Program.Get<T>(T)", "T", "C2?").WithLocation(23, 17),
                // (25,10): warning CS8620: Argument of type 'C1<C2?>' cannot be used for parameter 'x' of type 'C1<C2>' in 'C1<C2> C1<C2>.operator &(C1<C2> x, C1<C2> y)' due to differences in the nullability of reference types.
                //         (x && y).F.ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("C1<C2?>", "C1<C2>", "x", "C1<C2> C1<C2>.operator &(C1<C2> x, C1<C2> y)").WithLocation(25, 10),
                // (26,15): warning CS8620: Argument of type 'C1<C2?>' cannot be used for parameter 'y' of type 'C1<C2>' in 'C1<C2> C1<C2>.operator &(C1<C2> x, C1<C2> y)' due to differences in the nullability of reference types.
                //         (y && x).F.ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("C1<C2?>", "C1<C2>", "y", "C1<C2> C1<C2>.operator &(C1<C2> x, C1<C2> y)").WithLocation(26, 15)
                );
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/78828")]
        public void Binary_127_NullableAnalysis_WithLambda()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T)
    {
        public static T operator -(T x, System.Func<T> y)
        {
            return x;
        }
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x1 = null;
        var y = new C2();
        (y - (() => x1)).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            // https://github.com/dotnet/roslyn/issues/78828: Expect to infer T as C2? and get a null dereference warning.
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().ToArray();
 
            Assert.Equal(1, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2>(C2).operator -(C2, System.Func<C2>)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void Binary_128_NullableAnalysis_Logical_Chained()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T)
    {
        public static T operator &(T x, T y)
        {
            return x;
        }
 
        public static bool operator true(T x) => true;
        public static bool operator false(T x) => false;
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x1 = null;
        var y = new C2();
        (x1 && y && y && y && y && y).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
 
            comp.VerifyDiagnostics(
                // (26,10): warning CS8602: Dereference of a possibly null reference.
                //         (x1 && y && y && y && y && y).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1 && y && y && y && y && y").WithLocation(26, 10)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.BinaryExpressionSyntax>().ToArray();
 
            Assert.Equal(5, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator &(C2?, C2?)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator &(C2?, C2?)", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator &(C2?, C2?)", model.GetSymbolInfo(opNodes[2]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator &(C2?, C2?)", model.GetSymbolInfo(opNodes[3]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator &(C2?, C2?)", model.GetSymbolInfo(opNodes[4]).Symbol.ToDisplayString());
        }
 
        [Theory]
        [CombinatorialData]
        public void CompoundAssignment_001_Declaration([CombinatorialValues("+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>=", ">>>=")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(ref S1 s1)
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions2
{
    extension(ref S1 s1)
    {
        public S1 operator {{{op}}}(int x) => throw null;
    }
}
 
static class Extensions3
{
    extension(ref S1 s1)
    {
        void operator {{{op}}}(int x) {}
    }
    extension(C1)
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions4
{
    extension(ref S1? s1)
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions5
{
    extension(S1 s1)
    {
#line 600
        public void operator {{{op}}}(int x) {}
    }
#line 700
    extension(ref C2 c2)
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions6
{
    extension(C2 c2)
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions7
{
    extension(in S1 s1)
    {
#line 800
        public void operator {{{op}}}(int x) {}
    }
#line 900
    extension(in C2 c2)
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions8
{
    extension(ref readonly S1 s1)
    {
#line 1000
        public void operator {{{op}}}(int x) {}
    }
#line 1100
    extension(ref readonly C2 c2)
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions9
{
    extension<T>(T t) where T : struct
    {
#line 1200
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions10
{
    extension<T>(T t) where T : class
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions11
{
    extension<T>(T t)
    {
#line 1300
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions12
{
    extension<T>(ref T t) where T : struct
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions13
{
#line 1400
    extension<T>(ref T t) where T : class
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions14
{
#line 1500
    extension<T>(ref T t)
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions15
{
#line 1600
    extension<T>(in T t) where T : struct
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions16
{
#line 1700
    extension<T>(in T t) where T : class
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions17
{
#line 1800
    extension<T>(in T t)
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions18
{
#line 1900
    extension<T>(ref readonly T t) where T : struct
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions19
{
#line 2000
    extension<T>(ref readonly T t) where T : class
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions20
{
#line 2100
    extension<T>(ref readonly T t)
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions21
{
    extension(C2)
    {
#line 2200
        public void operator {{{op}}}(int x) {}
    }
}
 
struct S1
{}
 
static class C1
{}
 
class C2
{}
""";
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (13,28): error CS9503: The return type for this operator must be void
                //         public S1 operator +=(int x) => throw null;
                Diagnostic(ErrorCode.ERR_OperatorMustReturnVoid, op).WithLocation(13, 28),
                // (21,23): error CS9501: User-defined operator 'Extensions3.extension(ref S1).operator +=(int)' must be declared public
                //         void operator +=(int x) {}
                Diagnostic(ErrorCode.ERR_OperatorsMustBePublic, op).WithArguments("Extensions3.extension(ref S1).operator " + op + "(int)").WithLocation(21, 23),
                // (25,30): error CS9321: An extension block extending a static class cannot contain user-defined operators
                //         public void operator +=(int x) {}
                Diagnostic(ErrorCode.ERR_OperatorInExtensionOfStaticClass, op).WithLocation(25, 30),
                // (600,30): error CS9322: Cannot declare instance operator for a struct unless containing extension block receiver parameter is a 'ref' parameter
                //         public void operator +=(int x) {}
                Diagnostic(ErrorCode.ERR_InstanceOperatorStructExtensionWrongReceiverRefKind, op).WithLocation(600, 30),
                // (700,19): error CS9300: The 'ref' receiver parameter of an extension block must be a value type or a generic type constrained to struct.
                //     extension(ref C2 c2)
                Diagnostic(ErrorCode.ERR_RefExtensionParameterMustBeValueTypeOrConstrainedToOne, "C2").WithLocation(700, 19),
                // (800,30): error CS9322: Cannot declare instance operator for a struct unless containing extension block receiver parameter is a 'ref' parameter
                //         public void operator +=(int x) {}
                Diagnostic(ErrorCode.ERR_InstanceOperatorStructExtensionWrongReceiverRefKind, op).WithLocation(800, 30),
                // (900,18): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension(in C2 c2)
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "C2").WithLocation(900, 18),
                // (1000,30): error CS9322: Cannot declare instance operator for a struct unless containing extension block receiver parameter is a 'ref' parameter
                //         public void operator +=(int x) {}
                Diagnostic(ErrorCode.ERR_InstanceOperatorStructExtensionWrongReceiverRefKind, op).WithLocation(1000, 30),
                // (1100,28): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension(ref readonly C2 c2)
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "C2").WithLocation(1100, 28),
                // (1200,30): error CS9322: Cannot declare instance operator for a struct unless containing extension block receiver parameter is a 'ref' parameter
                //         public void operator +=(int x) {}
                Diagnostic(ErrorCode.ERR_InstanceOperatorStructExtensionWrongReceiverRefKind, op).WithLocation(1200, 30),
                // (1300,30): error CS9323: Cannot declare instance extension operator for a type that is not known to be a struct and is not known to be a class
                //         public void operator +=(int x) {}
                Diagnostic(ErrorCode.ERR_InstanceOperatorExtensionWrongReceiverType, op).WithLocation(1300, 30),
                // (1400,22): error CS9300: The 'ref' receiver parameter of an extension block must be a value type or a generic type constrained to struct.
                //     extension<T>(ref T t) where T : class
                Diagnostic(ErrorCode.ERR_RefExtensionParameterMustBeValueTypeOrConstrainedToOne, "T").WithLocation(1400, 22),
                // (1500,22): error CS9300: The 'ref' receiver parameter of an extension block must be a value type or a generic type constrained to struct.
                //     extension<T>(ref T t)
                Diagnostic(ErrorCode.ERR_RefExtensionParameterMustBeValueTypeOrConstrainedToOne, "T").WithLocation(1500, 22),
                // (1600,21): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension<T>(in T t) where T : struct
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "T").WithLocation(1600, 21),
                // (1700,21): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension<T>(in T t) where T : class
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "T").WithLocation(1700, 21),
                // (1800,21): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension<T>(in T t)
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "T").WithLocation(1800, 21),
                // (1900,31): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension<T>(ref readonly T t) where T : struct
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "T").WithLocation(1900, 31),
                // (2000,31): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension<T>(ref readonly T t) where T : class
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "T").WithLocation(2000, 31),
                // (2100,31): error CS9301: The 'in' or 'ref readonly' receiver parameter of extension must be a concrete (non-generic) value type.
                //     extension<T>(ref readonly T t)
                Diagnostic(ErrorCode.ERR_InExtensionParameterMustBeValueType, "T").WithLocation(2100, 31),
                // (2200,30): error CS9303: 'operator +=': cannot declare instance members in an extension block with an unnamed receiver parameter
                //         public void operator +=(int x) {}
                Diagnostic(ErrorCode.ERR_InstanceMemberWithUnnamedExtensionsParameter, op).WithArguments("operator " + op).WithLocation(2200, 30)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void CompoundAssignment_002_Declaration([CombinatorialValues("+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>=", ">>>=")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(ref S1 s1)
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            CompileAndVerify(comp, symbolValidator: verify, sourceSymbolValidator: verify, verify: Verification.FailsPEVerify).VerifyDiagnostics();
 
            void verify(ModuleSymbol m)
            {
                var name = CompoundAssignmentOperatorName(op);
                var method = m.GlobalNamespace.GetMember<MethodSymbol>("Extensions1." + name);
 
                AssertEx.Equal("Extensions1." + name + "(ref S1, int)", method.ToDisplayString());
                Assert.Equal(MethodKind.Ordinary, method.MethodKind);
                Assert.True(method.IsStatic);
                Assert.False(method.IsExtensionMethod);
                Assert.False(method.HasSpecialName);
                Assert.False(method.HasRuntimeSpecialName);
                Assert.False(method.HasUnsupportedMetadata);
            }
        }
 
        [Theory]
        [CombinatorialData]
        public void CompoundAssignment_003_Declaration([CombinatorialValues("+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>=", ">>>=")] string op, [CombinatorialValues("virtual", "abstract", "new", "override", "sealed", "readonly", "extern")] string modifier)
        {
            var src = $$$"""
static class Extensions1
{
    extension(ref S1 s1)
    {
        {{{modifier}}}
        public void operator {{{op}}}(int x) {}
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (6,30): error CS0106: The modifier 'abstract' is not valid for this item
                //         public void operator %=(int x) {}
                Diagnostic(ErrorCode.ERR_BadMemberFlag, op).WithArguments(modifier).WithLocation(6, 30)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void CompoundAssignment_004_Declaration([CombinatorialValues("+=", "-=", "*=", "/=")] string op)
        {
            var src = $$$"""
static class Extensions1
{
    extension(ref S1 s1)
    {
        public void operator checked {{{op}}}(int x) {}
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions2
{
    extension(ref S1 s1)
    {
#line 100
        public void operator checked {{{op}}}(int x) {}
    }
    extension(ref S1 s1)
    {
        public void operator {{{op}}}(int x) {}
    }
}
 
static class Extensions3
{
    extension(ref S1 s1)
    {
        public void operator checked {{{op}}}(int x) {}
    }
}
 
struct S1
{}
""";
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (112,38): error CS9025: The operator 'Extensions3.extension(ref S1).operator checked +=(int)' requires a matching non-checked version of the operator to also be defined
                //         public void operator checked +=(int x) {}
                Diagnostic(ErrorCode.ERR_CheckedOperatorNeedsMatch, op).WithArguments("Extensions3.extension(ref S1).operator checked " + op + "(int)").WithLocation(112, 38)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void CompoundAssignment_005_Consumption(bool fromMetadata)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x, S1 y)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            System.Console.Write(y.F);
            return new S1 { F = x.F + y.F };
        }
    }
}
 
public struct S1
{
    public int F;
}
""";
 
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        var s11 = new S1() { F = 101 };
        var s12 = new S1() { F = 202 };
 
        s11 += s12;
        System.Console.Write(":");
        System.Console.Write(s11.F);
        System.Console.Write(":");
        System.Console.Write(s12.F);
        System.Console.Write(":");
 
        var s2 = s11 += s12;
        System.Console.Write(":");
        System.Console.Write(s11.F);
        System.Console.Write(":");
        System.Console.Write(s12.F);
        System.Console.Write(":");
        System.Console.Write(s2.F);
    }
}
""";
 
            var comp1 = CreateCompilation(src1);
            var comp1Ref = fromMetadata ? comp1.EmitToImageReference() : comp1.ToMetadataReference();
 
            var comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:202:303:202:operator1:303:202:505:202:505").VerifyDiagnostics();
 
            var tree = comp2.SyntaxTrees.First();
            var model = comp2.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().Where(a => a.Kind() == SyntaxKind.AddAssignmentExpression).First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(S1).operator +(S1, S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:202:303:202:operator1:303:202:505:202:505").VerifyDiagnostics();
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            comp2.VerifyEmitDiagnostics(
                // (8,9): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                //         s11 += s12;
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "s11 += s12").WithArguments("extensions").WithLocation(8, 9),
                // (15,18): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                //         var s2 = s11 += s12;
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "s11 += s12").WithArguments("extensions").WithLocation(15, 18)
                );
 
            var src3 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1 = Extensions1.op_Addition(s1, s1);
    }
}
""";
            var comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp3, expectedOutput: "operator1:0:0").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp3, expectedOutput: "operator1:0:0").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            CompileAndVerify(comp3, expectedOutput: "operator1:0:0").VerifyDiagnostics();
 
            var src4 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1.op_Addition(s1);
        S1.op_Addition(s1, s1);
    }
}
""";
            var comp4 = CreateCompilation(src4, references: [comp1Ref]);
            comp4.VerifyEmitDiagnostics(
                // (6,12): error CS1061: 'S1' does not contain a definition for 'op_Addition' and no accessible extension method 'op_Addition' accepting a first argument of type 'S1' could be found (are you missing a using directive or an assembly reference?)
                //         s1.op_Addition(s1);
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "op_Addition").WithArguments("S1", "op_Addition").WithLocation(6, 12),
                // (7,12): error CS0117: 'S1' does not contain a definition for 'op_Addition'
                //         S1.op_Addition(s1, s1);
                Diagnostic(ErrorCode.ERR_NoSuchMember, "op_Addition").WithArguments("S1", "op_Addition").WithLocation(7, 12)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void CompoundAssignment_006_Consumption(bool fromMetadata)
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator +=(S1 y)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            System.Console.Write(y.F);
            x.F = x.F + y.F;
        }
    }
}
 
public struct S1
{
    public int F;
}

""" + CompilerFeatureRequiredAttribute;
 
            var src2 = $$$"""
class Program
{
    static void Main()
    {
        var s11 = new S1() { F = 101 };
        var s12 = new S1() { F = 202 };
 
        s11 += s12;
        System.Console.Write(":");
        System.Console.Write(s11.F);
        System.Console.Write(":");
        System.Console.Write(s12.F);
        System.Console.Write(":");
 
        var s2 = s11 += s12;
        System.Console.Write(":");
        System.Console.Write(s11.F);
        System.Console.Write(":");
        System.Console.Write(s12.F);
        System.Console.Write(":");
        System.Console.Write(s2.F);
    }
}
""";
 
            var comp1 = CreateCompilation(src1);
            var comp1Ref = fromMetadata ? comp1.EmitToImageReference() : comp1.ToMetadataReference();
 
            var comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:202:303:202:operator1:303:202:505:202:505").VerifyDiagnostics();
 
            var tree = comp2.SyntaxTrees.First();
            var model = comp2.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().Where(a => a.Kind() == SyntaxKind.AddAssignmentExpression).First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(ref S1).operator +=(S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("System.Void", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp2, expectedOutput: "operator1:101:202:303:202:operator1:303:202:505:202:505").VerifyDiagnostics();
 
            comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            comp2.VerifyEmitDiagnostics(
                // (8,9): error CS0019: Operator '+=' cannot be applied to operands of type 'S1' and 'S1'
                //         s11 += s12;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s11 += s12").WithArguments("+=", "S1", "S1").WithLocation(8, 9),
                // (15,18): error CS0019: Operator '+=' cannot be applied to operands of type 'S1' and 'S1'
                //         var s2 = s11 += s12;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s11 += s12").WithArguments("+=", "S1", "S1").WithLocation(15, 18)
                );
 
            var src3 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        Extensions1.op_AdditionAssignment(ref s1, s1);
    }
}
""";
            var comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp3, expectedOutput: "operator1:0:0").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext);
            CompileAndVerify(comp3, expectedOutput: "operator1:0:0").VerifyDiagnostics();
 
            comp3 = CreateCompilation(src3, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
            CompileAndVerify(comp3, expectedOutput: "operator1:0:0").VerifyDiagnostics();
 
            var src4 = $$$"""
class Program
{
    static void Main()
    {
        var s1 = new S1();
        s1.op_AdditionAssignment(s1);
        S1.op_AdditionAssignment(ref s1, s1);
    }
}
""";
            var comp4 = CreateCompilation(src4, references: [comp1Ref]);
            comp4.VerifyEmitDiagnostics(
                // (6,12): error CS1061: 'S1' does not contain a definition for 'op_AdditionAssignment' and no accessible extension method 'op_AdditionAssignment' accepting a first argument of type 'S1' could be found (are you missing a using directive or an assembly reference?)
                //         s1.op_AdditionAssignment(s1);
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "op_AdditionAssignment").WithArguments("S1", "op_AdditionAssignment").WithLocation(6, 12),
                // (7,12): error CS0117: 'S1' does not contain a definition for 'op_AdditionAssignment'
                //         S1.op_AdditionAssignment(ref s1, s1);
                Diagnostic(ErrorCode.ERR_NoSuchMember, "op_AdditionAssignment").WithArguments("S1", "op_AdditionAssignment").WithLocation(7, 12)
                );
 
            var src5 = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator +=(C1 y)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            System.Console.Write(y.F);
            x.F = x.F + y.F;
        }
    }
}
 
public class C1
{
    public int F;
}

""" + CompilerFeatureRequiredAttribute;
 
            var src6 = $$$"""
class Program
{
    static void Main()
    {
        var c11 = new C1() { F = 101 };
        var c1 = c11;
        var c12 = new C1() { F = 202 };
 
        c11 += c12;
        System.Console.Write(":");
        System.Console.Write(c11.F);
        System.Console.Write(":");
        System.Console.Write(c12.F);
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c11, c1) ? "True" : "False");
        System.Console.Write(":");
 
        var c2 = c11 += c12;
        System.Console.Write(":");
        System.Console.Write(c11.F);
        System.Console.Write(":");
        System.Console.Write(c12.F);
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c11, c1) ? "True" : "False");
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c11, c2) ? "True" : "False");
    }
}
""";
 
            var comp5 = CreateCompilation(src5);
            var comp5Ref = fromMetadata ? comp5.EmitToImageReference() : comp5.ToMetadataReference();
 
            var comp6 = CreateCompilation(src6, references: [comp5Ref], options: TestOptions.DebugExe);
            CompileAndVerify(comp6, expectedOutput: "operator1:101:202:303:202:True:operator1:303:202:505:202:True:True").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_007_Consumption_PredefinedComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S2 x, S2 y) => throw null;
    }
}
 
public struct S2
{
    public static implicit operator int(S2 x)
    {
        System.Console.Write("operator2");
        return 0;
    }
    public static implicit operator S2(int x)
    {
        System.Console.Write("operator3");
        return default;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        s2 += s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator2operator3").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("int.operator +(int, int)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_008_Consumption_PredefinedComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator +=(S2 y) => throw null;
    }
}
 
public struct S2
{
    public static implicit operator int(S2 x)
    {
        System.Console.Write("operator2");
        return 0;
    }
    public static implicit operator S2(int x)
    {
        System.Console.Write("operator3");
        return default;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        s2 += s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2operator2operator3").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("int.operator +(int, int)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_009_Consumption_NonExtensionComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S2 x, S2 y) => throw null;
    }
}
 
public struct S2
{
    public static S2 operator +(S2 x, S2 y)
    {
        System.Console.Write("operator2");
        return x;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        s2 += s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("S2.operator +(S2, S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_010_Consumption_NonExtensionComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S2 x, S2 y) => throw null;
    }
}
 
public struct S2
{
    public void operator +=(S2 y)
    {
        System.Console.Write("operator2");
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = s2 += s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().ElementAt(1);
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("S2.operator +=(S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_011_Consumption_NonExtensionComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator +=(S2 y) => throw null;
    }
}
 
public struct S2
{
    public static S2 operator +(S2 x, S2 y)
    {
        System.Console.Write("operator2");
        return x;
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        s2 += s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("S2.operator +(S2, S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_012_Consumption_NonExtensionComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator +=(S2 y) => throw null;
    }
}
 
public struct S2
{
    public void operator +=(S2 y)
    {
        System.Console.Write("operator2");
    }
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = s2 += s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().ElementAt(1);
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("S2.operator +=(S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_013_Consumption_InstanceInTheSameScopeComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator +=(S2 y)
        {
            System.Console.Write("operator2");
        }
 
        public static S2 operator +(S2 y, S2 z) => throw null;
    }
}
 
public struct S2
{
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = s2 += s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().ElementAt(1);
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(ref S2).operator +=(S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_014_Consumption_InstanceInTheSameScopeComesFirst()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator +=(S2 y)
        {
            System.Console.Write("operator2");
        }
    }
    extension(S2)
    {
        public static S2 operator +(S2 x, S2 y) => throw null;
    }
}
 
public struct S2
{
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = s2 += s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().ElementAt(1);
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(ref S2).operator +=(S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_015_Consumption_InstanceInTheSameScopeComesFirst()
        {
            var src = $$$"""
public static class Extensions2
{
    extension(S2)
    {
        public static S2 operator +(S2 x, S2 y) => throw null;
    }
}
 
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator +=(S2 y)
        {
            System.Console.Write("operator2");
        }
    }
}
 
public struct S2
{
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = s2 += s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().ElementAt(1);
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("Extensions1.extension(ref S2).operator +=(S2)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S2", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_016_Consumption_StaticTriedAfterInapplicableInstanceInTheSameScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator +=(S2 y) => throw null;
    }
    extension(S2)
    {
        public static S2 operator +(S2 x, S2 y)
        {
            System.Console.Write("operator2");
            return y;
        }
    }
}
 
public struct S1
{
}
 
public struct S2
{
}
 
class Program
{
    static void Main()
    {
        var s2 = new S2();
        _ = s2 += s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator2").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_017_Consumption_ScopeByScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x, S1 y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(S1)
        {
            public static S1 operator +(S1 x, S1 y)
            {
                System.Console.Write("operator1");
                return x;
            }
        }
    }
 
    namespace NS2
    {
        public static class Extensions3
        {
            extension(S2)
            {
                public static S2 operator +(S2 x, S2 y) => throw null;
            }
        }
 
        class Program
        {
            static void Main()
            {
                var s1 = new S1();
                _ = s1 += s1;
            }
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().ElementAt(1);
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("NS1.Extensions2.extension(S1).operator +(S1, S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_018_Consumption_ScopeByScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator +=(S1 y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(S1)
        {
            public static S1 operator +(S1 x, S1 y)
            {
                System.Console.Write("operator1");
                return x;
            }
        }
    }
 
    namespace NS2
    {
        public static class Extensions3
        {
            extension(ref S2 x)
            {
                public void operator +=(S2 y) => throw null;
            }
        }
 
        class Program
        {
            static void Main()
            {
                var s1 = new S1();
                _ = s1 += s1;
            }
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().ElementAt(1);
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("NS1.Extensions2.extension(S1).operator +(S1, S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_019_Consumption_ScopeByScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator +=(S1 y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(ref S1 x)
        {
            public void operator +=(S1 y)
            {
                System.Console.Write("operator1");
            }
        }
    }
 
    namespace NS2
    {
        public static class Extensions3
        {
            extension(ref S2 x)
            {
                public void operator +=(S2 y) => throw null;
            }
        }
 
        class Program
        {
            static void Main()
            {
                var s1 = new S1();
                _ = s1 += s1;
            }
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().ElementAt(1);
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("NS1.Extensions2.extension(ref S1).operator +=(S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_020_Consumption_ScopeByScope()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x, S1 y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(ref S1 x)
        {
            public void operator +=(S1 y)
            {
                System.Console.Write("operator1");
            }
        }
    }
 
    namespace NS2
    {
        public static class Extensions3
        {
            extension(S2)
            {
                public static S2 operator +(S2 x, S2 y) => throw null;
            }
        }
 
        class Program
        {
            static void Main()
            {
                var s1 = new S1();
                _ = s1 += s1;
            }
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().ElementAt(1);
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Equal("NS1.Extensions2.extension(ref S1).operator +=(S1)", symbolInfo.Symbol.ToDisplayString());
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Empty(symbolInfo.CandidateSymbols);
            Assert.Equal("S1", model.GetTypeInfo(opNode).Type.ToTestDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_021_Consumption_NonExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1
{
    public static I1 operator -(I1 x, I1 y) => x;
}
 
public interface I3
{
    public static I3 operator -(I3 x, I3 y) => x;
}
 
public interface I4 : I1, I3
{
}
 
public interface I2 : I4
{
}
 
public static class Extensions1
{
    extension(I2 z)
    {
        public void operator -=(I2 y) {}
        public static I2 operator -(I2 x, I2 y) => x;
    }
}
 
class Test2 : I2
{
    static void Main()
    {
        I2 x = new Test2();
        var y = x -= x;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (33,17): error CS0034: Operator '-=' is ambiguous on operands of type 'I2' and 'I2'
                //         var y = x -= x;
                Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "x -= x").WithArguments("-=", "I2", "I2").WithLocation(33, 17)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("I1.operator -(I1, I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("I3.operator -(I3, I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_022_Consumption_NonExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1
{
    public void operator -=(I1 y) {}
}
 
public interface I3
{
    public void operator -=(I3 y) {}
}
 
public interface I4 : I1, I3
{
}
 
public interface I2 : I4
{
}
 
public static class Extensions1
{
    extension(I2 z)
    {
        public void operator -=(I2 y) {}
        public static I2 operator -(I2 x, I2 y) => x;
    }
}
 
class Test2 : I2
{
    static void Main()
    {
        I2 x = new Test2();
        var y = x -= x;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (33,19): error CS0121: The call is ambiguous between the following methods or properties: 'I1.operator -=(I1)' and 'I3.operator -=(I3)'
                //         var y = x -= x;
                Diagnostic(ErrorCode.ERR_AmbigCall, "-=").WithArguments("I1.operator -=(I1)", "I3.operator -=(I3)").WithLocation(33, 19)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("I1.operator -=(I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("I3.operator -=(I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_023_Consumption_NonExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1
{
    public void operator -=(I1 y) {}
}
 
public interface I3
{
    public void operator -=(I3 y) {}
}
 
public interface I4 : I1, I3
{
}
 
public interface I2 : I4
{
    public static I2 operator -(I2 x, I2 y) => y;
}
 
public static class Extensions1
{
    extension(I2 z)
    {
        public void operator -=(I2 y) {}
        public static I2 operator -(I2 x, I2 y) => x;
    }
}
 
class Test2 : I2
{
    static void Main()
    {
        I2 x = new Test2();
#line 33
        var y = x -= x;
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
            comp.VerifyEmitDiagnostics(
                // (33,19): error CS0121: The call is ambiguous between the following methods or properties: 'I1.operator -=(I1)' and 'I3.operator -=(I3)'
                //         var y = x -= x;
                Diagnostic(ErrorCode.ERR_AmbigCall, "-=").WithArguments("I1.operator -=(I1)", "I3.operator -=(I3)").WithLocation(33, 19)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("I1.operator -=(I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("I3.operator -=(I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/78830")]
        public void CompoundAssignment_024_Consumption_ExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1;
public interface I3;
public interface I4 : I1, I3;
public interface I2 : I4;
 
public static class Extensions1
{
    extension(I2 z)
    {
        public void operator -=(I2 y) {}
        public static I2 operator -(I2 x, I2 y) => x;
    }
}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(I1)
        {
            public static I1 operator -(I1 x, I1 y) => x;
        }
 
        extension(I3)
        {
            public static I3 operator -(I3 x, I3 y) => x;
        }
    }
 
    class Test2 : I2
    {
        static void Main()
        {
            I2 x = new Test2();
            var y = x -= x;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src);
 
            // https://github.com/dotnet/roslyn/issues/78830: We might want to include more information into the error. Like what methods conflict.
            comp.VerifyEmitDiagnostics(
                // (35,21): error CS0034: Operator '-=' is ambiguous on operands of type 'I2' and 'I2'
                //             var y = x -= x;
                Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "x -= x").WithArguments("-=", "I2", "I2").WithLocation(35, 21)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("NS1.Extensions2.extension(I1).operator -(I1, I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("NS1.Extensions2.extension(I3).operator -(I3, I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_025_Consumption_ExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1;
public interface I3;
public interface I4 : I1, I3;
public interface I2 : I4;
 
public static class Extensions1
{
    extension(I2 z)
    {
        public void operator -=(I2 y) {}
        public static I2 operator -(I2 x, I2 y) => x;
    }
}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(I1 x)
        {
            public void operator -=(I1 y) {}
        }
 
        extension(I3 x)
        {
            public void operator -=(I3 y) {}
        }
    }
 
    class Test2 : I2
    {
        static void Main()
        {
            I2 x = new Test2();
            var y = x -= x;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src);
 
            comp.VerifyEmitDiagnostics(
                // (35,23): error CS0121: The call is ambiguous between the following methods or properties: 'Extensions2.extension(I1).operator -=(I1)' and 'Extensions2.extension(I3).operator -=(I3)'
                //             var y = x -= x;
                Diagnostic(ErrorCode.ERR_AmbigCall, "-=").WithArguments("NS1.Extensions2.extension(I1).operator -=(I1)", "NS1.Extensions2.extension(I3).operator -=(I3)").WithLocation(35, 23)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("NS1.Extensions2.extension(I1).operator -=(I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("NS1.Extensions2.extension(I3).operator -=(I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Fact]
        public void CompoundAssignment_026_Consumption_ExtensionAmbiguity()
        {
            var src = $$$"""
public interface I1;
public interface I3;
public interface I4 : I1, I3;
public interface I2 : I4;
 
public static class Extensions1
{
    extension(I2 z)
    {
        public void operator -=(I2 y) {}
        public static I2 operator -(I2 x, I2 y) => x;
    }
}
 
namespace NS1
{
    public static class Extensions2
    {
        extension(I1 x)
        {
            public void operator -=(I1 y) {}
        }
 
        extension(I3 x)
        {
            public void operator -=(I3 y) {}
        }
 
        extension(I2)
        {
            public static I2 operator -(I2 x, I2 y) => x;
        }
    }
 
    class Test2 : I2
    {
        static void Main()
        {
            I2 x = new Test2();
#line 35
            var y = x -= x;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src);
 
            comp.VerifyEmitDiagnostics(
                // (35,23): error CS0121: The call is ambiguous between the following methods or properties: 'Extensions2.extension(I1).operator -=(I1)' and 'Extensions2.extension(I3).operator -=(I3)'
                //             var y = x -= x;
                Diagnostic(ErrorCode.ERR_AmbigCall, "-=").WithArguments("NS1.Extensions2.extension(I1).operator -=(I1)", "NS1.Extensions2.extension(I3).operator -=(I3)").WithLocation(35, 23)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("NS1.Extensions2.extension(I1).operator -=(I1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("NS1.Extensions2.extension(I3).operator -=(I3)", symbolInfo.CandidateSymbols[1].ToDisplayString());
 
            var group = model.GetMemberGroup(opNode);
            Assert.Empty(group);
        }
 
        [Theory]
        [CombinatorialData]
        public void CompoundAssignment_027_Consumption_Lifted([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>", ">>>")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 z)
    {
        public void operator {{{op}}}=(S1 y) => throw null;
 
        public static S1 operator {{{op}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s11 = new S1();
        S1? s12 = new S1();
        _ = s11 {{{op}}}= s12;
        System.Console.Write(":");
        s11 = null;
        _ = s11 {{{op}}}= s12;
        _ = s12 {{{op}}}= s11;
        _ = s11 {{{op}}}= s11;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void CompoundAssignment_028_Consumption_Lifted([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>", ">>>")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 z)
    {
        public void operator {{{op}}}=(S1 y) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s11 = new S1();
        S1? s12 = new S1();
        _ = s11 {{{op}}}= s12;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (18,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1?' and 'S1?'
                //         _ = s11 += s12;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s11 " + op + "= s12").WithArguments(op + "=", "S1?", "S1?").WithLocation(18, 13)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void CompoundAssignment_029_Consumption_Lifted([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>", ">>>")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 z)
    {
        public void operator {{{op}}}=(S1 y) => throw null;
 
        public static S1 operator {{{op}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s11 = new S1();
        S1 s12 = new S1();
        _ = s11 {{{op}}}= s12;
        System.Console.Write(":");
        s11 = null;
        _ = s11 {{{op}}}= s12;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void CompoundAssignment_030_Consumption_Lifted([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>", ">>>")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 z)
    {
        public void operator {{{op}}}=(S1 y) => throw null;
 
        public static S1 operator {{{op}}}(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s11 = new S1();
        S1 s12 = new S1();
        _ = s12 {{{op}}}= s11;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (24,13): error CS0266: Cannot implicitly convert type 'S1?' to 'S1'. An explicit conversion exists (are you missing a cast?)
                //         _ = s12 += s11;
                Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "s12 " + op + "= s11").WithArguments("S1?", "S1").WithLocation(24, 13)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void CompoundAssignment_031_Consumption_Lifted([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>", ">>>")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 z)
    {
        public void operator {{{op}}}=(S1 y) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s11 = new S1();
        S1 s12 = new S1();
        _ = s11 {{{op}}}= s12;
        _ = s12 {{{op}}}= s11;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (18,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1?' and 'S1'
                //         _ = s11 += s12;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s11 " + op + "= s12").WithArguments(op + "=", "S1?", "S1").WithLocation(18, 13),
                // (19,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1' and 'S1?'
                //         _ = s12 += s11;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s12 " + op + "= s11").WithArguments(op + "=", "S1", "S1?").WithLocation(19, 13)
                );
        }
 
        [Theory]
        [CombinatorialData]
        public void CompoundAssignment_032_Consumption_Lifted([CombinatorialValues("+", "-", "*", "/", "%", "&", "|", "^")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x, S2 y)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            System.Console.Write(y.F);
            return new S1 { F = x.F * 1000 + y.F };
        }
        public static S2 operator {{{op}}}(S2 x, S1 y)
        {
            System.Console.Write("operator2:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            System.Console.Write(y.F);
            return new S2 { F = x.F * 1000 + y.F };
        }
    }
}
 
public struct S1
{
    public int F;
}
 
public struct S2
{
    public int F;
}
 
class Program
{
    static void Main()
    {
        S1?[] s1 = [new S1() { F = 101 }, null];
        S2?[] s2 = [new S2() { F = 202 }, null];
 
        foreach (var s11 in s1)
        {
            foreach (var s12 in s2)
            {
                var s21 = s11;
                var s22 = s12;
 
                Print(s21 {{{op}}}= s22, s21, s22);
                System.Console.WriteLine();
 
                s21 = s11;
                s22 = s12;
 
                Print(s22 {{{op}}}= s21, s22, s21);
                System.Console.WriteLine();
            }
        }
    }
 
    static void Print(S1? x, S1? y, S2? z)
    {
        System.Console.Write(":");
        System.Console.Write(x?.F.ToString() ?? "null");
        System.Console.Write(":");
        System.Console.Write(y?.F.ToString() ?? "null");
        System.Console.Write(":");
        System.Console.Write(z?.F.ToString() ?? "null");
    }
 
    static void Print(S2? x, S2? y, S1? z)
    {
        System.Console.Write(":");
        System.Console.Write(x?.F.ToString() ?? "null");
        System.Console.Write(":");
        System.Console.Write(y?.F.ToString() ?? "null");
        System.Console.Write(":");
        System.Console.Write(z?.F.ToString() ?? "null");
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput:
@"
operator1:101:202:101202:101202:202
operator2:202:101:202101:202101:101
:null:null:null
:null:null:101
:null:null:202
:null:null:null
:null:null:null
:null:null:null
").VerifyDiagnostics();
        }
 
        [Theory]
        [CombinatorialData]
        public void CompoundAssignment_033_Consumption_Lifted_Shift([CombinatorialValues("<<", ">>", ">>>")] string op)
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator {{{op}}}(S1 x, S2 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
public struct S2
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        S2? s2 = new S2();
        _ = s1 {{{op}}}= s2;
        System.Console.Write(":");
        s1 = null;
        _ = s1 {{{op}}}= s2;
        s1 = new S1();
        s2 = null;
        _ = s1 {{{op}}}= s2;
        s1 = null;
        _ = s1 {{{op}}}= s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_034_Consumption_LiftedIsWorse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x, S1 y) => throw null;
    }
    extension(S1?)
    {
        public static S1? operator +(S1? x, S1? y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        _ = s1 += s1;
        System.Console.Write(":");
        s1 = null;
        _ = s1 += s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_035_Consumption_ExtendedTypeIsNullable()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1?)
    {
        public static S1? operator +(S1? x, S1? y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = s1 += s1;
        Extensions1.op_Addition(s1, s1);
 
        S1? s2 = new S1();
        _ = s2 += s2;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (21,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s1 += s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 += s1").WithArguments("+=", "S1", "S1").WithLocation(21, 13)
                );
        }
 
        [Fact]
        public void CompoundAssignment_036_Consumption_ExtendedTypeIsNullable()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1? x)
    {
        public void operator +=(S1? y) {}
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = s1 += s1;
        Extensions1.op_AdditionAssignment(s1, s1);
        Extensions1.op_AdditionAssignment(ref s1, s1);
 
        S1? s2 = new S1();
        _ = s2 += s2;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (17,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s1 += s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 += s1").WithArguments("+=", "S1", "S1").WithLocation(17, 13),
                // (18,43): error CS1620: Argument 1 must be passed with the 'ref' keyword
                //         Extensions1.op_AdditionAssignment(s1, s1);
                Diagnostic(ErrorCode.ERR_BadArgRef, "s1").WithArguments("1", "ref").WithLocation(18, 43),
                // (19,47): error CS1503: Argument 1: cannot convert from 'ref S1' to 'ref S1?'
                //         Extensions1.op_AdditionAssignment(ref s1, s1);
                Diagnostic(ErrorCode.ERR_BadArgType, "s1").WithArguments("1", "ref S1", "ref S1?").WithLocation(19, 47)
                );
        }
 
        [Fact]
        public void CompoundAssignment_037_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S2 x, S2 y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S2(S1 x) => default;
}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        S2 s2 = new S2();
        _ = s1 += s2;
        _ = s2 += s1;
        _ = s1 += s1;
        Extensions1.op_Addition(s1, s1);
 
        S1? s3 = new S1();
        _ = s3 += s3;
        Extensions1.op_Addition(s3, s3);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (23,13): error CS0029: Cannot implicitly convert type 'S2' to 'S1'
                //         _ = s1 += s2;
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "s1 += s2").WithArguments("S2", "S1").WithLocation(23, 13),
                // (25,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s1 += s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 += s1").WithArguments("+=", "S1", "S1").WithLocation(25, 13),
                // (29,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1?' and 'S1?'
                //         _ = s3 += s3;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s3 += s3").WithArguments("+=", "S1?", "S1?").WithLocation(29, 13),
                // (30,33): error CS1503: Argument 1: cannot convert from 'S1?' to 'S2'
                //         Extensions1.op_Addition(s3, s3);
                Diagnostic(ErrorCode.ERR_BadArgType, "s3").WithArguments("1", "S1?", "S2").WithLocation(30, 33),
                // (30,37): error CS1503: Argument 2: cannot convert from 'S1?' to 'S2'
                //         Extensions1.op_Addition(s3, s3);
                Diagnostic(ErrorCode.ERR_BadArgType, "s3").WithArguments("2", "S1?", "S2").WithLocation(30, 37)
                );
 
            var src1 = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S2 x, S1 y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S2(S1 x) => default;
    public static implicit operator S1(S2 x) => default;
}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        S2 s2 = new S2();
        _ = s1 += s1;
        _ = s1 += s2;
        _ = s2 += s1;
        _ = s2 += s2;
        Extensions1.op_Addition(s1, s1);
        Extensions1.op_Addition(s1, s2);
    }
}
""";
 
            var comp1 = CreateCompilation(src1, options: TestOptions.DebugExe);
            comp1.VerifyEmitDiagnostics(
                // (24,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s1 += s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 += s1").WithArguments("+=", "S1", "S1").WithLocation(24, 13),
                // (25,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1' and 'S2'
                //         _ = s1 += s2;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 += s2").WithArguments("+=", "S1", "S2").WithLocation(25, 13)
                );
 
            var src2 = $$$"""
public static class Extensions1
{
    extension(S2)
    {
        public static S2 operator +(S1 x, S2 y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S2(S1 x) => default;
    public static implicit operator S1(S2 x) => default;
}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        S2 s2 = new S2();
        _ = s1 += s1;
        _ = s1 += s2;
        _ = s2 += s1;
        _ = s2 += s2;
        Extensions1.op_Addition(s1, s1);
        Extensions1.op_Addition(s2, s1);
    }
}
""";
 
            var comp2 = CreateCompilation(src2, options: TestOptions.DebugExe);
            comp2.VerifyEmitDiagnostics(
                // (24,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s1 += s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 += s1").WithArguments("+=", "S1", "S1").WithLocation(24, 13),
                // (26,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S2' and 'S1'
                //         _ = s2 += s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s2 += s1").WithArguments("+=", "S2", "S1").WithLocation(26, 13)
                );
        }
 
        [Fact]
        public void CompoundAssignment_038_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S2 x)
    {
        public void operator +=(S2 y) => throw null;
    }
}
 
public struct S1
{}
 
public struct S2
{
    public static implicit operator S2(S1 x) => default;
}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        S2 s2 = new S2();
        _ = s1 += s2;
        _ = s2 += s1;
        _ = s1 += s1;
        Extensions1.op_AdditionAssignment(ref s1, s1);
 
        S1? s3 = new S1();
        _ = s3 += s3;
        Extensions1.op_AdditionAssignment(ref s3, s3);
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (23,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1' and 'S2'
                //         _ = s1 += s2;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 += s2").WithArguments("+=", "S1", "S2").WithLocation(23, 13),
                // (25,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1' and 'S1'
                //         _ = s1 += s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 += s1").WithArguments("+=", "S1", "S1").WithLocation(25, 13),
                // (26,47): error CS1503: Argument 1: cannot convert from 'ref S1' to 'ref S2'
                //         Extensions1.op_AdditionAssignment(ref s1, s1);
                Diagnostic(ErrorCode.ERR_BadArgType, "s1").WithArguments("1", "ref S1", "ref S2").WithLocation(26, 47),
                // (29,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1?' and 'S1?'
                //         _ = s3 += s3;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s3 += s3").WithArguments("+=", "S1?", "S1?").WithLocation(29, 13),
                // (30,47): error CS1503: Argument 1: cannot convert from 'ref S1?' to 'ref S2'
                //         Extensions1.op_AdditionAssignment(ref s3, s3);
                Diagnostic(ErrorCode.ERR_BadArgType, "s3").WithArguments("1", "ref S1?", "ref S2").WithLocation(30, 47),
                // (30,51): error CS1503: Argument 2: cannot convert from 'S1?' to 'S2'
                //         Extensions1.op_AdditionAssignment(ref s3, s3);
                Diagnostic(ErrorCode.ERR_BadArgType, "s3").WithArguments("2", "S1?", "S2").WithLocation(30, 51)
                );
        }
 
        [Fact]
        public void CompoundAssignment_039_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static S1 operator +(object x, int y)
        {
            System.Console.Write("operator1");
            return default;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        s1 += 1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_040_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object x)
    {
        public void operator +=(int y) => throw null;
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        s1 += 1;
        Extensions1.op_AdditionAssignment(s1, 1);
 
        S1? s2 = new S1();
        s2 += 1;
        Extensions1.op_AdditionAssignment(s2, 1);
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (17,9): error CS0019: Operator '+=' cannot be applied to operands of type 'S1' and 'int'
                //         s1 += 1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 += 1").WithArguments("+=", "S1", "int").WithLocation(17, 9),
                // (21,9): error CS0019: Operator '+=' cannot be applied to operands of type 'S1?' and 'int'
                //         s2 += 1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s2 += 1").WithArguments("+=", "S1?", "int").WithLocation(21, 9)
                );
        }
 
        [Fact]
        public void CompoundAssignment_041_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static C1 operator +(object x, int y)
        {
            System.Console.Write("operator1");
            return null;
        }
    }
}
 
public class C1
{}
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        c1 = c1 += 1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_042_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1Base x)
    {
        public void operator +=(int y)
        {
            System.Console.Write("operator1:");
            System.Console.Write(x.F);
            System.Console.Write(":");
            System.Console.Write(y);
            x.F += y;
        }
    }
}
 
public class C1Base
{
    public int F;
}
 
public class C1 : C1Base
{}
 
class Program
{
    static void Main()
    {
        var c11 = new C1() { F = 101 };
        var c1 = c11;
        var c12 = 202;
 
        c11 += c12;
        System.Console.Write(":");
        System.Console.Write(c11.F);
        System.Console.Write(":");
        System.Console.Write(c12);
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c11, c1) ? "True" : "False");
        System.Console.Write(":");
 
        var c2 = c11 += c12;
        System.Console.Write(":");
        System.Console.Write(c11.F);
        System.Console.Write(":");
        System.Console.Write(c12);
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c11, c1) ? "True" : "False");
        System.Console.Write(":");
        System.Console.Write(ReferenceEquals(c11, c2) ? "True" : "False");
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:101:202:303:202:True:operator1:303:202:505:202:True:True").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_043_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(dynamic x)
    {
        public void operator +=(int y)
        {
            System.Console.Write("operator1");
        }
    }
}
 
public class C1
{}
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        c1 += 1;
        c1 = c1 += 1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (3,15): error CS1103: The receiver parameter of an extension cannot be of type 'dynamic'
                //     extension(dynamic x)
                Diagnostic(ErrorCode.ERR_BadTypeforThis, "dynamic").WithArguments("dynamic").WithLocation(3, 15)
                );
        }
 
        [Fact]
        public void CompoundAssignment_044_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object x)
    {
        public void operator +=(int y)
        {
            System.Console.Write("operator1");
        }
    }
}
 
public class C1
{}
 
class Program
{
    static void Main()
    {
        Test(new C1());
    }
 
    static void Test<T>(T c1) where T : class
    {
        c1 += 1;
        c1 = c1 += 1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_045_Consumption_ReceiverTypeMismatch()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref System.Span<int> x)
    {
        public void operator +=(int y) => throw null;
    }
}
 
class Program
{
    static void Main()
    {
        int[] a1 = null;
#line 17
        _ = a1 += 1;
        Extensions1.op_AdditionAssignment(ref a1, 1);
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (17,13): error CS0019: Operator '+=' cannot be applied to operands of type 'int[]' and 'int'
                //         _ = a1 += 1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "a1 += 1").WithArguments("+=", "int[]", "int").WithLocation(17, 13),
                // (18,47): error CS1503: Argument 1: cannot convert from 'ref int[]' to 'ref System.Span<int>'
                //         Extensions1.op_AdditionAssignment(ref a1, 1);
                Diagnostic(ErrorCode.ERR_BadArgType, "a1").WithArguments("1", "ref int[]", "ref System.Span<int>").WithLocation(18, 47)
                );
        }
 
        [Fact]
        public void CompoundAssignment_046_Consumption_Generic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(S1<T>) where T : struct
    {
        public static S1<T> operator +(S1<T> x, S1<T> y)
        {
            System.Console.Write(typeof(T).ToString());
            return x;
        }
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1<int>();
        s1 = s1 += s1;
        Extensions1.op_Addition(s1, s1);
 
        S1<int>? s2 = new S1<int>();
        _ = (s2 += s2).GetValueOrDefault();
        s2 = null;
        System.Console.Write(":");
        _ = (s2 += s2).GetValueOrDefault();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "System.Int32System.Int32System.Int32:").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_047_Consumption_Generic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(ref S1<T> x) where T : struct
    {
        public void operator +=(S1<T> y)
        {
            System.Console.Write(typeof(T).ToString());
        }
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1<int>();
        s1 = s1 += s1;
        Extensions1.op_AdditionAssignment(ref s1, s1);
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "System.Int32System.Int32").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_048_Consumption_Generic_Worse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(S1<T>)
    {
        public static S1<T> operator +(S1<T> x, S1<T> y)
        {
            System.Console.Write("[S1<T>]");
            return x;
        }
    }
 
    extension<T>(S1<T>?)
    {
        public static S1<T>? operator +(S1<T>? x, S1<T>? y)
        {
            System.Console.Write("[S1<T>?]");
            return x;
        }
    }
 
    extension(S1<int>)
    {
        public static S1<int> operator +(S1<int> x, S1<int> y)
        {
            System.Console.Write("[S1<int>]");
            return x;
        }
    }
 
    extension<T>(S2<T>)
    {
        public static S2<T> operator +(in S2<T> x, S2<T> y) => throw null;
 
        public static S2<T> operator +(S2<T> x, S2<T> y)
        {
            System.Console.Write("[S2<T>]");
            return x;
        }
    }
 
    extension(S2<int>)
    {
        public static S2<int> operator +(in S2<int> x, S2<int> y)
        {
            System.Console.Write("[in S2<int>]");
            return x;
        }
    }
}
 
public struct S1<T>
{}
 
public struct S2<T>
{}
 
class Program
{
    static void Main()
    {
        var s11 = new S1<int>();
        s11 = s11 += s11;
        Extensions1.op_Addition(s11, s11);
 
        System.Console.WriteLine();
 
        var s12 = new S1<byte>();
        s12 = s12 += s12;
        Extensions1.op_Addition(s12, s12);
 
        System.Console.WriteLine();
 
        var s21 = new S2<int>();
        s21 = s21 += s21;
        Extensions1.op_Addition(s21, s21);
 
        System.Console.WriteLine();
 
        var s22 = new S2<byte>();
        s22 = s22 += s22;
        Extensions1.op_Addition(s22, s22);
 
        System.Console.WriteLine();
 
        S1<int>? s13 = new S1<int>();
        s13 = s13 += s13;
        s13 = null;
        s13 = s13 += s13;
 
        System.Console.WriteLine();
 
        S1<byte>? s14 = new S1<byte>();
        s14 = s14 += s14;
        s14 = null;
        s14 = s14 += s14;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: @"
[S1<int>][S1<int>]
[S1<T>][S1<T>]
[in S2<int>][in S2<int>]
[S2<T>][S2<T>]
[S1<int>]
[S1<T>?][S1<T>?]
").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_049_Consumption_Generic_Worse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(ref S1<T> x)
    {
        public void operator +=(int y)
        {
            System.Console.Write("[S1<T>]");
        }
    }
 
    extension<T>(ref S1<T>? x)
    {
        public void operator +=(int y)
        {
            System.Console.Write("[S1<T>?]");
        }
    }
 
    extension(ref S1<int> x)
    {
        public void operator +=(int y)
        {
            System.Console.Write("[S1<int>]");
        }
    }
 
    extension(ref S1<int>? x)
    {
        public void operator +=(int y)
        {
            System.Console.Write("[S1<int>?]");
        }
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s11 = new S1<int>();
        s11 = s11 += 1;
        Extensions1.op_AdditionAssignment(ref s11, 1);
 
        System.Console.WriteLine();
 
        var s12 = new S1<byte>();
        s12 = s12 += 1;
        Extensions1.op_AdditionAssignment(ref s12, 1);
 
        System.Console.WriteLine();
 
        S1<int>? s13 = new S1<int>();
        s13 = s13 += 1;
        s13 = null;
        s13 = s13 += 1;
 
        System.Console.WriteLine();
 
        S1<byte>? s14 = new S1<byte>();
        s14 = s14 += 1;
        s14 = null;
        s14 = s14 += 1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: @"
[S1<int>][S1<int>]
[S1<T>][S1<T>]
[S1<int>?][S1<int>?]
[S1<T>?][S1<T>?]
").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_050_Consumption_Generic_ConstraintsViolation()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(S1<T>) where T : class
    {
        public static S1<T> operator +(S1<T> x, S1<T> y) => throw null;
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1<int>();
        _ = s1 += s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (17,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1<int>' and 'S1<int>'
                //         _ = s1 += s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 += s1").WithArguments("+=", "S1<int>", "S1<int>").WithLocation(17, 13)
                );
        }
 
        [Fact]
        public void CompoundAssignment_051_Consumption_Generic_ConstraintsViolation()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T>(ref S1<T> x) where T : class
    {
        public void operator +=(int i) => throw null;
    }
}
 
public struct S1<T>
{}
 
class Program
{
    static void Main()
    {
        var s1 = new S1<int>();
        _ = s1 += 1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (17,13): error CS0019: Operator '+=' cannot be applied to operands of type 'S1<int>' and 'int'
                //         _ = s1 += 1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 += 1").WithArguments("+=", "S1<int>", "int").WithLocation(17, 13)
                );
        }
 
        [Fact]
        public void CompoundAssignment_052_Consumption_OverloadResolutionPriority()
        {
            var src = $$$"""
using System.Runtime.CompilerServices;
 
public static class Extensions1
{
    extension(C1)
    {
        [OverloadResolutionPriority(1)]
        public static C2 operator +(C1 x, C1 y)
        {
            System.Console.Write("C1");
            return null;
        }
    }
    extension(C2)
    {
        public static C2 operator +(C2 x, C2 y)
        {
            System.Console.Write("C2");
            return x;
        }
    }
    extension(C3)
    {
        public static C4 operator +(C3 x, C3 y)
        {
            System.Console.Write("C3");
            return null;
        }
    }
    extension(C4)
    {
        public static C4 operator +(C4 x, C4 y)
        {
            System.Console.Write("C4");
            return x;
        }
    }
}
 
public class C1;
public class C2 : C1;
 
public class C3;
public class C4 : C3;
 
class Program
{
    static void Main()
    {
        var c2 = new C2();
        _ = c2 += c2;
        var c4 = new C4();
        _ = c4 += c4;
    }
}
""";
 
            var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition], options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "C1C4").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_053_Consumption_OverloadResolutionPriority()
        {
            var src = $$$"""
using System.Runtime.CompilerServices;
 
public static class Extensions1
{
    extension(C1 x)
    {
        [OverloadResolutionPriority(1)]
        public void operator +=(int y)
        {
            System.Console.Write("C1");
        }
    }
    extension(C2 x)
    {
        public void operator +=(int y)
        {
            System.Console.Write("C2");
        }
    }
    extension(C3 x)
    {
        public void operator +=(int y)
        {
            System.Console.Write("C3");
        }
    }
    extension(C4 x)
    {
        public void operator +=(int y)
        {
            System.Console.Write("C4");
        }
    }
}
 
public class C1;
public class C2 : C1;
 
public class C3;
public class C4 : C3;
 
class Program
{
    static void Main()
    {
        var c2 = new C2();
        _ = c2 += 1;
        var c4 = new C4();
        _ = c4 += 1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition], options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "C1C4").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_054_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x, C1 y)
        {
            System.Console.Write("regular");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 -= c1;
 
        checked
        {
            _ = c1 -= c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularregular").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_055_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator -=(C1 y)
        {
            System.Console.Write("regular");
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 -= c1;
 
        checked
        {
            _ = c1 -= c1;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularregular").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_056_Consumption_Checked_CheckedFormNotSupported()
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator |(C1 x, C1 y) => throw null;
        public static C1 operator checked |(C1 x, C1 y) => throw null;
    }
}
 
public class C1;
""";
 
            var comp1 = CreateCompilation(src1);
            comp1.VerifyEmitDiagnostics(
                // (6,35): error CS9023: User-defined operator '|' cannot be declared checked
                //         public static C1 operator checked |(C1 x, C1 y) => throw null;
                Diagnostic(ErrorCode.ERR_OperatorCantBeChecked, "checked").WithArguments("|").WithLocation(6, 35),
                // (6,43): error CS0111: Type 'Extensions1' already defines a member called 'op_BitwiseOr' with the same parameter types
                //         public static C1 operator checked |(C1 x, C1 y) => throw null;
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "|").WithArguments("op_BitwiseOr", "Extensions1").WithLocation(6, 43)
                );
 
            var src2 = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator |(C1 x, C1 y)
        {
            System.Console.Write("regular");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 |= c1;
 
        checked
        {
            _ = c1 |= c1;
        }
    }
}
""";
 
            var comp2 = CreateCompilation(src2, options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "regularregular").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_057_Consumption_Checked_CheckedFormNotSupported()
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator |(C1 x, C1 y) => throw null;
        public static C1 operator checked |(C1 x, C1 y) => throw null;
    }
}
 
public class C1;
""";
 
            var comp1 = CreateCompilation(src1);
            comp1.VerifyEmitDiagnostics(
                // (6,35): error CS9023: User-defined operator '|' cannot be declared checked
                //         public static C1 operator checked |(C1 x, C1 y) => throw null;
                Diagnostic(ErrorCode.ERR_OperatorCantBeChecked, "checked").WithArguments("|").WithLocation(6, 35),
                // (6,43): error CS0111: Type 'Extensions1' already defines a member called 'op_BitwiseOr' with the same parameter types
                //         public static C1 operator checked |(C1 x, C1 y) => throw null;
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "|").WithArguments("op_BitwiseOr", "Extensions1").WithLocation(6, 43)
                );
 
            var src2 = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator |(C1 x, C1 y)
        {
            System.Console.Write("regular");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 |= c1;
 
        checked
        {
            _ = c1 |= c1;
        }
    }
}
""";
 
            var comp2 = CreateCompilation(src2, options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "regularregular").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_058_Consumption_Checked_CheckedFormNotSupported()
        {
            var src1 = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator |=(C1 y) => throw null;
        public void operator checked |=(C1 y) => throw null;
    }
}
 
public class C1;

""" + CompilerFeatureRequiredAttribute;
 
            var comp1 = CreateCompilation(src1);
            comp1.VerifyEmitDiagnostics(
                // (6,30): error CS9023: User-defined operator '|=' cannot be declared checked
                //         public void operator checked |=(C1 y) => throw null;
                Diagnostic(ErrorCode.ERR_OperatorCantBeChecked, "checked").WithArguments("|=").WithLocation(6, 30),
                // (6,38): error CS0111: Type 'Extensions1' already defines a member called 'op_BitwiseOrAssignment' with the same parameter types
                //         public void operator checked |=(C1 y) => throw null;
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "|=").WithArguments("op_BitwiseOrAssignment", "Extensions1").WithLocation(6, 38)
                );
 
            var src2 = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator |=(C1 y)
        {
            System.Console.Write("regular");
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 |= c1;
 
        checked
        {
            _ = c1 |= c1;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp2 = CreateCompilation(src2, options: TestOptions.DebugExe);
            CompileAndVerify(comp2, expectedOutput: "regularregular").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_059_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x, C1 y)
        {
            System.Console.Write("regular");
            return x;
        }
        public static C1 operator checked -(C1 x, C1 y)
        {
            System.Console.Write("checked");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 -= c1;
 
        checked
        {
            _ = c1 -= c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_060_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator -=(C1 y)
        {
            System.Console.Write("regular");
        }
        public void operator checked -=(C1 y)
        {
            System.Console.Write("checked");
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 -= c1;
 
        checked
        {
            _ = c1 -= c1;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_061_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x, C1 y)
        {
            System.Console.Write("regular");
            return x;
        }
    }
    extension(C1)
    {
        public static C1 operator checked -(C1 x, C1 y)
        {
            System.Console.Write("checked");
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 -= c1;
 
        checked
        {
            _ = c1 -= c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_062_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator -=(C1 y)
        {
            System.Console.Write("regular");
        }
    }
    extension(C1 x)
    {
        public void operator checked -=(C1 y)
        {
            System.Console.Write("checked");
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 -= c1;
 
        checked
        {
            _ = c1 -= c1;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_063_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x, C1 y)
        {
            return x;
        }
 
        public static C1 operator checked -(C1 x, C1 y)
        {
            return x;
        }
    }
}
 
public static class Extensions2
{
    extension(C1)
    {
        public static C1 operator -(C1 x, C1 y)
        {
            return x;
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
        _ = c1 -= c1;
 
        checked
        {
            _ = c1 -= c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (35,13): error CS0034: Operator '-=' is ambiguous on operands of type 'C1' and 'C1'
                //         _ = c1 -= c1;
                Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "c1 -= c1").WithArguments("-=", "C1", "C1").WithLocation(35, 13),
                // (39,17): error CS0034: Operator '-=' is ambiguous on operands of type 'C1' and 'C1'
                //             _ = c1 -= c1;
                Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "c1 -= c1").WithArguments("-=", "C1", "C1").WithLocation(39, 17)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().Last();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("Extensions1.extension(C1).operator checked -(C1, C1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("Extensions2.extension(C1).operator -(C1, C1)", symbolInfo.CandidateSymbols[1].ToDisplayString());
        }
 
        [Fact]
        [WorkItem("https://github.com/dotnet/roslyn/issues/78968")]
        public void CompoundAssignment_064_Consumption_Checked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator -=(C1 y)
        {
        }
 
        public void operator checked -=(C1 y)
        {
        }
    }
}
 
public static class Extensions2
{
    extension(C1 x)
    {
        public void operator -=(C1 y)
        {
        }
    }
}
 
public class C1;
 
class Program
{
    static void Main()
    {
        var c1 = new C1();
#line 35
        _ = c1 -= c1;
 
        checked
        {
            _ = c1 -= c1;
        }
    }
}
""";
 
            var comp = CreateCompilation([src, CompilerFeatureRequiredAttribute], options: TestOptions.DebugExe);
#if DEBUG
            comp.VerifyEmitDiagnostics(
                // (35,16): error CS0121: The call is ambiguous between the following methods or properties: 'Extensions2.extension(C1).operator -=(C1)' and 'Extensions1.extension(C1).operator -=(C1)'
                //         _ = c1 -= c1;
                Diagnostic(ErrorCode.ERR_AmbigCall, "-=").WithArguments("Extensions2.extension(C1).operator -=(C1)", "Extensions1.extension(C1).operator -=(C1)").WithLocation(35, 16),
                // (39,20): error CS0121: The call is ambiguous between the following methods or properties: 'Extensions1.extension(C1).operator checked -=(C1)' and 'Extensions2.extension(C1).operator -=(C1)'
                //             _ = c1 -= c1;
                Diagnostic(ErrorCode.ERR_AmbigCall, "-=").WithArguments("Extensions1.extension(C1).operator checked -=(C1)", "Extensions2.extension(C1).operator -=(C1)").WithLocation(39, 20)
                );
#else
            // https://github.com/dotnet/roslyn/issues/78968: Understand what is causing DEBUG/RELEASE behavior difference
            comp.VerifyEmitDiagnostics(
                // (35,16): error CS0121: The call is ambiguous between the following methods or properties: 'Extensions1.extension(C1).operator -=(C1)' and 'Extensions2.extension(C1).operator -=(C1)'
                //         _ = c1 -= c1;
                Diagnostic(ErrorCode.ERR_AmbigCall, "-=").WithArguments("Extensions1.extension(C1).operator -=(C1)", "Extensions2.extension(C1).operator -=(C1)").WithLocation(35, 16),
                // (39,20): error CS0121: The call is ambiguous between the following methods or properties: 'Extensions1.extension(C1).operator checked -=(C1)' and 'Extensions2.extension(C1).operator -=(C1)'
                //             _ = c1 -= c1;
                Diagnostic(ErrorCode.ERR_AmbigCall, "-=").WithArguments("Extensions1.extension(C1).operator checked -=(C1)", "Extensions2.extension(C1).operator -=(C1)").WithLocation(39, 20)
                );
#endif
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNode = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().Last();
            var symbolInfo = model.GetSymbolInfo(opNode);
 
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
            AssertEx.Equal("Extensions1.extension(C1).operator checked -=(C1)", symbolInfo.CandidateSymbols[0].ToDisplayString());
            AssertEx.Equal("Extensions2.extension(C1).operator -=(C1)", symbolInfo.CandidateSymbols[1].ToDisplayString());
        }
 
        [Fact]
        public void CompoundAssignment_065_Consumption_CheckedLiftedIsWorse()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator -(S1 x, S1 y) => throw null;
        public static S1 operator checked -(S1 x, S1 y) => throw null;
    }
    extension(S1?)
    {
        public static S1? operator -(S1? x, S1? y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        _ = s1 -= s1;
        System.Console.Write(":");
 
        checked
        {
            _ = s1 -= s1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_066_Consumption_CheckedNoLiftedForm()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator -=(int i) => throw null;
        public void operator checked -=(int i) => throw null;
    }
    extension(ref S1? x)
    {
        public void operator -=(int i)
        {
            System.Console.Write("operator1");
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? s1 = new S1();
        _ = s1 -= 1;
        System.Console.Write(":");
 
        checked
        {
            _ = s1 -= 1;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1:operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_067_Consumption_OverloadResolutionPlusRegularVsChecked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1)
    {
        public static C2 operator -(C1 x, C1 y)
        {
            System.Console.Write("C1");
            return (C2)x;
        }
        public static C2 operator checked -(C1 x, C1 y)
        {
            System.Console.Write("checkedC1");
            return (C2)x;
        }
    }
    extension(C2)
    {
        public static C2 operator -(C2 x, C2 y)
        {
            System.Console.Write("C2");
            return x;
        }
    }
}
 
public class C1;
public class C2 : C1;
 
class Program
{
    static void Main()
    {
        C1 c1 = new C2();
        _ = c1 -= c1;
 
        checked
        {
            _ = c1 -= c1;
        }
 
        var c2 = new C2();
        _ = c2 -= c2;
 
        checked
        {
            _ = c2 -= c2;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "C1checkedC1C2C2").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_068_Consumption_OverloadResolutionPlusRegularVsChecked()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator -=(C1 y)
        {
            System.Console.Write("C1");
        }
        public void operator checked -=(C1 y)
        {
            System.Console.Write("checkedC1");
        }
    }
    extension(C2 x)
    {
        public void operator -=(C2 y)
        {
            System.Console.Write("C2");
        }
    }
}
 
public class C1;
public class C2 : C1;
public class C3 : C1;
 
class Program
{
    static void Main()
    {
        var c3 = new C3();
        _ = c3 -= c3;
 
        checked
        {
            _ = c3 -= c3;
        }
 
        var c2 = new C2();
        _ = c2 -= c2;
 
        checked
        {
            _ = c2 -= c2;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "C1checkedC1C2C2").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_069_Consumption_OnObject()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object)
    {
        public static object operator +(object x, object y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
        _ = s1 += s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_070_Consumption_OnObject()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object x)
    {
        public void operator +=(object y)
        {
            System.Console.Write("operator1");
        }
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
        _ = s1 += s1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_071_Consumption_NotOnDynamic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object z)
    {
        public static object operator +(object x, object y)
        {
            System.Console.Write("operator1");
            return x;
        }
 
        public void operator +=(object y)
        {
            System.Console.Write("operator2");
        }
    }
}
 
class Program
{
    static void Main()
    {
        dynamic s1 = new object();
        var s2 = new object();
        try
        {
            _ = s1 + s2;
        }
        catch
        {
            System.Console.Write("exception1");
        }
 
        try
        {
            _ = s2 + s1;
        }
        catch
        {
            System.Console.Write("exception2");
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "exception1exception2").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_072_Consumption_WithLambda()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(S1)
    {
        public static S1 operator +(S1 x, System.Func<int> y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
public class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = s1 += (() => 1);
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_073_Consumption_WithLambda()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 x)
    {
        public void operator +=(System.Func<int> y)
        {
            System.Console.Write("operator1");
        }
    }
}
 
public struct S1
{}
 
public class Program
{
    static void Main()
    {
        S1 s1 = new S1();
        _ = s1 += (() => 1);
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "operator1").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_074_Consumption_BadOperand()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(ref S1 z)
    {
        public static S1 operator +(S1 x, S2 y)
        {
            System.Console.Write("operator1");
            return x;
        }
        public static S1 operator +(S2 y, S1 x)
        {
            System.Console.Write("operator2");
            return x;
        }
        public void operator +=(S2 y)
        {
            System.Console.Write("operator3");
        }
    }
}
 
public struct S1
{}
public struct S2
{}
 
public class Program
{
    static void Main()
    {
        S1 s1 = new S1();
#line 28
        _ = s1 += new();
        _ = new() += s1;
        _ = new() += new();
        _ = s1 += default;
        _ = default += s1;
        _ = default += default;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (28,13): error CS8310: Operator '+=' cannot be applied to operand 'new()'
                //         _ = s1 += new();
                Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "s1 += new()").WithArguments("+=", "new()").WithLocation(28, 13),
                // (29,13): error CS0131: The left-hand side of an assignment must be a variable, property or indexer
                //         _ = new() += s1;
                Diagnostic(ErrorCode.ERR_AssgLvalueExpected, "new()").WithLocation(29, 13),
                // (30,13): error CS0131: The left-hand side of an assignment must be a variable, property or indexer
                //         _ = new() += new();
                Diagnostic(ErrorCode.ERR_AssgLvalueExpected, "new()").WithLocation(30, 13),
                // (31,13): error CS8310: Operator '+=' cannot be applied to operand 'default'
                //         _ = s1 += default;
                Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefaultOrNew, "s1 += default").WithArguments("+=", "default").WithLocation(31, 13),
                // (32,13): error CS0131: The left-hand side of an assignment must be a variable, property or indexer
                //         _ = default += s1;
                Diagnostic(ErrorCode.ERR_AssgLvalueExpected, "default").WithLocation(32, 13),
                // (33,13): error CS0131: The left-hand side of an assignment must be a variable, property or indexer
                //         _ = default += default;
                Diagnostic(ErrorCode.ERR_AssgLvalueExpected, "default").WithLocation(33, 13)
                );
        }
 
        [Fact]
        public void CompoundAssignment_075_Consumption_BadOperand()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(object y)
    {
        public void operator +=(int i)
        {
            System.Console.Write("operator2");
        }
    }
}
 
class Program
{
    static object P {get; set;}
 
    static void Main()
    {
        _ = P += 1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (18,13): error CS0019: Operator '+=' cannot be applied to operands of type 'object' and 'int'
                //         _ = P += 1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "P += 1").WithArguments("+=", "object", "int").WithLocation(18, 13)
                );
        }
 
        [Fact]
        public void CompoundAssignment_076_Consumption_BadReceiver()
        {
            var src = $$$"""
public static class Extensions1
{
    extension(__arglist)
    {
        public static object operator +(object x, object y)
        {
            return x;
        }
        public void operator +=(object y)
        {
        }
    }
}
 
class Program
{
    static void Main()
    {
        var s1 = new object();
        _ = s1 += s1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (3,15): error CS1669: __arglist is not valid in this context
                //     extension(__arglist)
                Diagnostic(ErrorCode.ERR_IllegalVarArgs, "__arglist").WithLocation(3, 15),
                // (5,39): error CS9319: One of the parameters of a binary operator must be the extended type.
                //         public static object operator +(object x, object y)
                Diagnostic(ErrorCode.ERR_BadExtensionBinaryOperatorSignature, "+").WithLocation(5, 39),
                // (20,13): error CS0019: Operator '+=' cannot be applied to operands of type 'object' and 'object'
                //         _ = s1 += s1;
                Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 += s1").WithArguments("+=", "object", "object").WithLocation(20, 13)
                );
        }
 
        [Fact]
        public void CompoundAssignment_077_Consumption_Checked_Generic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T1>(C1<T1>)
    {
        public static C1<T1> operator -(C1<T1> x, C1<T1> y)
        {
            System.Console.Write("regular");
            return x;
        }
    }
    extension<T2>(C1<T2>)
    {
        public static C1<T2> operator checked -(C1<T2> x, C1<T2> y)
        {
            System.Console.Write("checked");
            return x;
        }
    }
}
 
public class C1<T>;
 
class Program
{
    static void Main()
    {
        var c1 = new C1<int>();
        _ = c1 -= c1;
 
        checked
        {
            _ = c1 -= c1;
        }
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_078_Consumption_Checked_Generic()
        {
            var src = $$$"""
public static class Extensions1
{
    extension<T1>(C1<T1> x)
    {
        public void operator -=(C1<T1> y)
        {
            System.Console.Write("regular");
        }
    }
    extension<T2>(C1<T2> x)
    {
        public void operator checked -=(C1<T2> y)
        {
            System.Console.Write("checked");
        }
    }
}
 
public class C1<T>;
 
class Program
{
    static void Main()
    {
        var c1 = new C1<int>();
        _ = c1 -= c1;
 
        checked
        {
            _ = c1 -= c1;
        }
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            CompileAndVerify(comp, expectedOutput: "regularchecked").VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_079_Consumption_ExpressionTree()
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(S1 s1)
    {
        public static S1 operator +(S1 x, S1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1, S1>> ex = (s1) => s1 += s1;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (22,54): error CS0832: An expression tree may not contain an assignment operator
                //         Expression<System.Func<S1, S1>> ex = (s1) => s1 += s1;
                Diagnostic(ErrorCode.ERR_ExpressionTreeContainsAssignment, "s1 += s1").WithLocation(22, 54)
                );
        }
 
        [Fact]
        public void CompoundAssignment_080_Consumption_ExpressionTree()
        {
            var src = $$$"""
using System.Linq.Expressions;
 
public static class Extensions1
{
    extension(ref S1 s1)
    {
        public void operator +=(S1 y)
        {
            System.Console.Write("operator1");
        }
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        Expression<System.Func<S1, S1>> ex = (s1) => s1 += s1;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyEmitDiagnostics(
                // (21,54): error CS0832: An expression tree may not contain an assignment operator
                //         Expression<System.Func<S1, S1>> ex = (s1) => s1 += s1;
                Diagnostic(ErrorCode.ERR_ExpressionTreeContainsAssignment, "s1 += s1").WithLocation(21, 54)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_01
        /// </summary>
        [Fact]
        public void CompoundAssignment_081_RefSafety()
        {
            var source = """
public ref struct C
{
    public static C X(C left, C right) => right;
    public C M(C c, scoped C c1)
    {
#line 7
        c += c1;
        c = c + c1;
        c = X(c, c1);
        return c;
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator +(C left, C right) => right;
    }
}
""";
            CreateCompilation(source).VerifyDiagnostics(
                // (7,9): error CS8347: Cannot use a result of 'Extensions.extension(C).operator +(C, C)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         c += c1;
                Diagnostic(ErrorCode.ERR_EscapeCall, "c += c1").WithArguments("Extensions.extension(C).operator +(C, C)", "right").WithLocation(7, 9),
                // (7,14): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         c += c1;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(7, 14),
                // (8,13): error CS8347: Cannot use a result of 'Extensions.extension(C).operator +(C, C)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         c = c + c1;
                Diagnostic(ErrorCode.ERR_EscapeCall, "c + c1").WithArguments("Extensions.extension(C).operator +(C, C)", "right").WithLocation(8, 13),
                // (8,17): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         c = c + c1;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(8, 17),
                // (9,13): error CS8347: Cannot use a result of 'C.X(C, C)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         c = X(c, c1);
                Diagnostic(ErrorCode.ERR_EscapeCall, "X(c, c1)").WithArguments("C.X(C, C)", "right").WithLocation(9, 13),
                // (9,18): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         c = X(c, c1);
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(9, 18)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_02
        /// </summary>
        [Fact]
        public void CompoundAssignment_082_RefSafety()
        {
            var source = """
public ref struct C
{
    public static C X(C left, C right) => right;
    public static C Y(C left) => left;
    public C M1(C c, scoped C c1)
    {
#line 8
        return Y(c += c1);
    }
    public C M2(C c, scoped C c1)
    {
        return Y(c = X(c, c1));
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator +(C left, C right) => right;
    }
}
""";
            CreateCompilation(source).VerifyDiagnostics(
                // (8,16): error CS8347: Cannot use a result of 'C.Y(C)' in this context because it may expose variables referenced by parameter 'left' outside of their declaration scope
                //         return Y(c += c1);
                Diagnostic(ErrorCode.ERR_EscapeCall, "Y(c += c1)").WithArguments("C.Y(C)", "left").WithLocation(8, 16),
                // (8,18): error CS8347: Cannot use a result of 'Extensions.extension(C).operator +(C, C)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         return Y(c += c1);
                Diagnostic(ErrorCode.ERR_EscapeCall, "c += c1").WithArguments("Extensions.extension(C).operator +(C, C)", "right").WithLocation(8, 18),
                // (8,18): error CS8347: Cannot use a result of 'Extensions.extension(C).operator +(C, C)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         return Y(c += c1);
                Diagnostic(ErrorCode.ERR_EscapeCall, "c += c1").WithArguments("Extensions.extension(C).operator +(C, C)", "right").WithLocation(8, 18),
                // (8,23): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         return Y(c += c1);
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(8, 23),
                // (8,23): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         return Y(c += c1);
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(8, 23),
                // (12,22): error CS8347: Cannot use a result of 'C.X(C, C)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         return Y(c = X(c, c1));
                Diagnostic(ErrorCode.ERR_EscapeCall, "X(c, c1)").WithArguments("C.X(C, C)", "right").WithLocation(12, 22),
                // (12,27): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         return Y(c = X(c, c1));
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(12, 27)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_Scoped_Left
        /// </summary>
        [Fact]
        public void CompoundAssignment_083_RefSafety()
        {
            var source = """
public ref struct C
{
    public static C X(scoped C left, C right) => right;
    public C M(C c, scoped C c1)
    {
#line 7
        c += c1;
        c = c + c1;
        c = X(c, c1);
        return c;
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator +(scoped C left, C right) => right;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics(
                // (7,9): error CS8347: Cannot use a result of 'Extensions.extension(C).operator +(scoped C, C)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         c += c1;
                Diagnostic(ErrorCode.ERR_EscapeCall, "c += c1").WithArguments("Extensions.extension(C).operator +(scoped C, C)", "right").WithLocation(7, 9),
                // (7,14): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         c += c1;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(7, 14),
                // (8,13): error CS8347: Cannot use a result of 'Extensions.extension(C).operator +(scoped C, C)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         c = c + c1;
                Diagnostic(ErrorCode.ERR_EscapeCall, "c + c1").WithArguments("Extensions.extension(C).operator +(scoped C, C)", "right").WithLocation(8, 13),
                // (8,17): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         c = c + c1;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(8, 17),
                // (9,13): error CS8347: Cannot use a result of 'C.X(scoped C, C)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         c = X(c, c1);
                Diagnostic(ErrorCode.ERR_EscapeCall, "X(c, c1)").WithArguments("C.X(scoped C, C)", "right").WithLocation(9, 13),
                // (9,18): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         c = X(c, c1);
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(9, 18)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_Scoped_Right
        /// </summary>
        [Fact]
        public void CompoundAssignment_084_RefSafety()
        {
            var source = """
public ref struct C
{
    public static C X(C left, scoped C right) => left;
    public C M(C c, scoped C c1)
    {
        c += c1;
        c = c + c1;
        c = X(c, c1);
        return c;
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator +(C left, scoped C right) => left;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics();
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_Scoped_Both
        /// </summary>
        [Fact]
        public void CompoundAssignment_085_RefSafety()
        {
            var source = """
static class Extensions
{
    extension(C)
    {
#line 3
        public static C operator +(scoped C left, scoped C right) => right;
    }
}
 
public ref struct C
{
#line 4
    public static C X(scoped C left, scoped C right) => right;
    public C M(C c, scoped C c1)
    {
        c += c1;
        c = c + c1;
        c = X(c, c1);
        return c;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics(
                // (3,70): error CS8352: Cannot use variable 'scoped C right' in this context because it may expose referenced variables outside of their declaration scope
                //         public static C operator +(scoped C left, scoped C right) => right;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "right").WithArguments("scoped C right").WithLocation(3, 70),
                // (4,57): error CS8352: Cannot use variable 'scoped C right' in this context because it may expose referenced variables outside of their declaration scope
                //     public static C X(scoped C left, scoped C right) => right;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "right").WithArguments("scoped C right").WithLocation(4, 57)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_ScopedTarget_01
        /// </summary>
        [Fact]
        public void CompoundAssignment_086_RefSafety()
        {
            var source = """
public ref struct C
{
    public static C X(C left, C right) => right;
    public C M(scoped C c, C c1)
    {
        c += c1;
        c = c + c1;
        c = X(c, c1);
        return c1;
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator +(C left, C right) => right;
    }
}
""";
            CreateCompilation(source).VerifyDiagnostics();
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_ScopedTarget_02
        /// </summary>
        [Fact]
        public void CompoundAssignment_087_RefSafety()
        {
            var source = """
public ref struct C
{
    public static C X(C left, C right) => right;
    public static C Y(C left) => left;
    public C M1(scoped C c, C c1)
    {
#line 8
        return Y(c += c1);
    }
    public C M2(scoped C c, C c1)
    {
        return Y(c = X(c, c1));
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator +(C left, C right) => right;
    }
}
""";
            CreateCompilation(source).VerifyDiagnostics(
                // (8,16): error CS8347: Cannot use a result of 'C.Y(C)' in this context because it may expose variables referenced by parameter 'left' outside of their declaration scope
                //         return Y(c += c1);
                Diagnostic(ErrorCode.ERR_EscapeCall, "Y(c += c1)").WithArguments("C.Y(C)", "left").WithLocation(8, 16),
                // (8,18): error CS8352: Cannot use variable 'scoped C c' in this context because it may expose referenced variables outside of their declaration scope
                //         return Y(c += c1);
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c").WithArguments("scoped C c").WithLocation(8, 18),
                // (8,18): error CS8347: Cannot use a result of 'Extensions.extension(C).operator +(C, C)' in this context because it may expose variables referenced by parameter 'left' outside of their declaration scope
                //         return Y(c += c1);
                Diagnostic(ErrorCode.ERR_EscapeCall, "c += c1").WithArguments("Extensions.extension(C).operator +(C, C)", "left").WithLocation(8, 18),
                // (12,16): error CS8347: Cannot use a result of 'C.Y(C)' in this context because it may expose variables referenced by parameter 'left' outside of their declaration scope
                //         return Y(c = X(c, c1));
                Diagnostic(ErrorCode.ERR_EscapeCall, "Y(c = X(c, c1))").WithArguments("C.Y(C)", "left").WithLocation(12, 16),
                // (12,18): error CS8352: Cannot use variable 'scoped C c' in this context because it may expose referenced variables outside of their declaration scope
                //         return Y(c = X(c, c1));
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c = X(c, c1)").WithArguments("scoped C c").WithLocation(12, 18)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_ScopedTarget_03
        /// </summary>
        [Fact]
        public void CompoundAssignment_088_RefSafety()
        {
            var source = """
public ref struct C
{
    public static C X(C left, scoped C right) => left;
    public static C Y(C left) => left;
    public C M1(scoped C c, C c1)
    {
#line 8
        return Y(c += c1);
    }
    public C M2(scoped C c, C c1)
    {
        return Y(c = X(c, c1));
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator +(C left, scoped C right) => left;
    }
}
""";
            CreateCompilation(source).VerifyDiagnostics(
                // (8,16): error CS8347: Cannot use a result of 'C.Y(C)' in this context because it may expose variables referenced by parameter 'left' outside of their declaration scope
                //         return Y(c += c1);
                Diagnostic(ErrorCode.ERR_EscapeCall, "Y(c += c1)").WithArguments("C.Y(C)", "left").WithLocation(8, 16),
                // (8,18): error CS8352: Cannot use variable 'scoped C c' in this context because it may expose referenced variables outside of their declaration scope
                //         return Y(c += c1);
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c").WithArguments("scoped C c").WithLocation(8, 18),
                // (8,18): error CS8347: Cannot use a result of 'Extensions.extension(C).operator +(C, scoped C)' in this context because it may expose variables referenced by parameter 'left' outside of their declaration scope
                //         return Y(c += c1);
                Diagnostic(ErrorCode.ERR_EscapeCall, "c += c1").WithArguments("Extensions.extension(C).operator +(C, scoped C)", "left").WithLocation(8, 18),
                // (12,16): error CS8347: Cannot use a result of 'C.Y(C)' in this context because it may expose variables referenced by parameter 'left' outside of their declaration scope
                //         return Y(c = X(c, c1));
                Diagnostic(ErrorCode.ERR_EscapeCall, "Y(c = X(c, c1))").WithArguments("C.Y(C)", "left").WithLocation(12, 16),
                // (12,18): error CS8352: Cannot use variable 'scoped C c' in this context because it may expose referenced variables outside of their declaration scope
                //         return Y(c = X(c, c1));
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c = X(c, c1)").WithArguments("scoped C c").WithLocation(12, 18)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_ScopedTarget_04
        /// </summary>
        [Fact]
        public void CompoundAssignment_089_RefSafety()
        {
            var source = """
public ref struct C
{
    public static C X(scoped C left, C right) => right;
    public static C Y(C left) => left;
    public C M1(scoped C c, C c1)
    {
        return Y(c += c1);
    }
    public C M2(scoped C c, C c1)
    {
#line 12
        return Y(c = X(c, c1));
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator +(scoped C left, C right) => right; 
    }
}
""";
            CreateCompilation(source).VerifyDiagnostics(
                // (12,16): error CS8347: Cannot use a result of 'C.Y(C)' in this context because it may expose variables referenced by parameter 'left' outside of their declaration scope
                //         return Y(c = X(c, c1));
                Diagnostic(ErrorCode.ERR_EscapeCall, "Y(c = X(c, c1))").WithArguments("C.Y(C)", "left").WithLocation(12, 16),
                // (12,18): error CS8352: Cannot use variable 'scoped C c' in this context because it may expose referenced variables outside of their declaration scope
                //         return Y(c = X(c, c1));
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c = X(c, c1)").WithArguments("scoped C c").WithLocation(12, 18)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_Scoped_Left_ScopedTarget
        /// </summary>
        [Fact]
        public void CompoundAssignment_090_RefSafety()
        {
            var source = """
public ref struct C
{
    public static C X(scoped C left, C right) => right;
    public C M(scoped C c, C c1)
    {
        c += c1;
        c = c + c1;
        c = X(c, c1);
        return c1;
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator +(scoped C left, C right) => right;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics();
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_Scoped_Right_ScopedTarget
        /// </summary>
        [Fact]
        public void CompoundAssignment_091_RefSafety()
        {
            var source = """
public ref struct C
{
    public static C X(C left, scoped C right) => left;
    public C M(scoped C c, C c1)
    {
        c += c1;
        c = c + c1;
        c = X(c, c1);
        return c1;
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator +(C left, scoped C right) => left;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics();
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_Scoped_Both_ScopedTarget
        /// </summary>
        [Fact]
        public void CompoundAssignment_092_RefSafety()
        {
            var source = """
public ref struct C
{
    public static C X(scoped C left, scoped C right) => throw null;
    public C M(scoped C c, C c1)
    {
        c += c1;
        c = c + c1;
        c = X(c, c1);
        return c1;
    }
}
 
static class Extensions
{
    extension(C)
    {
        public static C operator +(scoped C left, scoped C right) => throw null;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics();
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_RegressionTest1
        /// </summary>
        [Fact]
        public void CompoundAssignment_093_RefSafety()
        {
            var source = """
using System;
 
public ref struct S1
{
    public S1(Span<int> span) { }
 
    static void Test()
    {
        S1 stackLocal = new S1(stackalloc int[1]);
        S1 heapLocal = new S1(default);
 
        stackLocal += stackLocal;
        stackLocal += heapLocal;
        heapLocal += heapLocal;
#line 16
        heapLocal += stackLocal; // 1
 
    }
}
 
static class Extensions
{
    extension(S1)
    {
        public static S1 operator +(S1 a, S1 b) => default;
    }
}
""";
            var comp = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.UnsafeDebugDll);
            comp.VerifyEmitDiagnostics(
                // (16,9): error CS8347: Cannot use a result of 'Extensions.extension(S1).operator +(S1, S1)' in this context because it may expose variables referenced by parameter 'b' outside of their declaration scope
                //         heapLocal += stackLocal; // 1
                Diagnostic(ErrorCode.ERR_EscapeCall, "heapLocal += stackLocal").WithArguments("Extensions.extension(S1).operator +(S1, S1)", "b").WithLocation(16, 9),
                // (16,22): error CS8352: Cannot use variable 'stackLocal' in this context because it may expose referenced variables outside of their declaration scope
                //         heapLocal += stackLocal; // 1
                Diagnostic(ErrorCode.ERR_EscapeVariable, "stackLocal").WithArguments("stackLocal").WithLocation(16, 22)
                );
        }
 
        /// <summary>
        /// This is a clone of Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics.RefEscapingTests.UserDefinedBinaryOperator_RefStruct_Compound_RegressionTest2
        /// </summary>
        [Fact]
        public void CompoundAssignment_094_RefSafety()
        {
            var source = """
using System;
 
public ref struct S1
{
    public S1(Span<int> span) { }
 
    static void Test()
    {
        S1 stackLocal = new(stackalloc int[1]);
        S1 heapLocal = new(default);
 
        stackLocal += stackLocal;
        stackLocal += heapLocal;
        heapLocal += heapLocal;
#line 16
        heapLocal += stackLocal; // 1
 
    }
}
 
public ref struct S2
{
    public S2(Span<int> span) { }
 
    static void Test()
    {
        S2 stackLocal = new(stackalloc int[1]);
        S2 heapLocal = new(default);
 
        stackLocal += stackLocal;
        stackLocal += heapLocal;
        heapLocal += heapLocal;
        heapLocal += stackLocal;
    }
}
 
public ref struct S3
{
    public S3(Span<int> span) { }
 
    static void Test()
    {
        S3 stackLocal = new(stackalloc int[1]);
        S3 heapLocal = new(default);
 
        stackLocal += stackLocal;
        stackLocal += heapLocal;
#line 50
        heapLocal += heapLocal; // 2
        heapLocal += stackLocal;  // 3
    }
}
 
public ref struct S4
{
    public S4(Span<int> span) { }
 
    static void Test()
    {
        S4 stackLocal = new(stackalloc int[1]);
        S4 heapLocal = new(default);
 
        stackLocal += stackLocal;
        stackLocal += heapLocal;
        heapLocal += heapLocal;
#line 68
        heapLocal += stackLocal; // 4
    }
}
 
static class Extensions
{
    extension(S1)
    {
        public static S1 operator +(S1 a, S1 b) => default;
    }
    extension(S2)
    {
        public static S2 operator +(S2 a, scoped S2 b) => default;
    }
    extension(S3)
    {
        public static S3 operator +(in S3 a, in S3 b) => default;
    }
    extension(S4)
    {
        public static S4 operator +(scoped in S4 a, scoped in S4 b) => default;
    }
}
""";
            var comp = CreateCompilation(source, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.UnsafeDebugDll);
            comp.VerifyEmitDiagnostics(
                // (16,9): error CS8347: Cannot use a result of 'Extensions.extension(S1).operator +(S1, S1)' in this context because it may expose variables referenced by parameter 'b' outside of their declaration scope
                //         heapLocal += stackLocal; // 1
                Diagnostic(ErrorCode.ERR_EscapeCall, "heapLocal += stackLocal").WithArguments("Extensions.extension(S1).operator +(S1, S1)", "b").WithLocation(16, 9),
                // (16,22): error CS8352: Cannot use variable 'stackLocal' in this context because it may expose referenced variables outside of their declaration scope
                //         heapLocal += stackLocal; // 1
                Diagnostic(ErrorCode.ERR_EscapeVariable, "stackLocal").WithArguments("stackLocal").WithLocation(16, 22),
                // (50,9): error CS8168: Cannot return local 'heapLocal' by reference because it is not a ref local
                //         heapLocal += heapLocal; // 2
                Diagnostic(ErrorCode.ERR_RefReturnLocal, "heapLocal").WithArguments("heapLocal").WithLocation(50, 9),
                // (50,9): error CS8347: Cannot use a result of 'Extensions.extension(S3).operator +(in S3, in S3)' in this context because it may expose variables referenced by parameter 'a' outside of their declaration scope
                //         heapLocal += heapLocal; // 2
                Diagnostic(ErrorCode.ERR_EscapeCall, "heapLocal += heapLocal").WithArguments("Extensions.extension(S3).operator +(in S3, in S3)", "a").WithLocation(50, 9),
                // (51,9): error CS8168: Cannot return local 'heapLocal' by reference because it is not a ref local
                //         heapLocal += stackLocal;  // 3
                Diagnostic(ErrorCode.ERR_RefReturnLocal, "heapLocal").WithArguments("heapLocal").WithLocation(51, 9),
                // (51,9): error CS8347: Cannot use a result of 'Extensions.extension(S3).operator +(in S3, in S3)' in this context because it may expose variables referenced by parameter 'a' outside of their declaration scope
                //         heapLocal += stackLocal;  // 3
                Diagnostic(ErrorCode.ERR_EscapeCall, "heapLocal += stackLocal").WithArguments("Extensions.extension(S3).operator +(in S3, in S3)", "a").WithLocation(51, 9),
                // (68,9): error CS8347: Cannot use a result of 'Extensions.extension(S4).operator +(scoped in S4, scoped in S4)' in this context because it may expose variables referenced by parameter 'b' outside of their declaration scope
                //         heapLocal += stackLocal; // 4
                Diagnostic(ErrorCode.ERR_EscapeCall, "heapLocal += stackLocal").WithArguments("Extensions.extension(S4).operator +(scoped in S4, scoped in S4)", "b").WithLocation(68, 9),
                // (68,22): error CS8352: Cannot use variable 'stackLocal' in this context because it may expose referenced variables outside of their declaration scope
                //         heapLocal += stackLocal; // 4
                Diagnostic(ErrorCode.ERR_EscapeVariable, "stackLocal").WithArguments("stackLocal").WithLocation(68, 22)
                );
        }
 
        [Fact]
        public void CompoundAssignment_095_RefSafety()
        {
            var source = """
public ref struct C
{
    public void X(C right) {}
    public C M1(C c, C c1)
    {
        c += c1;
        return c;
    }
    public C M2(C c, C c1)
    {
        c.X(c1);
        return c;
    }
}
 
static class Extensions
{
    extension(scoped ref C left)
    {
        public void operator +=(C right) {}
    }
}
""";
            CreateCompilation([source, CompilerFeatureRequiredAttribute]).VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_096_RefSafety()
        {
            var source = """
public ref struct C
{
    public void X(C right) {}
    public C M1(C c, scoped C c1)
    {
#line 7
        c += c1;
        return c;
    }
    public C M2(C c, scoped C c1)
    {
        c.X(c1);
        return c;
    }
}
 
static class Extensions
{
    extension(scoped ref C left)
    {
        public void operator +=(C right) {}
    }
}
""";
            CreateCompilation([source, CompilerFeatureRequiredAttribute]).VerifyDiagnostics(
                // (7,9): error CS8350: This combination of arguments to 'Extensions.extension(scoped ref C).operator +=(C)' is disallowed because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         c += c1;
                Diagnostic(ErrorCode.ERR_CallArgMixing, "c += c1").WithArguments("Extensions.extension(scoped ref C).operator +=(C)", "right").WithLocation(7, 9),
                // (7,14): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         c += c1;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(7, 14),
                // (12,9): error CS8350: This combination of arguments to 'C.X(C)' is disallowed because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         c.X(c1);
                Diagnostic(ErrorCode.ERR_CallArgMixing, "c.X(c1)").WithArguments("C.X(C)", "right").WithLocation(12, 9),
                // (12,13): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         c.X(c1);
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(12, 13)
                );
        }
 
        [Fact]
        public void CompoundAssignment_097_RefSafety()
        {
            var source = """
public ref struct C
{
    public void X(C right) {}
    public C M1(scoped C c, C c1)
    {
        c += c1;
#line 8
        return c;
    }
    public C M2(scoped C c, C c1)
    {
        c.X(c1);
        return c;
    }
}
 
static class Extensions
{
    extension(scoped ref C left)
    {
        public void operator +=(C right) {}
    }
}
""";
            CreateCompilation([source, CompilerFeatureRequiredAttribute]).VerifyDiagnostics(
                // (8,16): error CS8352: Cannot use variable 'scoped C c' in this context because it may expose referenced variables outside of their declaration scope
                //         return c;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c").WithArguments("scoped C c").WithLocation(8, 16),
                // (13,16): error CS8352: Cannot use variable 'scoped C c' in this context because it may expose referenced variables outside of their declaration scope
                //         return c;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c").WithArguments("scoped C c").WithLocation(13, 16)
                );
        }
 
        [Fact]
        public void CompoundAssignment_098_RefSafety()
        {
            var source = """
public ref struct C
{
    public void X(C right) {}
    public C M1(scoped C c, scoped C c1)
    {
        c += c1;
#line 8
        return c;
    }
    public C M2(scoped C c, scoped C c1)
    {
        c.X(c1);
        return c;
    }
}
 
static class Extensions
{
    extension(scoped ref C left)
    {
        public void operator +=(C right) {}
    }
}
""";
            CreateCompilation([source, CompilerFeatureRequiredAttribute]).VerifyDiagnostics(
                // (8,16): error CS8352: Cannot use variable 'scoped C c' in this context because it may expose referenced variables outside of their declaration scope
                //         return c;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c").WithArguments("scoped C c").WithLocation(8, 16),
                // (13,16): error CS8352: Cannot use variable 'scoped C c' in this context because it may expose referenced variables outside of their declaration scope
                //         return c;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c").WithArguments("scoped C c").WithLocation(13, 16)
                );
        }
 
        [Fact]
        public void CompoundAssignment_099_RefSafety()
        {
            var source = """
public ref struct C
{
    public void X(scoped C right) {}
    public C M1(C c, scoped C c1)
    {
        c += c1;
        return c;
    }
    public C M2(C c, scoped C c1)
    {
        c.X(c1);
        return c;
    }
}
 
static class Extensions
{
    extension(scoped ref C left)
    {
        public void operator +=(scoped C right) {}
    }
}
""";
            CreateCompilation([source, CompilerFeatureRequiredAttribute]).VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_100_RefSafety()
        {
            var source = """
public ref struct C
{
    public C M1(C c, C c1)
    {
        return c += c1;
    }
}
 
static class Extensions
{
    extension(ref C left)
    {
        public void operator +=(C right) {}
    }
}
""";
            CreateCompilation([source, CompilerFeatureRequiredAttribute]).VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_101_RefSafety()
        {
            var source = """
public ref struct C
{
    public C M1(scoped C c, C c1)
    {
#line 6
        return c += c1;
    }
}
 
static class Extensions
{
    extension(ref C left)
    {
        public void operator +=(C right) {}
    }
}
""";
            CreateCompilation([source, CompilerFeatureRequiredAttribute]).VerifyDiagnostics(
                // (6,16): error CS8352: Cannot use variable 'scoped C c' in this context because it may expose referenced variables outside of their declaration scope
                //         return c += c1;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c").WithArguments("scoped C c").WithLocation(6, 16)
                );
        }
 
        [Fact]
        public void CompoundAssignment_102_RefSafety()
        {
            var source = """
public ref struct C
{
    public C M1(C c, scoped C c1)
    {
#line 6
        return c += c1;
    }
}
 
static class Extensions
{
    extension(ref C left)
    {
        public void operator +=(C right) {}
    }
}
""";
            CreateCompilation([source, CompilerFeatureRequiredAttribute]).VerifyDiagnostics(
                // (6,16): error CS8350: This combination of arguments to 'Extensions.extension(ref C).operator +=(C)' is disallowed because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         return c += c1;
                Diagnostic(ErrorCode.ERR_CallArgMixing, "c += c1").WithArguments("Extensions.extension(ref C).operator +=(C)", "right").WithLocation(6, 16),
                // (6,21): error CS8352: Cannot use variable 'scoped C c1' in this context because it may expose referenced variables outside of their declaration scope
                //         return c += c1;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(6, 21)
                );
        }
 
        [Fact]
        public void CompoundAssignment_103_RefSafety()
        {
            var source = """
public ref struct C
{
    public C M1(C c, scoped C c1)
    {
        return c += c1;
    }
}
 
static class Extensions
{
    extension(ref C left)
    {
        public void operator +=(scoped C right) {}
    }
}
""";
            CreateCompilation([source, CompilerFeatureRequiredAttribute]).VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_104_RefSafety()
        {
            var source = """
public ref struct C
{
    public C M1(scoped C c, scoped C c1)
    {
#line 6
        return c += c1;
    }
}
 
static class Extensions
{
    extension(ref C left)
    {
        public void operator +=(C right) {}
    }
}
""";
            CreateCompilation([source, CompilerFeatureRequiredAttribute]).VerifyDiagnostics(
                // (6,16): error CS8352: Cannot use variable 'scoped C c' in this context because it may expose referenced variables outside of their declaration scope
                //         return c += c1;
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c").WithArguments("scoped C c").WithLocation(6, 16)
                );
        }
 
        [Fact]
        public void CompoundAssignment_105_RefSafety()
        {
            var source = """
public ref struct C
{
    static C X(C c) => throw null;
    public C M1(scoped C c, scoped C c1)
    {
#line 7
        return X(c += c1);
    }
}
 
static class Extensions
{
    extension(ref C left)
    {
        public void operator +=(C right) {}
    }
}
""";
            CreateCompilation([source, CompilerFeatureRequiredAttribute]).VerifyDiagnostics(
                // (7,16): error CS8347: Cannot use a result of 'C.X(C)' in this context because it may expose variables referenced by parameter 'c' outside of their declaration scope
                //         return X(c += c1);
                Diagnostic(ErrorCode.ERR_EscapeCall, "X(c += c1)").WithArguments("C.X(C)", "c").WithLocation(7, 16),
                // (7,18): error CS8352: Cannot use variable 'scoped C c' in this context because it may expose referenced variables outside of their declaration scope
                //         return X(c += c1);
                Diagnostic(ErrorCode.ERR_EscapeVariable, "c").WithArguments("scoped C c").WithLocation(7, 18)
                );
        }
 
        [Fact]
        public void CompoundAssignment_106_RefSafety()
        {
            var source = $$$"""
ref struct C
{
    public C M1(C c1)
    {
#line 8
        return c1 += 1;
    }
    public C M2(C c2)
    {
        return c2 -= 1;
    }
    public C M3(C c3, in int right)
    {
        return c3 += right;
    }
    public C M4(C c4, in int right)
    {
        return c4 -= right;
    }
}
 
static class Extensions
{
    extension(ref C x)
    {
        public void operator +=([System.Diagnostics.CodeAnalysis.UnscopedRef] in int right) {}
        public static C operator -(C left, [System.Diagnostics.CodeAnalysis.UnscopedRef] in int right) => throw null;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.Net90).VerifyDiagnostics(
                // (8,16): error CS8350: This combination of arguments to 'Extensions.extension(ref C).operator +=(in int)' is disallowed because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         return c1 += 1;
                Diagnostic(ErrorCode.ERR_CallArgMixing, "c1 += 1").WithArguments("Extensions.extension(ref C).operator +=(in int)", "right").WithLocation(8, 16),
                // (8,22): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return c1 += 1;
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "1").WithLocation(8, 22),
                // (12,16): error CS8347: Cannot use a result of 'Extensions.extension(ref C).operator -(C, in int)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         return c2 -= 1;
                Diagnostic(ErrorCode.ERR_EscapeCall, "c2 -= 1").WithArguments("Extensions.extension(ref C).operator -(C, in int)", "right").WithLocation(12, 16),
                // (12,16): error CS8347: Cannot use a result of 'Extensions.extension(ref C).operator -(C, in int)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         return c2 -= 1;
                Diagnostic(ErrorCode.ERR_EscapeCall, "c2 -= 1").WithArguments("Extensions.extension(ref C).operator -(C, in int)", "right").WithLocation(12, 16),
                // (12,22): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return c2 -= 1;
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "1").WithLocation(12, 22),
                // (12,22): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return c2 -= 1;
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "1").WithLocation(12, 22),
                // (16,16): error CS8350: This combination of arguments to 'Extensions.extension(ref C).operator +=(in int)' is disallowed because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         return c3 += right;
                Diagnostic(ErrorCode.ERR_CallArgMixing, "c3 += right").WithArguments("Extensions.extension(ref C).operator +=(in int)", "right").WithLocation(16, 16),
                // (16,22): error CS9077: Cannot return a parameter by reference 'right' through a ref parameter; it can only be returned in a return statement
                //         return c3 += right;
                Diagnostic(ErrorCode.ERR_RefReturnOnlyParameter, "right").WithArguments("right").WithLocation(16, 22),
                // (20,16): error CS8347: Cannot use a result of 'Extensions.extension(ref C).operator -(C, in int)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         return c4 -= right;
                Diagnostic(ErrorCode.ERR_EscapeCall, "c4 -= right").WithArguments("Extensions.extension(ref C).operator -(C, in int)", "right").WithLocation(20, 16),
                // (20,22): error CS9077: Cannot return a parameter by reference 'right' through a ref parameter; it can only be returned in a return statement
                //         return c4 -= right;
                Diagnostic(ErrorCode.ERR_RefReturnOnlyParameter, "right").WithArguments("right").WithLocation(20, 22)
                );
        }
 
        [Fact]
        public void CompoundAssignment_107_RefSafety()
        {
            var source = """
ref struct C
{
    public C M1(C c1)
    {
        return c1 += 1;
    }
    public C M2(C c2)
    {
#line 12
        return c2 -= 1;
    }
    public C M3(C c3, in int right)
    {
        return c3 += right;
    }
    public C M4(C c4, in int right)
    {
        return c4 -= right;
    }
}
 
static class Extensions
{
    extension(ref C x)
    {
        public void operator +=(in int right) {}
        public static C operator -(C left, in int right) => throw null;
    }
}
""";
            CreateCompilation(source, targetFramework: TargetFramework.Net90).VerifyDiagnostics(
                // (12,16): error CS8347: Cannot use a result of 'Extensions.extension(ref C).operator -(C, in int)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         return c2 -= 1;
                Diagnostic(ErrorCode.ERR_EscapeCall, "c2 -= 1").WithArguments("Extensions.extension(ref C).operator -(C, in int)", "right").WithLocation(12, 16),
                // (12,16): error CS8347: Cannot use a result of 'Extensions.extension(ref C).operator -(C, in int)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         return c2 -= 1;
                Diagnostic(ErrorCode.ERR_EscapeCall, "c2 -= 1").WithArguments("Extensions.extension(ref C).operator -(C, in int)", "right").WithLocation(12, 16),
                // (12,22): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return c2 -= 1;
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "1").WithLocation(12, 22),
                // (12,22): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
                //         return c2 -= 1;
                Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "1").WithLocation(12, 22),
                // (20,16): error CS8347: Cannot use a result of 'Extensions.extension(ref C).operator -(C, in int)' in this context because it may expose variables referenced by parameter 'right' outside of their declaration scope
                //         return c4 -= right;
                Diagnostic(ErrorCode.ERR_EscapeCall, "c4 -= right").WithArguments("Extensions.extension(ref C).operator -(C, in int)", "right").WithLocation(20, 16),
                // (20,22): error CS9077: Cannot return a parameter by reference 'right' through a ref parameter; it can only be returned in a return statement
                //         return c4 -= right;
                Diagnostic(ErrorCode.ERR_RefReturnOnlyParameter, "right").WithArguments("right").WithLocation(20, 22)
                );
        }
 
        [Fact]
        public void CompoundAssignment_108_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1)
    {
        public static C1 operator -(C1 x, C1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
 
    extension(C2)
    {
        public static C2 operator -(C2? x, C2? y)
        {
            System.Console.Write("operator2");
            return new C2();
        }
    }
}
 
public class C1
{}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C1? x1 = null;
        C1? x2 = null;
        C1 y = new C1();
#line 25
        _ = x1 -= y;
        y = y -= x2;
 
        C2? z = null;
        _ = z -= z;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (25,13): warning CS8604: Possible null reference argument for parameter 'x' in 'C1 extension(C1).operator -(C1 x, C1 y)'.
                //         _ = x1 -= y;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "C1 extension(C1).operator -(C1 x, C1 y)").WithLocation(25, 13),
                // (26,18): warning CS8604: Possible null reference argument for parameter 'y' in 'C1 extension(C1).operator -(C1 x, C1 y)'.
                //         y = y -= x2;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("y", "C1 extension(C1).operator -(C1 x, C1 y)").WithLocation(26, 18)
                );
        }
 
        [Fact]
        public void CompoundAssignment_109_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1)
    {
        public static C1? operator -(C1 x, C1 y)
        {
            System.Console.Write("operator1");
            return x;
        }
    }
}
 
public class C1
{}
 
class Program
{
    static void Main()
    {
        var x = new C1();
        C1 y = x -= x;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (23,16): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         C1 y = x -= x;
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x -= x").WithLocation(23, 16)
                );
        }
 
        [Fact]
        public void CompoundAssignment_110_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T)
    {
        public static T operator -(T x, T y)
        {
            return x;
        }
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x1 = null;
        C2? x2 = null;
        var y = new C2();
        (x1 -= y).ToString();
        (y -= x2).ToString();
        y.ToString();
        var z = new C2();
        (z -= z).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (24,10): warning CS8602: Dereference of a possibly null reference.
                //         (x1 -= y).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1 -= y").WithLocation(24, 10),
                // (25,10): warning CS8602: Dereference of a possibly null reference.
                //         (y -= x2).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y -= x2").WithLocation(25, 10),
                // (26,9): warning CS8602: Dereference of a possibly null reference.
                //         y.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(26, 9)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().ToArray();
 
            Assert.Equal(3, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator -(C2?, C2?)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator -(C2?, C2?)", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2>(C2).operator -(C2, C2)", model.GetSymbolInfo(opNodes[2]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void CompoundAssignment_111_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T)
    {
        public static T operator -(T x, int y)
        {
            return x;
        }
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        var y = new C2();
        (x -= 1).ToString();
        (y -= 1).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (23,10): warning CS8602: Dereference of a possibly null reference.
                //         (x -= 1).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x -= 1").WithLocation(23, 10)
                );
        }
 
        [Fact]
        public void CompoundAssignment_112_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T, S>(C1<T>) where T : new() where S : new()
    {
        public static C1<T> operator -(C1<T> x, C1<S> y)
        {
            return x;
        }
    }
}
 
public class C1<T> where T : new()
{
    public T F = new T();
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        var y = Get(new C2());
 
        (x -= y).F.ToString();
        (y -= x).F.ToString();
    }
 
    static C1<T> Get<T>(T x) where T : new()
    {
        return new C1<T>();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (29,9): warning CS8602: Dereference of a possibly null reference.
                //         (x -= y).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(x -= y).F").WithLocation(29, 9)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().ToArray();
 
            Assert.Equal(2, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?, C2>(C1<C2?>).operator -(C1<C2?>, C1<C2>)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2, C2?>(C1<C2>).operator -(C1<C2>, C1<C2?>)", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void CompoundAssignment_113_NullableAnalysis_Lifted()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(S1<T>) where T : new()
    {
        public static S1<T> operator -(S1<T> x, int y)
        {
            return x;
        }
    }
}
 
public struct S1<T> where T : new()
{
    public T F;
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null) -= 1;
 
        if (x != null)
            x.Value.F.ToString();
 
        var y = Get(new C2()) -= 1;
 
        if (y != null)
            y.Value.F.ToString();
    }
 
    static ref S1<T>? Get<T>(T x) where T : new()
    {
        throw null!;
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (29,13): warning CS8602: Dereference of a possibly null reference.
                //             x.Value.F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Value.F").WithLocation(29, 13)
                );
        }
 
        [Fact]
        public void CompoundAssignment_114_NullableAnalysis_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T) where T : notnull
    {
        public static C2 operator -(T x, T y)
        {
            return (C2)(object)x;
        }
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        var y = new C2();
        (x -= y).ToString();
        x = null;
#line 24
        (y -= x).ToString();
 
        var z = new C2();
        (z -= z).ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (23,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(T)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (x -= y).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "x -= y").WithArguments("Extensions1.extension<T>(T)", "T", "C2?").WithLocation(23, 10),
                // (24,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(T)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (y -= x).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "y -= x").WithArguments("Extensions1.extension<T>(T)", "T", "C2?").WithLocation(24, 10)
                );
        }
 
        [Fact]
        public void CompoundAssignment_115_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1 x)
    {
        public void operator -=(C1 y) {}
    }
 
    extension(C2? x)
    {
        public void operator -=(C2? y) {}
    }
}
 
public class C1
{}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C1? x1 = null;
        C1? x2 = null;
        C1 y = new C1();
#line 25
        _ = x1 -= y;
        y = y -= x2;
 
        C2? z = null;
        _ = z -= z;
 
        C2 a = new C2();
        C2? b = null;
        C2 c = a -= b;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (25,13): warning CS8604: Possible null reference argument for parameter 'x' in 'extension(C1)'.
                //         _ = x1 -= y;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "extension(C1)").WithLocation(25, 13),
                // (26,18): warning CS8604: Possible null reference argument for parameter 'y' in 'void extension(C1).operator -=(C1 y)'.
                //         y = y -= x2;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("y", "void extension(C1).operator -=(C1 y)").WithLocation(26, 18)
                );
        }
 
        [Fact]
        public void CompoundAssignment_116_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
using System.Diagnostics.CodeAnalysis;
 
public static class Extensions1
{
    extension([NotNull] ref S1? x)
    {
        public void operator -=(int y) { throw null!; }
    }
 
    extension([NotNull] C2? x)
    {
        public void operator -=(int y) { throw null!; }
    }
}
 
public struct S1
{}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        S1? x = null;
        var x1 = x -= 1;
        _ = x.Value;
        _ = x1.Value;
 
        C2? z = null;
        var z1 = z -= 1;
        z.ToString();
        z1.ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_117_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(ref S1? x)
    {
        public void operator -=(int y) {}
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        S1? x = null;
        var x1 = x -= 1;
        _ = x.Value;
        _ = x1.Value;
 
        S1? y = new S1();
        var y1 = y -= 1;
        _ = y.Value;
        _ = y1.Value;
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (20,13): warning CS8629: Nullable value type may be null.
                //         _ = x.Value;
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(20, 13),
                // (21,13): warning CS8629: Nullable value type may be null.
                //         _ = x1.Value;
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x1").WithLocation(21, 13),
                // (25,13): warning CS8629: Nullable value type may be null.
                //         _ = y.Value;
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(25, 13),
                // (26,13): warning CS8629: Nullable value type may be null.
                //         _ = y1.Value;
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y1").WithLocation(26, 13)
                );
        }
 
        [Fact]
        public void CompoundAssignment_118_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(ref S1? x)
    {
        public void operator -=(int y) {}
    }
}
 
public struct S1
{}
 
class Program
{
    static void Main()
    {
        _ = Get(new S1()).Value;
        var y1 = Get(new S1()) -= 1;
#line 26
        _ = y1.Value;
    }
 
    [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("x")]
    static ref S1? Get(S1? x) => throw null!;
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (26,13): warning CS8629: Nullable value type may be null.
                //         _ = y1.Value;
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y1").WithLocation(26, 13)
                );
        }
 
        [Fact]
        public void CompoundAssignment_119_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C1Base x)
    {
        public void operator -=(int y) {}
    }
 
    extension(C2Base? x)
    {
        public void operator -=(int y) {}
    }
}
 
public class C1Base {}
public class C1 : C1Base {}
 
public class C2Base {}
public class C2 : C2Base {}
 
class Program
{
    static void Main()
    {
        C1? x = null;
        var x1 = x -= 1;
        x.ToString();
        x1.ToString();
 
        C1 y = new C1();
        var y1 = y -= 1;
        y.ToString();
        y1.ToString();
 
        C2? z = null;
        var z1 = z -= 1;
        z.ToString();
        z1.ToString();
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (27,18): warning CS8604: Possible null reference argument for parameter 'x' in 'extension(C1Base)'.
                //         var x1 = x -= 1;
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "extension(C1Base)").WithLocation(27, 18),
                // (38,9): warning CS8602: Dereference of a possibly null reference.
                //         z.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(38, 9),
                // (39,9): warning CS8602: Dereference of a possibly null reference.
                //         z1.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z1").WithLocation(39, 9)
                );
        }
 
        [Fact]
        public void CompoundAssignment_120_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension(C2Base<string> x)
    {
        public void operator -=(int y) {}
    }
}
 
public class C2Base<T> {}
public class C2<T> : C2Base<T> {}
 
class Program
{
    static void Main()
    {
        C2<string?> z = new C2<string?>();
        var z1 = z -= 1;
        z.ToString();
        z1.ToString();
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (19,18): warning CS8620: Argument of type 'C2<string?>' cannot be used for parameter 'x' of type 'C2Base<string>' in 'extension(C2Base<string>)' due to differences in the nullability of reference types.
                //         var z1 = z -= 1;
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("C2<string?>", "C2Base<string>", "x", "extension(C2Base<string>)").WithLocation(19, 18)
                );
        }
 
        [Fact]
        public void CompoundAssignment_121_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
using System.Diagnostics.CodeAnalysis;
 
public static class Extensions1
{
    extension([NotNull] C2Base? x)
    {
        public void operator -=(int y) { throw null!; }
    }
}
 
public class C2Base
{}
 
public class C2 : C2Base
{}
 
class Program
{
    static void Main()
    {
        C2? z = null;
        var z1 = z -= 1;
        z.ToString();
        z1.ToString();
    }
}
""";
 
            var comp = CreateCompilation(src, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
        }
 
        [Fact]
        public void CompoundAssignment_122_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T x) where T : class?
    {
        public void operator -=(int y) {}
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        (x -= 1).ToString();
        var y = new C2();
        (y -= 1).ToString();
    }
}
""";
 
            var comp = CreateCompilation([src, CompilerFeatureRequiredAttribute], options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (19,10): warning CS8602: Dereference of a possibly null reference.
                //         (x -= 1).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x -= 1").WithLocation(19, 10)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().ToArray();
 
            Assert.Equal(2, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?>(C2?).operator -=(int)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2>(C2).operator -=(int)", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void CompoundAssignment_123_NullableAnalysis()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(C1<T> x) where T : new()
    {
        public void operator -=(int y) {}
    }
}
 
public class C1<T> where T : new()
{
    public T F = new T();
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        (x -= 1).F.ToString();
        var y = Get(new C2());
        (y -= 1).F.ToString();
    }
 
    static C1<T> Get<T>(T x) where T : new()
    {
        return new C1<T>();
    }
}
""";
 
            var comp = CreateCompilation([src, CompilerFeatureRequiredAttribute], options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (24,9): warning CS8602: Dereference of a possibly null reference.
                //         (x -= 1).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(x -= 1).F").WithLocation(24, 9)
                );
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var opNodes = tree.GetRoot().DescendantNodes().OfType<Syntax.AssignmentExpressionSyntax>().ToArray();
 
            Assert.Equal(2, opNodes.Length);
            AssertEx.Equal("Extensions1.extension<C2?>(C1<C2?>).operator -=(int)", model.GetSymbolInfo(opNodes[0]).Symbol.ToDisplayString());
            AssertEx.Equal("Extensions1.extension<C2>(C1<C2>).operator -=(int)", model.GetSymbolInfo(opNodes[1]).Symbol.ToDisplayString());
        }
 
        [Fact]
        public void CompoundAssignment_124_NullableAnalysis_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(T x) where T : class
    {
        public void operator -=(int y) {}
    }
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        C2? x = null;
        (x -= 1).ToString();
        var y = new C2();
        (y -= 1).ToString();
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (19,10): warning CS8634: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(T)'. Nullability of type argument 'C2?' doesn't match 'class' constraint.
                //         (x -= 1).ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "x -= 1").WithArguments("Extensions1.extension<T>(T)", "T", "C2?").WithLocation(19, 10),
                // (19,10): warning CS8602: Dereference of a possibly null reference.
                //         (x -= 1).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x -= 1").WithLocation(19, 10)
                );
        }
 
        [Fact]
        public void CompoundAssignment_125_NullableAnalysis_Constraints()
        {
            var src = $$$"""
#nullable enable
 
public static class Extensions1
{
    extension<T>(C1<T> x) where T : notnull, new()
    {
        public void operator -=(int y) {}
    }
}
 
public class C1<T> where T : new()
{
    public T F = new T();
}
 
public class C2
{}
 
class Program
{
    static void Main()
    {
        var x = Get((C2?)null);
        (x -= 1).F.ToString();
        var y = Get(new C2());
        (y -= 1).F.ToString();
    }
 
    static C1<T> Get<T>(T x) where T : new()
    {
        return new C1<T>();
    }
}

""" + CompilerFeatureRequiredAttribute;
 
            var comp = CreateCompilation(src, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (24,9): warning CS8602: Dereference of a possibly null reference.
                //         (x -= 1).F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(x -= 1).F").WithLocation(24, 9),
                // (24,10): warning CS8714: The type 'C2?' cannot be used as type parameter 'T' in the generic type or method 'Extensions1.extension<T>(C1<T>)'. Nullability of type argument 'C2?' doesn't match 'notnull' constraint.
                //         (x -= 1).F.ToString();
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "x -= 1").WithArguments("Extensions1.extension<T>(C1<T>)", "T", "C2?").WithLocation(24, 10)
                );
        }
    }
}