Make generated code compile without implicit usings - #4897
Make generated code compile without implicit usings#4897bernardnormier wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Updates generated Slice code to compile when consumers disable implicit usings.
Changes:
- Adds required framework namespaces to Slice generator preambles.
- Disables implicit usings across generator test projects and adds explicit test imports.
- Covers fixed-size tagged sequence and dictionary encoding.
Reviewed changes
Copilot reviewed 67 out of 67 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/ZeroC.Slice.Generator/Program.cs |
Adds collection and LINQ preamble imports. |
src/IceRpc.Slice.Generator/Program.cs |
Adds required framework preamble imports. |
tests/ZeroC.Slice.Generator.Tests/ZeroC.Slice.Generator.Tests.csproj |
Disables implicit usings. |
tests/ZeroC.Slice.Generator.Tests/WellKnownTypesTests.cs |
Adds explicit framework imports. |
tests/ZeroC.Slice.Generator.Tests/VariantEnumTests.cs |
Adds explicit System import. |
tests/ZeroC.Slice.Generator.Tests/TaggedTests.slice |
Adds fixed-size tagged collections. |
tests/ZeroC.Slice.Generator.Tests/TaggedTests.cs |
Tests tagged collection encoding and decoding. |
tests/ZeroC.Slice.Generator.Tests/StructTests.cs |
Adds explicit LINQ import. |
tests/ZeroC.Slice.Generator.Tests/SequenceDecodingTests.cs |
Adds explicit IO import. |
tests/ZeroC.Slice.Generator.Tests/EnumTests.cs |
Adds explicit framework imports. |
tests/ZeroC.Slice.Generator.Tests/DictionaryEncodingTests.cs |
Adds explicit collection and LINQ imports. |
tests/ZeroC.Slice.Generator.Tests/DictionaryDecodingTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Slice.Generator.Tests/TypeNameQualificationTests.cs |
Adds threading imports. |
tests/IceRpc.Slice.Generator.Tests/StructTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Slice.Generator.Tests/StreamTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Slice.Generator.Tests/ServiceTests.cs |
Adds threading imports. |
tests/IceRpc.Slice.Generator.Tests/SequenceMappingTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Slice.Generator.Tests/ProxyTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Slice.Generator.Tests/OperationTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Slice.Generator.Tests/OperationEncodingTests.cs |
Adds task import. |
tests/IceRpc.Slice.Generator.Tests/ModuleIdentifierTests.cs |
Adds threading imports. |
tests/IceRpc.Slice.Generator.Tests/InvokeOperationAsyncTests.cs |
Adds IO and task imports. |
tests/IceRpc.Slice.Generator.Tests/InvalidProxy.cs |
Adds explicit System import. |
tests/IceRpc.Slice.Generator.Tests/InterfaceTests.cs |
Adds explicit System import. |
tests/IceRpc.Slice.Generator.Tests/IdentifierAttributeTests.cs |
Adds threading imports. |
tests/IceRpc.Slice.Generator.Tests/IceRpc.Slice.Generator.Tests.csproj |
Disables implicit usings. |
tests/IceRpc.Slice.Generator.Tests/EnumTests.cs |
Adds explicit System import. |
tests/IceRpc.Slice.Generator.Tests/DictionaryMappingTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Slice.Generator.Tests/CustomSequence.cs |
Adds generic collections import. |
tests/IceRpc.Slice.Generator.Tests/CustomDictionary.cs |
Adds collection and LINQ imports. |
tests/IceRpc.Protobuf.Tests/StreamTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Protobuf.Tests/ServiceTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Protobuf.Tests/PipeReaderExtensionsTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Protobuf.Tests/OperationTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Protobuf.Tests/IceRpc.Protobuf.Tests.csproj |
Disables implicit usings. |
tests/IceRpc.Protobuf.Tests/AsyncStreamTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Ice.Generator.Tests/TypeNameQualificationTests.cs |
Adds threading imports. |
tests/IceRpc.Ice.Generator.Tests/StructTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Ice.Generator.Tests/ServiceTests.cs |
Adds threading imports. |
tests/IceRpc.Ice.Generator.Tests/SequenceMappingTests.cs |
Adds collection and task imports. |
tests/IceRpc.Ice.Generator.Tests/ProxyTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Ice.Generator.Tests/OperationTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Ice.Generator.Tests/InvokeOperationAsyncTests.cs |
Adds IO and task imports. |
tests/IceRpc.Ice.Generator.Tests/InvalidProxy.cs |
Adds explicit System import. |
tests/IceRpc.Ice.Generator.Tests/InterfaceTests.cs |
Adds explicit System import. |
tests/IceRpc.Ice.Generator.Tests/IdentifierAttributeTests.cs |
Adds threading imports. |
tests/IceRpc.Ice.Generator.Tests/IceRpc.Ice.Generator.Tests.csproj |
Disables implicit usings. |
tests/IceRpc.Ice.Generator.Tests/ExceptionTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Ice.Generator.Tests/DictionaryMappingTests.cs |
Adds collection and task imports. |
tests/IceRpc.Ice.Generator.Tests/CustomSequence.cs |
Adds explicit framework imports. |
tests/IceRpc.Ice.Generator.Tests/CsIdentifierOnModuleTests.cs |
Adds threading imports. |
tests/IceRpc.Ice.Generator.Tests/ClassTests.cs |
Adds explicit System import. |
tests/IceRpc.Ice.Generator.Base.Tests/TypeIdAttributeTests.cs |
Adds explicit System import. |
tests/IceRpc.Ice.Generator.Base.Tests/TaggedTests.cs |
Adds generic collections import. |
tests/IceRpc.Ice.Generator.Base.Tests/SlicingTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Ice.Generator.Base.Tests/SequenceMappingTests.cs |
Adds generic collections import. |
tests/IceRpc.Ice.Generator.Base.Tests/SequenceDecodingTests.cs |
Adds explicit IO import. |
tests/IceRpc.Ice.Generator.Base.Tests/IceRpc.Ice.Generator.Base.Tests.csproj |
Disables implicit usings. |
tests/IceRpc.Ice.Generator.Base.Tests/EnumTests.cs |
Adds explicit System import. |
tests/IceRpc.Ice.Generator.Base.Tests/CustomSequence.cs |
Adds explicit framework imports. |
tests/IceRpc.Ice.Generator.Base.Tests/ClassTests.cs |
Adds explicit IO import. |
tests/IceRpc.Ice.Generator.Base.Tests/ActivatorTests.cs |
Adds explicit framework imports. |
tests/IceRpc.Ice.Generator.Base.Tests.ReferencedAssemblies/DPrime/DPrime.csproj |
Disables implicit usings. |
tests/IceRpc.Ice.Generator.Base.Tests.ReferencedAssemblies/D/D.csproj |
Disables implicit usings. |
tests/IceRpc.Ice.Generator.Base.Tests.ReferencedAssemblies/C/C.csproj |
Disables implicit usings. |
tests/IceRpc.Ice.Generator.Base.Tests.ReferencedAssemblies/B/B.csproj |
Disables implicit usings. |
tests/IceRpc.Ice.Generator.Base.Tests.ReferencedAssemblies/A/A.csproj |
Disables implicit usings. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
I think all the changes to the tests are awesome and good and we should keep them. But I'm not sure about the changes to the 2 generators. Our original philosophy was to always qualify our own type-emissions, instead of injecting usings, and it's clear that in 2 places, we weren't careful enough.
That philosophy isn't set in stone of course, but this PR seems like a weak reason to deviate. The bugs in question could be fixed by just slightly tweaking 2 lines of code in our generators, with 0 side-effects to any users.
Adding 2 or 3 new usings to every generated file (possibly breaking some user's Slice in a patch release)... it just feels like a worse solution to the problem here.
| "IceRpc.Slice", | ||
| "IceRpc.Slice.Operations", | ||
| "System", | ||
| "System.Collections.Generic", |
There was a problem hiding this comment.
This PR claims that we emit unqualified collection types, but as far as I can tell, that's simply incorrect. Every IList, Dictionary, IEnumerable, etc. that we emit, is always fully qualified. Adding this using doesn't fix any bug.
I do see a use-case in making the cs::type attribute slightly more ergonomic.
I'm not completely against that, but I definitely think it should be in a different PR, since "making cs::type more friendly" is a completely unrelated to the implicit-usings.
There was a problem hiding this comment.
You're right — I checked: the generated corpora contain 541 fully qualified System.Collections.Generic references and zero unqualified generator-emitted collection types. The PR now takes the direction your comment points to: no preamble usings at all. The two emissions that relied on implicit usings are now fully qualified like everything else (global::System.Span, and global::System.Linq.Enumerable.Count(...) in its static form), and the corpora's cs::type texts qualify their collection types since those projects now disable implicit usings — with implicit usings enabled, cs::type("List") keeps working as before.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
80e0bb6 to
ae341c6
Compare
InsertCreativityHere
left a comment
There was a problem hiding this comment.
Looks good to me!
Fixes #4791.
The Slice generators emit fully qualified names for BCL types — except in two spots that relied on the consuming project enabling
ImplicitUsings: theSpan<byte>local emitted in everyRequest.Encode*/Response.Encode*helper, and the.Count()call emitted for tagged fixed-size collection fields. A consuming project without implicit usings — the SDK default — failed to compile the generated code.Both emissions are now fully qualified, like everything else the generators emit:
global::System.Span<byte>, andglobal::System.Linq.Enumerable.Count(...)in its static form — which also works when acs::typeattribute maps a sequence to an array, and drops a redundant nullable dereference by counting the non-null pattern variable.To keep this from regressing, the Slice, Ice and Protobuf generator test projects (including the
IceRpc.Ice.Generator.Base.Tests.ReferencedAssembliesprojects) now build with<ImplicitUsings>disable</ImplicitUsings>, and their handwritten test files declare their usings explicitly. This also verifies that theslice2csandprotoc-gen-icerpc-csharpoutputs compile without implicit usings — both already qualify all their references.The new
Sequence<int32>?andDictionary<int32, int32>?tagged fields inTaggedTests.slicecover the previously untested fixed-size tagged collection encoding.cs::typetext is passed through verbatim: in a project that doesn't enable implicit usings, qualify the C# type names you write incs::type— the test corpora now do (cs::type("global::System.Collections.Generic.List<bool>")).The checked-in
src/ZeroC.Slice.Symbols/Compilerfiles are deliberately not regenerated here: regenerating them is blocked by #4896.What's Changed entry
The Slice compiler now generates code that compiles in projects that don't enable
ImplicitUsings.