Skip to content

IL2080 from deconstruction assignment "using" ValueTuple #133911

Description

@jonpryor

Description

This is similar to #123767, except that the assignment is fully defined, as opposed to coming from a method parameter:

var (methodName, declType) = condition ? ("x", typeof(A)) : ("y", typeof(B));
var method = declType.GetMethod(methodName);

Reproduction Steps

Consider the following project: net11-il2080-valuetuple.zip

Or create with:

dotnet new classlib -n net11-il2080-valuetuple
cd net11-il2080-valuetuple
cat <<'EOF' | git apply
diff --git a/Class1.cs b/Class1.cs
index 550b959..e637880 100644
--- a/Class1.cs
+++ b/Class1.cs
@@ -1,6 +1,37 @@
-namespace net11_il2080_valuetuple;
+using System.Reflection;
+
+namespace net11_il2080_valuetuple;
 
 public class Class1
 {
+    public void M<T>()
+    {
+        int _icuVersion = 42;
+#if !NO_DESTRUCTURE
+        (var methodName, var type) = MyOS.IsBrowser()
+            ?  ($"uno_{typeof(T).Name}", typeof(BrowserICUSymbols))
+            :  ($"{typeof(T).Name}_{_icuVersion}", typeof(IOSICUSymbols));
+#else
+        var type = MyOS.IsBrowser()
+            ? typeof(BrowserICUSymbols)
+            : typeof(IOSICUSymbols);
+        var methodName = MyOS.IsBrowser()
+            ? $"uno_{typeof(T).Name}"
+            : $"{typeof(T).Name}_{_icuVersion}";
+#endif
+        var method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static);
+    }
+}
+
+static class MyOS
+{
+    public static bool IsBrowser() => false;
+}
 
+static class BrowserICUSymbols
+{
+}
+
+static class IOSICUSymbols
+{
 }
diff --git a/net11-il2080-valuetuple.csproj b/net11-il2080-valuetuple.csproj
index dabad04..40692be 100644
--- a/net11-il2080-valuetuple.csproj
+++ b/net11-il2080-valuetuple.csproj
@@ -1,10 +1,12 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>net10.0</TargetFramework>
+    <TargetFramework>net11.0</TargetFramework>
     <RootNamespace>net11_il2080_valuetuple</RootNamespace>
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
+    <IsAotCompatible>true</IsAotCompatible>
+    <DefineConstants Condition=" '$(NODestructure)' != '' ">$(DefineConstants);NO_DESTRUCTURE</DefineConstants>
   </PropertyGroup>
 
 </Project>
EOF

Build the project:

dotnet build

Expected behavior

No warning? No warning was emitted in .NET 10. (Which may not matter, as #123767 was not fixed in .NET 10 , but is fixed in .NET 11 rc.1…)

Actual behavior

An IL2080 warning is generated:

Class1.cs(22,22): warning IL2080: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.NonPublicMethods' in call to 'System.Type.GetMethod(String, BindingFlags)'. The field '(System.String, System.Type).Item2' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.

This warning is new in .NET 11 rc.1.

Regression?

"Yes", in that previously warning-free code now emits warnings, which become errors, due to the joy that is $(TreatWarningsAsErrors)=true.

Known Workarounds

"Deconstruct" the deconstruction assignment, i.e. "don't do that."

The offending code is this statement:

        (var methodName, var type) = MyOS.IsBrowser()
            ?  ($"uno_{typeof(T).Name}", typeof(BrowserICUSymbols))
            :  ($"{typeof(T).Name}_{_icuVersion}", typeof(IOSICUSymbols));
        var method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static);

If you build the project with -p:NoDestructure=1, then no IL2080 warning is generated, as this alternate codepath is used:

        var type = MyOS.IsBrowser()
            ? typeof(BrowserICUSymbols)
            : typeof(IOSICUSymbols);
        var methodName = MyOS.IsBrowser()
            ? $"uno_{typeof(T).Name}"
            : $"{typeof(T).Name}_{_icuVersion}";
        var method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static);

The runtime conditional is still present, we just remove the use of ValueTuple<string, Type>.

Configuration

  • .NET 11 rc.1. (Did not happen in .NET 11 Preview 7.)
  • macOS 26, though I doubt the host OS matters.
  • arm64, though I doubt the host OS matters.

Other information

When writing this up I had thought that use of ValueTuple<…> along with deconstruction assignment was "the problem."

…until I ran ildasm on the warning-emitting binary, and saw no use of ValueTuple<…>! I thus lack an explanation for why the originating "deconstruction assignment" usage is problematic. (IfValueTuple<…> had been present, then it would make sense that var _t = new ValueTuple<string, Type>("m", typeof(T)); var method = _t.Item2.GetMethod(_t.Item1) could be problematic, but when ValueTuple<…> isn't even in the IL stream…)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions