[Bug]: AotConverterGenerator emits conversions through [Obsolete(error: true)] operators, failing the build with CS0619

Closed Beginner friendly
#7,316 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
csharp
Domain
testing

Research direction

The conversions are collected in CollectConversionsForType and filtered in GetConversionInfoFromSymbol in src/TUnit.Core.SourceGenerator/Generators/AotConverterGenerator.cs, which already skips other non-emittable operators but ignores ObsoleteAttribute. Reproduce with the Token repro in the issue to see the CS0619 at the generated AotConverters.g.cs. Done when that build succeeds, operators marked [Obsolete(error: true)] are no longer emitted, and the other conversions still work.

Written by the indexing model from the issue text.

Description

bug P2
Bug report checklist
  • Searched existing issues and pull requests, no duplicate found
  • Searched the documentation, nothing describes this as expected behavior
  • Using the latest version of TUnit
Description

AotConverterGenerator emits a conversion through every conversion operator of a test parameter's type, including one marked [Obsolete("...", error: true)]. The generated code then fails the build with CS0619, although the test code never uses that operator.

Expected Behavior

The project builds. Operators with [Obsolete(error: true)] are skipped, since generated code that uses them cannot compile.

Actual Behavior

The build fails with CS0619 in AotConverters.g.cs. Line 41 of that file, in the converter generated for char:

global::Repro.Token converted = sourceTypedValue;
Steps to Reproduce

Repro.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <OutputType>Exe</OutputType>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="TUnit" Version="1.77.0" />
  </ItemGroup>

</Project>

Tests.cs:

namespace Repro;

public readonly record struct Token(string Value)
{
    public static implicit operator Token(string value) => new(value);

    [Obsolete("Use a string.", error: true)]
    public static implicit operator Token(char value) => new(value.ToString());
}

public class TokenTests
{
    [Test]
    [Arguments("abc")]
    public async Task Value_IsKept(Token token)
    {
        await Assert.That(token.Value).IsEqualTo("abc");
    }
}

Run dotnet build.

TUnit Version

1.77.0, also reproduced on 1.76.45

.NET Version

SDK 11.0.100-rc.3.26522.148, targeting net10.0 and net11.0

Operating System

Windows

IDE / Test Runner

dotnet CLI (dotnet build and dotnet run)

Error Output / Stack Trace
obj\Debug\net10.0\TUnit.Core.SourceGenerator\TUnit.Core.SourceGenerator.Generators.AotConverterGenerator\AotConverters.g.cs(41,49): error CS0619: 'Token.implicit operator Token(char)' is obsolete: 'Use a string.'
Additional Context

No AOT or trimming is involved, a plain build fails.

Checked on 1.77.0 with variations of the repro:

  • [MethodDataSource] instead of [Arguments]: same error.
  • A tuple parameter (Token Token, int Length): same error, because the generator also walks the type arguments.
  • An explicit operator instead of implicit: same error.
  • [Obsolete] without error: true: builds, because the generated file has #pragma warning disable.
  • Without the blocked operator: builds and the test passes.

Source (main is identical to v1.77.0 for this file):

  • CollectConversionsForType selects operators by name, IsStatic and parameter count only. The recursion into type arguments is a few lines below.
  • GetConversionInfoFromSymbol already skips operators that cannot be emitted (open generics, ref-like types, pointers, inaccessible types), but does not look at ObsoleteAttribute. That seems the natural place for the check.
IDE-Specific Issue?
  • Occurs with dotnet build and dotnet run, not only in an IDE
Dominant language
C#
Stars
4k
Forks
139
Avg merge
8h 50m
Merged PRs (30d)
255

Getting set up

Open in Codespaces

Starts the project's dev container in your browser, under your own GitHub account.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from thomhurst/TUnit

All issues in thomhurst/TUnit

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.