I'm implementing a function which is generic over implementations of nearest-neighbor maps. I'd like to hide the exact details of how I use this nearest-neighbor map, but require that maps still implement a generic trait when one of the generic parameters is a "secret" struct - in other words, they can only use a blanket implementation to implement the helper trait.
I've included a stripped-down version of what I'd like to do here:
mod lib {
pub trait Helper<T> { }
struct Secret;
pub struct Zeb<B>(B);
pub fn foo<B: Helper<Secret>>(b: B) -> Zeb<B> {
Zeb(b)
}
}
mod client {
use super::lib::{foo, Helper};
struct Bar<T>(Option<T>);
impl<T> Helper<T> for Bar<T> {}
pub fn baz() {
// error: type `Secret` is private
let zeb = foo(Bar(None));
}
}
Is there a way that I can expose the function foo without exposing Secret as a public type, while still letting users call foo with a custom helper?
What's weird for me is that (ignoring visibility errors for a second), you're trying to pass a Bar<?> (implementing Helper<Option<?>>) to a function taking a Helper<Secret>.
Is there something wonky happening in transcription? I've copied over to a playground here which reproduces the error for me.
Your recommendation to use the canonical sealing pattern does in fact work, though, which I think is the real solution.
#![allow(dead_code, private_bounds)]
mod lib {
pub trait Helper<T> {}
mod private {
pub struct Secret {}
}
use private::Secret;
pub struct Zeb<B>(B);
pub fn foo<B: Helper<Secret>>(b: B) -> Zeb<B> {
Zeb(b)
}
}
mod client {
use super::lib::{foo, Helper};
struct Bar<T>(Option<T>);
impl<T> Helper<T> for Bar<T> {}
pub fn baz() {
// error: type `Secret` is private
let _zeb = foo(Bar(None));
}
}
No - rather, I want to force the user to implement Helper<Secret> for Bar<Secret>, without allowing them to reference the Secret. If you'd like an example which more closely models what I'm trying to achieve (but has the same error as the simplified version), check here. However, this is all just noise on top of the original issue in the OP.