dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.97k stars 4.03k forks source link

Add public methods to supress visibility checks for compilation #11149

Closed jkotas closed 1 year ago

jkotas commented 8 years ago

The ability to suppress visibility checks was proven to be useful for auto-generated code like interop or serialization. It requires manipulating internal Roslyn details via private reflection today. There should be a public API to achieve it instead.

See https://github.com/dotnet/orleans/issues/1729 for example

jkotas commented 8 years ago

cc @jaredpar @tmat @yizhang82 @sergeybykov

sergeybykov commented 8 years ago

👍 cc @ReubenBond.

If would really help also if we could suppress visibility check on a per-type in addition to a per-assembly basis.

tmat commented 8 years ago

Why do you need per type?

sergeybykov commented 8 years ago

Why do you need per type?

Today we inject generated code back into the original solution, so that we only produce a single assembly and can leverage IntelliSense. If we could mark only codegen'ed types for suppression, other application types in the same assembly wouldn't be adversely affected.

ReubenBond commented 8 years ago

This feature would be immensely useful for serializers and other nuts & bolts libraries which involve code generation, for example, ORMs and RPC frameworks.

galvesribeiro commented 8 years ago

Is there any progress made on that issue @jkotas ?

Other folks on Roslyn channel mentioned that there a new tooling and new scenarios being created for codegeneration that could make our lifes easier in Orleans... Is there anything we can have a look?

jkotas commented 8 years ago

@galvesribeiro Check https://github.com/dotnet/roslyn/issues/5561

IMHO, I am not sure whether it would make your life in Orleans easier because of it works only for static compilation from sources case. It does not work for the dynamic case where you create Orleans proxies on the fly. You would need to maintain two disjoint solutions for these.

gafter commented 8 years ago

I'm actually more comfortable the way you do it (poking into Roslyn internals using reflection). This is a request to make the compiler stop obeying parts of the language specification, and... well... it is the job of the compiler to obey the language specification.

galvesribeiro commented 8 years ago

@gafter I dont agree with you. If that is the case, remove [InternalsVisibleTo()] from the framework, remove the ability to acess internal types from reflection, because all this bypass the language specification. What we are asking here is not to break the language but to give the power at least while generating code to skip the acessibility check so we can generate code for it.

jaredpar commented 8 years ago

@gafter the compiler already allows removing visibility checks at at API level for the expression evaluator. What is being asked here is not for the compiler command line to allow it but for the API experience to do so.

mjsabby commented 6 years ago

This would be really good to have for the aforementioned reasons. Any chance we can plumb this through to a public API?

ReubenBond commented 3 years ago

If Source Generators could emit code which had greater access to type internals, that would be very useful for serialization libraries.

For example, if we could emit code to get/set private/readonly/initonly fields and properties without reflection or runtime helpers (such as proposed in https://github.com/dotnet/runtime/issues/45152), we could write high-performance, straight-forward code.

Currently, serialization libraries choose between several options:

  1. Throw an error if the user creates a type with private/init-only/get-only/readonly data members
  2. Use reflection to bypass accessibility checks
  3. Emit IL which bypasses those checks
  4. Make the user create partial types and generate additional constructors and methods which access those members within the language rules

Option 1 coerces the user into avoiding language safety features (implementation hiding, immutable data), and may lead to buggier user code.

2 & 3 work today but are slow, potentially fragile, and are not AOT-friendly.

4 Is onerous for developers and prevents interop scenarios such as generating C# code external to foreign C# or F# assemblies. It is also overly restrictive in what code can be generated. For example, a generated deserialization ctor cannot be a generic method, and therefore cannot accept generic parameters (eg, Reader<TInputBuffer>). Not to mention the user's types with foreign members. There are ways around some of these limitations, but they are not ideal for performance: eg, generate a generic deserialization method which passes a surrogate type to a non-generic ctor.

I would like a mechanism to bend the accessibility rules for generated C# code in an opt-in fashion. For example, this could be enabled by adding a special attribute to generated types/methods which would otherwise be violating these checks. Consider [UnsafeSuppressAccessibilityChecks]. If we wanted to reduce the room for error further, we could add a Type argument to the attribute: [UnsafeSuppressAccessibilityChecks(typeof(MySerializedType<>))].

TwentyFourMinutes commented 2 years ago

I fully agree with @ReubenBond, Source Generators are truly awesome and we can finally move away from Reflection, Linq Expression and IL Generators to a more maintainable and less error prone solution. As it currently stands, we have to make 'ugly' workarounds to make things work like previously. This especially applies to ORMs and all other types of mappers.

Of course one might say that such attributes or abilities might be a bad idea and brake rules and that it should better be hidden through the reflection APIs. Anyhow, we already have the IgnoresAccessChecksToAttribute which is recognized and respected by the CLR. So IMHO I do not see any issue there.

ReubenBond commented 2 years ago

Could we consider this in the .NET 7 timeframe? Please see my comment above for more info: https://github.com/dotnet/roslyn/issues/11149#issuecomment-748517708

As Source Generators are becoming more popular (in part due to a push for more AOT compilation), I believe this feature becomes more desirable.

jaredpar commented 1 year ago

Closing as this is not planned for any release in the future.