mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 20:43:21 +00:00
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:
parent
dceec6176b
commit
57feb323f7
2 changed files with 48 additions and 8 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in a new issue