Skip to content

Injected NonNullTypesAttribute: Duplicate diagnostics and tightening a module scenario #29732

@jcouv

Description

@jcouv

Some follow-up issues from #29180

  • The GenerateMethodBody implementation in both injected symbols accumulates diagnostics every time we try to emit. (details)
        [Fact]
        public void NonNullTypesAttribute_WithBadAttributeConstructor()
        {
            var source = @"
namespace System
{
    public class Object { }
    public struct Void { }
    public class Attribute { public Attribute(bool ignored) { } }
    public class ValueType { }
    public struct Boolean { }
    public class String { }
    public class Enum { }
    public struct Int32 { }
    public class AttributeUsageAttribute : Attribute
    {
        public AttributeUsageAttribute(AttributeTargets validOn) : base(true) => throw null;
        public bool AllowMultiple { get; set; }
    }
    public enum AttributeTargets { Assembly = 1, Module = 2, Class = 4, Struct = 8,
        Enum = 16, Constructor = 32, Method = 64, Property = 128, Field = 256,
        Event = 512, Interface = 1024, Parameter = 2048, Delegate = 4096, ReturnValue = 8192,
        GenericParameter = 16384, All = 32767 }
}
";
            var comp = CreateEmptyCompilation(new[] { source, NonNullTypesTrue });
            comp.VerifyEmitDiagnostics(CodeAnalysis.Emit.EmitOptions.Default.WithRuntimeMetadataVersion("v4.0.30319"),
                // error CS1729: 'Attribute' does not contain a constructor that takes 0 arguments
                Diagnostic(ErrorCode.ERR_BadCtorArgCount).WithArguments("System.Attribute", "0").WithLocation(1, 1),
                // error CS1729: 'Attribute' does not contain a constructor that takes 0 arguments
                Diagnostic(ErrorCode.ERR_BadCtorArgCount).WithArguments("System.Attribute", "0").WithLocation(1, 1));

            comp.VerifyEmitDiagnostics(CodeAnalysis.Emit.EmitOptions.Default.WithRuntimeMetadataVersion("v4.0.30319"),
                // error CS1729: 'Attribute' does not contain a constructor that takes 0 arguments
                Diagnostic(ErrorCode.ERR_BadCtorArgCount).WithArguments("System.Attribute", "0").WithLocation(1, 1),
                // error CS1729: 'Attribute' does not contain a constructor that takes 0 arguments
                Diagnostic(ErrorCode.ERR_BadCtorArgCount).WithArguments("System.Attribute", "0").WithLocation(1, 1),
                // error CS1729: 'Attribute' does not contain a constructor that takes 0 arguments
                Diagnostic(ErrorCode.ERR_BadCtorArgCount).WithArguments("System.Attribute", "0").WithLocation(1, 1),
                // error CS1729: 'Attribute' does not contain a constructor that takes 0 arguments
                Diagnostic(ErrorCode.ERR_BadCtorArgCount).WithArguments("System.Attribute", "0").WithLocation(1, 1));
        }
  • The injected symbols are also subject to a race condition which could produce duplicate diagnostics. (details)
        public override ImmutableArray<CSharpAttributeData> GetAttributes()
        {
            if (_lazyCustomAttributes.IsDefault)
            {
                ImmutableInterlocked.InterlockedInitialize(ref _lazyCustomAttributes, MakeAttributes());
            }
            return _lazyCustomAttributes;
        }
  • We also want to tighten the guarantee that looking up injected symbols cannot yield symbols from a referenced assembly or an added module. They should only come from the injected declaration or from source. (reference)
        [Fact(Skip = "https://github.com/dotnet/roslyn/issues/29732 Crashing")]
        public void EmbeddedAttributeInAddedModule_Injected()
        {
            var code = "[module: System.Runtime.CompilerServices.NonNullTypes]";

            var module = CreateCompilation(code, options: TestOptions.ReleaseModule);
            var reference = ModuleMetadata.CreateFromImage(module.EmitToArray()).GetReference();

            var comp = CreateCompilation(code, references: new[] { reference });
            comp.VerifyEmitDiagnostics();
        }

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions