{"action":"created","comment":{"url":"https://api.github.com/repos/nrc/rustfmt/pulls/comments/32927796","id":32927796,"diff_hunk":"@@ -159,6 +159,27 @@ macro_rules! impl_enum_decodable {\n     };\n }\n \n+// Same as try!, but for Option\n+#[macro_export]\n+macro_rules! try_opt {\n+    ($expr:expr) => (match $expr {\n+        Some(val) => val,\n+        None => { return None; }\n+    })\n+}\n+\n+// Unwraps an iterator of Options. If any element is None, return None\n+#[macro_export]\n+macro_rules! try_opt_collect {\n+    ($expr:expr) => ({\n+        let mut res = Vec::with_capacity($expr.size_hint().0);","path":"src/utils.rs","position":17,"original_position":17,"commit_id":"4349611e31484c308e687a1aa9d5a535fc2f22a3","original_commit_id":"4349611e31484c308e687a1aa9d5a535fc2f22a3","user":{"login":"marcusklaas","id":1255413,"avatar_url":"https://avatars.githubusercontent.com/u/1255413?v=3","gravatar_id":"","url":"https://api.github.com/users/marcusklaas","html_url":"https://github.com/marcusklaas","followers_url":"https://api.github.com/users/marcusklaas/followers","following_url":"https://api.github.com/users/marcusklaas/following{/other_user}","gists_url":"https://api.github.com/users/marcusklaas/gists{/gist_id}","starred_url":"https://api.github.com/users/marcusklaas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marcusklaas/subscriptions","organizations_url":"https://api.github.com/users/marcusklaas/orgs","repos_url":"https://api.github.com/users/marcusklaas/repos","events_url":"https://api.github.com/users/marcusklaas/events{/privacy}","received_events_url":"https://api.github.com/users/marcusklaas/received_events","type":"User","site_admin":false},"body":"Could using `$expr` twice have unintended consequences? When it alters mutable state, for example? It think we're evaluating the expression twice anyway, which is not optimal.\r\n\r\nMaybe we should `let e = $expr;` first.","created_at":"2015-06-22T12:16:09Z","updated_at":"2015-06-22T12:16:09Z","html_url":"https://github.com/nrc/rustfmt/pull/107#discussion_r32927796","pull_request_url":"https://api.github.com/repos/nrc/rustfmt/pulls/107","_links":{"self":{"href":"https://api.github.com/repos/nrc/rustfmt/pulls/comments/32927796"},"html":{"href":"https://github.com/nrc/rustfmt/pull/107#discussion_r32927796"},"pull_request":{"href":"https://api.github.com/repos/nrc/rustfmt/pulls/107"}}},"pull_request":{"url":"https://api.github.com/repos/nrc/rustfmt/pulls/107","id":37633411,"html_url":"https://github.com/nrc/rustfmt/pull/107","diff_url":"https://github.com/nrc/rustfmt/pull/107.diff","patch_url":"https://github.com/nrc/rustfmt/pull/107.patch","issue_url":"https://api.github.com/repos/nrc/rustfmt/issues/107","number":107,"state":"open","locked":false,"title":"Add a Rewrite trait","user":{"login":"cassiersg","id":9348542,"avatar_url":"https://avatars.githubusercontent.com/u/9348542?v=3","gravatar_id":"","url":"https://api.github.com/users/cassiersg","html_url":"https://github.com/cassiersg","followers_url":"https://api.github.com/users/cassiersg/followers","following_url":"https://api.github.com/users/cassiersg/following{/other_user}","gists_url":"https://api.github.com/users/cassiersg/gists{/gist_id}","starred_url":"https://api.github.com/users/cassiersg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cassiersg/subscriptions","organizations_url":"https://api.github.com/users/cassiersg/orgs","repos_url":"https://api.github.com/users/cassiersg/repos","events_url":"https://api.github.com/users/cassiersg/events{/privacy}","received_events_url":"https://api.github.com/users/cassiersg/received_events","type":"User","site_admin":false},"body":"This PR is just a proposal of a new trait, and is primarily intended for discussion. It's a draft of implementation of an idea I wanted to share and discuss. It's just an idea, that will maybe not well work.\r\n\r\nBecause it might change a lot of code, I prefer to discuss it before a complete implementation.\r\n\r\nMotivation\r\n---------\r\n\r\nWe have a recurrent pattern in the code: rewrite some code with a given offset and width. (It's very common in `expr.rs`, for example).\r\n\r\nI wanted to abstract \"something that can be rewritten into offset and width\" when working on list formatting. Format a list (of args, types parameters...) is also something useful. With the current `lists` module, it needs some recurrent code, essentially : rewrite all items of the list within a maximal width, but the last one within the given width.\r\n\r\nI found a lot of these patterns when I tried to format types (`ast::Ty`).\r\n\r\nDesign\r\n-------\r\n\r\nThe idea is quite simple: add a new trait `Rewrite` to represent the \r\n```rust\r\npub trait Rewrite {\r\n    fn rewrite(&self, width: usize, offset: usize) -> Option<(String, Option<Comment>)>;\r\n}\r\n```\r\n`rewrite` returns an `Option` to express the fact that it's sometime not possible to not excess the given width. (Should it be a `Result` instead ?) The first element of the tuple (`String`) is the code formatted, and the second is a possible comment. Getting the comment separated of the code gives more degrees of freedom to the caller : it can put the comment on an own line before the code, of at the end of the line. The enum `Comment` is intended to be able to make a difference between a doc comment and another kind of comment (we will eventually replace bloc comments with line comments), but it's maybe not useful and a simple string would be sufficient.\r\n\r\nThe current implementation of this trait to format lists is only used by a place-holder for the `write_list` function.\r\n\r\nAt the very end, all `rewrite_*` functions could be impls of `Rewrite`.\r\n\r\nWhen it comes to implement and use this trait, things are getting wrong : it makes sense to implement it for `ast::Expr`, and using `rewrite_expr` as the `rewrite` method, but it doesn't work since `rewrite_expr` is itself a method of `FmtVisitor`.\r\n\r\nI see two solutions to this problem : in the longterm, we might have a self-sufficient AST, and `FmtVisitor` would not more be needed. Currently, it's not possible though. The second solution is to create structs containing the item we want to format and a ref to the `FmtVisitor`. I don't know if this approach would be sustainable if we use it extensively. There is maybe another solution. (?)\r\n\r\nI tried also an alternative, which is a more ad-hoc solution : pass the rewriting function as argument of `rewrite_list`. It looked me a bit \"hackish\" and less extensible, but maybe it's only because i'm not used to that.\r\n\r\nSo, please let me know what you think about it.\r\n\r\nAbout the list formatting algorithm, and tuple formatting, the changes are not very relevant, it's just an example of impl of `Rewrite`. The tuple formatting is a good example of use case for `Rewrite` : the same algorithm may be used for tuple litterals and for tuple types.","created_at":"2015-06-13T23:46:14Z","updated_at":"2015-06-22T12:16:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"767cf50a023fd28b18c58a15f8c343f2b5c6a866","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/nrc/rustfmt/pulls/107/commits","review_comments_url":"https://api.github.com/repos/nrc/rustfmt/pulls/107/comments","review_comment_url":"https://api.github.com/repos/nrc/rustfmt/pulls/comments{/number}","comments_url":"https://api.github.com/repos/nrc/rustfmt/issues/107/comments","statuses_url":"https://api.github.com/repos/nrc/rustfmt/statuses/4349611e31484c308e687a1aa9d5a535fc2f22a3","head":{"label":"cassiersg:rewrite","ref":"rewrite","sha":"4349611e31484c308e687a1aa9d5a535fc2f22a3","user":{"login":"cassiersg","id":9348542,"avatar_url":"https://avatars.githubusercontent.com/u/9348542?v=3","gravatar_id":"","url":"https://api.github.com/users/cassiersg","html_url":"https://github.com/cassiersg","followers_url":"https://api.github.com/users/cassiersg/followers","following_url":"https://api.github.com/users/cassiersg/following{/other_user}","gists_url":"https://api.github.com/users/cassiersg/gists{/gist_id}","starred_url":"https://api.github.com/users/cassiersg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cassiersg/subscriptions","organizations_url":"https://api.github.com/users/cassiersg/orgs","repos_url":"https://api.github.com/users/cassiersg/repos","events_url":"https://api.github.com/users/cassiersg/events{/privacy}","received_events_url":"https://api.github.com/users/cassiersg/received_events","type":"User","site_admin":false},"repo":{"id":36189450,"name":"rustfmt","full_name":"cassiersg/rustfmt","owner":{"login":"cassiersg","id":9348542,"avatar_url":"https://avatars.githubusercontent.com/u/9348542?v=3","gravatar_id":"","url":"https://api.github.com/users/cassiersg","html_url":"https://github.com/cassiersg","followers_url":"https://api.github.com/users/cassiersg/followers","following_url":"https://api.github.com/users/cassiersg/following{/other_user}","gists_url":"https://api.github.com/users/cassiersg/gists{/gist_id}","starred_url":"https://api.github.com/users/cassiersg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cassiersg/subscriptions","organizations_url":"https://api.github.com/users/cassiersg/orgs","repos_url":"https://api.github.com/users/cassiersg/repos","events_url":"https://api.github.com/users/cassiersg/events{/privacy}","received_events_url":"https://api.github.com/users/cassiersg/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/cassiersg/rustfmt","description":"Format Rust code","fork":true,"url":"https://api.github.com/repos/cassiersg/rustfmt","forks_url":"https://api.github.com/repos/cassiersg/rustfmt/forks","keys_url":"https://api.github.com/repos/cassiersg/rustfmt/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cassiersg/rustfmt/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cassiersg/rustfmt/teams","hooks_url":"https://api.github.com/repos/cassiersg/rustfmt/hooks","issue_events_url":"https://api.github.com/repos/cassiersg/rustfmt/issues/events{/number}","events_url":"https://api.github.com/repos/cassiersg/rustfmt/events","assignees_url":"https://api.github.com/repos/cassiersg/rustfmt/assignees{/user}","branches_url":"https://api.github.com/repos/cassiersg/rustfmt/branches{/branch}","tags_url":"https://api.github.com/repos/cassiersg/rustfmt/tags","blobs_url":"https://api.github.com/repos/cassiersg/rustfmt/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cassiersg/rustfmt/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cassiersg/rustfmt/git/refs{/sha}","trees_url":"https://api.github.com/repos/cassiersg/rustfmt/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cassiersg/rustfmt/statuses/{sha}","languages_url":"https://api.github.com/repos/cassiersg/rustfmt/languages","stargazers_url":"https://api.github.com/repos/cassiersg/rustfmt/stargazers","contributors_url":"https://api.github.com/repos/cassiersg/rustfmt/contributors","subscribers_url":"https://api.github.com/repos/cassiersg/rustfmt/subscribers","subscription_url":"https://api.github.com/repos/cassiersg/rustfmt/subscription","commits_url":"https://api.github.com/repos/cassiersg/rustfmt/commits{/sha}","git_commits_url":"https://api.github.com/repos/cassiersg/rustfmt/git/commits{/sha}","comments_url":"https://api.github.com/repos/cassiersg/rustfmt/comments{/number}","issue_comment_url":"https://api.github.com/repos/cassiersg/rustfmt/issues/comments{/number}","contents_url":"https://api.github.com/repos/cassiersg/rustfmt/contents/{+path}","compare_url":"https://api.github.com/repos/cassiersg/rustfmt/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cassiersg/rustfmt/merges","archive_url":"https://api.github.com/repos/cassiersg/rustfmt/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cassiersg/rustfmt/downloads","issues_url":"https://api.github.com/repos/cassiersg/rustfmt/issues{/number}","pulls_url":"https://api.github.com/repos/cassiersg/rustfmt/pulls{/number}","milestones_url":"https://api.github.com/repos/cassiersg/rustfmt/milestones{/number}","notifications_url":"https://api.github.com/repos/cassiersg/rustfmt/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cassiersg/rustfmt/labels{/name}","releases_url":"https://api.github.com/repos/cassiersg/rustfmt/releases{/id}","created_at":"2015-05-24T19:37:31Z","updated_at":"2015-05-24T19:37:32Z","pushed_at":"2015-06-22T11:33:26Z","git_url":"git://github.com/cassiersg/rustfmt.git","ssh_url":"git@github.com:cassiersg/rustfmt.git","clone_url":"https://github.com/cassiersg/rustfmt.git","svn_url":"https://github.com/cassiersg/rustfmt","homepage":null,"size":353,"stargazers_count":0,"watchers_count":0,"language":"Rust","has_issues":false,"has_downloads":true,"has_wiki":true,"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":"nrc:master","ref":"master","sha":"b74cdb7b533a1c9b37ed66e74ca5246887d9afef","user":{"login":"nrc","id":762626,"avatar_url":"https://avatars.githubusercontent.com/u/762626?v=3","gravatar_id":"","url":"https://api.github.com/users/nrc","html_url":"https://github.com/nrc","followers_url":"https://api.github.com/users/nrc/followers","following_url":"https://api.github.com/users/nrc/following{/other_user}","gists_url":"https://api.github.com/users/nrc/gists{/gist_id}","starred_url":"https://api.github.com/users/nrc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nrc/subscriptions","organizations_url":"https://api.github.com/users/nrc/orgs","repos_url":"https://api.github.com/users/nrc/repos","events_url":"https://api.github.com/users/nrc/events{/privacy}","received_events_url":"https://api.github.com/users/nrc/received_events","type":"User","site_admin":false},"repo":{"id":31830551,"name":"rustfmt","full_name":"nrc/rustfmt","owner":{"login":"nrc","id":762626,"avatar_url":"https://avatars.githubusercontent.com/u/762626?v=3","gravatar_id":"","url":"https://api.github.com/users/nrc","html_url":"https://github.com/nrc","followers_url":"https://api.github.com/users/nrc/followers","following_url":"https://api.github.com/users/nrc/following{/other_user}","gists_url":"https://api.github.com/users/nrc/gists{/gist_id}","starred_url":"https://api.github.com/users/nrc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nrc/subscriptions","organizations_url":"https://api.github.com/users/nrc/orgs","repos_url":"https://api.github.com/users/nrc/repos","events_url":"https://api.github.com/users/nrc/events{/privacy}","received_events_url":"https://api.github.com/users/nrc/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/nrc/rustfmt","description":"Format Rust code","fork":false,"url":"https://api.github.com/repos/nrc/rustfmt","forks_url":"https://api.github.com/repos/nrc/rustfmt/forks","keys_url":"https://api.github.com/repos/nrc/rustfmt/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nrc/rustfmt/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nrc/rustfmt/teams","hooks_url":"https://api.github.com/repos/nrc/rustfmt/hooks","issue_events_url":"https://api.github.com/repos/nrc/rustfmt/issues/events{/number}","events_url":"https://api.github.com/repos/nrc/rustfmt/events","assignees_url":"https://api.github.com/repos/nrc/rustfmt/assignees{/user}","branches_url":"https://api.github.com/repos/nrc/rustfmt/branches{/branch}","tags_url":"https://api.github.com/repos/nrc/rustfmt/tags","blobs_url":"https://api.github.com/repos/nrc/rustfmt/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nrc/rustfmt/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nrc/rustfmt/git/refs{/sha}","trees_url":"https://api.github.com/repos/nrc/rustfmt/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nrc/rustfmt/statuses/{sha}","languages_url":"https://api.github.com/repos/nrc/rustfmt/languages","stargazers_url":"https://api.github.com/repos/nrc/rustfmt/stargazers","contributors_url":"https://api.github.com/repos/nrc/rustfmt/contributors","subscribers_url":"https://api.github.com/repos/nrc/rustfmt/subscribers","subscription_url":"https://api.github.com/repos/nrc/rustfmt/subscription","commits_url":"https://api.github.com/repos/nrc/rustfmt/commits{/sha}","git_commits_url":"https://api.github.com/repos/nrc/rustfmt/git/commits{/sha}","comments_url":"https://api.github.com/repos/nrc/rustfmt/comments{/number}","issue_comment_url":"https://api.github.com/repos/nrc/rustfmt/issues/comments{/number}","contents_url":"https://api.github.com/repos/nrc/rustfmt/contents/{+path}","compare_url":"https://api.github.com/repos/nrc/rustfmt/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nrc/rustfmt/merges","archive_url":"https://api.github.com/repos/nrc/rustfmt/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nrc/rustfmt/downloads","issues_url":"https://api.github.com/repos/nrc/rustfmt/issues{/number}","pulls_url":"https://api.github.com/repos/nrc/rustfmt/pulls{/number}","milestones_url":"https://api.github.com/repos/nrc/rustfmt/milestones{/number}","notifications_url":"https://api.github.com/repos/nrc/rustfmt/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nrc/rustfmt/labels{/name}","releases_url":"https://api.github.com/repos/nrc/rustfmt/releases{/id}","created_at":"2015-03-07T22:51:56Z","updated_at":"2015-06-21T14:44:41Z","pushed_at":"2015-06-22T11:33:27Z","git_url":"git://github.com/nrc/rustfmt.git","ssh_url":"git@github.com:nrc/rustfmt.git","clone_url":"https://github.com/nrc/rustfmt.git","svn_url":"https://github.com/nrc/rustfmt","homepage":null,"size":1186,"stargazers_count":204,"watchers_count":204,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":30,"mirror_url":null,"open_issues_count":53,"forks":30,"open_issues":53,"watchers":204,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/nrc/rustfmt/pulls/107"},"html":{"href":"https://github.com/nrc/rustfmt/pull/107"},"issue":{"href":"https://api.github.com/repos/nrc/rustfmt/issues/107"},"comments":{"href":"https://api.github.com/repos/nrc/rustfmt/issues/107/comments"},"review_comments":{"href":"https://api.github.com/repos/nrc/rustfmt/pulls/107/comments"},"review_comment":{"href":"https://api.github.com/repos/nrc/rustfmt/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/nrc/rustfmt/pulls/107/commits"},"statuses":{"href":"https://api.github.com/repos/nrc/rustfmt/statuses/4349611e31484c308e687a1aa9d5a535fc2f22a3"}}}}