Skip to content

Logging Source Generator fails to compile due to CS0246 and CS0265 errors if type for generic constraint is in a different namespace #58550

@martincostello

Description

@martincostello

Description

If a containing class for a class used to provide the partial methods for the Logging Source Generator uses as class as a type constraint which is defined in another namespace, the project fails to compile with errors similar to the below.

Repro\Microsoft.Extensions.Logging.Generators\Microsoft.Extensions.Logging.Generators.LoggerMessageGenerator\LoggerMessage.g.cs(6,47): error CS0246: The type or namespace name 'Message' could not be found (are you missing a using directive or an assembly reference?) [Repro.csproj]
Repro\MessagePrinter.cs(6,26): error CS0265: Partial declarations of 'MessagePrinter<T>' have inconsistent constraints for type parameter 'T' [Repro.csproj]

If the type which is used for the type constraint of the class is in the same namespace, then project compiles and runs as expected.

The compilation errors can be worked around by using global using statements, such as:

<ItemGroup>
  <Using Include="Repro.AnotherNamespace" />
</ItemGroup>

Minimal repro

Repro.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <OutputType>Exe</OutputType>
    <RootNamespace>Repro</RootNamespace>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0-rc.1.21424.15" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0-rc.1.21424.15" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0-rc.1.21424.15" />
  </ItemGroup>
</Project>

Program.cs

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Repro;

using var serviceProvider = new ServiceCollection()
    .AddLogging(builder => builder.AddConsole())
    .BuildServiceProvider();

var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<MessagePrinter<Message>>();

var printer = new MessagePrinter<Message>(logger);
printer.Print(new() { Text = "Hello" });

Message.cs

namespace Repro.AnotherNamespace
{
    public class Message
    {
        public string? Text { get; set; }
    }
}

MessagePrinter.cs

using Microsoft.Extensions.Logging;
using Repro.AnotherNamespace;

namespace Repro
{
    public partial class MessagePrinter<T>
        where T : Message
    {
        private readonly ILogger _logger;

        public MessagePrinter(ILogger<MessagePrinter<T>> logger)
        {
            _logger = logger;
        }

        public void Print(T message)
        {
            Console.WriteLine(message);
            Log.Message(_logger, message.Text);
        }

        internal static partial class Log
        {
            [LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "The message is {Text}.")]
            internal static partial void Message(ILogger logger, string? text);
        }
    }
}

Expected Output

Repro> dotnet run
Repro.Message
info: Repro.MessagePrinter[1]
      The message is Hello.

Configuration

.NET SDK 6.0.100-rc.1.21424.38
Microsoft.Extensions.Logging 6.0.0-rc.1.21424.15

Regression?

No.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions