Skip to content

Convert funceval to UCO pattern#126809

Open
am11 wants to merge 23 commits intodotnet:mainfrom
am11:feature/MDCS-to-UCOA-pattern2
Open

Convert funceval to UCO pattern#126809
am11 wants to merge 23 commits intodotnet:mainfrom
am11:feature/MDCS-to-UCOA-pattern2

Conversation

@am11
Copy link
Copy Markdown
Member

@am11 am11 commented Apr 12, 2026

Built on top of #126542.

Last part of #123864 before the final cleanups.

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Apr 12, 2026
@am11
Copy link
Copy Markdown
Member Author

am11 commented Apr 12, 2026

cc @jkotas, @janvorli

Tested it with this program in VSCode:

Program.cs

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

// Test various funceval scenarios that exercise DoNormalFuncEval
var dt = new DateTime(2026, 4, 12);
var list = new System.Collections.Generic.List<int> { 1, 2, 3 };
var str = "hello funceval";
int x = 42;
double pi = 3.14;
bool flag = true;
var dict = new System.Collections.Generic.Dictionary<string, int> { ["one"] = 1, ["two"] = 2 };
var arr = new int[] { 10, 20, 30 };
object boxed = 99;
var guid = Guid.NewGuid();
var span = "hello".AsSpan(); // not directly evaluable but interesting
var tuple = (Name: "Alice", Age: 30);

// Breakpoint here - then evaluate expressions in Watch/Immediate window:
//
// === Instance methods on value types (boxes 'this') ===
//   dt.ToString()              → value type instance method
//   dt.AddDays(1)              → value type method with arg, returns value type
//   guid.ToString()            → Guid.ToString()
//   pi.ToString("F1")          → double method with string arg
//   tuple.ToString()           → ValueTuple instance method
//
// === Instance methods on ref types ===
//   str.Length                  → string property (handle-based 'this')
//   str.Contains("func")       → string method with string arg
//   str.Substring(6, 4)        → string method with two int args
//   list.Count                 → generic ref type property
//   list.Contains(2)           → generic method with boxed int arg
//   list[0]                    → indexer (get_Item)
//   dict["one"]                → dictionary indexer
//   dict.ContainsKey("two")    → dictionary method
//   arr.Length                 → array property
//
// === Primitive 'this' (box + call) ===
//   x.ToString()               → int.ToString()
//   x.GetType()                → int.GetType() returns System.Int32
//   flag.ToString()            → bool.ToString()
//   x.CompareTo(10)            → int.CompareTo(int)
//
// === Static methods (this = null) ===
//   string.Concat("a", "b")   → static with ref type args
//   string.IsNullOrEmpty("")   → static with ref type arg
//   int.Parse("123")           → static returning primitive
//   Math.Max(3, 7)             → static with two primitive args
//   DateTime.UtcNow            → static property returning value type
//   Environment.ProcessId      → static property returning int
//   RuntimeInformation.FrameworkDescription → static property returning string
//   Guid.NewGuid()             → static method returning value type
//   Convert.ToInt32("42")      → static with string arg returning int
//
// === NEW_OBJECT (constructor) ===
//   new DateTime(2000, 1, 1)   → value type ctor with primitive args
//   new List<int>()            → ref type default ctor
//   new string('x', 5)        → string ctor with char + int
//   new object()               → simplest ctor
//
// === Boxed object ===
//   boxed.ToString()           → call on boxed int (ELEMENT_TYPE_OBJECT)
//   boxed.GetType()            → GetType on boxed int
//
Debugger.Break();

Console.WriteLine($"dt={dt}, list.Count={list.Count}, str={str}, x={x}");
Console.WriteLine($"dict={dict.Count}, arr={arr.Length}, guid={guid}, pi={pi}, flag={flag}");

launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "funceval-test (branch)",
            "type": "coreclr",
            "request": "launch",
            "program": "c:\\temp\\runtime\\artifacts\\bin\\testhost\\net11.0-windows-Release-x64\\dotnet.exe",
            "args": ["exec", "C:\\temp\\funceval-test\\bin\\Debug\\net11.0\\funceval-test.dll"],
            "cwd": "${workspaceFolder}",
            "stopAtEntry": false,
            "env": {
                "DOTNET_ROOT": "c:\\temp\\runtime\\artifacts\\bin\\testhost\\net11.0-windows-Release-x64"
            }
        },
        {
            "name": "funceval-test (main)",
            "type": "coreclr",
            "request": "launch",
            "program": "c:\\temp\\runtime\\runtime2\\artifacts\\bin\\testhost\\net11.0-windows-Release-x64\\dotnet.exe",
            "args": ["exec", "C:\\temp\\funceval-test\\bin\\Debug\\net11.0\\funceval-test.dll"],
            "cwd": "${workspaceFolder}",
            "stopAtEntry": false,
            "env": {
                "DOTNET_ROOT": "c:\\temp\\runtime\\runtime2\\artifacts\\bin\\testhost\\net11.0-windows-Release-x64"
            }
        }
    ]
}

Results match main branch:

PR Main

@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

@jkotas
Copy link
Copy Markdown
Member

jkotas commented Apr 12, 2026

Built on top of #126542.

Does it depend on any of the changes in #126542 given that it just calls the public MethodInfo.Invoke API?

@am11
Copy link
Copy Markdown
Member Author

am11 commented Apr 12, 2026

Built on top of #126542.

Does it depend on any of the changes in #126542 given that it just calls the public MethodInfo.Invoke API?

#126542 moved InvokeMethod to managed and this is tested end to end that way. I can cherry-pick ffa8a51 on main if we want this one to go in first.

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

Labels

area-Diagnostics-coreclr community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants