diff options
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 36 |
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 3719f76a6..5c56c2eb0 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -28,8 +28,8 @@ use hir_def::{ | |||
28 | path::{path, Path}, | 28 | path::{path, Path}, |
29 | resolver::{HasResolver, Resolver, TypeNs}, | 29 | resolver::{HasResolver, Resolver, TypeNs}, |
30 | type_ref::{Mutability, TypeRef}, | 30 | type_ref::{Mutability, TypeRef}, |
31 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, TraitId, TypeAliasId, | 31 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId, |
32 | VariantId, | 32 | TypeAliasId, VariantId, |
33 | }; | 33 | }; |
34 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; | 34 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; |
35 | use ra_arena::map::ArenaMap; | 35 | use ra_arena::map::ArenaMap; |
@@ -376,17 +376,21 @@ impl<'a> InferenceContext<'a> { | |||
376 | ) -> Ty { | 376 | ) -> Ty { |
377 | match assoc_ty { | 377 | match assoc_ty { |
378 | Some(res_assoc_ty) => { | 378 | Some(res_assoc_ty) => { |
379 | let trait_ = match res_assoc_ty.lookup(self.db.upcast()).container { | ||
380 | hir_def::AssocContainerId::TraitId(trait_) => trait_, | ||
381 | _ => panic!("resolve_associated_type called with non-associated type"), | ||
382 | }; | ||
379 | let ty = self.table.new_type_var(); | 383 | let ty = self.table.new_type_var(); |
380 | let builder = Substs::build_for_def(self.db, res_assoc_ty) | 384 | let substs = Substs::build_for_def(self.db, res_assoc_ty) |
381 | .push(inner_ty) | 385 | .push(inner_ty) |
382 | .fill(params.iter().cloned()); | 386 | .fill(params.iter().cloned()) |
387 | .build(); | ||
388 | let trait_ref = TraitRef { trait_, substs: substs.clone() }; | ||
383 | let projection = ProjectionPredicate { | 389 | let projection = ProjectionPredicate { |
384 | ty: ty.clone(), | 390 | ty: ty.clone(), |
385 | projection_ty: ProjectionTy { | 391 | projection_ty: ProjectionTy { associated_ty: res_assoc_ty, parameters: substs }, |
386 | associated_ty: res_assoc_ty, | ||
387 | parameters: builder.build(), | ||
388 | }, | ||
389 | }; | 392 | }; |
393 | self.obligations.push(Obligation::Trait(trait_ref)); | ||
390 | self.obligations.push(Obligation::Projection(projection)); | 394 | self.obligations.push(Obligation::Projection(projection)); |
391 | self.resolve_ty_as_possible(ty) | 395 | self.resolve_ty_as_possible(ty) |
392 | } | 396 | } |
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 766790576..529d9e253 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 { | |||
541 | } | 541 | } |
542 | 542 | ||
543 | #[test] | 543 | #[test] |
544 | fn infer_ops_index_int() { | ||
545 | check_types( | ||
546 | r#" | ||
547 | //- /main.rs crate:main deps:std | ||
548 | struct Bar; | ||
549 | struct Foo; | ||
550 | |||
551 | impl std::ops::Index<u32> for Bar { | ||
552 | type Output = Foo; | ||
553 | } | ||
554 | |||
555 | struct Range; | ||
556 | impl std::ops::Index<Range> for Bar { | ||
557 | type Output = Bar; | ||
558 | } | ||
559 | |||
560 | fn test() { | ||
561 | let a = Bar; | ||
562 | let b = a[1]; | ||
563 | b; | ||
564 | //^ Foo | ||
565 | } | ||
566 | |||
567 | //- /std.rs crate:std | ||
568 | #[prelude_import] use ops::*; | ||
569 | mod ops { | ||
570 | #[lang = "index"] | ||
571 | pub trait Index<Idx> { | ||
572 | type Output; | ||
573 | } | ||
574 | } | ||
575 | "#, | ||
576 | ); | ||
577 | } | ||
578 | |||
579 | #[test] | ||
544 | fn infer_ops_index_autoderef() { | 580 | fn infer_ops_index_autoderef() { |
545 | check_types( | 581 | check_types( |
546 | r#" | 582 | r#" |