Исходный выпуск
Этот фрагмент кода относительно похож на фрагмент кода, который я пытаюсь исправить. Я также спросил об этом на форуме пользователя Rust .
игровая площадка
/// assume this function can't be modified.
fn foo<A>(
f1: impl Fn(&str) -> Result<(&str, A), ()>,
base: &str,
f2: impl Fn(A) -> bool
) {
let s: String = base.to_owned();
let option = Some(s.as_ref());
let mapped = option.map(f1);
let r = mapped.unwrap();
let (rem, prod) = r.unwrap();
assert!(f2(prod));
assert_eq!(rem.len(), 0);
}
fn main() {
fn bar<'a>(s: &'a str) -> Result<(&'a str, &'a str), ()> {
Ok((&s[..1], &s[..]))
}
fn baz(s: &str) -> Result<(&str, &str), ()> {
Ok((&s[..1], &s[..]))
}
foo(bar, "string", |s| s.len() == 5); // fails to compile
foo(baz, "string", |s| s.len() == 5); // fails to compile
}
error[E0271]: type mismatch resolving `for<'r> <for<'a> fn(&'a str) -> std::result::Result<(&'a str, &'a str), ()> {main::bar} as std::ops::FnOnce<(&'r str,)>>::Output == std::result::Result<(&'r str, _), ()>`
--> src/main.rs:27:5
|
2 | fn foo<A>(
| ---
3 | f1: impl Fn(&str) -> Result<(&str, A), ()>,
| --------------------- required by this bound in `foo`
...
27 | foo(bar, "string", |s| s.len() == 5); // fails to compile
| ^^^ expected bound lifetime parameter, found concrete lifetime
Изменить:
Основываясь на рекомендациях ряда людей здесь, в ветке внутренних компонентов , которую я сделал , и на форуме пользователей rust я изменил свой код, чтобы упростить его, используя черту оболочки.
игровая площадка
trait Parser<'s> {
type Output;
fn call(&self, input: &'s str) -> (&'s str, Self::Output);
}
impl<'s, F, T> Parser<'s> for F
where F: Fn(&'s str) -> (&'s str, T) {
type Output = T;
fn call(&self, input: &'s str) -> (&'s str, T) {
self(input)
}
}
fn foo<F1, F2>(
f1: F1,
base: &'static str,
f2: F2
)
where
F1: for<'a> Parser<'a>,
F2: FnOnce(&<F1 as Parser>::Output) -> bool
{
// These two lines cannot be changed.
let s: String = base.to_owned();
let str_ref = s.as_ref();
let (remaining, produced) = f1.call(str_ref);
assert!(f2(&produced));
assert_eq!(remaining.len(), 0);
}
struct Wrapper<'a>(&'a str);
fn main() {
fn bar<'a>(s: &'a str) -> (&'a str, &'a str) {
(&s[..1], &s[..])
}
fn baz<'a>(s: &'a str) -> (&'a str, Wrapper<'a>) {
(&s[..1], Wrapper(&s[..]))
}
foo(bar, "string", |s| s.len() == 5); // fails to compile
foo(baz, "string", |s| s.0.len() == 5); // fails to compile
}
этот код в настоящее время генерирует внутреннюю ошибку компилятора:
error: internal compiler error: src/librustc_infer/traits/codegen/mod.rs:61: Encountered error `OutputTypeParameterMismatch(Binder(<[closure@src/main.rs:45:24: 45:40] as std::ops::FnOnce<(&<for<'a> fn(&'a str) -> (&'a str, &'a str) {main::bar} as Parser<'_>>::Output,)>>), Binder(<[closure@src/main.rs:45:24: 45:40] as std::ops::FnOnce<(&&str,)>>), Sorts(ExpectedFound { expected: &str, found: <for<'a> fn(&'a str) -> (&'a str, &'a str) {main::bar} as Parser<'_>>::Output }))` selecting `Binder(<[closure@src/main.rs:45:24: 45:40] as std::ops::FnOnce<(&&str,)>>)` during codegen
thread 'rustc' panicked at 'Box<Any>', src/librustc_errors/lib.rs:875:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
note: rustc 1.43.0 (4fb7144ed 2020-04-20) running on x86_64-unknown-linux-gnu
note: compiler flags: -C codegen-units=1 -C debuginfo=2 --crate-type bin
note: some of the compiler flags provided by cargo are hidden
error: aborting due to previous error
error: could not compile `playground`.
To learn more, run the command again with --verbose.
Я сделал отчет об ошибке здесь .