Browse Source

Pin the allows ref struct interaction on nullable overrides

allows ref struct is inherited implicitly, so restating it on an override is
CS0460 even alongside a legal disambiguator. Roslyn still re-emits the byreflike
flag on the override's own type parameter, and the general constraint printer
turns that flag back into source, so the disambiguator stays legal only as long
as it is built separately. Cover a C# 13 base whose annotated and plain methods
both allow ref structs.

Assisted-by: Copilot:claude-opus-5:GitHub Copilot CLI
pull/3910/head
Sebastien Lebreton 2 months ago
parent
commit
ee2d747862
  1. 23
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3909.cs
  2. 3
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

23
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3909.cs

@ -222,5 +222,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return null; return null;
} }
} }
#if CS130
public class BaseWithAllowsRefStruct
{
public virtual void Annotated<T>(T? value) where T : allows ref struct
{
}
public virtual void Plain<T>(T value) where T : allows ref struct
{
}
}
public class DerivedWithAllowsRefStruct : BaseWithAllowsRefStruct
{
public override void Annotated<T>(T? value) where T : default
{
}
public override void Plain<T>(T value)
{
}
}
#endif
} }
} }

3
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -2619,6 +2619,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
// metadata, so which disambiguator is legal follows from them without resolving the base // metadata, so which disambiguator is legal follows from them without resolving the base
// member. The restated disambiguator leaves no metadata trace of its own, hence it must be // member. The restated disambiguator leaves no metadata trace of its own, hence it must be
// derived rather than read back. // derived rather than read back.
// The clause is built here rather than through ConvertTypeParameterConstraint, which also
// prints 'allows ref struct' from the byreflike flag. That flag is re-emitted on the
// override's own type parameter as well, and restating it is CS0460.
void AddNullabilityDisambiguatingConstraints(MethodDeclaration decl, IMethod method) void AddNullabilityDisambiguatingConstraints(MethodDeclaration decl, IMethod method)
{ {
if (method.TypeParameters.Count == 0) if (method.TypeParameters.Count == 0)

Loading…
Cancel
Save