Repository: rust-analyzer/rust-analyzer
Pull request #5211 (2020-07-03 15:45:43)

Fix inference of indexing argument (partly)
We need to add the `T: Index<Arg>` obligation to be resolved later as well, otherwise we can't make inferences about `Arg` later based on the `Index` impls.

This still doesn't fix indexing with integer variables though; there's a further problem with Chalk floundering because of the variable, I think.

matklad: cargo fmt fails

Patch:
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index 3719f76a6e..5c56c2eb09 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -28,8 +28,8 @@ use hir_def::{
     path::{path, Path},
     resolver::{HasResolver, Resolver, TypeNs},
     type_ref::{Mutability, TypeRef},
-    AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, TraitId, TypeAliasId,
-    VariantId,
+    AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId,
+    TypeAliasId, VariantId,
 };
 use hir_expand::{diagnostics::DiagnosticSink, name::name};
 use ra_arena::map::ArenaMap;
@@ -376,17 +376,21 @@ impl<'a> InferenceContext<'a> {
     ) -> Ty {
         match assoc_ty {
             Some(res_assoc_ty) => {
+                let trait_ = match res_assoc_ty.lookup(self.db.upcast()).container {
+                    hir_def::AssocContainerId::TraitId(trait_) => trait_,
+                    _ => panic!("resolve_associated_type called with non-associated type"),
+                };
                 let ty = self.table.new_type_var();
-                let builder = Substs::build_for_def(self.db, res_assoc_ty)
+                let substs = Substs::build_for_def(self.db, res_assoc_ty)
                     .push(inner_ty)
-                    .fill(params.iter().cloned());
+                    .fill(params.iter().cloned())
+                    .build();
+                let trait_ref = TraitRef { trait_, substs: substs.clone() };
                 let projection = ProjectionPredicate {
                     ty: ty.clone(),
-                    projection_ty: ProjectionTy {
-                        associated_ty: res_assoc_ty,
-                        parameters: builder.build(),
-                    },
+                    projection_ty: ProjectionTy { associated_ty: res_assoc_ty, parameters: substs },
                 };
+                self.obligations.push(Obligation::Trait(trait_ref));
                 self.obligations.push(Obligation::Projection(projection));
                 self.resolve_ty_as_possible(ty)
             }
diff --git a/crates/ra_ide_db/src/change.rs b/crates/ra_ide_db/src/change.rs
index 2504d7a338..dbe6eacc59 100644
--- a/crates/ra_ide_db/src/change.rs
+++ b/crates/ra_ide_db/src/change.rs
@@ -191,10 +191,12 @@ impl RootDatabase {
 
             // AstDatabase
             hir::db::AstIdMapQuery
+            hir::db::InternMacroQuery
             hir::db::MacroArgQuery
             hir::db::MacroDefQuery
             hir::db::ParseMacroQuery
             hir::db::MacroExpandQuery
+            hir::db::InternEagerExpansionQuery
 
             // DefDatabase
             hir::db::ItemTreeQuery
@@ -219,6 +221,17 @@ impl RootDatabase {
             hir::db::DocumentationQuery
             hir::db::ImportMapQuery
 
+            // InternDatabase
+            hir::db::InternFunctionQuery
+            hir::db::InternStructQuery
+            hir::db::InternUnionQuery
+            hir::db::InternEnumQuery
+            hir::db::InternConstQuery
+            hir::db::InternStaticQuery
+            hir::db::InternTraitQuery
+            hir::db::InternTypeAliasQuery
+            hir::db::InternImplQuery
+
             // HirDatabase
             hir::db::InferQueryQuery
             hir::db::TyQuery
@@ -233,6 +246,10 @@ impl RootDatabase {
             hir::db::InherentImplsInCrateQuery
             hir::db::TraitImplsInCrateQuery
             hir::db::TraitImplsInDepsQuery
+            hir::db::InternTypeCtorQuery
+            hir::db::InternTypeParamIdQuery
+            hir::db::InternChalkImplQuery
+            hir::db::InternAssocTyValueQuery
             hir::db::AssociatedTyDataQuery
             hir::db::TraitDatumQuery
             hir::db::StructDatumQuery
@@ -247,36 +264,6 @@ impl RootDatabase {
             // LineIndexDatabase
             crate::LineIndexQuery
         ];
-
-        // To collect interned data, we need to bump the revision counter by performing a synthetic
-        // write.
-        // We do this after collecting the non-interned queries to correctly attribute memory used
-        // by interned data.
-        self.runtime.synthetic_write(Durability::HIGH);
-
-        sweep_each_query![
-            // AstDatabase
-            hir::db::InternMacroQuery
-            hir::db::InternEagerExpansionQuery
-
-            // InternDatabase
-            hir::db::InternFunctionQuery
-            hir::db::InternStructQuery
-            hir::db::InternUnionQuery
-            hir::db::InternEnumQuery
-            hir::db::InternConstQuery
-            hir::db::InternStaticQuery
-            hir::db::InternTraitQuery
-            hir::db::InternTypeAliasQuery
-            hir::db::InternImplQuery
-
-            // HirDatabase
-            hir::db::InternTypeCtorQuery
-            hir::db::InternTypeParamIdQuery
-            hir::db::InternChalkImplQuery
-            hir::db::InternAssocTyValueQuery
-        ];
-
         acc.sort_by_key(|it| std::cmp::Reverse(it.1));
         acc
     }
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 8462640469..14982919db 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -273,22 +273,12 @@ pub fn analysis_stats(
     println!("Total: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage());
 
     if memory_usage {
-        let mut mem = host.per_query_memory_usage();
-
-        let before = ra_prof::memory_usage();
-        drop(vfs);
-        let vfs = before.allocated - ra_prof::memory_usage().allocated;
-        mem.push(("VFS".into(), vfs));
-
-        let before = ra_prof::memory_usage();
-        drop(host);
-        mem.push(("Unaccounted".into(), before.allocated - ra_prof::memory_usage().allocated));
-
-        mem.push(("Remaining".into(), ra_prof::memory_usage().allocated));
-
-        for (name, bytes) in mem {
+        for (name, bytes) in host.per_query_memory_usage() {
             println!("{:>8} {}", bytes, name)
         }
+        let before = ra_prof::memory_usage();
+        drop(host);
+        println!("leftover: {}", before.allocated - ra_prof::memory_usage().allocated)
     }
 
     Ok(())


Test patch:
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 766790576d..529d9e253e 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -540,6 +540,42 @@ mod ops {
     );
 }
 
+#[test]
+fn infer_ops_index_int() {
+    check_types(
+        r#"
+//- /main.rs crate:main deps:std
+struct Bar;
+struct Foo;
+
+impl std::ops::Index<u32> for Bar {
+    type Output = Foo;
+}
+
+struct Range;
+impl std::ops::Index<Range> for Bar {
+    type Output = Bar;
+}
+
+fn test() {
+    let a = Bar;
+    let b = a[1];
+    b;
+  //^ Foo
+}
+
+//- /std.rs crate:std
+#[prelude_import] use ops::*;
+mod ops {
+    #[lang = "index"]
+    pub trait Index<Idx> {
+        type Output;
+    }
+}
+"#,
+    );
+}
+
 #[test]
 fn infer_ops_index_autoderef() {
     check_types(