Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CallerInfo attributes are emitted to metadata even when they are ignored in source #73482

Open
RikkiGibson opened this issue May 15, 2024 · 3 comments

Comments

@RikkiGibson
Copy link
Contributor

RikkiGibson commented May 15, 2024

Version Used: fca6e1f

Steps to Reproduce:

        [Fact, WorkItem(531044, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531044")]
        public void TestUnconsumedCallerInfoAttributes()
        {
            string source = @"
using System.Runtime.CompilerServices;

partial class D
{
    partial void Goo(int line, string member, string path);
}

partial class D
{
    partial void Goo(
        [CallerLineNumber] int line,
        [CallerMemberName] string member,
        [CallerFilePath] string path) { }

    public static void Main()
    {
    }
}";

            CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
                // (12,10): warning CS4024: The CallerLineNumberAttribute applied to parameter 'line' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //         [CallerLineNumber] int line,
                Diagnostic(ErrorCode.WRN_CallerLineNumberParamForUnconsumedLocation, "CallerLineNumber").WithArguments("line"),
                // (13,10): warning CS4026: The CallerMemberNameAttribute applied to parameter 'member' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //         [CallerMemberName] string member,
                Diagnostic(ErrorCode.WRN_CallerMemberNameParamForUnconsumedLocation, "CallerMemberName").WithArguments("member"),
                // (14,10): warning CS4025: The CallerFilePathAttribute applied to parameter 'path' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //         [CallerFilePath] string path) { }
                Diagnostic(ErrorCode.WRN_CallerFilePathParamForUnconsumedLocation, "CallerFilePath").WithArguments("path"));
            
            CompileAndVerify(source, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: verify);

            void verify(ModuleSymbol module)
            {
                // These are ignored in source but they still get written out to metadata.
                // This means if the method is accessible from another compilation, then the attribute will be respected there, but not in the declaring compilation.
                var goo = module.GlobalNamespace.GetMember<MethodSymbol>("D.Goo");
                AssertEx.Equal(["System.Runtime.CompilerServices.CallerLineNumberAttribute"], goo.Parameters[0].GetAttributes().SelectAsArray(attr => attr.ToString()));
                AssertEx.Equal(["System.Runtime.CompilerServices.CallerMemberNameAttribute"], goo.Parameters[1].GetAttributes().SelectAsArray(attr => attr.ToString()));
                AssertEx.Equal(["System.Runtime.CompilerServices.CallerFilePathAttribute"], goo.Parameters[2].GetAttributes().SelectAsArray(attr => attr.ToString()));
            }
        }

Expected Behavior: Attributes which are ignored in source are not emitted to metadata

Actual Behavior: Attributes which are ignored in source are emitted to metadata

The C# standard says:

It is an error to have the same caller-info attribute on a parameter of both the defining and implementing part of a partial method declaration. Only caller-info attributes in the defining part are applied, whereas caller-info attributes occurring only in the implementing part are ignored.

My interpretation of the standard is that the attributes in the implementing part are expected to be completely dropped, and not emitted to metadata.

The effect of this bug is that if the method with CallerInfo attributes were used via metadata reference in another compilation, those attributes would be respected in the other compilation, but not in the declaring one.

This is just one of those weird old behaviors that nobody ever noticed, and unless someone tells me it is important to change it, I am planning to deliver the same weird old behavior for partial properties.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels May 15, 2024
@RikkiGibson RikkiGibson changed the title CallerInfo attributes are emitted to data even when they are ignored in source CallerInfo attributes are emitted to metadata even when they are ignored in source May 15, 2024
@jaredpar
Copy link
Member

This is 10-15 year old behavior now. Can't see a good reason for changing. Think we should keep the behavior and document it

@RikkiGibson
Copy link
Contributor Author

Can this issue itself be the documentation, or is there some "known spec violations" doc we should also dig up and add this to?

@jjonescz
Copy link
Contributor

We have this: https://github.com/dotnet/roslyn/blob/main/docs/compilers/CSharp/Deviations%20from%20Standard.md

@jaredpar jaredpar added Documentation and removed untriaged Issues and PRs which have not yet been triaged by a lead labels May 20, 2024
@jaredpar jaredpar added this to the Backlog milestone May 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants