Problematic behavior not appearing in rustdoc by private fields

⚓ Rust    📅 2025-09-16    👤 surdeus    👁️ 1      

surdeus

I am not good at English. Sorry if there are any funny expressions.


My two types have almost identical formats in rustdoc. However, when I used them in the same way, only one caused compile error. On my investigation, the cause seems to lie in the private fields (that aren't output in rustdoc).

- Question 1
This was surprising based on my experience with other languages. I believed that with just by API documentation, I could determine whether the code passed compilation. But Rust is not? Or is it just that the code below is so unnatural it's not even worth considering? (Especially MyType1 using PhantomData in odd way...)

- Question 2
I researched the specification around lifetime elision, but couldn't find the relevant section for the problematic lifetime inference (though it might just be my lack of English skill...)

Code

In the following, rustdoc outputs of MyType1 and MyType2 is almost identical (There are minor differences around Sync, etc). But MyType2 seems to have inferred T: 'a because it has a field of type &'a T. (I was doing this manually every time.)

use std::marker::PhantomData;

fn test() {
    let a = 42;
    test1(MyType1::new(Box::new(&a))); // ✔️ Compile OK
    test2(MyType2::new(Box::new(&a))); // ❌ Compile NG
}

fn test1<T>(_arg: MyType1<'static, T>) {}
fn test2<T>(_arg: MyType2<'static, T>) {}

pub struct MyType1<'a, T> {
    val: T,
    pd: PhantomData<&'a()> // 👈 Difference
}

pub struct MyType2<'a, T> {
    val: T,
    pd: PhantomData<&'a T> // 👈 Difference
}

impl<T> MyType1<'_, T> {
    pub fn new(val: T) -> Self {
        Self { val, pd: PhantomData }
    }
}

impl<T> MyType2<'_, T> {
    pub fn new(val: T) -> Self {
        Self { val, pd: PhantomData }
    }
}

error[E0597]: `a` does not live long enough
 --> src\lib.rs:6:33
  |
4 |     let a = 42;
  |         - binding `a` declared here
5 |     test1(MyType1::new(Box::new(&a)));
6 |     test2(MyType2::new(Box::new(&a)));
  |     ----------------------------^^---
  |     |                           |
  |     |                           borrowed value does not live long enough
  |     argument requires that `a` is borrowed for `'static`
7 | }
  | - `a` dropped here while still borrowed

6 posts - 3 participants

Read full topic

🏷️ Rust_feed