Awaiten used two different accessibility tests and only one of them was correct. Module member resolution asks Roslyn (`compilation.IsSymbolAccessibleWithin(candidate, containerSymbol)`), which honors `InternalsVisibleTo`. Constructor selection, setter injection and the container's inherited-member lookup instead hand-rolled a `SymbolEqualityComparer.Default.Equals(a.ContainingAssembly, b.ContainingAssembly)` "same assembly" comparison, which does not.
The two disagreed within a single scan. A referenced assembly that grants `[assembly: InternalsVisibleTo("MyApp")]` and exposes a `public sealed class Roaster` with an `internal` constructor passed `IsScanCandidate` (that check already asked Roslyn), and was then rejected by `IsAccessibleConstructor` — failing the build with AWT104 on a `new` the generated container could legally have emitted.
Replaces the hand-rolled comparison with Roslyn's own check at all three sites:
- `SelectConstructor` / `IsAccessibleConstructor` (AWT104): an internal constructor across an `InternalsVisibleTo` boundary is now selected, and without the grant still reports AWT104.
- `IsAccessibleSetter` (AWT136): property injection into an internal setter across the boundary now works; without the grant it still surfaces as AWT136 rather than an inaccessible-setter error in generated code.
- `AccessibleMembers` / `IsAccessibleFromDerived`: the base-type walk for factory / instance / hook lookup. The container's own members keep their deliberate permissiveness — they are yielded by the first loop untouched, and `IsSymbolAccessibleWithin(privateMember, containerSymbol)` would return true for them anyway, since a generated partial can use its container's private members.
Threads `Compilation` to the sites that lacked it (`SelectConstructor` and its five callers, `InjectionContext`, `ExpandOpenGenerics` / `RequiredServiceTypes`, and the scan's `FirstUnconstructableReason` / `UnsatisfiableInjectedMemberReason`).
Beyond `InternalsVisibleTo`, Roslyn's check also walks containing types, so a constructor that is public on a type nested privately in some other class is no longer treated as reachable. That code never compiled anyway.
`AwaitenGenerator.OpenGenerics.cs:593` looks like the same pattern but is not: it checks `DeclaredAccessibility == Accessibility.Public` for a `new()` constraint, and the constraint genuinely requires a public parameterless constructor. `where T : new()` over a type whose only parameterless constructor is `internal` is CS0310 even within one assembly, so relaxing it would make expansion synthesize closed generics that do not compile. Left as is.
All 591 generator tests pass unchanged, including `CrossAssemblyModuleTests.CrossAssemblyModule_InternalFactory_ReportsAwt108NamingTheModule`, which pins the opposite boundary: a cross-assembly internal member without `InternalsVisibleTo` is not imported into the referencing compilation's symbol tables at all, so it stays AWT108 (invisibility) rather than becoming AWT153 (inaccessibility).
Awaiten used two different accessibility tests and only one of them was correct. Module member resolution asks Roslyn (
compilation.IsSymbolAccessibleWithin(candidate, containerSymbol)), which honorsInternalsVisibleTo. Constructor selection, setter injection and the container's inherited-member lookup instead hand-rolled aSymbolEqualityComparer.Default.Equals(a.ContainingAssembly, b.ContainingAssembly)"same assembly" comparison, which does not.The two disagreed within a single scan. A referenced assembly that grants
[assembly: InternalsVisibleTo("MyApp")]and exposes apublic sealed class Roasterwith aninternalconstructor passedIsScanCandidate(that check already asked Roslyn), and was then rejected byIsAccessibleConstructor— failing the build with AWT104 on anewthe generated container could legally have emitted.Replaces the hand-rolled comparison with Roslyn's own check at all three sites:
SelectConstructor/IsAccessibleConstructor(AWT104): an internal constructor across anInternalsVisibleToboundary is now selected, and without the grant still reports AWT104.IsAccessibleSetter(AWT136): property injection into an internal setter across the boundary now works; without the grant it still surfaces as AWT136 rather than an inaccessible-setter error in generated code.AccessibleMembers/IsAccessibleFromDerived: the base-type walk for factory / instance / hook lookup. The container's own members keep their deliberate permissiveness — they are yielded by the first loop untouched, andIsSymbolAccessibleWithin(privateMember, containerSymbol)would return true for them anyway, since a generated partial can use its container's private members.Threads
Compilationto the sites that lacked it (SelectConstructorand its five callers,InjectionContext,ExpandOpenGenerics/RequiredServiceTypes, and the scan'sFirstUnconstructableReason/UnsatisfiableInjectedMemberReason).Beyond
InternalsVisibleTo, Roslyn's check also walks containing types, so a constructor that is public on a type nested privately in some other class is no longer treated as reachable. That code never compiled anyway.AwaitenGenerator.OpenGenerics.cs:593looks like the same pattern but is not: it checksDeclaredAccessibility == Accessibility.Publicfor anew()constraint, and the constraint genuinely requires a public parameterless constructor.where T : new()over a type whose only parameterless constructor isinternalis CS0310 even within one assembly, so relaxing it would make expansion synthesize closed generics that do not compile. Left as is.All 591 generator tests pass unchanged, including
CrossAssemblyModuleTests.CrossAssemblyModule_InternalFactory_ReportsAwt108NamingTheModule, which pins the opposite boundary: a cross-assembly internal member withoutInternalsVisibleTois not imported into the referencing compilation's symbol tables at all, so it stays AWT108 (invisibility) rather than becoming AWT153 (inaccessibility).