Proposal: add `assembly`-scoped types/files for assembly-only visibility
- Dominant language
- C#
- Stars
- 20.7k
- Forks
- 4.3k
- PR merge metrics
- PR metrics pending
Description
Please consider adding support for `assembly`-scoped declarations in C#.
Today, `file`-scoped types allow source generators and other code generation scenarios to create helper types that are isolated to a single source file. However, there is no equivalent way to declare something that is visible **throughout the current assembly** while remaining **completely invisible outside the assembly boundary**.
This proposal asks for an `assembly`-scoped concept: effectively, declarations that are available anywhere within the current assembly, but never exposed externally and never widened through mechanisms such as `InternalsVisibleTo`.
## Motivation
This is especially useful for source generators.
A generator may want to emit supporting types, attributes, or helpers that:
- can be referenced from any generated file in the same assembly
- can also be referenced by user-authored code in that same assembly, if intended
- are never visible to consumers of the assembly
- are never exposed to friend assemblies via `InternalsVisibleTo`
An example of this would be when generating marker attributes allowing the user to guide source generators through their execution... think `IncrementalGeneratorInitializationContext.SyntaxProvider.ForAttributeWithMetadataName()`
Today, the existing options do not fully cover this need:
- `file` is too restrictive, because it limits visibility to a single source file
- `internal` is too broad, because it becomes visible to friend assemblies through `InternalsVisibleTo` - often used on larger projects
- `public` is obviously not appropriate
An `assembly`-scoped declaration would fill the gap between `file` and `internal`.
## Example use case
A source generator wants to emit an attribute and helper types that are usable anywhere in the target assembly, but should never become part of the externally reachable surface area.
For example, something conceptually like:
```csharp
assembly class GeneratedHelper
{
// internal is largely invalid here - it's either public or private.
public static string Normalize(string value) => value.Trim();
}
assembly attribute class MyGeneratedAttribute : Attribute
{
}
```
Or, if the feature is modeled at the file level, an “assembly-scoped file” could make all top-level declarations in that file assembly-only.
## Expected behavior
Declarations marked as `assembly` should:
- be accessible from any source file within the same assembly
- not be accessible from any referencing assembly
- not be accessible through `InternalsVisibleTo`
- not appear as part of the assembly’s externally consumable API surface
- work well for generated attributes, marker types, and helper utilities
## Why this matters
This would give source generators a clean way to provide reusable implementation details across generated code without:
- forcing everything into a single file
- relying on `internal` and accepting leakage to friend assemblies
- creating awkward naming schemes to avoid collisions
- exposing implementation details more broadly than intended
## Requested outcome
It would be helpful to know whether the C# / .NET team sees this as:
- a reasonable language feature proposal
- something that is intentionally unsupported
- something source generators should solve in another way
If the last instance, I've been hunting around for a viable alternative since I began writing source generators, but I'm yet to come up with a 'good' solution to the leakage problem.
Contributor guide
Research direction
Start with the proposal's examples involving source generators, generated attributes, and IncrementalGeneratorInitializationContext.SyntaxProvider.ForAttributeWithMetadataName. Compare the requested assembly visibility with file, internal, public, and InternalsVisibleTo behavior. The issue does not identify implementation files or tests; done would require an agreed language design and corresponding compiler behavior, diagnostics, and coverage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100