API Compat reports CP0008 false positive for internal interfaces from friend assemblies
- Dominant language
- C#
- Stars
- 3.2k
- Forks
- 1.3k
- PR merge metrics
- PR metrics pending
Description
# API Compat reports CP0008 false positive for internal interfaces from friend assemblies
## Description
API Compat incorrectly reports CP0008 errors when comparing assemblies that implement internal interfaces from friend assemblies (via `InternalsVisibleTo`), even when the interface implementations haven't changed. Since internal interfaces are not part of the public API contract, these should not be reported as breaking changes.
## Steps to Reproduce
### 1. Create AssemblyA with internal interface
**AssemblyA.csproj:**
```xml
net11.0
```
**IInternal.cs:**
```csharp
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("AssemblyB")]
namespace TestNamespace
{
internal interface IInternalInterface
{
string GetValue();
}
public interface IPublicInterface
{
void DoWork();
}
}
```
Build: `dotnet build AssemblyA.csproj -o shared`
### 2. Create AssemblyB v1.0.0
**AssemblyB.csproj:**
```xml
net11.0
1.0.0
```
**MyClass.cs:**
```csharp
using TestNamespace;
namespace AssemblyB
{
public class MyClass : IPublicInterface, IInternalInterface
{
public void DoWork() { }
public string GetValue() => "v1.0.0";
}
}
```
Pack: `dotnet pack AssemblyB.csproj -o local-nuget`
### 3. Update to v1.1.0 with package validation
Update **AssemblyB.csproj:**
```xml
net11.0
1.1.0
true
1.0.0
```
Update **MyClass.cs** (bug fix only - no API change):
```csharp
using TestNamespace;
namespace AssemblyB
{
public class MyClass : IPublicInterface, IInternalInterface
{
public void DoWork() { }
public string GetValue() => "v1.1.0 - bug fix"; // <-- Only change
}
}
```
Create **nuget.config:**
```xml
```
Pack: `dotnet pack`
## Expected Behavior
No API compatibility errors should be reported because:
1. Both versions implement the same interfaces (IPublicInterface + IInternalInterface)
2. Only internal implementation changed (return value)
3. IInternalInterface is internal and not part of the public API surface
4. External consumers cannot see or depend on IInternalInterface
## Actual Behavior
```
error CP0008: Type 'AssemblyB.MyClass' does not implement interface 'TestNs.IPublicInterface'
on lib/net11.0/AssemblyB.dll but it does on [Baseline] lib/net11.0/AssemblyB.dll
```
API Compat reports CP0008 even though both versions implement identical interfaces.
## Real-World Impact
This issue affects .NET source-build infrastructure (dotnet/source-build-assets) where GenAPI generates reference source from baseline NuGet packages. When validating these packages:
**Microsoft.Build.Utilities.Core 17.11.48:**
- `IMetadataContainer` is **internal** in Microsoft.Build.Framework
- Microsoft.Build.Framework grants `InternalsVisibleTo("Microsoft.Build.Utilities.Core")`
- GenAPI correctly omits this internal interface (not public API)
- API Compat incorrectly reports CP0008
Currently requires manual suppressions in:
- microsoft.build.utilities.core/17.11.48 (IMetadataContainer)
- microsoft.build/17.11.48 (ITranslatable on 22 types, IBuildCheckResult)
## Environment
- .NET SDK: 11.0.100-preview.5.26227.104
- OS: Linux
## Related Issues
- #45995 - CP0008 false positive for generic interfaces where the type argument is internal
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.