{"action":"created","issue":{"url":"https://api.github.com/repos/rust-lang/rust/issues/23136","labels_url":"https://api.github.com/repos/rust-lang/rust/issues/23136/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/rust/issues/23136/comments","events_url":"https://api.github.com/repos/rust-lang/rust/issues/23136/events","html_url":"https://github.com/rust-lang/rust/issues/23136","id":60186890,"number":23136,"title":"regression in regionck / lifetime elision - \"`T` may not live enough\" errors","user":{"login":"japaric","id":5018213,"avatar_url":"https://avatars.githubusercontent.com/u/5018213?v=3","gravatar_id":"","url":"https://api.github.com/users/japaric","html_url":"https://github.com/japaric","followers_url":"https://api.github.com/users/japaric/followers","following_url":"https://api.github.com/users/japaric/following{/other_user}","gists_url":"https://api.github.com/users/japaric/gists{/gist_id}","starred_url":"https://api.github.com/users/japaric/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/japaric/subscriptions","organizations_url":"https://api.github.com/users/japaric/orgs","repos_url":"https://api.github.com/users/japaric/repos","events_url":"https://api.github.com/users/japaric/events{/privacy}","received_events_url":"https://api.github.com/users/japaric/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2015-03-07T02:53:41Z","updated_at":"2015-03-07T18:19:24Z","closed_at":null,"body":"### STR\r\n\r\nThis is an extract from [linalg.rs](https://github.com/japaric/linalg.rs/tree/19acc2c45861d3747f40763bfc3e5b921cc7f5cb) (sorry, it's a bit long)\r\n\r\n``` rust\r\npub mod strided {\r\n    use raw;\r\n\r\n    pub struct Slice<'a, T>(pub raw::Slice<'a, T>) where T: 'a;\r\n    impl<'a, T> Copy for Slice<'a, T> {}\r\n    pub struct SliceMut<'a, T>(pub raw::Slice<'a, T>) where T: 'a;\r\n}\r\n\r\npub mod raw {\r\n    use std::marker::PhantomData;\r\n\r\n    pub struct Slice<'a, T> where T: 'a {\r\n        _marker: PhantomData<&'a T>,\r\n        data: *mut T,\r\n        len: usize,\r\n    }\r\n\r\n    impl<'a, T> Copy for Slice<'a, T> {}\r\n}\r\n\r\npub struct MutRow<'a, T>(strided::SliceMut<'a, T>) where T: 'a;\r\npub struct Row<'a, T>(strided::Slice<'a, T>) where T: 'a;\r\nimpl<'a, T> Copy for Row<'a, T> {}\r\npub struct Scaled<T, M>(T, M);\r\n\r\n#[cfg(yesterday)]\r\nimpl<'a, 'b, T> AddAssign<Scaled<T, Row<'a, T>>> for MutRow<'b, T> {\r\n    fn add_assign(&mut self, rhs: &Scaled<T, Row<T>>) {\r\n        let &mut MutRow(strided::SliceMut(lhs)) = self;\r\n        let &Scaled(ref alpha, Row(strided::Slice(rhs))) = rhs;\r\n\r\n        axpy(lhs, alpha, rhs)\r\n    }\r\n}\r\n\r\n#[cfg(today)]\r\nimpl<'a, 'b, T> AddAssign<Scaled<T, Row<'a, T>>> for MutRow<'b, T>\r\n    where T: 'a,  // <--\r\n{\r\n    fn add_assign(&mut self, rhs: &Scaled<T, Row<'a, T>>) {  // <-- `Row<['a], T>`\r\n        let &mut MutRow(strided::SliceMut(lhs)) = self;\r\n        let &Scaled(ref alpha, Row(strided::Slice(rhs))) = rhs;\r\n\r\n        axpy(lhs, alpha, rhs)\r\n    }\r\n}\r\n\r\nfn axpy<T>(_: raw::Slice<T>, _: &T, _: raw::Slice<T>) {}\r\n\r\npub trait AddAssign<Rhs> {\r\n    fn add_assign(&mut self, &Rhs);\r\n}\r\n\r\nfn main() {}\r\n```\r\n\r\n### Stderr\r\n\r\n``` rust\r\nbug.rs:31:60: 31:63 error: the parameter type `T` may not live long enough [E0311]\r\nbug.rs:31         let &Scaled(ref alpha, Row(strided::Slice(rhs))) = rhs;\r\n                                                                     ^~~\r\nbug.rs:31:63: 31:63 help: consider adding an explicit lifetime bound for `T`\r\nbug.rs:29:55: 34:6 note: the parameter type `T` must be valid for the anonymous lifetime #3 defined on the block at 29:54...\r\nbug.rs:29     fn add_assign(&mut self, rhs: &Scaled<T, Row<T>>) {\r\nbug.rs:30         let &mut MutRow(strided::SliceMut(lhs)) = self;\r\nbug.rs:31         let &Scaled(ref alpha, Row(strided::Slice(rhs))) = rhs;\r\nbug.rs:32\r\nbug.rs:33         axpy(lhs, alpha, rhs)\r\nbug.rs:34     }\r\nbug.rs:31:60: 31:63 note: ...so that the type `T` will meet its required lifetime bounds\r\nbug.rs:31         let &Scaled(ref alpha, Row(strided::Slice(rhs))) = rhs;\r\n                                                                     ^~~\r\nerror: aborting due to previous error\r\n```\r\n\r\n---\r\n\r\nBoth cfg(today) and cfg(yesterday) compile with yesterday's nightly (`(3b3bb0e68 2015-03-04) (built 2015-03-05)`) but cfg(yesterday) fails to compile with today's nightly (`(b0746ff19 2015-03-05) (built 2015-03-06)`), the `impl` had to be changed to `cfg(today)` to make the code compile.\r\n\r\nI think the extra lifetime and bound in cfg(today) are redundant:\r\n\r\n- `where T: 'a` should be inferred from the use of `Row<'a, T>`, since it seems that `T: 'b` is being inferred from the `RowMut<'b, T>`.\r\n- The `'a` in `rhs: &Scaled<T, Row<'a, T>>` shouldn't be necessary, since its already spelled out in the `AddAssign<Scaled<T, Row<'a, T>>>`\r\n\r\nIn `linalg`s `src/add_assign.rs` there are several similar `impl`s where the lifetimes and bounds can be elided, and a few other `impl`s that need explicit annotation.\r\n\r\ncc @nikomatsakis "},"comment":{"url":"https://api.github.com/repos/rust-lang/rust/issues/comments/77702040","html_url":"https://github.com/rust-lang/rust/issues/23136#issuecomment-77702040","issue_url":"https://api.github.com/repos/rust-lang/rust/issues/23136","id":77702040,"user":{"login":"eddyb","id":77424,"avatar_url":"https://avatars.githubusercontent.com/u/77424?v=3","gravatar_id":"","url":"https://api.github.com/users/eddyb","html_url":"https://github.com/eddyb","followers_url":"https://api.github.com/users/eddyb/followers","following_url":"https://api.github.com/users/eddyb/following{/other_user}","gists_url":"https://api.github.com/users/eddyb/gists{/gist_id}","starred_url":"https://api.github.com/users/eddyb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eddyb/subscriptions","organizations_url":"https://api.github.com/users/eddyb/orgs","repos_url":"https://api.github.com/users/eddyb/repos","events_url":"https://api.github.com/users/eddyb/events{/privacy}","received_events_url":"https://api.github.com/users/eddyb/received_events","type":"User","site_admin":false},"created_at":"2015-03-07T18:19:24Z","updated_at":"2015-03-07T18:19:24Z","body":"@mahkoh I don't understand how `fn() -> &'a T` is supposed to be any different from `&'a T` - that seems like a bug.\r\nAlso, do we really need to keep `T: 'a` and `'a: 'b` explicit?\r\nI've always thought @nikomatsakis was planning to add the automatic bounds back."}}