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.
This commit is contained in:
Florian Diebold 2020-07-03 17:39:06 +02:00
parent dceec6176b
commit 57feb323f7
2 changed files with 48 additions and 8 deletions

View file

@ -28,8 +28,8 @@ use hir_def::{
path::{path, Path}, path::{path, Path},
resolver::{HasResolver, Resolver, TypeNs}, resolver::{HasResolver, Resolver, TypeNs},
type_ref::{Mutability, TypeRef}, type_ref::{Mutability, TypeRef},
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, TraitId, TypeAliasId, AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId,
VariantId, TypeAliasId, VariantId,
}; };
use hir_expand::{diagnostics::DiagnosticSink, name::name}; use hir_expand::{diagnostics::DiagnosticSink, name::name};
use ra_arena::map::ArenaMap; use ra_arena::map::ArenaMap;
@ -376,17 +376,21 @@ impl<'a> InferenceContext<'a> {
) -> Ty { ) -> Ty {
match assoc_ty { match assoc_ty {
Some(res_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 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) .push(inner_ty)
.fill(params.iter().cloned()); .fill(params.iter().cloned())
.build();
let trait_ref = TraitRef { trait_, substs: substs.clone() };
let projection = ProjectionPredicate { let projection = ProjectionPredicate {
ty: ty.clone(), ty: ty.clone(),
projection_ty: ProjectionTy { projection_ty: ProjectionTy { associated_ty: res_assoc_ty, parameters: substs },
associated_ty: res_assoc_ty,
parameters: builder.build(),
},
}; };
self.obligations.push(Obligation::Trait(trait_ref));
self.obligations.push(Obligation::Projection(projection)); self.obligations.push(Obligation::Projection(projection));
self.resolve_ty_as_possible(ty) self.resolve_ty_as_possible(ty)
} }

View file

@ -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] #[test]
fn infer_ops_index_autoderef() { fn infer_ops_index_autoderef() {
check_types( check_types(