将 impl 与通用参数混合使用和不使用它们有什么影响吗?

Does mixing impl with generic parameters and without them have any implications?

说,我有以下代码:

use std::ptr::NonNull;
use std::marker::PhantomPinned;
use std::pin::Pin;

#[derive(Debug)]
struct Unmovable {
    data: Vec<String>,
    cache: Option<NonNull<String>>,
    _pin: PhantomPinned,
}

impl<'a> Unmovable {
    pub fn new(data: Vec<String>) -> Pin<Box<Self>> {
        let internal = Self {
            data,
            cache: None,
            _pin: PhantomPinned
        };

        let mut boxed = Box::pin(internal);
        let cache = if boxed.data.len() > 0 {
            Some(NonNull::from(&boxed.data[0]))
        } else {
            None
        };

        unsafe {
            let ref_mut: Pin<&mut Unmovable> = Pin::as_mut(&mut boxed);
            Pin::get_unchecked_mut(ref_mut).cache = cache;
        }

        boxed
    }
    pub fn get_cache(&'a self) -> Option<&'a String> {
        Some(unsafe { self.cache?.as_ref() })
    }
}

fn main() {
    let unm = Unmovable::new(vec!["hello".to_owned(), "there".to_owned()]);
    println!("{:?}", unm);
    println!("{:?}", unm.get_cache());
}

我想知道,函数 new 是在泛型指定的 impl 块中实现还是在没有该泛型参数的情况下单独实现,有什么区别,因为它没有在那里使用。说实话,我有点惊讶 Rust 确实允许这样做,impl 一个不使用所有泛型的函数,因为它被禁止用于结构,例如。所以我很好奇这样的混合声明是否有一些含义。

new 函数是否相当于 impl 旁边没有泛型的单独实现?

类型参数或常量泛型将被禁止。但是 impl 上的免费生命周期是允许的。它们仅在关联类型中使用时才被禁止。原理解释in the source code:

    // (*) This is a horrible concession to reality. I think it'd be
    // better to just ban unconstrained lifetimes outright, but in
    // practice people do non-hygienic macros like:
    //
    // ```
    // macro_rules! __impl_slice_eq1 {
    //     ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
    //         impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
    //            ....
    //         }
    //     }
    // }
    // ```
    //
    // In a concession to backwards compatibility, we continue to
    // permit those, so long as the lifetimes aren't used in
    // associated types. I believe this is sound, because lifetimes
    // used elsewhere are not projected back out.

我对 rustc 的内部结构知之甚少,无法确定,但我很确定它不会影响任何事情。最好不要使用它;在需要它的方法上使用生命周期,而不是在实现上。