Hi there!
I'm writing a generic - over request/return types and the path separator character - router module and have encountered issues during testing.
Unfortunately, I couldn't very much reduce it to a simpler reproduction, but I'll try to be descriptive enough so that it's not a pain for you kind souls to dig through it. It's not a large library by any means - most if it is testing code, really.
The code is available on GitHub and requires min_const_generics
to build - unless of course you get rid of const SEPARATOR: char
everywhere, which, in hindsight, I really should have done myself. Apologies.
So what's happening is that when I define the handler to use a &[u8]
as its Request
type, Rust suddenly complains about mismatched types, which, by the way, are more likely "just" mismatched lifetimes.
error[E0308]: mismatched types
--> src\router.rs:115:57
|
115 | router.define(route.clone(), RouteHandler::Function(&handler));
| ^^^^^^^^ one type is more general than the other
|
= note: expected enum `std::result::Result<_, Error<'_, '_, &[u8]>>`
found enum `std::result::Result<_, Error<'_, 'request, &[u8]>>`
The test function (router.rs:108
) that fails to build is this:
#[test]
fn define() -> anyhow::Result<()> {
let mut router = Router::<_, _, '/'>::new();
let route = Route::parse("hello/there");
let other_route = Route::parse("hello/where");
router.define(route.clone(), RouteHandler::Function(&handler));
assert_eq!(router.routes.len(), 1);
assert!(router.get(&route).is_some());
assert!(router.get(&other_route).is_none());
Ok(())
}
And handler
refers to the following function (router.rs:89
):
fn handler<'router, 'request>(
params: HashMap<&'router str, &'request str>,
request: &'request [u8],
) -> Result<
'router,
'request,
&'request [u8],
bool,
> {
if params.len() != 1 || params["subject"] != "general" {
return Err(Error::InvalidParams(params.clone()));
}
match request {
[0x42] => Ok(true),
request => Err(Error::InvalidRequest(request)),
}
}
If I just replace &'request [u8]
(router.rs:91
and router.rs:95
) with an owned value like u8
and change [0x42]
to 0x42
(as an example), the build succeeds.
I'm not sure if I'm overlooking some straightforward lifetime rule or it's a limitation of Rust, but I've exhausted all my knowledge on the topic - which really wasn't much to begin with.
I've been banging my head against a wall over this for two days now, and I feel like my mind is at a point where it's physically incapable of coming up with a new angle. Any and all help is much appreciated!