Stream: t-compiler/rust-analyzer

Topic: Endless loading


Casper R. Storm (Feb 27 2021 at 06:51, on Zulip):

Hi everyone,
I am a little sure if this is the right place, but feel free to remove the stream if not.
I am the creator of Ajour - a rather big Rust desktop application. I've been using rust_analyzer in nvim since i started the project and never had any issues. However, lately a few collaborators told me that Ajour didn't work properly with rust_analyzer and VSCode and sure enough when I try to edit eg: gui/update.rs in VSCode it just loads endlessly and never saves the file. That same file works just fine in nvm with rust_analyzer lsp. I am unsure if this is a issue with VSCode, with RA or with Ajour.

Laurențiu (Feb 27 2021 at 06:55, on Zulip):

I can confirm. Looks like we balk on gui::update::query_and_sort_catalog

Laurențiu (Feb 27 2021 at 07:04, on Zulip):

As a workaround, you can give an explicit type to the collect call of catalog_rows_and_score (.collect::<Vec<(CatalogRow, i64)>>();)

Laurențiu (Feb 27 2021 at 07:04, on Zulip):

That seems to do the trick, at least in a slightly minimized version of the code

Laurențiu (Feb 27 2021 at 07:43, on Zulip):

Partial minimization:

fn query_and_sort_catalog(ajour: &mut Ajour) {
    if let Some(catalog) = &ajour.catalog {
        let query = ajour
            .catalog_search_state
            .query
            .as_ref()
            .map(|s| s.to_lowercase());
        let flavor = &ajour.config.wow.flavor;

        let mut catalog_rows_and_score = catalog
            .addons
            .iter()
            .filter_map(|a| {
                Some((a, 0))
            })
            .filter(|(a, _)| {
                a.game_versions
                    .iter()
                    .any(|gc| gc.flavor == flavor.base_flavor())
            })
            .map(|(a, score)| (CatalogRow::from(a.clone()), score))
            .collect::<Vec<_>>();

        catalog_rows_and_score.sort_by(|(addon_a, score_a), (addon_b, score_b)| {
            score_a.cmp(&score_b)
        });
    }
}
Laurențiu (Feb 27 2021 at 08:10, on Zulip):

https://github.com/rust-analyzer/rust-analyzer/issues/7796

detrumi (Feb 27 2021 at 08:28, on Zulip):

Looks like that's on the RA side of solving:

[DEBUG hir_ty::traits] solve(UCanonical { canonical: Canonical { value: InEnvironment { environment: Env([]), goal: Implemented({closure:ClosureId(3)}<[?0 := () for<0> [?0 := (&'static 2<[?0 := ^1.0, ?1 := (&'static ^1.1)]>), ?1 := (&'static 2<[?0 := ^1.2, ?1 := ^1.1]>), ?2 := Ordering<[]>]]>: FnMut<2<[?0 := (&'static 2<[?0 := ^0.3, ?1 := ^0.4]>), ?1 := (&'static 2<[?0 := ^0.3, ?1 := ^0.4]>)]>>) }, binders: [U0 with kind type, U0 with kind type, U0 with kind type, U0 with kind type, U0 with kind type] }, universes: 1 }) => None
[INFO hir_ty::traits] trait_solve_query(Normalize(<|&(?0.0, &?0.1), &(?0.2, ?0.1)| -> Ordering as FnOnce<(&(?0.3, ?0.4), &(?0.3, ?0.4))>>::Output => Ordering))
[DEBUG hir_ty::traits] solve goal: UCanonical { canonical: Canonical { value: InEnvironment { environment: Env([]), goal: AliasEq(AliasTy(?) = AdtId(EnumId(EnumId(8)))<[]>) }, binders: [U0 with kind type, U0 with kind type, U0 with kind type, U0 with kind type, U0 with kind type] }, universes: 1 }
[DEBUG hir_ty::traits::chalk] impls_for_trait FnOnce
[DEBUG hir_ty::traits::chalk] impls_for_trait returned 0 impls
[DEBUG hir_ty::traits::chalk] impls_for_trait FnOnce
[DEBUG hir_ty::traits::chalk] impls_for_trait returned 0 impls
[DEBUG hir_ty::traits::chalk] impls_for_trait FnOnce
[DEBUG hir_ty::traits::chalk] impls_for_trait returned 0 impls
[DEBUG hir_ty::traits::chalk] impls_for_trait FnOnce
...
Casper R. Storm (Feb 27 2021 at 08:28, on Zulip):

Thanks for investigating and digging into the issue, @Laurențiu Nicola & @detrumi.
Let me know if I can do anything to help out.

Laurențiu (Feb 27 2021 at 08:29, on Zulip):

I recall our handling of closures being less not quite great

detrumi (Feb 27 2021 at 08:30, on Zulip):

@Casper R. Storm We're able to reproduce it with a small example, so that should be enough for us to figure out the problem and fix it :smile:

detrumi (Feb 27 2021 at 08:31, on Zulip):

@Laurențiu Nicola Yeah, it's very hard to figure out what's going on when closures are involved

Laurențiu (Feb 27 2021 at 08:33, on Zulip):

@Casper R. Storm in the meanwhile, you can use that workaround I mentioned to make it easier on the users. I checked and analysis completes after that change

Laurențiu (Feb 27 2021 at 08:34, on Zulip):
diff --git i/src/gui/update.rs w/src/gui/update.rs
index 9c47a6e..b54b25a 100644
--- i/src/gui/update.rs
+++ w/src/gui/update.rs
@@ -2534,7 +2534,7 @@ fn query_and_sort_catalog(ajour: &mut Ajour) {
                 CatalogCategory::Choice(name) => a.categories.iter().any(|c| c == name),
             })
             .map(|(a, score)| (CatalogRow::from(a.clone()), score))
-            .collect::<Vec<_>>();
+            .collect::<Vec<(CatalogRow, i64)>>();

         let mut catalog_rows = if query.is_some() {
             // If a query is defined, the default sort is the fuzzy match score
Laurențiu (Feb 27 2021 at 08:35, on Zulip):

You probably didn't run into it in nvim because the Code extension does things like semantic highlighting and type hints, which need trait solving

detrumi (Feb 27 2021 at 09:05, on Zulip):

Filed chalk#688 with a description of the endlessly expanding query (it keeps nesting lifetimes)

Last update: Jul 26 2021 at 14:15UTC