From 57feb323f79d1d7f7dd6251d4606ba12a800953a Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 3 Jul 2020 17:39:06 +0200 Subject: [PATCH] Fix inference of indexing argument (partly) We need to add the `T: Index` 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. --- crates/ra_hir_ty/src/infer.rs | 20 +++++++++------- 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 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_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 for Bar { + type Output = Foo; +} + +struct Range; +impl std::ops::Index 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 { + type Output; + } +} +"#, + ); +} + #[test] fn infer_ops_index_autoderef() { check_types(