{"action":"created","issue":{"url":"https://api.github.com/repos/rust-lang/rust/issues/48495","repository_url":"https://api.github.com/repos/rust-lang/rust","labels_url":"https://api.github.com/repos/rust-lang/rust/issues/48495/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/rust/issues/48495/comments","events_url":"https://api.github.com/repos/rust-lang/rust/issues/48495/events","html_url":"https://github.com/rust-lang/rust/issues/48495","id":299910148,"node_id":"MDU6SXNzdWUyOTk5MTAxNDg=","number":48495,"title":"Inconsistency when borrow-checking 'ref mut' patterns","user":{"login":"Aaron1011","id":1408859,"node_id":"MDQ6VXNlcjE0MDg4NTk=","avatar_url":"https://avatars1.githubusercontent.com/u/1408859?v=4","gravatar_id":"","url":"https://api.github.com/users/Aaron1011","html_url":"https://github.com/Aaron1011","followers_url":"https://api.github.com/users/Aaron1011/followers","following_url":"https://api.github.com/users/Aaron1011/following{/other_user}","gists_url":"https://api.github.com/users/Aaron1011/gists{/gist_id}","starred_url":"https://api.github.com/users/Aaron1011/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Aaron1011/subscriptions","organizations_url":"https://api.github.com/users/Aaron1011/orgs","repos_url":"https://api.github.com/users/Aaron1011/repos","events_url":"https://api.github.com/users/Aaron1011/events{/privacy}","received_events_url":"https://api.github.com/users/Aaron1011/received_events","type":"User","site_admin":false},"labels":[{"id":604489711,"node_id":"MDU6TGFiZWw2MDQ0ODk3MTE=","url":"https://api.github.com/repos/rust-lang/rust/labels/A-NLL","name":"A-NLL","color":"d7e102","default":false},{"id":171502053,"node_id":"MDU6TGFiZWwxNzE1MDIwNTM=","url":"https://api.github.com/repos/rust-lang/rust/labels/A-borrow-checker","name":"A-borrow-checker","color":"d7e102","default":false},{"id":234902,"node_id":"MDU6TGFiZWwyMzQ5MDI=","url":"https://api.github.com/repos/rust-lang/rust/labels/C-enhancement","name":"C-enhancement","color":"f5f1fd","default":false},{"id":211668019,"node_id":"MDU6TGFiZWwyMTE2NjgwMTk=","url":"https://api.github.com/repos/rust-lang/rust/labels/T-lang","name":"T-lang","color":"bfd4f2","default":false}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-02-24T04:18:52Z","updated_at":"2018-07-03T19:21:18Z","closed_at":"2018-07-03T19:21:18Z","author_association":"CONTRIBUTOR","body":"While investigating https://github.com/rust-lang/rust/issues/48357, I discovered a strange inconsistency in how 'ref mut' patterns are checked.\r\n\r\nThis snippet is correctly rejected both with and without NLL ([playground](https://play.rust-lang.org/?gist=305798e34daee3d89120c5c636107637&version=nightly)):\r\n\r\n```rust\r\n#![feature(nll)]\r\n\r\nenum SimpleFoo {\r\n    Ref(u8)\r\n}\r\n\r\nfn bar(foo: SimpleFoo, other_num: &mut u8) {\r\n    match foo {\r\n        SimpleFoo::Ref(ref mut inner) => {\r\n            *inner = *other_num;\r\n        },\r\n    }\r\n}\r\n\r\nfn main() {}\r\n```\r\n\r\nIt's trying to take a mutable reference to a field of an immutable variable, which clearly should not compile.\r\n\r\nHowever, this snippet compiles both with and without NLL ([playground](https://play.rust-lang.org/?gist=8de749be40cf04a274dfc537900dbaf5&version=nightly)):\r\n\r\n```rust\r\n#![feature(nll)]\r\n\r\nenum SimpleFoo {\r\n    Ref(u8)\r\n}\r\n\r\nfn bar(foo: SimpleFoo, other_num: &mut u8) {\r\n    match (0, foo) {\r\n        (0, SimpleFoo::Ref(ref mut inner)) => {\r\n            *inner = *other_num;\r\n        },\r\n        _ => panic!()\r\n    }\r\n}\r\n\r\nfn main() {}\r\n```\r\n\r\nThe only difference is that `foo` is now part of a struct - but it now borrow checks. Since `foo` is consumed by the match, I don't think that this can lead to any soundness issues - but it's still both surprising and inconsistent.\r\n\r\nThe same issue comes into play in the `image` crate. [This line](https://github.com/PistonDevelopers/image/blob/7e3838a9fa8afde4ed1e6883d57e725a1a42e33f/src/tiff/decoder/mod.rs?utf8=%E2%9C%93#L401) displays the same inconsistency demonstrated in my example. `buffer` is an immutable variable, but a mutable reference is taken to the field of one it's variants (which is itself a mutable reference). The `ColorType` enum takes the place of an integer in the tuple, but the result is the same."},"comment":{"url":"https://api.github.com/repos/rust-lang/rust/issues/comments/402266096","html_url":"https://github.com/rust-lang/rust/issues/48495#issuecomment-402266096","issue_url":"https://api.github.com/repos/rust-lang/rust/issues/48495","id":402266096,"node_id":"MDEyOklzc3VlQ29tbWVudDQwMjI2NjA5Ng==","user":{"login":"nikomatsakis","id":155238,"node_id":"MDQ6VXNlcjE1NTIzOA==","avatar_url":"https://avatars0.githubusercontent.com/u/155238?v=4","gravatar_id":"","url":"https://api.github.com/users/nikomatsakis","html_url":"https://github.com/nikomatsakis","followers_url":"https://api.github.com/users/nikomatsakis/followers","following_url":"https://api.github.com/users/nikomatsakis/following{/other_user}","gists_url":"https://api.github.com/users/nikomatsakis/gists{/gist_id}","starred_url":"https://api.github.com/users/nikomatsakis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nikomatsakis/subscriptions","organizations_url":"https://api.github.com/users/nikomatsakis/orgs","repos_url":"https://api.github.com/users/nikomatsakis/repos","events_url":"https://api.github.com/users/nikomatsakis/events{/privacy}","received_events_url":"https://api.github.com/users/nikomatsakis/received_events","type":"User","site_admin":false},"created_at":"2018-07-03T19:21:18Z","updated_at":"2018-07-03T19:21:18Z","author_association":"CONTRIBUTOR","body":"This may be surprising, but it's the \"expected\" behavior from my POV. In particular, what happens is that `(0, foo)` constructs a tuple -- you are then matching against this tuple, which is a temporary. Temporaries are always considered mutable. This is what allows things like `foo.bar().iter_mut()` to type-check as well (since the return value of `bar()` will be stored in a temporary that will then be borrowed for the `iter_mut` call). Closing as \"working as designed, for better or worse\"."}}
{"actor":{"display_login":"nikomatsakis"}}