Runtime: NETStandard2.0 libraries referencing types absorbed into NETStandard2.1 cannot be used in NS2.1

Created on 9 Apr 2019  ·  21Comments  ·  Source: dotnet/runtime

How to reproduce

In Visual Studio 2019 RTM, create a new .NET Standard library, and set the target framework to ".NET Standard 2.1". Then add a reference to System.IO.Pipelines (either the lastest stable version 4.5.3 or beta version 4.6.0-preview3-191128.7).

Error message

The type System.ReadOnlySpan<T> (or other types defined in System.Memory assembly) is defined in both System.Memory, version=4.0.1.0 and netstandard, version=2.1.0.0.

Comments

Maybe the reference list of System.IO.Pipelines assembly under netstd 2.1 should be updated in order to fix this problem, and many thanks~

area-System.Memory

Most helpful comment

All 21 comments

cc @davidfowl, @pakrym, @ericstj, @terrajobst - presumably this won't be a one-off issue given what's in netstandard2.1.

Yep, expected given the current POR not to absorb the assembly past assembly identities into netstandard2.1. 2 options:

  1. Have System.Memory ship a new version that has a facade for ns2.1. People still need to upgrade the package reference to get this.
  2. Include a System.Memory facade in netstandard2.1.

2 is the expectation of our users, since that's what we did for 2.0. It's also the cheaper path, since 1 would imply a servicing change or bringing back the package in master.

/cc @wtgodbe

@terrajobst we need to do something here. Either we ship a new version of System.Memory and all other packages absorbed into netstandard, targeting netstandard2.1, and tell folks they need to upgrade, or we add the facades to the NETStandard 2.1 targeting pack like we did for 2.0.

As mentioned above I think the expectation of users is that we do the latter. I also think that practically speaking all our frameworks supporting ns2.1 will also want to support the 2.0 libs that were previously using these types, so they will include the old facades as well. So putting them in netstandard2.1 isn't really added burden.

This is now being caught in our package testing once we pick up a new SDK with NuGet mapping for NS2.1: https://github.com/dotnet/corefx/pull/36859

Here's the type overlap our tests are catching:

Type | Assembly
-- | --
System.Buffers.ArrayPool1 | System.Buffers.dll System.Buffers.Binary.BinaryPrimitives | System.Memory.dll System.Buffers.BuffersExtensions | System.Memory.dll System.Buffers.IBufferWriter1 | System.Memory.dll
System.Buffers.IMemoryOwner1 | System.Memory.dll System.Buffers.IPinnable | System.Memory.dll System.Buffers.MemoryHandle | System.Memory.dll System.Buffers.MemoryManager1 | System.Memory.dll
System.Buffers.MemoryPool1 | System.Memory.dll System.Buffers.OperationStatus | System.Memory.dll System.Buffers.ReadOnlySequence1 | System.Memory.dll
System.Buffers.ReadOnlySequence1/Enumerator | System.Memory.dll System.Buffers.ReadOnlySequenceSegment1 | System.Memory.dll
System.Buffers.StandardFormat | System.Memory.dll
System.Buffers.Text.Base64 | System.Memory.dll
System.Buffers.Text.Utf8Formatter | System.Memory.dll
System.Buffers.Text.Utf8Parser | System.Memory.dll
System.Memory1 | System.Memory.dll System.MemoryExtensions | System.Memory.dll System.ReadOnlyMemory1 | System.Memory.dll
System.ReadOnlySpan1 | System.Memory.dll System.ReadOnlySpan1/Enumerator | System.Memory.dll
System.Runtime.InteropServices.MemoryMarshal | System.Memory.dll
System.Runtime.InteropServices.SequenceMarshal | System.Memory.dll
System.SequencePosition | System.Memory.dll
System.Span1 | System.Memory.dll System.Span1/Enumerator | System.Memory.dll
System.Numerics.Matrix3x2 | System.Numerics.Vectors.dll
System.Numerics.Matrix4x4 | System.Numerics.Vectors.dll
System.Numerics.Plane | System.Numerics.Vectors.dll
System.Numerics.Quaternion | System.Numerics.Vectors.dll
System.Numerics.Vector | System.Numerics.Vectors.dll
System.Numerics.Vector1 | System.Numerics.Vectors.dll System.Numerics.Vector2 | System.Numerics.Vectors.dll System.Numerics.Vector3 | System.Numerics.Vectors.dll System.Numerics.Vector4 | System.Numerics.Vectors.dll System.Reflection.DispatchProxy | System.Reflection.DispatchProxy.dll System.Reflection.Emit.AssemblyBuilder | System.Reflection.Emit.dll System.Reflection.Emit.AssemblyBuilderAccess | System.Reflection.Emit.dll System.Reflection.Emit.ConstructorBuilder | System.Reflection.Emit.dll System.Reflection.Emit.EnumBuilder | System.Reflection.Emit.dll System.Reflection.Emit.EventBuilder | System.Reflection.Emit.dll System.Reflection.Emit.FieldBuilder | System.Reflection.Emit.dll System.Reflection.Emit.GenericTypeParameterBuilder | System.Reflection.Emit.dll System.Reflection.Emit.MethodBuilder | System.Reflection.Emit.dll System.Reflection.Emit.ModuleBuilder | System.Reflection.Emit.dll System.Reflection.Emit.PropertyBuilder | System.Reflection.Emit.dll System.Reflection.Emit.TypeBuilder | System.Reflection.Emit.dll System.Reflection.Emit.CustomAttributeBuilder | System.Reflection.Emit.ILGeneration.dll System.Reflection.Emit.ILGenerator | System.Reflection.Emit.ILGeneration.dll System.Reflection.Emit.Label | System.Reflection.Emit.ILGeneration.dll System.Reflection.Emit.LocalBuilder | System.Reflection.Emit.ILGeneration.dll System.Reflection.Emit.ParameterBuilder | System.Reflection.Emit.ILGeneration.dll System.Reflection.Emit.SignatureHelper | System.Reflection.Emit.ILGeneration.dll System.Reflection.Emit.DynamicMethod | System.Reflection.Emit.Lightweight.dll System.Runtime.CompilerServices.AsyncMethodBuilderAttribute | System.Threading.Tasks.Extensions.dll System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder | System.Threading.Tasks.Extensions.dll System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder1 | System.Threading.Tasks.Extensions.dll
System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable | System.Threading.Tasks.Extensions.dll
System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable/ConfiguredValueTaskAwaiter | System.Threading.Tasks.Extensions.dll
System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable1 | System.Threading.Tasks.Extensions.dll System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable1/ConfiguredValueTaskAwaiter | System.Threading.Tasks.Extensions.dll
System.Runtime.CompilerServices.ValueTaskAwaiter | System.Threading.Tasks.Extensions.dll
System.Runtime.CompilerServices.ValueTaskAwaiter1 | System.Threading.Tasks.Extensions.dll System.Threading.Tasks.Sources.IValueTaskSource | System.Threading.Tasks.Extensions.dll System.Threading.Tasks.Sources.IValueTaskSource1 | System.Threading.Tasks.Extensions.dll
System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags | System.Threading.Tasks.Extensions.dll
System.Threading.Tasks.Sources.ValueTaskSourceStatus | System.Threading.Tasks.Extensions.dll
System.Threading.Tasks.ValueTask | System.Threading.Tasks.Extensions.dll
System.Threading.Tasks.ValueTask`1 | System.Threading.Tasks.Extensions.dll

As discussed, we should include all those facades with .NET Standard 2.1.

Is this issue related to .NET Core at all? If not, let's move it to dotnet/standard.

I can confirm I'm seeing the same issue when using ValueTask in a .NET Standard 2.1 class library referencing a .NET Standard 2.0 library that relies on the System.Threading.Tasks.Extensions package (with the preview4 tooling):

The type 'ValueTask<TResult>' exists in both 'System.Threading.Tasks.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' and 'netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'

Good to hear it's something you'll be able to fix in 3.0 RTM.

Referencing any System.IO.Pipelines version into a netstandard2.1 project and usage of ReadOnlySpan results in error CS0433: The type 'ReadOnlySpan<T>' exists in both 'System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' and 'netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'

This happens in dotnet sdk version 3.0.100-preview6-011865

Re-opening until https://github.com/dotnet/corefx/pull/37532 is done. If I am mistaken, @wtgodbe, please feel free to re-close :)

@ahsonkhan good call, looks like github closed the issue automatically because I said "Resolved" in that PR 😄 . I just merged the second PR, so now we can actually close this.

@wtgodbe Can you let me know when we can very this in a core-sdk build?

The change in Standard has already been absorbed by core-sdk, with https://github.com/dotnet/core-sdk/commit/ebd193f9afcb1c3f37adedd32bbe6858bd8294c2#diff-5c6a1c77fe216efcfbbdccb11b863063. I believe you should be able to try validation now.

The change in Standard has already been absorbed by core-sdk, with dotnet/core-sdk@ebd193f#diff-5c6a1c77fe216efcfbbdccb11b863063. I believe you should be able to try validation now.

Works good ty!

@sgjsakura and @PinpointTownes, can you verify as well, please?

Sure. What’s needed for that? Do I have to install a nightly build of the SDK?

Le 17 mai 2019 à 01:21, Ahson Khan notifications@github.com a écrit :

@sgjsakura and @PinpointTownes, can you verify as well, please?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@PinpointTownes yes, a nightly build of the SDK should work for validation. You can grab the installer from https://dotnetcli.blob.core.windows.net/dotnet/Sdk/master/dotnet-sdk-latest-win-x64.exe. The repro steps in the original post for this issue should be sufficient.

Oddly I'm now getting a different error with 3.0.100-preview6-012016 :

error CS0012: The type 'ValueTask<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Threading.Tasks.Extensions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.

Are there additional things you need to do to make that work?
I'll make a tiny repro to ensure it's not a bug on my side.

I get the same error (with a different assembly version) with this simple repro:

error CS0012: The type 'ValueTask<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Threading.Tasks.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.

image

NetStandard20Library.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.2" />
  </ItemGroup>

</Project>

Class1.cs

using System.Threading.Tasks;

namespace NetStandard20Library
{
    public class Class1
    {
        public static ValueTask<int> Value => new ValueTask<int>(42);
    }
}

NetStandard21Library.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\NetStandard20Library\NetStandard20Library.csproj" />
  </ItemGroup>

</Project>

Class2.cs

using System.Threading.Tasks;
using NetStandard20Library;

namespace NetStandard21Library
{
    public class Class2
    {
        public async Task TestAsync()
        {
            var value = await Class1.Value;
        }
    }
}

I'm probably missing something obvious, but not sure what 😕

I can confirm everything works like a charm with the latest SDK. Great job 👍

teamcity test

Was this page helpful?
0 / 5 - 0 ratings

Related issues

matty-hall picture matty-hall  ·  3Comments

omariom picture omariom  ·  3Comments

chunseoklee picture chunseoklee  ·  3Comments

sahithreddyk picture sahithreddyk  ·  3Comments

noahfalk picture noahfalk  ·  3Comments