{"action":"created","comment":{"url":"https://api.github.com/repos/dotnet/csharplang/pulls/comments/105484671","pull_request_review_id":26372378,"id":105484671,"diff_hunk":"@@ -0,0 +1,161 @@\n+# Blittable Types\n+\n+* [x] Proposed\n+* [ ] Prototype\n+* [ ] Implementation\n+* [ ] Specification\n+\n+## Summary\n+[summary]: #summary\n+\n+The blittable feature will give language enforcement to the class of types known as \"unmanaged types\" in the C# language spec.  This is defined in section 18.2 as a type which is not a reference type and doesn't contain reference type fields at any level of nesting.  \n+\n+## Motivation\n+[motivation]: #motivation\n+\n+The primary motivation is to make it easier to author low level interop code in C#.  Blittable types are one of the core building blocks for interop code, yet abstracting around them is difficult today due to a lack of declarative language support.  \n+\n+This is the case even though blittable types are well defined in the language spec and many features, like pointers, can operate only on them.  The language chooses to let structs implicitly opt into being blittable by virtue of their construction with no avenue for opting out of such a classification.\n+\n+While attractive in small applications this is more difficult to manage across a large set of libraries authored by different developers.  It means small field additions to structs can cause compile and runtime breaks in downstream consumers with no warning to the developers that made the change.  This spooky action at a distance is one of the core problems with having an implicit opt in model here. \n+\n+A declarative, explicit opt in model makes it easier to code in this area.  Developers can be very explicit about the types they intend for interop.  This gives them compiler help when mistakes are made in their application and in any libraries they consume.  \n+\n+The lack of compile time support also makes it difficult to abstract over blittable types.  It's not possible for instance to author common helper routines using generic code:\n+\n+``` c#\n+void Hash<T>(T value) where T : blittable struct\n+{\n+    using (T* p = &value) { \n+        ...\n+    }\n+}\n+```\n+\n+Instead developers are forced to rewrite virtually the same code for all of their blittable types:\n+\n+``` c#\n+void Hash(Point p) { \n+    ...\n+}\n+\n+void Hash(Time t) { \n+    ...\n+}\n+```\n+\n+The lack of constraints here also make it impossible to have efficient conversions between streams of data and more structured types.  This is an operation that is common in networking stacks and serialization layers:\n+\n+``` c#\n+Span<byte> Convert<T>(ref T value) where T : blittable {\n+    ...\n+}\n+```\n+\n+Such routines are advantageous because they are provably safe at compile time and allocation free.  Interop authors today can not due this (even though it's at a layer where perf is critical).  Instead they need to rely on allocating routines that have expensive runtime checks to verify values are correctly blittable.\n+\n+## Detailed design\n+[design]: #detailed-design\n+\n+The language will introduce a new declaration modifier named `blittable` that can be applied to `struct` definitions.  \n+\n+``` c#\n+blittable struct Point \n+{\n+    public int X;\n+    public int Y;\n+}\n+```\n+\n+The compiler will enforce that the fields of such a struct definition fit one of the following categories:\n+\n+- `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `char`, `float`, `double`, `decimal`, or `bool`.","path":"proposals/blittable.md","position":72,"original_position":72,"commit_id":"4daf8b0bce2739dec53bc91074883f9466ad8ebf","original_commit_id":"4daf8b0bce2739dec53bc91074883f9466ad8ebf","user":{"login":"jaredpar","id":146967,"avatar_url":"https://avatars3.githubusercontent.com/u/146967?v=3","gravatar_id":"","url":"https://api.github.com/users/jaredpar","html_url":"https://github.com/jaredpar","followers_url":"https://api.github.com/users/jaredpar/followers","following_url":"https://api.github.com/users/jaredpar/following{/other_user}","gists_url":"https://api.github.com/users/jaredpar/gists{/gist_id}","starred_url":"https://api.github.com/users/jaredpar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaredpar/subscriptions","organizations_url":"https://api.github.com/users/jaredpar/orgs","repos_url":"https://api.github.com/users/jaredpar/repos","events_url":"https://api.github.com/users/jaredpar/events{/privacy}","received_events_url":"https://api.github.com/users/jaredpar/received_events","type":"User","site_admin":false},"body":"> Decimal, Guid, DateTime, DateTimeOffset, and TimeSpan are implicitly blittable as they are structs composed of blittable types.\r\n\r\nI've waffled a bit on whether these should be special cased as implicitly blittable, or waiting for source annotations to happen.  Leaning towards implicit.  \r\n\r\n> char and bool are in the category of \"sometimes blittable\", so we should be careful about including them.\r\n\r\nBeen way down this rabbit hole in Midori.  The basic problem comes down to whether you believe bilttable means ... \r\n\r\n1. A type which has no field, at any level of nesting, whose type is a reference type \r\n1. 1 + the constraint that all possible bit patterns represent a valid instance of the type \r\n\r\nIn Midori we actually separated this out into two features: primitive and blittable.  All blittable are primitive but not the other way around.  The distinction was interesting but IMHO wasn't worth the extra complexity. \r\n\r\nIn any case though, this feature definitely targets 1 above.  It's the language manifestation of the existing spec concept of \"unmanaged type\".  \r\n\r\n\r\n\r\n\r\n","created_at":"2017-03-10T20:43:02Z","updated_at":"2017-03-10T20:43:02Z","html_url":"https://github.com/dotnet/csharplang/pull/206#discussion_r105484671","pull_request_url":"https://api.github.com/repos/dotnet/csharplang/pulls/206","_links":{"self":{"href":"https://api.github.com/repos/dotnet/csharplang/pulls/comments/105484671"},"html":{"href":"https://github.com/dotnet/csharplang/pull/206#discussion_r105484671"},"pull_request":{"href":"https://api.github.com/repos/dotnet/csharplang/pulls/206"}}},"pull_request":{"url":"https://api.github.com/repos/dotnet/csharplang/pulls/206","id":108255880,"html_url":"https://github.com/dotnet/csharplang/pull/206","diff_url":"https://github.com/dotnet/csharplang/pull/206.diff","patch_url":"https://github.com/dotnet/csharplang/pull/206.patch","issue_url":"https://api.github.com/repos/dotnet/csharplang/issues/206","number":206,"state":"open","locked":false,"title":"Initial blittable proposal","user":{"login":"jaredpar","id":146967,"avatar_url":"https://avatars3.githubusercontent.com/u/146967?v=3","gravatar_id":"","url":"https://api.github.com/users/jaredpar","html_url":"https://github.com/jaredpar","followers_url":"https://api.github.com/users/jaredpar/followers","following_url":"https://api.github.com/users/jaredpar/following{/other_user}","gists_url":"https://api.github.com/users/jaredpar/gists{/gist_id}","starred_url":"https://api.github.com/users/jaredpar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaredpar/subscriptions","organizations_url":"https://api.github.com/users/jaredpar/orgs","repos_url":"https://api.github.com/users/jaredpar/repos","events_url":"https://api.github.com/users/jaredpar/events{/privacy}","received_events_url":"https://api.github.com/users/jaredpar/received_events","type":"User","site_admin":false},"body":"This is the initial proposal for the blittable feature as tracked by #187. ","created_at":"2017-02-28T04:21:18Z","updated_at":"2017-03-10T20:43:02Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f7492d26ccb9b5d5b3307a05914bd11aeaad7a4d","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/dotnet/csharplang/pulls/206/commits","review_comments_url":"https://api.github.com/repos/dotnet/csharplang/pulls/206/comments","review_comment_url":"https://api.github.com/repos/dotnet/csharplang/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dotnet/csharplang/issues/206/comments","statuses_url":"https://api.github.com/repos/dotnet/csharplang/statuses/4daf8b0bce2739dec53bc91074883f9466ad8ebf","head":{"label":"jaredpar:blittable","ref":"blittable","sha":"4daf8b0bce2739dec53bc91074883f9466ad8ebf","user":{"login":"jaredpar","id":146967,"avatar_url":"https://avatars3.githubusercontent.com/u/146967?v=3","gravatar_id":"","url":"https://api.github.com/users/jaredpar","html_url":"https://github.com/jaredpar","followers_url":"https://api.github.com/users/jaredpar/followers","following_url":"https://api.github.com/users/jaredpar/following{/other_user}","gists_url":"https://api.github.com/users/jaredpar/gists{/gist_id}","starred_url":"https://api.github.com/users/jaredpar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaredpar/subscriptions","organizations_url":"https://api.github.com/users/jaredpar/orgs","repos_url":"https://api.github.com/users/jaredpar/repos","events_url":"https://api.github.com/users/jaredpar/events{/privacy}","received_events_url":"https://api.github.com/users/jaredpar/received_events","type":"User","site_admin":false},"repo":{"id":83361163,"name":"csharplang","full_name":"jaredpar/csharplang","owner":{"login":"jaredpar","id":146967,"avatar_url":"https://avatars3.githubusercontent.com/u/146967?v=3","gravatar_id":"","url":"https://api.github.com/users/jaredpar","html_url":"https://github.com/jaredpar","followers_url":"https://api.github.com/users/jaredpar/followers","following_url":"https://api.github.com/users/jaredpar/following{/other_user}","gists_url":"https://api.github.com/users/jaredpar/gists{/gist_id}","starred_url":"https://api.github.com/users/jaredpar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaredpar/subscriptions","organizations_url":"https://api.github.com/users/jaredpar/orgs","repos_url":"https://api.github.com/users/jaredpar/repos","events_url":"https://api.github.com/users/jaredpar/events{/privacy}","received_events_url":"https://api.github.com/users/jaredpar/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jaredpar/csharplang","description":"The official repo for the design of the C# programming language","fork":true,"url":"https://api.github.com/repos/jaredpar/csharplang","forks_url":"https://api.github.com/repos/jaredpar/csharplang/forks","keys_url":"https://api.github.com/repos/jaredpar/csharplang/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jaredpar/csharplang/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jaredpar/csharplang/teams","hooks_url":"https://api.github.com/repos/jaredpar/csharplang/hooks","issue_events_url":"https://api.github.com/repos/jaredpar/csharplang/issues/events{/number}","events_url":"https://api.github.com/repos/jaredpar/csharplang/events","assignees_url":"https://api.github.com/repos/jaredpar/csharplang/assignees{/user}","branches_url":"https://api.github.com/repos/jaredpar/csharplang/branches{/branch}","tags_url":"https://api.github.com/repos/jaredpar/csharplang/tags","blobs_url":"https://api.github.com/repos/jaredpar/csharplang/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jaredpar/csharplang/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jaredpar/csharplang/git/refs{/sha}","trees_url":"https://api.github.com/repos/jaredpar/csharplang/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jaredpar/csharplang/statuses/{sha}","languages_url":"https://api.github.com/repos/jaredpar/csharplang/languages","stargazers_url":"https://api.github.com/repos/jaredpar/csharplang/stargazers","contributors_url":"https://api.github.com/repos/jaredpar/csharplang/contributors","subscribers_url":"https://api.github.com/repos/jaredpar/csharplang/subscribers","subscription_url":"https://api.github.com/repos/jaredpar/csharplang/subscription","commits_url":"https://api.github.com/repos/jaredpar/csharplang/commits{/sha}","git_commits_url":"https://api.github.com/repos/jaredpar/csharplang/git/commits{/sha}","comments_url":"https://api.github.com/repos/jaredpar/csharplang/comments{/number}","issue_comment_url":"https://api.github.com/repos/jaredpar/csharplang/issues/comments{/number}","contents_url":"https://api.github.com/repos/jaredpar/csharplang/contents/{+path}","compare_url":"https://api.github.com/repos/jaredpar/csharplang/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jaredpar/csharplang/merges","archive_url":"https://api.github.com/repos/jaredpar/csharplang/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jaredpar/csharplang/downloads","issues_url":"https://api.github.com/repos/jaredpar/csharplang/issues{/number}","pulls_url":"https://api.github.com/repos/jaredpar/csharplang/pulls{/number}","milestones_url":"https://api.github.com/repos/jaredpar/csharplang/milestones{/number}","notifications_url":"https://api.github.com/repos/jaredpar/csharplang/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jaredpar/csharplang/labels{/name}","releases_url":"https://api.github.com/repos/jaredpar/csharplang/releases{/id}","deployments_url":"https://api.github.com/repos/jaredpar/csharplang/deployments","created_at":"2017-02-27T21:57:44Z","updated_at":"2017-02-27T10:34:22Z","pushed_at":"2017-02-28T04:20:06Z","git_url":"git://github.com/jaredpar/csharplang.git","ssh_url":"git@github.com:jaredpar/csharplang.git","clone_url":"https://github.com/jaredpar/csharplang.git","svn_url":"https://github.com/jaredpar/csharplang","homepage":"","size":580,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"dotnet:master","ref":"master","sha":"81bbace21292d762db7c7f2f7bbe95d6e49c685f","user":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars3.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"repo":{"id":75990888,"name":"csharplang","full_name":"dotnet/csharplang","owner":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars3.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dotnet/csharplang","description":"The official repo for the design of the C# programming language","fork":false,"url":"https://api.github.com/repos/dotnet/csharplang","forks_url":"https://api.github.com/repos/dotnet/csharplang/forks","keys_url":"https://api.github.com/repos/dotnet/csharplang/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dotnet/csharplang/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dotnet/csharplang/teams","hooks_url":"https://api.github.com/repos/dotnet/csharplang/hooks","issue_events_url":"https://api.github.com/repos/dotnet/csharplang/issues/events{/number}","events_url":"https://api.github.com/repos/dotnet/csharplang/events","assignees_url":"https://api.github.com/repos/dotnet/csharplang/assignees{/user}","branches_url":"https://api.github.com/repos/dotnet/csharplang/branches{/branch}","tags_url":"https://api.github.com/repos/dotnet/csharplang/tags","blobs_url":"https://api.github.com/repos/dotnet/csharplang/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dotnet/csharplang/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dotnet/csharplang/git/refs{/sha}","trees_url":"https://api.github.com/repos/dotnet/csharplang/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dotnet/csharplang/statuses/{sha}","languages_url":"https://api.github.com/repos/dotnet/csharplang/languages","stargazers_url":"https://api.github.com/repos/dotnet/csharplang/stargazers","contributors_url":"https://api.github.com/repos/dotnet/csharplang/contributors","subscribers_url":"https://api.github.com/repos/dotnet/csharplang/subscribers","subscription_url":"https://api.github.com/repos/dotnet/csharplang/subscription","commits_url":"https://api.github.com/repos/dotnet/csharplang/commits{/sha}","git_commits_url":"https://api.github.com/repos/dotnet/csharplang/git/commits{/sha}","comments_url":"https://api.github.com/repos/dotnet/csharplang/comments{/number}","issue_comment_url":"https://api.github.com/repos/dotnet/csharplang/issues/comments{/number}","contents_url":"https://api.github.com/repos/dotnet/csharplang/contents/{+path}","compare_url":"https://api.github.com/repos/dotnet/csharplang/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dotnet/csharplang/merges","archive_url":"https://api.github.com/repos/dotnet/csharplang/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dotnet/csharplang/downloads","issues_url":"https://api.github.com/repos/dotnet/csharplang/issues{/number}","pulls_url":"https://api.github.com/repos/dotnet/csharplang/pulls{/number}","milestones_url":"https://api.github.com/repos/dotnet/csharplang/milestones{/number}","notifications_url":"https://api.github.com/repos/dotnet/csharplang/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dotnet/csharplang/labels{/name}","releases_url":"https://api.github.com/repos/dotnet/csharplang/releases{/id}","deployments_url":"https://api.github.com/repos/dotnet/csharplang/deployments","created_at":"2016-12-09T01:45:27Z","updated_at":"2017-03-10T20:10:40Z","pushed_at":"2017-03-08T18:04:42Z","git_url":"git://github.com/dotnet/csharplang.git","ssh_url":"git@github.com:dotnet/csharplang.git","clone_url":"https://github.com/dotnet/csharplang.git","svn_url":"https://github.com/dotnet/csharplang","homepage":"","size":589,"stargazers_count":598,"watchers_count":598,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":43,"mirror_url":null,"open_issues_count":185,"forks":43,"open_issues":185,"watchers":598,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dotnet/csharplang/pulls/206"},"html":{"href":"https://github.com/dotnet/csharplang/pull/206"},"issue":{"href":"https://api.github.com/repos/dotnet/csharplang/issues/206"},"comments":{"href":"https://api.github.com/repos/dotnet/csharplang/issues/206/comments"},"review_comments":{"href":"https://api.github.com/repos/dotnet/csharplang/pulls/206/comments"},"review_comment":{"href":"https://api.github.com/repos/dotnet/csharplang/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dotnet/csharplang/pulls/206/commits"},"statuses":{"href":"https://api.github.com/repos/dotnet/csharplang/statuses/4daf8b0bce2739dec53bc91074883f9466ad8ebf"}}}}
{"actor":{"display_login":"jaredpar"}}