From ffbd2055b08844cd3c887a47facbd12e6797529e Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 27 Jul 2026 16:45:36 +0200 Subject: [PATCH] Pin disambiguators for constraints on sibling method type parameters The chain cases in the fixture route T : TOuter through a class-level type parameter; the variant where the dependency target is a sibling method type parameter (M with T : U) was uncovered. It pins the same alignment from a different angle: csc rejects 'class' with CS8665 when U is merely class-constrained and requires 'default', but accepts 'class' when U carries a class-type constraint, matching what the tri-state IsReferenceType derives. Both directions were verified against csc before adding the expected output. Assisted-by: Claude:claude-fable-5:Claude Code --- .../TestCases/Pretty/Issue3909.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3909.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3909.cs index 8d8284974..f46d5df67 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3909.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3909.cs @@ -207,6 +207,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } + public abstract class MethodChainBase + { + public virtual T? DependentOnClassConstrained(T? value, U other) where T : U where U : class + { + return value; + } + + public virtual T? DependentOnClassType(T? value, U other) where T : U where U : Node + { + return value; + } + } + + public sealed class MethodChainDerived : MethodChainBase + { + public override T? DependentOnClassConstrained(T? value, U other) where T : default + { + return value; + } + + public override T? DependentOnClassType(T? value, U other) where T : class + { + return value; + } + } + public class ContainerBase where TOuter : class { public virtual TOuter? Pick(TItem item)