-
Notifications
You must be signed in to change notification settings - Fork 0
minijinja: type annotations needed #195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Labels
from-crater
A regression found via a crater run, not part of our test suite
Comments
Instance of #168 enum Value {
String(String),
U32(u32),
}
trait Arg<'a> {
type Output;
fn from_value(value: &'a Value) -> Option<Self::Output>;
}
impl<'a, 'b> Arg<'a> for &'b str {
type Output = &'a str;
fn from_value(value: &'a Value) -> Option<Self::Output> {
match value {
Value::String(s) => Some(s),
Value::U32(_) => None,
}
}
}
impl<'a> Arg<'a> for u32 {
type Output = u32;
fn from_value(value: &'a Value) -> Option<Self::Output> {
match value {
Value::String(_) => None,
Value::U32(x) => Some(*x),
}
}
}
fn get_values() -> Vec<Value> {
vec![Value::String("string".into()), Value::U32(128)]
}
trait Filter<A> {
fn filter(&mut self, arg: A);
}
impl<A, F: FnMut(A)> Filter<A> for F {
fn filter(&mut self, arg: A) {
self(arg)
}
}
fn inspect_values<F, A>(mut f: F)
where
A: for<'a> Arg<'a>,
F: for<'a> Filter<<A as Arg<'a>>::Output> + Filter<A>,
{
let values = get_values();
for arg in values.iter().filter_map(A::from_value) {
f.filter(arg);
}
}
fn generic_caller<F, A>(f: F)
where
A: for<'a> Arg<'a>,
F: for<'a> Filter<<A as Arg<'a>>::Output> + Filter<A>,
{
inspect_values(f)
}
fn main() {
generic_caller(|x: u32| println!("{x}"));
generic_caller(|x: &str| println!("'{}' has len {}", x, x.len()));
} |
Tragic :< |
a rewrite which should fix this? enum Value {
String(String),
U32(u32),
}
trait Arg<'a> {
type Output;
fn from_value(value: &'a Value) -> Option<Self::Output>;
}
impl<'a, 'b> Arg<'a> for &'b str {
type Output = &'a str;
fn from_value(value: &'a Value) -> Option<Self::Output> {
match value {
Value::String(s) => Some(s),
Value::U32(_) => None,
}
}
}
impl<'a> Arg<'a> for u32 {
type Output = u32;
fn from_value(value: &'a Value) -> Option<Self::Output> {
match value {
Value::String(_) => None,
Value::U32(x) => Some(*x),
}
}
}
fn get_values() -> Vec<Value> {
vec![Value::String("string".into()), Value::U32(128)]
}
trait Filter<A: for<'a> Arg<'a>> {
fn filter<'a>(&mut self, arg: <A as Arg<'a>>::Output);
}
// Move both `FnMut` bounds to the impl of `Filter` instead of having
// two generic bounds. This means we're now always choosing a unique
// where-bound in `generic_caller` and no longer rely on incomplete
// alias-relate.
impl<A: for<'a> Arg<'a>, F: for<'a> FnMut(<A as Arg<'a>>::Output) + FnMut(A)> Filter<A> for F {
fn filter<'a>(&mut self, arg: <A as Arg<'a>>::Output) {
self(arg)
}
}
fn inspect_values<F, A>(mut f: F)
where
A: for<'a> Arg<'a>,
F: Filter<A>,
{
let values = get_values();
for arg in values.iter().filter_map(A::from_value) {
f.filter(arg);
}
}
fn generic_caller<F, A>(f: F)
where
A: for<'a> Arg<'a>,
F: Filter<A>,
{
inspect_values(f)
}
fn foo(x: &str) {
println!("this is '{x}'")
}
fn main() {
generic_caller(|x: u32| println!("{x}"));
generic_caller(|x: &str| println!("'{}' has len {}", x, x.len()));
generic_caller(foo);
} |
fixed by mitsuhiko/minijinja#787 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The text was updated successfully, but these errors were encountered: