mirror of https://github.com/icsharpcode/ILSpy.git
Browse Source
C# 15 (.NET 11 preview 5) encodes the closed modifier as
System.Runtime.CompilerServices.ClosedAttribute on the implicitly
abstract type plus CompilerFeatureRequired("ClosedClasses") on every
constructor; the BCL does not ship the attribute yet, so assemblies
declare their own copy or reference one from another assembly. The
decompiler now reconstructs the modifier from this encoding, gated on a
new C# 15 ClosedHierarchies setting. Exported projects state LangVersion
preview because the compiler does not accept 15.0 yet.
The pretty tests cover the definition side only: switch exhaustiveness
over a closed hierarchy is compile-time knowledge that leaves no trace
in the IL of consuming code.
Compiling "#dependency" test assemblies to a temp file left them
unresolvable while decompiling the main test assembly; they now land
next to the main output. With its dependency resolvable, Issue3684 no
longer needs the disambiguating base-class cast. The cross-assembly
fixture also exposed a latent NRE in RecordDecompiler when a record's
base type cannot be resolved.
Assisted-by: Claude:claude-fable-5:Claude Code
christophwille/closedhierarchies
16 changed files with 193 additions and 8 deletions
@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
|
||||
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty |
||||
{ |
||||
internal class ClosedHierarchies |
||||
{ |
||||
public closed class Animal |
||||
{ |
||||
public string Name { get; } |
||||
|
||||
protected Animal() |
||||
{ |
||||
Name = "unnamed"; |
||||
} |
||||
|
||||
protected Animal(string name) |
||||
{ |
||||
Name = name; |
||||
} |
||||
} |
||||
|
||||
public class Cat : Animal |
||||
{ |
||||
} |
||||
|
||||
public sealed class Dog : Animal |
||||
{ |
||||
public Dog() |
||||
: base("Dog") |
||||
{ |
||||
} |
||||
} |
||||
|
||||
public closed class Job |
||||
{ |
||||
public required string Title { get; set; } |
||||
} |
||||
|
||||
public sealed class CompileJob : Job |
||||
{ |
||||
} |
||||
|
||||
public closed class Tree<T> |
||||
{ |
||||
} |
||||
|
||||
public sealed class Leaf<U> : Tree<U> |
||||
{ |
||||
} |
||||
|
||||
public sealed class ArrayLeaf<V> : Tree<V[]> |
||||
{ |
||||
} |
||||
} |
||||
public closed record JobStatus; |
||||
internal record JobStatusCanceled : JobStatus; |
||||
public record JobStatusQueued : JobStatus; |
||||
public record JobStatusRunning(int PercentComplete) : JobStatus; |
||||
internal closed class State |
||||
{ |
||||
} |
||||
internal sealed class StateActive : State |
||||
{ |
||||
} |
||||
} |
||||
#if !EXPECTED_OUTPUT
|
||||
// The .NET 11 preview 5 BCL does not ship ClosedAttribute yet; the compiler requires
|
||||
// every assembly using the 'closed' modifier to declare it (matched by full name).
|
||||
namespace System.Runtime.CompilerServices |
||||
{ |
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] |
||||
internal sealed class ClosedAttribute : Attribute |
||||
{ |
||||
} |
||||
} |
||||
#endif
|
||||
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
// #dependency ClosedHierarchiesCrossAssembly.dep.cs
|
||||
using CrossAssemblyClosed; |
||||
|
||||
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty |
||||
{ |
||||
public closed record LocalMessage; |
||||
public record LocalTextMessage(string Text) : LocalMessage; |
||||
public record Sedan(int Doors) : Car(Doors); |
||||
} |
||||
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
namespace CrossAssemblyClosed |
||||
{ |
||||
public closed record Vehicle; |
||||
public record Car(int Doors) : Vehicle; |
||||
public sealed record Truck(double PayloadTons) : Vehicle; |
||||
} |
||||
|
||||
// Public so that the main test assembly can use the 'closed' modifier without
|
||||
// declaring its own copy of the attribute (the shape the BCL will provide once
|
||||
// ClosedAttribute ships).
|
||||
namespace System.Runtime.CompilerServices |
||||
{ |
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] |
||||
public sealed class ClosedAttribute : Attribute |
||||
{ |
||||
} |
||||
} |
||||
Loading…
Reference in new issue