-
-
Notifications
You must be signed in to change notification settings - Fork 85
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
higher-ranked lifetime error
with a simple example involving a BTreeMap
#215
Labels
Comments
Seems like a standard library bug. Minimized: //use std::collections::HashMap as Map;
use std::collections::BTreeMap as Map;
fn assert_send<T: Send>(_: T) {}
fn main() {
assert_send(async {
let map = Map::<u32, Box<dyn Send + Sync>>::new();
let _iter = map.iter();
async {}.await;
});
} |
Apparently this is rust-lang/rust#64552. |
Thanks a lot for identifying the root cause in the standard library and even fixing it there, that's awesome! |
matthiaskrgr
added a commit
to matthiaskrgr/rust
that referenced
this issue
Oct 6, 2022
Fix overconstrained Send impls in btree internals Fixes dtolnay/async-trait#215. Minimal repro: ```rust use std::collections::btree_map::Iter; fn require_send<T: Send>(_: T) {} fn main() { require_send(async { let _iter = None::<Iter<(), &()>>; async {}.await; }); } ``` ```console error: higher-ranked lifetime error --> src/main.rs:6:5 | 6 | / require_send(async { 7 | | let _iter = None::<Iter<(), &()>>; 8 | | async {}.await; 9 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` ``` Not-quite-so-minimal repro: ```rust use std::collections::BTreeMap; use std::future::Future; fn spawn<T: Future + Send>(_: T) {} async fn f() { let map = BTreeMap::<u32, Box<dyn Send + Sync>>::new(); for _ in &map { async {}.await; } } fn main() { spawn(f()); } ``` ```console error: higher-ranked lifetime error --> src/main.rs:14:5 | 14 | spawn(f()); | ^^^^^^^^^^ | = note: could not prove `impl Future<Output = ()>: Send` ``` 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: ```console error: implementation of `Send` is not general enough --> src/main.rs:14:5 | 14 | spawn(f()); | ^^^^^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Immut<'0>, u32, Box<(dyn Send + Sync + '1)>, alloc::collections::btree::node::marker::LeafOrInternal>`, for any two lifetimes `'0` and `'1`... = note: ...but `Send` is actually implemented for the type `alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Immut<'2>, u32, Box<dyn Send + Sync>, alloc::collections::btree::node::marker::LeafOrInternal>`, for some specific lifetime `'2` error: implementation of `Send` is not general enough --> src/main.rs:14:5 | 14 | spawn(f()); | ^^^^^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Immut<'0>, u32, Box<(dyn Send + Sync + '1)>, alloc::collections::btree::node::marker::Leaf>`, for any two lifetimes `'0` and `'1`... = note: ...but `Send` is actually implemented for the type `alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Immut<'2>, u32, Box<dyn Send + Sync>, alloc::collections::btree::node::marker::Leaf>`, for some specific lifetime `'2` ```
thomcc
pushed a commit
to tcdi/postgrestd
that referenced
this issue
Feb 10, 2023
Fix overconstrained Send impls in btree internals Fixes dtolnay/async-trait#215. Minimal repro: ```rust use std::collections::btree_map::Iter; fn require_send<T: Send>(_: T) {} fn main() { require_send(async { let _iter = None::<Iter<(), &()>>; async {}.await; }); } ``` ```console error: higher-ranked lifetime error --> src/main.rs:6:5 | 6 | / require_send(async { 7 | | let _iter = None::<Iter<(), &()>>; 8 | | async {}.await; 9 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` ``` Not-quite-so-minimal repro: ```rust use std::collections::BTreeMap; use std::future::Future; fn spawn<T: Future + Send>(_: T) {} async fn f() { let map = BTreeMap::<u32, Box<dyn Send + Sync>>::new(); for _ in &map { async {}.await; } } fn main() { spawn(f()); } ``` ```console error: higher-ranked lifetime error --> src/main.rs:14:5 | 14 | spawn(f()); | ^^^^^^^^^^ | = note: could not prove `impl Future<Output = ()>: Send` ``` 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: ```console error: implementation of `Send` is not general enough --> src/main.rs:14:5 | 14 | spawn(f()); | ^^^^^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Immut<'0>, u32, Box<(dyn Send + Sync + '1)>, alloc::collections::btree::node::marker::LeafOrInternal>`, for any two lifetimes `'0` and `'1`... = note: ...but `Send` is actually implemented for the type `alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Immut<'2>, u32, Box<dyn Send + Sync>, alloc::collections::btree::node::marker::LeafOrInternal>`, for some specific lifetime `'2` error: implementation of `Send` is not general enough --> src/main.rs:14:5 | 14 | spawn(f()); | ^^^^^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Immut<'0>, u32, Box<(dyn Send + Sync + '1)>, alloc::collections::btree::node::marker::Leaf>`, for any two lifetimes `'0` and `'1`... = note: ...but `Send` is actually implemented for the type `alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Immut<'2>, u32, Box<dyn Send + Sync>, alloc::collections::btree::node::marker::Leaf>`, for some specific lifetime `'2` ```
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The following (playground)
results in
however, it works fine when the BTreeMap is replaced by a HashMap.
Might that be an issue with
async_trait
, or something I misunderstood?The text was updated successfully, but these errors were encountered: