Why doesn't information like Send "leak" about associated types through RPIT functions?
⚓ Rust 📅 2026-03-17 👤 surdeus 👁️ 2Return position impl Trait happily allows details about the actual concrete implementation to leak to users. For example, even if we return only impl Any we can tell whether the actual type implements Send or not (playground):
fn check_send<T: Send>(t: T) {}
fn foo() -> impl Any {
0
}
fn bar() -> impl Any {
fn make_mutex_guard() -> MutexGuard<'static, ()> {
todo!();
}
make_mutex_guard()
}
fn baz() {
check_send(foo());
// Doesn't compile:
// check_send(bar());
}
I've always thought this "leaking" of information was a little weird, but I could believe it's necessary to make other language features work harmoniously. However when I tried to lean into it, I found that it doesn't work for types associated with the anonymous implementation returned (playground):
trait SomeTrait {
type AssocType;
fn make_assoc_type(&self) -> Self::AssocType {
todo!();
}
}
impl SomeTrait for () {
type AssocType = i32;
}
fn foo() -> impl SomeTrait {
()
}
fn baz() {
check_send(foo().make_assoc_type());
}
error[E0277]: `<impl SomeTrait as SomeTrait>::AssocType` cannot be sent between threads safely
--> src/lib.rs:24:16
|
24 | check_send(foo().make_assoc_type());
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^ `<impl SomeTrait as SomeTrait>::AssocType` cannot be sent between threads safely
| |
| required by a bound introduced by this call
|
= help: the trait `Send` is not implemented for `<impl SomeTrait as SomeTrait>::AssocType`
note: required by a bound in `check_send`
Why is this treated differently? Why does the leaking of this information only extend for one level? It's not as if the compiler doesn't know the real, concrete associated type here, because I can e.g. allocate space for it on the heap.
1 post - 1 participant
🏷️ Rust_feed