type parameter {Q}
is part of concrete type but not used in parameter list for the impl Trait
type alias
and the reference seems like a rabbit hole
type parameter {Q}
is part of concrete type but not used in parameter list for the impl Trait
type alias
and the reference seems like a rabbit hole
Can you post your code that generates the error?
a code example is here in playground
#![feature(type_alias_impl_trait)]
use std::rc::Rc;
type CallbackInner<IN, OUT> = impl Fn(IN) -> OUT;
pub struct Callback<IN, OUT = ()> {
cb: Rc<CallbackInner<IN, OUT>>,
}
impl<IN, OUT, F: Fn(IN) -> OUT + 'static> From<F> for Callback<IN, OUT> {
fn from(func: F) -> Self {
Callback { cb: Rc::new(func) }
}
}
A TAIT is supposed to refer to a specific concrete type, so that generic From impl doesn't make a lot of sense. The From impl accepts an open set of types, for this to work Callback could only be constructed only with one specific type. TAIT is generally more useful as a output than (as is in this case) an input.
In this case, there’s not much reason to use impl Fn(…)
instead of dyn Fn(…)
: You’re storing the closure inside an Rc
, so it’s behind a pointer anyway.
use std::rc::Rc;
type CallbackInner<IN, OUT> = dyn Fn(IN) -> OUT;
pub struct Callback<IN, OUT = ()> {
cb: Rc<CallbackInner<IN, OUT>>,
}
impl<IN, OUT, F: Fn(IN) -> OUT + 'static> From<F> for Callback<IN, OUT> {
fn from(func: F) -> Self {
Callback { cb: Rc::new(func) }
}
}
The inputs to the TAIT must uniquely determine the output -- the aliased type. But in your playground there are multiple F
that could be used to define the alias. This is possible because F
is not an input to the TAIT ("not used in parameter list") even though it is part of the alias ("concrete type") .
A direct fix would be to make F
an input to the TAIT.
Seems like the op might instead have been looking for trait aliases? I don't think it works much better here, but it makes more sense.
Hmm, like so? Perhaps, the motivation is unclear to me. If so, you can do something similar on stable.
Without implied bounds, you're going have to repeat the bounds on the F
parameter everywhere anyway, so I'd be inclined to just
pub struct Callback<F> {
cb: Rc<F>,
}
impl<F> From<F> for Callback<F> {
fn from(func: F) -> Self {
Callback { cb: Rc::new(func) }
}
}
at the struct level.
Yeah, that's what I meant by it not working much better, but if you understand the difference between trait aliases and TAIT, I doubt that you would think the OP code would work?
Honestly, thinking more on it, I think they were just trying to look for a way to spell:
pub struct Callback<IN, OUT = ()> {
cb: Rc<impl Fn(IN) -> OUT>,
}
which is understandable, but is basically impossible. (Unless Rust just picks dyn
, which I guess is technically correct)
Yeah... probably @2e71828's reply is the closest thing to that, probably exactly what they want if they need to accept "everything" like the From
implementation implies. It could be adapted to TAIT to hide the dyn Fn(In) -> Out
but I don't see a point to doing so. I guess that would still be more flexible if the type is public somehow and you might wrap up the closures in something else later on.
I assume there's an opaque type alias RFC somewhere, but I can only find TAIT by that name. I suppose newtype-ing is good enough.
https://rust-lang.github.io/rfcs/2071-impl-trait-existential-types.html
https://rust-lang.github.io/rfcs/2515-type_alias_impl_trait.html
Yeah, that's what I found by the name "opaque types". I meant something like pub type PublicName = not_pub private::Name
where nothing about PublicName
leaks, apropos to:
Oh, I misunderstood, I thought you couldn't find the RFCs because it got renamed / is usually abbreviated . TAIT is the opaque alias RFC as far as I'm aware. It is a little funny you can't declare and define it in one go, but then again, self-documentation is the only real reason I can think of to do so. (If you never use it, why do you need it?)
Related: private_in_public
and RFC 2145.
I'm doing diagnostic message migration and uncapble of understanding the error message, which makes me worry.
The code was found in an issue I lost track of.
Ah, then I would be talking about whoever wrote that code, assuming they weren't trying to produce this error!
I do think the error could be improved. I'm not sure what the bar for unstable features is though?
Perhaps something like:
No type for
CallbackInner<IN, OUT>
could be determined, as this expression requires it to have a parameter forF
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.