{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/188","labels_url":"https://api.github.com/repos/dotnet/roslyn/issues/188/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/roslyn/issues/188/comments","events_url":"https://api.github.com/repos/dotnet/roslyn/issues/188/events","html_url":"https://github.com/dotnet/roslyn/issues/188","id":56113873,"number":188,"title":"Proposal: Add completeness checking (algebraic data types) to pattern matching draft specification","user":{"login":"agocke","id":515774,"avatar_url":"https://avatars.githubusercontent.com/u/515774?v=3","gravatar_id":"","url":"https://api.github.com/users/agocke","html_url":"https://github.com/agocke","followers_url":"https://api.github.com/users/agocke/followers","following_url":"https://api.github.com/users/agocke/following{/other_user}","gists_url":"https://api.github.com/users/agocke/gists{/gist_id}","starred_url":"https://api.github.com/users/agocke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/agocke/subscriptions","organizations_url":"https://api.github.com/users/agocke/orgs","repos_url":"https://api.github.com/users/agocke/repos","events_url":"https://api.github.com/users/agocke/events{/privacy}","received_events_url":"https://api.github.com/users/agocke/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dotnet/roslyn/labels/2%20-%20Ready","name":"2 - Ready","color":"CCCCCC"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Area-Language%20Design","name":"Area-Language Design","color":"5319e7"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Feature%20Request","name":"Feature Request","color":"fc2929"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Language-C%23","name":"Language-C#","color":"207de5"}],"state":"open","locked":false,"assignee":{"login":"gafter","id":3804346,"avatar_url":"https://avatars.githubusercontent.com/u/3804346?v=3","gravatar_id":"","url":"https://api.github.com/users/gafter","html_url":"https://github.com/gafter","followers_url":"https://api.github.com/users/gafter/followers","following_url":"https://api.github.com/users/gafter/following{/other_user}","gists_url":"https://api.github.com/users/gafter/gists{/gist_id}","starred_url":"https://api.github.com/users/gafter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gafter/subscriptions","organizations_url":"https://api.github.com/users/gafter/orgs","repos_url":"https://api.github.com/users/gafter/repos","events_url":"https://api.github.com/users/gafter/events{/privacy}","received_events_url":"https://api.github.com/users/gafter/received_events","type":"User","site_admin":false},"milestone":null,"comments":20,"created_at":"2015-01-31T05:45:04Z","updated_at":"2016-01-19T22:48:59Z","closed_at":null,"body":"# Background\r\n\r\nAs noted in issue #180, many modern programming programs are data-focused, especially distributed applications which tend to store, manipulate, and move sets of data between different storage and computation points. One solution proposed to deal with this issue is a combination of records and pattern matching. Records provide a simple way to declare and structure the data types and pattern matching provides a way to destructure and manipulate the data. \r\n\r\n# Problem\r\n\r\nRecords provide a great way to represent the data and pattern matching provides a great way to manipulate the data, but there is currently no mechanism in the #180 proposal to ensure that the data and the logic remain in sync. The nature of records and pattern matching is that the data declaration code is often far from the data consumption code. In a distributed system it's even more likely that a single data structure will be consumed and manipulated in various parts of the code base. If the data structure is ever modified, there is currently no mechanism in the draft to alert the programmer that all instances of manipulation logic must be updated.\r\n\r\n# Solution\r\n\r\nAdd completeness checking to certain `switch` statements on certain record types. The core of this proposal is to provide a warning when a `switch` statement does not handle every possible match on a type hierarchy. This proposal features two possible designs for this idea, presented in order of increasingly intrusive modification to the language.\r\n\r\n## Design 1\r\n\r\nThis design actually features no new syntax or semantics beyond that of proposal #180. The suggestion is to create a C# type heirarchy which can be guaranteed 'complete' with existing language features. In this case, complete means that it is not possible for a new subclass of the root member of the type hierarchy, so the compiler can be sure that any and all subclasses of the chosen switching type are visible in the current compilation.\r\n\r\nWe can construct this type hierarchy in existing C# with the following rules:\r\n\r\n1. All subclasses of the root type must be sealed, preventing any subclassing of any existing leaf types in the hierarchy.\r\n2. All constructors of the root type must be private, prevent any subclassing of the root type.\r\n  * As a consequence, all subclasses must be inner classes and thus must be in source in the current compilation\r\n\r\nHere's an example of the structure of this type hierarchy:\r\n\r\n```csharp\r\nabstract class C\r\n{\r\n  private C() {}\r\n  public sealed class C_1 : C {}\r\n  public sealed class C_2 : C {}\r\n      ...\r\n  public sealed class C_n : C {}\r\n}\r\n```\r\n\r\nThis guarantees that `switch`ing on an instance of type `C` which explicitly matches `C_1`...`C_n` has matched against every possible instance of `C`. The only thing which changes about the language specification is a requirement that the compiler produce a warning when not all cases are matched.\r\n\r\n## Design 2\r\n\r\nThere are a few disadvantages to Design 1:\r\n\r\n1. The mandated structure is complicated and brittle. Forgetting to mark any of the subclasses as `sealed` or adding any public constructors won't produce a compiler error or warning, but the compiler will now silently skip the completeness check.\r\n2. The structure is verbose -- most of the `sealed` or `private` markers are mostly part of the 'incantation' of completeness and are not directly related to the task at hand.\r\n3. The relevant record instances are all nested classes, so all references require an extra layer of naming indirection.\r\n\r\nDesign 2 attempts to fix these problems by replacing much of the boiler plate with a new combination of modifiers on a type -- `abstract` + `sealed`. Under Design 2, marking the root type of a hierarchy as `abstract sealed` will cause the structure from Design 1 to be generated by the compiler in lowering. The following example demonstrates what the structure from Design 1 looks like with an `abstract sealed` type:\r\n\r\n```csharp\r\nabstract sealed class C {}\r\npublic class C_1 : C {}\r\npublic class C_2 : C {}\r\n   ...\r\npublic class C_n : C {}\r\n```\r\n\r\nIn this case, most of the problems with Design 1 are solved, but new semantics are required to be added to the language."},"comment":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/comments/173013389","html_url":"https://github.com/dotnet/roslyn/issues/188#issuecomment-173013389","issue_url":"https://api.github.com/repos/dotnet/roslyn/issues/188","id":173013389,"user":{"login":"agocke","id":515774,"avatar_url":"https://avatars.githubusercontent.com/u/515774?v=3","gravatar_id":"","url":"https://api.github.com/users/agocke","html_url":"https://github.com/agocke","followers_url":"https://api.github.com/users/agocke/followers","following_url":"https://api.github.com/users/agocke/following{/other_user}","gists_url":"https://api.github.com/users/agocke/gists{/gist_id}","starred_url":"https://api.github.com/users/agocke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/agocke/subscriptions","organizations_url":"https://api.github.com/users/agocke/orgs","repos_url":"https://api.github.com/users/agocke/repos","events_url":"https://api.github.com/users/agocke/events{/privacy}","received_events_url":"https://api.github.com/users/agocke/received_events","type":"User","site_admin":false},"created_at":"2016-01-19T22:48:59Z","updated_at":"2016-01-19T22:48:59Z","body":"@Shiney There are no abstract or concrete interfaces, just interfaces. I'm not sure what you're asking. Can you provide an example?"}}