Repository: dotnet/roslyn
File: src/Compilers/CSharp/Test/CSharp15/ExtensionIndexersTests.cs (C#)

Code before:
            // (18,24): error CS8337: The first parameter of a 'ref' extension method 'M2' must be a value type or a generic type constrained to struct.
            //     public static void M2(this ref C c) { }
            Diagnostic(ErrorCode.ERR_RefExtensionMustBeValueTypeOrConstrainedToOne, "M2").WithArguments("M2").WithLocation(18, 24));
    }

    [Fact]
    public void Dynamic_01()
    {
        var src = """
dynamic d = new object();
_ = new object()[d];
_ = new object().M(d);

static class E
{
    extension(object o)
    {
        public int this[object o2] { get => 0; }
        public void M(object o2) { }
    }
}
""";
        // PROTOTYPE extension indexer access with dynamic argument should be disallowed
        var comp = CreateCompilation(src, targetFramework: TargetFramework.Net100);
        comp.VerifyEmitDiagnostics(
            // (3,5): error CS1973: 'object' has no applicable method named 'M' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
            // _ = new object().M(d);
            Diagnostic(ErrorCode.ERR_BadArgTypeDynamicExtension, "new object().M(d)").WithArguments("object", "M").WithLocation(3, 5));
    }

    [Fact]
    public void Dynamic_04()
    {
        var src = """
int i = 42;
_ = i[i];

static class E
{
    extension(object o)
    {
        public int this[dynamic d] { get { System.Console.Write(d); return 0; } }
    }
}
""";
        var comp = CreateCompilation(src, targetFramework: TargetFramework.Net100);
        CompileAndVerify(comp, expectedOutput: ExpectedOutput("42"), verify: Verification.FailsPEVerify).VerifyDiagnostics();
    }

    [Fact]
    public void Dynamic_05()

Review comment (suggestion):
>// (2,5): error CS0021: Cannot apply indexing with [] to an expression of type 'object' [](http://example.com/codeflow?start=12&length=87)

Do we have a test covering scenario of a dynamic receiver? Is behavior consistent with classic and new extension methods, and extension properties as well? #Resolved

Code after:
            // (18,24): error CS8337: The first parameter of a 'ref' extension method 'M2' must be a value type or a generic type constrained to struct.
            //     public static void M2(this ref C c) { }
            Diagnostic(ErrorCode.ERR_RefExtensionMustBeValueTypeOrConstrainedToOne, "M2").WithArguments("M2").WithLocation(18, 24));
    }

    [Fact]
    public void Dynamic_01()
    {
        var src = """
dynamic d = new object();
_ = new object()[d];
_ = new object().M(d);

static class E
{
    extension(object o)
    {
        public int this[object o2] { get => 0; }
        public void M(object o2) { }
    }
}
""";
        // PROTOTYPE diagnostic quality, consider a dedicated error when extension indexer is found given dynamic argument
        var comp = CreateCompilation(src, targetFramework: TargetFramework.Net100);
        comp.VerifyEmitDiagnostics(
            // (2,5): error CS0021: Cannot apply indexing with [] to an expression of type 'object'
            // _ = new object()[d];
            Diagnostic(ErrorCode.ERR_BadIndexLHS, "new object()[d]").WithArguments("object").WithLocation(2, 5),
            // (3,5): error CS1973: 'object' has no applicable method named 'M' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
            // _ = new object().M(d);
            Diagnostic(ErrorCode.ERR_BadArgTypeDynamicExtension, "new object().M(d)").WithArguments("object", "M").WithLocation(3, 5));

        var tree = comp.SyntaxTrees[0];
        var model = comp.GetSemanticModel(tree);
        var indexerAccess = GetSyntax<ElementAccessExpressionSyntax>(tree, "new object()[d]");
        Assert.Null(model.GetSymbolInfo(indexerAccess).Symbol);
        Assert.Equal([], model.GetSymbolInfo(indexerAccess).CandidateSymbols.ToDisplayStrings());

        var invocation = GetSyntax<InvocationExpressionSyntax>(tree, "new object().M(d)");
        Assert.Null(model.GetSymbolInfo(invocation).Symbol);
        Assert.Equal([], model.GetSymbolInfo(invocation).CandidateSymbols.ToDisplayStrings());
    }

    [Fact]
    public void Dynamic_02()
    {
        var src = """
dynamic d = new object();
_ = new C()[d];
_ = new C().M(d);