Skip to content

Make generated code compile without implicit usings - #4897

Open
bernardnormier wants to merge 2 commits into
icerpc:mainfrom
bernardnormier:fix-generated-code-implicit-usings
Open

Make generated code compile without implicit usings#4897
bernardnormier wants to merge 2 commits into
icerpc:mainfrom
bernardnormier:fix-generated-code-implicit-usings

Conversation

@bernardnormier

@bernardnormier bernardnormier commented Aug 27, 2026

Copy link
Copy Markdown
Member

Fixes #4791.

The Slice generators emit fully qualified names for BCL types — except in two spots that relied on the consuming project enabling ImplicitUsings: the Span<byte> local emitted in every Request.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>, and global::System.Linq.Enumerable.Count(...) in its static form — which also works when a cs::type attribute 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.ReferencedAssemblies projects) now build with <ImplicitUsings>disable</ImplicitUsings>, and their handwritten test files declare their usings explicitly. This also verifies that the slice2cs and protoc-gen-icerpc-csharp outputs compile without implicit usings — both already qualify all their references.

The new Sequence<int32>? and Dictionary<int32, int32>? tagged fields in TaggedTests.slice cover the previously untested fixed-size tagged collection encoding.

cs::type text is passed through verbatim: in a project that doesn't enable implicit usings, qualify the C# type names you write in cs::type — the test corpora now do (cs::type("global::System.Collections.Generic.List<bool>")).

The checked-in src/ZeroC.Slice.Symbols/Compiler files 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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@InsertCreativityHere InsertCreativityHere left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/IceRpc.Slice.Generator/Program.cs Outdated
"IceRpc.Slice",
"IceRpc.Slice.Operations",
"System",
"System.Collections.Generic",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

bernardnormier and others added 2 commits August 28, 2026 15:55
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bernardnormier
bernardnormier force-pushed the fix-generated-code-implicit-usings branch from 80e0bb6 to ae341c6 Compare August 28, 2026 19:56
@bernardnormier
bernardnormier requested review from externl and a balanced review from Copilot August 28, 2026 19:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 69 out of 69 changed files in this pull request and generated no new comments.

@externl externl left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

@InsertCreativityHere InsertCreativityHere left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Audit-Medium] Generated code depends on ImplicitUsings being enabled in the consumer project

4 participants