Skip to content
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

Strange borrowing issue in inherent async method. #68950

Closed
crlf0710 opened this issue Feb 8, 2020 · 4 comments
Closed

Strange borrowing issue in inherent async method. #68950

crlf0710 opened this issue Feb 8, 2020 · 4 comments
Labels
A-async-await Area: Async & Await AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@crlf0710
Copy link
Member

crlf0710 commented Feb 8, 2020

Not sure whether it's a bug, but it is indeed strange...

struct A;
// this compiles
fn test(s: &mut A, arg: &str, handler: Box<dyn Fn() + 'static>) {
        
}
// this doesn't
impl A {
    async fn test2(&mut self, arg: &str, handler: Box<dyn Fn() + 'static>) {
        
    }
}

test2 errors with:

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
  --> src/lib.rs:8:76
   |
8  |     async fn test2(&mut self, arg: &str, handler: Box<dyn Fn() + 'static>) {
   |                                                                            ^
   |
@crlf0710
Copy link
Member Author

crlf0710 commented Feb 8, 2020

@rustbot modify labels to +A-async-await +C-bug +T-compiler

@rustbot rustbot added A-async-await Area: Async & Await C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 8, 2020
@crlf0710
Copy link
Member Author

crlf0710 commented Feb 8, 2020

Seems similar to #68759 ....

@Aaron1011
Copy link
Member

This appears to have the same underlying cause as #64552 (which @csmoe is working on in #68362).

When you write handler: Box<dyn FnOnce() + 'static> (or handler: Box<dyn FnOnce()>, which desugars to the same thing), the AST lowering doesn't create a lifetime parameter in the created opaque type, since you don't need a lifetime parameter for 'static. However,

However, when we create the generator type, we forget that the region is 'static:

// The types in the generator interior contain lifetimes local to the generator itself,
// which should not be exposed outside of the generator. Therefore, we replace these
// lifetimes with existentially-bound lifetimes, which reflect the exact value of the
// lifetimes not being known by users.
//
// These lifetimes are used in auto trait impl checking (for example,
// if a Sync generator contains an &'α T, we need to check whether &'α T: Sync),
// so knowledge of the exact relationships between them isn't particularly important.
debug!("types in generator {:?}, span = {:?}", type_list, body.value.span);
// Replace all regions inside the generator interior with late bound regions
// Note that each region slot in the types gets a new fresh late bound region,
// which means that none of the regions inside relate to any other, even if
// typeck had previously found constraints that would cause them to be related.
let mut counter = 0;
let type_list = fcx.tcx.fold_regions(&type_list, &mut false, |_, current_depth| {
counter += 1;
fcx.tcx.mk_region(ty::ReLateBound(current_depth, ty::BrAnon(counter)))
});

Thus, we end up trying to process a member constraint for some newly created region _#0r. Since by construction we have no constraints for it, we cannot prove that it is equal to any of the regions in the member constraint (even though it's "really" 'static).

As a workaround, we could special-case 'static during the creation of the generator type, and leave it as-is instead of creating a fresh late-bound region.

As in #64552, I believe the full solution is for generator types to carry 'extra' region constraints with them in some form, so that we don't lose the lexical region information that we had prior to the lowering.

@tmandry tmandry added AsyncAwait-OnDeck AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. labels Feb 11, 2020
@tmandry
Copy link
Member

tmandry commented Mar 3, 2020

Thanks @Aaron1011. I'm going to close this as a duplicate of #64552, but note on the issue that we should add a test with the code from this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-async-await Area: Async & Await AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
Archived in project
Development

No branches or pull requests

4 participants