Closed
Description
... even though the value of the expression does not borrow from anything.
rustc 1.21.0-nightly (c11f689d2 2017-08-29)
binary: rustc
commit-hash: c11f689d2475dd9ab956e881238d5d7b6b485efb
commit-date: 2017-08-29
host: x86_64-pc-windows-msvc
release: 1.21.0-nightly
LLVM version: 4.0
#![feature(conservative_impl_trait, generators, generator_trait)]
use std::ops::{ Generator, GeneratorState };
fn foo(_: &str) -> String {
String::new()
}
fn bar(baz: String) -> impl Generator<Yield = String, Return = ()> {
move || {
yield foo(&baz);
}
}
fn main() {
assert_eq!(bar(String::new()).resume(), GeneratorState::Yielded(String::new()));
}
This gives:
error[E0564]: only named lifetimes are allowed in `impl Trait`, but `` was found in the type `[generator@src\main.rs:10:2: 12:3 baz:std::string::String ((), std::string::String, &str, fn(&str) -> std::string::String {foo})]`
--> src\main.rs:9:24
|
9 | fn bar(baz: String) -> impl Generator<Yield = String, Return = ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- yield foo(&baz);
+ let quux = foo(&baz);
+ yield quux;
#![feature(conservative_impl_trait, generators, generator_trait)]
use std::ops::{ Generator, GeneratorState };
fn foo(_: &str) -> Result<String, ()> {
Err(())
}
fn bar(baz: String) -> impl Generator<Yield = String, Return = ()> {
move || {
if let Ok(quux) = foo(&baz) {
yield quux;
}
}
}
fn main() {
assert_eq!(bar(String::new()).resume(), GeneratorState::Complete(()));
}
This gives
error[E0564]: only named lifetimes are allowed in `impl Trait`, but `` was found in the type `[generator@src\main.rs:10:2: 14:3 baz:std::string::String ((), std::result::Result<std::string::String, ()>, &str, std::string::String, fn(&str) -> std::result::Result<std::string::String, ()> {foo})]`
--> src\main.rs:9:24
|
9 | fn bar(baz: String) -> impl Generator<Yield = String, Return = ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- if let Ok(quux) = foo(&baz) {
+ let quux = foo(&baz);
+ if let Ok(quux) = quux {
I assume the borrows in the expressions are the problem because in both cases, adding a + 'static
bound to the impl Generator
returns the error that baz
does not live long enough, even though it does not need to be borrowed past the call to foo(&baz)
.
Activity
alexcrichton commentedon Aug 31, 2017
cc @Zoxc
alexcrichton commentedon Aug 31, 2017
This may or may not be the same as #44200
Zoxc commentedon Aug 31, 2017
Like #44200 this is due to how interior types are being calculated.
In both your examples
&baz
is considered a temporary and lives to the enclosing destruction scope, which are the yield statement and the if statement. Both of these contains a yield expression so&str
is being considered part of the generator interior. Nowimpl Trait
only allows explicitly named lifetimes in the return type so it gives an error about that&str
, although poorly. You need to pass-Z verbose
to the compiler for that error to be usable.Arnavion commentedon Aug 31, 2017
Just to be clear, you're only talking about the situation due to the bug with generators, right? Because in regular Rust the borrow of
&baz
is limited to thefoo(&baz)
expression and not any outermatch
/if let
expression that it's part of. (Otherwise something likeif let Some(first) = iter.next() { if let Some(second) = iter.next() { } }
would not compile and complain about multiple mutable borrows ofiter
.)Zoxc commentedon Aug 31, 2017
@Arnavion It's not really a bug (just undesirable semantics), and you typically don't notice these rules unless the types involved have destructors (which references do not) and isn't immediately moved.
Arnavion commentedon Aug 31, 2017
Okay, regardless of what we call it, it's something that happens only with generators and not with regular Rust code, so it would be nice to fix it.
pftbest commentedon Sep 5, 2017
This code produces the same error:
Is there some workaround?
Arnavion commentedon Sep 5, 2017
@pftbest
If you still want to keep the
while let
you can do something like:pftbest commentedon Sep 5, 2017
@Arnavion , thanks! Looks like I also hit #38615 when I forgot to add
move
.25 remaining items