dotnet / dotnet/roslyn

Unexpected semantic information from bad method group conversion in local declaration

Open
#75,833 2 comments 0 reactions 0 assignees View on GitHub
Area-Compilers
Dominant language
C#
Stars
20.7k
Forks
4.3k
PR merge metrics
PR metrics pending

Description

There's also similar issue in assignment and possibly in invocations. See tests that refer to this issue.

```csharp

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75833")]
public void GetSymbolInfo_ImplicitUserDefinedConversionOnMethodGroup_InLocalDeclaration()
{
var src = """
public class C
{
public static void M()
{
C x = C.Test;
}

public static int Test() => 1;

public static implicit operator C(System.Func intDelegate)
{
return new C();
}
}
""";
var comp = CreateCompilation(src);
comp.VerifyEmitDiagnostics(
// (5,17): error CS0428: Cannot convert method group 'Test' to non-delegate type 'C'. Did you intend to invoke the method?
// C x = C.Test;
Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "Test").WithArguments("Test", "C").WithLocation(5, 17));

var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var memberAccess = GetSyntax(tree, "C.Test");
Assert.Equal("C C.op_Implicit(System.Func intDelegate)", model.GetSymbolInfo(memberAccess).Symbol.ToTestDisplayString()); // Unexpected: Should be null
var conversion = model.GetConversion(memberAccess);
Assert.Equal(ConversionKind.ExplicitUserDefined, conversion.Kind); // Unexpected: Should be NoConversion or possibly Identity for error case
Assert.Equal(ConversionKind.MethodGroup, conversion.UserDefinedFromConversion.Kind);
Assert.Equal(ConversionKind.Identity, conversion.UserDefinedToConversion.Kind);
}

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75833")]
public void GetSymbolInfo_ImplicitUserDefinedConversionOnMethodGroup_WithToConversion_InLocalDeclaration()
{
var src = """
public struct C
{
public static void M()
{
C? x = C.Test;
}

public static int Test() => 1;

public static implicit operator C(System.Func intDelegate)
{
return new C();
}
}
""";
var comp = CreateCompilation(src);
comp.VerifyEmitDiagnostics(
// (5,18): error CS0428: Cannot convert method group 'Test' to non-delegate type 'C?'. Did you intend to invoke the method?
// C? x = C.Test;
Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "Test").WithArguments("Test", "C?").WithLocation(5, 18));

var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var memberAccess = GetSyntax(tree, "C.Test");
Assert.Null(model.GetSymbolInfo(memberAccess).Symbol);
var conversion = model.GetConversion(memberAccess);
Assert.Equal(ConversionKind.ExplicitUserDefined, conversion.Kind); // Unexpected: Should be NoConversion or possibly Identity for error case
Assert.Equal(ConversionKind.MethodGroup, conversion.UserDefinedFromConversion.Kind);
Assert.Equal(ConversionKind.Identity, conversion.UserDefinedToConversion.Kind);
}

```

Contributor guide

Open the contributing guide

Research direction

Start with the two named tests, GetSymbolInfo_ImplicitUserDefinedConversionOnMethodGroup_InLocalDeclaration and GetSymbolInfo_ImplicitUserDefinedConversionOnMethodGroup_WithToConversion_InLocalDeclaration, and trace CreateCompilation, GetSymbolInfo, and GetConversion behavior. Compare the local-declaration case with the mentioned assignment and invocation cases; done means the diagnostics remain correct and the semantic symbol and conversion results match the intended error-case expectations.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.