I find it is untrackable by just reading the plain source code, when the generic relationship is convoluted.
Is there any way to disclose the compiler's instantiation trajectory of a particular generic struct or function?
Elaborated:
Thanks for interesting in this quesion. It is elaborated here. I'm studying the Warp crate recently. So take it for example.
use warp::Filter;
async fn handler_without_parameter() -> Result<impl warp::Reply, warp::Rejection> {
Ok(warp::reply::json(&"dumb".to_string()))
}
fn main() {
let get_items = warp::get()
.and(warp::path("/"))
.and(warp::path::end())
.and_then(handler_without_parameter); //Ok here
}
async fn handler_without_parameter() -> Result<impl warp::Reply, warp::Rejection> {
Ok(warp::reply::json(&"dumb".to_string()))
}
fn main() {
let para: HashMap<String, String> = HashMap::new();
let para_filter = warp::any().map(move || para.clone()); // A filter with data
let get_items = warp::get()
.and(warp::path("/"))
.and(warp::path::end())
.and(para_filter) //chain with the data filter
.and_then(handler_without_parameter); // error[E0593]: function is expected to take 1 argument, but it takes 0 arguments
}
After chaining a filter( which taking along with data), the parameter of the method and_then
is expected to take 1 argument. I'm curious about this requirement change for and_then
, so I try to figure out the monomorphization course of this method.
https://docs.rs/warp/0.3.5/warp/trait.Filter.html#method.and_then
fn and<F>(self, other: F) -> And<Self, F>
where
Self: Sized,
<Self::Extract as Tuple>::HList: Combine<<F::Extract as Tuple>::HList>,
F: Filter + Clone,
F::Error: CombineRejection<Self::Error>,
{
And {
first: self,
second: other,
}
}
fn and_then<F>(self, fun: F) -> AndThen<Self, F>
where
Self: Sized,
F: Func<Self::Extract> + Clone,
F::Output: TryFuture + Send,
<F::Output as TryFuture>::Error: CombineRejection<Self::Error>,
{
AndThen {
filter: self,
callback: fun,
}
}
And the base trait is:
pub trait FilterBase {
type Extract: Tuple; // + Send;
type Error: IsReject;
type Future: Future<Output = Result<Self::Extract, Self::Error>> + Send;
fn filter(&self, internal: Internal) -> Self::Future;
fn map_err<F, E>(self, _internal: Internal, fun: F) -> MapErr<Self, F>
...
}
I can't figure out why the added chaining could incur the requirement change of the and_then
method, since, to me, the generics relation here is very convoluted.
Even with the hints provided by rust-analyzer, it doesn't help a lot, because the Extract = ...
part is eclipsed.