Repository navigation
fix(sourcegen): emit typeof(Nullable<>) for a T? parameter of a generic test method - #7322
Conversation
|
Important Review skippedReview was skipped as selected files did not have any reviewable changes.
|
| Layer / File(s) | Summary |
|---|---|
Nullable generic metadata and regression coverage src/TUnit.Core.SourceGenerator/CodeGenerationHelpers.cs, tests/TUnit.TestProject/Bugs/_7197/NullableValueTypeGenericMethodTests.cs, tests/TUnit.Core.SourceGenerator.Tests/Bugs/7197/Tests7197.cs, tests/TUnit.Core.SourceGenerator.Tests/Tests7197.Test.verified.txt |
The generator emits typeof(global::System.Nullable<>) when a constructed generic type contains generic parameters. The regression test covers Run<int>(1, null) and its generated test registration. |
Test fixture compatibility
| Layer / File(s) | Summary |
|---|---|
Readonly struct fixture tests/TUnit.Core.SourceGenerator.Tests/AotConverterScanTests.cs |
The fixture replaces its positional record struct with a readonly struct and explicit constructor. |
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix · Severity of issue fixed: Medium
Possibly related issues
- Red main: AotConverterScanTests.SkipsConversionsBlockedByObsoleteError fails on net472 (IsExternalInit) #7329 — The fixture change removes the record struct that required
IsExternalInit, matching the reported .NET Framework test build failure.
Possibly related PRs
- thomhurst/TUnit#7319 — Both changes address the
IsExternalInitrequirement in the same test fixture; this PR replaces the record struct, while#7319adds polyfills. - thomhurst/TUnit#7317 — Both changes modify the same obsolete-conversion test fixture; this PR changes the struct form used by that regression test.
Suggested labels: PATCH
Merge Risk: 
Minimal · previous review a8474
-
The nullable generic metadata fix and net472-compatible fixture change present no identified merge-blocking risk.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passed-
Full details: Linked Issues check
-
Explanation
Objective [
#7197]: generated code for a generic test method with a T? (Nullable<T>) parameter, where T : struct, must compile and run as Run<int>(1, null). The diff at src/TUnit.Core.SourceGenerator/CodeGenerationHelpers.cs (GenerateTypeInfo, hasGenericParameters branch) emits typeof(global::System.Nullable<>) when namedType.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T. Other generic definitions keep GetTypeOfExpression(ConstructUnboundGenericType()). This removes the typeof(T?) expression that referenced T outside the method scope. The PR adds the repro test at tests/TUnit.TestProject/Bugs/_7197/NullableValueTypeGenericMethodTests.cs and the Tests7197 snapshot (Tests7197.Test.verified.txt). The snapshot shows the registered metadata and an invocation that casts arguments to int and int? and calls Run<int>. The build and test results (net10.0 source-gen and --reflection modes; 863 generator tests on four frameworks) are author-reported. I did not rebuild or rerun them. The code evidence supports the requirement.
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 1 functions across 4 files. (1 skipped: 1 unsupported.)
-
Full details: Out of Scope Changes check
-
Explanation
The change to tests/TUnit.Core.SourceGenerator.Tests/AotConverterScanTests.cs has no connection to
#7197. It replaces the record struct Token in the SkipsConversionsBlockedByObsoleteError fixture with a plain readonly struct, to fix a net472 CS0518 IsExternalInit build failure. That failure concerns a different test fixture and a different target framework. It does not concern nullable parameter metadata generation. The PR description states that this change fixes a red main build. That is a separate concern from the linked issue. The source generator fix, the repro test, and the Tests7197 snapshot are in scope and are connected to the objective.Resolution
Remove the AotConverterScanTests.cs change from this PR and submit it in a separate pull request that references the failing test (AotConverterScanTests.SkipsConversionsBlockedByObsoleteError) and the red modularpipeline (windows-latest) run. Keep the CodeGenerationHelpers.cs fix, the Tests7197 snapshot, and the Bugs/_7197 repro test in this PR.
-
Finishing Touches
-
Generate docstrings
-
- Commit to this branch
- Create a new PR
Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
A rabbit checks the generic type,
Where nullable values take their shape.
The tests now follow int and null,
And structs compile without record rules.
The source is ready, neat and bright.
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Review: LGTM.
Optional: the |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
[Medium impact] The PR appears safe to merge. SummaryFixes generated metadata for
No actionable issues were found. Reviews (2) · Last reviewed commit: "fix(sourcegen): emit typeof(Nullable<>) ..." · Reviewed by Greptile |
ReviewThe fix is correct and small. Checking
Optional follow-up: the special case sits at one call site. If other places build No blocking issues. LGTM. |
…ic test method (#7197) The display format shortens an unbound Nullable<> to 'T?', so the parameter's ConstructedGeneric TypeInfo emitted typeof(T?) outside T's scope (CS0246). Also fix AotConverterScanTests.SkipsConversionsBlockedByObsoleteError on net472, which failed because a record struct needs IsExternalInit.
a8474e3 to
b782124
Compare
|
I rebased onto On the new base, the I turned auto-merge off before force-pushing. It should be re-armed once |
ReviewThe fix is correct and minimal. Tests: there is an engine repro in Non-blocking suggestion: the same problem could affect other open generics that the display format abbreviates. Putting the open-definition printing in one helper, instead of special-casing at this call site, would make that harder to miss. I found no other affected case here. LGTM. |
Closes #7197
Summary
A generic test method with a
T?parameter, whereT : struct, made the source generator emit code that did not compile:Cause
CodeGenerationHelpers.GenerateTypeInfodescribes a parameter type that contains a type parameter as aConstructedGeneric, usingtypeof(<unbound definition>). It prints that definition withDisplayFormats.FullyQualifiedGenericWithGlobalPrefix, which shortens an unboundNullable<>toT?. The result,typeof(T?), is emitted outside the method, whereTdoesn't exist.Fix
For a
Nullable<T>definition, emittypeof(global::System.Nullable<>). I left the shared display format as it is because many other call sites use it.The generated parameter metadata is now:
Tests
tests/TUnit.TestProject/Bugs/_7197/NullableValueTypeGenericMethodTests.cs([EngineTest(ExpectedResult.Pass)]) is the repro from the issue. Before the fix the test project did not build. After the fix the test passes asRun<int>(1, null)in both source-gen and--reflectionmodes (net10.0, Release).Tests7197generator snapshot, which I reviewed. All 863TUnit.Core.SourceGenerator.Testspass on net10.0, net9.0, net8.0 and net472.Also fixed (red
main)The net472
AotConverterScanTestsfixture fix that was here is now onmainvia #7330, so after rebasing this PR no longer touches that file.Summary by CodeRabbit
nullto the same method and verify the nullable parameter is empty.