-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix overconstrained Send impls in btree internals #102680
Conversation
r? @thomcc (rust-highfive has picked a reviewer for you, use r? to override) |
Hey! It looks like you've submitted a new PR for the library teams! If this PR contains changes to any Examples of
|
The general issue is #64552 - this fixes a particular instance by eliminating the need for rustc to attempt to prove a lifetime bound on the erased witness types. As long as the new impl is sound, I think it's fine to merge this. However, users will continue to see these unhelpful errors in other cases until the underlying issue is resolved. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, good catch. It doesn't make sense that we'd bound those on the same lifetime we use in the marker, so this looks fine to me.
I don't think this needs libs-api sign-off, as it's hard to imagine how this could be intentionally forbidden, but you'd have a better idea (as someone actually part of that team) so I'll leave that choice to you.
r=me if you move the tests out of uitest (or feel strongly that they shouldn't be moved).
@@ -0,0 +1,20 @@ | |||
// check-fail |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think most people don't bother to run the uitests locally for library patches, and the error message is the same as any other Sync error, so IMO its a bit better to do this as a compile_fail
doctest on something private, and put check-pass
in the normal tests.
That said this is unlikely to unexpectedly break in the future, so if you feel strongly that they should be a uitest
, fine by me as-is.
Currently pretty much all of the btree_map and btree_set ones fail, as well as linked_list::DrainFilter. error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:38:5 | 38 | / require_send_sync(async { 39 | | let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>; 40 | | async {}.await; 41 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:56:5 | 56 | / require_send_sync(async { 57 | | let _v = None::< 58 | | alloc::collections::btree_map::DrainFilter< 59 | | '_, ... | 65 | | async {}.await; 66 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:68:5 | 68 | / require_send_sync(async { 69 | | let _v = None::<alloc::collections::btree_map::Entry<'_, &u32, &u32>>; 70 | | async {}.await; 71 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:88:5 | 88 | / require_send_sync(async { 89 | | let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>; 90 | | async {}.await; 91 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:93:5 | 93 | / require_send_sync(async { 94 | | let _v = None::<alloc::collections::btree_map::IterMut<'_, &u32, &u32>>; 95 | | async {}.await; 96 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:98:5 | 98 | / require_send_sync(async { 99 | | let _v = None::<alloc::collections::btree_map::Keys<'_, &u32, &u32>>; 100 | | async {}.await; 101 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:103:5 | 103 | / require_send_sync(async { 104 | | let _v = None::<alloc::collections::btree_map::OccupiedEntry<'_, &u32, &u32>>; 105 | | async {}.await; 106 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:108:5 | 108 | / require_send_sync(async { 109 | | let _v = None::<alloc::collections::btree_map::OccupiedError<'_, &u32, &u32>>; 110 | | async {}.await; 111 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:113:5 | 113 | / require_send_sync(async { 114 | | let _v = None::<alloc::collections::btree_map::Range<'_, &u32, &u32>>; 115 | | async {}.await; 116 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:118:5 | 118 | / require_send_sync(async { 119 | | let _v = None::<alloc::collections::btree_map::RangeMut<'_, &u32, &u32>>; 120 | | async {}.await; 121 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:123:5 | 123 | / require_send_sync(async { 124 | | let _v = None::<alloc::collections::btree_map::VacantEntry<'_, &u32, &u32>>; 125 | | async {}.await; 126 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:128:5 | 128 | / require_send_sync(async { 129 | | let _v = None::<alloc::collections::btree_map::Values<'_, &u32, &u32>>; 130 | | async {}.await; 131 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:133:5 | 133 | / require_send_sync(async { 134 | | let _v = None::<alloc::collections::btree_map::ValuesMut<'_, &u32, &u32>>; 135 | | async {}.await; 136 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:146:5 | 146 | / require_send_sync(async { 147 | | let _v = None::<alloc::collections::btree_set::Difference<'_, &u32>>; 148 | | async {}.await; 149 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:151:5 | 151 | / require_send_sync(async { 152 | | let _v = None::<alloc::collections::btree_set::DrainFilter<'_, &u32, fn(&&u32) -> bool>>; 153 | | async {}.await; 154 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:156:5 | 156 | / require_send_sync(async { 157 | | let _v = None::<alloc::collections::btree_set::Intersection<'_, &u32>>; 158 | | async {}.await; 159 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:166:5 | 166 | / require_send_sync(async { 167 | | let _v = None::<alloc::collections::btree_set::Iter<'_, &u32>>; 168 | | async {}.await; 169 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:171:5 | 171 | / require_send_sync(async { 172 | | let _v = None::<alloc::collections::btree_set::Range<'_, &u32>>; 173 | | async {}.await; 174 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:176:5 | 176 | / require_send_sync(async { 177 | | let _v = None::<alloc::collections::btree_set::SymmetricDifference<'_, &u32>>; 178 | | async {}.await; 179 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:181:5 | 181 | / require_send_sync(async { 182 | | let _v = None::<alloc::collections::btree_set::Union<'_, &u32>>; 183 | | async {}.await; 184 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: future cannot be sent between threads safely --> library/alloc/tests/autotraits.rs:243:23 | 243 | require_send_sync(async { | _______________________^ 244 | | let _v = 245 | | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>; 246 | | async {}.await; 247 | | }); | |_____^ future created by async block is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NonNull<std::collections::linked_list::Node<&u32>>` note: future is not `Send` as this value is used across an await --> library/alloc/tests/autotraits.rs:246:17 | 244 | let _v = | -- has type `Option<std::collections::linked_list::DrainFilter<'_, &u32, for<'a, 'b> fn(&'a mut &'b u32) -> bool>>` which is not `Send` 245 | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>; 246 | async {}.await; | ^^^^^^ await occurs here, with `_v` maybe used later 247 | }); | - `_v` is later dropped here note: required by a bound in `require_send_sync` --> library/alloc/tests/autotraits.rs:3:25 | 3 | fn require_send_sync<T: Send + Sync>(_: T) {} | ^^^^ required by this bound in `require_send_sync` error: future cannot be shared between threads safely --> library/alloc/tests/autotraits.rs:243:23 | 243 | require_send_sync(async { | _______________________^ 244 | | let _v = 245 | | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>; 246 | | async {}.await; 247 | | }); | |_____^ future created by async block is not `Sync` | = help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `NonNull<std::collections::linked_list::Node<&u32>>` note: future is not `Sync` as this value is used across an await --> library/alloc/tests/autotraits.rs:246:17 | 244 | let _v = | -- has type `Option<std::collections::linked_list::DrainFilter<'_, &u32, for<'a, 'b> fn(&'a mut &'b u32) -> bool>>` which is not `Sync` 245 | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>; 246 | async {}.await; | ^^^^^^ await occurs here, with `_v` maybe used later 247 | }); | - `_v` is later dropped here note: required by a bound in `require_send_sync` --> library/alloc/tests/autotraits.rs:3:32 | 3 | fn require_send_sync<T: Send + Sync>(_: T) {} | ^^^^ required by this bound in `require_send_sync`
Moved test to library/alloc/tests/autotraits.rs and extended it to cover alloc::collections more thoroughly, which revealed a I left out negative tests for now but I am thinking of following up with some based on https://github.com/dtolnay/proc-macro2/blob/1.0.46/tests/marker.rs or the static_assertions crate. |
@bors r+ |
…iaskrgr Rollup of 5 pull requests Successful merges: - rust-lang#98496 (make `compare_const_impl` a query and use it in `instance.rs`) - rust-lang#102680 (Fix overconstrained Send impls in btree internals) - rust-lang#102718 (Fix `opaque_hidden_inferred_bound` lint ICE) - rust-lang#102725 (Remove `-Ztime`) - rust-lang#102736 (Migrate search input color to CSS variable) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Fixes dtolnay/async-trait#215.
Minimal repro:
Not-quite-so-minimal repro:
I am not familiar with the btree internals, but it seems clear to me that the
async fn f
above should return a Send future. Using HashMap instead of BTreeMap in that code makes it already return a Send future.The "higher-ranked lifetime error" message may be a regression in Rust 1.63. Using older compilers the error message was more detailed: