IL2080 from deconstruction assignment "using" ValueTuple
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### Description
This is similar to #123767, *except* that the *assignment* is fully defined, as opposed to coming from a method parameter:
```csharp
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](https://github.com/user-attachments/files/32208432/net11-il2080-valuetuple.zip)
Or create with:
```sh
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()
+ {
+ 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 @@
- net10.0
+ net11.0
net11_il2080_valuetuple
enable
enable
+ true
+ $(DefineConstants);NO_DESTRUCTURE
EOF
```
Build the project:
```dotnetcli
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:
```csharp
(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:
```csharp
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`.
### 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. (If`ValueTuple<…>` *had* been present, then it would make sense that `var _t = new ValueTuple("m", typeof(T)); var method = _t.Item2.GetMethod(_t.Item1)` could be problematic, but when `ValueTuple<…>` isn't even in the IL stream…)
Contributor guide
Assessment
This issue has not been assessed yet.