dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.97k stars 4.65k forks source link

DLR ignores unmanaged constraint when picking overload #72799

Open IS4Code opened 2 years ago

IS4Code commented 2 years ago

Description

When a method is called with a dynamic argument, the unmanaged constraint (and likely other new constraints) is not taken into account when the overload is being picked.

Reproduction Steps

Create a method like N<T>(T value) where T : unmanaged and call it with a dynamic-typed instance of a non-unmanaged type. For example:

public static void Main(string[] args)
{
    M<int>(); // True
    M<string>(); // False
    M<ValueTuple<string>>(); // True
}

static void M<T>()
{
    Console.WriteLine(N((dynamic)default(T)));
}

static bool N<T>(T value) where T : unmanaged => true;

static bool N(object value) => false;

Expected behavior

The overload with where T : unmanaged should not be picked, as it violates the constraint and is inconsistent with C#.

Actual behavior

where T : unmanaged is treated as where T : struct in the DLR, and is picked even for a non-unmanaged type.

Regression?

No response

Known Workarounds

No response

Configuration

Tested on .NET 8, 6, and 5.

Other information

No response

dotnet-issue-labeler[bot] commented 2 years ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

ghost commented 2 years ago

Tagging subscribers to this area: @cston See info in area-owners.md if you want to be subscribed.

Issue Details
### Description When a method is called with a `dynamic` argument, the `unmanaged` constraint (and likely other new constraints) is not taken into account when the overload is being picked. ### Reproduction Steps Create a method like `N(T value) where T : unmanaged` and call it with a `dynamic`-typed instance of a non-unmanaged type. For example: ```cs public static void Main(string[] args) { M(); // True M(); // False M>(); // True } static void M() { Console.WriteLine(N((dynamic)default(T))); } static bool N(T value) where T : unmanaged => true; static bool N(object value) => false; ``` ### Expected behavior The overload with `where T : unmanaged` should not be picked, as it violates the constraint and is inconsistent with C#. ### Actual behavior `where T : unmanaged` is treated as `where T : struct` in the DLR, and is picked even for a non-unmanaged type. ### Regression? _No response_ ### Known Workarounds _No response_ ### Configuration Tested on .NET 6 and 5. ### Other information _No response_
Author: IllidanS4
Assignees: -
Labels: `area-Microsoft.CSharp`, `untriaged`
Milestone: -
IS4Code commented 6 months ago

Issue still exists on .NET 8.