Skip to content

NLL exponential(?) increase in compile times when nesting borrowed futures #61324

Open
@david-mcgillicuddy-moixa

Description

When nesting futures in the pattern:

trait Foo<'a> {
    fn get_unit(&'a self) -> Box<dyn Future<Item=(), Error=Box<dyn Error+'a>> + 'a>;
    fn foo(&'a self) -> Box<dyn Future<Item=Vec<()>, Error=Box<dyn Error+'a>> + 'a> {
        Box::new(
            self.get_unit().and_then(move |unit1| {
                self.get_unit().and_then(move |unit2| {
                    ...

I get a blow up in complation times at around n = 10 or 11.
N = 9 takes 15 seconds, N = 10 takes 83 seconds, and N = 11 takes 18 minutes.

Switching things to the static lifetime make the times reasonable again.

Playground link showing the full example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=136faa5e507b53e587480d23f9fc87d8

It happens on both nightly and stable. I ran with cargo rustc -- -Z time-passes and got:

...
  time: 0.862	item-bodies checking
    time: 0.029	rvalue promotion + match checking
    time: 0.002	liveness checking + intrinsic checking
  time: 0.031	misc checking 2
  time: 0.000	borrow checking
    time: 0.000	solve_nll_region_constraints(DefId(0:38 ~ my_crate[cd01]::async_mod[0]::Foo[0]::get_unit[0]))
    time: 0.000	solve_nll_region_constraints(DefId(0:50 ~ my_crate[cd01]::async_mod[0]::Foo[0]::foo[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]))
    time: 0.000	solve_nll_region_constraints(DefId(0:49 ~ my_crate[cd01]::async_mod[0]::Foo[0]::foo[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]))
    time: 0.000	solve_nll_region_constraints(DefId(0:48 ~ my_crate[cd01]::async_mod[0]::Foo[0]::foo[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]))
    time: 0.001	solve_nll_region_constraints(DefId(0:47 ~ my_crate[cd01]::async_mod[0]::Foo[0]::foo[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]))
    time: 0.006	solve_nll_region_constraints(DefId(0:46 ~ my_crate[cd01]::async_mod[0]::Foo[0]::foo[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]))
    time: 0.040	solve_nll_region_constraints(DefId(0:45 ~ my_crate[cd01]::async_mod[0]::Foo[0]::foo[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]))
    time: 0.207	solve_nll_region_constraints(DefId(0:44 ~ my_crate[cd01]::async_mod[0]::Foo[0]::foo[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]))
    time: 1.486	solve_nll_region_constraints(DefId(0:43 ~ my_crate[cd01]::async_mod[0]::Foo[0]::foo[0]::{{closure}}[0]::{{closure}}[0]::{{closure}}[0]))
    time: 13.384	solve_nll_region_constraints(DefId(0:42 ~ my_crate[cd01]::async_mod[0]::Foo[0]::foo[0]::{{closure}}[0]::{{closure}}[0]))
    time: 124.880	solve_nll_region_constraints(DefId(0:41 ~ my_crate[cd01]::async_mod[0]::Foo[0]::foo[0]::{{closure}}[0]))
    time: 0.000	solve_nll_region_constraints(DefId(0:40 ~ my_crate[cd01]::async_mod[0]::Foo[0]::foo[0]))
  time: 143.577	MIR borrow checking
...
   Finished dev [unoptimized + debuginfo] target(s) in 2m 28s

Metadata

Metadata

Assignees

Labels

A-NLLArea: Non-lexical lifetimes (NLL)A-borrow-checkerArea: The borrow checkerC-bugCategory: This is a bug.I-compiletimeIssue: Problems and improvements with respect to compile times.NLL-performantWorking towards the "performance is good" goalT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions