about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_ty/src/infer.rs20
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs36
2 files changed, 48 insertions, 8 deletions
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index 3719f76a6e2..5c56c2eb093 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_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 766790576d0..529d9e253e7 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -541,6 +541,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(
         r#"