Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InternalsVisibleTo from two other projects leads to not being able to use PolySharp #50

Open
cremor opened this issue Jan 17, 2023 · 13 comments

Comments

@cremor
Copy link

cremor commented Jan 17, 2023

Description

If one project references two other projects that both have InternalsVisibleTo to the first project defined, the first project can't use C# features that should be enabled by PolySharp.

Reproduction Steps

  1. Create a new solution with 3 projects using an older .NET version.
  2. Set <LangVersion>11.0</LangVersion> for all projects.
  3. Add PolySharp to all projects.
  4. Try to use a C# 11 feature, e.g. required properties, in all projects. See that it works as expected.
  5. Add a project reference from two projects to the third one.
  6. Add <ItemGroup><InternalsVisibleTo Include="ThirdProjectName" /></ItemGroup> to the referenced projects.

Expected Behavior

Should be able to compile the code.

Actual Behavior

I get compile errors about missing compiler required members.

System info

This section should contain useful info such as:

  • PolySharp NuGet version 1.10.0
  • Operating system version Windows 10 22H2
  • Visual Studio version, or .NET SDK/runtime version VS 17.4.4, SDK 7.0.102, runtime 7.0.2

Additional context

It looks like the compiler error is missleading. The members are not missing, they are there multiple times (so the compiler sees the internal types from both referenced projects). If only one referenced project with InternalsVisibleTo exists then no error happens.

It looks like PolySharp also sees the internal types of the other projects and doesn't generate any additional types. (It only generates the TypeForwards.)
But I can actually fix the problem and compile my code when I manually add the required compiler types. Then the compiler doesn't error any more, even though it should then actually see each type 3 times.
So maybe the fix for this would be to still generate the required types if the source generator only finds an internal type from another assembly in the current project?

In my actual solution I don't add PolySharp to each project individually but instead use Global Package References. But it seems like this doesn't change anything for this problem.

@Shane32
Copy link

Shane32 commented Jan 18, 2023

See similar issue:

@cremor
Copy link
Author

cremor commented Jan 18, 2023

Thanks, but I don't think there is a way to apply this to my situation, right? I don't need to exclude PolySharp from running in one project like in the linked issue. Instead I'd need it to run even though it thinks it doesn't need to.

@Shane32
Copy link

Shane32 commented Jan 18, 2023

I’m not sure. It sounded like the identical issue to mine so I posted the link. I had 2 viable workarounds which both worked for me, one being to ensure the TFM for all projects matched, and the other being to exclude PolySharp from the third project. If that’s viable you could do so with a ProjectReference Remove in the csproj while maintaining global package references.

@cremor
Copy link
Author

cremor commented Jan 18, 2023

I only have a single target framework (net48) and need PolySharp in all projects.

@cremor
Copy link
Author

cremor commented Jan 19, 2023

Without knowing anything how PolySharp works internally I see three possible solutions:

  • Change PolySharp to generate types which are only available in the current project as an internal type from a different assembly.
    I think this would be the best solution, unless it has some unexpected negative consequence.
  • Change PolySharp to generate types which are only available in the current project as an internal type from at least two different assemblies.
    This change would have a smaller impact, but is very specific for my problem. There might be other situations that I'm not thinking of right now which then would not be fixed.
  • Add a new setting to PolySharp that forces it to generate types even if they are available in the current project (similar to PolySharpIncludeGeneratedTypes).
    This would allow a fix for my problem without changing anything for existing users. But it would also require other users that have the problem to find that setting and known to enable it to fix this (complicated) problem.

@Applesauce314
Copy link

Applesauce314 commented Mar 24, 2023

I had the exact same issue [InternalsVisibleTo] in multiple referenced projects, giving the same issue as above.
My solution was as follows:

  1. Create an additional project (I called it PolyfillProvider),
  2. Have this project target the TFMs used by any project in my solution (in my case net6.0;net472;netstandard2.0)
  3. Add Polysharp to this project
  4. Made the polysharp polyfills public <PolySharpUsePublicAccessibilityForGeneratedTypes>true</PolySharpUsePublicAccessibilityForGeneratedTypes>
  5. add this project as a reference to all the other projects.

Each project gets only the polyfills needed for the TFM.
You would not get per project customization, but you get the benefits of PolySharp.

Edit: If public accessibility is a problem for you see alternate steps in the comment below

@m-ringler
Copy link

This issue is preventing me from switching from the IsExternalInit and IndexRange nuget packages to PolySharp (which I would
otherwise prefer as a one-stop-solution). @cremor's suggested solutions would all be acceptable for me.

@Applesauce314's public generated types workaround has the side effect of making the generated types visible to consumers of your code. If two libraries use that workaround you cannot (easily) use both of them at the same time. So that does not work for me.

@Applesauce314
Copy link

@Applesauce314's public generated types workaround has the side effect of making the generated types visible to consumers of your code. If two libraries use that workaround you cannot (easily) use both of them at the same time. So that does not work for me.

@m-ringler I checked if removing <PolySharpUsePublicAccessibilityForGeneratedTypes>true</PolySharpUsePublicAccessibilityForGeneratedTypes> and instead adding [assembly: InternalsVisibleTo("assembly.Name")] for each project that needs the polyfills, and it worked, I think that would satisfy the need to not have the polyfills public, I did not test having multiple polyfill projects that do this, but I would expect it to work.

@JoelDavidLang
Copy link

Is there an ideal solution to this issue yet?

I just encountered it when creating a .NET 6.0 unit test project for a library that is targeting .NET Standard 2.0 while using PolySharp. Because the library has internals visible to the unit test project, I get this error.

It seems I can work around it by excluding IsExternalInit from generation in the unit test project. I want PolySharp to handle this by default though, so this error doesn't happen.

@Applesauce314
Copy link

Is there an ideal solution to this issue yet?

I just encountered it when creating a .NET 6.0 unit test project for a library that is targeting .NET Standard 2.0 while using PolySharp. Because the library has internals visible to the unit test project, I get this error.

It seems I can work around it by excluding IsExternalInit from generation in the unit test project. I want PolySharp to handle this by default though, so this error doesn't happen.

I don't know if it is "ideal", but I have been using the separate project with the default
internal accessibilty and [assembly:InternalsVisibleTo()] for each project that uses it for a month now.

The only problem I have had so far was when I added a new project and forgot to add it to the list, spent a few minutes looking for a broken config before I remembered.

@martinsuchan
Copy link

Hi, this problem is currently blocking us from using PolySharp in our larger solution.
Out of available options I think having a MSBuild flag for "Always generating polyfills" is the best option here?

@lilith
Copy link

lilith commented Jan 23, 2024

I would concur. And this happens a lot with unit test projects. I publish a lot (77+) of NuGet packages that multi-target net8.0;netstandard2.0;net6.0. If Always generate polyfills works well, perhaps it should be the default at least for unit test projects?

@dropsonic
Copy link

Bump. This issue also blocks PolySharp usage in our solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants