Declare EmbeddedAttribute as partial so it can coexist with Reflectify - #153
Merged
Merged
Conversation
…s copy Pathy ships as source and compiles into the consuming assembly. It declares Microsoft.CodeAnalysis.EmbeddedAttribute so its own types can be marked [Embedded], which tells Roslyn to hide them from every other assembly, including InternalsVisibleTo friends. Reflectify is another source-only package by the same author and declares the same attribute for the same reason. A project that uses both packages therefore ended up with two declarations of one type in a single compilation, which failed to build with CS0101. Declaring the type as partial fixes this. Two partial declarations of the same type merge into one type instead of colliding, and Roslyn matches [Embedded] by name, so it does not care how many parts the type came from. Reflectify made the same change in dennisdoomen/reflectify#170. For the parts to merge they must have an identical shape, so the type-level attributes had to go. C# does not allow a non-AllowMultiple attribute to be repeated across parts of a partial type, so leaving [AttributeUsage] in place would fail with CS0579 and defeat the purpose. Dropping it costs nothing because AttributeTargets.All is already the default when an attribute carries no [AttributeUsage]. [ExcludeFromCodeCoverage] was removed for the same reason. Verified with a scratch consumer project that compiles Pathy's sources next to Reflectify's declaration: the library builds, a friend assembly can still reach the library's own internal types, and Pathy types remain hidden from it. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This was referenced Aug 10, 2026
This was referenced Aug 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
Pathy ships as source and compiles into the consuming assembly. It declares
Microsoft.CodeAnalysis.EmbeddedAttributeso its own types can be marked[Embedded]. That attribute tells Roslyn to hide those types from every other assembly, includingInternalsVisibleTofriends.Reflectify is another source-only package that declares the same attribute for the same reason. A project that uses both packages ended up with two declarations of one type in a single compilation:
This is not theoretical. FluentAssertions already consumes Reflectify, so any project combining it with Pathy would hit this.
The fix
Declare the attribute as
partial:Two
partialdeclarations of the same type merge into one type instead of colliding. Roslyn matches[Embedded]by name, so it does not care how many parts the type came from. Embedding keeps working exactly as before.Reflectify made the matching change in dennisdoomen/reflectify#170. Both sides are needed. Neither one works alone.
Why the type-level attributes had to be removed
This part is not optional, and it is easy to undo by accident.
C# does not allow a non-
AllowMultipleattribute to be repeated across the parts of a partial type. If both Pathy's part and Reflectify's part carry[AttributeUsage], the build fails:So re-adding
[AttributeUsage(AttributeTargets.All)]would silently bring the collision straight back, just with a different error code. Please do not add it back. It is also redundant:AttributeTargets.Allis already the default when an attribute carries no[AttributeUsage], so removing it changes nothing at runtime.[ExcludeFromCodeCoverage]was removed for the same reason.Both parts must have an identical shape for the merge to work: same accessibility (
internal), samesealed, same base type, and no type-level attributes. Reflectify's copy is nowinternal sealed partial class EmbeddedAttribute : System.Attribute { }. An XML<remarks>block on the declaration records this constraint for the next reader.Analyzer suppressions
None were needed. Removing
[AttributeUsage]normally triggersCA1018,MA0010andRCS1203, and this repo escalates warnings to errors. I checked by forcing the analyzer package set on (it is currently gated on anet6.0target framework that no project in this repo builds) and confirmed those three analyzers do fire on a plain test attribute type in this project, but none of them fire on this declaration. No#pragmaand no.editorconfigchange was required.Verification
dotnet build -c Releaseon the full solution: 0 warnings, 0 errors.Pathy.Specsnet8.0 109 passed,Pathy.ApiVerificationTestsnet8.0 8 passed, 0 failures. Thenet472run reports "No test is available ... make sure that test discoverer & executors are registered". I confirmed this happens on unmodifiedmainas well, so it is a pre-existing local environment issue and not a regression from this change.PATHY_PUBLIC), next to a second file holding Reflectify's declaration, withInternalsVisibleTopointing at a friend assembly. Results:internaltypes,Pathy.ChainablePath(CS0234), so embedding still works.partialreproduces the collision (CS0260), and putting[AttributeUsage]back on both parts reproducesCS0579.The scratch project was deleted afterwards.