Skip to content

Inherent method specialization #14

@lambda-fairy

Description

@lambda-fairy

Thanks for writing up the autoref specialization guide!

There's a similar technique which depends on Rust favoring inherent impls over traits.

Taking the DisplayToString example:

use std::fmt::{Display, Write};

pub trait DisplayToString {
    fn my_to_string(&self) -> String;
}

pub struct DisplayToStringWrapper<'a, T: ?Sized>(pub &'a T);

// This is an inherent method, so it's tried first
impl<'a, T: AsRef<str> + ?Sized> DisplayToStringWrapper<'a, T> {
    pub fn my_to_string(&self) -> String {
        println!("called specialized impl");
        self.0.as_ref().into()
    }
}

// This is only used if the inherent method fails to type-check
impl<'a, T: Display + ?Sized> DisplayToString for DisplayToStringWrapper<'a, T> {
    fn my_to_string(&self) -> String {
        println!("blanket impl");
        self.to_string()
    }
}

This can be more reliable than the autoref approach. For example, (&&String::from("hello")).my_to_string() will fall back to the slow path using autoref specialization but stick to the fast path with inherent impls. The drawback is that it only allows for one fallback case. Overall, I think this approach makes some interesting tradeoffs and may be worth calling (hehe) out in the article!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions